From a647541dec18c1766e7c2cfc17051c173396f273 Mon Sep 17 00:00:00 2001
From: smblucker <smblucker@outlook.com>
Date: Mon, 7 May 2018 13:02:06 -0400
Subject: [PATCH] Implementing INVALID opcode

Signed-off-by: smblucker <smblucker@outlook.com>
---
 execution/evm/asm/opcodes.go |  2 ++
 execution/evm/vm.go          |  8 ++++++--
 execution/evm/vm_test.go     | 20 ++++++++++++++++++++
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/execution/evm/asm/opcodes.go b/execution/evm/asm/opcodes.go
index 0db53834..8dd39340 100644
--- a/execution/evm/asm/opcodes.go
+++ b/execution/evm/asm/opcodes.go
@@ -189,6 +189,7 @@ const (
 	// 0x70 range - other
 	STATICCALL   = 0xfa
 	REVERT       = 0xfd
+	INVALID      = 0xfe
 	SELFDESTRUCT = 0xff
 )
 
@@ -347,6 +348,7 @@ var opCodeNames = map[OpCode]string{
 	STATICCALL:   "STATICCALL",
 	// 0x70 range - other
 	REVERT:       "REVERT",
+	INVALID:      "INVALID",
 	SELFDESTRUCT: "SELFDESTRUCT",
 }
 
diff --git a/execution/evm/vm.go b/execution/evm/vm.go
index 5597fe03..35a3ac63 100644
--- a/execution/evm/vm.go
+++ b/execution/evm/vm.go
@@ -48,6 +48,7 @@ var (
 	ErrDataStackUnderflow     = errors.New("Data stack underflow")
 	ErrInvalidContract        = errors.New("Invalid contract")
 	ErrNativeContractCodeCopy = errors.New("Tried to copy native contract code")
+	ErrExecutionAborted       = errors.New("Execution aborted")
 	ErrExecutionReverted      = errors.New("Execution reverted")
 )
 
@@ -1039,6 +1040,9 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 			vm.Debugf(" => [%v, %v] (%d) 0x%X\n", offset, size, len(output), output)
 			return output, ErrExecutionReverted
 
+		case INVALID: //0xFE
+			return nil, ErrExecutionAborted
+
 		case SELFDESTRUCT: // 0xFF
 			addr := stack.Pop()
 			if useGasNegative(gas, GasGetAccount, &err) {
@@ -1079,8 +1083,8 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 		case STATICCALL, SHL, SHR, SAR, RETURNDATASIZE, RETURNDATACOPY:
 			return nil, fmt.Errorf("%s not yet implemented", op.Name())
 		default:
-			vm.Debugf("(pc) %-3v Invalid opcode %X\n", pc, op)
-			return nil, fmt.Errorf("invalid opcode %X", op)
+			vm.Debugf("(pc) %-3v Unknown opcode %X\n", pc, op)
+			return nil, fmt.Errorf("unknown opcode %X", op)
 		}
 		pc++
 	}
diff --git a/execution/evm/vm_test.go b/execution/evm/vm_test.go
index 27ce0770..23f942a8 100644
--- a/execution/evm/vm_test.go
+++ b/execution/evm/vm_test.go
@@ -374,6 +374,26 @@ func TestMsgSender(t *testing.T) {
 
 }
 
+func TestInvalid(t *testing.T) {
+	ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger)
+
+	// Create accounts
+	account1 := newAccount(1)
+	account2 := newAccount(1, 0, 1)
+
+	var gas uint64 = 100000
+
+	bytecode := MustSplice(PUSH32, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61,
+		0x67, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, PUSH1, 0x00, MSTORE, PUSH1, 0x0E, PUSH1, 0x00, INVALID)
+
+	output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	expected := "call error: " + ErrExecutionAborted.Error()
+	assert.EqualError(t, err, expected)
+	t.Logf("Output: %v Error: %v\n", output, err)
+
+}
+
 // These code segment helpers exercise the MSTORE MLOAD MSTORE cycle to test
 // both of the memory operations. Each MSTORE is done on the memory boundary
 // (at MSIZE) which Solidity uses to find guaranteed unallocated memory.
-- 
GitLab