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 burningttgRegistrar
: address of the TTG Registrar that governs earnings eligibilitytotalNonEarningSupply
: total supply of non-earning tokensprincipalOfTotalEarningSupply
: 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:
Name | Type | Description |
---|---|---|
ttgRegistrar_ | address | The TTG Registrar contract address |
minterGateway_ | address | The 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:
Name | Type | Description |
---|---|---|
account_ | address | The recipient of the tokens |
amount_ | uint256 | The 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:
Name | Type | Description |
---|---|---|
account_ | address | The account to burn tokens from |
amount_ | uint256 | The 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:
Name | Type | Description |
---|---|---|
account_ | address | The 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:
Name | Type | Description |
---|---|---|
currentIndex_ | uint128 | The new index value |
rateModel
function rateModel() public view returns (address rateModel_)
Returns the address of the rate model contract.
Return Values:
Name | Type | Description |
---|---|---|
rateModel_ | address | The address of the rate model |
earnerRate
function earnerRate() public view returns (uint32 earnerRate_)
Returns the current rate used for interest calculations.
Return Values:
Name | Type | Description |
---|---|---|
earnerRate_ | uint32 | Current 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:
Name | Type | Description |
---|---|---|
totalEarningSupply_ | uint240 | Total 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:
Name | Type | Description |
---|---|---|
totalSupply_ | uint256 | Total supply of all tokens |
principalBalanceOf
function principalBalanceOf(address account_) external view returns (uint240 balance_)
Returns the principal amount for earning accounts.
Parameters:
Name | Type | Description |
---|---|---|
account_ | address | The account to check |
Return Values:
Name | Type | Description |
---|---|---|
balance_ | uint240 | Principal 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:
Name | Type | Description |
---|---|---|
account_ | address | The account to check |
Return Values:
Name | Type | Description |
---|---|---|
balance_ | uint256 | Current token balance |
isEarning
function isEarning(address account_) external view returns (bool isEarning_)
Checks if an account is in earning mode.
Parameters:
Name | Type | Description |
---|---|---|
account_ | address | The account to check |
Return Values:
Name | Type | Description |
---|---|---|
isEarning_ | bool | Whether 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:
Name | Type | Description |
---|---|---|
currentIndex_ | uint128 | Current 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 modeStoppedEarning
: Emitted when an account transitions to non-earning modeIndexUpdated
: 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.