Thinking About Smart Contract Security
The Perils of Smart Contract Security: A Layered Approach to Mitigating Risks
The world of smart contracts has seen its fair share of high-profile breaches and losses, with the DAO hack being one of the most infamous examples. In the aftermath of these incidents, the community has come together to crowdsourcing a list of major bugs and vulnerabilities in smart contracts on Ethereum. This list serves as a stark reminder of the importance of prioritizing security in the development of smart contracts.
The Complexity of Value and Fragility of Value
The philosophy behind smart contract security can be understood through the concepts of "complexity of value" and "fragility of value." These ideas, formalized by the friendly AI research community, highlight the intricate nature of human values and the potential for unintended consequences. A super-intelligent AI, for instance, would search through every corner case to maximize its objective, leading to outcomes that may not align with human values.
In the context of smart contracts, this means that even with the best intentions, the implementation may not accurately reflect the desired outcome. The utility of this concept is crucial in AI research, as it underscores the need for careful consideration of the potential consequences of an AI's actions.
Mitigating Risks through Defense-in-Depth
Given the complexity of smart contract security, a layered approach is necessary to mitigate risks. One category of solutions involves taking common patterns and hardcoding them, such as making owner a keyword that can only be initialized to equal msg.sender in the constructor. Another category involves creating standardized mid-level components, like discouraging every casino from creating its own random number generator.
A more important category of solutions involves mitigating the specific and unintuitive quirks of the EVM execution environment. These include the gas limit, re-entrancy, and the call stack limit. The call stack limit, for instance, can be mitigated through EIPs that substitute its purpose with a change to gas mechanics.
Compiler-Driven Solutions
Compilers can play a crucial role in mitigating risks by throwing warnings if a contract does not provably consume less than 2300 gas if called with no data or if a function does not provably terminate within a safe amount of gas. Variable names can be colored or a heuristic warning can be given if two variable names are too close to each other.
Coding Patterns and Justification
Certain coding patterns are more dangerous than others, and while they should not be banned, they should be clearly highlighted, requiring developers to justify their use of them. A particularly involved example is the idea of a "general purpose decentralized exchange" contract where anyone can place orders offering to trade a given amount of asset A for a given amount of asset B.
Defense in Depth: Expiry Dates and Waiting Periods
To prevent losses (but not thefts), contracts that are not intended to be permanent can have an expiry date, after which the owner can take arbitrary actions on behalf of the contract. Trusted multisig "owners" may emerge to mitigate the risk of dishonest owners. Thefts can be mitigated by adding waiting periods, as seen in the MakerDAO's proposed feature of creating a delay before any governance change becomes active.
Formal Verification
Formal verification can be layered on top of the development process to prove termination, specific properties, or fit into a restricted subset of Solidity that makes re-entrancy, gas issues, and call stack issues impossible. This can provide an additional layer of security and confidence in the contract's behavior.
Conclusion
The world of smart contract security is complex and multifaceted, requiring a layered approach to mitigate risks. By understanding the concepts of "complexity of value" and "fragility of value," developers can better appreciate the potential consequences of their actions. Compiler-driven solutions, coding patterns, and justification, defense in depth, and formal verification are all crucial components of a robust security strategy.
As the community continues to evolve and improve, it is essential to prioritize security and provide practical insights and implications for real-world applications. By working together, we can create a safer and more secure world for smart contracts.
Action Steps
- Take on the project of making a superior development environment that includes some of the features mentioned above.
- Standardize as many components as possible to reduce the risk of errors and make it easier for developers to create secure contracts.
- Experiment with different smart contract programming languages and formal verification and symbolic execution tools to improve the security of contracts.
- Discuss coding standards, EIPs, changes to Solidity, etc. that can mitigate the risk of accidental or deliberate errors.
- If you are developing a multimillion-dollar smart contract application, consider reaching out to security researchers and work with them on using your project as a test case for various verification tools.
Source: https://blog.ethereum.org/en/2016/06/19/thinking-smart-contract-security




