What is EVM?
EVM is the runtime for the Ethereum blockchain. Allows you to run smart contract code by compiling to EVM bytecode.
Basics: Solidity → Bytecode → Opcode
As you know, Solidity code must be compiled into bytecode before being deployed on the Ethereum network. This bytecode corresponds to a series of opcode instructions that the EVM interprets.
Source: a file written in a programming language such as Java, Solidity.
Bytecode: compiled from source code and run on virtual machine like JVM, EVM.
machine code: code that only the operating system can read. The bytecode is converted to machine code and finally executed.
To efficiently store opcodes, they are encoded into bytecode. Each opcode is allocated a byte (for example, STOP – 0x00). Let’s look at the following bytecode: 0x6001600101
At run time, the bytecode is split into bytes (1 byte is equal to 2 hexadecimal characters). Bytes in the range 0x60-0x7f (PUSH1-PUSH32) are treated differently because they include push data (which must be appended to the opcode, not treated as a separate opcode).
The first instruction is 0x60, which translates to PUSH1. Therefore, we know that the push data is 1 byte long and push the next byte onto the stack. Now there is 1 element on the stack and we can move on to the next instruction. Since we know that 0x01 is part of the PUSH instruction, the next instruction we need to execute is another 0x60 (PUSH1) instruction along with the same data. Now there are 2 identical elements in the stack. The last instruction is 0x01, which translates to ADD. This instruction takes 2 elements from the stack and pushes the sum of these elements onto the stack. There is now one element on the stack: 0x02.
You can divide all opcodes into the following categories:
1) Stack management operation codes (POP, PUSH, DUP, SWAP);
2) Arithmetic operations / comparison / bitwise operation codes (ADD, SUB, GT, LT, AND, OR);
3) Environment operation codes (CALLER, CALLVALUE, NUMBER);
4) Operation codes that control memory (MLOAD, MSTORE, MSTORE8, MSIZE);
5) Memory management operation codes (SLOAD, SSTORE);
6) Operation codes related to the program counter (JUMP, JUMPI, PC, JUMPDEST);
7) Stop operation codes (STOP, RETURN, REVERT, INVALID, SELFDESTRUCT).
The EVM uses a stack based architecture. The word size (that is, the size of the data element on the stack) is 256 bits (32 bytes). This is done to make it easier to perform 256-bit Keccak hash and elliptic curve calculations. Its memory model is based on addressable byte arrays. The maximum stack depth is 1024. The EVM also has an independent storage model; it is similar to memory, but is not an array of bytes, but an array of words based on word addressing. A store is a persistent key and value store that is maintained as part of the system state (persistent store in a Merkle tree). All data in memory and storage will be initialized to 0. The EVM is not a standard von Neumann structure. Program code is stored in an independent virtual ROM that can only interact with specific instructions, rather than in shared memory or storage.
Why is gas needed?
Gas fees help keep the Ethereum network secure. By charging a fee for every computation performed on the network, we prevent attackers from spamming the network. To avoid random or hostile infinite loops or other computational waste in code, each transaction must set a limit on the number of computational code execution steps it can use. The basic unit of calculation is “gas”.
Although the transaction includes a limit, any gas not used in the transaction is returned to the user (i.e. max fee – (base fee + tip) is returned).
Types of Ethereum Accounts
Externally owned – controlled by someone who has a private key.
contract – a smart contract deployed on the network, controlled by code.
Both types of accounts have the ability to:
1) Receive, store and send ETH and tokens;
2) Interact with deployed smart contracts.
1) Creating an account costs nothing;
2) Can initiate transactions;
3) Transactions between Externally-owned can only be transfers of ETH / tokens.
1) Creating a contract requires a cost because network storage is used;
2) Can only send transactions in response to received transactions;
3) Transactions from an Externally-owned account to a Contract account can run code that can perform many different actions, such as transferring tokens or even creating a new contract.
Create an account
The EVM handles addresses that are 160 bits long.
An account consists of a cryptographic key pair: public and private. The public key is generated from the private key using the ECDSA algorithm.
The public address of the Externally-owned account is formed as follows – the last 20 bytes from Keccak-256(public key) are taken and 0x is added to the beginning.
The Contract address is usually specified when the contract is deployed on the Ethereum blockchain. The address is formed from the Externally-owned address of the creator and the number of transactions sent from this address (“nonce”). Last 20 bytes from Keccak-256(RLP(Externally-owned; nonce)).
About RLP: https://eth.wiki/fundamentals/rlp
Screenshots of formulas from Ethereum Yellow Paper: https://ethereum.github.io/yellowpaper/paper.pdf
What’s Included in Each Type of Account
Each account consists of balance, nonce, bytecode and stored data (storage). However, there are some differences between the two types of accounts. For example, External-owned has empty bytecode and storage fields, while Contract stores its bytecode and the root Merkle hash of the entire state tree. Moreover, while External-owned have a corresponding private key, Contract does not. The actions of Contract accounts are controlled by code.