Quality Solidity Code with OpenZeppelin and Friends
Given the fact that all of Ethereum’s computations need to be reproduced on all the nodes in the network, Ethereum’s computing is inherently costly and inefficient. (In fact, Ethereum’s developer docs on GitHub state that we shouldn’t expect more computational power from Ethereum than we do from a 1999 phone.)
So, security on the Ethereum Virtual Machine — meaning, the security of smart contracts deployed on Ethereum blockchain — is of paramount importance. All the errors on it cost real money — whether it’s errors thrown by badly-written contracts, or hackers exploiting loopholes in contracts, like in the well-known DAO hack, which caused a community split and sprang the Ethereum Classic blockchain into existence.
Turing Completeness — and a whole range of other design decisions that have made Ethereum a lot more capable and sophisticated — have come at a cost. Ethereum’s richness has made it more vulnerable to errors and hackers.
To add to the problem, smart contracts deployed on Ethereum cannot be modified. The blockchain is an immutable data structure.
This and this article go into more depth regarding security of smart contracts, and the ecosystem of tools and libraries to help us to make our smart contracts secure.
Let’s look at some amazing upgrades to our toolset we can use today to utilize the best practices the Solidity environment can offer.
One of the coolest tools in the toolset of an Ethereum developer is OpenZeppelin’s library. It’s a framework consisting of many Solidity code patterns and smart contract modules, written in a secure way. The authors are Solidity auditors and consultants themselves, and you can read about a third-party audit of these modules here. Manuel Araoz from Zeppelin Solutions, an Argentinian company behind OpenZeppelin, outlines the main Solidity security patterns and considerations.
OpenZeppelin is establishing itself as an industry standard for reusable and secure open source (MIT) base of Solidity code, which can easily be deployed using Truffle. It consists of smart contracts which, once installed via npm, can be easily imported and used in our contracts.
The Truffle Framework published a tutorial for using OpenZeppelin with Truffle and Ganache.
These contracts are meant to be imported and their methods are meant to be overridden, as needed. The files shouldn’t be modified in themselves.
OpenZeppelin’s library contains a set of contracts for publishing tokens on the Ethereum platform — for ERC20 tokens, including a BasicToken contract, BurnableToken, CappedToken. This is a mintable token with a fixed cap, MintableToken, PausableToken, with which token transfers can be paused. Then there is TokenVesting, a contract that can release its token balance gradually like a typical vesting scheme, with a cliff and vesting period, and more.
There’s also set of contracts for ERC721 tokens — or non-fungible, unique tokens of the CryptoKitties type.
ERC827 tokens contracts, standard for sending data along with transacted tokens, are also included.
There’s also a set of crowdsale contracts — contracts for conducting Initial Coin Offerings. These can log purchases, deliver/emit tokens to buyers, forward ETH funds. There are functions for validating and processing token purchases.
The FinalizableCrowdsale contract provides for execting some logic post-sale. PostDeliveryCrowdsale allows freezing of withdrawals until the end of the crowdsale. RefundableCrowdsale is an extension of the Crowdsale contract that adds a funding goal, and the possibility of users getting a refund if the goal is not met.
Destructible contracts can be destroyed by the owner, and have all the funds sent to the owner. There are also contracts for implementing pausability to child contracts.
OpenZeppelin provides many helpers and utilities for conducting ICOs — like a contract which enables recovery of ERC20 tokens mistakenly sent to an ICO address instead of ETH. A heritable contract provides for transferring of ownership to another owner under certain circumstances. The Ownable contract has an owner address, and provides basic authorization/permissions and transferring of ownership.
The RBAC contract provides utilities for role-based access control. We can assign different roles to different addresses, with an unlimited number of roles.
Zeppelin also provides a sample crowdsale starter Truffle project which hasn’t been audited yet, so it’s best used as an introduction to using OpenZeppelin. It makes it easy to start off with a crowdsale and a token fast.
ZeppelinOs is an open-source, decentralized platform of tools and services on top of the EVM to develop and manage smart contract applications securely.
In effect, this is a kind of middleware layer on top of EVM, which would be a step further than the current OpenZeppelin framework. What Zeppelin Solutions promise here is enabling developers to opt-in to mutability for their deployed code through upgradeability patterns. Those who write smart contracts for the EVM know that one of the concerns/restrictions is immutability of deployed contracts: once on the blockchain, contracts cannot be changed. That is one of the things that make the promise of ZeppelinOs interesting.
Up until now, in order to “update” a contract one would have to deploy two contracts — one as a proxy with the interface, and the other as the implementation. The proxy’s functions would be called, forwarding requests to the implementation. Then, if a change was needed, the implementation is switched out in the proxy (another implementation is retargeted, and optionally the original one is killed off with a
suicide function) and the new implementation seamlessly activates.
We are waiting to see the future adoption of ZeppelinOs by the community. Zeppelin Solutions are already namedropping some non-trivial players like OpenBazaar, district0x, storj.io as some who are using ZeppelinOs.
Some of the officially supported boxes are:
Drizzle: a set of React/Redux-based front-end libraries that make creation of dapp front ends easier.
React box: a bare-bones app to start interacting with smart contracts from a React, front-end application.
React Auth box: brings a set of components needed for authentication powered by smart contracts.
React-Uport: this authentication box connects the front end with the UPort blockchain authentication system.
Then there’s the webpack project boilerplate box we mentioned before.
Community-created boxes also bring along boilerplates for integration of contracts with mobile apps / Status IM, or provide Angular and Vue.js boilerplates, etc.
These boxes are integrated with Truffle, so we get started with them by running commands like
truffle unbox react — which will download the React box and install its dependencies locally.
TokenMarket is another company that has published a repository of Solidity contracts and tools for managing token sales / ICOs. It’s a limited company incorporated in Gibraltar that does ICO consulting. It was awarded “The Best ICO Advisor” at Cryptocurrency World Expo Berlin Summit 2018.
Tokenmarket’s ICO repository on GitHub says that one of its design goals/principles is to use or build upon the existing OpenZeppelin contracts, calling them a gold standard of Solidity contracts. So from this, a lot of the TokenMarket’s ICO codebase is based on OpenZeppelin’s code base, and then it builds further on it (by inheriting from it in OOP fashion).
TokenMarket regularly (tries to) keep up to date with its upstream code base, OpenZeppelin. It adds more to it, though, such as the following:
- AMLtoken contract: this gives the Owner the chance to reclaim tokens from a participant before the token is released after a participant has failed a prolonged AML process.
- Gnosis Wallet: basically a multi-sig wallet, which requires consensus of multiple parties for certain transactions.
- a Centrally Issued Token contract.
- KYCCrowdsale: a contract that only lets in investors who are not anonymous.
- Relaunched Crowdsale contract: this restores a previous crowdsale and allows for changing of some parameters.
- Milestone Pricing: this contract provides for milestone-based pricing, and pre-ICO-deals.
Although there’s a lot of the code in the repositories we talk about here, the EVM is Turing complete so all these various contracts do not, even remotely, exhaust its full capabilities. Provided that the system — Ethereum — survives and continues to be competitive, with enough people on the network, we can look forward to much bigger versatility in what these blockchain contracts attempt to solve.
Consensys Ventures is a Swiss ventures/investing company that’s profiling itself as an angel/seed investing company in the decentralized space — and this particularly means the Ethereum space. Beyond other resources they offer their protege companies, they have put together a nice little compendium of best practices for Ethereum smart contracts. Although narrowly speaking this isn’t code, it still contains quite a number of good and bad examples of Solidity code.
It’s mostly about best security practices of Solidity smart contracts.
The complete list of topics goes a bit beyond the scope of this article, because the resource is comprehensive and is worth reading even to remind a smart contract developer of all they need to keep in mind when writing software for the EVM. And this especially goes if one writes programs from scratch (not relying on already made and vetted code like OpenZeppelin’s).
Some of the articles deal with external calls, avoiding state changes after external calls, handling errors in external calls, favoring pull over push for external calls, staying aware of the tradeoffs between abstract contracts and interfaces, not assuming that contracts are created with zero balance, differentiating functions and events, multiple inheritance caution, warnings about timestamp dependence and gameability of such constructs — for example, with blocks — and many other such tips with a lot of code examples.
Then there are token-specific warnings, warnings related to token standards, software engineering techniques, security tools — for static analysis, testing, linters, etc.
They also list known attacks, from those that include calling on external code and contracts, functions that could be called repeatedly in such cases, reentrancy problems, cross-function race conditions, Here they analyze a whole range of problems, some of which manifested in the DAO hack.
They further mention transaction-ordering dependence, timestamp dependence, integer overflow and underflow, different possibilities/points of DoS attacks, like DoS with block gas limit, then forcibly sending Ether to a contract; and they also analyze historical and deprecated attacks. Definitely give their docs a read.
In this introduction to the ecosystem, we went through some of the available resources for writing good, production ready smart contracts on the Ethereum Virtual Machine. This includes both reusing already audited, vetted code (OpenZeppelin claim there is over $4 billion worth of cryptocurrency running on their contracts) to practical resources to learn writing ones own secure, production-ready software.
We’re pretty certain the list isn’t complete yet. Did we miss anything worth mentioning? Let us know!