diff --git a/execution/evm/log_event_test.go b/execution/evm/log_event_test.go
index 3a054d51afd1281da7c51ef66aab91a68425337a..91808042a822a57643f624875f152c22412e9e84 100644
--- a/execution/evm/log_event_test.go
+++ b/execution/evm/log_event_test.go
@@ -22,6 +22,7 @@ import (
 	"time"
 
 	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/account/state"
 	. "github.com/hyperledger/burrow/binary"
 	"github.com/hyperledger/burrow/event"
 	. "github.com/hyperledger/burrow/execution/evm/asm"
@@ -42,6 +43,7 @@ var expectedTopics = []Word256{
 func TestLog4(t *testing.T) {
 
 	st := newAppState()
+	cache := state.NewCache(st)
 	// Create accounts
 	account1 := acm.ConcreteAccount{
 		Address: acm.Address{1, 3, 5, 7, 9},
@@ -52,7 +54,7 @@ func TestLog4(t *testing.T) {
 	st.accounts[account1.Address()] = account1
 	st.accounts[account2.Address()] = account2
 
-	ourVm := NewVM(st, newParams(), acm.ZeroAddress, nil, logger)
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 
 	emitter := event.NewEmitter(logging.NewNoopLogger())
 
@@ -83,7 +85,7 @@ func TestLog4(t *testing.T) {
 		stop,
 	}
 
-	_, err := ourVm.Call(account1, account2, code, []byte{}, 0, &gas)
+	_, err := ourVm.Call(cache, account1, account2, code, []byte{}, 0, &gas)
 	require.NoError(t, err)
 	select {
 	case <-time.After(5 * time.Second):
diff --git a/execution/evm/vm.go b/execution/evm/vm.go
index 03c67c3fc5c5e83919f037ffffd450190b1f0350..32ea15dff619f8f8b1f9a8ea2d68d879fe9e3252 100644
--- a/execution/evm/vm.go
+++ b/execution/evm/vm.go
@@ -105,7 +105,6 @@ type Params struct {
 }
 
 type VM struct {
-	stateWriter      state.Writer
 	memoryProvider   func() Memory
 	params           Params
 	origin           acm.Address
@@ -119,10 +118,9 @@ type VM struct {
 	dumpTokens       bool
 }
 
-func NewVM(stateWriter state.Writer, params Params, origin acm.Address, txid []byte,
+func NewVM(params Params, origin acm.Address, txid []byte,
 	logger *logging.Logger, options ...func(*VM)) *VM {
 	vm := &VM{
-		stateWriter:    stateWriter,
 		memoryProvider: DefaultDynamicMemoryProvider,
 		params:         params,
 		origin:         origin,
@@ -184,7 +182,7 @@ func (vm *VM) fireCallEvent(exception *string, output *[]byte, callerAddress, ca
 // value: To be transferred from caller to callee. Refunded upon error.
 // gas:   Available gas. No refunds for gas.
 // code: May be nil, since the CALL opcode may be used to send value from contracts to accounts
-func (vm *VM) Call(caller, callee acm.MutableAccount, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
+func (vm *VM) Call(callState state.Cache, caller, callee acm.MutableAccount, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
 
 	exception := new(string)
 	// fire the post call event (including exception if applicable)
@@ -194,10 +192,12 @@ func (vm *VM) Call(caller, callee acm.MutableAccount, code, input []byte, value
 		*exception = err.Error()
 		return
 	}
+	//childCallState
+	childCallState := state.NewCache(callState)
 
 	if len(code) > 0 {
 		vm.stackDepth += 1
-		output, err = vm.call(caller, callee, code, input, value, gas)
+		output, err = vm.call(childCallState, caller, callee, code, input, value, gas)
 		vm.stackDepth -= 1
 		if err != nil {
 			err = ErrCall{
@@ -210,6 +210,9 @@ func (vm *VM) Call(caller, callee acm.MutableAccount, code, input []byte, value
 				return nil, fmt.Errorf("error transferring value %v %s (callee) -> %s (caller)",
 					value, callee, caller)
 			}
+		} else {
+			// Copy any state updates from child call frame into current call frame
+			childCallState.Sync(callState)
 		}
 		if vm.stackDepth == 0 {
 			// clean up ready for next call
@@ -224,7 +227,7 @@ func (vm *VM) Call(caller, callee acm.MutableAccount, code, input []byte, value
 // The intent of delegate call is to run the code of the callee in the storage context of the caller;
 // while preserving the original caller to the previous callee.
 // Different to the normal CALL or CALLCODE, the value does not need to be transferred to the callee.
-func (vm *VM) DelegateCall(caller acm.Account, callee acm.MutableAccount, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
+func (vm *VM) DelegateCall(callState state.Cache, caller acm.Account, callee acm.MutableAccount, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
 
 	exception := new(string)
 	// fire the post call event (including exception if applicable)
@@ -234,12 +237,17 @@ func (vm *VM) DelegateCall(caller acm.Account, callee acm.MutableAccount, code,
 
 	// DelegateCall does not transfer the value to the callee.
 
+	childCallState := state.NewCache(callState)
+
 	if len(code) > 0 {
 		vm.stackDepth += 1
-		output, err = vm.call(caller, callee, code, input, value, gas)
+		output, err = vm.call(childCallState, caller, callee, code, input, value, gas)
 		vm.stackDepth -= 1
 		if err != nil {
 			*exception = err.Error()
+		} else {
+			// Copy any state updates from child call frame into current call frame
+			childCallState.Sync(callState)
 		}
 	}
 
@@ -259,7 +267,7 @@ func useGasNegative(gasLeft *uint64, gasToUse uint64, err *error) bool {
 }
 
 // Just like Call() but does not transfer 'value' or modify the callDepth.
-func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
+func (vm *VM) call(callState state.Cache, caller acm.Account, callee acm.MutableAccount, code, input []byte, value uint64, gas *uint64) (output []byte, err error) {
 	vm.Debugf("(%d) (%X) %X (code=%d) gas: %v (d) %X\n", vm.stackDepth, caller.Address().Bytes()[:4], callee.Address(),
 		len(callee.Code()), *gas, input)
 
@@ -561,7 +569,7 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 			if useGasNegative(gas, GasGetAccount, &err) {
 				return nil, err
 			}
-			acc, errAcc := vm.stateWriter.GetAccount(acm.AddressFromWord256(addr))
+			acc, errAcc := callState.GetAccount(acm.AddressFromWord256(addr))
 			if errAcc != nil {
 				return nil, firstErr(err, errAcc)
 			}
@@ -657,7 +665,7 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 			if useGasNegative(gas, GasGetAccount, &err) {
 				return nil, err
 			}
-			acc, errAcc := vm.stateWriter.GetAccount(acm.AddressFromWord256(addr))
+			acc, errAcc := callState.GetAccount(acm.AddressFromWord256(addr))
 			if errAcc != nil {
 				return nil, firstErr(err, errAcc)
 			}
@@ -678,7 +686,7 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 			if useGasNegative(gas, GasGetAccount, &err) {
 				return nil, err
 			}
-			acc, errAcc := vm.stateWriter.GetAccount(acm.AddressFromWord256(addr))
+			acc, errAcc := callState.GetAccount(acm.AddressFromWord256(addr))
 			if errAcc != nil {
 				return nil, firstErr(err, errAcc)
 			}
@@ -793,7 +801,7 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 
 		case SLOAD: // 0x54
 			loc := stack.Pop()
-			data, errSto := vm.stateWriter.GetStorage(callee.Address(), loc)
+			data, errSto := callState.GetStorage(callee.Address(), loc)
 			if errSto != nil {
 				return nil, firstErr(err, errSto)
 			}
@@ -805,7 +813,7 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 			if useGasNegative(gas, GasStorageUpdate, &err) {
 				return nil, err
 			}
-			vm.stateWriter.SetStorage(callee.Address(), loc, data)
+			callState.SetStorage(callee.Address(), loc, data)
 			vm.Debugf("%s {0x%X := 0x%X}\n", callee.Address(), loc, data)
 
 		case JUMP: // 0x56
@@ -902,7 +910,7 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 		case CREATE: // 0xF0
 			vm.returnData = nil
 
-			if !HasPermission(vm.stateWriter, callee, permission.CreateContract) {
+			if !HasPermission(callState, callee, permission.CreateContract) {
 				return nil, ErrPermission{"create_contract"}
 			}
 			contractValue, popErr := stack.PopU64()
@@ -926,14 +934,14 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 			if useGasNegative(gas, GasCreateAccount, &gasErr) {
 				return nil, firstErr(err, gasErr)
 			}
-			newAccount, createErr := vm.createAccount(callee, logger)
+			newAccount, createErr := vm.createAccount(callState, callee, logger)
 			if createErr != nil {
 				return nil, firstErr(err, createErr)
 			}
 
 			// Run the input to get the contract code.
 			// NOTE: no need to copy 'input' as per Call contract.
-			ret, err_ := vm.Call(callee, newAccount, input, input, contractValue, gas)
+			ret, err_ := vm.Call(callState, callee, newAccount, input, input, contractValue, gas)
 			if err_ != nil {
 				stack.Push(Zero256)
 				vm.returnData = ret
@@ -943,13 +951,13 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 			}
 
 			if err_ == ErrExecutionReverted {
-				return ret, nil
+				return nil, ErrExecutionReverted
 			}
 
 		case CALL, CALLCODE, DELEGATECALL: // 0xF1, 0xF2, 0xF4
 			vm.returnData = nil
 
-			if !HasPermission(vm.stateWriter, callee, permission.Call) {
+			if !HasPermission(callState, callee, permission.Call) {
 				return nil, ErrPermission{"call"}
 			}
 			gasLimit, popErr := stack.PopU64()
@@ -999,7 +1007,7 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 
 			if nativeContract := registeredNativeContracts[addr]; nativeContract != nil {
 				// Native contract
-				ret, callErr = nativeContract(vm.stateWriter, callee, args, &gasLimit, logger)
+				ret, callErr = nativeContract(callState, callee, args, &gasLimit, logger)
 
 				// for now we fire the Call event. maybe later we'll fire more particulars
 				var exception string
@@ -1013,7 +1021,7 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 				if useGasNegative(gas, GasGetAccount, &callErr) {
 					return nil, callErr
 				}
-				acc, errAcc := state.GetMutableAccount(vm.stateWriter, acm.AddressFromWord256(addr))
+				acc, errAcc := state.GetMutableAccount(callState, acm.AddressFromWord256(addr))
 				if errAcc != nil {
 					return nil, firstErr(callErr, errAcc)
 				}
@@ -1025,23 +1033,23 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 					if acc == nil {
 						return nil, firstErr(callErr, ErrUnknownAddress)
 					}
-					ret, callErr = vm.Call(callee, callee, acc.Code(), args, value, &gasLimit)
+					ret, callErr = vm.Call(callState, callee, callee, acc.Code(), args, value, &gasLimit)
 				} else if op == DELEGATECALL {
 					if acc == nil {
 						return nil, firstErr(callErr, ErrUnknownAddress)
 					}
-					ret, callErr = vm.DelegateCall(caller, callee, acc.Code(), args, value, &gasLimit)
+					ret, callErr = vm.DelegateCall(callState, caller, callee, acc.Code(), args, value, &gasLimit)
 				} else {
 					// nil account means we're sending funds to a new account
 					if acc == nil {
-						if !HasPermission(vm.stateWriter, caller, permission.CreateAccount) {
+						if !HasPermission(callState, caller, permission.CreateAccount) {
 							return nil, ErrPermission{"create_account"}
 						}
 						acc = acm.ConcreteAccount{Address: acm.AddressFromWord256(addr)}.MutableAccount()
 					}
 					// add account to the tx cache
-					vm.stateWriter.UpdateAccount(acc)
-					ret, callErr = vm.Call(callee, acc, acc.Code(), args, value, &gasLimit)
+					callState.UpdateAccount(acc)
+					ret, callErr = vm.Call(callState, callee, acc, acc.Code(), args, value, &gasLimit)
 				}
 			}
 			vm.returnData = ret
@@ -1049,11 +1057,11 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 			// In case any calls deeper in the stack (particularly SNatives) has altered either of two accounts to which
 			// we hold a reference, we need to freshen our state for subsequent iterations of this call frame's EVM loop
 			var getErr error
-			caller, getErr = vm.stateWriter.GetAccount(caller.Address())
+			caller, getErr = callState.GetAccount(caller.Address())
 			if getErr != nil {
 				return nil, firstErr(err, getErr)
 			}
-			callee, getErr = state.GetMutableAccount(vm.stateWriter, callee.Address())
+			callee, getErr = state.GetMutableAccount(callState, callee.Address())
 			if getErr != nil {
 				return nil, firstErr(err, getErr)
 			}
@@ -1102,7 +1110,6 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 			return output, nil
 
 		case REVERT: // 0xFD
-			return nil, fmt.Errorf("REVERT not yet fully implemented")
 			offset, size := stack.PopBigInt(), stack.PopBigInt()
 			output, memErr := memory.Read(offset, size)
 			if memErr != nil {
@@ -1121,7 +1128,7 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 			if useGasNegative(gas, GasGetAccount, &err) {
 				return nil, err
 			}
-			receiver, errAcc := state.GetMutableAccount(vm.stateWriter, acm.AddressFromWord256(addr))
+			receiver, errAcc := state.GetMutableAccount(callState, acm.AddressFromWord256(addr))
 			if errAcc != nil {
 				return nil, firstErr(err, errAcc)
 			}
@@ -1130,11 +1137,11 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 				if useGasNegative(gas, GasCreateAccount, &gasErr) {
 					return nil, firstErr(err, gasErr)
 				}
-				if !HasPermission(vm.stateWriter, callee, permission.CreateContract) {
+				if !HasPermission(callState, callee, permission.CreateContract) {
 					return nil, firstErr(err, ErrPermission{"create_contract"})
 				}
 				var createErr error
-				receiver, createErr = vm.createAccount(callee, logger)
+				receiver, createErr = vm.createAccount(callState, callee, logger)
 				if createErr != nil {
 					return nil, firstErr(err, createErr)
 				}
@@ -1145,8 +1152,8 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 			if errAdd != nil {
 				return nil, firstErr(err, errAdd)
 			}
-			vm.stateWriter.UpdateAccount(receiver)
-			vm.stateWriter.RemoveAccount(callee.Address())
+			callState.UpdateAccount(receiver)
+			callState.RemoveAccount(callee.Address())
 			vm.Debugf(" => (%X) %v\n", addr[:4], callee.Balance())
 			fallthrough
 
@@ -1155,6 +1162,7 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 
 		case STATICCALL, CREATE2:
 			return nil, fmt.Errorf("%s not yet implemented", op.Name())
+
 		default:
 			vm.Debugf("(pc) %-3v Unknown opcode %X\n", pc, op)
 			return nil, fmt.Errorf("unknown opcode %X", op)
@@ -1163,13 +1171,13 @@ func (vm *VM) call(caller acm.Account, callee acm.MutableAccount, code, input []
 	}
 }
 
-func (vm *VM) createAccount(callee acm.MutableAccount, logger *logging.Logger) (acm.MutableAccount, error) {
-	newAccount := DeriveNewAccount(callee, state.GlobalAccountPermissions(vm.stateWriter), logger)
-	err := vm.stateWriter.UpdateAccount(newAccount)
+func (vm *VM) createAccount(callState state.Cache, callee acm.MutableAccount, logger *logging.Logger) (acm.MutableAccount, error) {
+	newAccount := DeriveNewAccount(callee, state.GlobalAccountPermissions(callState), logger)
+	err := callState.UpdateAccount(newAccount)
 	if err != nil {
 		return nil, err
 	}
-	err = vm.stateWriter.UpdateAccount(callee)
+	err = callState.UpdateAccount(callee)
 	if err != nil {
 		return nil, err
 	}
diff --git a/execution/evm/vm_test.go b/execution/evm/vm_test.go
index b885d2664aad7e03f163cefaf9c008aade5b1346..edce8d7d8f0f057bab30d54e7d32adb88753dbfb 100644
--- a/execution/evm/vm_test.go
+++ b/execution/evm/vm_test.go
@@ -74,7 +74,8 @@ func newAccount(seed ...byte) acm.MutableAccount {
 
 // Runs a basic loop
 func TestVM(t *testing.T) {
-	ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger)
+	cache := state.NewCache(newAppState())
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 
 	// Create accounts
 	account1 := newAccount(1)
@@ -87,7 +88,7 @@ func TestVM(t *testing.T) {
 		MSTORE, PUSH1, 0x05, JUMP, JUMPDEST)
 
 	start := time.Now()
-	output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err := ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	fmt.Printf("Output: %v Error: %v\n", output, err)
 	fmt.Println("Call took:", time.Since(start))
 	if err != nil {
@@ -96,7 +97,8 @@ func TestVM(t *testing.T) {
 }
 
 func TestSHL(t *testing.T) {
-	ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger)
+	cache := state.NewCache(newAppState())
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 	account1 := newAccount(1)
 	account2 := newAccount(1, 0, 1)
 
@@ -104,7 +106,7 @@ func TestSHL(t *testing.T) {
 
 	//Shift left 0
 	bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SHL, return1())
-	output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err := ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value := []uint8([]byte{0x1})
 	expected := LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -118,7 +120,7 @@ func TestSHL(t *testing.T) {
 	//Alternative shift left 0
 	bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SHL, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
 
@@ -132,7 +134,7 @@ func TestSHL(t *testing.T) {
 
 	//Shift left 1
 	bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SHL, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x2})
 	expected = LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -146,7 +148,7 @@ func TestSHL(t *testing.T) {
 	//Alternative shift left 1
 	bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHL, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE})
 
@@ -161,7 +163,7 @@ func TestSHL(t *testing.T) {
 	//Alternative shift left 1
 	bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHL, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE})
 
@@ -175,7 +177,7 @@ func TestSHL(t *testing.T) {
 
 	//Shift left 255
 	bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0xFF, SHL, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x80})
 	expected = RightPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -189,7 +191,7 @@ func TestSHL(t *testing.T) {
 	//Alternative shift left 255
 	bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SHL, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x80})
 	expected = RightPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -202,7 +204,7 @@ func TestSHL(t *testing.T) {
 
 	//Shift left 256 (overflow)
 	bytecode = MustSplice(PUSH1, 0x01, PUSH2, 0x01, 0x00, SHL, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x00})
 	expected = LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -217,7 +219,7 @@ func TestSHL(t *testing.T) {
 	bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SHL,
 		return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x00})
 	expected = LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -230,7 +232,7 @@ func TestSHL(t *testing.T) {
 
 	//Shift left 257 (overflow)
 	bytecode = MustSplice(PUSH1, 0x01, PUSH2, 0x01, 0x01, SHL, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x00})
 	expected = LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -244,7 +246,8 @@ func TestSHL(t *testing.T) {
 }
 
 func TestSHR(t *testing.T) {
-	ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger)
+	cache := state.NewCache(newAppState())
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 	account1 := newAccount(1)
 	account2 := newAccount(1, 0, 1)
 
@@ -252,7 +255,7 @@ func TestSHR(t *testing.T) {
 
 	//Shift right 0
 	bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SHR, return1())
-	output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err := ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value := []uint8([]byte{0x1})
 	expected := LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -266,7 +269,7 @@ func TestSHR(t *testing.T) {
 	//Alternative shift right 0
 	bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SHR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
 
@@ -280,7 +283,7 @@ func TestSHR(t *testing.T) {
 
 	//Shift right 1
 	bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SHR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x00})
 	expected = LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -294,7 +297,7 @@ func TestSHR(t *testing.T) {
 	//Alternative shift right 1
 	bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0x01, SHR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x40})
 	expected = RightPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -308,7 +311,7 @@ func TestSHR(t *testing.T) {
 	//Alternative shift right 1
 	bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	expected = []uint8([]byte{0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
 
@@ -323,7 +326,7 @@ func TestSHR(t *testing.T) {
 	//Shift right 255
 	bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0xFF, SHR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x1})
 	expected = LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -337,7 +340,7 @@ func TestSHR(t *testing.T) {
 	//Alternative shift right 255
 	bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SHR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x1})
 	expected = LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -352,7 +355,7 @@ func TestSHR(t *testing.T) {
 	bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x00, SHR,
 		return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x00})
 	expected = LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -367,7 +370,7 @@ func TestSHR(t *testing.T) {
 	bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SHR,
 		return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x00})
 	expected = LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -382,7 +385,7 @@ func TestSHR(t *testing.T) {
 	bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x01, SHR,
 		return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x00})
 	expected = LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -396,7 +399,8 @@ func TestSHR(t *testing.T) {
 }
 
 func TestSAR(t *testing.T) {
-	ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger)
+	cache := state.NewCache(newAppState())
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 	account1 := newAccount(1)
 	account2 := newAccount(1, 0, 1)
 
@@ -404,7 +408,7 @@ func TestSAR(t *testing.T) {
 
 	//Shift arith right 0
 	bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SAR, return1())
-	output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err := ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value := []uint8([]byte{0x1})
 	expected := LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -418,7 +422,7 @@ func TestSAR(t *testing.T) {
 	//Alternative arith shift right 0
 	bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SAR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
 
@@ -432,7 +436,7 @@ func TestSAR(t *testing.T) {
 
 	//Shift arith right 1
 	bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SAR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x00})
 	expected = LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -446,7 +450,7 @@ func TestSAR(t *testing.T) {
 	//Alternative shift arith right 1
 	bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0x01, SAR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0xc0})
 	expected = RightPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -460,7 +464,7 @@ func TestSAR(t *testing.T) {
 	//Alternative shift arith right 1
 	bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SAR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
 
@@ -475,7 +479,7 @@ func TestSAR(t *testing.T) {
 	//Shift arith right 255
 	bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0xFF, SAR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
 
@@ -490,7 +494,7 @@ func TestSAR(t *testing.T) {
 	//Alternative shift arith right 255
 	bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SAR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
 
@@ -505,7 +509,7 @@ func TestSAR(t *testing.T) {
 	//Alternative shift arith right 255
 	bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SAR, return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x00})
 	expected = RightPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -520,7 +524,7 @@ func TestSAR(t *testing.T) {
 	bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x00, SAR,
 		return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
 
@@ -536,7 +540,7 @@ func TestSAR(t *testing.T) {
 	bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SAR,
 		return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	value = []uint8([]byte{0x00})
 	expected = LeftPadBytes(value, 32)
 	assert.Equal(t, expected, output)
@@ -551,7 +555,7 @@ func TestSAR(t *testing.T) {
 	bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x01, SAR,
 		return1())
-	output, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
 
@@ -567,7 +571,8 @@ func TestSAR(t *testing.T) {
 
 //Test attempt to jump to bad destination (position 16)
 func TestJumpErr(t *testing.T) {
-	ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger)
+	cache := state.NewCache(newAppState())
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 
 	// Create accounts
 	account1 := newAccount(1)
@@ -580,7 +585,7 @@ func TestJumpErr(t *testing.T) {
 	var err error
 	ch := make(chan struct{})
 	go func() {
-		_, err = ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+		_, err = ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 		ch <- struct{}{}
 	}()
 	tick := time.NewTicker(time.Second * 2)
@@ -597,14 +602,17 @@ func TestJumpErr(t *testing.T) {
 // Tests the code for a subcurrency contract compiled by serpent
 func TestSubcurrency(t *testing.T) {
 	st := newAppState()
-
+	cache := state.NewCache(st)
 	// Create accounts
 	account1 := newAccount(1, 2, 3)
 	account2 := newAccount(3, 2, 1)
-	st.accounts[account1.Address()] = account1
-	st.accounts[account2.Address()] = account2
+	cache.UpdateAccount(account1)
+	cache.UpdateAccount(account2)
+	cache.Sync(st)
+	//st.accounts[account1.Address()] = account1
+	//st.accounts[account2.Address()] = account2
 
-	ourVm := NewVM(st, newParams(), acm.ZeroAddress, nil, logger)
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 
 	var gas uint64 = 1000
 
@@ -623,7 +631,7 @@ func TestSubcurrency(t *testing.T) {
 		JUMPDEST, POP, JUMPDEST, PUSH1, 0x00, RETURN)
 
 	data, _ := hex.DecodeString("693200CE0000000000000000000000004B4363CDE27C2EB05E66357DB05BC5C88F850C1A0000000000000000000000000000000000000000000000000000000000000005")
-	output, err := ourVm.Call(account1, account2, bytecode, data, 0, &gas)
+	output, err := ourVm.Call(cache, account1, account2, bytecode, data, 0, &gas)
 	fmt.Printf("Output: %v Error: %v\n", output, err)
 	if err != nil {
 		t.Fatal(err)
@@ -633,59 +641,71 @@ func TestSubcurrency(t *testing.T) {
 //This test case is taken from EIP-140 (https://github.com/ethereum/EIPs/blob/master/EIPS/eip-140.md);
 //it is meant to test the implementation of the REVERT opcode
 func TestRevert(t *testing.T) {
-	ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger)
+	cache := state.NewCache(newAppState())
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 
 	// Create accounts
 	account1 := newAccount(1)
 	account2 := newAccount(1, 0, 1)
 
+	key, value := []byte{0x00}, []byte{0x00}
+	cache.SetStorage(account1.Address(), LeftPadWord256(key), LeftPadWord256(value))
+
 	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, REVERT)
+	bytecode := MustSplice(PUSH13, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61,
+		PUSH1, 0x00, SSTORE, 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, REVERT)
 
-	start := time.Now()
-	output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	/*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, REVERT)*/
+
+	output, err := ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 	assert.Error(t, err, "Expected execution reverted error")
-	fmt.Printf("Output: %v Error: %v\n", output, err)
-	fmt.Println("Call took:", time.Since(start))
+
+	storageVal, err := cache.GetStorage(account1.Address(), LeftPadWord256(key))
+	assert.Equal(t, LeftPadWord256(value), storageVal)
+
+	t.Logf("Output: %v Error: %v\n", output, err)
+
 }
 
 // Test sending tokens from a contract to another account
 func TestSendCall(t *testing.T) {
-	fakeAppState := newAppState()
-	ourVm := NewVM(fakeAppState, newParams(), acm.ZeroAddress, nil, logger)
+	cache := state.NewCache(newAppState())
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 
 	// Create accounts
 	account1 := newAccount(1)
 	account2 := newAccount(2)
 	account3 := newAccount(3)
 
-	fakeAppState.UpdateAccount(account1)
-	fakeAppState.UpdateAccount(account2)
-	fakeAppState.UpdateAccount(account3)
+	cache.UpdateAccount(account1)
+	cache.UpdateAccount(account2)
+	cache.UpdateAccount(account3)
 	// account1 will call account2 which will trigger CALL opcode to account3
 	addr := account3.Address()
 	contractCode := callContractCode(addr)
 
 	//----------------------------------------------
 	// account2 has insufficient balance, should fail
-	_, err := runVMWaitError(ourVm, account1, account2, addr, contractCode, 1000)
+	_, err := runVMWaitError(cache, ourVm, account1, account2, addr, contractCode, 1000)
 	assert.Error(t, err, "Expected insufficient balance error")
 
 	//----------------------------------------------
 	// give account2 sufficient balance, should pass
 	account2, err = newAccount(2).AddToBalance(100000)
 	require.NoError(t, err)
-	_, err = runVMWaitError(ourVm, account1, account2, addr, contractCode, 1000)
+	_, err = runVMWaitError(cache, ourVm, account1, account2, addr, contractCode, 1000)
 	assert.NoError(t, err, "Should have sufficient balance")
 
 	//----------------------------------------------
 	// insufficient gas, should fail
 	account2, err = newAccount(2).AddToBalance(100000)
 	require.NoError(t, err)
-	_, err = runVMWaitError(ourVm, account1, account2, addr, contractCode, 100)
+	_, err = runVMWaitError(cache, ourVm, account1, account2, addr, contractCode, 100)
 	assert.NoError(t, err, "Expected insufficient gas error")
 }
 
@@ -695,8 +715,8 @@ func TestSendCall(t *testing.T) {
 // We first run the DELEGATECALL with _just_ enough gas expecting a simple return,
 // and then run it with 1 gas unit less, expecting a failure
 func TestDelegateCallGas(t *testing.T) {
-	appState := newAppState()
-	ourVm := NewVM(appState, newParams(), acm.ZeroAddress, nil, logger)
+	cache := state.NewCache(newAppState())
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 
 	inOff := 0
 	inSize := 0 // no call data
@@ -716,7 +736,7 @@ func TestDelegateCallGas(t *testing.T) {
 	costBetweenGasAndDelegateCall := gasCost + subCost + delegateCallCost + pushCost
 
 	// Do a simple operation using 1 gas unit
-	calleeAccount, calleeAddress := makeAccountWithCode(appState, "callee",
+	calleeAccount, calleeAddress := makeAccountWithCode(cache, "callee",
 		MustSplice(PUSH1, calleeReturnValue, return1()))
 
 	// Here we split up the caller code so we can make a DELEGATE call with
@@ -729,14 +749,14 @@ func TestDelegateCallGas(t *testing.T) {
 	callerCodeSuffix := MustSplice(GAS, SUB, DELEGATECALL, returnWord())
 
 	// Perform a delegate call
-	callerAccount, _ := makeAccountWithCode(appState, "caller",
+	callerAccount, _ := makeAccountWithCode(cache, "caller",
 		MustSplice(callerCodePrefix,
 			// Give just enough gas to make the DELEGATECALL
 			costBetweenGasAndDelegateCall,
 			callerCodeSuffix))
 
 	// Should pass
-	output, err := runVMWaitError(ourVm, callerAccount, calleeAccount, calleeAddress,
+	output, err := runVMWaitError(cache, ourVm, callerAccount, calleeAccount, calleeAddress,
 		callerAccount.Code(), 100)
 	assert.NoError(t, err, "Should have sufficient funds for call")
 	assert.Equal(t, Int64ToWord256(calleeReturnValue).Bytes(), output)
@@ -747,23 +767,23 @@ func TestDelegateCallGas(t *testing.T) {
 		callerCodeSuffix))
 
 	// Should fail
-	_, err = runVMWaitError(ourVm, callerAccount, calleeAccount, calleeAddress,
+	_, err = runVMWaitError(cache, ourVm, callerAccount, calleeAccount, calleeAddress,
 		callerAccount.Code(), 100)
 	assert.Error(t, err, "Should have insufficient gas for call")
 }
 
 func TestMemoryBounds(t *testing.T) {
-	appState := newAppState()
+	cache := state.NewCache(newAppState())
 	memoryProvider := func() Memory {
 		return NewDynamicMemory(1024, 2048)
 	}
-	ourVm := NewVM(appState, newParams(), acm.ZeroAddress, nil, logger, MemoryProvider(memoryProvider))
-	caller, _ := makeAccountWithCode(appState, "caller", nil)
-	callee, _ := makeAccountWithCode(appState, "callee", nil)
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger, MemoryProvider(memoryProvider))
+	caller, _ := makeAccountWithCode(cache, "caller", nil)
+	callee, _ := makeAccountWithCode(cache, "callee", nil)
 	gas := uint64(100000)
 	// This attempts to store a value at the memory boundary and return it
 	word := One256
-	output, err := ourVm.call(caller, callee,
+	output, err := ourVm.call(cache, caller, callee,
 		MustSplice(pushWord(word), storeAtEnd(), MLOAD, storeAtEnd(), returnAfterStore()),
 		nil, 0, &gas)
 	assert.NoError(t, err)
@@ -771,7 +791,7 @@ func TestMemoryBounds(t *testing.T) {
 
 	// Same with number
 	word = Int64ToWord256(232234234432)
-	output, err = ourVm.call(caller, callee,
+	output, err = ourVm.call(cache, caller, callee,
 		MustSplice(pushWord(word), storeAtEnd(), MLOAD, storeAtEnd(), returnAfterStore()),
 		nil, 0, &gas)
 	assert.NoError(t, err)
@@ -782,7 +802,7 @@ func TestMemoryBounds(t *testing.T) {
 	for i := 0; i < 10; i++ {
 		code = MustSplice(code, storeAtEnd(), MLOAD)
 	}
-	output, err = ourVm.call(caller, callee, MustSplice(code, storeAtEnd(), returnAfterStore()),
+	output, err = ourVm.call(cache, caller, callee, MustSplice(code, storeAtEnd(), returnAfterStore()),
 		nil, 0, &gas)
 	assert.NoError(t, err)
 	assert.Equal(t, word.Bytes(), output)
@@ -792,19 +812,23 @@ func TestMemoryBounds(t *testing.T) {
 	for i := 0; i < 100; i++ {
 		code = MustSplice(code, storeAtEnd(), MLOAD)
 	}
-	output, err = ourVm.call(caller, callee, MustSplice(code, storeAtEnd(), returnAfterStore()),
+	output, err = ourVm.call(cache, caller, callee, MustSplice(code, storeAtEnd(), returnAfterStore()),
 		nil, 0, &gas)
 	assert.Error(t, err, "Should hit memory out of bounds")
 }
 
 func TestMsgSender(t *testing.T) {
 	st := newAppState()
+	cache := state.NewCache(st)
 	account1 := newAccount(1, 2, 3)
 	account2 := newAccount(3, 2, 1)
-	st.accounts[account1.Address()] = account1
-	st.accounts[account2.Address()] = account2
+	cache.UpdateAccount(account1)
+	cache.UpdateAccount(account2)
+	cache.Sync(st)
+	//st.accounts[account1.Address()] = account1
+	//st.accounts[account2.Address()] = account2
 
-	ourVm := NewVM(st, newParams(), acm.ZeroAddress, nil, logger)
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 
 	var gas uint64 = 100000
 
@@ -827,7 +851,7 @@ func TestMsgSender(t *testing.T) {
 	require.NoError(t, err)
 
 	// Run the contract initialisation code to obtain the contract code that would be mounted at account2
-	contractCode, err := ourVm.Call(account1, account2, code, code, 0, &gas)
+	contractCode, err := ourVm.Call(cache, account1, account2, code, code, 0, &gas)
 	require.NoError(t, err)
 
 	// Not needed for this test (since contract code is passed as argument to vm), but this is what an execution
@@ -837,7 +861,7 @@ func TestMsgSender(t *testing.T) {
 	// Input is the function hash of `get()`
 	input, err := hex.DecodeString("6d4ce63c")
 
-	output, err := ourVm.Call(account1, account2, contractCode, input, 0, &gas)
+	output, err := ourVm.Call(cache, account1, account2, contractCode, input, 0, &gas)
 	require.NoError(t, err)
 
 	assert.Equal(t, account1.Address().Word256().Bytes(), output)
@@ -845,7 +869,8 @@ func TestMsgSender(t *testing.T) {
 }
 
 func TestInvalid(t *testing.T) {
-	ourVm := NewVM(newAppState(), newParams(), acm.ZeroAddress, nil, logger)
+	cache := state.NewCache(newAppState())
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 
 	// Create accounts
 	account1 := newAccount(1)
@@ -857,7 +882,7 @@ func TestInvalid(t *testing.T) {
 		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)
+	output, err := ourVm.Call(cache, 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)
@@ -866,7 +891,7 @@ func TestInvalid(t *testing.T) {
 
 func TestReturnDataSize(t *testing.T) {
 	cache := state.NewCache(newAppState())
-	ourVm := NewVM(cache, newParams(), acm.ZeroAddress, nil, logger)
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 
 	accountName := "account2addresstests"
 
@@ -877,6 +902,7 @@ func TestReturnDataSize(t *testing.T) {
 	// Create accounts
 	account1 := newAccount(1)
 	account2, _ := makeAccountWithCode(cache, accountName, callcode)
+	cache.UpdateAccount(account2)
 
 	var gas uint64 = 100000
 
@@ -891,7 +917,7 @@ func TestReturnDataSize(t *testing.T) {
 
 	expected := LeftPadBytes([]byte{0x0E}, 32)
 
-	output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err := ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 
 	assert.Equal(t, expected, output)
 
@@ -904,7 +930,7 @@ func TestReturnDataSize(t *testing.T) {
 
 func TestReturnDataCopy(t *testing.T) {
 	cache := state.NewCache(newAppState())
-	ourVm := NewVM(cache, newParams(), acm.ZeroAddress, nil, logger)
+	ourVm := NewVM(newParams(), acm.ZeroAddress, nil, logger)
 
 	accountName := "account2addresstests"
 
@@ -915,6 +941,7 @@ func TestReturnDataCopy(t *testing.T) {
 	// Create accounts
 	account1 := newAccount(1)
 	account2, _ := makeAccountWithCode(cache, accountName, callcode)
+	cache.UpdateAccount(account2)
 
 	var gas uint64 = 100000
 
@@ -930,7 +957,7 @@ func TestReturnDataCopy(t *testing.T) {
 
 	expected := []byte{0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65}
 
-	output, err := ourVm.Call(account1, account2, bytecode, []byte{}, 0, &gas)
+	output, err := ourVm.Call(cache, account1, account2, bytecode, []byte{}, 0, &gas)
 
 	assert.Equal(t, expected, output)
 
@@ -984,10 +1011,10 @@ func makeAccountWithCode(accountUpdater state.AccountUpdater, name string,
 // and then waits for any exceptions transmitted by Data in the AccCall
 // event (in the case of no direct error from call we will block waiting for
 // at least 1 AccCall event)
-func runVMWaitError(ourVm *VM, caller, callee acm.MutableAccount, subscribeAddr acm.Address,
+func runVMWaitError(vmCache state.Cache, ourVm *VM, caller, callee acm.MutableAccount, subscribeAddr acm.Address,
 	contractCode []byte, gas uint64) ([]byte, error) {
 	eventCh := make(chan *evm_events.EventDataCall)
-	output, err := runVM(eventCh, ourVm, caller, callee, subscribeAddr, contractCode, gas)
+	output, err := runVM(eventCh, vmCache, ourVm, caller, callee, subscribeAddr, contractCode, gas)
 	if err != nil {
 		return output, err
 	}
@@ -1002,7 +1029,7 @@ func runVMWaitError(ourVm *VM, caller, callee acm.MutableAccount, subscribeAddr
 
 // Subscribes to an AccCall, runs the vm, returns the output and any direct
 // exception
-func runVM(eventCh chan<- *evm_events.EventDataCall, ourVm *VM, caller, callee acm.MutableAccount,
+func runVM(eventCh chan<- *evm_events.EventDataCall, vmCache state.Cache, ourVm *VM, caller, callee acm.MutableAccount,
 	subscribeAddr acm.Address, contractCode []byte, gas uint64) ([]byte, error) {
 
 	// we need to catch the event from the CALL to check for exceptions
@@ -1017,7 +1044,7 @@ func runVM(eventCh chan<- *evm_events.EventDataCall, ourVm *VM, caller, callee a
 	evc := event.NewEventCache(emitter)
 	ourVm.SetPublisher(evc)
 	start := time.Now()
-	output, err := ourVm.Call(caller, callee, contractCode, []byte{}, 0, &gas)
+	output, err := ourVm.Call(vmCache, caller, callee, contractCode, []byte{}, 0, &gas)
 	fmt.Printf("Output: %v Error: %v\n", output, err)
 	fmt.Println("Call took:", time.Since(start))
 	evc.Flush()
diff --git a/execution/execution.go b/execution/execution.go
index ee3c342fbe486dee7b0db3752649f7de7518d585..a26646e00096aba66eaf2cb4bb1ee33190c36091 100644
--- a/execution/execution.go
+++ b/execution/execution.go
@@ -388,10 +388,10 @@ func (exe *executor) Execute(tx txs.Tx) (err error) {
 				// Write caller/callee to txCache.
 				txCache.UpdateAccount(caller)
 				txCache.UpdateAccount(callee)
-				vmach := evm.NewVM(txCache, params, caller.Address(), tx.Hash(exe.chainID), logger, exe.vmOptions...)
+				vmach := evm.NewVM(params, caller.Address(), tx.Hash(exe.chainID), logger, exe.vmOptions...)
 				vmach.SetPublisher(exe.eventCache)
 				// NOTE: Call() transfers the value from caller to callee iff call succeeds.
-				ret, err = vmach.Call(caller, callee, code, tx.Data, value, &gas)
+				ret, err = vmach.Call(txCache, caller, callee, code, tx.Data, value, &gas)
 				if err != nil {
 					// Failure. Charge the gas fee. The 'value' was otherwise not transferred.
 					logger.InfoMsg("Error on execution",
diff --git a/execution/transactor.go b/execution/transactor.go
index f42278b580a15c02cb8d6f695cfc562ef984e6ee..d6e2206d3a8dcf40e220d8a7dd6a777cea4eb665 100644
--- a/execution/transactor.go
+++ b/execution/transactor.go
@@ -87,7 +87,7 @@ func (trans *Transactor) Call(reader state.Reader, fromAddress, toAddress acm.Ad
 	txCache := state.NewCache(reader)
 	params := vmParams(trans.tip)
 
-	vmach := evm.NewVM(txCache, params, caller.Address(), nil, trans.logger.WithScope("Call"))
+	vmach := evm.NewVM(params, caller.Address(), nil, trans.logger.WithScope("Call"))
 	vmach.SetPublisher(trans.eventEmitter)
 
 	gas := params.GasLimit
@@ -96,7 +96,7 @@ func (trans *Transactor) Call(reader state.Reader, fromAddress, toAddress acm.Ad
 			err = fmt.Errorf("panic from VM in simulated call: %v\n%s", r, debug.Stack())
 		}
 	}()
-	ret, err := vmach.Call(caller, callee, callee.Code(), data, 0, &gas)
+	ret, err := vmach.Call(txCache, caller, callee, callee.Code(), data, 0, &gas)
 	if err != nil {
 		return nil, err
 	}
@@ -113,9 +113,9 @@ func (trans *Transactor) CallCode(reader state.Reader, fromAddress acm.Address,
 	txCache := state.NewCache(reader)
 	params := vmParams(trans.tip)
 
-	vmach := evm.NewVM(txCache, params, caller.Address(), nil, trans.logger.WithScope("CallCode"))
+	vmach := evm.NewVM(params, caller.Address(), nil, trans.logger.WithScope("CallCode"))
 	gas := params.GasLimit
-	ret, err := vmach.Call(caller, callee, code, data, 0, &gas)
+	ret, err := vmach.Call(txCache, caller, callee, code, data, 0, &gas)
 	if err != nil {
 		return nil, err
 	}