mToken
In the Market Protocol, each mToken
contract can be thought of as an individual vault that stores an underlying asset for a pool. Each underlying asset has its own mToken
and they are unique to each pool, thanks to the isolation provided by the protocol. Also in our docs, we use CToken
and MToken
interchangeably.
Implementation
The mToken
contract is implemented as an upgradable proxy, where the CTokenDelegator
contract proxies all interactions/logic to CTokenDelegate
while using the storage of CTokenDelegator
. To learn more about upgradable proxies, read Proxy Upgradable Pattern by OpenZeppelin.
Some Important Terms
Exchange Rate
Each mToken
is convertible into an ever increasing quantity of the underlying asset, as interest accrues in the market.
Interest Calculation
The APY for supplying or borrowing into a mToken
in any given pool, can be calculated very easily, here's a sample snippet:
Reserves
Reserves are an accounting entry in each mToken contract that represents a portion of historical interest set aside as cash which can be withdrawn or transferred through the protocol's governance. A small portion of borrower interest accrues into the protocol, determined by the reserve factor.
Reserve factor is the fraction of interest that is set-aside for reserves.
View Methods
exchangeRateCurrent -> uint
returns - The current exchange rate as an unsigned integer, scaled by 1e18.
getCash -> uint
returns - The total amount of underlying balance owned by the contract as an unsigned integer, scaled by 1e18.
totalBorrowsCurrent -> uint
returns - The total amount of underlying that has been currently loaned out to users with interest included.
note - use
eth_call
on this function, otherwise it will create a transaction.
totalSupply -> uint
returns - The total number of tokens that are in circulation
totalReserves -> uint
returns - The total amount of reserves of the underlying held in this
mToken
balanceOfUnderlying(address) -> uint
returns - The total amount of underlying asset owned by a user that is held in this contract
note - use
eth_call
on this function, otherwise it will create a transaction.This is calculated by multiplying the exchangeRate with the number of
mTokens
the user holds
borrowRatePerBlock -> uint
returns - The current per-block borrow interest rate for this
mToken
scaled by 1e18.
supplyRatePerBlock -> uint
returns - The current per-block supply interest rate for this
mToken
scaled by 1e18.
reserveFactorMantissa -> uint
returns - Reserve Factor of the
mToken
which is fraction of interest currently set aside for reserves. It is scaled to 18 decimals.
adminFeeMantissa -> uint
returns - The admin fee charged by the pool administrator. It is scaled to 18 decimals.
Write Methods
mint(uint) -> uint
Allows a user to deposit underlying into this mToken
. approve
must be called on the underlying for this contract.
mintAmount - the amount of underlying to be deposited
returns - an error code. 0 is a success and anything else is a failure.
borrow(uint) -> uint
Allows a user who has collateral in the pool, to borrow from this mToken
.
borrowAmount - the amount of underlying to be borrowed
returns - an error code. 0 is a success and anything else is a failure.
redeem(uint) -> uint
Allows a user who has supplied underlying in this mToken
to redeem it back based on the number of mTokens
they want. It uses exchangeRate internally to convert number of mTokens
to underlying tokens.
redeemAmount - the number of
mTokens
against which the user wants to redeem underlyingreturns - an error code. 0 is a success and anything else is a failure
redeemUnderlying(uint) -> uint
Allows a user who has supplied underlying in this mToken
to redeem it back based on the number of underlying tokens they want.
redeemAmount - the number of underlying tokens which they want to redeem
returns - an error code. 0 is a success and anything else is a failure
repayBorrow(uint) -> uint
Allows a user to repay their loan previously taken from this mToken
repayAmount - the number of underlying tokens the user wants to repay
returns - an error code. 0 is a success and anything else is a failure
repayBorrowBehalf(address, uint) -> uint
Allows a user to repay a loan on someone else's behalf
borrower - address of the borrower's account for which the user wants to repay
repayAmount - the number of underlying tokens the user wants to repay
returns - an error code. 0 is a success and anything else is a failure
liquidateBorrow(address, uint, address) -> uint
Allows a user to liquidate an unhealthy borrower's debt and gain liquidation incentive for doing this.
borrower - the account which is being liquidated
repayAmount - the number of underlying tokens the user wants to repay
mTokenCollateral - the mToken to be received for liquidating this account's debt
returns - an error code. 0 is a success and anything else is a failure
_setAdminFee(uint) -> uint
Allows pool administrators to set an admin fee for managing this asset.
newAdminFeeMantissa - the new admin fee to be set. scaled to 18 decimals.
returns - an error code. 0 is a success and anything else is a failure.
_setReserveFactor(uint) -> uint
Allows pool administrators to set the reserve factor, which contributes a fraction of the interest into reserves.
newReserveFactorMantissa - the new reserve factor value to be set. scaled to 18 decimals.
returns - an error code. 0 is a success and anything else is a failure.
_setInterestRateModel(address) -> uint
Allows pool administrators to set a new interest rate model for this mToken
.
newInterestRateModel - address of the new interest rate model contract
returns - an error code. 0 is a success and anything else is a failure.
_setNameAndSymbol(string, string) -> uint
Allows pool administrators to change the name/symbol of this mToken
to their desired name/symbol.
Error Codes
Code | Name | Description |
---|---|---|
0 | NO_ERROR | Success. Not an error. |
1 | UNAUTHORIZED | The sender is not authorized to perform this action. |
2 | BAD_INPUT | An invalid argument was supplied by the caller. |
3 | COMPTROLLER_REJECTION | The comptroller rejects the action requested by the market/mToken. |
4 | COMPTROLLER_CALCULATION_ERROR | An internal calculation has failed in the comptroller. |
5 | INTEREST_RATE_MODEL_ERROR | The interest rate model returned an invalid value. |
6 | INVALID_ACCOUNT_PAIR | The specified combination of accounts is invalid. |
7 | INVALID_CLOSE_AMOUNT_REQUESTED | The amount to liquidate is invalid. |
8 | INVALID_COLLATERAL_FACTOR | The collateral factor is invalid. |
9 | MATH_ERROR | A math calculation error occurred. |
10 | MARKET_NOT_FRESH | Interest has not been properly accrued. |
11 | MARKET_NOT_LISTED | The |
12 | TOKEN_INSUFFICIENT_ALLOWANCE | ERC-20 contract must allow |
13 | TOKEN_INSUFFICIENT_BALANCE | Caller does not have sufficient balance in the ERC-20 contract to complete the desired action. |
14 | TOKEN_INSUFFICIENT_CASH | The |
15 | TOKEN_TRANSFER_IN_FAILED | Failure in ERC-20 when transferring token into the |
16 | TOKEN_TRANSFER_OUT_FAILED | Failure in ERC-20 when transferring token out of the |
17 | UTILIZATION_ABOVE_MAX | No more of this token can be borrowed right now. |
Failure Info
Code | Name |
---|---|
0 | ACCEPT_ADMIN_PENDING_ADMIN_CHECK |
1 | ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED |
2 | ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED |
3 | ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED |
4 | ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED |
5 | ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED |
6 | ACCRUE_INTEREST_NEW_TOTAL_FUSE_FEES_CALCULATION_FAILED |
7 | ACCRUE_INTEREST_NEW_TOTAL_ADMIN_FEES_CALCULATION_FAILED |
8 | ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED |
9 | BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED |
10 | BORROW_ACCRUE_INTEREST_FAILED |
11 | BORROW_CASH_NOT_AVAILABLE |
12 | BORROW_FRESHNESS_CHECK |
13 | BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED |
14 | BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED |
15 | BORROW_MARKET_NOT_LISTED |
16 | BORROW_COMPTROLLER_REJECTION |
17 | LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED |
18 | LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED |
19 | LIQUIDATE_COLLATERAL_FRESHNESS_CHECK |
20 | LIQUIDATE_COMPTROLLER_REJECTION |
21 | LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED |
22 | LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX |
23 | LIQUIDATE_CLOSE_AMOUNT_IS_ZERO |
24 | LIQUIDATE_FRESHNESS_CHECK |
25 | LIQUIDATE_LIQUIDATOR_IS_BORROWER |
26 | LIQUIDATE_REPAY_BORROW_FRESH_FAILED |
27 | LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED |
28 | LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED |
29 | LIQUIDATE_SEIZE_COMPTROLLER_REJECTION |
30 | LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER |
31 | LIQUIDATE_SEIZE_TOO_MUCH |
32 | MINT_ACCRUE_INTEREST_FAILED |
33 | MINT_COMPTROLLER_REJECTION |
34 | MINT_EXCHANGE_CALCULATION_FAILED |
35 | MINT_EXCHANGE_RATE_READ_FAILED |
36 | MINT_FRESHNESS_CHECK |
37 | MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED |
38 | MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED |
39 | MINT_TRANSFER_IN_FAILED |
40 | MINT_TRANSFER_IN_NOT_POSSIBLE |
41 | NEW_UTILIZATION_RATE_ABOVE_MAX |
42 | REDEEM_ACCRUE_INTEREST_FAILED |
43 | REDEEM_COMPTROLLER_REJECTION |
44 | REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED |
45 | REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED |
46 | REDEEM_EXCHANGE_RATE_READ_FAILED |
47 | REDEEM_FRESHNESS_CHECK |
48 | REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED |
49 | REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED |
50 | REDEEM_TRANSFER_OUT_NOT_POSSIBLE |
51 | WITHDRAW_PROTOCOL_FEES_ACCRUE_INTEREST_FAILED |
52 | WITHDRAW_PROTOCOL_FEES_CASH_NOT_AVAILABLE |
53 | WITHDRAW_PROTOCOL_FEES_FRESH_CHECK |
54 | WITHDRAW_PROTOCOL_FEES_VALIDATION |
55 | WITHDRAW_ADMIN_FEES_ACCRUE_INTEREST_FAILED |
56 | WITHDRAW_ADMIN_FEES_CASH_NOT_AVAILABLE |
57 | WITHDRAW_ADMIN_FEES_FRESH_CHECK |
58 | WITHDRAW_ADMIN_FEES_VALIDATION |
59 | REDUCE_RESERVES_ACCRUE_INTEREST_FAILED |
60 | REDUCE_RESERVES_ADMIN_CHECK |
61 | REDUCE_RESERVES_CASH_NOT_AVAILABLE |
62 | REDUCE_RESERVES_FRESH_CHECK |
63 | REDUCE_RESERVES_VALIDATION |
64 | REPAY_BEHALF_ACCRUE_INTEREST_FAILED |
65 | REPAY_BORROW_ACCRUE_INTEREST_FAILED |
66 | REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED |
67 | REPAY_BORROW_COMPTROLLER_REJECTION |
68 | REPAY_BORROW_FRESHNESS_CHECK |
69 | REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED |
70 | REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED |
71 | REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE |
72 | SET_COLLATERAL_FACTOR_OWNER_CHECK |
73 | SET_COLLATERAL_FACTOR_VALIDATION |
74 | SET_COMPTROLLER_OWNER_CHECK |
75 | SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED |
76 | SET_INTEREST_RATE_MODEL_FRESH_CHECK |
77 | SET_INTEREST_RATE_MODEL_OWNER_CHECK |
78 | SET_MAX_ASSETS_OWNER_CHECK |
79 | SET_ORACLE_MARKET_NOT_LISTED |
80 | SET_ORACLE_MARKET_NOT_LISTED |
81 | SET_PENDING_ADMIN_OWNER_CHECK |
82 | SET_ADMIN_FEE_ACCRUE_INTEREST_FAILED |
83 | SET_ADMIN_FEE_ADMIN_CHECK |
84 | SET_ADMIN_FEE_FRESH_CHECK |
85 | SET_ADMIN_FEE_BOUNDS_CHECK |
86 | SET_PROTOCOL_FEE_ACCRUE_INTEREST_FAILED |
87 | SET_PROTOCOL_FEE_FRESH_CHECK |
88 | SET_PROTOCOL_FEE_BOUNDS_CHECK |
89 | SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED |
90 | SET_RESERVE_FACTOR_ADMIN_CHECK |
91 | SET_RESERVE_FACTOR_FRESH_CHECK |
92 | SET_RESERVE_FACTOR_BOUNDS_CHECK |
93 | TRANSFER_COMPTROLLER_REJECTION |
94 | TRANSFER_NOT_ALLOWED |
95 | TRANSFER_NOT_ENOUGH |
96 | TRANSFER_TOO_MUCH |
97 | ADD_RESERVES_ACCRUE_INTEREST_FAILED |
98 | ADD_RESERVES_FRESH_CHECK |
99 | ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE |
Last updated