In 2017 the news about a successful hacker attack on the Parity wallet emerged. The Parity wallet was a Smart Contract wallet that could be used for managing cryptocurrency funds. The attacker took over the control of the Smart Contract and transferred all of the currency deposited in it to his account. The damage has been estimated at USD 30M and the hack prompted waves of negative responses from the public.
Why was this possible?
The developers of the Smart Contract code were using a proxy that was delegating calls to the current main implementation. This kind of proxy functionality is a common way of implementing upgradeability for contracts. Any call to the proxy contract itself that does not match existing function's signatures is being forwarded for execution within the proxy context via the Solidity's delegatecall instruction.
However, the developers of the Smart Contract made a mistake - they forgot about implementing access control for one of the critical methods at the implementation level. Usually, this is being done with appropriate function modifiers being added to the function.
Since this method lacked the modifier, it could be called by any account in the world (that’s one of the features of public blockchains), at one point it’s been exploited.
The lesson to take away from these developments is the following: The concepts of the blockchain, decentralization and Smart Contracts have brought us exciting new possibilities for creating financial services. But along these possibilities, as is usually the case, came new risks. On one hand we have trustless (i.e., requiring no trusted party that could centralize the system) applications that lower the entering barrier for the providers of financial services. On the other hand we must understand that the risk exposure of this kind of service is huge. Everything we deploy to the blockchain is essentially public.
Exposure, when combined with high-value assets and transactions, results in high risks (or, from the perspective of a hacker - opportunities). There are ways to manage these risks and increase the security of our business. They include Risk Management and Treatment, deploying appropriate security controls (for monitoring, vulnerability management, controlling access), auditing the code before deployment to blockchain’s mainnet.
But in this blog entry I wanted to introduce one specific way to reduce the Smart Contract-related risks significantly and at little to no cost. If you would ask me to choose just one solution for risk mitigation, I would tell you to build your software relying on a verified code pattern library such as the OpenZeppelin framework.
OpenZeppelin framework is a project that has been created as a response to many other incidents that happened in the web3 world over the years that are similar to the Parity hack. The authors of the framework recognized the necessity to compile available security best practices and produce some verified code templates for use by web3 developers.
OpenZeppelin framework is a library of secure Smart Contract templates that your developers can use for building your product. It contains templates for most popular business models such as:
It also provides important security controls that you can re-use in your project:
One noteworthy aspect of these templates is that they are being built and maintained by a large (400 contributors at the time of writing), vibrant community with the Smart Contract security as a main focus. This means that an extensive body of experience and knowledge about risks, weaknesses, vulnerabilities, attack techniques is distilled down to these templates.
As an example, the framework provides an easy-to-use Access Control role-based security model (RBAC). When you are creating your product and you want to properly authenticate and authorize specific wallets to access critical functions, all you need to do is to inherit this functionality in your code, define roles and assign wallets of your choice to specific roles.
There are some rules, however, when it comes to using this framework. One of the most important ones is - you don’t modify the framework code itself, unless you know what you're doing. There were many considerations that went into crystalizing the final implementation of individual modules of the framework. If you decide to interfere with its internal mechanics, you risk compromising one or more of those, without even knowing it.
One more thing to keep in mind. Folks behind the OpenZeppelin project are still only humans and sometimes they make mistakes. It would be great if companies could afford to have on board a specialist skilled enough to catch any bugs that slip through but it's obviously impossible. Still, I believe that for a small company that has to deal with small security budget, choosing OpenZeppelin code patterns is a way to go as low likelihood of bugs being present beats the high likelihood of bugs being introduced while writing own contracts from scratch.
To put it all together, using the OpenZeppelin framework in your development efforts is one of the best cost-effective measures to mitigate the risks related to the Smart Contract exposure. The framework provides easy-to-use templates for a variety of use cases. In subsequent blog entries I will try to give you specific examples of the usage.
Here I would also like to encourage you to read more about the threat models that apply to various technological layers in the blockchain universe starting with this thread. In this series I am working on identifying threats for specific perspectives such as the end user perspective or the service provider perspective.