ethereum.forks.amsterdam.vm.instructions.stackethereum.forks.bogota.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.

def pop(​evm: Evm​) -> None:
27
    <snip>
36
    # STACK
37
    stack.pop(evm.stack)
38
39
    # GAS
40
    charge_gas(evm, GasCosts.OPCODE_POP)
41
42
    # OPERATION
43
    pass
44
45
    # PROGRAM COUNTER
46
    evm.pc += Uint(1)

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:
50
    <snip>
63
    # STACK
64
    pass
65
66
    # GAS
67
    if num_bytes == 0:
68
        charge_gas(evm, GasCosts.OPCODE_PUSH0)
69
    else:
70
        charge_gas(evm, GasCosts.OPCODE_PUSH)
71
72
    # OPERATION
73
    data_to_push = U256.from_be_bytes(
74
        buffer_read(evm.code, U256(evm.pc + Uint(1)), U256(num_bytes))
75
    )
76
    stack.push(evm.stack, data_to_push)
77
78
    # PROGRAM COUNTER
79
    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:
83
    <snip>
96
    # STACK
97
    pass
98
99
    # GAS
100
    charge_gas(evm, GasCosts.OPCODE_DUP)
101
    if item_number >= len(evm.stack):
102
        raise StackUnderflowError
103
    data_to_duplicate = evm.stack[len(evm.stack) - 1 - item_number]
104
    stack.push(evm.stack, data_to_duplicate)
105
106
    # PROGRAM COUNTER
107
    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:
111
    <snip>
128
    # STACK
129
    pass
130
131
    # GAS
132
    charge_gas(evm, GasCosts.OPCODE_SWAP)
133
    if item_number >= len(evm.stack):
134
        raise StackUnderflowError
135
    evm.stack[-1], evm.stack[-1 - item_number] = (
136
        evm.stack[-1 - item_number],
137
        evm.stack[-1],
138
    )
139
140
    # PROGRAM COUNTER
141
    evm.pc += Uint(1)

push0

144
push0: Callable[[Evm], None] = partial(push_n, num_bytes=0)

push1

145
push1: Callable[[Evm], None] = partial(push_n, num_bytes=1)

push2

146
push2: Callable[[Evm], None] = partial(push_n, num_bytes=2)

push3

147
push3: Callable[[Evm], None] = partial(push_n, num_bytes=3)

push4

148
push4: Callable[[Evm], None] = partial(push_n, num_bytes=4)

push5

149
push5: Callable[[Evm], None] = partial(push_n, num_bytes=5)

push6

150
push6: Callable[[Evm], None] = partial(push_n, num_bytes=6)

push7

151
push7: Callable[[Evm], None] = partial(push_n, num_bytes=7)

push8

152
push8: Callable[[Evm], None] = partial(push_n, num_bytes=8)

push9

153
push9: Callable[[Evm], None] = partial(push_n, num_bytes=9)

push10

154
push10: Callable[[Evm], None] = partial(push_n, num_bytes=10)

push11

155
push11: Callable[[Evm], None] = partial(push_n, num_bytes=11)

push12

156
push12: Callable[[Evm], None] = partial(push_n, num_bytes=12)

push13

157
push13: Callable[[Evm], None] = partial(push_n, num_bytes=13)

push14

158
push14: Callable[[Evm], None] = partial(push_n, num_bytes=14)

push15

159
push15: Callable[[Evm], None] = partial(push_n, num_bytes=15)

push16

160
push16: Callable[[Evm], None] = partial(push_n, num_bytes=16)

push17

161
push17: Callable[[Evm], None] = partial(push_n, num_bytes=17)

push18

162
push18: Callable[[Evm], None] = partial(push_n, num_bytes=18)

push19

163
push19: Callable[[Evm], None] = partial(push_n, num_bytes=19)

push20

164
push20: Callable[[Evm], None] = partial(push_n, num_bytes=20)

push21

165
push21: Callable[[Evm], None] = partial(push_n, num_bytes=21)

push22

166
push22: Callable[[Evm], None] = partial(push_n, num_bytes=22)

push23

167
push23: Callable[[Evm], None] = partial(push_n, num_bytes=23)

push24

168
push24: Callable[[Evm], None] = partial(push_n, num_bytes=24)

push25

169
push25: Callable[[Evm], None] = partial(push_n, num_bytes=25)

push26

170
push26: Callable[[Evm], None] = partial(push_n, num_bytes=26)

push27

171
push27: Callable[[Evm], None] = partial(push_n, num_bytes=27)

push28

172
push28: Callable[[Evm], None] = partial(push_n, num_bytes=28)

push29

173
push29: Callable[[Evm], None] = partial(push_n, num_bytes=29)

push30

174
push30: Callable[[Evm], None] = partial(push_n, num_bytes=30)

push31

175
push31: Callable[[Evm], None] = partial(push_n, num_bytes=31)

push32

176
push32: Callable[[Evm], None] = partial(push_n, num_bytes=32)

dup1

178
dup1: Callable[[Evm], None] = partial(dup_n, item_number=0)

dup2

179
dup2: Callable[[Evm], None] = partial(dup_n, item_number=1)

dup3

180
dup3: Callable[[Evm], None] = partial(dup_n, item_number=2)

dup4

181
dup4: Callable[[Evm], None] = partial(dup_n, item_number=3)

dup5

182
dup5: Callable[[Evm], None] = partial(dup_n, item_number=4)

dup6

183
dup6: Callable[[Evm], None] = partial(dup_n, item_number=5)

dup7

184
dup7: Callable[[Evm], None] = partial(dup_n, item_number=6)

dup8

185
dup8: Callable[[Evm], None] = partial(dup_n, item_number=7)

dup9

186
dup9: Callable[[Evm], None] = partial(dup_n, item_number=8)

dup10

187
dup10: Callable[[Evm], None] = partial(dup_n, item_number=9)

dup11

188
dup11: Callable[[Evm], None] = partial(dup_n, item_number=10)

dup12

189
dup12: Callable[[Evm], None] = partial(dup_n, item_number=11)

dup13

190
dup13: Callable[[Evm], None] = partial(dup_n, item_number=12)

dup14

191
dup14: Callable[[Evm], None] = partial(dup_n, item_number=13)

dup15

192
dup15: Callable[[Evm], None] = partial(dup_n, item_number=14)

dup16

193
dup16: Callable[[Evm], None] = partial(dup_n, item_number=15)

swap1

195
swap1: Callable[[Evm], None] = partial(swap_n, item_number=1)

swap2

196
swap2: Callable[[Evm], None] = partial(swap_n, item_number=2)

swap3

197
swap3: Callable[[Evm], None] = partial(swap_n, item_number=3)

swap4

198
swap4: Callable[[Evm], None] = partial(swap_n, item_number=4)

swap5

199
swap5: Callable[[Evm], None] = partial(swap_n, item_number=5)

swap6

200
swap6: Callable[[Evm], None] = partial(swap_n, item_number=6)

swap7

201
swap7: Callable[[Evm], None] = partial(swap_n, item_number=7)

swap8

202
swap8: Callable[[Evm], None] = partial(swap_n, item_number=8)

swap9

203
swap9: Callable[[Evm], None] = partial(swap_n, item_number=9)

swap10

204
swap10: Callable[[Evm], None] = partial(swap_n, item_number=10)

swap11

205
swap11: Callable[[Evm], None] = partial(swap_n, item_number=11)

swap12

206
swap12: Callable[[Evm], None] = partial(swap_n, item_number=12)

swap13

207
swap13: Callable[[Evm], None] = partial(swap_n, item_number=13)

swap14

208
swap14: Callable[[Evm], None] = partial(swap_n, item_number=14)

swap15

209
swap15: Callable[[Evm], None] = partial(swap_n, item_number=15)

swap16

210
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:
214
    <snip>
225
    # STACK
226
    pass
227
228
    # GAS
229
    charge_gas(evm, GasCosts.OPCODE_DUPN)
230
231
    # OPERATION
232
    immediate_data = U8(
233
        buffer_read(evm.code, U256(evm.pc + Uint(1)), U256(1))[0]
234
    )
235
    item_number = decode_single(immediate_data)
236
    if int(item_number) > len(evm.stack):
237
        raise StackUnderflowError
238
    data_to_duplicate = evm.stack[-item_number]
239
    stack.push(evm.stack, data_to_duplicate)
240
241
    # PROGRAM COUNTER
242
    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:
246
    <snip>
257
    # STACK
258
    pass
259
260
    # GAS
261
    charge_gas(evm, GasCosts.OPCODE_SWAPN)
262
263
    # OPERATION
264
    immediate_data = U8(
265
        buffer_read(evm.code, U256(evm.pc + Uint(1)), U256(1))[0]
266
    )
267
    item_number = decode_single(immediate_data)
268
    # SWAPN with decoded value n swaps top (position 1) with position (n+1)
269
    if int(item_number) + 1 > len(evm.stack):
270
        raise StackUnderflowError
271
    # stack[-1] is top (position 1), stack[-(item_number+1)] is position (n+1)
272
    evm.stack[-1], evm.stack[-(item_number + U8(1))] = (
273
        evm.stack[-(item_number + U8(1))],
274
        evm.stack[-1],
275
    )
276
277
    # PROGRAM COUNTER
278
    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:
282
    <snip>
293
    # STACK
294
    pass
295
296
    # GAS
297
    charge_gas(evm, GasCosts.OPCODE_EXCHANGE)
298
299
    # OPERATION
300
    immediate_data = U8(
301
        buffer_read(evm.code, U256(evm.pc + Uint(1)), U256(1))[0]
302
    )
303
    n, m = decode_pair(immediate_data)
304
    # EXCHANGE swaps position (n+1) with position (m+1)
305
    depth = max(n, m) + U8(1)
306
    if int(depth) > len(evm.stack):
307
        raise StackUnderflowError
308
    evm.stack[-(n + U8(1))], evm.stack[-(m + U8(1))] = (
309
        evm.stack[-(m + U8(1))],
310
        evm.stack[-(n + U8(1))],
311
    )
312
313
    # PROGRAM COUNTER
314
    evm.pc += Uint(2)