Skip to content

MinterGateway

Where money is born.

The MinterGateway contract serves as the central hub for minting and burning MTokens, managing minter collateral, and tracking debt obligations in the M0 Protocol.

Minter Types and Lifecycle

The system recognizes several states for minters:

  1. Approved: Minters whitelisted by the TTG governance system
  2. Active: Approved minters who have activated their minting capabilities
  3. Frozen: Active minters temporarily prevented from minting (but can still burn)
  4. Deactivated: Former minters who have exited the system (cannot be reactivated)

Collateral Management

Unlike traditional onchain collateral systems, M0 uses a validator-verified offchain collateral model:

  • Real-World Backing: Collateral exists in a Special Purpose Vehicle (SPV) as real-world assets
  • Validator Verification: Trusted validators periodically verify and sign off on collateral values
  • Update Requirements: Minters must update their collateral regularly (typically daily)
  • Expiration Mechanism: Collateral is considered zero if not updated within the specified interval
  • Update Signatures: Multiple validator signatures are required, with the minimum threshold set by governance

Minting Process

Creating new MTokens follows a structured three-step process designed to enhance security and enable validator oversight:

  1. Update Collateral: Minters provide validator signatures confirming offchain collateral

    function updateCollateral(
        uint256 collateral,
        uint256[] calldata retrievalIds,
        bytes32 metadataHash,
        address[] calldata validators,
        uint256[] calldata timestamps,
        bytes[] calldata signatures
    )
  2. Propose Mint: Minters request to mint a specific amount to a destination, creating a proposal that validators can review

    function proposeMint(uint256 amount, address destination)
  3. Execute Mint: After a mandatory delay period (mintDelay) and before expiry (mintTTL), minters execute their proposal if it hasn't been frozen or canceled by validators

    function mintM(uint256 mintId)

This multi-step approach with time delays creates security checkpoints where validators can intervene if they detect suspicious activity, providing crucial protection for the protocol's monetary integrity.

Debt and Interest System

Minters accrue interest on their outstanding debt:

  • Continuous Indexing: The same indexing system used in MToken tracks growth of obligations
  • Principal Storage: Like earning balances, minter debt is stored as principal amounts that grow with interest
  • Rate Model: Interest rates are determined by an external rate model set through governance
  • ActiveOwedM: The current value of a minter's obligations including accrued interest

Validator Signature Verification

The signature verification system includes several security features:

  • Multi-signature Requirement: Requires multiple validator signatures for collateral updates
  • Ordered Validator Addresses: Validators addresses must be provided in ascending order to prevent duplicates
  • Timestamp Validation: Each signature includes a timestamp that must be:
    • Newer than the last signature from that validator for that minter
    • Not in the future
    • Not zero
  • Replay Protection: The system tracks the last used timestamp for each validator-minter pair
  • Signature Format: Uses EIP-712 typed data signatures that are validator-specific

Penalty System

The protocol enforces discipline through two types of penalties:

  1. Missed Updates Penalty: Applied when minters fail to update collateral within required intervals
    • Calculated as penaltyRate × principalOfActiveOwedM × missedIntervals
    • Charged only once per missed interval
  2. Undercollateralization Penalty: Applied when active owed M exceeds allowed maximum
    • Calculated as penaltyRate × principalOfExcessOwedM × timeSpan / updateCollateralInterval
    • Proportional to the duration of undercollateralization

Collateral Retrievals

Minters can reduce their collateral through a structured process:

  1. Propose Retrieval: Minter requests to retrieve a specific amount of collateral

    function proposeRetrieval(uint256 collateral)
  2. Validator Inclusion: Validators specifically include the retrieval IDs they've approved in their next collateral update signatures. Only these explicitly included retrievals will be processed.

  3. Retrieval Resolution: When collateral is updated, the approved retrievals are processed and their amounts are no longer deducted from the minter's effective collateral value

This ensures that collateral can only be retrieved with explicit validator approval, maintaining the system's safety.

Note the retrieval flow includes these technical aspects:

  • Retrieval proposals have unique IDs generated sequentially
  • Proposed retrievals are tracked in _pendingCollateralRetrievals mapping
  • The system prevents retrievals that would cause undercollateralization
  • Pending retrievals are explicitly deducted from the minter's effective collateral value for all system calculations, ensuring proper collateralization before the retrievals are resolved
  • Multiple retrievals can be resolved in a single update
  • Retrievals can only be resolved during a validated collateral update, requiring validator signatures that explicitly approve the retrieval IDs to be processed

Validator Role

Validators serve as trusted entities who:

  • Verify offchain collateral and sign update requests
  • Must provide timestamps with their signatures to prevent replay attacks
  • Can cancel suspicious mint proposals
  • Can freeze minters to prevent further minting for a governance-defined period
  • Enable the bridge between offchain assets and onchain accounting

Burning Mechanism

Any token holder can burn MTokens to reduce a minter's debt:

  • For active minters, burns reduce the principal of their owed M
  • For deactivated minters, burns reduce their fixed inactive owed M
  • After deactivation, burning serves as an informal liquidation mechanism

Index Update Triggers

The interest index is updated in several key situations:

  • When collateral is updated through updateCollateral()
  • When tokens are minted via mintM()
  • When tokens are burned via burnM()
  • When a minter is deactivated via deactivateMinter()
  • When updateIndex() is explicitly called

Each update synchronizes both the MinterGateway's index and the MToken's index simultaneously, ensuring that minter obligation rates and earner yield rates maintain proper system balance throughout the protocol.

function updateIndex() public override(IContinuousIndexing, ContinuousIndexing) returns (uint128 index_) {
    // ...
    index_ = super.updateIndex(); // Update minter index and rate.
 
    // ...
    IMToken(mToken).updateIndex(); // Update earning index and rate.
}

Total Owed M Accounting

The system tracks minter obligations with specialized accounting:

  • Active Owed M: Tracked as principal amounts that accrue interest
  • Inactive Owed M: Fixed amounts for deactivated minters that don't accrue interest
  • Total Owed M: The sum of active and inactive obligations
  • Excess Owed M: The difference between total owed M and total M supply, minted to the TTG Vault

Timing Constraints

The system enforces several timing-related constraints:

  • Collateral Update Frequency: Minters must update at least once per updateCollateralInterval
  • Mint Delay: Proposals must wait mintDelay seconds before execution
  • Mint TTL: Proposals expire after mintTTL seconds
  • Earliest Collateral Update: The timestamp for a new update must be greater than:
    • The last update timestamp
    • The latest proposed retrieval timestamp
    • block.timestamp - updateCollateralInterval

Security Mechanisms

The MinterGateway implements several safety features:

  • Mint Delay & TTL (Time-To-Leave): Creates a time window for validators to review and potentially cancel mints
  • Collateralization Caps: Enforces maximum mint-to-collateral ratios (set by governance)
  • Multi-signature Requirement: Requires multiple validator signatures for collateral updates
  • Strictly Ordered Validations: Validator addresses must be provided in ascending order
  • Timestamp Verification: Prevents reuse of signatures and ensures freshness of collateral data
  • Excess Yield Distribution: Any yield generated by minters beyond what's distributed to earners goes to the TTG Vault (also called the Distribution Vault)

Emergency Measures

For extreme circumstances, the protocol includes additional safeguards:

Mint Proposal Cancellation

Validators can cancel suspicious mint proposals before they're executed, allowing them to quickly intervene if they detect potentially harmful minting activity.

function cancelMint(address minter_, uint256 mintId_) external onlyApprovedValidator {
    uint48 id_ = _mintProposals[minter_].id;
    if (id_ != mintId_ || id_ == 0) revert InvalidMintProposal();
    delete _mintProposals[minter_];
    emit MintCanceled(id_, minter_, msg.sender);
}

Validator Freeze

Validators can freeze minters to stop them from minting tokens for a governance-defined period:

function freezeMinter(address minter_) external onlyApprovedValidator returns (uint40 frozenUntil_) {
    unchecked {
        _minterStates[minter_].frozenUntilTimestamp = frozenUntil_ = uint40(block.timestamp) + minterFreezeTime();
    }
    emit MinterFrozen(minter_, frozenUntil_);
}

Minter Deactivation

Governance can completely deactivate minters who have been removed from the approved list:

function deactivateMinter(address minter_) external onlyActiveMinter(minter_) returns (uint240 inactiveOwedM_) {
    if (isMinterApproved(minter_)) revert StillApprovedMinter();
    // Implementation details for deactivation process
}

Once deactivated, a minter cannot be reactivated, providing a permanent resolution for problematic minters.

Open Redemption

Anyone can burn $M tokens to repay a deactivated minter's debt:

function _repayForDeactivatedMinter(address minter_, uint240 maxAmount_) internal returns (uint240 amount_) {
    amount_ = UIntMath.min240(inactiveOwedMOf(minter_), maxAmount_);
    unchecked {
        _rawOwedM[minter_] -= amount_;
        totalInactiveOwedM -= amount_;
    }
}

This creates an informal liquidation mechanism for deactivated minters.