Smart Contracts Must Be Highly Stable

A Pattern for Upgradeable Software on the Blockchain

Stephen Fiser
Jan 17 · 5 min read

By Stephen Fiser

Every software system has components that are stable and others that are volatile. In fact, this is a desirable attribute. If every component was completely stable, the system would likely be too rigid, and if everything was volatile, the system would fall apart.

As a slightly oversimplified example, in a conventional web or mobile application, the “view” code that makes up the actual screens changes all of the time. On the other hand, there are likely key business rules — like how payroll is calculated or how accounting is performed— that will change much less frequently.

A key engineering principle is to always have less stable components depend on more stable components.

If you think about it, this is highly intuitive. It’s exactly how things work in most real world cases — we place less stable objects on top of more stable objects. For example, you place your morning cup of coffee on the table, not the other way around. The coffee is much easier to move, and it is more likely to be moved than the table.

Being able to make volatile components depend on stable components requires that you can recognize dependencies. One clear sign of a dependency is a piece of code knowing the name of another piece of code. For example:

In this (silly) example, the Person class has a dependency on the Dog class. If someone decided to delete the file that contains the code for Dog, the Person class would break. We might also realize that not all people like dogs (and thus the type of friend required is volatile), and do something like this:

We can expand this idea a bit to deal with system components instead of individual bits of code. The vast majority of systems that are actually useful in today’s world exhibit more complex architectures than just a few files strung together. Web and mobile applications typically run on and interact with multiple servers, APIs, services, etc.

It’s not as straight forward, but we can identify dependencies between larger components of systems by evaluating whether or not one component knows about another.

For example, if I build an application that makes use of the Twitter API, Twitter knows nothing about my application, and I can change anything I want on my application without breaking Twitter’s code. My application clearly has a dependency on Twitter, but not the other way around.

Further, if Twitter makes changes to their API carelessly, there is a high probability that it will break my system. This is why so much thought and energy has gone toward the design and upgrade process of APIs over the past couple of decades. If breaking changes are going to be released, a new version number is made such that users of the previous version can continue uninterrupted until a predefined deprecation date.

With regard to dependencies, blockchains don’t have the ability to reach outside of the blockchain itself and discover information. This is because it would be impossible to reach consensus.

All of the nodes in a blockchain have to come to an agreement. Suppose that we write a smart contract that says:

The problem is that when one node goes and checks the weather, it might see a temperature of 90, and another might see one of 89.5 — thus leading to conflicting answers to the question “is it hot”? This is why the concept of an “oracle” was developed, but we’ll deal with that on another day.

What this essentially means is that a system of smart contracts can’t know about any other part of your system by default — all of your web or mobile related code will depend on your smart contracts and not the other way around. From our earlier discussion, this implies that your smart contracts need to be stable, and the rest of your system needs to change around it.

Smart contracts have a weird quirk from a software development perspective; you can’t change the code once they are deployed. You would think this fact alone means that they are stable, but it doesn’t. Often, if a smart contract is found to have a bug or vulnerability, a new contract is released and all users of the contract must update to the new one immediately. This is similar to Twitter rolling out a massive change to their current API. All of the users would have to make the upgrade immediately or be at risk.

As previously discussed, we can devise upgradeable smart contract systems using conventional object oriented programming techniques. This allows us to create endpoints that are actually and intentionally stable, all while maintaining the ability to make improvements to the core logic and behavior of the system.

In this diagram, all of the items in the blue box are protected and can only be called by the Proxy contracts. These are essentially the API endpoints of the system. If function names and arguments lists are carefully chosen, we can keep these as long living endpoints, while at the same time being able to upgrade the implementation logic. We can do all of this without our users needing to change any of their code.


About us

Blue Bear Digital Inc. is a software architecture and engineering firm. We help companies come up with innovative ways to use new technology, and we help them design and build it. Get in touch at info@bluebear.tech.

Blue Bear Digital Inc.

Thoughts on Software Architecture, Business, and Blockchain

Stephen Fiser

Written by

CEO at Blue Bear Digital Inc.

Blue Bear Digital Inc.

Thoughts on Software Architecture, Business, and Blockchain