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) 구현체에서도 내용을 가져왔습니다. 이 문서는 접근하기 쉬운 참조 자료로 작성되었으나, 특별히 엄밀하지는 않습니다. 정확성을 확신하고 모든 엣지 케이스를 파악하고 싶다면, 젤로 페이퍼나 클라이언트 구현체를 사용하는 것을 권장합니다.
대화형 참조 자료를 찾고 계신가요? evm.codes (opens in a new tab)를 확인해 보세요.
동적 가스 비용이 있는 연산에 대해서는 gas.md (opens in a new tab)를 참조하세요.
💡 간단한 팁: 전체 줄을 보려면 데스크톱에서 [shift] + scroll를 사용하여 가로로 스크롤하세요.
| 스택 | 이름 | 가스 | 초기 스택 | 결과 스택 | 메모리 / 스토리지 | 참고 |
|---|---|---|---|---|---|---|
| 00 | STOP | 0 | 실행 중지 | |||
| 01 | ADD | 3 | a, b | a + b | (u)int256 덧셈 모듈로 2**256 | |
| 02 | MUL | 5 | a, b | a * b | (u)int256 곱셈 모듈로 2**256 | |
| 03 | SUB | 3 | a, b | a - b | (u)int256 뺄셈 모듈로 2**256 | |
| 04 | DIV | 5 | a, b | a // b | uint256 나눗셈 | |
| 05 | SDIV | 5 | a, b | a // b | int256 나눗셈 | |
| 06 | MOD | 5 | a, b | a % b | uint256 모듈로 | |
| 07 | SMOD | 5 | a, b | a % b | int256 모듈로 | |
| 08 | ADDMOD | 8 | a, b, N | (a + b) % N | (u)int256 덧셈 모듈로 N | |
| 09 | MULMOD | 8 | a, b, N | (a * b) % N | (u)int256 곱셈 모듈로 N | |
| 0A | EXP | A1 (opens in a new tab) | a, b | a ** b | uint256 거듭제곱 모듈로 2**256 | |
| 0B | SIGNEXTEND | 5 | b, x | SIGNEXTEND(x, b) | (b+1) 바이트에서 32바이트로 x의 부호 확장(sign extend) (opens in a new tab) | |
| 0C-0F | 유효하지 않음 | |||||
| 10 | LT | 3 | a, b | a < b | uint256 미만 | |
| 11 | GT | 3 | a, b | a > b | uint256 초과 | |
| 12 | SLT | 3 | a, b | a < b | int256 미만 | |
| 13 | SGT | 3 | a, b | a > b | int256 초과 | |
| 14 | EQ | 3 | a, b | a == b | (u)int256 같음 | |
| 15 | ISZERO | 3 | a | a == 0 | (u)int256 0 여부 | |
| 16 | AND | 3 | a, b | a && b | 비트 단위 AND | |
| 17 | OR | 3 | a, b | a || b | 비트 단위 OR | |
| 18 | XOR | 3 | a, b | a ^ b | 비트 단위 XOR | |
| 19 | NOT | 3 | a | ~a | 비트 단위 NOT | |
| 1A | BYTE | 3 | i, x | (x >> (248 - i * 8)) && 0xFF | 왼쪽에서부터 (u)int256 x의 i번째 바이트 | |
| 1B | SHL | 3 | shift, val | val << shift | 왼쪽 시프트 | |
| 1C | SHR | 3 | shift, val | val >> shift | 논리적 오른쪽 시프트 | |
| 1D | SAR | 3 | shift, val | val >> shift | 산술적 오른쪽 시프트 | |
| 1E-1F | 유효하지 않음 | |||||
| 20 | KECCAK256 | A2 (opens in a new tab) | ost, len | keccak256(mem[ost:ost+len-1]) | keccak256 | |
| 21-2F | 유효하지 않음 | |||||
| 30 | ADDRESS | 2 | . | address(this) | 실행 중인 컨트랙트의 주소 | |
| 31 | BALANCE | A5 (opens in a new tab) | addr | addr.balance | 잔액 (Wei 단위) | |
| 32 | ORIGIN | 2 | . | tx.origin | 트랜잭션을 시작한 주소 | |
| 33 | CALLER | 2 | . | msg.sender | 메시지 발신자(msg sender)의 주소 | |
| 34 | CALLVALUE | 2 | . | msg.value | 메시지 값 (Wei 단위) | |
| 35 | CALLDATALOAD | 3 | idx | msg.data[idx:idx+32] | 인덱스 idx의 메시지 데이터에서 워드(word) 읽기 | |
| 36 | CALLDATASIZE | 2 | . | len(msg.data) | 메시지 데이터의 길이 (바이트 단위) | |
| 37 | CALLDATACOPY | A3 (opens in a new tab) | dstOst, ost, len | . | mem[dstOst:dstOst+len-1] := msg.data[ost:ost+len-1] | 메시지 데이터 복사 |
| 38 | CODESIZE | 2 | . | len(this.code) | 실행 중인 컨트랙트 코드의 길이 (바이트 단위) | |
| 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 | 트랜잭션의 가스 가격 (가스 단위당 Wei) ** (opens in a new tab) | |
| 3B | EXTCODESIZE | A5 (opens in a new tab) | addr | len(addr.code) | 해당 주소(addr)에 있는 코드의 크기 (바이트 단위) | |
| 3C | EXTCODECOPY | A4 (opens in a new tab) | addr, dstOst, ost, len | . | mem[dstOst:dstOst+len-1] := addr.code[ost:ost+len-1] | addr에서 코드 복사 |
| 3D | RETURNDATASIZE | 2 | . | size | 마지막 외부 호출에서 반환된 데이터의 크기 (바이트 단위) | |
| 3E | RETURNDATACOPY | A3 (opens in a new tab) | dstOst, ost, len | . | mem[dstOst:dstOst+len-1] := returndata[ost:ost+len-1] | 마지막 외부 호출에서 반환된 데이터 복사 |
| 3F | EXTCODEHASH | A5 (opens in a new tab) | addr | hash | hash = addr.exists ? keccak256(addr.code) : 0 | |
| 40 | BLOCKHASH | 20 | blockNum | blockHash(blockNum) | ||
| 41 | COINBASE | 2 | . | block.coinbase | 현재 블록 제안자의 주소 | |
| 42 | TIMESTAMP | 2 | . | block.timestamp | 현재 블록의 타임스탬프 | |
| 43 | NUMBER | 2 | . | block.number | 현재 블록의 번호 | |
| 44 | PREVRANDAO | 2 | . | randomness beacon | 무작위성 비컨 | |
| 45 | GASLIMIT | 2 | . | block.gaslimit | 현재 블록의 가스 한도 | |
| 46 | CHAINID | 2 | . | chain_id | 현재 체인 ID (opens in a new tab)를 스택에 푸시 | |
| 47 | SELFBALANCE | 5 | . | address(this).balance | 실행 중인 컨트랙트의 잔액 (Wei 단위) | |
| 48 | BASEFEE | 2 | . | block.basefee | 현재 블록의 기본 수수료 | |
| 49 | BLOBHASH | 3 | idx | tx.blob_versioned_hashes[idx] | EIP-4844 (opens in a new tab) | |
| 4A | BLOBBASEFEE | 2 | . | block.blobbasefee | 현재 블록의 블롭 기본 수수료 (EIP-7516 (opens in a new tab)) | |
| 4B-4F | 유효하지 않음 | |||||
| 50 | POP | 2 | _anon | . | 스택의 맨 위에서 항목을 제거하고 버림 | |
| 51 | MLOAD | 3* (opens in a new tab) | ost | mem[ost:ost+32] | 오프셋 ost의 메모리에서 워드(word) 읽기 | |
| 52 | MSTORE | 3* (opens in a new tab) | ost, val | . | mem[ost:ost+32] := val | 메모리에 워드(word) 쓰기 |
| 53 | MSTORE8 | 3* (opens in a new tab) | ost, val | . | mem[ost] := val && 0xFF | 메모리에 단일 바이트 쓰기 |
| 54 | SLOAD | A6 (opens in a new tab) | key | storage[key] | 스토리지에서 워드(word) 읽기 | |
| 55 | SSTORE | A7 (opens in a new tab) | key, val | . | storage[key] := val | 스토리지에 워드(word) 쓰기 |
| 56 | JUMP | 8 | dst | . | $pc := dst는 dst이 유효한 jumpdest인 경우에만 pc가 할당됨을 나타냄 | |
| 57 | JUMPI | 10 | dst, condition | . | $pc := condition ? dst : $pc + 1 | |
| 58 | PC | 2 | . | $pc | 프로그램 카운터 | |
| 59 | MSIZE | 2 | . | len(mem) | 현재 실행 컨텍스트의 메모 크기 (바이트 단위) | |
| 5A | GAS | 2 | . | gasRemaining | ||
| 5B | JUMPDEST | 1 | 유효한 점프 목적지 표시 | 유효한 점프 목적지 (예: 푸시 데이터 내부에 있지 않은 점프 목적지) | ||
| 5C | TLOAD | 100 | key | tstorage[key] | 임시 스토리지(transient storage)에서 워드(word) 읽기 (EIP-1153 (opens in a new tab)) | |
| 5D | TSTORE | 100 | key, val | . | tstorage[key] := val | 임시 스토리지(transient storage)에 워드(word) 쓰기 (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] | 한 영역에서 다른 영역으로 메모리 복사 (EIP-5656 (opens in a new tab)) |
| 5F | PUSH0 | 2 | . | uint8 | 상수 값 0을 스택에 푸시 | |
| 60 | PUSH1 | 3 | . | uint8 | 1바이트 값을 스택에 푸시 | |
| 61 | PUSH2 | 3 | . | uint16 | 2바이트 값을 스택에 푸시 | |
| 62 | PUSH3 | 3 | . | uint24 | 3바이트 값을 스택에 푸시 | |
| 63 | PUSH4 | 3 | . | uint32 | 4바이트 값을 스택에 푸시 | |
| 64 | PUSH5 | 3 | . | uint40 | 5바이트 값을 스택에 푸시 | |
| 65 | PUSH6 | 3 | . | uint48 | 6바이트 값을 스택에 푸시 | |
| 66 | PUSH7 | 3 | . | uint56 | 7바이트 값을 스택에 푸시 | |
| 67 | PUSH8 | 3 | . | uint64 | 8바이트 값을 스택에 푸시 | |
| 68 | PUSH9 | 3 | . | uint72 | 9바이트 값을 스택에 푸시 | |
| 69 | PUSH10 | 3 | . | uint80 | 10바이트 값을 스택에 푸시 | |
| 6A | PUSH11 | 3 | . | uint88 | 11바이트 값을 스택에 푸시 | |
| 6B | PUSH12 | 3 | . | uint96 | 12바이트 값을 스택에 푸시 | |
| 6C | PUSH13 | 3 | . | uint104 | 13바이트 값을 스택에 푸시 | |
| 6D | PUSH14 | 3 | . | uint112 | 14바이트 값을 스택에 푸시 | |
| 6E | PUSH15 | 3 | . | uint120 | 15바이트 값을 스택에 푸시 | |
| 6F | PUSH16 | 3 | . | uint128 | 16바이트 값을 스택에 푸시 | |
| 70 | PUSH17 | 3 | . | uint136 | 17바이트 값을 스택에 푸시 | |
| 71 | PUSH18 | 3 | . | uint144 | 18바이트 값을 스택에 푸시 | |
| 72 | PUSH19 | 3 | . | uint152 | 19바이트 값을 스택에 푸시 | |
| 73 | PUSH20 | 3 | . | uint160 | 20바이트 값을 스택에 푸시 | |
| 74 | PUSH21 | 3 | . | uint168 | 21바이트 값을 스택에 푸시 | |
| 75 | PUSH22 | 3 | . | uint176 | 22바이트 값을 스택에 푸시 | |
| 76 | PUSH23 | 3 | . | uint184 | 23바이트 값을 스택에 푸시 | |
| 77 | PUSH24 | 3 | . | uint192 | 24바이트 값을 스택에 푸시 | |
| 78 | PUSH25 | 3 | . | uint200 | 25바이트 값을 스택에 푸시 | |
| 79 | PUSH26 | 3 | . | uint208 | 26바이트 값을 스택에 푸시 | |
| 7A | PUSH27 | 3 | . | uint216 | 27바이트 값을 스택에 푸시 | |
| 7B | PUSH28 | 3 | . | uint224 | 28바이트 값을 스택에 푸시 | |
| 7C | PUSH29 | 3 | . | uint232 | 29바이트 값을 스택에 푸시 | |
| 7D | PUSH30 | 3 | . | uint240 | 30바이트 값을 스택에 푸시 | |
| 7E | PUSH31 | 3 | . | uint248 | 31바이트 값을 스택에 푸시 | |
| 7F | PUSH32 | 3 | . | uint256 | 32바이트 값을 스택에 푸시 | |
| 80 | DUP1 | 3 | a | a, a | 스택의 1번째 값 복제 | |
| 81 | DUP2 | 3 | _, a | a, _, a | 스택의 2번째 값 복제 | |
| 82 | DUP3 | 3 | _, _, a | a, _, _, a | 스택의 3번째 값 복제 | |
| 83 | DUP4 | 3 | _, _, _, a | a, _, _, _, a | 스택의 4번째 값 복제 | |
| 84 | DUP5 | 3 | ..., a | a, ..., a | 스택의 5번째 값 복제 | |
| 85 | DUP6 | 3 | ..., a | a, ..., a | 스택의 6번째 값 복제 | |
| 86 | DUP7 | 3 | ..., a | a, ..., a | 스택의 7번째 값 복제 | |
| 87 | DUP8 | 3 | ..., a | a, ..., a | 스택의 8번째 값 복제 | |
| 88 | DUP9 | 3 | ..., a | a, ..., a | 스택의 9번째 값 복제 | |
| 89 | DUP10 | 3 | ..., a | a, ..., a | 스택의 10번째 값 복제 | |
| 8A | DUP11 | 3 | ..., a | a, ..., a | 스택의 11번째 값 복제 | |
| 8B | DUP12 | 3 | ..., a | a, ..., a | 스택의 12번째 값 복제 | |
| 8C | DUP13 | 3 | ..., a | a, ..., a | 스택의 13번째 값 복제 | |
| 8D | DUP14 | 3 | ..., a | a, ..., a | 스택의 14번째 값 복제 | |
| 8E | DUP15 | 3 | ..., a | a, ..., a | 스택의 15번째 값 복제 | |
| 8F | DUP16 | 3 | ..., a | a, ..., a | 스택의 16번째 값 복제 | |
| 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 | 유효하지 않음 | |||||
| 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 | DELEGATECALL과 동일하지만, 원래의 msg.sender 및 msg.value를 전달하지 않음 |
| 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 | 유효하지 않음 | |||||
| FA | STATICCALL | AA (opens in a new tab) | gas, addr, argOst, argLen, retOst, retLen | success | mem[retOst:retOst+retLen-1] := returndata | |
| FB-FC | 유효하지 않음 | |||||
| FD | REVERT | 0* (opens in a new tab) | ost, len | . | revert(mem[ost:ost+len-1]) | |
| FE | INVALID | AF (opens in a new tab) | 지정된 유효하지 않은 연산 코드 - EIP-141 (opens in a new tab) | |||
| FF | SELFDESTRUCT | AB (opens in a new tab) | addr | . | 모든 ETH를 addr(으)로 보냄; 컨트랙트가 생성된 것과 동일한 트랜잭션에서 실행되는 경우 컨트랙트를 파기함 |