diff --git a/core/vm/instructions.go b/core/vm/instructions.go index baf6df8117..a57e9caa0f 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -973,11 +973,11 @@ func opDupN(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { code := scope.Contract.Code i := *pc + 1 - // Ensure an immediate byte exists after DUPN - if i >= uint64(len(code)) { - return nil, &ErrInvalidOpCode{opcode: INVALID} + // If the immediate byte is missing, treat as 0x00 (same convention as PUSHn). + var x byte + if i < uint64(len(code)) { + x = code[i] } - x := code[i] // This range is excluded to preserve compatibility with existing opcodes. if x > 90 && x < 128 { @@ -1000,11 +1000,11 @@ func opSwapN(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { code := scope.Contract.Code i := *pc + 1 - // Ensure an immediate byte exists after SWAPN - if i >= uint64(len(code)) { - return nil, &ErrInvalidOpCode{opcode: INVALID} + // If the immediate byte is missing, treat as 0x00 (same convention as PUSHn). + var x byte + if i < uint64(len(code)) { + x = code[i] } - x := code[i] // This range is excluded to preserve compatibility with existing opcodes. if x > 90 && x < 128 { @@ -1029,11 +1029,11 @@ func opExchange(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { code := scope.Contract.Code i := *pc + 1 - // Ensure an immediate byte exists after EXCHANGE - if i >= uint64(len(code)) { - return nil, &ErrInvalidOpCode{opcode: INVALID} + // If the immediate byte is missing, treat as 0x00 (same convention as PUSHn). + var x byte + if i < uint64(len(code)) { + x = code[i] } - x := code[i] // This range is excluded both to preserve compatibility with existing opcodes // and to keep decode_pair’s 16-aligned arithmetic mapping valid (0–79, 128–255). diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index f38da7fb22..56cb2686a6 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -1027,6 +1027,15 @@ func TestEIP8024_Execution(t *testing.T) { 1, }, }, + { + name: "DUPN_MISSING_IMMEDIATE", + codeHex: "60016000808080808080808080808080808080e6", + wantVals: []uint64{ + 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, + }, + }, { name: "SWAPN", codeHex: "600160008080808080808080808080808080806002e700", @@ -1036,11 +1045,29 @@ func TestEIP8024_Execution(t *testing.T) { 2, }, }, + { + name: "SWAPN_MISSING_IMMEDIATE", + codeHex: "600160008080808080808080808080808080806002e7", + wantVals: []uint64{ + 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, + }, + }, { name: "EXCHANGE", codeHex: "600060016002e801", wantVals: []uint64{2, 0, 1}, }, + { + name: "EXCHANGE_MISSING_IMMEDIATE", + codeHex: "600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060016002e8", + wantVals: []uint64{ + 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, + }, + }, { name: "INVALID_SWAPN_LOW", codeHex: "e75b", @@ -1092,21 +1119,6 @@ func TestEIP8024_Execution(t *testing.T) { codeHex: "60016002e801", // (n,m)=(1,2), need 3 items, have 2 wantErr: true, }, - { - name: "MISSING_IMMEDIATE_DUPN", - codeHex: "e6", // no operand - wantErr: true, - }, - { - name: "MISSING_IMMEDIATE_SWAPN", - codeHex: "e7", // no operand - wantErr: true, - }, - { - name: "MISSING_IMMEDIATE_EXCHANGE", - codeHex: "e8", // no operand - wantErr: true, - }, { name: "PC_INCREMENT", codeHex: "600060006000e80115", @@ -1123,25 +1135,25 @@ func TestEIP8024_Execution(t *testing.T) { var err error for pc < uint64(len(code)) && err == nil { op := code[pc] - switch op { - case 0x00: + switch OpCode(op) { + case STOP: return - case 0x60: + case PUSH1: _, err = opPush1(&pc, evm, scope) - case 0x80: + case DUP1: dup1 := makeDup(1) _, err = dup1(&pc, evm, scope) - case 0x56: + case JUMP: _, err = opJump(&pc, evm, scope) - case 0x5b: + case JUMPDEST: _, err = opJumpdest(&pc, evm, scope) - case 0x15: + case ISZERO: _, err = opIszero(&pc, evm, scope) - case 0xe6: + case DUPN: _, err = opDupN(&pc, evm, scope) - case 0xe7: + case SWAPN: _, err = opSwapN(&pc, evm, scope) - case 0xe8: + case EXCHANGE: _, err = opExchange(&pc, evm, scope) default: err = &ErrInvalidOpCode{opcode: OpCode(op)}