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:
- Implement the
IMintBurnToken interface
- Grant minter role to the TokenMinter contract
- Set appropriate minter allowance for the TokenMinter
- Be registered via
TokenController.linkTokenPair()
Burn-and-Mint Flow
-
Source Chain: User calls
TokenMessenger.depositForBurn()
- TokenMessenger calls
TokenMinter.burn()
- TokenMinter calls
IMintBurnToken.burn() on USDC contract
- USDC is burned from user’s balance
-
Attestation: Circle attesters sign the message hash
-
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