Ensuring the security and optimisation of a live protocol requires a multi faceted approach. In addition to a macro-level architecture and a robust governance decentralization plan, the micro-level architecture, code formatting, documentation, testing procedures and auditing play vital roles in the process.
Open reward pool for discovering and reporting vulnerabilities in the mStable protocol.
Initial audit performed by Bramah Systems.
mStable contracts are tested with both integration results and invariants in mind.
Tests are written in Typescript, using Typechain to generate typings for all contracts. Tests are executed using
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.
Running tests on a fork of mainnet allows us to validate that all connections act as assumed before performing a real mainnet deployment.
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.
One of the core principles of our architecture design is the separation of concerns. Many critical modules are immutable, and those modules which are upgradable have an option to be permanently locked into place, subject to a governance process. Contracts that implement Open-Zeppelin's Upgradable Proxies are governed and upgraded by a DelayedProxyAdmin, via mStable governance.
We use common standardised contracts, for example
MiniMe or Open-Zeppelin where possible and learn from previous smart contract systems by applying security measures like
Solc v 0.5.x.
The Nexus supports the system by providing read access of all modules, as a sort of system registry. This centralises the burden for updates and reduces the chance of a mishap.
See governance roadmap for more info.
Deterministic and battle tested deployment scripts play a vital role in ensuring that live contracts are instantiated with and attributed to the correct addresses.
We believe that code should be easily understandable and so write with the average reader in mind. Our contracts are formatted for optimal comprehension and supplemented with comprehensive comments.
Using descriptive and verbose variable and function names
Using error messages for every revert, require or assert statement
Avoid function and variables shadowing
Remove unused functions, variables and parameters
Always declare function & variable visibility
Capitalising on the growing ecosystem of tooling available for writing contracts on Ethereum, we use such tools as: