Note: this is the original Ethereum white paper. To see the latest Homestead release white paper, visit Ethdocs.org.
Ethereum: A Next-Generation Generalized Smart Contract and Decentralized Application Platform
In the last few months, there has been a great amount of interest into the area of using Bitcoin-like blockchains, the mechanism that allows for the entire world to agree on the state of a public ownership database, for more than just money. Commonly cited applications include “colored coins”, the idea of using on-blockchain digital assets to represent custom currencies and financial instruments, “smart property”, physical objects such as cars which track a colored coin on a blockchain to determine their present legitimate owner, as well as more advanced applications such as decentralized exchange, financial derivatives, peer-to-peer gambling and on-blockchain identity and reputation systems. Perhaps the most ambitious of all is the concept of “autonomous agents” or “decentralized autonomous corporations” – autonomous entities that operate on the blockchain without any central control whatsoever, eschewing all dependence on legal contracts and organizational bylaws in favor of having resources and funds autonomously managed by a self-enforcing smart contract on a cryptographic blockchain.
However, most of these applications are difficult to implement today, simply because the scripting systems of Bitcoin, and even proto-cryptocurrency-2.0 alternatives such as the Bitcoin-based colored coins protocol and so-called “metacoins”, are far too limited to allow the kind of arbitrarily complex computation that DACs require. What this project intends to do is take the innovations that such protocols bring, and generalize them – create a fully-fledged, Turing-complete (but heavily fee-regulated) cryptographic ledger that allows participants to encode arbitrarily complex contracts, autonomous agents and relationships that will be mediated entirely by the blockchain. Rather than being limited to a specific set of transaction types, users will be able to use Ethereum as a sort of “Minecraft of crypto-finance” – that is to say, one will be able to implement any feature that one desires simply by coding it in the protocol’s internal scripting language. Custom currencies, financial derivatives, identity systems and decentralized organizations will all be easy to do, and it will also be possible to construct transaction types that even the Ethereum developers did not imagine. Altogether, we believe that this design is a solid step toward the realization of “cryptocurrency 2.0”; we hope that Ethereum will be to cryptocurrency what Web 2.0 was to the World Wide Web circa 1995.
Why A New Protocol
When one wants to create a new application, especially one in so delicate an area as cryptography or cryptocurrency, the immediate, and correct, first instinct is to use existing protocols as much as possible. There is no need to create a new currency, or even a new protocol, when the problem can be solved entirely by using existing technologies. Indeed, the puzzle of attempting to solve the problems of smart property, smart contracts and decentralized autonomous corporations on top of Bitcoin is how our interest in cryptocurrency 2.0 technologies originally started. Over the course of our research, however, it became evident that while the Bitcoin protocol is more than adequate for currency, basic multisignature escrow and certain simple versions of smart contracts, there are fundamental limitations that make it non-viable for anything beyond a certain very limited scope of features.
The first attempt to implement a system for managing smart property and custom currencies and assets on top of a blockchain was built as a sort of overlay protocol on top of Bitcoin itself, with many advocates making a comparison to the way that HTTP serves as a layer on top of TCP in the internet protocol stack. The colored coins protocol is roughly defined as follows:
- A colored coin issuer determines that a given transaction output
Hbeing the transaction hash and
ithe output index) represents a certain asset, and publishes a “color definition” specifying this transaction output alongside what it represents (eg. 1 satoshi from
H:i= 1 ounce of gold redeemable at amagimetals.com).
- Others “install” the color definition file in their colored coin clients.
- When the color is first released, output
H:iis the only transaction output to have that color.
- If a transaction spends inputs with color X, then its outputs will also have color X. For example, if the owner of
H:iimmediately makes a tranasction to split that output among five addresses, then those transaction outputs will all also have color X. If a transaction has inputs of different colors, then a “color transfer rule” or “color kernel” determines which colors which outputs are (eg. a very naive implementation may say that output 0 has the same color as input 0, output 1 the same color as input 1, etc).
- When a colored coin client notices that it received a new transaction output, it uses a back-tracing algorithm based on the color kernel to determine the color of the output. Because the rule is deterministic, all clients will agree on what color (or colors) each output has.
However, the protocol has several fundamental flaws:
- Difficulty of simplified payment verification – Bitcoin’s Merkle tree construction allows for a protocol known as “simplified payment verification“, where a client that does not download the full blockchain can quickly determine the validity of a transaction output by asking other nodes to provide a series of hashes starting from the transaction hash, going up the Merkle tree and culminating at the root hash in the block header. The client will still need to download the block headers to be secure, but the amount of data bandwidth and verification time required drops by a factor of nearly a thousand. With colored coins, this is much harder. The reason is that one cannot determine the color of a transaction output simply by looking up the Merkle tree; rather, one needs to employ the backward scanning algorithm, fetching potentially hundreds of transactions and requesting a Merkle tree validity proof of each one, before a client can be fully satisfied that a transaction has a certain color. After over a year of investigation, including help from ourselves, no solution has been found to this problem.
- Incompatibility with scripting – as mentioned above, Bitcoin does have a moderately flexible scripting system, for example allowing users to sign transactions of the form “I release this transaction output to anyone who is willing to pay to me 1 BTC”. Other examples include assurance contracts, efficient micropayments and on-blockchain auctions. However, this system is inherently not color-aware; that is to say, one cannot make a transaction of the form “I release this transaction output to anyone who is willing to pay me one gold coin defined by the genesis
H:i“, because the scripting language has no idea that there even are different colors. One major consequence of this is that, while trust-free swapping of two different colored coins is possible, a full decentralized exchange is not since there is no way to place an order to buy or sell that is enforceable.
- Same limitations as Bitcoin – theoretically, on-blockchain protocols can support advanced derivatives, bets and various kinds of conditional transfers that will be described in more detail later in this paper. Colored coins inherits the limitations of Bitcoin in terms of the impossibility of many such arrangements.
Another concept, once again in the spirit of sitting on top of Bitcoin much like HTTP over TCP, is that of “metacoins”. The concept of a metacoin is simple: the metacoin protocol provides for a way of encoding metacoin transaction data into the outputs of a Bitcoin transaction, and a metacoin node works by processing all Bitcoin transactions and evaluating Bitcoin transactions that are valid metacoin transactions in order to determine the current balance sheet at any given time. For example, a simple metacoin protocol might require a transaction to have four outputs:
MAKRER would be a specific marker address to identify a transaction as a metacoin transaction,
FROM would be the address that coins are sent from,
TO would be the address that coins are sent to and
VALUE would be an address encoding the amount sent. Because the Bitcoin protocol is not metacoin-aware, and thus will not reject invalid metacoin transactions, the metacoin protocol must treat all transactions with the first output going to
MARKER as valid and react accordingly. For example, an implementation of the relevant part of this metacoin protocol might look like this:
if tx.output != MARKER: break else if balance[tx.output] < decode_value(tx.output): break else if not tx.hasSignature(tx.output): break else: balance[tx.output] -= decode_value(tx.output); balance[tx.output] += decode_value(tx.output);
The advantage of a metacoin protocol is that it can allow for more advanced transaction types, including custom currencies, decentralized exchange, derivatives, etc, that are impossible on top of Bitcoin itself. However, metacoins on top of Bitcoin have one major flaw: simplified payment verification, already difficult with colored coins, is outright impossible on a metacoin. The reason is that while one can use SPV to determine that there is a transaction sending 30 metacoins to address X, that by itself does not mean that address X has 30 metacoins; what if the sender of the transaction did not have 30 metacoins to start with and so the transaction is invalid? Finding out any part of the current state essentially requires scanning through all transactions going back to the metacoin’s original launch to figure out which transactions are valid and which ones are not. This makes it impossible to have a truly secure client without downloading the entire 12 GB Bitcoin blockchain.
Ethereum solves both of these issues by being hosted on its own blockchain, and by storing a distinct “state tree” representing the current balance of each address and a “transaction list” representing the transactions between the current block and the previous block in each block. Ethereum contracts are allowed to have an arbitrarily large memory, and the Turing-complete scripting language makes it possible to encode an entire currency inside of a single contract. The intention of Ethereum is not to replace colored coins and metacoins by offering superior features; rather, Ethereum intends to serve as a superior foundational layer offering a uniquely powerful scripting system on top of which arbitrarily advanced contracts, currencies and other decentralized applications can be built. If existing colored coins and metacoin projects were to move onto Ethereum, they would gain the benefits of Ethereum’s simplified payment verification, compatibility with financial derivatives and decentralized exchange, and the ability to work together on a single network. With Ethereum, someone with an idea for a new contract or transaction type that might drastically improve the state of what can be done with cryptocurrency would not need to start their own coin; they could simply implement their idea in Ethereum script code.
The design behind Ethereum is intended to follow the following principles:
- Simplicity – the Ethereum protocol should be as simple as possible, even at the cost of some data storage inefficiency or time inefficiency. An average programmer should ideally be able to follow and implement the entire specification, so as to eventually help minimize the influence that any specific individual or elite group can have on the protocol and furthering the vision of Ethereum as a protocol that is open to all. Optimizations which add complexity should not be included unless they provide very substantial benefit.
- Universality – it is a fundamental part of Ethereum’s design philosophy that Ethereum does not have “features”. Instead, Ethereum provides an internal Turing-complete scripting language which you can use to construct any smart contract or transaction type that can be mathematically defined. Want to invent your own financial derivative? With Ethereum, you can. Want to make your own currency? Set it up as an Ethereum contract. Want to set up a full-scale Daemon or Skynet? You may need to have a few thousand interlocking contracts, and be sure to feed them generously, to do that, but nothing is stopping you.
- Modularity – different parts of the Ethereum protocol should be designed to be as modular and separable as possible. Over the course of development, it should be easy to make a small protocol modification in one place and have the application stack continue to function without any further modification. Innovations such as Dagger, Patricia trees and RLP should be implemented as separate libraries and made to be feature-complete even if Ethereum does not require certain features so as to make them usable in other protocols as well. Ethereum development should be maximally done so as to benefit the entire cryptocurrency ecosystem, not just itself.
- Non-discrimination – the protocol should not attempt to actively restrict or prevent specific categories of usage, and all regulatory mechanisms in the protocol should be designed to directly regulate the harm, not attempt to oppose specific undesirable applications. You can even run an infinite loop script on top of Ethereum for as long as you are willing to keep paying the per-computational-step transaction fee for it.
Basic Building Blocks
At its core, Ethereum starts off as a fairly regular proof-of-work mined cryptocurrency without many extra complications; in fact, Ethereum is in many ways simpler than the Bitcoin-based cryptocurrencies that we use today. The concept of a transaction having multiple inputs and outputs, for example, is gone, replaced by a more intuitive balance-based model (to prevent transaction replay attacks, as part of each account balance we also store an incrementing nonce). Sequence numbers and lock times are also removed, and all transaction and block data is encoded in a single format. Instead of addresses being the RIPEMD160 hash of the SHA256 hash of the public key prefixed with
04, addresses are simply the last 20 bytes of the SHA3 hash of the public key. Unlike other cryptocurrencies, which aim to have “features”, Ethereum intends to take features away, and instead provide its users with near-infinite power through an all-encompassing mechanism called “contracts”.
Ethereum Client P2P Protocol
The Ethereum client P2P protocol is a fairly standard cryptocurrency protocol, and can just as easily be used for any other cryptocurrency; the only modification is the introduction of the “Greedy Heaviest Observed Subtree” (GHOST) protocol first introduced by Yonatan Sompolinsky and Aviv Zohar in December 2013; the motivation for and implementation of GHOST will be described in more detail below. The Ethereum client will be entirely reactive; it will not do anything by itself (except for the networking daemon maintaining connections) unless provoked. However, the client will also be more powerful; unlike bitcoind, which only stores a limited amount of data about the blockchain, the Ethereum client will also act as a fully functional backend for a block explorer.
When the client reads a message, it will perform the following steps:
- Hash the data, and check if the data with that hash has already been received. If so, exit. Otherwise, pass it along to the data parser.
- If the data parser says that a data item is a valid block, go to step 3. If the data parser says that a data item is a transaction, see if there are enough funds in the sending address for the transaction to go through, and if there are add it to the local transaction list and publish it to the network. If the data parser says that a data item is a message, send the message to the message responder and return the response.
- Check if the “parent” parameter in the block is already stored in the database. If it is not, exit
- Check if every block header in the “uncles” parameter in the block has the block’s parent as its own parent. If any is not, exit. Note that uncle blocks do not need to be in the database; they just need to have valid proof of work.
- Call the state updater with arguments (1) the parent of the block, (2) the transaction list of the block, (3) the timestamp of the block and (4) the coinbase of the block and see if the block header outputted by the state updater is exactly the same. If not, exit. If yes, add the block to the database and publish it to the network.
TD(block)(“total difficulty”) for the new block. TD is defined recursively by
TD(genesis_block) = 0and
TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty. If the new block has higher TD than the current block, set the current block to the new block.
If the node is mining, the node performs the following additional steps upon receiving a block:
- Determine if the block’s parent is in the database. If not, discard it.
TD(block)(“total difficulty”). If
TD(block)is higher than of any existing block in the database, start mining on that block and clear all uncles. Also, remove all transactions in the new block from the transaction pool if present, and immediately apply the remaining transactions to the new block.
- If the block’s parent is the parent of the highest block, add the block header to the set of uncles and restart the proof of work.
Upon receiving a transaction, the miner should apply the transaction to the current block and then start mining the new block header after the current mining round finishes.
The motivation behind GHOST is that blockchains with fast confirmation times currently suffer from reduced security due to a high stale rate; because blocks take a certain time to propagate through the network, call it
t, if miner A mines a block and then miner B happens to mine another block before miner A’s block propagates to B, miner B’s block will end up wasted and will not contribute to network security. Furthermore, there is a centralization issue: if miner A is a mining pool with 30% hashpower and B has 10% hashpower, A will have a risk of producing stale blocks 70% of the time whereas B will have a risk of producing stale blocks 90% of the time. Thus, if the stale rate is high, A will be substantially more efficient simply by virtue of its size. With these two effects combined, blockchains which produce blocks quickly are very likely to lead to one mining pool having enough percentage of the network to have de facto control over the mining process. GHOST solves the first issue of network security loss by including stale blocks in the calculation of which chain is the “longest”. Ethereum only does GHOST down one level for simplicity (ie. stale blocks must be included as uncles in the next block in order to count), but this should have 90%+ of the benefit of GHOST. Also, in Ethereum we give stales 3/4 of their block reward (and the nephew that includes them 1/8 as a reward); this modification is intended to solve the second issue of centralization bias.
Currency and Issuance
The Ethereum network includes its own built-in currency, ether. The main reason for including a currency in the network is twofold. First, like Bitcoin, ether is rewarded to miners to as to incentivize network security. Second, it serves as a mechanism for paying transaction fees for anti-spam purposes. Of the two main alternatives to fees, per-transaction proof of work similar to Hashcash and feeless laissez-faire, the former is wasteful of resources and unfairly punitive against weak computers and smartphones and the latter would lead to the network being almost immediately overwhelmed by an infinitely looping “logic bomb” contract. Ether will have a theoretical hard cap of 2128 units (compare 250.9 in BTC), although not more than 2100 units will be released in the foreseeable future. For convenience and to avoid future argument (see the current mBTC/uBTC/satoshi debate), the denominations will be pre-labelled:
- 1: wei
- 10^3: __
- 10^6: __
- 10^9: koblitz
- 10^12: szabo
- 10^15: finney
- 10^18: ether
This should be taken as an expanded version of the concept of “dollars” and “cents” or “BTC” and “satoshi” that is intended to be future proof; only szabo, finney and ether will likely be used in the foreseeable future. The right to name the 103 and 106 units will be left as a high-level secondary reward for the fundraiser subject to pre-approval from ourselves.
|After 1 year||After 5 years|
The issuance model will be as follows:
- Ether will be sold in a Mastercoin-style fundraiser at the price of 1 ether for 0.0001 BTC. Suppose that X ether gets collected in this way.
- 0.25X ether will be given to the founders.
- 0.25X ether will be given to the Ethereum organization as a reserve pool to pay expenses in ETH such as ETH salaries or bounties for those developers who want part or all of their compensation to be in this form
- 0.5X ether will be mined per year forever after that point (ie. permanent linear inflation)
For example, after five years and assuming no transactions, 25% of the ether will be in the hands of the fundraiser participants, 6.25% in the founder pool, 6.25% paid to the reserve pool, and 62.5% will belong to miners. The linear model reduces the risk of what some see as excessive wealth concentration in Bitcoin, and gives individuals living in present and future eras a fair chance to acquire currency units, while at the same time retaining a strong incentive to invest because the inflation “rate” still tends to zero over time. We also theorize that because coins are always lost over time, and coin loss can be modeled as a percentage of the total supply per year, that the total currency supply in circulation will in fact eventually stabilize at a value equal to the annual issuance divided by the loss rate (eg. 200x annual issuance at a loss rate of 0.5%).
All data in Ethereum will be stored in recursive length prefix encoding, which serializes arrays of strings of arbitrary length and dimension into strings. For example,
['dog', 'cat'] is serialized (in byte array format) as
[ 130, 67, 100, 111, 103, 67, 99, 97, 116]; the general idea is to encode the data type and length in a single byte followed by the actual data (eg. converted into a byte array, ‘dog’ becomes
[ 100, 111, 103 ], so its serialization is
[ 67, 100, 111, 103 ]. Note that RLP encoding is, as suggested by the name, recursive; when RLP encoding an array, one is really encoding a string which is the concatenation of the RLP encodings of each of the elements. In the event that storing a number is required, the number will be stored in big-endian base 256 format (eg. 32767 in byte array format as
[ 127, 255 ]).
A full block is stored as:
[ block_header, transaction_list , uncle_list ]
The block header is:
[ parent hash, sha3(rlp_encode(uncle_list)), coinbase address, state_root, sha3(rlp_encode(transaction_list)), difficulty, timestamp, nonce ]
Where the data for the proof of work is the RLP encoding of the block WITHOUT the nonce.
transaction_list are the lists of the uncle block headers and tranactions in the block, respectively.
state_root is the root of a Merkle Patricia tree containing (key, value) pairs for all addresses where each address is represented as a 20-byte binary string. At each address, the value stored in the Merkle Patricia tree is a string which is the RLP-serialized form of an object of one of the following two forms:
[ balance, nonce ] [ balance, nonce, contract_root ]
nonce is the number of transactions made from the address, and is incremented every time a transaction is made. The purpose of this is to (1) make each transaction valid only once to prevent replay attacks, and (2) to make it impossible (more precisely, cryptographically infeasible) to construct a contract with the same hash as a pre-existing contract.
balance refers to the contract or address’s balance, denominated in wei.
contract_root is the root of yet another Patricia tree, conaining the contract’s memory, if that address is controlled by a contract. Note that in the main Patricia tree all addresses have a length of 20, even if they start with one or more zero bytes, and in the contract subtrees all indices have a length of 32, prepending with zero bytes if necessary.
Over the past five years of experience with Bitcoin and alternative cryptocurrencies, one important property for proof of work functions that has been discovered is that of “memory-hardness” – computing a valid proof of work should require not only a large number of computations, but also a large amount of memory. Currently, two major categories of memory-hard functions, scrypt and Primecoin mining, exist, but both are imperfect; neither require nearly as much memory as an ideal memory-hard function could require, and both suffer from time-memory tradeoff attacks, where the function can be computed with significantly less memory than intended at the cost of sacrificing some computational efficiency. Ethereum instead uses an algorithm called Dagger, a memory-hard proof of work based on moderately connected directed acyclic graphs (DAGs, hence the name), which, while far from optimal, has much stronger memory-hardness properties than anything else in use today: an estimated 50-500 MB of RAM will be required per thread depending on the choice of parameters.
Dagger is more fully specified here: http://wiki.ethereum.org/index.php/Dagger
A transaction is stored as:
[ nonce, receiving_address, value, [ data item 0, data item 1 ... data item n ], v, r, s ]
nonce is the number of transactions already sent by that address, or an empty string if this is the first transaction.
(v,r,s) is the raw Electrum-style signature of the transaction without the signature made with the private key corresponding to the sending address, with
27 <= v <= 30. From an Electrum-style signature (65 bytes) it is possible to extract the public key, and thereby the address, directly. Note that all transactions in Ethereum are valid; invalid transactions or transactions with insufficient balance simply have no effect. Transaction fees will be included automatically. If one wishes to voluntarily pay a higher fee, one is always free to do so by constructing a contract which forwards transactions but automatically sends a certain amount or percentage to the miner of the current block.
Difficulty is adjusted by the formula:
D(genesis_block) = 2^36 D(block) = if block.timestamp >= block.parent.timestamp + 42: D(block.parent) - floor(D(block.parent) / 1024) else: D(block.parent) + floor(D(block.parent) / 1024)
This stabilizes around a block time of 60 seconds automatically (note that at a block time of 60 seconds, 50% of blocks come within 42 seconds of the previous;
1 - 1/e = 63.22% come within 60 seconds), and adjusts at a maximum rate of about 0.1% per block (~100% per 12 hours).
Transactions sent to the empty string as an address are a special type of transaction, creating a “contract”.
Here is where we get to the actually interesting part of the Ethereum protocol. In Ethereum, there are actually two types of entities that can generate and receive transactions: actual people (or bots, as cryptographic protocols cannot distinguish between the two) and contracts. A contract is essentially an automated agent that lives on the Ethereum network, has an Ethereum address and balance, and can send and receive transactions. A contract is “activated” every time someone sends a transaction to it, at which point it runs its code, perhaps modifying its internal state or even sending some transactions, and then shuts down. The “code” for a contract is written in a special-purpose low-level language consisting of a stack, which is not persistent, and 2^256 memory entries, which constitute the contract’s permanent state. Note that Ethereum users will not need to code in this low-level stack language; we will provide a simple C-like language with variables, expressions, conditionals and while loops, and provide a compiler down to Ethereum code.
Here are some examples of what can be done with Ethereum contracts, with all code examples written in a language that will likely be very similar to the C-like high-level language that we will release. The variables
tx.datan are properties of the incoming transaction,
contract.creator of the contract itself, and
block.timestamp properties of the block.
block.basefee is the “base fee” which all transaction fees in Ethereum are calculated as a multiple of; for more info see the “fees” section below. All variables expressed as capital letters (eg.
A) are constants, to be set by the contract creator when actually releasing the contract. The keywords
ether, representing the denominations of ether, simply act as multipliers of 1, 1 million, etc, respectively.
Sub-currencies have many applications, ranging from currencies representing assets such as USD or gold to company stocks and even currencies with only one unit issued to represent collectibles or smart property. Advanced special-purpose financial protocols sitting on top of Ethereum may also wish to organize themselves with an internal currency. Sub-currencies are surprisingly easy to implement in Ethereum; this section describes a fairly simple contract for doing so.
The idea is that if someone wants to send
X currency units to address
A in currency contract
C, they will need to make a transaction of the form
(C, 100 * block.basefee, [A, X]), and the contract parses the transaction and adjusts balances accordingly. For a transaction to be valid, it must send 100 times the base fee worth of ether to the contract in order to “feed” the contract (as each computational step after the first 16 for any contract costs the contract a small fee and the contract will stop working if its balance drains to zero).
if tx.value < 100 * block.basefee: stop if contract.memory: from = tx.sender to = tx.data value = tx.data if to <= 1000: stop if contract.memory[from] < value: stop contract.memory[from] = contract.memory[from] - value contract.memory[to] = contract.memory[to] + value else: contract.memory[mycreator] = 10000000000000000 contract.memory = 1
Ethereum sub-currency developers may also wish to add some other more advanced features:
- Include a mechanism by which people can buy currency units in exchange for ether, perhaps auctioning off a set number of units every day.
- Allow transaction fees to be paid in the internal currency, and then refund the ether transaction fee to the sender. This solves one major problem that all other “sub-currency” protocols have had to date: the fact that sub-currency users need to maintain a balance of sub-currency units to use and units in the main currency to pay transaction fees in. Here, a new account would need to be “activated” once with ether, but from that point on it would not need to be recharged.
- Allow for a trust-free decentralized exchange between the currency and ether. Note that trust-free decentralized exchange between any two contracts is theoretically possible in Ethereum even without special support, but special support will allow the process to be done about ten times more cheaply.
The underlying key ingredient of a financial derivative is a data feed to provide the price of a particular asset as expressed in another asset (in Ethereum’s case, the second asset will usually be ether). There are many ways to implement a data feed; one method, pioneered by the developers of Mastercoin, is to include the data feed in the blockchain. Here is the code:
if tx.value < block.basefee: stop if tx.sender != contract.creator: stop memory[data] = data
Any other contract will then be able to query index
I of data store
D by using
block.contract_memory(D,I). A more advanced way to implement a data feed may be to do it off-chain – have the data feed provider sign all values, require anyone attempting to trigger the contract to include the latest signed data, and then use Ethereum’s internal scripting functionality to verify the signature. Pretty much any derivative can be made from this, including leveraged trading, options, and even more advanced constructions like collateralized debt obligations (no bailouts here though, so be mindful of black swan risks).
To show an example, let’s make a hedging contract. The basic idea is that the contract is created by party
A, who puts up 4000 ether as a deposit. The contract then lies open for any party to accept it by putting in 1000 ether. Say that 1000 ether is worth $25 at the time the contract is made, according to index
I of data store
D. If party
B accepts it, then after 30 days anyone can send a transaction to make the contract process, sending the same dollar value worth of ether (in our example, $25) back to
B and the rest to
B gains the benefit of being completely insulated against currency volatility risk without having to rely on any issuers. The only risk to
B is if the value of ether falls by over 80% in 30 days – and even then, if
B is online
B can simply quickly hop onto another hedging contract. The benefit to
A is the implicit 0.2% fee in the contract, and
A can hedge against losses by separately holding USD in another location (or, alternatively,
A can be an individual who is optimistic about the future of Ethereum and wants to hold ether at 1.25x leverage, in which case the fee may even be in
state = contract.memory if state == 0: if tx.value < 1000 ether: stop contract.memory = 998 * block.contract_memory(D,I) contract.memory = block.timestamp contract.memory = tx.sender else: if tx.value < 200 finney: stop ethervalue = contract.memory / block.contract_memory(D,I) if ethervalue >= 5000 ether: send(contract.memory,2000 ether,) else if block.timestamp < contract.memory: send(contract.memory,ethervalue,) send(A,5000 - ethervalue,)
More advanced financial contracts are also possible; complex multi-clause options (eg. “Anyone, hereinafter referred to as X, can claim this contract by putting in 2 USD before Dec 1. X will have a choice on Dec 4 between receiving 1.95 USD on Dec 29 and the right to choose on Dec 11 between 2.20 EUR on Dec 28 and the right to choose on Dec 18 between 1.20 GBP on Dec 30 and paying 1 EUR and getting 3.20 EUR on Dec 29”) can be defined simply by storing a state variable just like the contract above but having more clauses in the code, one clause for each possible state. Note that financial contracts of any form do need to be fully collateralized; the Ethereum network controls no enforcement agency and cannot collect debt.
Identity and Reputation Systems
The earliest alternative cryptocurrency of all, Namecoin, attempted to use a Bitcoin-like blockchain to provide a name registration system, where users can register their names in a public database alongside other data. The major cited use case is for a DNS system, mapping domain names like “bitcoin.org” (or, in Namecoin’s case, “bitcoin.bit”) to an IP address. Other use cases include email authentication and potentially more advanced reputation systems. Here is a simple contract to provide a Namecoin-like name registration system on Ethereum:
if tx.value < 25 ether: stop if contract.memory[tx.data]: stop contract.memory[tx.data] = contract.memory[tx.data]
One can easily add more complexity to allow users to change mappings, automatically send transactions to the contract and have them forwarded, and even add reputation and web-of-trust systems.
Decentralized Autonomous Organizations
The general concept of a “decentralized autonomous corporation” is that of an entity that has a certain set of shareholders which collect dividends and which, perhpas with a 67% majority, have the right to modify its code. The shareholders would collectively decide on how the corporation should allocate its funds, using either bounties, salaries or even more exotic mechanisms such as an internal currency to reward work, and the funds would be distributed automatically. This essentially replicates the legal trappings of a traditional company but using only cryptographic blockchain technology for enforcement. This is the “corporate” model of a decentralized organization; an alternative, perhaps described as a “decentralized autonomous community”, would have all members have an equal share in the decision making and require 67% of existing members to agree to add or remove a member. The requirement that one person can only have one membership would then need to be enforced collectively by the group.
Some “skeleton code” for a DAO might look as follows.
There are three transaction types:
[0,k]to register a vote in favor of a code change
[1,k,L,v0,v1...vn]to register a code change at code
kin favor of setting memory starting from location
v0, v1 ... vn
[2,k]to finalize a given code change
Note that the design relies on the randomness of addresses and hashes for data integrity; the contract will likely get corrupted in some fashion after about
2^128 uses, but that is acceptable since nothing close to that volume of usage will exist in the foreseeable future.
2^255 is used as a magic number to store the total number of members, and a membership is stored with a
1 at the member’s address. The last three lines of the contract are there to add
C as the first member; from there, it will be C’s responsibility to use the democratic code change protocol to add a few other members and code to bootstrap the organization.
k = sha3(tx.data) if tx.data == 0: if contract.memory[tx.sender] == 0: stop if contract.memory[k + tx.sender] == 0: contract.memory[k + tx.sender] = 1 contract.memory[k] += 1 else if tx.data == 1: if tx.value <= tx.datan * block.basefee * 200: stop if contract.memory[k] > 0: stop i = 3 while i < tx.datan: contract.memory[k + i] = tx.data[i] i = i + 1 contract.memory[k] = 1 contract.memory[k+1] = tx.datan contract.memory[k+2] = tx.data else if tx.data == 2: if contract.memory[k] >= contract.memory[2 ^ 255] * 2 / 3: if tx.value <= tx.datan * block.basefee * 200: stop i = 3 L = contract.memory[k+1] loc = contract.memory[k+2] while i < L: contract.memory[loc+i-3] = tx.data[i] i = i + 1 if contract.memory[2 ^ 255 + 1] == 0: contract.memory[2 ^ 255 + 1] = 1 contract.memory[C] = 1
This implements the “egalitarian” DAO model; one can easily extend it to a shareholder model by also storing how many shares each owner holds and providing a simple way to transfer shares.
1) Crop insurace. One can easily make a financial derivatives contract but using a data feed of the weather instead of any price index. If a farmer in Iowa purchases a derivative that pays out inversely based on the precipitation in Iowa, then if there is a drought the farmer will automatically receive money and if there is enough rain the farmer will be happy because their crops would do well.
2) Generic insurance, relying on one of a specified set of third-party judges to adjudicate claims. The contract can even include a complex appeals process if so desired.
3) A decentrally managed data feed, using proof-of-stake voting to give an average (or more likely, median) of everyone’s opinion on the price of a commodity, the weather or any other relevant data
4) An offer to participate in a cryptographically secure, trust-free peer-to-peer bet
5) SatoshiDice. The entire gambling site can essentially be replicated on the blockchain using either peer-to-peer bet functionality or a centralized model.
6) A full-scale on-chain stock market. Prediction markets are also easy to implement as a trivial consequence.
7) An on-chain decentralized marketplace, using the identity and reputation system as a base.
How do contracts work?
A contract making transaction is encoded as follows:
[ nonce, '', value, [ data item 0, data item 1, ... ], v, r, s ]
The data items will, in most cases, be script codes (more on this below). Contract creation transaction validation happens as follows:
- Deserialize the transaction, and extract its sending address from its signature.
- Calculate the transaction’s fee. Check that the balance of the creator is at least the endowment plus the fee. If not, exit, and if yes pay the fee.
- Take the last 20 bytes of the hash of the transaction making the contract. If a contract with that address already exists, exit. Otherwise, create the contract at that address
- Copy data item
ito memory slot
[0 ... n-1]in the contract.
Whenever a transaction is sent to a contract, the contract executes its scripting code. The precise steps that happen when a contract receives a transaction are as follows:
Contract Script Interpretation
- The contract’s ether balance increases by the amount sent
- The index pointer is set to zero, and
STEPCOUNT = 0
- Repeat forever:
- if the command at the index pointer is
STOP, invalid or greater than 255, exit from the loop
MINERFEE = 0,
VOIDFEE = 0
STEPCOUNT <- STEPCOUNT + 1
STEPCOUNT > 16, set
MINERFEE <- MINERFEE + STEPFEE
- see if the command is
STORE. If so, set
MINERFEE <- MINERFEE + DATAFEE
- see if the command will fill up a previously zero memory field. If so, set
VOIDFEE <- VOIDFEE + MEMORYFEE
- see if the commend will zero a previously used memory field. If so, set
VOIDFEE <- VOIDFEE - MEMORYFEE
- see if the command is
BALANCE. If so, set
MINERFEE <- MINERFEE + EXTROFEE
- see if the command is a crypto operation. If so, set
MINERFEE <- MINERFEE + CRYPTOFEE
MINERFEE + VOIDFEE > CONTRACT.BALANCE, HALT and exit from the loop
- else, subtract
MINERFEE + VOIDFEEfrom the contract’s balance and add
MINERFEEto a running counter that will be added to the miner’s balance once all transactions are parsed. Note that
MINERFEEmay be negative in some cases, in which case the contract balance would actually increase
- run the command
- if the command did not exit with an error, update the index pointer and return to the start of the loop. If the contract did exit with an error, break out of the loop.
- if the command at the index pointer is
The language maintains a stack which is initialized as empty, and all operations either manipulate the stack, perform special operations such as sending transactions and setting memory, or do both. In the following descriptions,
S[-2], etc represent the topmost, second topmost, etc items on the stack. The individual operations are defined as follows:
(00) STOP– halts execution
(01) ADD– pops two items and pushes
S[-2] + S[-1] mod 2^256.
(02) MUL– pops two items and pushes
S[-2] * S[-1] mod 2^256
(03) SUB– pops two items and pushes
S[-2] - S[-1] mod 2^256
(04) DIV– pops two items and pushes
floor(S[-2] / S[-1]). If
S[-1] = 0, halts execution.
(05) SDIV– pops two items and pushes
floor(S[-2] / S[-1]), but treating values above
2^255as negative (ie.
x -> 2^256 - x). If
S[-1] = 0, halts execution.
(06) MOD– pops two items and pushes
S[-2] mod S[-1]. If
S[-1] = 0, halts execution.
(07) SMOD– pops two items and pushes
S[-2] mod S[-1], but treating values above
2^255as negative (ie.
x -> 2^256 - x). If
S[-1] = 0, halts execution.
(08) EXP– pops two items and pushes
S[-2] ^ S[-1] mod 2^256
(09) NEG– pops one item and pushes
2^256 - S[-1]
(0a) LT– pops two items and pushes 1 if
S[-2] < S[-1]else 0
(0b) LE– pops two items and pushes 1 if
S[-2] <= S[-1]else 0
(0c) GT– pops two items and pushes 1 if
S[-2] > S[-1]else 0
(0d) GE– pops two items and pushes 1 if
S[-2] >= S[-1]else 0
(0e) EQ– pops two items and pushes 1 if
S[-2] == S[-1]else 0
(of) NOT– pops one item and pushes 1 if
S[-1] = 0else 0
(10) MYADDRESS– pushes the contract’s address as a number
(11) TXSENDER– pushes the transaction sender’s address as a number
(12) TXVALUE– pushes the transaction value
(13) TXDATAN– pushes the number of data items
(14) TXDATA– pops one item and pushes data item
S[-1], or zero if index out of range
(15) BLK_PREVHASH– pushes the hash of the previous block (NOT the current one since that’s impossible!)
(16) BLK_COINBASE– pushes the coinbase of the current block
(17) BLK_TIMESTAMP– pushes the timestamp of the current block
(18) BLK_NUMBER– pushes the current block number
(19) BLK_DIFFICULTY– pushes the difficulty of the current block
(1a) BASEFEE– pushes the base fee (
xas defined in the fee section below)
(20) SHA256– pops one item and then
ceil(S[-1] / 32)further items. Then takes those items as 32-byte strings, concatenates them in top-to-bottom order, taking out the low-order bytes of the bottommost if necessary, and pushes the SHA256 of the resulting string.
(21) RIPEMD160– works just like
SHA256but with the
(22) ECMUL– pops three items. If
(S[-2],S[-1])are a valid point in secp256k1, including both coordinates being less than
(S[-2],S[-1]) * S[-3], using
(0,0)as the point at infinity. Otherwise, pushes
(2^256 - 1, 2^256 - 1). Note that there are no restrictions on
(23) ECADD– pops four items and pushes
(S[-4],S[-3]) + (S[-2],S[-1])if both points are valid, otherwise
(2^256 - 1,2^256 - 1).
(24) ECSIGN– pops two items and pushes
(v,r,s)as the Electrum-style RFC6979 deterministic signature of message hash
S[-1]with private key
S[-2] mod N.
(25) ECRECOVER– pops four items and pushes
(x,y)as the public key from the signature
(S[-3],S[-2],S[-1])of message hash
S[-4]. If the signature has invalid
v,r,svalues (ie. v not in
[27,28], r not in
[0,P], s not in
(2^256 - 1,2^256 - 1).
(26) ECVALID– pops two items and pushes 1 if
(S[-2],S[-1])is a valid secp256k1 point (including
(0,0)) else 0
(27) SHA3– works just like
SHA256but with the
SHA3hash, 256 bit version.
(30) PUSH– pushes the item in memory at the index pointer + 1, and advances the index pointer by 2.
(31) POP– pops one item.
(32) DUP– pushes
S[-1]to the stack.
(33) DUPN– reads item in memory at the index pointer + 1, say N, and pushes
S[-N]to the stack. Advances the index pointer by 2. If
N = 0, exits with an error instead.
(34) SWAP– pops two items and pushes
(35) SWAPN– reads item in memory at the index pointer + 1, say N, and swaps
S[-N]to the stack. Advances the index pointer by 2. If
N = 0, exits with an error instead.
(36) LOAD– pops one item and pushes the item in memory at index
(37) STORE– pops two items and sets the item in memory at index
(40) JMP– pops one item and sets the index pointer to
(41) JMPI– pops two items and sets the index pointer to
(42) IND– pushes the index pointer
(50) EXTRO– pops two items and pushes memory index
(51) BALANCE– pops one item and pushes balance of that address, or zero if the address is invalid
(60) MKTX– pops three items and initializes a transaction to send
S[-3]data items. Pops that many data items and adds them in order popped as data items to the transaction. Then sends the transaction. Note that if
S[-1] = 0then this creates a new contract.
(ff) SUICIDE– pops one item, destroys the contract and clears all memory, sending the entire balance plus the negative fee from clearing memory to the address at
Ethereum will have seven primary fees, of which one applies to transaction senders and six apply to contracts. The fees are:
TXFEE(100x) – fee for sending a transaction
NEWCONTRACTFEE(100x) – fee for creating a new contract, not including the memory fee for each item in script code
STEPFEE(x) – fee for every computational step after than first sixteen in contract execution
MEMORYFEE(100x) – fee for adding a new item to a contract’s memory, including when first creating a contract. The memory fee is the only fee that is not paid to a miner, and is refunded when memory from a contract is removed.
DATAFEE(20x) – fee for accessing or setting a contract’s memory from inside that contract
EXTROFEE(40x) – fee for accessing memory from another contract inside a contract
CRYPTOFEE(20x) – fee for using any of the cryptographic operations
One novel innovation in Ethereum is that the fees will be inversely proportional to the square root of the difficulty; that is,
x = floor(10^21 / floor(difficulty ^ 0.5)). The reason why this is done is twofold:
- It creates a fully decentralized mechanism for setting transaction fees that ensures that fees do not grow too quickly with the growth of the network. For example, if ether becomes 4x more valuable, then it is expected that network mining power and therefore difficulty will increase by 4x, meaning that ether-denominated transaction fees will decrease by 2x and therefore real-value transaction fees will only increase 2x.
- If computers get 4x more powerful due to Moore’s Law, difficulty will increase 4x and so fees will decrease 2x, reflecting computers’ increased ability to handle higher load.
The reason the exponent should be kept below 1 is that (1) Moore’s Law may affect computing power faster than the slowest component of the transaction processing pipeline, and (2) if the Ethereum network grows very quickly due to an increased number of computers and not any increase in power to each individual computer, an exponent of 1 may push per-computer load too high.
The Ethereum protocol’s design philosophy is in many ways the opposite from that taken by many other cryptocurrencies today. Other cryptocurrencies aim to add complexity and increase the number of “features”; Ethereum, on the other hand, takes features away. The protocol does not “support” multisignature transactions, multiple inputs and outputs, hash codes, lock times or many other features that even Bitcoin provides. Instead, all complexity comes from an all-powerful, Turing-complete assembly language, which can be used to build up literally any feature that is mathematically describable. As a result, we have a cryptocurrency protocol whose codebase is very small, and yet which can do anything that any cryptocurrency will ever be able to do.
References and Further Reading
- Colored coins whitepaper: https://docs.google.com/a/buterin.com/document/d/1AnkP_cVZTCMLIzw4DvsW6M8Q2JC0lIzrTLuoWu2z1BE/edit
- Mastercoin whitepaper: https://github.com/mastercoin-MSC/spec
- Decentralized autonomous corporations, Bitcoin Magazine: http://bitcoinmagazine.com/7050/bootstrapping-a-decentralized-autonomous-corporation-part-i/
- Smart property: https://en.bitcoin.it/wiki/Smart_Property
- Smart contracts: https://en.bitcoin.it/wiki/Contracts
- Simplified payment verification: https://en.bitcoin.it/wiki/Scalability#Simplifiedpaymentverification
- Merkle trees: http://en.wikipedia.org/wiki/Merkle_tree
- Patricia trees: http://en.wikipedia.org/wiki/Patricia_tree
- Bitcoin whitepaper: http://bitcoin.org/bitcoin.pdf
- GHOST: http://www.cs.huji.ac.il/~avivz/pubs/13/btcscalabilityfull.pdf
- StorJ and Autonomous Agents, Jeff Garzik: http://garzikrants.blogspot.ca/2013/01/storj-and-bitcoin-autonomous-agents.html
- Ethereum RLP: http://wiki.ethereum.org/index.php/RLP
- Ethereum Merkle Patricia trees: http://wiki.ethereum.org/index.php/Patricia_Tree
- Ethereum Dagger: http://wiki.ethereum.org/index.php/Dagger
Reddit comment from Ethereum founder Vitalik Buterin, which led to this archived page from May 21st, 2016.