diff --git a/core/vm/instructions.go b/core/vm/instructions.go index cc225e484f48f..1e91ff255c6f2 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -801,6 +801,10 @@ func opRevert(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b return ret, ErrExecutionReverted } +func opUndefined(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + return nil, &ErrInvalidOpCode{opcode: OpCode(scope.Contract.Code[*pc])} +} + func opStop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { return nil, errStopToken } diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 99257d57a8315..a4c54b1fb84b7 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -193,9 +193,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 676cfc06093ec..bb559b594999f 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -200,7 +200,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, @@ -1002,4 +1002,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 }