ethereum.forks.bpo5.vm.instructions.stackethereum.forks.amsterdam.vm.instructions.stack
Ethereum Virtual Machine (EVM) Stack Instructions.
.. contents:: Table of Contents :backlinks: none :local:
Introduction
Implementations of the EVM stack related instructions.
pop ¶
Removes an item from the stack.
Parameters
evm : The current EVM frame.
push_n ¶
Pushes an N-byte immediate onto the stack. Push zero if num_bytes is zero.
Parameters
evm : The current EVM frame.
num_bytes : The number of immediate bytes to be read from the code and pushed to the stack. Push zero if num_bytes is zero.
def push_n(evm: Evm, num_bytes: int) -> None:
| 53 | <snip> |
|---|---|
| 66 | # STACK |
| 67 | pass |
| 68 | |
| 69 | # GAS |
| 70 | if num_bytes == 0: |
| 71 | charge_gas(evm, GasCosts.OPCODE_PUSH0) |
| 72 | else: |
| 73 | charge_gas(evm, GasCosts.OPCODE_PUSH) |
| 74 | |
| 75 | # OPERATION |
| 76 | data_to_push = U256.from_be_bytes( |
| 77 | buffer_read(evm.code, U256(evm.pc + Uint(1)), U256(num_bytes)) |
| 78 | ) |
| 79 | stack.push(evm.stack, data_to_push) |
| 80 | |
| 81 | # PROGRAM COUNTER |
| 82 | evm.pc += Uint(1) + Uint(num_bytes) |
dup_n ¶
Duplicates the Nth stack item (from top of the stack) to the top of stack.
Parameters
evm : The current EVM frame.
item_number : The stack item number (0-indexed from top of stack) to be duplicated to the top of stack.
def dup_n(evm: Evm, item_number: int) -> None:
| 86 | <snip> |
|---|---|
| 99 | # STACK |
| 100 | pass |
| 101 | |
| 102 | # GAS |
| 103 | charge_gas(evm, GasCosts.OPCODE_DUP) |
| 104 | if item_number >= len(evm.stack): |
| 105 | raise StackUnderflowError |
| 106 | data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number] |
| 107 | stack.push(evm.stack, data_to_duplicate) |
| 108 | |
| 109 | # PROGRAM COUNTER |
| 110 | evm.pc += Uint(1) |
swap_n ¶
Swaps the top and the item_number element of the stack, where
the top of the stack is position zero.
If item_number is zero, this function does nothing (which should not be
possible, since there is no SWAP0 instruction).
Parameters
evm : The current EVM frame.
item_number : The stack item number (0-indexed from top of stack) to be swapped with the top of stack element.
def swap_n(evm: Evm, item_number: int) -> None:
| 114 | <snip> |
|---|---|
| 131 | # STACK |
| 132 | pass |
| 133 | |
| 134 | # GAS |
| 135 | charge_gas(evm, GasCosts.OPCODE_SWAP) |
| 136 | if item_number >= len(evm.stack): |
| 137 | raise StackUnderflowError |
| 138 | evm.stack[-1], evm.stack[-1 - item_number] = ( |
| 139 | evm.stack[-1 - item_number], |
| 140 | evm.stack[-1], |
| 141 | ) |
| 142 | |
| 143 | # PROGRAM COUNTER |
| 144 | evm.pc += Uint(1) |
push0¶
| 147 | push0: Callable[[Evm], None] = partial(push_n, num_bytes=0) |
|---|
push1¶
| 148 | push1: Callable[[Evm], None] = partial(push_n, num_bytes=1) |
|---|
push2¶
| 149 | push2: Callable[[Evm], None] = partial(push_n, num_bytes=2) |
|---|
push3¶
| 150 | push3: Callable[[Evm], None] = partial(push_n, num_bytes=3) |
|---|
push4¶
| 151 | push4: Callable[[Evm], None] = partial(push_n, num_bytes=4) |
|---|
push5¶
| 152 | push5: Callable[[Evm], None] = partial(push_n, num_bytes=5) |
|---|
push6¶
| 153 | push6: Callable[[Evm], None] = partial(push_n, num_bytes=6) |
|---|
push7¶
| 154 | push7: Callable[[Evm], None] = partial(push_n, num_bytes=7) |
|---|
push8¶
| 155 | push8: Callable[[Evm], None] = partial(push_n, num_bytes=8) |
|---|
push9¶
| 156 | push9: Callable[[Evm], None] = partial(push_n, num_bytes=9) |
|---|
push10¶
| 157 | push10: Callable[[Evm], None] = partial(push_n, num_bytes=10) |
|---|
push11¶
| 158 | push11: Callable[[Evm], None] = partial(push_n, num_bytes=11) |
|---|
push12¶
| 159 | push12: Callable[[Evm], None] = partial(push_n, num_bytes=12) |
|---|
push13¶
| 160 | push13: Callable[[Evm], None] = partial(push_n, num_bytes=13) |
|---|
push14¶
| 161 | push14: Callable[[Evm], None] = partial(push_n, num_bytes=14) |
|---|
push15¶
| 162 | push15: Callable[[Evm], None] = partial(push_n, num_bytes=15) |
|---|
push16¶
| 163 | push16: Callable[[Evm], None] = partial(push_n, num_bytes=16) |
|---|
push17¶
| 164 | push17: Callable[[Evm], None] = partial(push_n, num_bytes=17) |
|---|
push18¶
| 165 | push18: Callable[[Evm], None] = partial(push_n, num_bytes=18) |
|---|
push19¶
| 166 | push19: Callable[[Evm], None] = partial(push_n, num_bytes=19) |
|---|
push20¶
| 167 | push20: Callable[[Evm], None] = partial(push_n, num_bytes=20) |
|---|
push21¶
| 168 | push21: Callable[[Evm], None] = partial(push_n, num_bytes=21) |
|---|
push22¶
| 169 | push22: Callable[[Evm], None] = partial(push_n, num_bytes=22) |
|---|
push23¶
| 170 | push23: Callable[[Evm], None] = partial(push_n, num_bytes=23) |
|---|
push24¶
| 171 | push24: Callable[[Evm], None] = partial(push_n, num_bytes=24) |
|---|
push25¶
| 172 | push25: Callable[[Evm], None] = partial(push_n, num_bytes=25) |
|---|
push26¶
| 173 | push26: Callable[[Evm], None] = partial(push_n, num_bytes=26) |
|---|
push27¶
| 174 | push27: Callable[[Evm], None] = partial(push_n, num_bytes=27) |
|---|
push28¶
| 175 | push28: Callable[[Evm], None] = partial(push_n, num_bytes=28) |
|---|
push29¶
| 176 | push29: Callable[[Evm], None] = partial(push_n, num_bytes=29) |
|---|
push30¶
| 177 | push30: Callable[[Evm], None] = partial(push_n, num_bytes=30) |
|---|
push31¶
| 178 | push31: Callable[[Evm], None] = partial(push_n, num_bytes=31) |
|---|
push32¶
| 179 | push32: Callable[[Evm], None] = partial(push_n, num_bytes=32) |
|---|
dup1¶
| 181 | dup1: Callable[[Evm], None] = partial(dup_n, item_number=0) |
|---|
dup2¶
| 182 | dup2: Callable[[Evm], None] = partial(dup_n, item_number=1) |
|---|
dup3¶
| 183 | dup3: Callable[[Evm], None] = partial(dup_n, item_number=2) |
|---|
dup4¶
| 184 | dup4: Callable[[Evm], None] = partial(dup_n, item_number=3) |
|---|
dup5¶
| 185 | dup5: Callable[[Evm], None] = partial(dup_n, item_number=4) |
|---|
dup6¶
| 186 | dup6: Callable[[Evm], None] = partial(dup_n, item_number=5) |
|---|
dup7¶
| 187 | dup7: Callable[[Evm], None] = partial(dup_n, item_number=6) |
|---|
dup8¶
| 188 | dup8: Callable[[Evm], None] = partial(dup_n, item_number=7) |
|---|
dup9¶
| 189 | dup9: Callable[[Evm], None] = partial(dup_n, item_number=8) |
|---|
dup10¶
| 190 | dup10: Callable[[Evm], None] = partial(dup_n, item_number=9) |
|---|
dup11¶
| 191 | dup11: Callable[[Evm], None] = partial(dup_n, item_number=10) |
|---|
dup12¶
| 192 | dup12: Callable[[Evm], None] = partial(dup_n, item_number=11) |
|---|
dup13¶
| 193 | dup13: Callable[[Evm], None] = partial(dup_n, item_number=12) |
|---|
dup14¶
| 194 | dup14: Callable[[Evm], None] = partial(dup_n, item_number=13) |
|---|
dup15¶
| 195 | dup15: Callable[[Evm], None] = partial(dup_n, item_number=14) |
|---|
dup16¶
| 196 | dup16: Callable[[Evm], None] = partial(dup_n, item_number=15) |
|---|
swap1¶
| 198 | swap1: Callable[[Evm], None] = partial(swap_n, item_number=1) |
|---|
swap2¶
| 199 | swap2: Callable[[Evm], None] = partial(swap_n, item_number=2) |
|---|
swap3¶
| 200 | swap3: Callable[[Evm], None] = partial(swap_n, item_number=3) |
|---|
swap4¶
| 201 | swap4: Callable[[Evm], None] = partial(swap_n, item_number=4) |
|---|
swap5¶
| 202 | swap5: Callable[[Evm], None] = partial(swap_n, item_number=5) |
|---|
swap6¶
| 203 | swap6: Callable[[Evm], None] = partial(swap_n, item_number=6) |
|---|
swap7¶
| 204 | swap7: Callable[[Evm], None] = partial(swap_n, item_number=7) |
|---|
swap8¶
| 205 | swap8: Callable[[Evm], None] = partial(swap_n, item_number=8) |
|---|
swap9¶
| 206 | swap9: Callable[[Evm], None] = partial(swap_n, item_number=9) |
|---|
swap10¶
| 207 | swap10: Callable[[Evm], None] = partial(swap_n, item_number=10) |
|---|
swap11¶
| 208 | swap11: Callable[[Evm], None] = partial(swap_n, item_number=11) |
|---|
swap12¶
| 209 | swap12: Callable[[Evm], None] = partial(swap_n, item_number=12) |
|---|
swap13¶
| 210 | swap13: Callable[[Evm], None] = partial(swap_n, item_number=13) |
|---|
swap14¶
| 211 | swap14: Callable[[Evm], None] = partial(swap_n, item_number=14) |
|---|
swap15¶
| 212 | swap15: Callable[[Evm], None] = partial(swap_n, item_number=15) |
|---|
swap16¶
| 213 | swap16: Callable[[Evm], None] = partial(swap_n, item_number=16) |
|---|
dupn ¶
Duplicate the Nth stack item (from top of the stack) to the top of stack. The item number is read from the immediate byte following the opcode and decoded using the EIP-8024 index shifting rules.
Parameters
evm : The current EVM frame.
def dupn(evm: Evm) -> None:
| 217 | <snip> |
|---|---|
| 228 | # STACK |
| 229 | pass |
| 230 | |
| 231 | # GAS |
| 232 | charge_gas(evm, GasCosts.OPCODE_DUPN) |
| 233 | |
| 234 | # OPERATION |
| 235 | immediate_data = U8( |
| 236 | buffer_read(evm.code, U256(evm.pc + Uint(1)), U256(1))[0] |
| 237 | ) |
| 238 | item_number = decode_single(immediate_data) |
| 239 | if int(item_number) > len(evm.stack): |
| 240 | raise StackUnderflowError |
| 241 | data_to_duplicate = evm.stack[-item_number] |
| 242 | stack.push(evm.stack, data_to_duplicate) |
| 243 | |
| 244 | # PROGRAM COUNTER |
| 245 | evm.pc += Uint(2) |
swapn ¶
Swap the top stack item with the Nth stack item. The value N is read from the immediate byte following the opcode and decoded using the EIP-8024 index shifting rules.
Parameters
evm : The current EVM frame.
def swapn(evm: Evm) -> None:
| 249 | <snip> |
|---|---|
| 260 | # STACK |
| 261 | pass |
| 262 | |
| 263 | # GAS |
| 264 | charge_gas(evm, GasCosts.OPCODE_SWAPN) |
| 265 | |
| 266 | # OPERATION |
| 267 | immediate_data = U8( |
| 268 | buffer_read(evm.code, U256(evm.pc + Uint(1)), U256(1))[0] |
| 269 | ) |
| 270 | item_number = decode_single(immediate_data) |
| 271 | # SWAPN with decoded value n swaps top (position 1) with position (n+1) |
| 272 | if int(item_number) + 1 > len(evm.stack): |
| 273 | raise StackUnderflowError |
| 274 | # stack[-1] is top (position 1), stack[-(item_number+1)] is position (n+1) |
| 275 | evm.stack[-1], evm.stack[-(item_number + U8(1))] = ( |
| 276 | evm.stack[-(item_number + U8(1))], |
| 277 | evm.stack[-1], |
| 278 | ) |
| 279 | |
| 280 | # PROGRAM COUNTER |
| 281 | evm.pc += Uint(2) |
exchange ¶
Exchange the Nth stack item with the Mth stack item. The values N and M are decoded from the immediate byte using the EIP-8024 index shifting rules.
Parameters
evm : The current EVM frame.
def exchange(evm: Evm) -> None:
| 285 | <snip> |
|---|---|
| 296 | # STACK |
| 297 | pass |
| 298 | |
| 299 | # GAS |
| 300 | charge_gas(evm, GasCosts.OPCODE_EXCHANGE) |
| 301 | |
| 302 | # OPERATION |
| 303 | immediate_data = U8( |
| 304 | buffer_read(evm.code, U256(evm.pc + Uint(1)), U256(1))[0] |
| 305 | ) |
| 306 | n, m = decode_pair(immediate_data) |
| 307 | # EXCHANGE swaps position (n+1) with position (m+1) |
| 308 | depth = max(n, m) + U8(1) |
| 309 | if int(depth) > len(evm.stack): |
| 310 | raise StackUnderflowError |
| 311 | evm.stack[-(n + U8(1))], evm.stack[-(m + U8(1))] = ( |
| 312 | evm.stack[-(m + U8(1))], |
| 313 | evm.stack[-(n + U8(1))], |
| 314 | ) |
| 315 | |
| 316 | # PROGRAM COUNTER |
| 317 | evm.pc += Uint(2) |