Smart Contract Architecture And Testing Best Practices
Writing secure code for smart contracts starts with the mindset that a developer needs to do more than just write a piece of self-executing code. They need to program with an added awareness of all the things that could potentially go wrong with the code, later on down the road. Simply knowing how to write a smart contract isn’t enough. A developer should be aware of best practices to follow for ensuring adequate security of their code.
Secure code is important because smart contracts run very differently from most programs. Smart contracts don’t traditionally offer simple upgrade paths, especially when it comes to critical components such as code that controls the value in a token contract. Once a smart contract is up and running, changing it becomes complicated and nearly unfeasible.
Unsecure or buggy smart contracts can lead to distrust in the blockchain ecosystem. Thankfully, several interested parties have helped to compile smart contract writing guidelines. Smart contract code isn’t standardized, but these resources are convenient and beneficial for developers: Consensys’ smart contracts best practices, Solidity’s Security Considerations, Zeppelin’s open framework, and Zeppelin’s recently released v1.0.1 open framework consisting of a library for writing secure smart contracts on Ethereum.
Even after a public code audit by Zeppelin, ether.camp’s HackerGold Token (HKG) was found to have a bug serious enough to warrant a reissue of the token. The code audit recommended changes that would have prevented the bug in the HKG token contract. Clearly there is a difference between due diligence and actually correcting flaws in the code.
This shows how integral quality code architecture is in the Ethereum ecosystem. In a blog post on Medium by ICONOMI’s Daniel Zakrisson, he outlines some best practices for smart contract design and testing. He’s hoping to draw more attention to the issue of buggy code and hopefully magnify discussions surrounding industry best practices.
One of the more significant areas Zakrisson covered is verification and validation testing. Verification makes sure that code meets the design specifications and requirements it’s created to do. This can be achieved in different ways, and the testing can be mostly automated. Further code reviews and security audits are crucial in the later stages of verification. After verification testing comes validation testing. Validation is more about putting a product through its paces and making sure it will function how it’s supposed to once it’s deployed. Both verification and validation testing occur during the alpha and beta phases of a project.
Zakrisson also compiled a quick check-list for smart contract developers, regarding architecture and minimum testing standards. If programmers are thinking about writing a smart contract or are actively working on one, this guideline would be of use:
- Use and reuse audited open source code as much as possible (such as ERC: 20)
- Separate token issuance and token control from all other code into separate contracts
- Implement a safety stop (kill switch) function at the top of the code in case something happens
- Implement a contract transfer function whenever possible
- Have a testing plan for both verification and validation testing
- Do code reviews
- Do verification testing with automated unit, functional and integration tests
- Do external security audits
- Do validation testing by extensively testing on the testnet and then
- After testnet testing, do more testing with limited risk in proof-of-concept or alpha stage on the main net
This is merely a guideline to add to the growing list of industry standard precautions. The best advice any developer can follow is to do their homework and make sure they’ve exhausted every resource available to them. When the whole ecosystem depends on the reliability of smart contracts, a contract’s code security is paramount.