Skip to main content


Contract: JBController​‌

Interface: IJBController

Mint new token supply into an account, and optionally reserve a supply to be distributed according to the project's current funding cycle configuration.

Only a project's owner, a designated operator, one of its terminals, or the current data source can mint its tokens.


function mintTokensOf(
uint256 _projectId,
uint256 _tokenCount,
address _beneficiary,
string calldata _memo,
bool _preferClaimedTokens,
bool _useReservedRate
) external virtual override returns (uint256 beneficiaryTokenCount) { ... }
  • Arguments:
    • _projectId is the ID of the project to which the tokens being minted belong.
    • _tokenCount is the amount of tokens to mint in total, counting however many should be reserved.
    • _beneficiary is the account that the tokens are being minted for.
    • _memo is a memo to pass along to the emitted event.
    • _preferClaimedTokens is a flag indicating whether a project's attached token contract should be minted if they have been issued.
    • _useReservedRate is whether to use the current funding cycle's reserved rate in the mint calculation.
  • Through the _requirePermissionAllowingOverride` internal function call, the function is only accessible by the project's owner, from an operator that has been given the JBOperations.MINT permission by the project owner for the provided _projectId, from one of the project's terminals, or from the project's current funding cycle data source.
  • The function can be overriden by inheriting contracts.
  • The function overrides a function definition from the IJBController interface.
  • The function returns the amount of tokens minted for the beneficiary.


  1. Make sure there is a specified amount of tokens to mint.

    // There should be tokens to mint.
    if (_tokenCount == 0) revert ZERO_TOKENS_TO_MINT();
  2. Make sure the message sender has appropriate permissions and that the project currently allows directly minting tokens by checking that it isn't paused when being called by any contract other than one of the project's terminals or current data sources. If the request is coming from a terminal or current data source, allow minting regardless of the pause state because it could be a sub-routine of another operation such as receiving payments. If minting is allowed, get a reference to the reserved rate that should be used. If claimed tokens are prefered at a funding cycle level, override the argument's preference.

    // Define variables that will be needed outside scoped section below.
    uint256 _reservedRate;

    // Scoped section prevents stack too deep. `_fundingCycle` is only used within scope.
    // Get a reference to the project's current funding cycle.
    JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);

    // Minting limited to: project owner, authorized callers, project terminal and current funding cycle data source
    directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender)) ||
    msg.sender == address(_fundingCycle.dataSource())

    // If the message sender is a terminal or a datasource, the current funding cycle must allow minting.
    if (
    !_fundingCycle.mintingAllowed() &&
    !directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender)) &&
    msg.sender != address(_fundingCycle.dataSource())

    // Determine the reserved rate to use.
    _reservedRate = _useReservedRate ? _fundingCycle.reservedRate() : 0;

    // Override the claimed token preference with the funding cycle value.
    _preferClaimedTokens = _preferClaimedTokens == true
    ? _preferClaimedTokens
    : _fundingCycle.preferClaimedTokenOverride();

    Library references:

    Internal references:

    External references:

  3. If the operation should reserve 100% of the minted tokens, the token tracker should be updated to add a difference of the specified token count instead of minting the tokens directly. This will allow a future distribution of reserved tokens to mint the token count to reserved addresses. Otherwise, update the token tracker if there is no intent to reserve tokens alongside the mint and mint the unreserved tokens for the beneficiary.

    if (_reservedRate == JBConstants.MAX_RESERVED_RATE)
    // Subtract the total weighted amount from the tracker so the full reserved token amount can be printed later.
    _processedTokenTrackerOf[_projectId] =
    _processedTokenTrackerOf[_projectId] -
    else {
    // The unreserved token count that will be minted for the beneficiary.
    beneficiaryTokenCount = PRBMath.mulDiv(
    JBConstants.MAX_RESERVED_RATE - _reservedRate,

    if (_reservedRate == 0)
    // If there's no reserved rate, increment the tracker with the newly minted tokens.
    _processedTokenTrackerOf[_projectId] =
    _processedTokenTrackerOf[_projectId] +

    // Mint the tokens.
    tokenStore.mintFor(_beneficiary, _projectId, beneficiaryTokenCount, _preferClaimedTokens);

    Library references:

    Internal references:

    External references:

  4. Emit a MintTokens event with the relevant parameters.

    emit MintTokens(_beneficiary, _projectId, _tokenCount, _memo, _reservedRate, msg.sender);

    Event references: