> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/circlefin/evm-cctp-contracts/llms.txt
> Use this file to discover all available pages before exploring further.

# TokenMinter

> Contract responsible for minting and burning tokens on the local domain

## Overview

The `TokenMinter` contract manages the minting and burning of tokens for cross-chain transfers. It maintains a registry of local mintable tokens and their corresponding tokens on remote domains, enabling the system to determine which token to mint on the local domain for a burned token on a remote domain, and vice versa. All local and remote tokens are assumed to be fungible at a constant 1:1 exchange rate.

## State Variables

<ParamField path="localTokenMessenger" type="address" required>
  Local TokenMessenger with permission to call mint and burn on this TokenMinter. Only this address can trigger minting and burning operations.
</ParamField>

## Functions

### mint

Mints tokens corresponding to a burn on a remote domain.

```solidity theme={null}
function mint(
    uint32 sourceDomain,
    bytes32 burnToken,
    address to,
    uint256 amount
) external returns (address mintToken)
```

<ParamField path="sourceDomain" type="uint32" required>
  Source domain where `burnToken` was burned
</ParamField>

<ParamField path="burnToken" type="bytes32" required>
  Burned token address as bytes32
</ParamField>

<ParamField path="to" type="address" required>
  Address to receive minted tokens corresponding to `burnToken` on this domain
</ParamField>

<ParamField path="amount" type="uint256" required>
  Amount of tokens to mint. Must be less than or equal to the minterAllowance of this TokenMinter for the given mint token.
</ParamField>

**Returns:** `address` - The address of the token that was minted

**Access Control:**

* Only callable by the local TokenMessenger
* Only executable when contract is not paused

**Behavior:**

* Looks up the local token address using `getLocalToken(sourceDomain, burnToken)`
* Validates the local token exists (is not address(0))
* Calls the `mint()` function on the local token contract
* Returns the minted token address

**Reverts if:**

* Caller is not the local TokenMessenger
* Contract is paused
* The (sourceDomain, burnToken) pair does not map to a nonzero local token address
* The mint operation on the token contract fails

<Note>
  You can query the local token address for a given (sourceDomain, burnToken) pair using the `getLocalToken()` view function.
</Note>

### burn

Burns tokens owned by this TokenMinter.

```solidity theme={null}
function burn(
    address burnToken,
    uint256 burnAmount
) external
```

<ParamField path="burnToken" type="address" required>
  Burnable token address
</ParamField>

<ParamField path="burnAmount" type="uint256" required>
  Amount of tokens to burn. Must be greater than 0 and less than or equal to the maximum burn amount per message.
</ParamField>

**Access Control:**

* Only callable by the local TokenMessenger
* Only executable when contract is not paused
* Must be within burn limit for the token

**Behavior:**

* Validates burn amount is within the per-message burn limit
* Calls the `burn()` function on the token contract
* Burns tokens from the TokenMinter's balance

**Reverts if:**

* Caller is not the local TokenMessenger
* Contract is paused
* burnAmount is 0
* burnAmount exceeds the maximum burn amount per message for the token
* The burn operation on the token contract fails

### addLocalTokenMessenger

Adds a TokenMessenger for the local domain. Only this TokenMessenger has permission to call `mint()` and `burn()` on this TokenMinter.

```solidity theme={null}
function addLocalTokenMessenger(
    address newLocalTokenMessenger
) external
```

<ParamField path="newLocalTokenMessenger" type="address" required>
  The address of the new TokenMessenger on the local domain. Must be nonzero.
</ParamField>

**Access Control:**

* Only callable by the contract owner

**Reverts if:**

* newLocalTokenMessenger is address(0)
* A local TokenMessenger is already set

**Events:**

* Emits `LocalTokenMessengerAdded` event

### removeLocalTokenMessenger

Removes the TokenMessenger for the local domain.

```solidity theme={null}
function removeLocalTokenMessenger() external
```

**Access Control:**

* Only callable by the contract owner

**Reverts if:**

* No local TokenMessenger is set

**Events:**

* Emits `LocalTokenMessengerRemoved` event

### setTokenController

Sets the token controller to a new address.

```solidity theme={null}
function setTokenController(
    address newTokenController
) external
```

<ParamField path="newTokenController" type="address" required>
  Address of new token controller. Must be nonzero.
</ParamField>

**Access Control:**

* Only callable by the contract owner

**Behavior:**

* Updates the token controller address
* Emits `SetTokenController` event

**Reverts if:**

* newTokenController is address(0)

<Note>
  The token controller is responsible for managing token pair mappings and burn limits. This is inherited from the `TokenController` role.
</Note>

### getLocalToken

Gets the local token address associated with a given remote domain and token.

```solidity theme={null}
function getLocalToken(
    uint32 remoteDomain,
    bytes32 remoteToken
) external view returns (address)
```

<ParamField path="remoteDomain" type="uint32" required>
  Remote domain identifier
</ParamField>

<ParamField path="remoteToken" type="bytes32" required>
  Remote token address as bytes32
</ParamField>

**Returns:** `address` - Local token address, or address(0) if no mapping exists

**Usage:**

* Query this function to determine which local token will be minted for a given remote token
* Returns address(0) if the remote token is not supported on this domain

## Burn Limits

The TokenMinter inherits from `TokenController`, which manages per-message burn limits for each token. These limits ensure that no single transaction can burn an excessive amount of tokens.

### Per-Message Burn Limits

* Each token has a maximum burn amount per message
* The `burn()` function enforces this limit via the `onlyWithinBurnLimit` modifier
* Burn limits are managed by the token controller
* Limits help protect against potential exploits and maintain system stability

<Warning>
  Attempting to burn more than the per-message burn limit will cause the transaction to revert. Always check the burn limit for a token before initiating a transfer.
</Warning>

## Token Management

The TokenMinter maintains a registry that maps remote tokens to local tokens:

* **Token Pair Registry**: Maps (remoteDomain, remoteToken) → localToken
* **1:1 Exchange Rate**: All token pairs are assumed to be fungible at a 1:1 ratio
* **Token Controller**: Manages the token pair mappings and burn limits

### Adding Token Support

To support a new token for cross-chain transfers:

1. The token controller must add a mapping between the remote token and local token
2. Set appropriate burn limits for the token
3. Ensure the TokenMinter has sufficient minter allowance on the local token contract

## Events

### LocalTokenMessengerAdded

Emitted when a local TokenMessenger is added.

```solidity theme={null}
event LocalTokenMessengerAdded(address localTokenMessenger)
```

<ParamField path="localTokenMessenger" type="address">
  Address of local TokenMessenger
</ParamField>

### LocalTokenMessengerRemoved

Emitted when a local TokenMessenger is removed.

```solidity theme={null}
event LocalTokenMessengerRemoved(address localTokenMessenger)
```

<ParamField path="localTokenMessenger" type="address">
  Address of local TokenMessenger that was removed
</ParamField>

## Access Control

The TokenMinter implements strict access control:

* **Owner**: Can add/remove local TokenMessenger and set token controller
* **Local TokenMessenger**: Can call mint() and burn() functions
* **Token Controller**: Manages token pair mappings and burn limits

### Modifier: onlyLocalTokenMessenger

Ensures that only the registered local TokenMessenger can call protected functions.

```solidity theme={null}
modifier onlyLocalTokenMessenger()
```

Reverts with "Caller not local TokenMessenger" if the caller is not the registered local TokenMessenger.

## Integration with TokenMessenger

The TokenMinter works in tandem with the TokenMessenger:

1. **Burn Flow**: TokenMessenger transfers tokens to TokenMinter, then calls `burn()`
2. **Mint Flow**: TokenMessenger calls `mint()` when receiving a cross-chain message
3. **Access Control**: Only the registered TokenMessenger can trigger minting/burning

```mermaid theme={null}
sequenceDiagram
    participant User
    participant TokenMessenger
    participant TokenMinter
    participant Token
    
    User->>TokenMessenger: depositForBurn()
    TokenMessenger->>Token: transferFrom(user, tokenMinter, amount)
    TokenMessenger->>TokenMinter: burn(token, amount)
    TokenMinter->>Token: burn(amount)
```
