Skip to content

MToken

Code

MToken is an ERC20 token implementing a dual-balance accounting system, allowing users to choose between non-earning and earning balances.

Token Overview

MBalance Struct

The MToken uses a special balance struct to track the state of each account's balance:

struct MBalance {
    bool isEarning;
    uint240 rawBalance;
}

This struct serves dual purposes:

  • For non-earning accounts: rawBalance represents the actual token balance
  • For earning accounts: rawBalance represents the principal amount, which grows over time via indexing

Key State Variables

address public immutable minterGateway;
address public immutable ttgRegistrar;
uint240 public totalNonEarningSupply;
uint112 public principalOfTotalEarningSupply;
mapping(address account => MBalance balance) internal _balances;

These variables track the essential state of the token system:

  • minterGateway: authorized address for minting and burning
  • ttgRegistrar: address of the TTG Registrar that governs earnings eligibility
  • totalNonEarningSupply: total supply of non-earning tokens
  • principalOfTotalEarningSupply: principal amount of earning tokens
  • _balances: mapping of account balances

Functions

constructor

constructor(address ttgRegistrar_, address minterGateway_) ContinuousIndexing() ERC20Extended("M by M0", "M", 6)

Initializes the token with:

  • Name: "M by M0"
  • Symbol: "M"
  • Decimals: 6
  • TTG Registrar and Minter Gateway addresses

Parameters:

NameTypeDescription
ttgRegistrar_addressThe TTG Registrar contract address
minterGateway_addressThe Minter Gateway contract address

mint

function mint(address account_, uint256 amount_) external onlyMinterGateway

Mints new tokens to the specified account.

  • Only callable by the minter gateway
  • Handles both earning and non-earning accounts differently

Parameters:

NameTypeDescription
account_addressThe recipient of the tokens
amount_uint256The amount of tokens to mint

burn

function burn(address account_, uint256 amount_) external onlyMinterGateway

Burns tokens from the specified account.

  • Only callable by the minter gateway
  • Handles both earning and non-earning accounts differently

Parameters:

NameTypeDescription
account_addressThe account to burn tokens from
amount_uint256The amount of tokens to burn

startEarning

function startEarning() external

Transitions the caller's account to earning mode.

  • Converts non-earning balance to principal
  • Reverts if caller is not approved as an earner by TTG Registrar
  • Emits a StartedEarning event

stopEarning (self)

function stopEarning() external

Transitions the caller's account to non-earning mode.

  • Converts principal plus accrued interest to a standard balance
  • Emits a StoppedEarning event

stopEarning (for other account)

function stopEarning(address account_) external

Transitions a specified account to non-earning mode.

  • Reverts if the account is approved as an earner by TTG Registrar
  • Useful for administrative operations or governance

Parameters:

NameTypeDescription
account_addressThe account to stop earning for

updateIndex

function updateIndex() public virtual returns (uint128 currentIndex_)

Updates the stored index based on time elapsed and current rate.

  • Fetches the latest rate from the rate model
  • Emits an IndexUpdated event

Return Values:

NameTypeDescription
currentIndex_uint128The new index value

rateModel

function rateModel() public view returns (address rateModel_)

Returns the address of the rate model contract.

Return Values:

NameTypeDescription
rateModel_addressThe address of the rate model

earnerRate

function earnerRate() public view returns (uint32 earnerRate_)

Returns the current rate used for interest calculations.

Return Values:

NameTypeDescription
earnerRate_uint32Current rate in basis points

totalEarningSupply

function totalEarningSupply() public view returns (uint240 totalEarningSupply_)

Calculates the current total of all earning tokens including accrued interest.

Return Values:

NameTypeDescription
totalEarningSupply_uint240Total amount of earning tokens

totalSupply

function totalSupply() external view returns (uint256 totalSupply_)

Returns the sum of total non-earning supply and total earning supply.

Return Values:

NameTypeDescription
totalSupply_uint256Total supply of all tokens

principalBalanceOf

function principalBalanceOf(address account_) external view returns (uint240 balance_)

Returns the principal amount for earning accounts.

Parameters:

NameTypeDescription
account_addressThe account to check

Return Values:

NameTypeDescription
balance_uint240Principal balance if earning, otherwise zero

balanceOf

function balanceOf(address account_) external view returns (uint256 balance_)

Returns the token balance of an account.

  • For earning accounts: Returns principal with accrued interest
  • For non-earning accounts: Returns raw balance

Parameters:

NameTypeDescription
account_addressThe account to check

Return Values:

NameTypeDescription
balance_uint256Current token balance

isEarning

function isEarning(address account_) external view returns (bool isEarning_)

Checks if an account is in earning mode.

Parameters:

NameTypeDescription
account_addressThe account to check

Return Values:

NameTypeDescription
isEarning_boolWhether the account is in earning mode

currentIndex

function currentIndex() public view override returns (uint128)

Calculates the current index based on the rate and time elapsed.

Return Values:

NameTypeDescription
currentIndex_uint128Current index value

Key Internal Functions

_transfer

Internal override of the ERC20 transfer function handling transfers between earning and non-earning accounts.

_startEarning/_stopEarning

Internal functions to handle transitioning accounts between earning and non-earning modes.

_getPresentAmount

Calculates the present value of a principal amount using the current or specified index.

_getPrincipalAmount

Calculates the principal amount from a present value using rounding favoring the protocol.

_isApprovedEarner

Checks if an account is approved to earn by the TTG Registrar.

_rate

Retrieves the current rate from the rate model contract.

Events

event StartedEarning(address indexed account);
event StoppedEarning(address indexed account);
event IndexUpdated(uint128 indexed index, uint32 indexed rate);
  • StartedEarning: Emitted when an account transitions to earning mode
  • StoppedEarning: Emitted when an account transitions to non-earning mode
  • IndexUpdated: Emitted when the index is updated with a new value

Custom Errors

error InsufficientBalance(address account, uint256 rawBalance, uint256 amount);
error IsApprovedEarner();
error NotApprovedEarner();
error NotMinterGateway();
error OverflowsPrincipalOfTotalSupply();
error ZeroMinterGateway();
error ZeroTTGRegistrar();

These custom errors provide clear signals about issues during operations.