In this post I introduce the notion of programmable money and smart contracts, why they go hand-in-hand with blockchains, how smart contracts are programmed today and how they might be programmed in the future.
Programmable money
Imagine if moving money around the world were as convenient and as cheap as sending a text message to a friend living abroad. Imagine if transferring ownership of something as important as a house could be done entirely online with the same level of trust and guarantees as those provided by a notary, at a fraction of the cost. These things and many more are made possible by a combination of emerging technologies including cryptographic currencies, decentralised peer-to-peer networks and new consensus protocols based on distributed ledgers (“blockchains”). Together they form the basis for a new digital financial system sometimes called “decentralized finance” (“DeFi”). In the words of MIT’s Digital Currency Initiative, the promise of these technologies is to “empower individuals by making it as fast and easy to move value across the world as it is to move information”.
For the first time in human history, these technologies have enabled money to become “programmable” in the same way that we can today talk about programmable appliances (Internet of Things) or programmable networks (Software Defined Networking). This “programmable money” is programmed by means of so-called “smart contracts”, software programs that automatically move digital assets according to arbitrary pre-specified rules1. Smart contracts are used in industry to implement tokenised (cryptographic) money (Tether, DAI and many others), escrow services (EscrowMyEther), lending platforms (Aave, Maker, Compound), decentralised autonomous organisations (DAOs), atomic swaps (Uniswap), auctions (TokenSwap), prediction markets (Augur), fundraisers (WeiFund), and so forth.
The role of Blockchain
As mentioned, smart contracts are software programs that automatically move digital assets according to arbitrary pre-specified rules. But what sets these programs apart from traditional programs running on the mainframe computers of banks and insurance companies? The answer lies in the trust model. If Alice and Bob want to exchange digital assets according to a program (a sequence of instructions) that they both agree to, there is still the question of who will execute those instructions? If Alice executes the program on her computer, Bob must trust Alice to faithfully run the exact sequence of instructions that they both agreed to. Alice and Bob do not necessarily trust each other, so this setup is not a workable solution (and of course, neither is the symmetrical setup where Bob would execute the code on his computer).
Up until just a decade ago, the only practical solution to this problem was to let the program be executed by a common, trusted third-party (e.g. a bank or payments processor that Alice and Bob both trust). Then in 2009 a pseudonymous programmer named Satoshi Nakamoto invented the idea of using a replicated ledger (now commonly known as a “blockchain”) distributed across many computers interconnected by a peer-to-peer network and used it to implement a decentralised digital payments system called Bitcoin2. In 2013, a 19-year old prodigy named Vitalik Buterin realised that one could take this idea of a distributed ledger and use it to build not just a decentralised payments network, but a fully Turing-complete “decentralised computer”1. The resulting system is called Ethereum and it essentially turns a network of individually untrustworthy computers into a single global virtual trustworthy computer.
How does Ethereum now solve Alice and Bob’s problem? Rather than Alice or Bob having to place their trust in a single trusted third party as before, they can now place their trust in a collective network of computers that pledge to faithfully execute the program that they both agreed to. As long as the majority of computers does not misbehave, the program will execute as intended. Whether it is better to trust a single party like a bank or a decentralised network like Ethereum depends on a lot of factors, and the key point here is not that one setup is necessarily better or worse than the other. The key point is that the rise of decentralised computers has given individuals like Alice and Bob, as well as companies and institutions around the world new options to transact with one another without having to rely on centralised trusted third parties, if they would want to do so.
While Ethereum has not yet reached mainstream economic adoption, in the last 5 years the platform has experienced significant growth in both usage (parties using it to transact) as well as in its infrastructure (parties contributing resources to scale and secure the platform). Ethereum is currently the largest programmable decentralised computer in the world with the total value of funds “locked” into its smart contracts estimated at over $11 Billion at the time of writing this post.
Programming smart contracts
A “decentralised computer” is essentially a replicated state machine, a concept first described by Leslie Lamport in one of the most influential papers on distributed systems3. Likewise, an individual smart contract at its core is a state machine. An illustrative example of the typical state machine logic coded up within a smart contract is that of a vending machine. A vending machine encapsulates the simple protocol that one must first insert coins into the machine (locking up assets into the contract), after which one can select a good, after which the vending machine dispenses the good and returns any change (releasing assets from the contract)4.
Programming directly at the abstraction level of state machines is generally considered to be cumbersome and low-level. Thus high-level programming languages were created in which to express the contract logic. On the Ethereum platform for example, contracts are typically written in high-level programming languages and then compiled into bytecode for the Ethereum Virtual Machine (EVM). The most widely used such high-level language is called Solidity. Solidity uses a Java-like syntax to describe the states and state transitions of a smart contract.
A common use case of smart contracts in Ethereum is to create new kinds of cryptographic money, also called “tokens”. In recent years, standard contract interfaces have emerged that enable tokens defined by different contracts to become interoperable and interchangeable, such as the ERC20 standard These standards define operations on smart contracts that quite resemble object-oriented interfaces.
Risks in programming smart contracts
As with any code, smart contracts may contain bugs (unintended side-effects). However, bugs in smart contracts code may have consequences far greater than bugs in typical object-oriented application code. In 2016, hackers were able to exploit a simple programming bug in a smart contract program called The DAO and steal digital assets valued at around $50M at the time of the attack. The DAO was a decentralised autonomous organization, an investment vehicle that raised money via one of the largest crowdfunding campaigns in history. The DAO attack laid bare the enormous risks and responsibilities that go with programming smart contracts.
Bugs in smart contracts are particularly pernicious because such contracts embody the principle of “code as law”: participants agree to abide by the code in the contract to act as the final arbiter. This makes cooperation more predictable, reducing counterparty risk. However, when disputes do arise (perhaps due to a “bug” in the code, or a condition that was not fully specified), there is no legal system to seek recourse. Transactions cannot be rolled back, making mistakes irrecoverable and final. Thus, despite the fact that smart contracts programming is like high-level application programming, it also shares strong similarities with hardware and embedded programming, where a flaw in microcode or firmware may have large repercussions once the hardware is deployed in the field. As a result, there are many security best practices that smart contract developers must now painstakingly follow.
New directions in programming smart contracts
In order for smart contracts and decentralized finance to receive mainstream adoption, we need to make “programmable money” significantly easier and safer to program. As the DeFi economy matures and more smart contracts are developed, more flaws will inevitably come to light and the industry will see the need to move toward safer smart contracts languages and platforms.
Seven years ago, before the invention of Ethereum when smart contracts did not yet receive any kind of significant adoption, with Mark S. Miller we explored the possibility of writing smart contracting logic in a widely used, general-purpose programming language called JavaScript5 (on which I’ve written before on this blog). That work was itself based on seminal work by Mark on exploring the use of object-capabilities to implement digital financial instruments6.
The choice for JavaScript offers many advantages: a large user base, familiarity, flexibility, mature tooling and ease-of-use. However, its obscure semantics make it difficult to reason about code correctness, which, as we’ve seen, is paramount in smart contracts programming. To mitigate this, smart contract logic can be written in a secure subset of JavaScript such as Secure ECMAScript or Jessie. Mark’s company Agoric is turning this approach into a viable industry-strength solution, through their development of a smart contracts framework called Zoe.
Another promising direction towards safer smart contract programming lies in a new generation of dedicated smart contract programming languages that embrace novel type systems to statically verify desirable characteristics of smart contracts code, such as the Move programming language7 built as part of Facebook’s Libra digital currency initiative. Move introduces resource types built on linear logic8 to provide better control to developers over resources such as digital tokens that should not be accidentally or maliciously copied or deleted in program code.
Looking ahead
Whether the next generation of smart contracts will be written in a secure subset of a pre-existing language, or in an entirely fresh, dedicated programming language is hard to say. It is in fact humbling to consider how incredibly nascent the field of smart contracts programming really is. The Ethereum platform launched only in July 2015, and the majority of smart contracts written by companies are but a few years old. Similar to how Web programming has evolved significantly in the last 30 years (from hand-written HTML pages and PHP scripts and an imperative programming mindset in the early ‘90s to sophisticated JavaScript Web frameworks and a functional programming mindset today), we have strong reasons to believe that the way smart contracts are programmed is poised to radically change in the years to come.
References
-
V. Buterin, A next generation smart contract and decentralised application platform, White Paper, 2014. ↩ ↩2
-
S. Nakamoto. Bitcoin: A Peer-to-Peer Electronic Cash System, White Paper, 2009. ↩
-
L. Lamport. Time, clocks, and the ordering of events in a distributed system. Communications of the ACM 21, 7 (July 1978), pp. 558–565. ↩
-
N. Szabo, Formalizing and Securing Relationships on Public Networks, First Monday, 1997. ↩
-
M.S. Miller, T. Van Cutsem, B. Tulloh. Distributed Electronic Rights in JavaScript. European Symposium on Programming (ESOP) 2013. LNCS vol 7792. Springer. ↩
-
M. S. Miller, C. Morningstar, B. Frantz. Capability-based Financial Instruments. Financial Cryptography, Springer-Verlag, 2000. ↩
-
S. Blackshear, E. Cheng, D. L. Dill, V. Gao, B. Maurer, T. Nowacki, A. Pott, S. Qadeer, D. Russi, S. Sezer, T. Zakian and R. Zhou. Move: A Language With Programmable Resources. (2019). ↩
-
J. Girard. “Linear logic”. Journal of Theoretical Computer Science. vol 50, no. 1, pp. 1-101, 1987. ↩