跳转到主要内容
Change page

EVM 操作码

概述

这是 wolflo/evm-opcodes (opens in a new tab) 上 EVM 参考页面的更新版本。 同时也参考了黄皮书 (opens in a new tab)Jello Paper (opens in a new tab)以及 geth (opens in a new tab) 实现。 本文旨在提供一份易于理解的参考资料,但并非特别严谨。 如果你想确保准确无误并了解每一个边缘情况,建议查阅 Jello Paper 或客户端实现。

正在寻找交互式参考资料?请查看 evm.codes (opens in a new tab)

有关具有动态 Gas 成本的操作,请参阅 gas.md (opens in a new tab)

💡 小提示:要在桌面设备上查看完整行,请使用 [shift] + scroll 进行水平滚动。

堆栈名称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 (opens in a new tab)a, ba ** buint256 指数运算,对 2**256 取模
0BSIGNEXTEND5b, xSIGNEXTEND(x, b)符号扩展 (opens in a new tab) 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, ba || b按位或
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 (opens in a new tab)ost, lenkeccak256(mem[ost:ost+len-1])keccak256
21-2F无效
30ADDRESS2.address(this)执行中合约的地址
31BALANCEA5 (opens in a new tab)addraddr.balance余额,单位为 Wei
32ORIGIN2.tx.origin发起交易的地址
33CALLER2.msg.sender消息发送者的地址
34CALLVALUE2.msg.value消息 value,单位为 Wei
35CALLDATALOAD3idxmsg.data[idx:idx+32]从消息数据的索引 idx 处读取一个字(word)
36CALLDATASIZE2.len(msg.data)消息数据的长度,单位为字节
37CALLDATACOPYA3 (opens in a new tab)dstOst, ost, len.mem[dstOst:dstOst+len-1] := msg.data[ost:ost+len-1]复制消息数据
38CODESIZE2.len(this.code)执行中合约的代码长度,单位为字节
39CODECOPYA3 (opens in a new tab)dstOst, ost, len.mem[dstOst:dstOst+len-1] := this.code[ost:ost+len-1]
3AGASPRICE2.tx.gasprice交易的 Gas 价格,单位为 Wei/Gas ** (opens in a new tab)
3BEXTCODESIZEA5 (opens in a new tab)addrlen(addr.code)地址处代码的大小,单位为字节
3CEXTCODECOPYA4 (opens in a new tab)addr, dstOst, ost, len.mem[dstOst:dstOst+len-1] := addr.code[ost:ost+len-1]addr 复制代码
3DRETURNDATASIZE2.size上一次外部调用返回数据的大小,单位为字节
3ERETURNDATACOPYA3 (opens in a new tab)dstOst, ost, len.mem[dstOst:dstOst+len-1] := returndata[ost:ost+len-1]复制上一次外部调用返回的数据
3FEXTCODEHASHA5 (opens in a new tab)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 (opens in a new tab) 推入堆栈
47SELFBALANCE5.address(this).balance执行中合约的余额,单位为 Wei
48BASEFEE2.block.basefee当前区块的基础费用
49BLOBHASH3idxtx.blob_versioned_hashes[idx]EIP-4844 (opens in a new tab)
4ABLOBBASEFEE2.block.blobbasefee当前区块的斑点基础费用(EIP-7516 (opens in a new tab)
4B-4F无效
50POP2_anon.从堆栈顶部移除项并丢弃
51MLOAD3* (opens in a new tab)ostmem[ost:ost+32]从内存偏移量 ost 处读取一个字(word)
52MSTORE3* (opens in a new tab)ost, val.mem[ost:ost+32] := val向内存写入一个字(word)
53MSTORE83* (opens in a new tab)ost, val.mem[ost] := val && 0xFF向内存写入单字节
54SLOADA6 (opens in a new tab)keystorage[key]从存储中读取一个字(word)
55SSTOREA7 (opens in a new tab)key, val.storage[key] := val向存储写入一个字(word)
56JUMP8dst.$pc := dst 标记仅当 dst 是有效的跳转目标(jumpdest)时,才赋值给 pc
57JUMPI10dst, condition.$pc := condition ? dst : $pc + 1
58PC2.$pc程序计数器
59MSIZE2.len(mem)当前执行上下文中的内存大小,单位为字节
5AGAS2.gasRemaining
5BJUMPDEST1mark valid jump destination有效的跳转目标,例如不在 push 数据内部的跳转目标
5CTLOAD100keytstorage[key]从瞬态存储中读取一个字(word)(EIP-1153 (opens in a new tab)
5DTSTORE100key, val.tstorage[key] := val向瞬态存储写入一个字(word)(EIP-1153 (opens in a new tab)
5EMCOPY3+3*words+A0 (opens in a new tab)dstOst, ost, len.mem[dstOst] := mem[ost:ost+len]将内存从一个区域复制到另一个区域(EIP-5656 (opens in a new tab)
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 (opens in a new tab)ost, len.LOG0(memory[ost:ost+len-1])
A1LOG1A8 (opens in a new tab)ost, len, topic0.LOG1(memory[ost:ost+len-1], topic0)
A2LOG2A8 (opens in a new tab)ost, len, topic0, topic1.LOG2(memory[ost:ost+len-1], topic0, topic1)
A3LOG3A8 (opens in a new tab)ost, len, topic0, topic1, topic2.LOG3(memory[ost:ost+len-1], topic0, topic1, topic2)
A4LOG4A8 (opens in a new tab)ost, len, topic0, topic1, topic2, topic3.LOG4(memory[ost:ost+len-1], topic0, topic1, topic2, topic3)
A5-EF无效
F0CREATEA9 (opens in a new tab)val, ost, lenaddraddr = keccak256(rlp([address(this), this.nonce]))
F1CALLAA (opens in a new tab)gas, addr, val, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] := returndata
F2CALLCODEAA (opens in a new tab)gas, addr, val, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] = returndata与 DELEGATECALL 相同,但不传播原始的 msg.sender 和 msg.value
F3RETURN0* (opens in a new tab)ost, len.return mem[ost:ost+len-1]
F4DELEGATECALLAA (opens in a new tab)gas, addr, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] := returndata
F5CREATE2A9 (opens in a new tab)val, ost, len, saltaddraddr = keccak256(0xff ++ address(this) ++ salt ++ keccak256(mem[ost:ost+len-1]))[12:]
F6-F9无效
FASTATICCALLAA (opens in a new tab)gas, addr, argOst, argLen, retOst, retLensuccessmem[retOst:retOst+retLen-1] := returndata
FB-FC无效
FDREVERT0* (opens in a new tab)ost, len.revert(mem[ost:ost+len-1])
FEINVALIDAF (opens in a new tab)指定的无效操作码 - EIP-141 (opens in a new tab)
FFSELFDESTRUCTAB (opens in a new tab)addr.将所有 ETH 发送至 addr;如果在创建合约的同一笔交易中执行,则会销毁该合约