Smart contracts: the brain of Dapps

Roberto Infante
10 min readMar 13, 2019

If you are interested in blockchain technology, I bet you have often heard the term “smart contract”. But do you know how a smart contract actually works? In this article, extracted from chapter 3 of my book Building Ethereum Dapps, I will introduce Ethereum smart contracts in detail.

As I briefly mentioned in my two previous articles, Transaction lifecycle on the Ethereum blockchain and Introduction to the Ethereum blockchain, an Ethereum smart contract, or simply contract, is a software artifact containing business rules and a state. It’s written in a high-level language such as Solidity, compiled into EVM bytecode, deployed onto the Ethereum network, and stored on its blockchain against a specific account generated at deployment.
As shown in figure 1, a contract receives transaction messages from a user account (or from other contracts) and executes its logic on the Ethereum Virtual Machine (EVM). This might optionally involve sending messages to other contracts, reading state from the blockchain, or writing state to the blockchain (specifically from/to the State Merkle-Patricia trie). The account sending the message to the contract gets charged (in Ether) by the successful mining node for computation and network resources consumed during the processing of the requested operation. The amount of such computation and resources is calculated in a unit called gas, as you’ll see later, so it’s common to say that a transaction consumes a certain amount of gas (rather than resources).

Figure 1. An Ethereum contract receives a transaction message from a user account. Its logic is executed on the Ethereum Virtual Machine (EVM), then the successful miner calculates the cost for the computational and network resources used, in a unit called gas, and then charges the user account in Ether.

If you want to understand smart contracts, how they get instantiated by users and by other contracts, and especially how they get executed, you need to go in greater detail through various concepts I’ve only touched on so far:

  • Accounts
  • Ether and gas
  • Transaction messages
  • The Ethereum Virtual Machine

I’ll start by start telling you more about the various types of accounts.

Accounts

You’ve already come across the concept of account a few times. Accounts are available in two types:

  • Externally owned accounts (EOA) (or simply External Accounts) — These are also known informally as user accounts. They’re publicly identifiable from their public key, but they can only be operated by knowing the private key. If you buy some Ether, you’d store it in this type of account. Also, you’d start a transaction against a smart contract from an EOA.
  • Contract accounts — These are the accounts that contracts are executed under. The account address is generated at deployment time, and it identifies the location of the contract in the blockchain.

Both EOAs and contract accounts hold data, in the form of a key-value store, and an Ether balance. Table 1 compares the main properties of EOAs and contract accounts.

Table 1. Comparison between an EOA and a Contract Account

Ether

I’ve mentioned Ether casually a few times, so it’s probably time you learned more about it. Ether is the cryptocurrency that the Ethereum blockchain supports. Its main purpose is to represent monetary value for services and goods traded over the platform.

Ether is also used to pay for transaction fees. These are, as mentioned in the next section, calculated in a unit called gas, which measures computational resources that a transaction consumes. But these fees are settled in Ether (calculated from the price of a unit of gas, expressed in Ether). Miners charge transaction fees to get compensated for the computational power they provide the network while appending new transaction blocks to the blockchain.

Ether comes in various denominations, which are all defined, as you can see in table 2, as a multiple of wei, the smallest Ether denomination.

Table 2. Ether denominations and values in wei

Figure 2 summarizes the Ether lifecycle, which goes through the following steps:

1. Minting Ether

2. Transferring Ether

3. Storing Ether

4. Exchanging Ether

Figure 2. The Ether lifecycle. Ether is minted by miner nodes into miner user accounts, then it gets transferred to EOAs (also known as user accounts). From there, it can get stored on various wallets. Ultimately, it can get converted to real currency, such as USD, EUR, YEN, GBP, and others, through cryptocurrency exchanges.

Minting Ether

If you’re unfamiliar with cryptocurrencies, you must be wondering how Ether is minted and exchanged. Ether is generated through the mining process, during which miners compete to group and append transactions into new blockchain blocks, as I discussed in the article Introduction to the Ethereum blockchain. When successful, a miner gets rewarded with a certain number of Ether coins. Blocks are added to the Ethereum blockchain every 15 seconds or so, and the money supply increases accordingly.

Transferring Ether

Once Ether has been generated, it’s allocated to the miner’s external account. Miners can then transfer Ether to other external accounts or contract accounts, either through the Ethereum wallet or programmatically, as you’ll see later.

Exchanging Ether

Because Ether is valuable, it doesn’t generally get transferred for free between accounts. It’s often transferred in return for goods and services traded through smart contracts, but also in return for conventional currency, such as US dollars, euros, pounds, yen, and so on. Although it’s possible to buy Ether from individual owners and pay them an agreed amount of conventional currency, it’s more effective to handle such transactions using cryptocurrency exchanges. Two main types of exchanges are available: centralized, such as Kraken, Coinbase, and Coinsquare, and decentralized, such as EtherEx. Each exchange is generally biased toward a specific real-world currency.

Storing Ether

Once someone acquires Ether, either through mining, smart contract trading, or exchange-based trading, it’s allocated to an account. You can manage accounts using many methods, each with a different trade-off between convenience and security. The most convenient one is generally through desktop or online wallets, which allow you to transfer Ether easily. The most secure one is through cold or paper storage, which means generating the private key offline and holding it literally on a piece of paper. Hardware wallets present another high-security option and are conceptually similar to paper wallets because they can be considered offline. The main difference is that the account owner stores the private key on a small electronic device similar to a USB key. Table 3 summarizes the different options.

Table 3. Wallet types and their characteristics

I’ve mentioned that transaction fees are charged in Ether but calculated in a unit called gas. Let’s see what gas is and how it’s related to transaction costs.

Gas

Gas is the unit of measure for transaction fees charged on the Ethereum platform. The amount of gas used to complete a transaction depends on the amount of computational resources that the EVM spends while running the transaction. Specifically, it depends on the exact low-level EVM instructions that have been executed during the transaction. Table 4 gives an idea of the amount of gas charged for the most common EVM operations.

Table 4. Gas cost for simple EVM operations

The main reason the execution of a transaction is charged in units of gas, and indirectly in units of computational work, is to prevent denial of service (DoS) attacks by unscrupulous participants who might want to disrupt the network. To launch a DoS attack, a malicious participant would have to spam the network with a high number of transactions, each performing a large amount of computational work; for instance, an infinite loop. The amount of gas corresponding to this work would be high, and it would have to be paid in a correspondingly high amount of Ether — it’s unlikely anyone would pay for disrupting a service!

Most smart contract development IDEs give an idea of the total amount of gas required to complete a transaction. For example, in the screenshot in figure 3, you can see a gas estimate for the execution of the transfer function of the SimpleCoin contract from the last section of chapter 1 of my book Building Ethereum Dapps, obtained by clicking the Details button on the output panel.

Figure 3. Transaction costs for the execution of the SimpleCoin transfer function

Transaction fee costs are calculated according to this formula:

transaction fees (in Ether) = number of units of gas consumed * price per unit of gas (in Ether)

Let’s break it down:

  • The EVM determines the number of units of gas consumed, as you saw earlier, while running the transaction, and that depends on the computational cost of the code being run during the transaction.
  • The sender of the transaction decides the price of a unit of gas (in Ether). The higher it is, the more likely it is that miners will include the transaction in the block they’re processing. Miners prioritize transactions that are likely to pay high fees, so if a transaction is expected to consume a relatively low amount of gas, the sender will have to set a relatively high gas price to guarantee quick processing.
  • The transaction sender sets a limit for the maximum amount of gas that a transaction should consume. This protects the sender from higher than expected transaction costs due to execution of the code in a way different from what was intended; for instance, if the developer introduces a bug that causes an infinite loop. Such limits should be relatively close to the estimated amount of gas needed to complete the transaction.

While a transaction is being executed, the EVM consumes its gas. Two outcomes are possible at the end of the transaction:

1. The transaction completes successfully. In this case, the unused gas is returned to the sender.

2. The amount of gas available ends before the completion of the transaction. In this case, the EVM throws an end of gas exception, and the transaction is rolled back.

You might be wondering who pockets the transaction fee. Given either of the two transaction outcomes, the miner who has processed the transaction receives the fee. For the first outcome, they earn the fee by including the transaction in a new block that has been successfully appended to the blockchain. For the second outcome, even though the EVM throws an exception, the miner still charges the gas in Ether, and they collect the related transaction fee as usual. In short, a successful miner is rewarded by minting new Ether and getting transaction fees from the transaction senders. In the early stages of the Ethereum platform, most of a miner’s profits came from minting.

Calls and transactions

Accounts interact with each other through two types of messages: calls and transactions.

Calls

A call is sent through a message that doesn’t get stored on the blockchain and whose execution has the following characteristics:

  • It can only perform read-only operations, which don’t alter the state of the blockchain.
  • It doesn’t consume any gas, and, consequently, it’s free.
  • It’s processed synchronously.
  • It immediately returns a return value.
  • It doesn’t allow transferring Ether to the contract account.

Typical calls are direct invocations of contract member variables, including mappings, and invocations of so-called constant functions, which don’t alter contract state.

Transactions

A transaction, which I introduced to you in the article Transaction lifecycle on the Ethereum blockchain, is sent through a message that gets serialized and stored on the blockchain during the mining process. It contains the following fields:

  • Sender address
  • Recipient address
  • Value — Amount of Ether to be transferred (in wei), in case the message is being used to transfer Ether (optional)
  • Data — Input parameters, in case the message is being used as a function call (optional)
  • StartGas — Maximum amount of gas to be used for the execution of the message. If this limit is exceeded, the EVM throws an exception and rolls back the state of the message.
  • Digital signature — Proves the identity of the transaction sender
  • GasPrice — The price of a unit of gas (expressed in Ether) the transaction initiator is willing to pay, as discussed in the gas section

The execution of a transaction has the following characteristics:

  • It can perform write operations, which alter the state of the blockchain.
  • It consumes gas, which must be paid for in Ether.
  • It’s processed asynchronously: it gets executed through mining and then gets appended on a new blockchain block, which gets broadcast throughout the network.
  • It immediately returns a transaction ID, but not a return value.
  • It allows transferring Ether to the contract account. (The Ether transfer becomes part of the transaction itself.)

By now you know contracts are executed on the EVM on each node of the Ethereum network. I’ll provide a quick overview of how the EVM works.

The Ethereum Virtual Machine

The Ethereum Virtual Machine (EVM) is a stack-based abstract computing machine, similar in purpose to the Java virtual machine (JVM) and to the .NET Common Language Runtime (CLR). It enables a computer to run an Ethereum application and has two memory areas:

  • Volatile memory, or simply memory. This is a word-addressed byte array, which gets allocated to a contract at every message call. Reads access 256-bit words, whereas writes can be performed on a width of 8 or 256 bits.
  • Storage. This is a key-value store where both key and value have a width of 256 bits. Storage is allocated to each account and is persisted on the blockchain. A contract account can access only its own storage.

EVM opcodes cover operations including Boolean, bitwise, and arithmetic comparisons and jumps (both conditional and unconditional). These are the main opcodes handling contract creation and calls:

  • CREATE — This performs the creation of a new contract instance.
  • CALL — A contract sends a message to itself or other contracts through this operator.
  • DELEGATECALL — This operator allows the calling contract to send a message to an external contract but execute the related code in the context of the caller. This operator is especially useful for the creation of libraries of shared code that multiple contracts can access.

The EVM is completely sandboxed: a contract can’t access network or filesystem resources. It can only access other contracts. A more in-depth explanation of the EVM is outside the scope of this book. The best reference for understanding its design is Gavin Wood’s so-called Yellow Paper.

I hope you have enjoyed this walk through an Ethereum smart contract. If you would like to learn more, please check out my next article, “Getting started with Go Ethereum”, or have a look at my book: Building Ethereum Dapps.

I am planning to write more on Ethereum and programming on Medium — Please ‘Follow’ me!

--

--

Roberto Infante
Roberto Infante

Written by Roberto Infante

Quantitative developer, passionate about latest tech. Author of Building Ethereum Dapps and LangChain in Action (Manning Publications).

Responses (1)