├── 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 | --------------------------------------------------------------------------------