diff --git a/execution/evm/asm/opcodes.go b/execution/evm/asm/opcodes.go
index 0db53834facf9d6e682f06de1f58ccae99c321af..8dd393402452c9efbbc360ae33a30e9098905079 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 5597fe037f7425bde516b25dbd557eaed98f9dd0..35a3ac63a96805f35e209ba74dfcbe484ca64b32 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 27ce077083f3aea74d99c513e551f78e101799f5..23f942a8cb152c46fc0eed94ef2a9e7b77585665 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.