Skip to main content


Contract: JBController​‌

Interface: IJBController

Burns a token holder's supply.

Only a token's holder, a designated operator, or a project's terminal can burn it.


function burnTokensOf(
address _holder,
uint256 _projectId,
uint256 _tokenCount,
string calldata _memo,
bool _preferClaimedTokens
directory.isTerminalDelegateOf(_projectId, msg.sender)
) { ... }
  • Arguments:
    • _holder is the account that is having its tokens burned.
    • _projectId is the ID of the project to which the tokens being burned belong.
    • _tokenCount is the number of tokens to burn.
    • _memo is a memo to pass along to the emitted event.
    • _preferClaimedTokens is flag indicating whether a project's attached token contract should be burned first if they have been issued.
  • Through the requirePermissionAllowingOverride modifier, the function is only accessible by the project's owner, from an operator that has been given the JBOperations.BURN permission by the project owner for the provided _projectId, or from one of the project's terminal's delegates.
  • The function can be overriden by inheriting contracts.
  • The function overrides a function definition from the IJBController interface.
  • The function doesn't return anything.


  1. Make sure there is a specified number of tokens to burn.

    // There should be tokens to burn
    if (_tokenCount == 0) revert NO_BURNABLE_TOKENS();
  2. Get a reference to the current funding cycle for the project.

    // Get a reference to the project's current funding cycle.
    JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);

    Internal references:

    External references:

  3. Make sure the current funding cycle for the project hasn't paused burning if the request is not coming from one of the project's terminals. If the request is coming from a terminal, allow burning regardless of the pause state because it could be a sub-routine of another operation such as redemption.

    // If the message sender is a terminal, the current funding cycle must not be paused.
    if (
    _fundingCycle.burnPaused() &&
    !directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender))

    Internal references:

    Library references:

    External references:

  4. Update the token tracker so that the correct amount of reserved tokens are still mintable after the burn.

    // Update the token tracker so that reserved tokens will still be correctly mintable.
    _processedTokenTrackerOf[_projectId] =
    _processedTokenTrackerOf[_projectId] -

    Library references:

    Internal references:

  5. Burn the tokens.

    // Burn the tokens.
    tokenStore.burnFrom(_holder, _projectId, _tokenCount, _preferClaimedTokens);

    Internal references:

    External references:

  6. Emit a BurnTokens event with the relevant parameters.

    emit BurnTokens(_holder, _projectId, _tokenCount, _memo, msg.sender);

    Event references: