Mã lệnh cho EVM
Tổng quan
Đây là phiên bản cập nhật của trang tham khảo EVM tại wolflo/evm-opcodes (opens in a new tab). Cũng được trích xuất từ sách vàng (opens in a new tab), Jello Paper (opens in a new tab), và bản triển khai geth (opens in a new tab). 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 nó 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 được 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 (opens in a new tab).
Đối với các hoạt động có chi phí Gas động, hãy xem gas.md (opens in a new tab).
💡 Mẹo nhanh: Để xem toàn bộ các dòng, hãy sử dụng [shift] + scroll để 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 (opens in a new tab) | 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 (opens in a new tab) x từ (b+1) byte thành 32 byte | |
| 0C-0F | không hợp lệ | |||||
| 10 | LT | 3 | a, b | a < b | uint256 nhỏ hơn | |
| 11 | GT | 3 | a, b | a > b | uint256 lớn hơn | |
| 12 | SLT | 3 | a, b | a < b | int256 nhỏ hơn | |
| 13 | SGT | 3 | a, b | a > b | int256 lớn hơn | |
| 14 | EQ | 3 | a, b | a == b | (u)int256 bằng nhau | |
| 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 (opens in a new tab) | 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 (opens in a new tab) | 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 msg | |
| 34 | CALLVALUE | 2 | . | msg.value | giá trị msg, tính bằng Wei | |
| 35 | CALLDATALOAD | 3 | idx | msg.data[idx:idx+32] | đọc word từ dữ liệu msg tại chỉ số idx | |
| 36 | CALLDATASIZE | 2 | . | len(msg.data) | độ dài của dữ liệu msg, tính bằng byte | |
| 37 | CALLDATACOPY | A3 (opens in a new tab) | dstOst, ost, len | . | mem[dstOst:dstOst+len-1] := msg.data[ost:ost+len-1] | sao chép dữ liệu msg |
| 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 (opens in a new tab) | 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 cho mỗi đơn vị gas ** (opens in a new tab) | |
| 3B | EXTCODESIZE | A5 (opens in a new tab) | addr | len(addr.code) | kích thước mã tại địa chỉ, tính bằng byte | |
| 3C | EXTCODECOPY | A4 (opens in a new tab) | 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 (opens in a new tab) | 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 (opens in a new tab) | addr | hash | mã băm = 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 | beacon 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 ID chuỗi (opens in a new tab) 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 (opens in a new tab) | |
| 4A | BLOBBASEFEE | 2 | . | block.blobbasefee | phí cơ sở khối dữ liệu của khối hiện tại (EIP-7516 (opens in a new tab)) | |
| 4B-4F | không hợp lệ | |||||
| 50 | POP | 2 | _anon | . | xóa mục ở đầu ngăn xếp và loại bỏ nó | |
| 51 | MLOAD | 3* (opens in a new tab) | ost | mem[ost:ost+32] | đọc word từ bộ nhớ tại offset ost | |
| 52 | MSTORE | 3* (opens in a new tab) | ost, val | . | mem[ost:ost+32] := val | ghi một word vào bộ nhớ |
| 53 | MSTORE8 | 3* (opens in a new tab) | ost, val | . | mem[ost] := val && 0xFF | ghi một byte đơn vào bộ nhớ |
| 54 | SLOAD | A6 (opens in a new tab) | key | storage[key] | đọc word từ lưu trữ | |
| 55 | SSTORE | A7 (opens in a new tab) | key, val | . | storage[key] := val | ghi word vào 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 word từ lưu trữ tạm thời (EIP-1153 (opens in a new tab)) | |
| 5D | TSTORE | 100 | key, val | . | tstorage[key] := val | ghi word vào lưu trữ tạm thời (EIP-1153 (opens in a new tab)) |
| 5E | MCOPY | 3+3*words+A0 (opens in a new tab) | dstOst, ost, len | . | mem[dstOst] := mem[ost:ost+len] | sao chép bộ nhớ từ vùng này sang vùng khác (EIP-5656 (opens in a new tab)) |
| 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 | sao chép giá trị thứ 1 trên ngăn xếp | |
| 81 | DUP2 | 3 | _, a | a, _, a | sao chép giá trị thứ 2 trên ngăn xếp | |
| 82 | DUP3 | 3 | _, _, a | a, _, _, a | sao chép giá trị thứ 3 trên ngăn xếp | |
| 83 | DUP4 | 3 | _, _, _, a | a, _, _, _, a | sao chép giá trị thứ 4 trên ngăn xếp | |
| 84 | DUP5 | 3 | ..., a | a, ..., a | sao chép giá trị thứ 5 trên ngăn xếp | |
| 85 | DUP6 | 3 | ..., a | a, ..., a | sao chép giá trị thứ 6 trên ngăn xếp | |
| 86 | DUP7 | 3 | ..., a | a, ..., a | sao chép giá trị thứ 7 trên ngăn xếp | |
| 87 | DUP8 | 3 | ..., a | a, ..., a | sao chép giá trị thứ 8 trên ngăn xếp | |
| 88 | DUP9 | 3 | ..., a | a, ..., a | sao chép giá trị thứ 9 trên ngăn xếp | |
| 89 | DUP10 | 3 | ..., a | a, ..., a | sao chép giá trị thứ 10 trên ngăn xếp | |
| 8A | DUP11 | 3 | ..., a | a, ..., a | sao chép giá trị thứ 11 trên ngăn xếp | |
| 8B | DUP12 | 3 | ..., a | a, ..., a | sao chép giá trị thứ 12 trên ngăn xếp | |
| 8C | DUP13 | 3 | ..., a | a, ..., a | sao chép giá trị thứ 13 trên ngăn xếp | |
| 8D | DUP14 | 3 | ..., a | a, ..., a | sao chép giá trị thứ 14 trên ngăn xếp | |
| 8E | DUP15 | 3 | ..., a | a, ..., a | sao chép giá trị thứ 15 trên ngăn xếp | |
| 8F | DUP16 | 3 | ..., a | a, ..., a | sao chép 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 (opens in a new tab) | ost, len | . | LOG0(memory[ost:ost+len-1]) | |
| A1 | LOG1 | A8 (opens in a new tab) | ost, len, topic0 | . | LOG1(memory[ost:ost+len-1], topic0) | |
| A2 | LOG2 | A8 (opens in a new tab) | ost, len, topic0, topic1 | . | LOG2(memory[ost:ost+len-1], topic0, topic1) | |
| A3 | LOG3 | A8 (opens in a new tab) | ost, len, topic0, topic1, topic2 | . | LOG3(memory[ost:ost+len-1], topic0, topic1, topic2) | |
| A4 | LOG4 | A8 (opens in a new tab) | 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 (opens in a new tab) | val, ost, len | addr | addr = keccak256(rlp([address(this), this.nonce])) | |
| F1 | CALL | AA (opens in a new tab) | gas, addr, val, argOst, argLen, retOst, retLen | success | mem[retOst:retOst+retLen-1] := returndata | |
| F2 | CALLCODE | AA (opens in a new tab) | 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* (opens in a new tab) | ost, len | . | return mem[ost:ost+len-1] | |
| F4 | DELEGATECALL | AA (opens in a new tab) | gas, addr, argOst, argLen, retOst, retLen | success | mem[retOst:retOst+retLen-1] := returndata | |
| F5 | CREATE2 | A9 (opens in a new tab) | 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 (opens in a new tab) | gas, addr, argOst, argLen, retOst, retLen | success | mem[retOst:retOst+retLen-1] := returndata | |
| FB-FC | không hợp lệ | |||||
| FD | REVERT | 0* (opens in a new tab) | ost, len | . | revert(mem[ost:ost+len-1]) | |
| FE | INVALID | AF (opens in a new tab) | mã lệnh không hợp lệ được chỉ định - EIP-141 (opens in a new tab) | |||
| FF | SELFDESTRUCT | AB (opens in a new tab) | addr | . | gửi toàn bộ ETH đến addr; nếu được thực thi trong cùng một giao dịch mà hợp đồng được tạo, nó sẽ phá hủy hợp đồng |