Dr. ir. Oskar van Deventer
- Scientific Coordinator
Although the term smart contract is relatively old (first coined by Nick Szabo in 1996), smart contracts have really captured people's imagination since the introduction of the Ethereum platform, fueling the blockchain hype of a few years ago. In this blockchain context, a smart contract is a computer program that runs on a blockchain, checked by thousands of computers, and can in many cases never be changed once it is created.
This combination of verifiability and immutability(*) has given the smart contract its name, and indeed, it inspires a high level of trust. However, especially the latter property of immutability is a double-edged sword: it is comforting to know that you can trust the code you rely on to never change, but simultaneously, if you ever discover that a smart contract you rely on contains a critical bug, the ensuing migration to a bug-free contract may be expensive and tedious.
Many solutions to this problem have been conceived. An example is the proxy contract: a contract that forwards all its users to a second, 'real' smart contract, but can be configured to change the forwarding address. When the time comes to update the smart contract, its owners simply upload the new version, change the forwarding address in the proxy smart contract, and forget about the old version.
Though this arguably solves the update problem, it creates a new problem: who is allowed to replace your smart contract by a new one? If you are the only user, the answer is simple: you. However, as the name "smart contract" implies, smart contracts are often used by multiple parties to cooperate. In that case, the answer may be more complex: is there still an all-powerful owner? Do you trust all other parties to unilaterally upgrade the smart contract? Will you call a vote? Even if the answer is currently straightforward ("I trust them all"), you might later wish to allow more parties to use the contract that you do not completely trust.
In this post, we explore the concept of governance bootstrapping: starting out with a very simple set of rules for upgrading a smart contract, and evolve it to a more complex set of rules using one or more policy updates.
All of this is discussed in the context of the Ethereum blockchain, but as the principles involved are general, we expect much of the discussion to apply to other distributed ledger technologies as well.
(*) We use the term "immutability" loosely here. To be precise, the data-structures used in a typical blockchain (hash-chains and hash-trees) allow for easy detection and rejection of unwanted changes. However, if the majority of a participants of a blockchain agree, changes are possible within the shared "truth".
Suppose you have a smart contract that is rather important to you. For example, you and your friend have started a company, and your initial capital is kept in a smart contract. This "wallet" is instructed to spend your funds according to, say, a multi-signature scheme that forces you and your friend to agree to any expenditure.
However, you wish to account for the possibility that your wallet smart contract contains a bug. This is not unheard of: nobody is infallible, and since a bug might end up costing you a lot of money, it would be nice if you can patch bugs. But of course, you need to make arrangements to make sure that this update can only be done by someone you trust, like you.
To this end, you introduce a new "governor" smart contract. Only the governor is allowed to update the wallet contract, and before it does so, it can perform any number of checks you want it to. For now, it just checks whether the person performing the update is you.
Unfortunately (but predictably), your friend does not like this, and would like to have the same powers as you, since it's her company, too. This forces us to consider the concept of updating the governor -- which might feel slightly paradoxical, since the governor is supposed to control who updates your wallet. Have we ended up right where we started?
Fortunately, we haven't: there is still the governor. Let's endow the governor contract with an additional power: the power to update itself. It still checks if a request for an update conforms to the rules, but now you have the additional ability to change the rules.
As a first order of business, you change the governor to a new one: this new governor allows both you and your friend to perform updates.
However, this solution is still not optimal: what if your friend suddenly decides to perform an update that allows her to spend the money without your approval? Since your friend has the same concern about you, you decide to apply the concept behind the wallet software to the governor as well: you pass an update that requires both of you to approve any updates to the wallet software or the governor.
All is well, and your company grows. At some point, you hire an accountant, who gets unilateral power to spend your money; you and your friend approve a wallet software update that changes the rules accordingly.
However, after several years, your company's growth calls for separate board of directors.
Reluctant to part with your powers entirely, but still cognizant of the needs of a large organisation, your friend and you update the governor once again to enforce a new policy: updates can be approved by either the two of you, or the entirety of the board of directors and at least one of its founders. And then, with support of the entirety of the board, you could, if you wanted to, remove your partner from the company and from the governor contract.
In the above example, we have demonstrated how an evolving governance policy might be recorded in a smart contract, making it future-proof from the get-go. The example demonstrates how you might record update policies in a governance, both for the main smart contract and for the governance contract. In addition, we suggested a possible upgrade path from the simple "owner has all power" policy to a more complex weighted voting system.
Accompanying this post is a GitHub repository in which we have implemented this example, as well as several other use-cases. Please try it yourself and let us know whether it works for your use-cases.
Erik Weitenberg and Maarten Everts, TNO