├── LICENSE
├── README.md
├── gas.md
├── precompiles.md
└── update_log.md
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 wolflo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EVM Opcodes
2 | Opcode costs are drawn from the [Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf), the [Jello Paper](https://jellopaper.org/evm/), and the [geth](https://github.com/ethereum/go-ethereum) implementation.
3 | This is intended to be an accessible reference, but it is informal and does not address opcode semantics.
4 | If you want to be certain of correctness and aware of every edge case, I would suggest using the Jello Paper or a client implementation.
5 | If you are looking for an informal reference with more information about opcode semantics, try [evm.codes](https://www.evm.codes/).
6 |
7 | For operations with dynamic gas costs, see [gas.md](gas.md).
8 |
9 | ### Notation
10 | * `a, b` => `a + b` indicates that the `ADD` opcode takes two items off the stack (`a` and `b`) and places the sum of these two values on the stack. The leftmost item (`a`) is the top of the stack.
11 | * All stack descriptions elide subsequent items that may be on the stack. It can be assumed that unspecified stack elements do not influence the semantics of an operation, except when a stack overflow would result.
12 | * The maximum stack size is 1024 items, and all stack items are 32 bytes.
13 | * `a // b` indicates flooring division. The result of division by 0 in the EVM is 0.
14 | * All arithmetic operations are modulo 2\*\*256.
15 | * Including the designated `INVALID` opcode, the EVM currently implements 141 opcodes, 65 of which are duplicates indicating the number of operands (`PUSHn`, `DUPn`, `SWAPn`, `LOGn`).
16 |
17 | #
18 | | Hex | Name | Gas | Stack | Mem / Storage | Notes |
19 | | :---: | :--- | :---: | :--- | :--- | :--- |
20 | | | | | top, bottom| | |
21 | 00 | STOP | 0 | | || halt execution
22 | 01 | ADD | 3 | `a, b` => `a + b` || (u)int256 addition modulo 2\*\*256
23 | 02 | MUL | 5 | `a, b` => `a * b` || (u)int256 multiplication modulo 2\*\*256
24 | 03 | SUB | 3 | `a, b` => `a - b` || (u)int256 addition modulo 2\*\*256
25 | 04 | DIV | 5 | `a, b` => `a // b` || uint256 division
26 | 05 | SDIV | 5 | `a, b` => `a // b` || int256 division
27 | 06 | MOD | 5 | `a, b` => `a % b` || uint256 modulus
28 | 07 | SMOD | 5 | `a, b` => `a % b` || int256 modulus
29 | 08 | ADDMOD | 8 | `a, b, N` => `(a + b) % N` || (u)int256 addition modulo N
30 | 09 | MULMOD | 8 | `a, b, N` => `(a * b) % N` || (u)int256 multiplication modulo N
31 | 0A | EXP |[A1](gas.md#a1-exp)| `a, b` => `a ** b` || uint256 exponentiation modulo 2\*\*256
32 | 0B | SIGNEXTEND | 5 | `b, x` => `SIGNEXTEND(x, b)` || [sign extend](https://en.wikipedia.org/wiki/Sign_extension) `x` from `(b+1)` bytes to 32 bytes
33 | 0C-0F | *invalid*
34 | 10 | LT | 3 | `a, b` => `a < b` || uint256 less-than
35 | 11 | GT | 3 | `a, b` => `a > b` || uint256 greater-than
36 | 12 | SLT | 3 | `a, b` => `a < b` || int256 less-than
37 | 13 | SGT | 3 | `a, b` => `a > b` || int256 greater-than
38 | 14 | EQ | 3 | `a, b` => `a == b` || (u)int256 equality
39 | 15 | ISZERO | 3 | `a` => `a == 0` || (u)int256 iszero
40 | 16 | AND | 3 | `a, b` => `a && b` || bitwise AND
41 | 17 | OR | 3 | `a, b` => `a \|\| b` || bitwise OR
42 | 18 | XOR | 3 | `a, b` => `a ^ b` || bitwise XOR
43 | 19 | NOT | 3 | `a` => `~a` || bitwise NOT
44 | 1A | BYTE | 3 | `i, x` => `(x >> (248 - i * 8)) && 0xFF` || `i`th byte of (u)int256 `x`, from the left
45 | 1B | SHL | 3 | `shift, val` => `val << shift` || shift left
46 | 1C | SHR | 3 | `shift, val` => `val >> shift` || logical shift right
47 | 1D | SAR | 3 | `shift, val` => `val >> shift` || arithmetic shift right
48 | 1E-1F | *invalid*
49 | 20 | SHA3 |[A2](gas.md#a2-sha3)| `ost, len` => `keccak256(mem[ost:ost+len])` || keccak256
50 | 21-2F | *invalid*
51 | 30 | ADDRESS | 2 | `.` => `address(this)` || address of executing contract
52 | 31 | BALANCE |[A5](gas.md#a5-balance-extcodesize-extcodehash)| `addr` => `addr.balance` || balance, in wei
53 | 32 | ORIGIN | 2 | `.` => `tx.origin` || address that originated the tx
54 | 33 | CALLER | 2 | `.` => `msg.sender` || address of msg sender
55 | 34 | CALLVALUE | 2 | `.` => `msg.value` || msg value, in wei
56 | 35 | CALLDATALOAD | 3 | `idx` => `msg.data[idx:idx+32]` || read word from msg data at index `idx`
57 | 36 | CALLDATASIZE | 2 | `.` => `len(msg.data)` || length of msg data, in bytes
58 | 37 | CALLDATACOPY |[A3](gas.md#a3-copy-operations)| `dstOst, ost, len` => `.` | mem[dstOst:dstOst+len] := msg.data[ost:ost+len | copy msg data
59 | 38 | CODESIZE | 2 | `.` => `len(this.code)` || length of executing contract's code, in bytes
60 | 39 | CODECOPY |[A3](gas.md#a3-copy-operations)| `dstOst, ost, len` => `.` || mem[dstOst:dstOst+len] := this.code[ost:ost+len] | copy executing contract's bytecode
61 | 3A | GASPRICE | 2 | `.` => `tx.gasprice` || gas price of tx, in wei per unit gas [\*\*](https://github.com/ethereum/EIPs/blob/0341984ff14c8ce398f6d2b3e009c07cd99df8eb/EIPS/eip-1559.md#gasprice)
62 | 3B | EXTCODESIZE |[A5](gas.md#a5-balance-extcodesize-extcodehash)| `addr` => `len(addr.code)` || size of code at addr, in bytes
63 | 3C | EXTCODECOPY |[A4](gas.md#a4-extcodecopy)|`addr, dstOst, ost, len` => `.` | mem[dstOst:dstOst+len] := addr.code[ost:ost+len] | copy code from `addr`
64 | 3D |RETURNDATASIZE | 2 | `.` => `size` || size of returned data from last external call, in bytes
65 | 3E |RETURNDATACOPY |[A3](gas.md#a3-copy-operations)| `dstOst, ost, len` => `.` | mem[dstOst:dstOst+len] := returndata[ost:ost+len] | copy returned data from last external call
66 | 3F | EXTCODEHASH |[A5](gas.md#a5-balance-extcodesize-extcodehash)| `addr` => `hash` || hash = addr.exists ? keccak256(addr.code) : 0
67 | 40 | BLOCKHASH | 20 | `blockNum` => `blockHash(blockNum)` ||
68 | 41 | COINBASE | 2 | `.` => `block.coinbase` || address of miner of current block
69 | 42 | TIMESTAMP | 2 | `.` => `block.timestamp` || timestamp of current block
70 | 43 | NUMBER | 2 | `.` => `block.number` || number of current block
71 | 44 | DIFFICULTY | 2 | `.` => `block.difficulty` || difficulty of current block
72 | 45 | GASLIMIT | 2 | `.` => `block.gaslimit` || gas limit of current block
73 | 46 | CHAINID | 2 | `.` => `chain_id` || push current [chain id](https://eips.ethereum.org/EIPS/eip-155) onto stack
74 | 47 | SELFBALANCE | 5 | `.` => `address(this).balance` || balance of executing contract, in wei
75 | 48 | BASEFEE | 2 | `.` => `block.basefee` || base fee of current block
76 | 49-4F | *invalid*
77 | 50 | POP | 2 | `_anon` => `.` || remove item from top of stack and discard it
78 | 51 | MLOAD |3[\*](gas.md#a0-1-memory-expansion)| `ost` => `mem[ost:ost+32]` || read word from memory at offset `ost`
79 | 52 | MSTORE |3[\*](gas.md#a0-1-memory-expansion)| `ost, val` => `.` | mem[ost:ost+32] := val | write a word to memory
80 | 53 | MSTORE8 |3[\*](gas.md#a0-1-memory-expansion)| `ost, val` => `.` | mem[ost] := val && 0xFF | write a single byte to memory
81 | 54 | SLOAD |[A6](gas.md#a6-sload)| `key` => `storage[key]` || read word from storage
82 | 55 | SSTORE |[A7](gas.md#a7-sstore) | `key, val` => `.` | storage[key] := val | write word to storage
83 | 56 | JUMP | 8 | `dst` => `.` || `$pc := dst`
84 | 57 | JUMPI | 10 | `dst, condition` => `.` || `$pc := condition ? dst : $pc + 1`
85 | 58 | PC | 2 | `.` => `$pc` || program counter
86 | 59 | MSIZE | 2 | `.` => `len(mem)` || size of memory in current execution context, in bytes
87 | 5A | GAS | 2 | `.` => `gasRemaining` ||
88 | 5B | JUMPDEST | 1 | || mark valid jump destination
89 | 5C-5F | *invalid*
90 | 60 | PUSH1 | 3 | `.` => `uint8` || push 1-byte value onto stack
91 | 61 | PUSH2 | 3 | `.` => `uint16` || push 2-byte value onto stack
92 | 62 | PUSH3 | 3 | `.` => `uint24` || push 3-byte value onto stack
93 | 63 | PUSH4 | 3 | `.` => `uint32` || push 4-byte value onto stack
94 | 64 | PUSH5 | 3 | `.` => `uint40` || push 5-byte value onto stack
95 | 65 | PUSH6 | 3 | `.` => `uint48` || push 6-byte value onto stack
96 | 66 | PUSH7 | 3 | `.` => `uint56` || push 7-byte value onto stack
97 | 67 | PUSH8 | 3 | `.` => `uint64` || push 8-byte value onto stack
98 | 68 | PUSH9 | 3 | `.` => `uint72` || push 9-byte value onto stack
99 | 69 | PUSH10 | 3 | `.` => `uint80` || push 10-byte value onto stack
100 | 6A | PUSH11 | 3 | `.` => `uint88` || push 11-byte value onto stack
101 | 6B | PUSH12 | 3 | `.` => `uint96` || push 12-byte value onto stack
102 | 6C | PUSH13 | 3 | `.` => `uint104` || push 13-byte value onto stack
103 | 6D | PUSH14 | 3 | `.` => `uint112` || push 14-byte value onto stack
104 | 6E | PUSH15 | 3 | `.` => `uint120` || push 15-byte value onto stack
105 | 6F | PUSH16 | 3 | `.` => `uint128` || push 16-byte value onto stack
106 | 70 | PUSH17 | 3 | `.` => `uint136` || push 17-byte value onto stack
107 | 71 | PUSH18 | 3 | `.` => `uint144` || push 18-byte value onto stack
108 | 72 | PUSH19 | 3 | `.` => `uint152` || push 19-byte value onto stack
109 | 73 | PUSH20 | 3 | `.` => `uint160` || push 20-byte value onto stack
110 | 74 | PUSH21 | 3 | `.` => `uint168` || push 21-byte value onto stack
111 | 75 | PUSH22 | 3 | `.` => `uint176` || push 22-byte value onto stack
112 | 76 | PUSH23 | 3 | `.` => `uint184` || push 23-byte value onto stack
113 | 77 | PUSH24 | 3 | `.` => `uint192` || push 24-byte value onto stack
114 | 78 | PUSH25 | 3 | `.` => `uint200` || push 25-byte value onto stack
115 | 79 | PUSH26 | 3 | `.` => `uint208` || push 26-byte value onto stack
116 | 7A | PUSH27 | 3 | `.` => `uint216` || push 27-byte value onto stack
117 | 7B | PUSH28 | 3 | `.` => `uint224` || push 28-byte value onto stack
118 | 7C | PUSH29 | 3 | `.` => `uint232` || push 29-byte value onto stack
119 | 7D | PUSH30 | 3 | `.` => `uint240` || push 30-byte value onto stack
120 | 7E | PUSH31 | 3 | `.` => `uint248` || push 31-byte value onto stack
121 | 7F | PUSH32 | 3 | `.` => `uint256` || push 32-byte value onto stack
122 | 80 | DUP1 | 3 | `a` => `a, a` || clone 1st value on stack
123 | 81 | DUP2 | 3 | `_, a` => `a, _, a` || clone 2nd value on stack
124 | 82 | DUP3 | 3 | `_, _, a` => `a, _, _, a` || clone 3rd value on stack
125 | 83 | DUP4 | 3 | `_, _, _, a` => `a, _, _, _, a` || clone 4th value on stack
126 | 84 | DUP5 | 3 | `..., a` => `a, ..., a` || clone 5th value on stack
127 | 85 | DUP6 | 3 | `..., a` => `a, ..., a` || clone 6th value on stack
128 | 86 | DUP7 | 3 | `..., a` => `a, ..., a` || clone 7th value on stack
129 | 87 | DUP8 | 3 | `..., a` => `a, ..., a` || clone 8th value on stack
130 | 88 | DUP9 | 3 | `..., a` => `a, ..., a` || clone 9th value on stack
131 | 89 | DUP10 | 3 | `..., a` => `a, ..., a` || clone 10th value on stack
132 | 8A | DUP11 | 3 | `..., a` => `a, ..., a` || clone 11th value on stack
133 | 8B | DUP12 | 3 | `..., a` => `a, ..., a` || clone 12th value on stack
134 | 8C | DUP13 | 3 | `..., a` => `a, ..., a` || clone 13th value on stack
135 | 8D | DUP14 | 3 | `..., a` => `a, ..., a` || clone 14th value on stack
136 | 8E | DUP15 | 3 | `..., a` => `a, ..., a` || clone 15th value on stack
137 | 8F | DUP16 | 3 | `..., a` => `a, ..., a` || clone 16th value on stack
138 | 90 | SWAP1 | 3 | `a, b` => `b, a` ||
139 | 91 | SWAP2 | 3 | `a, _, b` => `b, _, a` ||
140 | 92 | SWAP3 | 3 | `a, _, _, b` => `b, _, _, a` ||
141 | 93 | SWAP4 | 3 | `a, _, _, _, b` => `b, _, _, _, a` ||
142 | 94 | SWAP5 | 3 | `a, ..., b` => `b, ..., a` ||
143 | 95 | SWAP6 | 3 | `a, ..., b` => `b, ..., a` ||
144 | 96 | SWAP7 | 3 | `a, ..., b` => `b, ..., a` ||
145 | 97 | SWAP8 | 3 | `a, ..., b` => `b, ..., a` ||
146 | 98 | SWAP9 | 3 | `a, ..., b` => `b, ..., a` ||
147 | 99 | SWAP10 | 3 | `a, ..., b` => `b, ..., a` ||
148 | 9A | SWAP11 | 3 | `a, ..., b` => `b, ..., a` ||
149 | 9B | SWAP12 | 3 | `a, ..., b` => `b, ..., a` ||
150 | 9C | SWAP13 | 3 | `a, ..., b` => `b, ..., a` ||
151 | 9D | SWAP14 | 3 | `a, ..., b` => `b, ..., a` ||
152 | 9E | SWAP15 | 3 | `a, ..., b` => `b, ..., a` ||
153 | 9F | SWAP16 | 3 | `a, ..., b` => `b, ..., a` ||
154 | A0 | LOG0 |[A8](gas.md#a8-log-operations)| `ost, len` => `.` || LOG0(memory[ost:ost+len])
155 | A1 | LOG1 |[A8](gas.md#a8-log-operations)| `ost, len, topic0` => `.` || LOG1(memory[ost:ost+len], topic0)
156 | A2 | LOG2 |[A8](gas.md#a8-log-operations)| `ost, len, topic0, topic1` => `.` || LOG1(memory[ost:ost+len], topic0, topic1)
157 | A3 | LOG3 |[A8](gas.md#a8-log-operations)| `ost, len, topic0, topic1, topic2` => `.` || LOG1(memory[ost:ost+len], topic0, topic1, topic2)
158 | A4 | LOG4 |[A8](gas.md#a8-log-operations)| `ost, len, topic0, topic1, topic2, topic3` => `.` || LOG1(memory[ost:ost+len], topic0, topic1, topic2, topic3)
159 | A5-EF | *invalid*
160 | F0 | CREATE |[A9](gas.md#a9-create-operations)| `val, ost, len` => `addr` || addr = keccak256(rlp\_encode([address(this), this.nonce]))
161 | F1 | CALL |[AA](gas.md#aa-call-operations)| gas, addr, val, argOst, argLen, retOst, retLen
=> `success` | mem[retOst:retOst+retLen] := returndata |
162 | F2 | CALLCODE |[AA](gas.md#aa-call-operations)| `gas, addr, val, argOst, argLen, retOst, retLen` => `success` | mem[retOst:retOst+retLen] = returndata | same as DELEGATECALL, but does not propagate original msg.sender and msg.value
163 | F3 | RETURN |0[\*](gas.md#a0-1-memory-expansion)| `ost, len` => `.` || return mem[ost:ost+len]
164 | F4 | DELEGATECALL |[AA](gas.md#aa-call-operations)| `gas, addr, argOst, argLen, retOst, retLen`
=> `success` | mem[retOst:retOst+retLen] := returndata |
165 | F5 | CREATE2 |[A9](gas.md#a9-create-operations)| `val, ost, len, salt` => `addr` || addr = keccak256(0xff ++ address(this) ++ salt ++ keccak256(mem[ost:ost+len]))[12:]
166 | F6-F9 | *invalid*
167 | FA | STATICCALL |[AA](gas.md#aa-call-operations)| `gas, addr, argOst, argLen, retOst, retLen` => `success` | mem[retOst:retOst+retLen] := returndata |
168 | FB-FC | *invalid*
169 | FD | REVERT |0[\*](gas.md#a0-1-memory-expansion)| `ost, len` => `.` || revert(mem[ost:ost+len])
170 | FE | INVALID |[AF](gas.md#af-invalid) ||| designated invalid opcode - [EIP-141](https://eips.ethereum.org/EIPS/eip-141)
171 | FF | SELFDESTRUCT |[AB](gas.md#ab-selfdestruct)| `addr` => `.` ||| destroy contract and sends all funds to `addr`
172 |
--------------------------------------------------------------------------------
/gas.md:
--------------------------------------------------------------------------------
1 | # Appendix - Dynamic Gas Costs
2 |
3 | ### A0-0: Intrinsic Gas
4 | Intrinsic gas is the amount of gas paid prior to execution of a transaction.
5 | That is, the gas paid by the initiator of a transaction, which will always be an externally-owned account, before any state updates are made or any code is executed.
6 |
7 | Gas Calculation:
8 | - `gas_cost = 21000`: base cost
9 | - **If** `tx.to == null` (contract creation tx):
10 | - `gas_cost += 32000`
11 | - `gas_cost += 4 * bytes_zero`: gas added to base cost for every zero byte of memory data
12 | - `gas_cost += 16 * bytes_nonzero`: gas added to base cost for every nonzero byte of memory data
13 |
14 | ### A0-1: Memory Expansion
15 | An additional gas cost is paid by any operation that expands the memory that is in use.
16 | This memory expansion cost is dependent on the existing memory size and is `0` if the operation does not reference a memory address higher than the existing highest referenced memory address.
17 | A reference is any read, write, or other usage of memory (such as in a `CALL`).
18 |
19 | Terms:
20 | - `new_mem_size`: the highest referenced memory address after the operation in question (in bytes)
21 | - `new_mem_size_words = (new_mem_size + 31) // 32`: number of (32-byte) words required for memory after the operation in question
22 | - Cmem(machine_state)
: the memory cost function for a given machine state
23 |
24 | Gas Calculation:
25 | - gas\_cost = Cmem(new_state) - Cmem(old_state)
26 | - gas\_cost = (new\_mem\_size\_words ^ 2 // 512) + (3 * new\_mem\_size\_words) - Cmem(old_state)
27 |
28 | Useful Notes:
29 | - The following opcodes incur a memory expansion cost in addition to their otherwise static gas cost: `RETURN`, `REVERT`, `MLOAD`, `MSTORE`, `MSTORE8`.
30 | - Referencing a zero length range does not require memory to be extended to the beginning of the range.
31 | - The memory cost function is linear up to 724 bytes of memory used, at which point additional memory costs substantially more.
32 |
33 | ### A0-2: Access Sets
34 | As of [EIP-2929](https://eips.ethereum.org/EIPS/eip-2929), two transaction-wide access sets are maintained.
35 | These access sets keep track of which addresses and storage slots have already been touched within the current transaction.
36 |
37 | - `touched_addresses : Set[Address]`
38 | - a set where every element is an address
39 | - initialized to include `tx.origin`, `tx.to`\*, and all precompiles
40 | - \* For a contract creation transaction, `touched_addresses` is initialized to include the address of the created contract instead of `tx.to`, which is the zero address.
41 | - `touched_storage_slots : Set[(Address, Bytes32)]`
42 | - a set where every element is a tuple, `(address, storage_key)`
43 | - initialized to the empty set, `{}`
44 |
45 | The access sets above are relevant for the following operations:
46 | - `ADDRESS_TOUCHING_OPCODES := { EXTCODESIZE, EXTCODECOPY, EXTCODEHASH, BALANCE, CALL, CALLCODE, DELEGATECALL, STATICCALL, SELFDESTRUCT }`
47 | - `STORAGE_TOUCHING_OPCODES := { SLOAD, SSTORE }`
48 |
49 | #### Updating the Access Sets
50 |
51 | When an address is the target of one of the `ADDRESS_TOUCHING_OPCODES`, the address is immediately added to the `touched_addresses` set.
52 |
53 | - touched addresses = touched_addresses ∪ { target_address }
54 |
55 | When a storage slot is the target of one of the `STORAGE_TOUCHING_OPCODES`, the `(address, key)` pair is immediately added to the `touched_storage_slots` set.
56 |
57 | - touched_storage_slots = touched_storage_slots ∪ { (current_address, target_storage_key) }
58 |
59 | Important Notes:
60 | - Adding duplicate elements to these sets is a no-op. Performant implementations will use a map with more complicated addition logic.
61 | - If an execution frame reverts, the access sets will return to the state they were in before the frame was entered.
62 | - Additions to the `touched_addresses` set for `*CALL` and `CREATE*` opcodes are made immediately *before* the new execution frames are entered, so any failure within a call or contract creation will not remove the target address of the failing `*CALL` or `CREATE*` from the `touched_addresses` set.
63 | Some tricky edge cases:
64 | - For `*CALL`, if the call fails for exceeding the maximum call depth or attempting to send more value than the balance of the current address, the target address remains in the `touched_addresses` set.
65 | - For `CREATE*`, if the contract creation fails for exceeding the maximum call depth or attempting to send more value than the balance of the current address, the address of the created contract does **NOT** remain in the `touched_addresses` set.
66 | - If a `CREATE*` operation fails for attempting to deploy a contract to a non-empty account, the address of the created contract remains in the `touched_addresses` set.
67 |
68 | #### Pre-populating the Access Sets
69 |
70 | [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930) introduced an optional access *list* that can be included as part of a transaction.
71 | This access list allows elements to be added to the `touched_addresses` and `touched_storage_slots` access *sets* before execution of a transaction begins.
72 | The cost for doing so is `2400` gas for each address added to `touched_addresses` and `1900` gas for each `(address, storage_key)` pair added to `touched_storage_slots`.
73 | This cost is charged at the same time as [intrinsic gas](#a0-0-intrinsic-gas).
74 |
75 | Important Notes:
76 | - No `(ADDR, storage_key)` pair can be added to `touched_storage_slots` without also adding `ADDR` to `touched_addresses`.
77 | - The access list may contain duplicates.
78 | The addition of a duplicate item to one of the access sets is a no-op, but the cost of addition is still charged.
79 | - Providing an access list with a transaction can yield a modest discount for each unique access, but this is not always the case.
80 | See [@fvictorio/gas-costs-after-berlin](https://hackmd.io/@fvictorio/gas-costs-after-berlin) for a more complete discussion.
81 |
82 | ### A0-3: Gas Refunds
83 | Originally intended to provide incentive for clearing unused state, the total `gas_refund` is tracked throughout the execution of a transaction.
84 | As of [EIP-3529](https://eips.ethereum.org/EIPS/eip-3529), `SSTORE` is the only operation that potentially provides a gas refund.
85 |
86 | The maximum refund for a transaction is capped at 1/5th the gas consumed for the entire transaction.
87 | ```
88 | refund_amt := min(gas_refund, tx.gas_consumed // 5)
89 | ```
90 | The gas consumed includes the [intrinsic gas](#a0-0-intrinsic-gas), the cost of [pre-populating](#pre-populating-the-access-sets) the access sets, and the cost of any code execution.
91 |
92 | When a transaction is finalized, the gas used by the transaction is decreased by `refund_amt`.
93 | This effectively reimburses refund_amt \* tx.gasprice
to `tx.origin`, but it has the added effect of decreasing the impact of the transaction on the total gas consumed in the block (for purposes of determining the block gas limit).
94 |
95 | Because the gas refund is not applied until the end of a transaction, a nonzero refund will not affect whether or not a transaction results in an `OUT_OF_GAS` exception.
96 |
97 | #
98 |
99 | ## A1: EXP
100 | Terms:
101 | - `byte_len_exponent`: the number of bytes in the exponent (exponent is `b` in the stack representation)
102 |
103 | Gas Calculation:
104 | - `gas_cost = 10 + 50 * byte_len_exponent`
105 |
106 |
107 | ## A2: SHA3
108 | Terms:
109 | - `data_size`: size of the message to hash in bytes (`len` in the stack representation)
110 | - `data_size_words = (data_size + 31) // 32`: number of (32-byte) words in the message to hash
111 | - `mem_expansion_cost`: the cost of any memory expansion required (see [A0-1](#a0-1-memory-expansion))
112 |
113 | Gas Calculation:
114 | - `gas_cost = 30 + 6 * data_size_words + mem_expansion_cost`
115 |
116 |
117 | ## A3: \*COPY Operations
118 | The following applies for the operations `CALLDATACOPY`, `CODECOPY`, and `RETURNDATACOPY` (not `EXTCODECOPY`).
119 |
120 | Terms:
121 | - `data_size`: size of the data to copy in bytes (`len` in the stack representation)
122 | - `data_size_words = (data_size + 31) // 32`: number of (32-byte) words in the data to copy
123 | - `mem_expansion_cost`: the cost of any memory expansion required (see [A0-1](#a0-1-memory-expansion))
124 |
125 | Gas Calculation:
126 | - `gas_cost = 3 + 3 * data_size_words + mem_expansion_cost`
127 |
128 |
129 | ## A4: EXTCODECOPY
130 |
131 | Terms:
132 | - `target_addr`: the address to copy code from (`addr` in the stack representation)
133 | - `access_cost`: The cost of accessing a warm vs. cold account (see [A0-2](#a0-2-access-sets))
134 | - `access_cost = 100` **if** `target_addr` **in** `touched_addresses` (warm access)
135 | - `access_cost = 2600` **if** `target_addr` **not in** `touched_addresses` (cold access)
136 | - `data_size`: size of the data to copy in bytes (`len` in the stack representation)
137 | - `data_size_words = (data_size + 31) // 32`: number of (32-byte) words in the data to copy
138 | - `mem_expansion_cost`: the cost of any memory expansion required (see [A0-1](#a0-1-memory-expansion))
139 |
140 | Gas Calculation:
141 | - `gas_cost = access_cost + 3 * data_size_words + mem_expansion_cost`
142 |
143 |
144 | ## A5: BALANCE, EXTCODESIZE, EXTCODEHASH
145 |
146 | The opcodes `BALANCE`, `EXTCODESIZE`, `EXTCODEHASH` have the same pricing function based on making a single account access.
147 | See [A0-2](#a0-2-access-sets) for details on EIP-2929 and `touched_addresses`.
148 |
149 | Terms:
150 | - `target_addr`: the address of interest (`addr` in the opcode stack representations)
151 |
152 | Gas Calculation:
153 | - `gas_cost = 100` **if** `target_addr` **in** `touched_addresses` (warm access)
154 | - `gas_cost = 2600` **if** `target_addr` **not in** `touched_addresses` (cold access)
155 |
156 |
157 | ## A6: SLOAD
158 |
159 | See [A0-2](#a0-2-access-sets) for details on EIP-2929 and `touched_storage_slots`.
160 |
161 | Terms:
162 | - `context_addr`: the address of the current execution context (i.e. what `ADDRESS` would put on the stack)
163 | - `target_storage_key`: The 32-byte storage index to load from (`key` in the stack representation)
164 |
165 | Gas Calculation:
166 | - `gas_cost = 100` **if** `(context_addr, target_storage_key)` **in** `touched_storage_slots` (warm access)
167 | - `gas_cost = 2100` **if** `(context_addr, target_storage_key)` **not in** `touched_storage_slots` (cold access)
168 |
169 |
170 | ## A7: SSTORE
171 | This gets messy.
172 | See [EIP-2200](https://eips.ethereum.org/EIPS/eip-2200), activated in the Istanbul hardfork.
173 |
174 | The cost of an `SSTORE` operation is dependent on the existing value and the value to be stored:
175 | 1. Zero vs. nonzero values - storing nonzero values is more costly than storing zero
176 | 1. The current value of the slot vs. the value to store - changing the value of a slot is more costly than not changing it
177 | 2. "Dirty" vs. "clean" slot - changing a slot that has not yet been changed within the current execution context is more costly than changing a slot that has already been changed
178 |
179 | The cost is also dependent on whether or not the targeted storage slot has already been accessed within the same transaction.
180 | See [A0-2](#a0-2-access-sets) for details on EIP-2929 and `touched_storage_slots`.
181 |
182 | Terms:
183 | - `context_addr`: the address of the current execution context (i.e. what `ADDRESS` would put on the stack)
184 | - `target_storage_key`: The 32-byte storage index to store to (`key` in the stack representation)
185 | - `orig_val`: the value of the storage slot if the current transaction is reverted
186 | - `current_val`: the value of the storage slot immediately *before* the `sstore` op in question
187 | - `new_val`: the value of the storage slot immediately *after* the `sstore` op in question
188 |
189 | Gas Calculation:
190 | - `gas_cost = 0`
191 | - `gas_refund = 0`
192 | - **If** `gas_left <= 2300`:
193 | - `throw OUT_OF_GAS_ERROR` (can not `sstore` with < 2300 gas for backwards compatibility)
194 | - **If** `(context_addr, target_storage_key)` **not in** `touched_storage_slots` ([cold access](#a0-2-access-sets)):
195 | - `gas_cost += 2100`
196 | - **If** `new_val == current_val` (no-op):
197 | - `gas_cost += 100`
198 | - **Else** `new_val != current_val`:
199 | - **If** `current_val == orig_val` ("clean slot", not yet updated in current execution context):
200 | - **If** `orig_val == 0` (slot started zero, currently still zero, now being changed to nonzero):
201 | - `gas_cost += 20000`
202 | - **Else** `orig_val != 0` (slot started nonzero, currently still same nonzero value, now being changed):
203 | - `gas_cost += 2900` and update the refund as follows..
204 | - **If** `new_val == 0` (the value to store is 0):
205 | - `gas_refund += 4800`
206 | - **Else** `current_val != orig_val` ("dirty slot", already updated in current execution context):
207 | - `gas_cost += 100` and update the refund as follows..
208 | - **If** `orig_val != 0` (execution context started with a nonzero value in slot):
209 | - **If** `current_val == 0` (slot started nonzero, currently zero, now being changed to nonzero):
210 | - `gas_refund -= 4800`
211 | - **Else if** `new_val == 0` (slot started nonzero, currently still nonzero, now being changed to zero):
212 | - `gas_refund += 4800`
213 | - **If** `new_val == orig_val` (slot is reset to the value it started with):
214 | - **If** `orig_val == 0` (slot started zero, currently nonzero, now being reset to zero):
215 | - `gas_refund += 19900`
216 | - **Else** `orig_val != 0` (slot started nonzero, currently different nonzero value, now reset to orig. nonzero value):
217 | - `gas_refund += 2800`
218 |
219 |
220 | ## A8: LOG\* Operations
221 | Note that for `LOG*` operations gas is paid per byte of data (not per word).
222 |
223 | Terms:
224 | - `num_topics`: the \* of the LOG\* op. e.g. LOG0 has `num_topics = 0`, LOG4 has `num_topics = 4`
225 | - `data_size`: size of the data to log in bytes (`len` in the stack representation).
226 | - `mem_expansion_cost`: the cost of any memory expansion required (see [A0-1](#a0-1-memory-expansion))
227 |
228 | Gas Calculation:
229 | - `gas_cost = 375 + 375 * num_topics + 8 * data_size + mem_expansion_cost`
230 |
231 |
232 | ## A9: CREATE\* Operations
233 |
234 | Common Terms:
235 | - `mem_expansion_cost`: the cost of any memory expansion required (see [A0-1](#a0-1-memory-expansion))
236 | - `code_deposit_cost`: the per-byte cost incurred for storing the deployed code (see [A9-F](#a9-f-code-deposit-cost)).
237 |
238 | ### A9-1: CREATE
239 |
240 | Gas Calculation:
241 | - `gas_cost = 32000 + mem_expansion_cost + code_deposit_cost`
242 |
243 | ### A9-2: CREATE2
244 | `CREATE2` incurs an additional dynamic cost over `CREATE` because of the need to hash the init code.
245 |
246 | Terms:
247 | - `data_size`: size of the init code in bytes (`len` in the stack representation)
248 | - `data_size_words = (data_size + 31) // 32`: number of (32-byte) words in the init code
249 |
250 | Gas Calculation:
251 | - `gas_cost = 32000 + 6 * data_size_words + mem_expansion_cost + code_deposit_cost`
252 |
253 | ### A9-F: Code Deposit Cost
254 | In addition to the static and dynamic cost of the `CREATE` and `CREATE2` operations, a per-byte cost is charged for storing the returned runtime code.
255 | Unlike the static and dynamic costs of the opcodes, this cost is not applied until *after* the execution of the initialization code halts.
256 |
257 | Terms:
258 | - `returned_code_size`: the length of the returned runtime code
259 |
260 | Gas Calculation:
261 | - `code_deposit_cost = 200 * returned_code_size`
262 |
263 | A note related to the code deposit step of contract creation:
264 | As of [EIP-3541](https://eips.ethereum.org/EIPS/eip-3541), any code returned from a contract creation (i.e. what *would* become the deployed contract code), results in an exceptional abort of the entire contract creation if the code's first byte is `0xEF`.
265 |
266 | ## AA: CALL\* Operations
267 | Gas costs for `CALL`, `CALLCODE`, `DELEGATECALL`, and `STATICCALL` operations.
268 | A big piece of the gas calculation for these operations is determining the gas to send along with the call.
269 | There's a good chance that you are primarily interested in the `base_cost` and can ignore this additional calculation, because the `gas_sent_with_call` is consumed in the context of the called contract, and the unconsumed gas is returned.
270 | If not, see the `gas_sent_with_call` [section](#aa-f-gas-to-send-with-call-operations).
271 |
272 | Similar to selfdestruct, `CALL` incurs an additional cost if it forces an account to be added to the state trie by sending a nonzero amount of eth to an address that was previously empty.
273 | "Empty", in this case is defined according to [EIP-161](https://eips.ethereum.org/EIPS/eip-161) (`balance == nonce == code == 0x`).
274 |
275 | Common Terms:
276 | - `call_value`: the value sent with the call (`val` in the stack representation)
277 | - `target_addr`: the recipient of the call (`addr` in the stack representation)
278 | - `access_cost`: The cost of accessing a warm vs. cold account (see [A0-2](#a0-2-access-sets))
279 | - `access_cost = 100` **if** `target_addr` **in** `touched_addresses` (warm access)
280 | - `access_cost = 2600` **if** `target_addr` **not in** `touched_addresses` (cold access)
281 | - `mem_expansion_cost`: the cost of any memory expansion required (see [A0-1](#a0-1-memory-expansion))
282 | - `gas_sent_with_call`: the gas ultimately sent with the call
283 |
284 | ### AA-1: CALL
285 |
286 | Gas Calculation:
287 | - `base_gas = access_cost + mem_expansion_cost`
288 | - **If** `call_value > 0` (sending value with call):
289 | - `base_gas += 9000`
290 | - **If** `is_empty(target_addr)` (forcing a new account to be created in the state trie):
291 | - `base_gas += 25000`
292 |
293 | Calculate the `gas_sent_with_call` [below](#aa-f-gas-to-send-with-call-operations).
294 |
295 | And the final cost of the operation:
296 | - `gas_cost = base_gas + gas_sent_with_call`
297 |
298 | ### AA-2: CALLCODE
299 |
300 | Gas Calculation:
301 | - `base_gas = access_cost + mem_expansion_cost`
302 | - **If** `call_value > 0` (sending value with call):
303 | - `base_gas += 9000`
304 |
305 | Calculate the `gas_sent_with_call` [below](#aa-f-gas-to-send-with-call-operations).
306 |
307 | And the final cost of the operation:
308 | - `gas_cost = base_gas + gas_sent_with_call`
309 |
310 | ### AA-3: DELEGATECALL
311 |
312 | Gas Calculation:
313 | - `base_gas = access_cost + mem_expansion_cost`
314 |
315 | Calculate the `gas_sent_with_call` [below](#aa-f-gas-to-send-with-call-operations).
316 |
317 | And the final cost of the operation:
318 | - `gas_cost = base_gas + gas_sent_with_call`
319 |
320 | ### AA-4: STATICCALL
321 |
322 | Gas Calculation:
323 | - `base_gas = access_cost + mem_expansion_cost`
324 |
325 | Calculate the `gas_sent_with_call` [below](#aa-f-gas-to-send-with-call-operations).
326 |
327 | And the final cost of the operation:
328 | - `gas_cost = base_gas + gas_sent_with_call`
329 |
330 | ### AA-F: Gas to Send with CALL Operations
331 | In addition to the base cost of executing the operation, `CALL`, `CALLCODE`, `DELEGATECALL`, and `STATICCALL` need to determine how much gas to send along with the call.
332 | Much of the complexity here comes from a backward-compatible change made in [EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md).
333 | Here's an overview of why this calculation is used:
334 |
335 | EIP-150 increased the `base_cost` of the `CALL` opcode from 40 to 700 gas, but most contracts in use at the time were sending `available_gas - 40` with every call.
336 | So, when `base_cost` increased, these contracts were suddenly trying to send more gas than they had left (`requested_gas > remaining_gas`).
337 | To avoid breaking these contracts, if the `requested_gas` is more than `remaining_gas`, we send `all_but_one_64th` of `remaining_gas` instead of trying to send `requested_gas`, which would result in an `OUT_OF_GAS_ERROR`.
338 |
339 | Terms:
340 | - `base_gas`: the cost of the operation before taking into account the gas that should be sent along with the call.
341 | See [AA](#aa-call-operations) for this calculation.
342 | - `available_gas`: the gas remaining in the current execution context immediately before the execution of the opcode
343 | - `remaining_gas`: the gas remaining after deducting `base_cost` of the op but before deducting `gas_sent_with_call`
344 | - `requested_gas`: the gas requested to be sent with the call (`gas` in the stack representation)
345 | - `all_but_one_64th`: All but floor(1/64) of the remaining gas
346 | - `gas_sent_with_call`: the gas ultimately sent with the call
347 |
348 | Gas Calculation:
349 | - `remaining_gas = available_gas - base_gas`
350 | - `all_but_one_64th = remaining_gas - (remaining_gas // 64)`
351 | - `gas_sent_with_call = min(requested_gas, all_but_one_64th)`
352 |
353 | Any portion of `gas_sent_with_call` that is not used by the recipient of the call is refunded to the caller after the call returns. Also, if `call_value > 0`, a 2300 gas stipend is added to the amount of gas included in the call, but not to the cost of making the call.
354 |
355 |
356 | ## AB: SELFDESTRUCT
357 | The gas cost of a `SELFDESTRUCT` operation is dependent on whether or not the operation results in a new account being added to the state trie.
358 | If a nonzero amount of eth is sent to an address that was previously empty, an additional cost is incurred.
359 | "Empty", in this case is defined according to [EIP-161](https://eips.ethereum.org/EIPS/eip-161) (`balance == nonce == code == 0x`).
360 |
361 | The cost also increases if the operation requires a cold access of the recipient address.
362 | See [A0-2](#a0-2-access-sets) for details on EIP-2929 and `touched_addresses`.
363 |
364 | Terms:
365 | - `target_addr`: the recipient of the self-destructing contract's funds (`addr` in the stack representation)
366 | - `context_addr`: the address of the current execution context (i.e. what `ADDRESS` would put on the stack)
367 |
368 | Gas Calculation:
369 | - `gas_cost = 5000`: base cost
370 | - **If** `balance(context_addr) > 0 && is_empty(target_addr)` (sending funds to a previously empty address):
371 | - `gas_cost += 25000`
372 | - **If** `target_addr` **not in** `touched_addresses` (cold access):
373 | - `gas_cost += 2600`
374 |
375 |
376 | ## AF: INVALID
377 | On execution of any invalid operation, whether the designated `INVALID` opcode or simply an undefined opcode, all remaining gas is consumed and the state is reverted to the point immediately prior to the beginning of the current execution context.
378 |
--------------------------------------------------------------------------------
/precompiles.md:
--------------------------------------------------------------------------------
1 | # EVM Precompiles
2 |
3 | References:
4 | These files are useful, but should use the actual geth repo tho
5 |
6 | - https://github.com/ethereum-optimism/optimism/blob/6d38f4731c449c3de1b0fc00d4ea18196073bd00/l2geth/params/protocol_params.go#L91
7 | - https://github.com/ethereum-optimism/optimism/blob/6d38f4731c449c3de1b0fc00d4ea18196073bd00/l2geth/core/vm/contracts.go#L357
8 |
9 | All numbers are for Istanbul:
10 |
11 | | Address | Name | Gas | Notes |
12 | | :-----: | :------------- | :-----: | :---- |
13 | | 0x01 | ecrecover | 3000 | |
14 | | 0x02 | sha256hash | Dynamic | |
15 | | 0x03 | ripemd160hash | Dynamic | |
16 | | 0x04 | dataCopy | Dynamic | |
17 | | 0x05 | bigModExp | Dynamic | |
18 | | 0x06 | bn256Add | 150 | |
19 | | 0x07 | bn256ScalarMul | 6000 | |
20 | | 0x08 | bn256Pairing | Dynamic | |
21 | | 0x09 | blake2F | Dynamic | |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/update_log.md:
--------------------------------------------------------------------------------
1 | | Date | Hardfork | Branch |
2 | | :---:| :--- | :--- |
3 | 29 Jan 2020 | [Istanbul](https://github.com/ethereum/eth1.0-specs/blob/29a892ee02f780cd355f164d829ac99a6f144ec4/network-upgrades/mainnet-upgrades/istanbul.md) | [hardfork-istanbul](https://github.com/wolflo/evm-opcodes/tree/hardfork-istanbul)
4 | 14 April 2021 | [Berlin](https://github.com/ethereum/eth1.0-specs/blob/29a892ee02f780cd355f164d829ac99a6f144ec4/network-upgrades/mainnet-upgrades/berlin.md) | [hardfork-berlin](https://github.com/wolflo/evm-opcodes/tree/hardfork-berlin)
5 | 5 August 2021 | [London](https://github.com/ethereum/eth1.0-specs/blob/29a892ee02f780cd355f164d829ac99a6f144ec4/network-upgrades/mainnet-upgrades/london.md) | main
6 |
--------------------------------------------------------------------------------