diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 3a361eb0e8..5dcf90b770 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -779,6 +779,10 @@ func opRevert(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([] return ret, ErrExecutionReverted } +func opUndefined(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { + return nil, &ErrInvalidOpCode{opcode: OpCode(callContext.contract.Code[*pc])} +} + func opStop(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { return nil, errStopToken } diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index eabf1dce19..51551678db 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -207,9 +207,6 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // enough stack items available to perform the operation. op = contract.GetOp(pc) operation := in.cfg.JumpTable[op] - if operation == nil { - return nil, &ErrInvalidOpCode{opcode: op} - } // Validate stack if sLen := stack.len(); sLen < operation.minStack { return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.minStack} diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 1b6f6d1d45..55ad78adc5 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -181,7 +181,7 @@ func newHomesteadInstructionSet() JumpTable { // newFrontierInstructionSet returns the frontier instructions // that can be executed during the frontier phase. func newFrontierInstructionSet() JumpTable { - return JumpTable{ + tbl := JumpTable{ STOP: { execute: opStop, constantGas: 0, @@ -983,4 +983,13 @@ func newFrontierInstructionSet() JumpTable { maxStack: maxStack(1, 0), }, } + + // Fill all unassigned slots with opUndefined. + for i, entry := range tbl { + if entry == nil { + tbl[i] = &operation{execute: opUndefined, maxStack: maxStack(0, 0)} + } + } + + return tbl }