Skip to main content

IMintBurnToken Interface

The IMintBurnToken interface defines the contract interface for ERC20 tokens that support both minting and burning operations. This interface is implemented by USDC and other tokens that integrate with CCTP’s TokenMinter contract. Source: IMintBurnToken.sol

Overview

IMintBurnToken extends the standard ERC20 interface (IERC20) with additional mint and burn functions. These functions are called by the TokenMinter contract during cross-chain transfers:
  • mint() is called when receiving USDC on the destination chain
  • burn() is called when sending USDC from the source chain

Interface Definition

interface IMintBurnToken is IERC20 {
    function mint(address to, uint256 amount) external returns (bool);
    function burn(uint256 amount) external;
}

Functions

mint

Mints new tokens to a specified address.
function mint(address to, uint256 amount) external returns (bool);

Parameters

  • to (address): The address that will receive the minted tokens
  • amount (uint256): The amount of tokens to mint (must be less than or equal to the minter’s allowance)

Returns

  • bool: Returns true if the operation was successful

Requirements

  • Caller must have minter role
  • Caller must have sufficient minter allowance
  • Recipient address must not be blacklisted
  • Amount must be greater than 0

Usage in CCTP

The TokenMinter contract calls this function when processing a cross-chain transfer on the destination chain. After verifying the attestation, TokenMinter mints the specified amount of USDC to the recipient. Reference: src/TokenMinter.sol:111

burn

Burns tokens from the caller’s balance.
function burn(uint256 amount) external;

Parameters

  • amount (uint256): The amount of tokens to burn from the caller’s balance

Requirements

  • Caller must have minter role
  • Caller must not be blacklisted
  • Amount must be less than or equal to the caller’s balance
  • Amount must be greater than 0

Usage in CCTP

The TokenMinter contract calls this function when processing a depositForBurn request on the source chain. The USDC is burned before the cross-chain message is sent. Reference: src/TokenMinter.sol:86

Implementation Example

Here’s how a token contract might implement this interface:
contract MintBurnToken is IMintBurnToken, ERC20 {
    mapping(address => bool) public minters;
    mapping(address => uint256) public minterAllowance;
    mapping(address => bool) public blacklisted;
    
    modifier onlyMinter() {
        require(minters[msg.sender], "Caller is not a minter");
        _;
    }
    
    modifier notBlacklisted(address account) {
        require(!blacklisted[account], "Account is blacklisted");
        _;
    }
    
    function mint(address to, uint256 amount) 
        external 
        override 
        onlyMinter 
        notBlacklisted(to)
        returns (bool) 
    {
        require(amount > 0, "Amount must be greater than 0");
        require(
            amount <= minterAllowance[msg.sender],
            "Mint amount exceeds minter allowance"
        );
        
        minterAllowance[msg.sender] -= amount;
        _mint(to, amount);
        
        return true;
    }
    
    function burn(uint256 amount) 
        external 
        override 
        onlyMinter 
        notBlacklisted(msg.sender) 
    {
        require(amount > 0, "Amount must be greater than 0");
        require(amount <= balanceOf(msg.sender), "Insufficient balance");
        
        _burn(msg.sender, amount);
    }
}

Integration with CCTP

Token Registration

For a token to be used with CCTP, it must:
  1. Implement the IMintBurnToken interface
  2. Grant minter role to the TokenMinter contract
  3. Set appropriate minter allowance for the TokenMinter
  4. Be registered via TokenController.linkTokenPair()

Burn-and-Mint Flow

  1. Source Chain: User calls TokenMessenger.depositForBurn()
    • TokenMessenger calls TokenMinter.burn()
    • TokenMinter calls IMintBurnToken.burn() on USDC contract
    • USDC is burned from user’s balance
  2. Attestation: Circle attesters sign the message hash
  3. Destination Chain: Relayer calls MessageTransmitter.receiveMessage()
    • MessageTransmitter calls TokenMessenger.handleReceiveMessage()
    • TokenMessenger calls TokenMinter.mint()
    • TokenMinter calls IMintBurnToken.mint() on USDC contract
    • USDC is minted to recipient’s address

Security Considerations

Token contracts implementing this interface must include proper access control to prevent unauthorized minting and burning.

Access Control

  • Minter Role: Only authorized minters (like TokenMinter) should be able to call mint() and burn()
  • Allowance Limits: Implement minter allowances to cap the maximum amount that can be minted
  • Blacklisting: Support address blacklisting to comply with regulatory requirements

Validation

  • Amount Checks: Always validate that amounts are greater than zero
  • Balance Checks: Ensure sufficient balance before burning
  • Overflow Protection: Use SafeMath or Solidity 0.8+ to prevent overflows

External Resources

Build docs developers (and LLMs) love