Skip to main content

Life of a revnet

A revnet is a Juicebox project owned by a special contract that enforces a certain set of rules. The result is a capital formation engine for revenue-backed tokens, without risks of mismanaged payouts.

To launch a revnet, call REVDeployer.deployFor(...).

function deployFor(
uint256 revnetId,
REVConfig calldata configuration,
JBTerminalConfig[] calldata terminalConfigurations,
REVBuybackHookConfig calldata buybackHookConfiguration,
REVSuckerDeploymentConfig calldata suckerDeploymentConfiguration
)
external
override
returns (uint256 revnetId) { ... }

Check out the Launching a revnet example page for more info on how to build revnets to various specifications.

View revnet info

Launching a revnet will mint a new ERC-721 in the JBProjects contract. The owner will remain the REVDeployer contract and can be found using JBProjects.uriOf(...).

function ownerOf(uint256 projectId) external returns (address owner) { ... }

A link to the revnet's metadata can be found using JBController.uriOf(...).

function uriOf(uint256 projectId) external view returns (string memory)
View stages

Stages data can be found in the JBController contract. Stages are modeled as rulesets.

function getRulesetOf(
uint256 projectId,
uint256 rulesetId
) external view returns (JBRuleset memory ruleset, JBRulesetMetadata memory metadata)

The revnet's current stage can be found using JBController.currentRulesetOf(...).

function currentRulesetOf(uint256 projectId) external view returns (JBRuleset memory ruleset, JBRulesetMetadata memory metadata)

The revnet's upcoming stage can be found using JBController.upcomingRulesetOf(...).

By default, the upcoming stage is a copy of the current one that starts immediately afterwards, using a discounted weight if applicable.

If the revnet has queued a new stage, the upcoming stage will reflect the changes once its start time is reached. Stages queued during a stage with no ballot are automatically queued.

The revnet has no upcoming stage if the current stage has no duration, meaning the stage lasts forever.

function upcomingRulesetOf(uint256 projectId) external view returns (JBRuleset memory ruleset, JBRulesetMetadata memory metadata)

The revnet's latest queued stage can be found using JBController.latestQueuedRulesetOf(...).

function latestQueuedRulesetOf(uint256 projectId) external view returns (JBRuleset memory, JBRulesetMetadata memory metadata, JBApprovalStatus);

All of a revnet's stages can be found using JBController.allRulesetsOf(...).

function allRulesetsOf(uint256 projectId) external view returns (JBRuleset[] memory rulesets, JBRulesetMetadata[] memory metadata);
View splits

A revnet's splits data can be found in the JBSplits contract. A set of splits used for any particular functionality during any particular stage configuration can be found using JBSplits.splitsOf(...).

function splitsOf(uint256 projectId, uint256 rulesetId, uint256 groupId) external view returns (JBSplit[] memory)
View accounting contexts

A revnet's accounting contexts data can be found in its IJBTerminal contracts. For example, if a revnet is using the JBMultiTerminal contract, its accounting contexts can be found through its JBMultiTerminal.accountingContextsOf(...) transaction.

function accountingContextsOf(uint256 projectId) external view returns (JBAccountingContext[] memory) { ... }

Or, through the JBMultiTerminal.accountingContextForTokenOf(...) transaction.

function accountingContextForTokenOf(
uint256 projectId,
address token
)
external view returns (JBAccountingContext memory) { ... }
View terminals and controller

The JBDirectory contract stores addresses of terminals that a revnet accepts funds through. A revnet's permanently set terminals can be found using JBDirectory.terminalsOf(...), and the address of the terminal to which payments to revnets should be sent for any token can be found using JBDirectory.primaryTerminalOf(...).

function terminalsOf(uint256 projectId) external view returns (IJBTerminal[] memory) { ... }
function primaryTerminalOf(uint256 projectId, address token) external view returns (IJBTerminal)

The [JBDirectory](/docs/v4/api/core/f the controller that is managing a revnet's stages and tokens. The revnet's controller can be found using JBDirectory.controllerOf(...).

function controllerOf(uint256 projectId) external view returns (IERC165) { ... }

Once a revnet has been created, it can begin accepting funds from anyone through any terminal it has added, using any token that it has specified accounting contexts for. For example, if the revnet has added the JBMultiTerminal with only an ETH accounting context, only ETH can be sent to the revnet by calling its JBMultiTerminal.pay(...) transaction.

function pay(
uint256 projectId,
address token,
uint256 amount,
address beneficiary,
uint256 minReturnedTokens,
string calldata memo,
bytes calldata metadata
) external payable returns (uint256 beneficiaryTokenCount);

Check out the Paying a project example page for more info on how to pay a revnet.

View revnet balance

A revnet's balance can be found in the JBTerminalStore contract.

function balanceOf(address terminal, uint256 projectId, address token) external view returns (uint256);

The JBTerminalStore can also resolve the total amount in all of a revnet's terminals using JBTerminalStore.currentTotalSurplusOf(...).

function currentTotalSurplusOf(
uint256 projectId,
uint256 decimals,
uint256 currency
)
external
view
returns (uint256);
View revnet token balance

Each holder's balance of a revnet's token can be found in the JBTokens contract. The balance can be found using JBTokens.totalBalanceOf(...).

function totalBalanceOf(address holder, uint256 projectId) external view returns (uint256 result) { ... }

To only retrieve a holder's internally tracked token credit balance, use JBTokens.creditBalanceOf(...)

function creditBalanceOf(address holder, uint256 projectId) external view returns (uint256) { ... }
View price conversions

The protocol uses price feeds to convert values from one currency to another when sending payouts, using surplus allowances, issuing revnet tokens when payments are received in various currencies, and more. Current currency indexes can be found in JBCurrencyIds. If the currency strongly correlates to an ERC-20, it is cusom to use the first 32 bytes of its address as the currency. Since ETH is treated using JBConstants.NATIVE_TOKEN, its currency is 61166. New currencies and price feeds can be added in the future.

The same price feeds the protocol uses internally can be accessed externally through the JBPrices contract using JBPrices.pricePerUnitOf(...).

function pricePerUnitOf(
uint256 projectId,
uint256 pricingCurrency,
uint256 unitCurrency,
uint256 decimals
) external view returns (uint256) { ... }

A revnet automatically issues an ERC-20 token for itself when it is created.

View the revnet's token

The token currently being used by a revnet can be found in the JBTokens contract by using JBTokens.tokenOf(...).

function tokenOf(uint256 projectId) external view override returns (IJBToken) { ... }

At any point, anyone can distribute a revnet's split tokens to the revnet's preprogrammed splits by calling JBController.sendReservedTokensToSplitsOf(...).

function sendReservedTokensToSplitsOf(uint256 projectId) external returns (uint256) { ... }
View split token balance

A project's undistributed split token balance can be found in the revnet's current controller. For example in the JBController, this balance can be found using JBController.pendingReservedTokenBalanceOf(...).

function pendingReservedTokenBalanceOf(uint256 projectId) external view returns (uint256) { ... }

For revnets using JBController, the revnet token's total supply including any allocated split tokens that have yet to be distributed can be found in using JBController.totalTokenSupplyWithReservedTokensOf(...).

function totalTokenSupplyWithReservedTokensOf(uint256 projectId) external view returns (uint256) { ... }

Anyone who holds a revnet's tokens can cash them out at one of the revnet's terminals for a proportional share of the revnet's balance. For example, if the revnet has funds in the JBMultiTerminal, ETH can be reclaimed by redeeming revnet tokens in its JBMultiTerminal.cashOutTokensOf(...) transaction. The surplus amount is the terminal's balance minus the current ruleset's payout limit, and can be set to include the revnet's balance across all terminals.

Cashing out tokens allows a revnet's token holders to exit the community at any time with their share of the funds. If the revnet's cash out tax rate is more than 0%, cash outs incur a 2.5% NANA membership fee, and a 2.5% REV membership fee. Both NANA and REV are revnets themselves, so fee payers will receive a proportional share of the respective networks.

function cashOutTokensOf(
address holder,
uint256 projectId,
uint256 cashOutCount,
address tokenToReclaim,
uint256 minTokensReclaimed,
address payable beneficiary,
bytes calldata metadata
)
external
returns (uint256 reclaimAmount);
View cash out values

Any surplus allowance used can also be found in the terminal store contracts for each terminal using JBTerminalStore.usedSurplusAllowanceOf(...).

function currentReclaimableSurplusOf(
uint256 projectId,
uint256 tokenCount,
uint256 totalSupply,
uint256 surplus
)
external view returns (uint256) { ... }

or, to determine the surplus of a revnet from its terminals, use JBTerminalStore.currentReclaimableSurplusOf(...).

function currentReclaimableSurplusOf(
uint256 projectId,
uint256 cashOutCount,
IJBTerminal[] calldata terminals,
JBAccountingContext[] calldata accountingContexts,
uint256 decimals,
uint256 currency
)
external view returns (uint256) { ... }

Anyone can burn their tokens by calling JBController.burnTokensOf(...).

function burnTokensOf(address holder, uint256 projectId, uint256 tokenCount, string calldata memo) external;

At any point, anyone can inject funds into one of a revnet's terminals by calling the terminal's JBMultiTerminal.addToBalanceOf(...) transaction.

function addToBalanceOf(
uint256 projectId,
address token,
uint256 amount,
bool shouldReturnHeldFees,
string calldata memo,
bytes calldata metadata
) external payable;