跳转到主要内容
Change page

EVM 操作码

概述

这是 wolflo/evm-opcodes (在新标签页中打开) 处 EVM 参考页面的更新版本。 内容还借鉴了黄皮书 (在新标签页中打开)Jello Paper (在新标签页中打开) 以及 geth (在新标签页中打开) 实现。 这旨在成为一份易于理解的参考资料,但并不是特别严谨。 如果你想确保正确性并了解每一个边缘情况,建议使用 Jello Paper 或客户端实现。

正在寻找交互式参考资料?请查看 evm.codes (在新标签页中打开)

有关具有动态 Gas 成本的操作,请参阅 gas.md (在新标签页中打开)

💡 快速提示:要查看整行,请在桌面上使用 [shift] + 滚动 进行水平滚动。

堆栈名称Gas初始堆栈结果堆栈内存 / 存储备注
00STOP0停止执行
01ADD3a, ba + b(u)int256 加法,模 2**256
02MUL5a, ba * b(u)int256 乘法,模 2**256
03SUB3a, ba - b(u)int256 减法,模 2**256
04DIV5a, ba // buint256 除法
05SDIV5a, ba // bint256 除法
06MOD5a, ba % buint256 取模
07SMOD5a, ba % bint256 取模
08ADDMOD8a, b, N(a + b) % N(u)int256 加法,模 N
09MULMOD8a, b, N(a * b) % N(u)int256 乘法,模 N
0AEXPA1 (在新标签页中打开)a, ba ** buint256 指数运算,模 2**256
0BSIGNEXTEND5b, xSIGNEXTEND(x, b)x(b+1) 字节符号扩展 (在新标签页中打开)到 32 字节
0C-0F无效
10LT3a, ba < buint256 小于
11GT3a, ba > buint256 大于
12SLT3a, ba < bint256 小于
13SGT3a, ba > bint256 大于
14EQ3a, ba == b(u)int256 等于
15ISZERO3aa == 0(u)int256 是否为零
16AND3a, ba && b按位与
17OR3a, b`ab`
18XOR3a, ba ^ b按位异或
19NOT3a~a按位非
1ABYTE3i, x(x >> (248 - i * 8)) && 0xFF(u)int256 x 的第 i 个字节,从左起
1BSHL3shift, valval << shift左移
1CSHR3shift, valval >> shift逻辑右移
1DSAR3shift, valval >> shift算术右移
1E-1F无效
20KECCAK256A2 (在新标签页中打开)ost, lenkeccak256(mem[ost:ost+len-1])keccak256
21-2F无效
30ADDRESS2.address(this)执行合约的地址
31BALANCEA5 (在新标签页中打开)addraddr.balance余额,单位为 Wei
32ORIGIN2.tx.origin发起交易的地址
33CALLER2.msg.sender消息发送者的地址
34CALLVALUE2.msg.value消息值,单位为 Wei
35CALLDATALOAD3idxmsg.data[idx:idx+32]从索引 idx 处的消息数据中读取字
36CALLDATASIZE2.len(msg.data)消息数据的长度,单位为字节
37CALLDATACOPYA3 (在新标签页中打开)dstOst, ost, len.mem[dstOst:dstOst+len-1] := msg.data[ost:ost+len-1]复制消息数据
38CODESIZE2.len(this.code)执行合约代码的长度,单位为字节
39CODECOPYA3 (在新标签页中打开)dstOst, ost, len.mem[dstOst:dstOst+len-1] := this.code[ost:ost+len-1]
3AGASPRICE2.tx.gasprice交易的 Gas 价格,单位为 Wei 每单位 Gas ** (在新标签页中打开)
3BEXTCODESIZEA5 (在新标签页中打开)addrlen(addr.code)addr 处代码的大小,单位为字节
3CEXTCODECOPYA4 (在新标签页中打开)addr, dstOst, ost, len.mem[dstOst:dstOst+len-1] := addr.code[ost:ost+len-1]addr 复制代码
3DRETURNDATASIZE2.size上次外部调用返回数据的大小,单位为字节
3ERETURNDATACOPYA3 (在新标签页中打开)dstOst, ost, len.mem[dstOst:dstOst+len-1] := returndata[ost:ost+len-1]复制上次外部调用返回的数据
3FEXTCODEHASHA5 (在新标签页中打开)addrhashhash = addr.exists ? keccak256(addr.code) : 0
40BLOCKHASH20blockNumblockHash(blockNum)
41COINBASE2.block.coinbase当前区块提议者的地址
42TIMESTAMP2.block.timestamp当前区块的时间戳
43NUMBER2.block.number当前区块的编号
44PREVRANDAO2.randomness beacon随机性信标
45GASLIMIT2.block.gaslimit当前区块的 gas 上限
46CHAINID2.chain_id将当前链 ID (在新标签页中打开) 推入堆栈
47SELFBALANCE5.address(this).balance执行合约的余额,单位为 Wei
48BASEFEE2.block.basefee当前区块的基础费用
49BLOBHASH3idxtx.blob_versioned_hashes[idx]EIP-4844 (在新标签页中打开)
4ABLOBBASEFEE2.block.blobbasefee当前区块的斑点基础费用 (EIP-7516 (在新标签页中打开))
4B-4F无效
50POP2_anon.从堆栈顶部移除项并丢弃
51MLOAD3* (在新标签页中打开)ostmem[ost:ost+32]从偏移量 ost 处的内存中读取字
52MSTORE3* (在新标签页中打开)ost, val.mem[ost:ost+32] := val将一个字写入内存
53MSTORE83* (在新标签页中打开)ost, val.mem[ost] := val && 0xFF将单个字节写入内存
54SLOADA6 (在新标签页中打开)keystorage[key]从存储中读取字
55SSTOREA7 (在新标签页中打开)key, val.storage[key] := val将字写入存储
56JUMP8dst.$pc := dst 标记仅当 dst 是有效的 jumpdest 时才分配 pc
57JUMPI10dst, condition.$pc := condition ? dst : $pc + 1
58PC2.$pc程序计数器
59MSIZE2.len(mem)当前执行上下文中内存的大小,单位为字节
5AGAS2.gasRemaining
5BJUMPDEST1标记有效的跳转目标有效的跳转目标,例如不在 push 数据内的跳转目标
5CTLOAD100keytstorage[key]从瞬态存储中读取字 (EIP-1153 (在新标签页中打开))
5DTSTORE100key, val.tstorage[key] := val将字写入瞬态存储 (EIP-1153 (在新标签页中打开))
5EMCOPY3+3*words+A0 (在新标签页中打开)dstOst, ost, len.mem[dstOst] := mem[ost:ost+len]将内存从一个区域复制到另一个区域 (EIP-5656 (在新标签页中打开))
5FPUSH02.uint8将常量值 0 推入堆栈
60PUSH13.uint8将 1 字节值推入堆栈
61PUSH23.uint16将 2 字节值推入堆栈
62PUSH33.uint24将 3 字节值推入堆栈
63PUSH43.uint32将 4 字节值推入堆栈
64PUSH53.uint40将 5 字节值推入堆栈
65PUSH63.uint48将 6 字节值推入堆栈
66PUSH73.uint56将 7 字节值推入堆栈
67PUSH83.uint64将 8 字节值推入堆栈
68PUSH93.uint72将 9 字节值推入堆栈
69PUSH103.uint80将 10 字节值推入堆栈
6APUSH113.uint88将 11 字节值推入堆栈
6BPUSH123.uint96将 12 字节值推入堆栈
6CPUSH133.uint104将 13 字节值推入堆栈
6DPUSH143.uint112将 14 字节值推入堆栈
6EPUSH153.uint120将 15 字节值推入堆栈
6FPUSH163.uint128将 16 字节值推入堆栈
70PUSH173.uint136将 17 字节值推入堆栈
71PUSH183.uint144将 18 字节值推入堆栈
72PUSH193.uint152将 19 字节值推入堆栈
73PUSH203.uint160将 20 字节值推入堆栈
74PUSH213.uint168将 21 字节值推入堆栈
75PUSH223.uint176将 22 字节值推入堆栈
76PUSH233.uint184将 23 字节值推入堆栈
77PUSH243.uint192将 24 字节值推入堆栈
78PUSH253.uint200将 25 字节值推入堆栈
79PUSH263.uint208将 26 字节值推入堆栈
7APUSH273.uint216将 27 字节值推入堆栈
7BPUSH283.uint224将 28 字节值推入堆栈
7CPUSH293.uint232将 29 字节值推入堆栈
7DPUSH303.uint240将 30 字节值推入堆栈
7EPUSH313.uint248将 31 字节值推入堆栈
7FPUSH323.uint256将 32 字节值推入堆栈
80DUP13aa, a克隆堆栈上的第 1 个值
81DUP23_, aa, _, a克隆堆栈上的第 2 个值
82DUP33_, _, aa, _, _, a克隆堆栈上的第 3 个值
83DUP43_, _, _, aa, _, _, _, a克隆堆栈上的第 4 个值
84DUP53..., aa, ..., a克隆堆栈上的第 5 个值
85DUP63..., aa, ..., a克隆堆栈上的第 6 个值
86DUP73..., aa, ..., a克隆堆栈上的第 7 个值
87DUP83..., aa, ..., a克隆堆栈上的第 8 个值
88DUP93..., aa, ..., a克隆堆栈上的第 9 个值
89DUP103..., aa, ..., a克隆堆栈上的第 10 个值
8ADUP113..., aa, ..., a克隆堆栈上的第 11 个值
8BDUP123..., aa, ..., a克隆堆栈上的第 12 个值
8CDUP133..., aa, ..., a克隆堆栈上的第 13 个值
8DDUP143..., aa, ..., a克隆堆栈上的第 14 个值
8EDUP153..., aa, ..., a克隆堆栈上的第 15 个值
8FDUP163..., aa, ..., a克隆堆栈上的第 16 个值
90SWAP13a, bb, a
91SWAP23a, _, bb, _, a
92SWAP33a, _, _, bb, _, _, a
93SWAP43a, _, _, _, bb, _, _, _, a
94SWAP53a, ..., bb, ..., a
95SWAP63a, ..., bb, ..., a
96SWAP73a, ..., bb, ..., a
97SWAP83a, ..., bb, ..., a
98SWAP93a, ..., bb, ..., a
99SWAP103a, ..., bb, ..., a
9ASWAP113a, ..., bb, ..., a
9BSWAP123a, ..., bb, ..., a
9CSWAP133a, ..., bb, ..., a
9DSWAP143a, ..., bb, ..., a
9ESWAP153a, ..., bb, ..., a
9FSWAP163a, ..., bb, ..., a
A0LOG0A8 (在新标签页中打开)ost, len.LOG0(memory[ost:ost+len-1])
A1LOG1A8 (在新标签页中打开)ost, len, topic0.LOG1(memory[ost:ost+len-1], topic0)
A2LOG2A8 (在新标签页中打开)ost, len, topic0, topic1.LOG2(memory[ost:ost+len-1], topic0, topic1)
A3LOG3A8 (在新标签页中打开)ost, len, topic0, topic1, topic2.LOG3(memory[ost:ost+len-1], topic0, topic1, topic2)
A4LOG4A8 (在新标签页中打开)ost, len, topic0, topic1, topic2, topic3.LOG4(memory[ost:ost+len-1], topic0, topic1, topic2, topic3)
A5-EF无效
F0CREATEA9 (在新标签页中打开)val, ost, lenaddraddr = keccak256(rlp([address(this), this.nonce]))
F1CALLAA (在新标签页中打开)gas, addr, val, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] := returndata
F2CALLCODEAA (在新标签页中打开)gas, addr, val, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] = returndata与 DELEGATECALL 相同,但不会传播原始的 msg.sender 和 msg.value
F3RETURN0* (在新标签页中打开)ost, len.return mem[ost:ost+len-1]
F4DELEGATECALLAA (在新标签页中打开)gas, addr, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] := returndata
F5CREATE2A9 (在新标签页中打开)val, ost, len, saltaddraddr = keccak256(0xff ++ address(this) ++ salt ++ keccak256(mem[ost:ost+len-1]))[12:]
F6-F9无效
FASTATICCALLAA (在新标签页中打开)gas, addr, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] := returndata
FB-FC无效
FDREVERT0* (在新标签页中打开)ost, len.revert(mem[ost:ost+len-1])
FEINVALIDAF (在新标签页中打开)指定的无效操作码 - EIP-141 (在新标签页中打开)
FFSELFDESTRUCTAB (在新标签页中打开)addr.将所有 ETH 发送到 addr;如果在创建合约的同一笔交易中执行,则会销毁该合约