Namespaces & IDs
Some Juicebox protocol contracts and utilities use shared namespaces and indices.
Operator Permissions
JBOperatorStore
allows addresses to give permissions to any other address to take specific actions on their behalf. Typically, a project owner or protocol user would grant a proxy contract or an EOA (called an operator) administrative protocol permissions. This is administered through the requirePermission
and requirePermissionAllowingOverride
modifiers from JBOperatable
. When granting permissions to an operator, an address can pass a domain
to limit these permissions to a certain project ID (where the domain is the project's ID), or can pass a domain of 0
to grant permissions across all domains (see Operator).
These permissions are represented by the following indices:
Index | Name | Found on | Description |
---|---|---|---|
1 | RECONFIGURE | JBOperations | Allow an operator to call JBController3_1.reconfigureFundingCyclesOf(...) (or similar functions on other controllers) on an address' behalf. |
2 | REDEEM | JBOperations | Allow an operator to call JBPayoutRedemptionPaymentTerminal3_1_1.redeemTokensOf(...) (or similar functions on other terminals) on an address' behalf, redeeming token holders according to a project's (or its data source's) rules. |
3 | MIGRATE_CONTROLLER | JBOperations | Allow an operator to call JBController3_1.migrate(...) (or similar functions on other controllers) on an address' behalf. To migrate, the project must have allowControllerMigration enabled. |
4 | MIGRATE_TERMINAL | JBOperations | Allow an operator to call JBPayoutRedemptionPaymentTerminal3_1_1.migrate(...) (or similar functions on other payment terminals) on an address' behalf. To migrate, the project must have allowTerminalMigration . |
5 | PROCESS_FEES | JBOperations | Allow an operator to call JBPayoutRedemptionPaymentTerminal3_1_1.processFees(...) (or similar functions on other terminals) on an address' behalf. See Hold fees. |
6 | SET_METADATA | JBOperations | Allow an operator to call JBProjects.setMetadataOf(...) on an address' behalf. |
7 | ISSUE | JBOperations | Allow an operator to call JBTokenStore.issueFor(...) on an address' behalf. This issues an ERC-20 token for a project's token holders to claim. |
8 | SET_TOKEN | JBOperations | Allow an operator to call JBTokenStore.setFor(...) on an address' behalf. This sets a project's token (if not already set). |
9 | MINT | JBOperations | Allow an operator to call JBTokenStore.mintFor(...) on an address' behalf. allowMinting must be enabled to mint project tokens. |
10 | BURN | JBOperations | Allow an operator to call JBController3_1.burnTokensOf(...) on an address' behalf. This burns a token holder's supply. |
11 | CLAIM | JBOperations | Allow an operator to call JBTokenStore.claimFor(...) on an address' behalf. This claims internally tracked (unclaimed) tokens as a project's ERC-20. |
12 | TRANSFER | JBOperations | Allow an operator to call JBTokenStore.transferFrom(...) on an address' behalf. pauseTransfers must be false to transfer unclaimed (internally tracked) tokens. |
13 | REQUIRE_CLAIM | JBOperations | Allow an operator to call JBTokenStore.shouldRequireClaimingFor(...) on an address' behalf, forcing all future tokens to be claimed (as ERC-20). This function (and the corresponding permission) have been deprecated in Juicebox v3. |
14 | SET_CONTROLLER | JBOperations | Allow an operator to call JBDirectory.setControllerOf(...) on an address' behalf. To set new controller(s), the project must have allowSetController enabled. |
15 | SET_TERMINALS | JBOperations | Allow an operator to call JBDirectory.setTerminalsOf(...) on an address' behalf. To set new terminal(s), the project must have allowSetTerminals enabled. |
16 | SET_PRIMARY_TERMINAL | JBOperations | Allow an operator to call JBDirectory.setPrimaryTerminalOf(...) on an address' behalf. |
17 | USE_ALLOWANCE | JBOperations | Allow an operator to call JBPayoutRedemptionPaymentTerminal3_1_1.useAllowanceOf(...) (or similar functions on other terminals) on an address' behalf. This uses a project's overflow allowance. |
18 | SET_SPLITS | JBOperations | Allow an operator to call JBSplitsStore.set(...) on an address' behalf. This sets a project's splits. |
19 | SET_ENS_NAME_FOR | JBOperations2 | Allow an operator to call JBProjectHandles.setEnsNamePartsFor(...) on an address' behalf, associating an ENS name with a project. |
20 | SET_TOKEN_URI | JBUriOperations | Allow an operator to call TokenUriResolver.setTokenUriResolverForProject(...) , setting a project's IJBTokenUriResolver . This is the URI resolver used for the Project NFT. |
21 | ADJUST_TIERS | JB721Operations | Allow an operator to call JBTiered721Delegate.adjustTiers(...) on an address' behalf. |
22 | UPDATE_METADATA | JB721Operations | Allow an operator to call JBTiered721Delegate.setMetadata(...) on an addresses' behalf. |
23 | MINT | JB721Operations | Allow an operator to call JBTiered721Delegate.mintFor(...) on an addresses' behalf. |
24 | SET_POOL_PARAMS | JBBuybackDelegateOperations | Allow an operator to call JBGenericBuybackDelegate.changeSecondsAgo(...) or JBGenericBuybackDelegate.setTwapDelta(...) on an addresses' behalf. |
25 | CHANGE_POOL | JBBuybackDelegateOperations | Allow an operator to call JBGenericBuybackDelegate.setPoolFor(...) on an addresses' behalf. |
Delegate IDs
When paying a Juicebox project with a delegate, clients must pass the appropriate metadata in the JBDidPayData3_1_1
(or the JBDidPayData
for projects using older payment terminals). The same is true for redemptions and the JBDidRedeemData3_1_1
(or JBDidRedeemData
for projects using older payment terminals).
This metadata must explicitly specify the delegate being interacted with. For older delegates, this is typically the interfaceId
of the delegate's interface. Newer delegates are identified by a 4 byte ID specified in the constructor arguments, which can be read by calling a delegate's delegateId()
view function:
function delegateId() external view returns (bytes4);
The deploy script defaults for notable delegates have been compiled below:
Delegate | delegateId |
---|---|
juice-buyback | BUYB |
juice-721-delegate | 721P |
juice-721-delegate | 721R |
Frontends interacting with newer delegates can use JBMetadata-Helper
to simplify this process.
Splits Groups
Juicebox projects store splits for an arbitrary number of groups, each corresponding to a specific kind of distribution (such as ETH payouts or reserved tokens). Each one of these groups corresponds to a specific index:
Index | Name | Found on | Description |
---|---|---|---|
1 | ETH_PAYOUT | JBSplitsGroups | Used when distributing ETH payouts via JBPayoutRedemptionPaymentTerminal3_1_1.distributePayoutsOf(...) . |
2 | RESERVED_TOKENS | JBSplitsGroups | Used when distributing reserved tokens. |
These groups must be specified when passing JBGroupedSplits
to a function such as:
JBController3_1.launchProjectFor(...)
JBController3_1.launchFundingCyclesFor(...)
JBController3_1.reconfigureFundingCyclesOf(...)
JBSplitsStore.set(...)
You can find a terminal's splits group index by accessing the relevant JBPayoutRedemptionPaymentTerminal3_1_1.payoutSplitsGroup
property.
Currency Prices
Juicebox uses JBPrices
to manage and normalize prices for various currencies, with each currency having its own index:
Index | Name | Found on | Description |
---|---|---|---|
1 | ETH | JBCurrencies | 1 ETH = 1 ETH. |
2 | USD | JBCurrencies | Uses JBChainlinkV3PriceFeed , a generalized price feed for Chainlink's AggregatorV3Interface . |
The protocol uses this to allow projects to do their accounting in any number of currencies, but manage all funds in ETH or other assets (regardless of accounting denomination). Price feeds must adhere to IJBPriceFeed
. New price feeds can be added via JBPrices.addFeedFor(...)
, which can only be called by the JuiceboxDAO multisig.
Interface IDs
ERC-165 introduced standard interface detection via the ERC165.sol
interface:
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
This allows people to check whether a given contract adheres to an interface. For your convenience, here are the interfaceId
s for interfaces in juice-contracts-v3
:
Metadata
Juicebox project metadata (such as a project's name, logo, and description) are stored on IPFS. A project's metadata IPFS hash can be found by accessing the JBProjects.metadataContentOf(...)
property, which takes two arguments:
_projectId
is the ID of the project to which the metadata belongs._domain
is the domain within which the metadata applies.
As of 2023-04-13, all projects store their metadata within domain 0
, but future frontends or contracts with unique metadata needs might consider utilizing new domains.
Example
If one calls JBProjects.metadataContentOf(...)
with _projectId
as 1
and _domain
as 0
, the contract will return the IPFS hash QmQHGuXv7nDh1rxj48HnzFtwvVxwF1KU9AfB6HbfG8fmJF
.
Now, one can navigate to a public IPFS gateway or a dedicated gateway (from Infura, Cloudflare, or another provider) to read the project's metadata:
{
"name": "JuiceboxDAO",
"description": "Supports projects built using the Juicebox protocol, and the development of the protocol itself. All projects withdrawing funds from their treasury pay a 2.5% membership fee and receive JBX at the current issuance rate. JBX members govern the NFT that represents ownership over this treasury.",
"logoUri": "https://jbx.mypinata.cloud/ipfs/QmWXCt1zYAJBkNb7cLXTNRNisuWu9mRAmXTaW9CLFYkWVS",
"infoUri": "https://snapshot.org/#/jbdao.eth",
"twitter": "juiceboxETH",
"discord": "https://discord.gg/W9mTVG4QhD",
"payButton": "Add juice",
"tokens": [],
"version": 4
}
See it yourself at https://ipfs.io/ipfs/QmQHGuXv7nDh1rxj48HnzFtwvVxwF1KU9AfB6HbfG8fmJF
. To learn more about IPFS, visit the IPFS docs.
Also see Project Metadata.