Published in

0xCODE

# The Ethereum Virtual Machine (EVM) Runtime Environment

The EVM (Ethereum Virtual Machine) provides an operating system runtime environment on the Ethereum blockchain. Solidity code in a smart contract must undergo translation from high-level human readable code to low-level machine readable code. This requires converting text to hexadecimal values which translate code to bytecode. The bytecode is generated by a compiler. The bytecode is then processed by the EVM and executed on the network. The EVM can be built on top of an FPGA (Field Programmable Array) or stack-based CPU. It provides a layer of abstraction that allows portability of the code across a distributed platform (e.g. Ethereum network).

The EVM is an example of what is called a Stack Machine. Just like in other stack-based programming languages, the LAST input you put in is the FIRST one you take out. This is the concept of Last In First Out (LIFO). It uses a Zero Address Format instruction set where the operands are always in a known location. This does not require addresses in registers since the values in the stack are temporary. Thus when an operation is performed, the values at the top of the stack are “popped” and the resulting value is “pushed” back into the stack. Another term for this is Reverse Polish Notation.

Let’s take the following example.

`x = 12 + 4 * 5 `

x is equal to the product of 4 and 5 added to 12, following the PEMDAS principle.

Using the LIFO concept, it is read much differently by a stack machine. In this case, the equation would look like this example.

`x = 4 5 * 12 +`

The way this is read from the call stack would be:

Take the values 4 and 5 then multiply, pop the values off the stack and then put the resulting product to the top of the stack. Then take the product and the value 12 to get the sum of x, then pop the values off the stack. Push the sum x back to the top of the stack

In both cases the result we get for this operation is 32. The act of putting data into the call stack uses what is called the PUSH method, while removing data is called the POP method.

Compiling the code from human readable ASCII characters to machine readable hexadecimal characters is just the first step. Next, the machine code must execute what are called opcodes. The opcode or operation code is what tells the computer what operations to perform. We have the operands, our data to which actions depend on what the operators will perform.

This is a simple smart contract that performs an escrow function.

`pragma solidity ^0.5.1;contract Escrow {        address agent;        mapping(address => uint256) public deposits;        modifier onlyAgent() {         require(msg.sender == agent);        _;    }        constructor () public {        agent = msg.sender;    }        function deposit(address payee) public onlyAgent payable {        uint256 amount = msg.value;        deposits[payee] = deposits[payee] + amount;    }        function withdraw(address payable payee) public onlyAgent {        uint256 payment = deposits[payee];        deposits[payee] = 0;        payee.transfer(payment);    }}`

The following is an example of the bytecode that was generated from the code after compilation.

`{ "linkReferences": {}, "object": "608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506103ac806100606000396000f3fe608060405260043610610051576000357c01000000000000000000000000000000000000000000000000000000009004806351cff8d914610056578063f340fa01146100a7578063fc7e286d146100eb575b600080fd5b34801561006257600080fd5b506100a56004803603602081101561007957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610150565b005b6100e9600480360360208110156100bd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061027f565b005b3480156100f757600080fd5b5061013a6004803603602081101561010e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610368565b6040518082815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156101ab57600080fd5b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561027a573d6000803e3d6000fd5b505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156102da57600080fd5b600034905080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050565b6001602052806000526040600020600091509050548156fea165627a7a72305820d6fa1114b349521b18dd6efdd04f06c882f1f7984c04829d2400baec88dc76950029", "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLER PUSH1 0x0 DUP1 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP PUSH2 0x3AC DUP1 PUSH2 0x60 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x51 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x51CFF8D9 EQ PUSH2 0x56 JUMPI DUP1 PUSH4 0xF340FA01 EQ PUSH2 0xA7 JUMPI DUP1 PUSH4 0xFC7E286D EQ PUSH2 0xEB JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x62 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xA5 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x79 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x150 JUMP JUMPDEST STOP JUMPDEST PUSH2 0xE9 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0xBD JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x27F JUMP JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xF7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x13A PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x10E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x368 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 DUP1 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0x1AB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x8FC DUP3 SWAP1 DUP2 ISZERO MUL SWAP1 PUSH1 0x40 MLOAD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP9 DUP9 CALL SWAP4 POP POP POP POP ISZERO DUP1 ISZERO PUSH2 0x27A JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0x2DA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 CALLVALUE SWAP1 POP DUP1 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD ADD PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP POP POP JUMP JUMPDEST PUSH1 0x1 PUSH1 0x20 MSTORE DUP1 PUSH1 0x0 MSTORE PUSH1 0x40 PUSH1 0x0 KECCAK256 PUSH1 0x0 SWAP2 POP SWAP1 POP SLOAD DUP2 JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 0xd6 STATICCALL GT EQ 0xb3 0x49 MSTORE SHL XOR 0xdd PUSH15 0xFDD04F06C882F1F7984C04829D2400 0xba 0xec DUP9 0xdc PUSH23 0x9500290000000000000000000000000000000000000000 ", "sourceMap": "56:676:0:-;;;331:57;8:9:-1;5:2;;;30:1;27;20:12;5:2;331:57:0;371:10;363:5;;:18;;;;;;;;;;;;;;;;;;56:676;;;;;;"}`

The following are the opcodes generated for this smart contract.

`PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x51 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x51CFF8D9 EQ PUSH2 0x56 JUMPI DUP1 PUSH4 0xF340FA01 EQ PUSH2 0xA7 JUMPI DUP1 PUSH4 0xFC7E286D EQ PUSH2 0xEB JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x62 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xA5 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x79 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x150 JUMP JUMPDEST STOP JUMPDEST PUSH2 0xE9 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0xBD JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x27F JUMP JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xF7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x13A PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x10E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x368 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 DUP1 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0x1AB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x8FC DUP3 SWAP1 DUP2 ISZERO MUL SWAP1 PUSH1 0x40 MLOAD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP9 DUP9 CALL SWAP4 POP POP POP POP ISZERO DUP1 ISZERO PUSH2 0x27A JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO ISZERO PUSH2 0x2DA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 CALLVALUE SWAP1 POP DUP1 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD ADD PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP POP POP JUMP JUMPDEST PUSH1 0x1 PUSH1 0x20 MSTORE DUP1 PUSH1 0x0 MSTORE PUSH1 0x40 PUSH1 0x0 KECCAK256 PUSH1 0x0 SWAP2 POP SWAP1 POP SLOAD DUP2 JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 0xd6 STATICCALL GT EQ 0xb3 0x49 MSTORE SHL XOR 0xdd PUSH15 0xFDD04F06C882F1F7984C04829D2400 0xba 0xec DUP9 0xdc PUSH23 0x9500290000000000000000000000000000000000000000`

The opcode are assembly language commands that are executed by the CPU. In fact, developers can use assembly instead of high-level programming code to achieve the same purpose but it is much more complicated. The ease of use and friendly UI from an IDE is much better and probably less time consuming for most developers. I will not explain the assembly language code any further since that in itself is another lesson.

The smart contract is going to be deployed on the blockchain, which is a distributed and decentralized network. The ABI (Application Binary Interface) provides a standard way to interact with the smart contract over the network. It allows for both external apps and contract-to-contract interaction. Developers use the ABI in their apps or DApps (Decentralized Applications) to access the methods and functions in the smart contract.

`[ {  "constant": false,  "inputs": [   {    "name": "payee",    "type": "address"   }  ],  "name": "withdraw",  "outputs": [],  "payable": false,  "stateMutability": "nonpayable",  "type": "function" }, {  "constant": false,  "inputs": [   {    "name": "payee",    "type": "address"   }  ],  "name": "deposit",  "outputs": [],  "payable": true,  "stateMutability": "payable",  "type": "function" }, {  "constant": true,  "inputs": [   {    "name": "",    "type": "address"   }  ],  "name": "deposits",  "outputs": [   {    "name": "",    "type": "uint256"   }  ],  "payable": false,  "stateMutability": "view",  "type": "function" }, {  "inputs": [],  "payable": false,  "stateMutability": "nonpayable",  "type": "constructor" }]`

When the smart contract is deployed to the blockchain, the EVM will execute the compiled code’s opcodes in the bytecode. If the function requires a change in the blockchain’s state, a unit of computation called gas (measured in wei) will be charged to the contract owner. These costs follow the Ethereum protocol which requires expending a cost for computation across the network, which are the fees that are paid to the miners who will verify the transaction that is put into a block. Simple call functions, which do not require any change to the state of the blockchain, do not expend gas and are therefore free. An example of this would be a balance inquiry call on a stored value in a smart contract.

In terms of cost, storing data on the stack using the PUSH method is the cheapest. This is followed by the MSTORE method, which stores data in the RAM (system memory). In both methods, since the data values are temporary, they are not persistent on the blockchain. It becomes persistent when using the SSTORE method, which stores the data on the disk storage. The SSTORE method is also the most expensive because it stores persistent data on the blockchain.

Now back to the smart contract details from this example. When the smart contract was deployed and executed by the EVM, it now resides on the blockchain. It will become immutable and at the same time transparent, meaning it cannot be directly changed and it is viewable by the public. The smart contract is also assigned with its own address. In this example it is:

0x692a70d2e424a56d2c6c27aa97d1a86395877b3a

This smart contract was deployed on a test system, but if the smart contract were deployed to the mainnet on the Ethereum blockchain, it can be searched using the block explorer. This contains more details about the smart contract, including the balance, ether value and the public address of the contract creator. All the transactions are also listed and searchable by their transaction hash value.

This diagram illustrates the EVM in relation to the Ethereum network architecture.

--

--

--

## More from 0xCODE

Essays and Articles on software engineering, development and computer science.

## Vincent Tabora

Editor HD-PRO, DevOps Trusterras (Cybersecurity, Blockchain, Software Development, Engineering, Photography, Technology)