Mã lệnh cho EVM
Tổng quan
Đây là phiên bản cập nhật của trang tham chiếu EVM tại wolflo/evm-opcodes (mở trong tab mới). Cũng được trích xuất từ Sách vàng (mở trong tab mới), Jello Paper (mở trong tab mới), và bản triển khai geth (mở trong tab mới). Tài liệu này nhằm mục đích trở thành một tài liệu tham khảo dễ tiếp cận, nhưng không đặc biệt nghiêm ngặt. Nếu bạn muốn chắc chắn về tính chính xác và nhận biết mọi trường hợp ngoại lệ, bạn nên sử dụng Jello Paper hoặc một bản triển khai máy khách.
Bạn đang tìm kiếm một tài liệu tham khảo tương tác? Hãy xem evm.codes (mở trong tab mới).
Đối với các hoạt động có chi phí Gas động, hãy xem gas.md (mở trong tab mới).
💡 Mẹo nhanh: Để xem toàn bộ các dòng, hãy sử dụng [shift] + cuộn để cuộn ngang trên máy tính để bàn.
| Ngăn xếp | Tên | Gas | Ngăn xếp ban đầu | Ngăn xếp kết quả | Bộ nhớ / Lưu trữ | Ghi chú |
|---|---|---|---|---|---|---|
| 00 | STOP | 0 | dừng thực thi | |||
| 01 | ADD | 3 | a, b | a + b | phép cộng (u)int256 modulo 2**256 | |
| 02 | MUL | 5 | a, b | a * b | phép nhân (u)int256 modulo 2**256 | |
| 03 | SUB | 3 | a, b | a - b | phép trừ (u)int256 modulo 2**256 | |
| 04 | DIV | 5 | a, b | a // b | phép chia uint256 | |
| 05 | SDIV | 5 | a, b | a // b | phép chia int256 | |
| 06 | MOD | 5 | a, b | a % b | phép chia lấy dư uint256 | |
| 07 | SMOD | 5 | a, b | a % b | phép chia lấy dư int256 | |
| 08 | ADDMOD | 8 | a, b, N | (a + b) % N | phép cộng (u)int256 modulo N | |
| 09 | MULMOD | 8 | a, b, N | (a * b) % N | phép nhân (u)int256 modulo N | |
| 0A | EXP | A1 (mở trong tab mới) | a, b | a ** b | phép lũy thừa uint256 modulo 2**256 | |
| 0B | SIGNEXTEND | 5 | b, x | SIGNEXTEND(x, b) | mở rộng dấu (mở trong tab mới) x từ (b+1) byte thành 32 byte | |
| 0C-0F | không hợp lệ | |||||
| 10 | LT | 3 | a, b | a < b | nhỏ hơn uint256 | |
| 11 | GT | 3 | a, b | a > b | lớn hơn uint256 | |
| 12 | SLT | 3 | a, b | a < b | nhỏ hơn int256 | |
| 13 | SGT | 3 | a, b | a > b | lớn hơn int256 | |
| 14 | EQ | 3 | a, b | a == b | bằng nhau (u)int256 | |
| 15 | ISZERO | 3 | a | a == 0 | (u)int256 bằng không | |
| 16 | AND | 3 | a, b | a && b | AND theo bit | |
| 17 | OR | 3 | a, b | a || b | OR theo bit | |
| 18 | XOR | 3 | a, b | a ^ b | XOR theo bit | |
| 19 | NOT | 3 | a | ~a | NOT theo bit | |
| 1A | BYTE | 3 | i, x | (x >> (248 - i * 8)) && 0xFF | byte thứ i của (u)int256 x, từ trái sang | |
| 1B | SHL | 3 | shift, val | val << shift | dịch trái | |
| 1C | SHR | 3 | shift, val | val >> shift | dịch phải logic | |
| 1D | SAR | 3 | shift, val | val >> shift | dịch phải số học | |
| 1E-1F | không hợp lệ | |||||
| 20 | KECCAK256 | A2 (mở trong tab mới) | ost, len | keccak256(mem[ost:ost+len-1]) | keccak256 | |
| 21-2F | không hợp lệ | |||||
| 30 | ADDRESS | 2 | . | address(this) | địa chỉ của hợp đồng đang thực thi | |
| 31 | BALANCE | A5 (mở trong tab mới) | addr | addr.balance | số dư, tính bằng Wei | |
| 32 | ORIGIN | 2 | . | tx.origin | địa chỉ đã khởi tạo giao dịch | |
| 33 | CALLER | 2 | . | msg.sender | địa chỉ của người gửi tin nhắn | |
| 34 | CALLVALUE | 2 | . | msg.value | giá trị tin nhắn, tính bằng Wei | |
| 35 | CALLDATALOAD | 3 | idx | msg.data[idx:idx+32] | đọc từ (word) từ dữ liệu tin nhắn tại chỉ số idx | |
| 36 | CALLDATASIZE | 2 | . | len(msg.data) | độ dài của dữ liệu tin nhắn, tính bằng byte | |
| 37 | CALLDATACOPY | A3 (mở trong tab mới) | dstOst, ost, len | . | mem[dstOst:dstOst+len-1] := msg.data[ost:ost+len-1] | sao chép dữ liệu tin nhắn |
| 38 | CODESIZE | 2 | . | len(this.code) | độ dài mã của hợp đồng đang thực thi, tính bằng byte | |
| 39 | CODECOPY | A3 (mở trong tab mới) | dstOst, ost, len | . | mem[dstOst:dstOst+len-1] := this.code[ost:ost+len-1] | |
| 3A | GASPRICE | 2 | . | tx.gasprice | giá gas của giao dịch, tính bằng Wei trên mỗi đơn vị Gas ** (mở trong tab mới) | |
| 3B | EXTCODESIZE | A5 (mở trong tab mới) | addr | len(addr.code) | kích thước mã tại addr, tính bằng byte | |
| 3C | EXTCODECOPY | A4 (mở trong tab mới) | addr, dstOst, ost, len | . | mem[dstOst:dstOst+len-1] := addr.code[ost:ost+len-1] | sao chép mã từ addr |
| 3D | RETURNDATASIZE | 2 | . | size | kích thước dữ liệu trả về từ lệnh gọi bên ngoài cuối cùng, tính bằng byte | |
| 3E | RETURNDATACOPY | A3 (mở trong tab mới) | dstOst, ost, len | . | mem[dstOst:dstOst+len-1] := returndata[ost:ost+len-1] | sao chép dữ liệu trả về từ lệnh gọi bên ngoài cuối cùng |
| 3F | EXTCODEHASH | A5 (mở trong tab mới) | addr | hash | hash = addr.exists ? keccak256(addr.code) : 0 | |
| 40 | BLOCKHASH | 20 | blockNum | blockHash(blockNum) | ||
| 41 | COINBASE | 2 | . | block.coinbase | địa chỉ của người đề xuất khối hiện tại | |
| 42 | TIMESTAMP | 2 | . | block.timestamp | dấu thời gian của khối hiện tại | |
| 43 | NUMBER | 2 | . | block.number | số của khối hiện tại | |
| 44 | PREVRANDAO | 2 | . | randomness beacon | báo hiệu tính ngẫu nhiên | |
| 45 | GASLIMIT | 2 | . | block.gaslimit | giới hạn gas của khối hiện tại | |
| 46 | CHAINID | 2 | . | chain_id | đẩy chain id (mở trong tab mới) hiện tại vào ngăn xếp | |
| 47 | SELFBALANCE | 5 | . | address(this).balance | số dư của hợp đồng đang thực thi, tính bằng Wei | |
| 48 | BASEFEE | 2 | . | block.basefee | phí cơ sở của khối hiện tại | |
| 49 | BLOBHASH | 3 | idx | tx.blob_versioned_hashes[idx] | EIP-4844 (mở trong tab mới) | |
| 4A | BLOBBASEFEE | 2 | . | block.blobbasefee | phí cơ sở khối dữ liệu của khối hiện tại (EIP-7516 (mở trong tab mới)) | |
| 4B-4F | không hợp lệ | |||||
| 50 | POP | 2 | _anon | . | xóa mục khỏi đỉnh ngăn xếp và loại bỏ nó | |
| 51 | MLOAD | 3* (mở trong tab mới) | ost | mem[ost:ost+32] | đọc từ (word) từ bộ nhớ tại độ lệch ost | |
| 52 | MSTORE | 3* (mở trong tab mới) | ost, val | . | mem[ost:ost+32] := val | ghi một từ (word) vào bộ nhớ |
| 53 | MSTORE8 | 3* (mở trong tab mới) | ost, val | . | mem[ost] := val && 0xFF | ghi một byte duy nhất vào bộ nhớ |
| 54 | SLOAD | A6 (mở trong tab mới) | key | storage[key] | đọc từ (word) từ bộ lưu trữ | |
| 55 | SSTORE | A7 (mở trong tab mới) | key, val | . | storage[key] := val | ghi từ (word) vào bộ lưu trữ |
| 56 | JUMP | 8 | dst | . | $pc := dst đánh dấu rằng pc chỉ được gán nếu dst là một jumpdest hợp lệ | |
| 57 | JUMPI | 10 | dst, condition | . | $pc := condition ? dst : $pc + 1 | |
| 58 | PC | 2 | . | $pc | bộ đếm chương trình | |
| 59 | MSIZE | 2 | . | len(mem) | kích thước bộ nhớ trong ngữ cảnh thực thi hiện tại, tính bằng byte | |
| 5A | GAS | 2 | . | gasRemaining | ||
| 5B | JUMPDEST | 1 | đánh dấu đích nhảy hợp lệ | một đích nhảy hợp lệ, ví dụ như một đích nhảy không nằm trong dữ liệu push | ||
| 5C | TLOAD | 100 | key | tstorage[key] | đọc từ (word) từ bộ lưu trữ tạm thời (EIP-1153 (mở trong tab mới)) | |
| 5D | TSTORE | 100 | key, val | . | tstorage[key] := val | ghi từ (word) vào bộ lưu trữ tạm thời (EIP-1153 (mở trong tab mới)) |
| 5E | MCOPY | 3+3*words+A0 (mở trong tab mới) | dstOst, ost, len | . | mem[dstOst] := mem[ost:ost+len] | sao chép bộ nhớ từ khu vực này sang khu vực khác (EIP-5656 (mở trong tab mới)) |
| 5F | PUSH0 | 2 | . | uint8 | đẩy giá trị hằng số 0 vào ngăn xếp | |
| 60 | PUSH1 | 3 | . | uint8 | đẩy giá trị 1 byte vào ngăn xếp | |
| 61 | PUSH2 | 3 | . | uint16 | đẩy giá trị 2 byte vào ngăn xếp | |
| 62 | PUSH3 | 3 | . | uint24 | đẩy giá trị 3 byte vào ngăn xếp | |
| 63 | PUSH4 | 3 | . | uint32 | đẩy giá trị 4 byte vào ngăn xếp | |
| 64 | PUSH5 | 3 | . | uint40 | đẩy giá trị 5 byte vào ngăn xếp | |
| 65 | PUSH6 | 3 | . | uint48 | đẩy giá trị 6 byte vào ngăn xếp | |
| 66 | PUSH7 | 3 | . | uint56 | đẩy giá trị 7 byte vào ngăn xếp | |
| 67 | PUSH8 | 3 | . | uint64 | đẩy giá trị 8 byte vào ngăn xếp | |
| 68 | PUSH9 | 3 | . | uint72 | đẩy giá trị 9 byte vào ngăn xếp | |
| 69 | PUSH10 | 3 | . | uint80 | đẩy giá trị 10 byte vào ngăn xếp | |
| 6A | PUSH11 | 3 | . | uint88 | đẩy giá trị 11 byte vào ngăn xếp | |
| 6B | PUSH12 | 3 | . | uint96 | đẩy giá trị 12 byte vào ngăn xếp | |
| 6C | PUSH13 | 3 | . | uint104 | đẩy giá trị 13 byte vào ngăn xếp | |
| 6D | PUSH14 | 3 | . | uint112 | đẩy giá trị 14 byte vào ngăn xếp | |
| 6E | PUSH15 | 3 | . | uint120 | đẩy giá trị 15 byte vào ngăn xếp | |
| 6F | PUSH16 | 3 | . | uint128 | đẩy giá trị 16 byte vào ngăn xếp | |
| 70 | PUSH17 | 3 | . | uint136 | đẩy giá trị 17 byte vào ngăn xếp | |
| 71 | PUSH18 | 3 | . | uint144 | đẩy giá trị 18 byte vào ngăn xếp | |
| 72 | PUSH19 | 3 | . | uint152 | đẩy giá trị 19 byte vào ngăn xếp | |
| 73 | PUSH20 | 3 | . | uint160 | đẩy giá trị 20 byte vào ngăn xếp | |
| 74 | PUSH21 | 3 | . | uint168 | đẩy giá trị 21 byte vào ngăn xếp | |
| 75 | PUSH22 | 3 | . | uint176 | đẩy giá trị 22 byte vào ngăn xếp | |
| 76 | PUSH23 | 3 | . | uint184 | đẩy giá trị 23 byte vào ngăn xếp | |
| 77 | PUSH24 | 3 | . | uint192 | đẩy giá trị 24 byte vào ngăn xếp | |
| 78 | PUSH25 | 3 | . | uint200 | đẩy giá trị 25 byte vào ngăn xếp | |
| 79 | PUSH26 | 3 | . | uint208 | đẩy giá trị 26 byte vào ngăn xếp | |
| 7A | PUSH27 | 3 | . | uint216 | đẩy giá trị 27 byte vào ngăn xếp | |
| 7B | PUSH28 | 3 | . | uint224 | đẩy giá trị 28 byte vào ngăn xếp | |
| 7C | PUSH29 | 3 | . | uint232 | đẩy giá trị 29 byte vào ngăn xếp | |
| 7D | PUSH30 | 3 | . | uint240 | đẩy giá trị 30 byte vào ngăn xếp | |
| 7E | PUSH31 | 3 | . | uint248 | đẩy giá trị 31 byte vào ngăn xếp | |
| 7F | PUSH32 | 3 | . | uint256 | đẩy giá trị 32 byte vào ngăn xếp | |
| 80 | DUP1 | 3 | a | a, a | nhân bản giá trị thứ 1 trên ngăn xếp | |
| 81 | DUP2 | 3 | _, a | a, _, a | nhân bản giá trị thứ 2 trên ngăn xếp | |
| 82 | DUP3 | 3 | _, _, a | a, _, _, a | nhân bản giá trị thứ 3 trên ngăn xếp | |
| 83 | DUP4 | 3 | _, _, _, a | a, _, _, _, a | nhân bản giá trị thứ 4 trên ngăn xếp | |
| 84 | DUP5 | 3 | ..., a | a, ..., a | nhân bản giá trị thứ 5 trên ngăn xếp | |
| 85 | DUP6 | 3 | ..., a | a, ..., a | nhân bản giá trị thứ 6 trên ngăn xếp | |
| 86 | DUP7 | 3 | ..., a | a, ..., a | nhân bản giá trị thứ 7 trên ngăn xếp | |
| 87 | DUP8 | 3 | ..., a | a, ..., a | nhân bản giá trị thứ 8 trên ngăn xếp | |
| 88 | DUP9 | 3 | ..., a | a, ..., a | nhân bản giá trị thứ 9 trên ngăn xếp | |
| 89 | DUP10 | 3 | ..., a | a, ..., a | nhân bản giá trị thứ 10 trên ngăn xếp | |
| 8A | DUP11 | 3 | ..., a | a, ..., a | nhân bản giá trị thứ 11 trên ngăn xếp | |
| 8B | DUP12 | 3 | ..., a | a, ..., a | nhân bản giá trị thứ 12 trên ngăn xếp | |
| 8C | DUP13 | 3 | ..., a | a, ..., a | nhân bản giá trị thứ 13 trên ngăn xếp | |
| 8D | DUP14 | 3 | ..., a | a, ..., a | nhân bản giá trị thứ 14 trên ngăn xếp | |
| 8E | DUP15 | 3 | ..., a | a, ..., a | nhân bản giá trị thứ 15 trên ngăn xếp | |
| 8F | DUP16 | 3 | ..., a | a, ..., a | nhân bản giá trị thứ 16 trên ngăn xếp | |
| 90 | SWAP1 | 3 | a, b | b, a | ||
| 91 | SWAP2 | 3 | a, _, b | b, _, a | ||
| 92 | SWAP3 | 3 | a, _, _, b | b, _, _, a | ||
| 93 | SWAP4 | 3 | a, _, _, _, b | b, _, _, _, a | ||
| 94 | SWAP5 | 3 | a, ..., b | b, ..., a | ||
| 95 | SWAP6 | 3 | a, ..., b | b, ..., a | ||
| 96 | SWAP7 | 3 | a, ..., b | b, ..., a | ||
| 97 | SWAP8 | 3 | a, ..., b | b, ..., a | ||
| 98 | SWAP9 | 3 | a, ..., b | b, ..., a | ||
| 99 | SWAP10 | 3 | a, ..., b | b, ..., a | ||
| 9A | SWAP11 | 3 | a, ..., b | b, ..., a | ||
| 9B | SWAP12 | 3 | a, ..., b | b, ..., a | ||
| 9C | SWAP13 | 3 | a, ..., b | b, ..., a | ||
| 9D | SWAP14 | 3 | a, ..., b | b, ..., a | ||
| 9E | SWAP15 | 3 | a, ..., b | b, ..., a | ||
| 9F | SWAP16 | 3 | a, ..., b | b, ..., a | ||
| A0 | LOG0 | A8 (mở trong tab mới) | ost, len | . | LOG0(memory[ost:ost+len-1]) | |
| A1 | LOG1 | A8 (mở trong tab mới) | ost, len, topic0 | . | LOG1(memory[ost:ost+len-1], topic0) | |
| A2 | LOG2 | A8 (mở trong tab mới) | ost, len, topic0, topic1 | . | LOG2(memory[ost:ost+len-1], topic0, topic1) | |
| A3 | LOG3 | A8 (mở trong tab mới) | ost, len, topic0, topic1, topic2 | . | LOG3(memory[ost:ost+len-1], topic0, topic1, topic2) | |
| A4 | LOG4 | A8 (mở trong tab mới) | ost, len, topic0, topic1, topic2, topic3 | . | LOG4(memory[ost:ost+len-1], topic0, topic1, topic2, topic3) | |
| A5-EF | không hợp lệ | |||||
| F0 | CREATE | A9 (mở trong tab mới) | val, ost, len | addr | addr = keccak256(rlp([address(this), this.nonce])) | |
| F1 | CALL | AA (mở trong tab mới) | gas, addr, val, argOst, argLen, retOst, retLen | success | mem[retOst:retOst+retLen-1] := returndata | |
| F2 | CALLCODE | AA (mở trong tab mới) | gas, addr, val, argOst, argLen, retOst, retLen | success | mem[retOst:retOst+retLen-1] = returndata | giống như DELEGATECALL, nhưng không truyền msg.sender và msg.value ban đầu |
| F3 | RETURN | 0* (mở trong tab mới) | ost, len | . | return mem[ost:ost+len-1] | |
| F4 | DELEGATECALL | AA (mở trong tab mới) | gas, addr, argOst, argLen, retOst, retLen | success | mem[retOst:retOst+retLen-1] := returndata | |
| F5 | CREATE2 | A9 (mở trong tab mới) | val, ost, len, salt | addr | addr = keccak256(0xff ++ address(this) ++ salt ++ keccak256(mem[ost:ost+len-1]))[12:] | |
| F6-F9 | không hợp lệ | |||||
| FA | STATICCALL | AA (mở trong tab mới) | gas, addr, argOst, argLen, retOst, retLen | success | mem[retOst:retOst+retLen-1] := returndata | |
| FB-FC | không hợp lệ | |||||
| FD | REVERT | 0* (mở trong tab mới) | ost, len | . | revert(mem[ost:ost+len-1]) | |
| FE | INVALID | AF (mở trong tab mới) | mã lệnh không hợp lệ được chỉ định - EIP-141 (mở trong tab mới) | |||
| FF | SELFDESTRUCT | AB (mở trong tab mới) | addr | . | gửi tất cả ETH đến addr; nếu được thực thi trong cùng một giao dịch khi hợp đồng được tạo, nó sẽ phá hủy hợp đồng |