Security of blockchain-based smart contracts I

Recently, blockchain technology has been advocated as a game changer for many industries. Distributed ledger technology that has emerged out of Bitcoin has promising applications beyond digital currencies.

One of the most promising use cases of blockchain technology is the development of smart contracts.

Smart contracts are self-executing contracts, in which the terms are specified in code. Essentially, this means encoding legal contracts in computer code, which executes them automatically.

Whilst the concept has been around for a while, at least since Nick Szabo’s wrote up the concept in 1996, it was not until the advent of the Turing-complete Ethereum blockchain that smart contract use became common.

Contracts on the Ethereum blockchain exist at contract addresses and can be invoked by transaction calls.

Executing contracts written in code and stored on an immutable public blockchain creates certain risks and issues, which we will discuss in a general way in this post. In an upcoming second part, we will look at more specific examples of smart contract security vulnerabilities.

Smart contract

Code is Law?

A literal interpretation of the smart contract idea leads to the “Code is Law” paradigm, which means that smart contracts are binding and are interpreted as if they were legal documents. Any software engineer aware of the impossibility to create completely error free code will get sweaty hands at the thought of a computer program being legally binding. There are a number of obvious problems:

  1. Code contains bugs.It is extremely difficult to write bug-free code and even if all possible precautions are taken, there will always be unexpected execution paths or possible vulnerabilities in reasonably complex software.
  2. Legal contracts are subject to interpretation and arbitration.It is very difficult to create air-tight contracts. In any large contract, typos may slip in and some clauses need to be interpreted and arbitrated. That is what courts do in case of dispute. If in a legal contract the sale price is specified as $100 on 39 out of 40 pages and on one page an additional zero sneaks in, a court would rule in “the spirit of the contract”. A computer just executes the clause as written. The immutability of the blockchain adds to this problem, as contracts cannot be amended easily.
  3. Software engineers are no legal experts and vice versa. A different skill set is required to draft a good contract, not necessarily compatible with writing a good computer program.

Two Examples of High-profile Smart Contract Exploits

The DAO Attack

A lot has already been said about this case, which we will not reiterate here. A good overview of the attack and the aftermath can be found here.

In summary, in June 2016, an attacker managed to divert a large amount of crowdsourced funds (3.5M ETH, approximately 15% of total ETH at the time) into his own child contract, in which the funds were locked for 28 days, leading to a race against time to find a solution.

The important point to note in this case, is that the contract was attacked by making it behave in an unexpected way. In this particular case re-entrancy vulnerabilities were exploited. We will look at re-entrancy in a follow-up of this post.

The Parity Hack

This was in fact the second hack of the multi-signature wallet contract provided by Parity. The multisig wallet contract, used by many start-ups, had most of its logic implemented in a library contract. Each wallet consisted in a light-weight client contract connecting to this single point of failure.

Parity multisig architecture

There was a crucial bug in the library contract, which consisted in an initialisation function being able to be called exactly once.

In November 2017, someone did initialise the contract and by doing so became the owner of the contract. This then allowed him to invoke owner only functions, a privilege he used to call the following function:

// kills the contract sending everything to `_to`.
function kill(address _to) onlymanyowners(sha3(msg.data)) external {
    suicide(_to);
}

This is the equivalent of a self-destruct button, which renders the contract useless. Calling this function caused all the funds of the client contracts to be frozen, probably forever.

At the time of writing, it is still unclear whether the hack constituted a deliberate attack or was accidental, with the perpetrator claiming accidental actions.

Both attacks show, that even relatively simple contracts, written by the biggest players in the blockchain ecosystem, are prone to basic bugs with serious consequences.

What can be done?

Recent history has shown that executing smart contracts on public blockchains is dangerous and nowhere safe enough to substitute more traditional legal systems with their precise language, room for interpretation and arbitration.

This does not mean we should abandon smart contracts. They are extremely useful tools and open up interesting applications. However, we should not consider them substitutes for legally binding contracts, but complementary tools for automation.

Furthermore, we should take the following precautions to avoid vulnerabilities:

  • Use open source and community accepted de facto standards for library contracts, such as Open Zeppelin contracts.
  • Use recommended patterns and best practise guidelines, such as those provided by Consensys.
  • Consider contracting an audit of your smart contracts by a reputable provider.

In an upcoming post in this series we will look at some known vulnerabilities, including code examples, and how to prevent them.