trybadger v1.2.2
Badger Contracts
Badger is an opionionated-by-default primitive designed to drive the actions of on-chain Organizations and their members with Badges. As a primitive, the contracts have been designed to remove the need of including any opinionated logic in the core contracts while maintaining the ability of a user-specific solution.
While the core contracts are opinionless, Hooks
and Managers
can be used to introduce opinionated logic to the system depending on the need of each Badge, Organization or even Manager. Further, instead of having to apply opinion organization-wide, Hooks
and Managers
can be applied to a single Badge while still maintaing the ability to set global values when wanted.
contracts
āā (š = Organization || š·ļø = Badge)
āā hooks
āāāāā forfeit
āāāāāāā š·ļø BadgerForfeitForbidden - "Forfeiting a Badge is not allowed."
āāāāā hook
āāāāāāā š BadgerHookBlocklist - "Forbids certain addresses from being enabled as a Hook."
āāāāā mint
āāāāāāā š·ļø BadgerMintMax - "Maximum number of Badges that can be minted to a recipient."
āāāāāāā š·ļø BadgerMintMaxAllowance - "Maximum number of Badges that can be minted by a specific manager."
āāāāāāā š·ļø BadgerMintMaxSupply - "Maximum number of Badges that can be minted."
āāāāāāā š·ļø BadgerMintSelf - "Mint mechanism that requires the recipient to be the caller."
āāāāā revoke
āāāāāāā š·ļø BadgerRevokeForbidden - "Revoking a Badge is not allowed."
āāāāā transfer
āāāāāāā š BadgerTransferBlocklist - "Addresses that are not allowed to receive any Badge."
āāāāāāā š·ļø BadgerTransferBound - "Enforce account bound functionality per token id."
āāāāāāā š·ļø BadgerTransferBoundManaged - "Enforce account bound functionality that can be overridden by a Manager."
āāāāā types
āāāāāāā BadgerForfeitHook - "Type declaration of interface for a Forfeit Hook."
āāāāāāā BadgerHookHook - "Type declaration of interface for a Hook Hook."
āāāāāāā BadgerMintHook - "Type declaration of interface for a Mint Hook."
āāāāāāā BadgerRevokeHook - "Type declaration of interface for a Revoke Hook."
āāāāāāā BadgerTransferHook - "Type declaration of interface for a Transfer Hook."
āāāāā BadgerHook - "Minimal framework for a Badger Organization Hook."
āāāāā BadgerHooked - "Logic that drives the consumption of Organization Hooks."
āā interfaces
āāāāā IBadger - "Interface to of Badger Factory to enable programatic Organization creation."
āāāāā IBadgerConfigured - "Interface to a Badger Module that can be configured."
āāāāā IBadgerHook - "Interface of a Hook powering exogenous logic of an Organization."
āāāāā IBadgerHooked - "Interface of the logic driving the consumption of Organization Hooks."
āāāāā IBadgerManaged - "Interface of the logic driving the consumption of Organization Managers."
āāāāā IBadgerOrganization - "Non-admin interface for Badger Organization consumption."
āāāāā IBadgerOrganizationLogic - "Admin-level interface for the backend framework that drives an Organization."
āā managers
āāāāā š·ļø BadgerManagerClaimable - "Enable an open-edition claiming where users can claim a Badge at no cost."
āāāāā š·ļø BadgerManagerPaidERC20 - "Mint using ERC20s as a Payment Token to mint Badges."
āāāāā š·ļø BadgerManagerPaidERC721 - "Mint using ERC721s as a Payment Token to mint Badges."
āāāāā š·ļø BadgerManagerPaidERC1155 - "Mint using ERC1155s as a Payment Token to mint Badges."
āāāāā š·ļø BadgerManagerPaidNative - "Mint using native tokens as a Payment Token to mint Badges."
āāāāā š·ļø BadgerManagerSignature - "Mint gated by a system signature when minting Badges."
āā Badger - "Factory that deploys new Badger Organizations and Badges."
āā BadgerNetwork - "Inline controller of configuring a Badger Module."
āā BadgerOrganization - "The logic driving the non-admin functions of a Badger Organization."
āā BadgerOrganizationLogic - "The state of the Organization and Badges and all admin-level functions an Organization has."
The Shape of an Organization
Badger Organizations are built with a rather straightforward middle-out approach. Designed to scale in both directions of need: case-specific centralization and decentralization live at the core of how Organizations have been built.
At the core, Organizations are deployed by a Factory and instantiated with just an Owner. An Owner has the ability to empower Managers, connect Hooks, create Badges and more all in a single interface and localized smart contract.
- There are Organizations with Badges and Managers.
- There are Badges with Members and Managers.
- There are Modules that can be plugged in at a object-level to enable new functionality.
Organizations grow and evolve over time and Badger is prepared to support that change. With Hooks
, not only can old functionality be disabled, but new Hooks
and Managers
can be integrated that drive the future needs without abandoning the historical power and integration of the existing Organization.
The Manager Pattern
Every Organization and Badge has an optional set of Managers
that permits shared access to admin-level functions of the relative scope.
- An Organization Manager operates as one would expect to a real-world business; the owner implicitly trusts the manager and has given shared access to key functions.
- Create, mint and revoke new Badges.
- Adjust the delegates of all Badges.
- The only action that an Organization Manager cannot do is add new Managers or resign from the position however the Owner may remove the Manager.
- A Badge Manager operates with shared logic to the Organization Manager while strictly scoped to the level of a single token.
- Mint and revoke the assigned Badge.
- The only action that an Badge Manager cannot do is add new Managers or resign from the position however the Owner and other Organization Managers may remove the Badge Manager.
Immutable Hooks and Managers
When developing Hooks and Managers that drive a Badger Organization, it has been made of utmost important to make modules immutable and ownerless. Meaning, while the Badger team may develop and deploy a module that Organizations consume, there is no mechanism of changing the connected smart contract. With this architecture, everything is constantly localized to the sender of the message.
- When writing the configuration, the reference is set to the
msg.sender
. - Execution of a
Hook
is triggered by the consuming Organization, not an external reference or sender. - Usage of a
Manager
precedes the execution of an Organization action. - A Badge can be assigned many
Managers
andHooks
specific to the needs of each Badge.
Although there has been a foundational framework of hooks and managers offered. Those with the knowledge and experience to write their own hooks and managers are encouraged to do so.
- Hook Hooks: Hooks that are triggered when a hook is set with an active
isHook
. - Mint Hooks: Hooks that are triggered when a Badge is minted.
- Revoke Hooks: Hooks that are triggered when a Badge is revoked.
- Forfeit Hooks: Hooks that are triggered when a Badge is forfeited.
- Transfer Hooks: Hooks that are triggered when a Badge is transferred.
Revokability
Out of the gate, Badger Organizations are empowered with the ability to have Revokable
Badges under the control of Organization and Badge Managers (depending on the respective configuration of each.) Badger is designed to drive complex permissions and on-chain access policies with the addition of permission revocation: a critical feature to any permission system.
Although Badges are designed to be revokable by default, a RevokeHook
may be applied to a Badge to prevent revocation such as BadgerRevokeForbidden.sol
. This is useful for Badges that are meant to be permanent and not revokable.
Eternal Forfeits
The final piece of semi-opinion included in the default operation of Badger is that token forfeiture is recommended and enabled by default however again by be prevented with a hook in ForfeitHook
such as BadgerForfeitForbidden.sol
.
Notably, while the mechanism of permanent account binding is possible, it is not recommended. This is because the social contract of Badges is that they are not means of identity resolution and that a Badge holder may forfeit their Badge at any time.
Types...? In Solidity?
The Badger Organization is designed to be a framework for the creation of Badges and Organizations. To enable this, consumption of Hooks is driven by the decoding of the bytes
data that is passed to the execute
function. This is done by the BadgerOrganizationHooked.sol
contract.
With a DRY approach, the types offered serve as a boilerplate template to implement a new hook of a specific type.
CONFIG_SCHEMA
reflects the bytes schema needed when calling.config()
EXECUTE_SCHEMA
reflects the bytes schema needed when calling.execute()
Audit
Badger V6 is in the process of being audited. Responses will be made public once it has been completed and all issues have been resolved.
In the meantime, you can find resources of due diligence below:
- c4udit - "A low-complexity audit of the Badger contracts utilizing the C4 model."
- gas report - "Gas usage of the Badger contracts."
- abis - "ABI files of the Badger contracts."
Testing the Contract
To run the smart contracts you may use the following command:
docker compose run --build -e MINING=true --rm badger_node npx hardhat test