This repo contains all contracts and tests relevant to the core mStable protocol. mStable is built to make tokenized assets easy, safe and profitable.
mStable Assets (mAssets) are tokens that allows minting and redemption at a 1:1 ratio for underlying Basket Assets (bAssets) of the same peg (i.e. USD, BTC, Gold). The first products are mUSD
and the mUSD Savings Contract
; mAssets can be deposited to earn interest through their respective Savings Contract, just like you would with a savings account, with each mAsset balance accruing interest earned across the DeFi ecosystem. bAssets
within an mAsset
can also be swapped 1:1 (provided they remain within their forge validator limits), with a small swapFee paid to Savers.
Core mAsset contracts utilise OpenZeppelin's InitializableAdminUpgradeabilityProxy to facilitate future upgrades, bug fixes or feature additions. The upgrades are governed by mStable Governors (with current governor address stored in the Nexus - the system kernel) and executed via the DelayedProxyAdmin. Both changes to the governor
, and contract upgrades have a one week delay built in to execution. This allows mStable users a one week opt out window if they do not agree with the given update.
mStable rewards those who contribute to its utility and growth. Whether that’s by swapping stablecoins for mStable assets in release 1.0, or post release 1.1 with staking mStable's system token MTA to participate in the system’s governance, or contributing to mStable liquidity pools on Uniswap.
For security concerns, please visit https://docs.mstable.org/protocol/ or email [email protected].
🏠 https://mstable.org
📀 https://app.mstable.org
📄 https://docs.mstable.org
master
contains complete, tested and audited contract code, generally onmainnet
beta
is for the pre-release code, generally onropsten
$ yarn
Deployment scripts are located in migrations/src
. To run, start ganache
or ganache-cli
and run the migration script.
NB: You should locally use the latest version of ganache-cli
, as contracts rely on recent opcodes
$ ganache-cli -p 7545
$ yarn migrate
Tests are written in Typescript, using Typechain to generate typings for all contracts. Tests are executed using truffle
and ganache-cli
.
$ ganache-cli -p 7545 -l 50000000 --allowUnlimitedContractSize
$ yarn test
mStable-contracts test suite is built to support execution on a mainnet fork of ganache. This allows tests to be ran using all mainnet dependencies (bAssets, lending protocols). To do this, certain mainnet accounts need to be unlocked to allows tx to be sent from that origin.
NB: The following commands assume you have a full Ethereum node running and exposed on local port 1234
$ ganache-cli -f http://localhost:1234 -p 7545 -l 100000000 --allowUnlimitedContractSize --unlock "0x6cC5F688a315f3dC28A7781717a9A798a59fDA7b" --unlock "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE" --unlock "0x3dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3"
$ yarn test-prep
$ truffle test ./test/xxx.spec.tx --network fork
Key folders:
/contracts/z_mocks
: All mocks used throughout the test suite/security
: Scripts used to run static analysis tools like Slither and Securify/test
: Unit tests in folders corresponding to contracts/xx/test-utils
: Core util files used throughout the test framework/machines
: Mock contract machines for creating configurable instances of the contracts
/types
: TS Types used throughout the suite/generated
: Output from Typechain; strongly-typed, Truffle-flavoured contract interfaces
Solidity-coverage is used to run coverage analysis on test suite.
This produces reports that are visible in the /coverage
folder, and navigatable/uploadable. Ultimately they are used as a reference that there is some sort of adequate cover, although they will not be a source of truth for a robust test framework. Reports publically available on coveralls.
NB: solidity-coverage runs with solc optimizer=false
(see discussion)
script [scriptName] [args]
> Runs custom Truffle scripts
Example usage:
- Mint 100 MUSD:
yarn script mint 100
- Redeem 100 of the MUSD basset at index 0 (USDT):
yarn redeem-basset 0 100
- Deposit 100 mUSD into savings:
yarn deposit-savings 100
- Withdraw 100 mUSD from savings:
yarn withdraw-savings 100
- Travel through time (forwards only, sorry):
yarn script time-travel 1 year
Codebase rules are enforced through a passing CI (visible in .circleci/config.yml
). These rules are:
- Linting of both the contracts (through Solium) and TS files (ESLint)
- Passing test suite
- Maintaining high unit testing coverage
- Solidity imports deconstructed as
import { xxx } from "../xxx.sol"
- Solidity commented as per NatSpec format
- Internal function ordering from high > low order