diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 4d6197912..b3b7310dd 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -718,7 +718,14 @@ func opReturn(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S ret := memory.GetPtr(offset.Int64(), size.Int64()) evm.interpreter.intPool.put(offset, size) + return ret, nil +} +func opRevert(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + offset, size := stack.pop(), stack.pop() + ret := memory.GetPtr(offset.Int64(), size.Int64()) + + evm.interpreter.intPool.put(offset, size) return ret, nil } @@ -731,7 +738,6 @@ func opSuicide(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack * evm.StateDB.AddBalance(common.BigToAddress(stack.pop()), balance) evm.StateDB.Suicide(contract.Address()) - return nil, nil } diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 954839f2e..23f930e91 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -209,6 +209,10 @@ func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret if verifyPool { verifyIntegerPool(in.intPool) } + // checks whether the operation should revert state. + if operation.reverts { + in.evm.StateDB.RevertToSnapshot(snapshot) + } switch { case err != nil: diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 2d238f7a1..2d7697e9c 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -89,6 +89,13 @@ func NewMetropolisInstructionSet() [256]operation { memorySize: memoryReturnDataCopy, valid: true, } + instructionSet[REVERT] = operation{ + execute: opRevert, + gasCost: constGasFunc(GasFastestStep), + validateStack: makeStackFunc(2, 0), + valid: true, + reverts: true, + } return instructionSet } diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go index be87cae18..0c6550735 100644 --- a/core/vm/opcodes.go +++ b/core/vm/opcodes.go @@ -204,6 +204,7 @@ const ( DELEGATECALL STATICCALL = 0xfa + REVERT = 0xfd SELFDESTRUCT = 0xff ) @@ -360,6 +361,7 @@ var opCodeToString = map[OpCode]string{ CALLCODE: "CALLCODE", DELEGATECALL: "DELEGATECALL", STATICCALL: "STATICCALL", + REVERT: "REVERT", SELFDESTRUCT: "SELFDESTRUCT", PUSH: "PUSH", @@ -509,6 +511,7 @@ var stringToOp = map[string]OpCode{ "CALL": CALL, "RETURN": RETURN, "CALLCODE": CALLCODE, + "REVERT": REVERT, "SELFDESTRUCT": SELFDESTRUCT, }