github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/evm/evm_test.go (about)

     1  // Copyright Monax Industries Limited
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package evm
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/binary"
     9  	"math/big"
    10  	"reflect"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/hyperledger/burrow/acm"
    15  	"github.com/hyperledger/burrow/acm/acmstate"
    16  	. "github.com/hyperledger/burrow/binary"
    17  	"github.com/hyperledger/burrow/crypto"
    18  	"github.com/hyperledger/burrow/execution/engine"
    19  	"github.com/hyperledger/burrow/execution/errors"
    20  	"github.com/hyperledger/burrow/execution/evm/abi"
    21  	. "github.com/hyperledger/burrow/execution/evm/asm"
    22  	. "github.com/hyperledger/burrow/execution/evm/asm/bc"
    23  	"github.com/hyperledger/burrow/execution/exec"
    24  	"github.com/hyperledger/burrow/execution/native"
    25  	"github.com/hyperledger/burrow/execution/solidity"
    26  	"github.com/hyperledger/burrow/txs"
    27  	"github.com/stretchr/testify/assert"
    28  	"github.com/stretchr/testify/require"
    29  	"github.com/tmthrgd/go-hex"
    30  )
    31  
    32  // Test output is a bit clearer if we /dev/null the logging, but can be re-enabled by uncommenting the below
    33  //var logger, _, _ = lifecycle.NewStdErrLogger()
    34  
    35  // Runs a basic loop
    36  func TestEVM(t *testing.T) {
    37  	vm := New(engine.Options{
    38  		Natives: native.MustDefaultNatives(),
    39  	})
    40  
    41  	t.Run("BasicLoop", func(t *testing.T) {
    42  		st := acmstate.NewMemoryState()
    43  		blockchain := new(engine.TestBlockchain)
    44  		eventSink := exec.NewNoopEventSink()
    45  
    46  		// Create accounts
    47  		account1 := newAccount(t, st, "1")
    48  		account2 := newAccount(t, st, "101")
    49  
    50  		bytecode := MustSplice(PUSH1, 0x00, PUSH1, 0x20, MSTORE, JUMPDEST, PUSH2, 0x0F, 0x0F, PUSH1, 0x20, MLOAD,
    51  			SLT, ISZERO, PUSH1, 0x1D, JUMPI, PUSH1, 0x01, PUSH1, 0x20, MLOAD, ADD, PUSH1, 0x20,
    52  			MSTORE, PUSH1, 0x05, JUMP, JUMPDEST)
    53  
    54  		start := time.Now()
    55  		output, err := vm.Execute(st, blockchain, eventSink, engine.CallParams{
    56  			Caller: account1,
    57  			Callee: account2,
    58  			Gas:    big.NewInt(100000),
    59  		}, bytecode)
    60  		t.Logf("Output: %v Error: %v\n", output, err)
    61  		t.Logf("Call took: %v", time.Since(start))
    62  		require.NoError(t, err)
    63  	})
    64  
    65  	t.Run("SHL", func(t *testing.T) {
    66  		st := acmstate.NewMemoryState()
    67  		account1 := newAccount(t, st, "1")
    68  		account2 := newAccount(t, st, "101")
    69  
    70  		gas := big.NewInt(100000)
    71  
    72  		//Shift left 0
    73  		bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SHL, return1())
    74  		output, err := call(vm, st, account1, account2, bytecode, nil, gas)
    75  		value := []byte{0x1}
    76  		expected := LeftPadBytes(value, 32)
    77  		assert.Equal(t, expected, output)
    78  
    79  		t.Logf("Result: %v == %v\n", output, expected)
    80  
    81  		if err != nil {
    82  			t.Fatal(err)
    83  		}
    84  
    85  		//Alternative shift left 0
    86  		bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    87  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SHL, return1())
    88  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
    89  		expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    90  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
    91  
    92  		assert.Equal(t, expected, output)
    93  
    94  		t.Logf("Result: %v == %v\n", output, expected)
    95  
    96  		if err != nil {
    97  			t.Fatal(err)
    98  		}
    99  
   100  		//Shift left 1
   101  		bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SHL, return1())
   102  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   103  		value = []byte{0x2}
   104  		expected = LeftPadBytes(value, 32)
   105  		assert.Equal(t, expected, output)
   106  
   107  		t.Logf("Result: %v == %v\n", output, expected)
   108  
   109  		if err != nil {
   110  			t.Fatal(err)
   111  		}
   112  
   113  		//Alternative shift left 1
   114  		bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   115  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHL, return1())
   116  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   117  		value = []byte{0x2}
   118  		expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   119  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}
   120  
   121  		assert.Equal(t, expected, output)
   122  
   123  		t.Logf("Result: %v == %v\n", output, expected)
   124  
   125  		if err != nil {
   126  			t.Fatal(err)
   127  		}
   128  
   129  		//Alternative shift left 1
   130  		bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   131  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHL, return1())
   132  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   133  		expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   134  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}
   135  
   136  		assert.Equal(t, expected, output)
   137  
   138  		t.Logf("Result: %v == %v\n", output, expected)
   139  
   140  		if err != nil {
   141  			t.Fatal(err)
   142  		}
   143  
   144  		//Shift left 255
   145  		bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0xFF, SHL, return1())
   146  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   147  		value = []byte{0x80}
   148  		expected = RightPadBytes(value, 32)
   149  		assert.Equal(t, expected, output)
   150  
   151  		t.Logf("Result: %v == %v\n", output, expected)
   152  
   153  		if err != nil {
   154  			t.Fatal(err)
   155  		}
   156  
   157  		//Alternative shift left 255
   158  		bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   159  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SHL, return1())
   160  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   161  		value = []byte{0x80}
   162  		expected = RightPadBytes(value, 32)
   163  		assert.Equal(t, expected, output)
   164  
   165  		t.Logf("Result: %v == %v\n", output, expected)
   166  
   167  		if err != nil {
   168  			t.Fatal(err)
   169  		}
   170  
   171  		//Shift left 256 (overflow)
   172  		bytecode = MustSplice(PUSH1, 0x01, PUSH2, 0x01, 0x00, SHL, return1())
   173  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   174  		value = []byte{0x00}
   175  		expected = LeftPadBytes(value, 32)
   176  		assert.Equal(t, expected, output)
   177  
   178  		t.Logf("Result: %v == %v\n", output, expected)
   179  
   180  		if err != nil {
   181  			t.Fatal(err)
   182  		}
   183  
   184  		//Alternative shift left 256 (overflow)
   185  		bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   186  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SHL,
   187  			return1())
   188  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   189  		value = []byte{0x00}
   190  		expected = LeftPadBytes(value, 32)
   191  		assert.Equal(t, expected, output)
   192  
   193  		t.Logf("Result: %v == %v\n", output, expected)
   194  
   195  		if err != nil {
   196  			t.Fatal(err)
   197  		}
   198  
   199  		//Shift left 257 (overflow)
   200  		bytecode = MustSplice(PUSH1, 0x01, PUSH2, 0x01, 0x01, SHL, return1())
   201  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   202  		value = []byte{0x00}
   203  		expected = LeftPadBytes(value, 32)
   204  		assert.Equal(t, expected, output)
   205  
   206  		t.Logf("Result: %v == %v\n", output, expected)
   207  
   208  		if err != nil {
   209  			t.Fatal(err)
   210  		}
   211  	})
   212  
   213  	t.Run("SHR", func(t *testing.T) {
   214  		st := acmstate.NewMemoryState()
   215  		account1 := newAccount(t, st, "1")
   216  		account2 := newAccount(t, st, "101")
   217  
   218  		gas := big.NewInt(100000)
   219  
   220  		//Shift right 0
   221  		bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SHR, return1())
   222  		output, err := call(vm, st, account1, account2, bytecode, nil, gas)
   223  		value := []byte{0x1}
   224  		expected := LeftPadBytes(value, 32)
   225  		assert.Equal(t, expected, output)
   226  
   227  		t.Logf("Result: %v == %v\n", output, expected)
   228  
   229  		if err != nil {
   230  			t.Fatal(err)
   231  		}
   232  
   233  		//Alternative shift right 0
   234  		bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   235  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SHR, return1())
   236  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   237  		expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   238  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
   239  
   240  		assert.Equal(t, expected, output)
   241  
   242  		t.Logf("Result: %v == %v\n", output, expected)
   243  
   244  		if err != nil {
   245  			t.Fatal(err)
   246  		}
   247  
   248  		//Shift right 1
   249  		bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SHR, return1())
   250  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   251  		value = []byte{0x00}
   252  		expected = LeftPadBytes(value, 32)
   253  		assert.Equal(t, expected, output)
   254  
   255  		t.Logf("Result: %v == %v\n", output, expected)
   256  
   257  		if err != nil {
   258  			t.Fatal(err)
   259  		}
   260  
   261  		//Alternative shift right 1
   262  		bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   263  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0x01, SHR, return1())
   264  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   265  		value = []byte{0x40}
   266  		expected = RightPadBytes(value, 32)
   267  		assert.Equal(t, expected, output)
   268  
   269  		t.Logf("Result: %v == %v\n", output, expected)
   270  
   271  		if err != nil {
   272  			t.Fatal(err)
   273  		}
   274  
   275  		//Alternative shift right 1
   276  		bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   277  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SHR, return1())
   278  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   279  		expected = []byte{0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   280  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
   281  
   282  		assert.Equal(t, expected, output)
   283  
   284  		t.Logf("Result: %v == %v\n", output, expected)
   285  
   286  		if err != nil {
   287  			t.Fatal(err)
   288  		}
   289  
   290  		//Shift right 255
   291  		bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   292  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0xFF, SHR, return1())
   293  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   294  		value = []byte{0x1}
   295  		expected = LeftPadBytes(value, 32)
   296  		assert.Equal(t, expected, output)
   297  
   298  		t.Logf("Result: %v == %v\n", output, expected)
   299  
   300  		if err != nil {
   301  			t.Fatal(err)
   302  		}
   303  
   304  		//Alternative shift right 255
   305  		bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   306  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SHR, return1())
   307  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   308  		value = []byte{0x1}
   309  		expected = LeftPadBytes(value, 32)
   310  		assert.Equal(t, expected, output)
   311  
   312  		t.Logf("Result: %v == %v\n", output, expected)
   313  
   314  		if err != nil {
   315  			t.Fatal(err)
   316  		}
   317  
   318  		//Shift right 256 (underflow)
   319  		bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   320  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x00, SHR,
   321  			return1())
   322  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   323  		value = []byte{0x00}
   324  		expected = LeftPadBytes(value, 32)
   325  		assert.Equal(t, expected, output)
   326  
   327  		t.Logf("Result: %v == %v\n", output, expected)
   328  
   329  		if err != nil {
   330  			t.Fatal(err)
   331  		}
   332  
   333  		//Alternative shift right 256 (underflow)
   334  		bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   335  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SHR,
   336  			return1())
   337  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   338  		value = []byte{0x00}
   339  		expected = LeftPadBytes(value, 32)
   340  		assert.Equal(t, expected, output)
   341  
   342  		t.Logf("Result: %v == %v\n", output, expected)
   343  
   344  		if err != nil {
   345  			t.Fatal(err)
   346  		}
   347  
   348  		//Shift right 257 (underflow)
   349  		bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   350  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x01, SHR,
   351  			return1())
   352  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   353  		value = []byte{0x00}
   354  		expected = LeftPadBytes(value, 32)
   355  		assert.Equal(t, expected, output)
   356  
   357  		t.Logf("Result: %v == %v\n", output, expected)
   358  
   359  		if err != nil {
   360  			t.Fatal(err)
   361  		}
   362  	})
   363  
   364  	t.Run("SAR", func(t *testing.T) {
   365  		st := acmstate.NewMemoryState()
   366  		account1 := newAccount(t, st, "1")
   367  		account2 := newAccount(t, st, "101")
   368  
   369  		gas := big.NewInt(100000)
   370  
   371  		//Shift arith right 0
   372  		bytecode := MustSplice(PUSH1, 0x01, PUSH1, 0x00, SAR, return1())
   373  		output, err := call(vm, st, account1, account2, bytecode, nil, gas)
   374  		value := []byte{0x1}
   375  		expected := LeftPadBytes(value, 32)
   376  		assert.Equal(t, expected, output)
   377  
   378  		t.Logf("Result: %v == %v\n", output, expected)
   379  
   380  		if err != nil {
   381  			t.Fatal(err)
   382  		}
   383  
   384  		//Alternative arith shift right 0
   385  		bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   386  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x00, SAR, return1())
   387  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   388  		expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   389  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
   390  
   391  		assert.Equal(t, expected, output)
   392  
   393  		t.Logf("Result: %v == %v\n", output, expected)
   394  
   395  		if err != nil {
   396  			t.Fatal(err)
   397  		}
   398  
   399  		//Shift arith right 1
   400  		bytecode = MustSplice(PUSH1, 0x01, PUSH1, 0x01, SAR, return1())
   401  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   402  		value = []byte{0x00}
   403  		expected = LeftPadBytes(value, 32)
   404  		assert.Equal(t, expected, output)
   405  
   406  		t.Logf("Result: %v == %v\n", output, expected)
   407  
   408  		if err != nil {
   409  			t.Fatal(err)
   410  		}
   411  
   412  		//Alternative shift arith right 1
   413  		bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   414  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0x01, SAR, return1())
   415  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   416  		value = []byte{0xc0}
   417  		expected = RightPadBytes(value, 32)
   418  		assert.Equal(t, expected, output)
   419  
   420  		t.Logf("Result: %v == %v\n", output, expected)
   421  
   422  		if err != nil {
   423  			t.Fatal(err)
   424  		}
   425  
   426  		//Alternative shift arith right 1
   427  		bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   428  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0x01, SAR, return1())
   429  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   430  		expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   431  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
   432  
   433  		assert.Equal(t, expected, output)
   434  
   435  		t.Logf("Result: %v == %v\n", output, expected)
   436  
   437  		if err != nil {
   438  			t.Fatal(err)
   439  		}
   440  
   441  		//Shift arith right 255
   442  		bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   443  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1, 0xFF, SAR, return1())
   444  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   445  		expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   446  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
   447  
   448  		assert.Equal(t, expected, output)
   449  
   450  		t.Logf("Result: %v == %v\n", output, expected)
   451  
   452  		if err != nil {
   453  			t.Fatal(err)
   454  		}
   455  
   456  		//Alternative shift arith right 255
   457  		bytecode = MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   458  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SAR, return1())
   459  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   460  		expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   461  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
   462  
   463  		assert.Equal(t, expected, output)
   464  
   465  		t.Logf("Result: %v == %v\n", output, expected)
   466  
   467  		if err != nil {
   468  			t.Fatal(err)
   469  		}
   470  
   471  		//Alternative shift arith right 255
   472  		bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   473  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH1, 0xFF, SAR, return1())
   474  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   475  		value = []uint8([]byte{0x00})
   476  		expected = RightPadBytes(value, 32)
   477  		assert.Equal(t, expected, output)
   478  
   479  		t.Logf("Result: %v == %v\n", output, expected)
   480  
   481  		if err != nil {
   482  			t.Fatal(err)
   483  		}
   484  
   485  		//Shift arith right 256 (reset)
   486  		bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   487  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x00, SAR,
   488  			return1())
   489  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   490  		expected = []uint8([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   491  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
   492  
   493  		assert.Equal(t, expected, output)
   494  
   495  		t.Logf("Result: %v == %v\n", output, expected)
   496  
   497  		if err != nil {
   498  			t.Fatal(err)
   499  		}
   500  
   501  		//Alternative shift arith right 256 (reset)
   502  		bytecode = MustSplice(PUSH32, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   503  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, PUSH2, 0x01, 0x00, SAR,
   504  			return1())
   505  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   506  		value = []byte{0x00}
   507  		expected = LeftPadBytes(value, 32)
   508  		assert.Equal(t, expected, output)
   509  
   510  		t.Logf("Result: %v == %v\n", output, expected)
   511  
   512  		if err != nil {
   513  			t.Fatal(err)
   514  		}
   515  
   516  		//Shift arith right 257 (reset)
   517  		bytecode = MustSplice(PUSH32, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   518  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH2, 0x01, 0x01, SAR,
   519  			return1())
   520  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
   521  		expected = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   522  			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
   523  
   524  		assert.Equal(t, expected, output)
   525  
   526  		t.Logf("Result: %v == %v\n", output, expected)
   527  
   528  		if err != nil {
   529  			t.Fatal(err)
   530  		}
   531  	})
   532  
   533  	//Test attempt to jump to bad destination (position 16)
   534  	t.Run("JumpErr", func(t *testing.T) {
   535  		st := acmstate.NewMemoryState()
   536  
   537  		// Create accounts
   538  		account1 := newAccount(t, st, "1")
   539  		account2 := newAccount(t, st, "2")
   540  
   541  		gas := big.NewInt(100000)
   542  
   543  		bytecode := MustSplice(PUSH1, 0x10, JUMP)
   544  
   545  		var err error
   546  		ch := make(chan struct{})
   547  		go func() {
   548  			_, err = call(vm, st, account1, account2, bytecode, nil, gas)
   549  			ch <- struct{}{}
   550  		}()
   551  		tick := time.NewTicker(time.Second * 2)
   552  		select {
   553  		case <-tick.C:
   554  			t.Fatal("VM ended up in an infinite loop from bad jump dest (it took too long!)")
   555  		case <-ch:
   556  			if err == nil {
   557  				t.Fatal("Expected invalid jump dest err")
   558  			}
   559  		}
   560  	})
   561  
   562  	// Tests the code for a subcurrency contract compiled by serpent
   563  	t.Run("Subcurrency", func(t *testing.T) {
   564  		st := acmstate.NewMemoryState()
   565  		// Create accounts
   566  		account1 := newAccount(t, st, "1, 2, 3")
   567  		account2 := newAccount(t, st, "3, 2, 1")
   568  
   569  		gas := big.NewInt(1000)
   570  
   571  		bytecode := MustSplice(PUSH3, 0x0F, 0x42, 0x40, CALLER, SSTORE, PUSH29, 0x01, 0x00, 0x00, 0x00,
   572  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   573  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PUSH1,
   574  			0x00, CALLDATALOAD, DIV, PUSH4, 0x15, 0xCF, 0x26, 0x84, DUP2, EQ, ISZERO, PUSH2,
   575  			0x00, 0x46, JUMPI, PUSH1, 0x04, CALLDATALOAD, PUSH1, 0x40, MSTORE, PUSH1, 0x40,
   576  			MLOAD, SLOAD, PUSH1, 0x60, MSTORE, PUSH1, 0x20, PUSH1, 0x60, RETURN, JUMPDEST,
   577  			PUSH4, 0x69, 0x32, 0x00, 0xCE, DUP2, EQ, ISZERO, PUSH2, 0x00, 0x87, JUMPI, PUSH1,
   578  			0x04, CALLDATALOAD, PUSH1, 0x80, MSTORE, PUSH1, 0x24, CALLDATALOAD, PUSH1, 0xA0,
   579  			MSTORE, CALLER, SLOAD, PUSH1, 0xC0, MSTORE, CALLER, PUSH1, 0xE0, MSTORE, PUSH1,
   580  			0xA0, MLOAD, PUSH1, 0xC0, MLOAD, SLT, ISZERO, ISZERO, PUSH2, 0x00, 0x86, JUMPI,
   581  			PUSH1, 0xA0, MLOAD, PUSH1, 0xC0, MLOAD, SUB, PUSH1, 0xE0, MLOAD, SSTORE, PUSH1,
   582  			0xA0, MLOAD, PUSH1, 0x80, MLOAD, SLOAD, ADD, PUSH1, 0x80, MLOAD, SSTORE, JUMPDEST,
   583  			JUMPDEST, POP, JUMPDEST, PUSH1, 0x00, PUSH1, 0x00, RETURN)
   584  
   585  		data := hex.MustDecodeString("693200CE0000000000000000000000004B4363CDE27C2EB05E66357DB05BC5C88F850C1A0000000000000000000000000000000000000000000000000000000000000005")
   586  		output, err := call(vm, st, account1, account2, bytecode, data, gas)
   587  		t.Logf("Output: %v Error: %v\n", output, err)
   588  		if err != nil {
   589  			t.Fatal(err)
   590  		}
   591  		require.NoError(t, err)
   592  	})
   593  
   594  	//This test case is taken from EIP-140 (https://github.com/ethereum/EIPs/blob/master/EIPS/eip-140.md);
   595  	//it is meant to test the implementation of the REVERT opcode
   596  	t.Run("Revert", func(t *testing.T) {
   597  		st := acmstate.NewMemoryState()
   598  
   599  		// Create accounts
   600  		account1 := newAccount(t, st, "1")
   601  		account2 := newAccount(t, st, "1, 0, 1")
   602  
   603  		key, value := []byte{0x00}, []byte{0x00}
   604  		err := st.SetStorage(account1, LeftPadWord256(key), value)
   605  		require.NoError(t, err)
   606  
   607  		gas := big.NewInt(100000)
   608  
   609  		bytecode := MustSplice(PUSH13, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61,
   610  			PUSH1, 0x00, SSTORE, PUSH32, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
   611  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   612  			PUSH1, 0x00, MSTORE, PUSH1, 0x0E, PUSH1, 0x00, REVERT)
   613  
   614  		/*bytecode := MustSplice(PUSH32, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61,
   615  		0x67, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   616  		0x00, 0x00, 0x00, PUSH1, 0x00, MSTORE, PUSH1, 0x0E, PUSH1, 0x00, REVERT)*/
   617  
   618  		output, err := call(vm, st, account1, account2, bytecode, nil, gas)
   619  		assert.Error(t, err, "Expected execution reverted error")
   620  
   621  		storageVal, err := st.GetStorage(account1, LeftPadWord256(key))
   622  		require.NoError(t, err)
   623  		assert.Equal(t, value, storageVal)
   624  
   625  		t.Logf("Output: %v\n", output)
   626  	})
   627  
   628  	// Test sending tokens from a contract to another account
   629  	t.Run("SendCall", func(t *testing.T) {
   630  		st := acmstate.NewMemoryState()
   631  
   632  		// Create accounts
   633  		account1 := newAccount(t, st, "1")
   634  		account2 := newAccount(t, st, "2")
   635  		account3 := newAccount(t, st, "3")
   636  
   637  		// account1 will call account2 which will trigger CALL opcode to account3
   638  		addr := account3
   639  		contractCode := callContractCode(addr)
   640  
   641  		//----------------------------------------------
   642  		// account2 has insufficient balance, should fail
   643  		//txe := runVM(st, account1, account2, contractCode, 100000)
   644  		//exCalls := txe.ExceptionalCalls()
   645  		//require.Len(t, exCalls, 1)
   646  		//require.Equal(t, errors.Codes.InsufficientBalance, errors.GetCode(exCalls[0].Header.Exception))
   647  
   648  		//----------------------------------------------
   649  		// give account2 sufficient balance, should pass
   650  		addToBalance(t, st, account2, 100000)
   651  		//txe = runVM(st, account1, account2, contractCode, 1000)
   652  		//assert.Nil(t, txe.Exception, "Should have sufficient balance")
   653  
   654  		//----------------------------------------------
   655  		// insufficient gas, should fail
   656  		txe := runVM(st, account1, account2, contractCode, 19)
   657  		assert.NotNil(t, txe.Exception, "Expected insufficient gas error")
   658  	})
   659  
   660  	// Test to ensure that contracts called with STATICCALL cannot modify state
   661  	// as per https://github.com/ethereum/EIPs/blob/master/EIPS/eip-214.md
   662  	t.Run("StaticCallReadOnly", func(t *testing.T) {
   663  		gas1, gas2 := byte(0x1), byte(0x1)
   664  		value := byte(0x69)
   665  		var inOff, inSize, retOff, retSize byte
   666  
   667  		logDefault := MustSplice(PUSH1, inSize, PUSH1, inOff)
   668  		testRecipient := engine.AddressFromName("1")
   669  		// check all illegal state modifications in child staticcall frame
   670  		for _, illegalContractCode := range []acm.Bytecode{
   671  			MustSplice(PUSH9, "arbitrary", PUSH1, 0x00, SSTORE),
   672  			MustSplice(logDefault, LOG0),
   673  			MustSplice(logDefault, PUSH1, 0x1, LOG1),
   674  			MustSplice(logDefault, PUSH1, 0x1, PUSH1, 0x1, LOG2),
   675  			MustSplice(logDefault, PUSH1, 0x1, PUSH1, 0x1, PUSH1, 0x1, LOG3),
   676  			MustSplice(logDefault, PUSH1, 0x1, PUSH1, 0x1, PUSH1, 0x1, PUSH1, 0x1, LOG4),
   677  			MustSplice(PUSH1, 0x0, PUSH1, 0x0, PUSH1, 0x69, CREATE),
   678  			MustSplice(PUSH20, testRecipient, SELFDESTRUCT),
   679  		} {
   680  			// TODO: CREATE2
   681  
   682  			t.Logf("Testing state-modifying bytecode: %v", illegalContractCode.MustTokens())
   683  			st := acmstate.NewMemoryState()
   684  			callee := makeAccountWithCode(t, st, "callee", MustSplice(illegalContractCode, PUSH1, 0x1, return1()))
   685  
   686  			// equivalent to CALL, but enforce state immutability for children
   687  			code := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, inOff,
   688  				PUSH1, value, PUSH20, callee, PUSH2, gas1, gas2, STATICCALL, PUSH1, retSize,
   689  				PUSH1, retOff, RETURN)
   690  			caller := makeAccountWithCode(t, st, "caller", code)
   691  
   692  			txe := runVM(st, caller, callee, code, 1000)
   693  			// the topmost caller can never *illegally* modify state
   694  			require.Error(t, txe.Exception)
   695  			require.Equal(t, errors.Codes.IllegalWrite, txe.Exception.ErrorCode(),
   696  				"should get an error from child accounts that st is read only")
   697  		}
   698  	})
   699  
   700  	t.Run("StaticCallWithValue", func(t *testing.T) {
   701  		gas1, gas2 := byte(0x1), byte(0x1)
   702  		value := byte(0x69)
   703  		var inOff, inSize, retOff, retSize byte
   704  
   705  		st := acmstate.NewMemoryState()
   706  
   707  		finalAddress := makeAccountWithCode(t, st, "final", MustSplice(PUSH1, int64(20), return1()))
   708  
   709  		// intermediate account CALLs another contract *with* a value
   710  		callee := makeAccountWithCode(t, st, "callee", MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
   711  			inOff, PUSH1, value, PUSH20, finalAddress, PUSH2, gas1, gas2, CALL, returnWord()))
   712  
   713  		callerCode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
   714  			inOff, PUSH1, value, PUSH20, callee, PUSH2, gas1, gas2, STATICCALL, PUSH1, retSize,
   715  			PUSH1, retOff, RETURN)
   716  		caller := makeAccountWithCode(t, st, "caller", callerCode)
   717  
   718  		addToBalance(t, st, callee, 100000)
   719  		txe := runVM(st, caller, callee, callerCode, 1000)
   720  		require.NotNil(t, txe.Exception)
   721  		require.Equal(t, errors.Codes.IllegalWrite, txe.Exception.ErrorCode(),
   722  			"expected static call violation because of call with value")
   723  	})
   724  
   725  	t.Run("StaticCallNoValue", func(t *testing.T) {
   726  		gas1, gas2 := byte(0x1), byte(0x1)
   727  		value := byte(0x69)
   728  		var inOff, inSize, retOff, retSize byte
   729  
   730  		// this final test just checks that STATICCALL actually works
   731  		st := acmstate.NewMemoryState()
   732  
   733  		finalAddress := makeAccountWithCode(t, st, "final", MustSplice(PUSH1, int64(20), return1()))
   734  		// intermediate account CALLs another contract *without* a value
   735  		callee := makeAccountWithCode(t, st, "callee", MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
   736  			inOff, PUSH1, 0x00, PUSH20, finalAddress, PUSH2, gas1, gas2, CALL, returnWord()))
   737  
   738  		callerCode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
   739  			inOff, PUSH1, value, PUSH20, callee, PUSH2, gas1, gas2, STATICCALL, PUSH1, retSize,
   740  			PUSH1, retOff, RETURN)
   741  		caller := makeAccountWithCode(t, st, "caller", callerCode)
   742  
   743  		addToBalance(t, st, callee, 100000)
   744  		txe := runVM(st, caller, callee, callerCode, 1000)
   745  		// no exceptions expected because value never set in children
   746  		require.NoError(t, txe.Exception.AsError())
   747  		exCalls := txe.ExceptionalCalls()
   748  		require.Len(t, exCalls, 0)
   749  	})
   750  
   751  	// Test evm account creation
   752  	t.Run("Create", func(t *testing.T) {
   753  		st := acmstate.NewMemoryState()
   754  
   755  		code := MustSplice(PUSH1, 0x0, PUSH1, 0x0, PUSH1, 0x0, CREATE, PUSH1, 0, MSTORE, PUSH1, 20, PUSH1, 12, RETURN)
   756  		callee := makeAccountWithCode(t, st, "callee", code)
   757  		// ensure pre-generated address has same sequence number
   758  		nonce := make([]byte, txs.HashLength+uint64Length)
   759  		binary.BigEndian.PutUint64(nonce[txs.HashLength:], 1)
   760  		addr := crypto.NewContractAddress(callee, nonce)
   761  
   762  		gas := big.NewInt(100000)
   763  		caller := newAccount(t, st, "1, 2, 3")
   764  		output, err := call(vm, st, caller, callee, code, nil, gas)
   765  		assert.NoError(t, err, "Should return new address without error")
   766  		assert.Equal(t, addr.Bytes(), output, "Addresses should be equal")
   767  	})
   768  
   769  	// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1014.md
   770  	t.Run("Create2", func(t *testing.T) {
   771  		st := acmstate.NewMemoryState()
   772  
   773  		// salt of 0s
   774  		var salt [32]byte
   775  		code := MustSplice(PUSH1, 0x0, PUSH1, 0x0, PUSH1, 0x0, PUSH32, salt[:], CREATE2, PUSH1, 0, MSTORE, PUSH1, 20, PUSH1, 12, RETURN)
   776  		callee := makeAccountWithCode(t, st, "callee", code)
   777  		addr := crypto.NewContractAddress2(callee, salt, code)
   778  
   779  		gas := big.NewInt(100000)
   780  		caller := newAccount(t, st, "1, 2, 3")
   781  		output, err := call(vm, st, caller, callee, code, nil, gas)
   782  		assert.NoError(t, err, "Should return new address without error")
   783  		assert.Equal(t, addr.Bytes(), output, "Returned value not equal to create2 address")
   784  	})
   785  
   786  	// This test was introduced to cover an issues exposed in our handling of the
   787  	// gas limit passed from caller to callee on various forms of CALL.
   788  	// The idea of this test is to implement a simple DelegateCall in EVM code
   789  	// We first run the DELEGATECALL with _just_ enough gas expecting a simple return,
   790  	// and then run it with 1 gas unit less, expecting a failure
   791  	t.Run("DelegateCallGas", func(t *testing.T) {
   792  		st := acmstate.NewMemoryState()
   793  
   794  		inOff := 0
   795  		inSize := 0 // no call data
   796  		retOff := 0
   797  		retSize := 32
   798  		calleeReturnValue := int64(20)
   799  
   800  		callee := makeAccountWithCode(t, st, "callee", MustSplice(PUSH1, calleeReturnValue, PUSH1, 0, MSTORE, PUSH1, 32, PUSH1, 0, RETURN))
   801  
   802  		// 6 op codes total
   803  		baseOpsCost := engine.GasBaseOp * 6
   804  		// 4 pushes
   805  		pushCost := engine.GasStackOp * 4
   806  		// 2 pushes 2 pops
   807  		returnCost := engine.GasStackOp * 4
   808  
   809  		delegateCallCost := baseOpsCost + pushCost + returnCost
   810  
   811  		// Here we split up the caller code so we can make a DELEGATE call with
   812  		// different amounts of gas. The value we sandwich in the middle is the amount
   813  		// we subtract from the available gas (that the caller has available), so:
   814  		// code := MustSplice(callerCodePrefix, <amount to subtract from GAS> , callerCodeSuffix)
   815  		// gives us the code to make the call
   816  		callerCodePrefix := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize,
   817  			PUSH1, inOff, PUSH20, callee, PUSH1)
   818  		callerCodeSuffix := MustSplice(DELEGATECALL, returnWord())
   819  
   820  		// Perform a delegate call
   821  		//Give just enough gas to make the DELEGATECALL
   822  		callerCode := MustSplice(callerCodePrefix,
   823  			delegateCallCost, callerCodeSuffix)
   824  		caller := makeAccountWithCode(t, st, "caller", callerCode)
   825  		// Should pass
   826  		txe := runVM(st, caller, callee, callerCode, 100)
   827  		assert.Nil(t, txe.Exception, "Should have sufficient funds for call")
   828  		assert.Equal(t, Int64ToWord256(calleeReturnValue).Bytes(), txe.Result.Return)
   829  
   830  		callerCode2 := MustSplice(callerCodePrefix,
   831  			// Shouldn't be enough gas to make call
   832  			delegateCallCost-1, callerCodeSuffix)
   833  		caller2 := makeAccountWithCode(t, st, "caller2", callerCode2)
   834  
   835  		// Should fail
   836  		txe = runVM(st, caller2, callee, callerCode2, 100)
   837  		assert.NotNil(t, txe.Exception, "Should have insufficient gas for call")
   838  	})
   839  
   840  	t.Run("MemoryBounds", func(t *testing.T) {
   841  		st := acmstate.NewMemoryState()
   842  		blockchain := new(engine.TestBlockchain)
   843  		eventSink := exec.NewNoopEventSink()
   844  		vm := New(engine.Options{
   845  			MemoryProvider: func(err errors.Sink) engine.Memory {
   846  				return engine.NewDynamicMemory(1024, 2048, err)
   847  			},
   848  		})
   849  		caller := makeAccountWithCode(t, st, "caller", nil)
   850  		callee := makeAccountWithCode(t, st, "callee", nil)
   851  		word := One256
   852  		// This attempts to store a value at the memory boundary and return it
   853  		params := engine.CallParams{
   854  			Gas:    big.NewInt(100000),
   855  			Caller: caller,
   856  			Callee: callee,
   857  		}
   858  		code := MustSplice(pushWord(word), storeAtEnd(), MLOAD, storeAtEnd(), returnAfterStore())
   859  
   860  		output, err := vm.Execute(st, blockchain, eventSink, params, code)
   861  		assert.NoError(t, err)
   862  		assert.Equal(t, word.Bytes(), output)
   863  
   864  		// Same with number
   865  		word = Int64ToWord256(232234234432)
   866  		code = MustSplice(pushWord(word), storeAtEnd(), MLOAD, storeAtEnd(), returnAfterStore())
   867  		output, err = vm.Execute(st, blockchain, eventSink, params, code)
   868  		assert.NoError(t, err)
   869  		assert.Equal(t, word.Bytes(), output)
   870  
   871  		// Now test a series of boundary stores
   872  		code = pushWord(word)
   873  		for i := 0; i < 10; i++ {
   874  			code = MustSplice(code, storeAtEnd(), MLOAD)
   875  		}
   876  		code = MustSplice(code, storeAtEnd(), returnAfterStore())
   877  		output, err = vm.Execute(st, blockchain, eventSink, params, code)
   878  		assert.NoError(t, err)
   879  		assert.Equal(t, word.Bytes(), output)
   880  
   881  		// Same as above but we should breach the upper memory limit set in memoryProvider
   882  		code = pushWord(word)
   883  		for i := 0; i < 100; i++ {
   884  			code = MustSplice(code, storeAtEnd(), MLOAD)
   885  		}
   886  		code = MustSplice(code, storeAtEnd(), returnAfterStore())
   887  		_, err = vm.Execute(st, blockchain, eventSink, params, code)
   888  		assert.Error(t, err, "Should hit memory out of bounds")
   889  	})
   890  
   891  	t.Run("MsgSender", func(t *testing.T) {
   892  		st := acmstate.NewMemoryState()
   893  		account1 := newAccount(t, st, "1, 2, 3")
   894  		account2 := newAccount(t, st, "3, 2, 1")
   895  		gas := big.NewInt(100000)
   896  
   897  		/*
   898  				pragma solidity ^0.5.4;
   899  
   900  				contract SimpleStorage {
   901  			                function get() public constant returns (address) {
   902  			        	        return msg.sender;
   903  			    	        }
   904  				}
   905  		*/
   906  
   907  		// This bytecode is compiled from Solidity contract above using remix.ethereum.org online compiler
   908  		code := hex.MustDecodeString("6060604052341561000f57600080fd5b60ca8061001d6000396000f30060606040526004361060" +
   909  			"3f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636d4ce63c14604457" +
   910  			"5b600080fd5b3415604e57600080fd5b60546096565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ff" +
   911  			"ffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000339050905600a165627a" +
   912  			"7a72305820b9ebf49535372094ae88f56d9ad18f2a79c146c8f56e7ef33b9402924045071e0029")
   913  
   914  		var err error
   915  		// Run the contract initialisation code to obtain the contract code that would be mounted at account2
   916  		contractCode, err := call(vm, st, account1, account2, code, code, gas)
   917  		require.NoError(t, err)
   918  
   919  		// Not needed for this test (since contract code is passed as argument to vm), but this is what an execution
   920  		// framework must do
   921  		err = engine.InitEVMCode(st, account2, contractCode)
   922  		require.NoError(t, err)
   923  
   924  		// Input is the function hash of `get()`
   925  		input := hex.MustDecodeString("6d4ce63c")
   926  
   927  		output, err := call(vm, st, account1, account2, contractCode, input, gas)
   928  		require.NoError(t, err)
   929  
   930  		assert.Equal(t, account1.Word256().Bytes(), output)
   931  	})
   932  
   933  	t.Run("Invalid", func(t *testing.T) {
   934  		st := acmstate.NewMemoryState()
   935  
   936  		// Create accounts
   937  		account1 := newAccount(t, st, "1")
   938  		account2 := newAccount(t, st, "1, 0, 1")
   939  
   940  		gas := big.NewInt(100000)
   941  
   942  		bytecode := MustSplice(PUSH32, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61,
   943  			0x67, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   944  			0x00, 0x00, 0x00, PUSH1, 0x00, MSTORE, PUSH1, 0x0E, PUSH1, 0x00, INVALID)
   945  
   946  		output, err := call(vm, st, account1, account2, bytecode, nil, gas)
   947  		assert.Equal(t, errors.Codes.ExecutionAborted, errors.GetCode(err))
   948  		t.Logf("Output: %v Error: %v\n", output, err)
   949  	})
   950  
   951  	t.Run("ReturnDataSize", func(t *testing.T) {
   952  		st := acmstate.NewMemoryState()
   953  
   954  		accountName := "account2addresstests"
   955  
   956  		ret := "My return message"
   957  		callcode := MustSplice(PUSH32, RightPadWord256([]byte(ret)), PUSH1, 0x00, MSTORE, PUSH1, len(ret), PUSH1, 0x00, RETURN)
   958  
   959  		// Create accounts
   960  		account1 := newAccount(t, st, "1")
   961  		account2 := makeAccountWithCode(t, st, accountName, callcode)
   962  
   963  		gas := big.NewInt(100000)
   964  
   965  		gas1, gas2 := byte(0x1), byte(0x1)
   966  		value := byte(0x69)
   967  		inOff, inSize := byte(0x0), byte(0x0) // no call data
   968  		retOff, retSize := byte(0x0), byte(len(ret))
   969  
   970  		bytecode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, inOff, PUSH1, value,
   971  			PUSH20, account2, PUSH2, gas1, gas2, CALL,
   972  			RETURNDATASIZE, PUSH1, 0x00, MSTORE, PUSH1, 0x20, PUSH1, 0x00, RETURN)
   973  
   974  		expected := Uint64ToWord256(uint64(len(ret))).Bytes()
   975  
   976  		output, err := call(vm, st, account1, account2, bytecode, nil, gas)
   977  		require.NoError(t, err)
   978  		assert.Equal(t, expected, output)
   979  
   980  		t.Logf("Output: %v Error: %v\n", output, err)
   981  
   982  		if err != nil {
   983  			t.Fatal(err)
   984  		}
   985  	})
   986  
   987  	t.Run("ReturnDataCopy", func(t *testing.T) {
   988  		st := acmstate.NewMemoryState()
   989  
   990  		accountName := "account2addresstests"
   991  
   992  		ret := "My return message"
   993  		callcode := MustSplice(PUSH32, RightPadWord256([]byte(ret)), PUSH1, 0x00, MSTORE, PUSH1, len(ret), PUSH1, 0x00, RETURN)
   994  
   995  		// Create accounts
   996  		account1 := newAccount(t, st, "1")
   997  		account2 := makeAccountWithCode(t, st, accountName, callcode)
   998  
   999  		gas := big.NewInt(100000)
  1000  
  1001  		gas1, gas2 := byte(0x1), byte(0x1)
  1002  		value := byte(0x69)
  1003  		inOff, inSize := byte(0x0), byte(0x0) // no call data
  1004  		retOff, retSize := byte(0x0), byte(len(ret))
  1005  
  1006  		bytecode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1, inOff, PUSH1, value,
  1007  			PUSH20, account2, PUSH2, gas1, gas2, CALL, RETURNDATASIZE, PUSH1, 0x00, PUSH1, 0x00, RETURNDATACOPY,
  1008  			RETURNDATASIZE, PUSH1, 0x00, RETURN)
  1009  
  1010  		expected := []byte(ret)
  1011  
  1012  		output, err := call(vm, st, account1, account2, bytecode, nil, gas)
  1013  		require.NoError(t, err)
  1014  		assert.Equal(t, expected, output)
  1015  
  1016  		t.Logf("Output: %v Error: %v\n", output, err)
  1017  	})
  1018  
  1019  	t.Run("CallNonExistent", func(t *testing.T) {
  1020  		st := acmstate.NewMemoryState()
  1021  		blockchain := new(engine.TestBlockchain)
  1022  		eventSink := exec.NewNoopEventSink()
  1023  		account1 := newAccount(t, st, "1")
  1024  		addToBalance(t, st, account1, 100000)
  1025  		unknownAddress := engine.AddressFromName("nonexistent")
  1026  
  1027  		params := engine.CallParams{
  1028  			Caller: account1,
  1029  			Callee: unknownAddress,
  1030  			Value:  *big.NewInt(100),
  1031  			Gas:    big.NewInt(100000),
  1032  		}
  1033  		_, ex := vm.Execute(st, blockchain, eventSink, params, nil)
  1034  		require.Equal(t, errors.Codes.NonExistentAccount, errors.GetCode(ex),
  1035  			"Should not be able to call account before creating it (even before initialising)")
  1036  		acc, err := st.GetAccount(unknownAddress)
  1037  		require.NoError(t, err)
  1038  		require.Nil(t, acc)
  1039  	})
  1040  
  1041  	t.Run("GetBlockHash", func(t *testing.T) {
  1042  		st := acmstate.NewMemoryState()
  1043  		blockchain := new(engine.TestBlockchain)
  1044  		eventSink := exec.NewNoopEventSink()
  1045  
  1046  		// Create accounts
  1047  		account1 := newAccount(t, st, "1")
  1048  		account2 := newAccount(t, st, "101")
  1049  
  1050  		var gas = big.NewInt(100000)
  1051  
  1052  		bytecode := MustSplice(PUSH1, 2, BLOCKHASH)
  1053  
  1054  		params := engine.CallParams{
  1055  			Caller: account1,
  1056  			Callee: account2,
  1057  			Gas:    gas,
  1058  		}
  1059  		// Non existing block
  1060  		blockchain.BlockHeight = 1
  1061  		_, err := vm.Execute(st, blockchain, eventSink, params, bytecode)
  1062  		require.Equal(t, errors.Codes.InvalidBlockNumber, errors.GetCode(err),
  1063  			"attempt to get block hash of a non-existent block")
  1064  
  1065  		// Excessive old block
  1066  		blockchain.BlockHeight = 258
  1067  		bytecode = MustSplice(PUSH1, 1, BLOCKHASH)
  1068  
  1069  		_, err = vm.Execute(st, blockchain, eventSink, params, bytecode)
  1070  		require.Equal(t, errors.Codes.BlockNumberOutOfRange, errors.GetCode(err),
  1071  			"attempt to get block hash of a block outside of allowed range")
  1072  
  1073  		// Get block hash
  1074  		blockchain.BlockHeight = 257
  1075  		bytecode = MustSplice(PUSH1, 2, BLOCKHASH, return1())
  1076  
  1077  		output, err := vm.Execute(st, blockchain, eventSink, params, bytecode)
  1078  		assert.NoError(t, err)
  1079  		assert.Equal(t, LeftPadWord256([]byte{2}), LeftPadWord256(output))
  1080  
  1081  		// Get block hash fail
  1082  		blockchain.BlockHeight = 3
  1083  		bytecode = MustSplice(PUSH1, 4, BLOCKHASH, return1())
  1084  
  1085  		_, err = vm.Execute(st, blockchain, eventSink, params, bytecode)
  1086  		require.Equal(t, errors.Codes.InvalidBlockNumber, errors.GetCode(err),
  1087  			"attempt to get block hash failed")
  1088  	})
  1089  
  1090  	t.Run("PushWord", func(t *testing.T) {
  1091  		word := Int64ToWord256(int64(2133213213))
  1092  		assert.Equal(t, MustSplice(PUSH4, 0x7F, 0x26, 0x40, 0x1D), pushWord(word))
  1093  		word[0] = 1
  1094  		assert.Equal(t, MustSplice(PUSH32,
  1095  			1, 0, 0, 0, 0, 0, 0, 0,
  1096  			0, 0, 0, 0, 0, 0, 0, 0,
  1097  			0, 0, 0, 0, 0, 0, 0, 0,
  1098  			0, 0, 0, 0, 0x7F, 0x26, 0x40, 0x1D), pushWord(word))
  1099  		assert.Equal(t, MustSplice(PUSH1, 0), pushWord(Word256{}))
  1100  		assert.Equal(t, MustSplice(PUSH1, 1), pushWord(Int64ToWord256(1)))
  1101  	})
  1102  
  1103  	// Kind of indirect test of Splice, but here to avoid import cycles
  1104  	t.Run("Bytecode", func(t *testing.T) {
  1105  		assert.Equal(t,
  1106  			MustSplice(1, 2, 3, 4, 5, 6),
  1107  			MustSplice(1, 2, 3, MustSplice(4, 5, 6)))
  1108  		assert.Equal(t,
  1109  			MustSplice(1, 2, 3, 4, 5, 6, 7, 8),
  1110  			MustSplice(1, 2, 3, MustSplice(4, MustSplice(5), 6), 7, 8))
  1111  		assert.Equal(t,
  1112  			MustSplice(PUSH1, 2),
  1113  			MustSplice(byte(PUSH1), 0x02))
  1114  		assert.Equal(t,
  1115  			[]byte{},
  1116  			MustSplice(MustSplice(MustSplice())))
  1117  
  1118  		contractAccount := &acm.Account{Address: crypto.AddressFromWord256(Int64ToWord256(102))}
  1119  		addr := contractAccount.Address
  1120  		gas1, gas2 := byte(0x1), byte(0x1)
  1121  		value := byte(0x69)
  1122  		inOff, inSize := byte(0x0), byte(0x0) // no call data
  1123  		retOff, retSize := byte(0x0), byte(0x20)
  1124  		contractCodeBytecode := MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
  1125  			inOff, PUSH1, value, PUSH20, addr, PUSH2, gas1, gas2, CALL, PUSH1, retSize,
  1126  			PUSH1, retOff, RETURN)
  1127  		contractCode := []byte{0x60, retSize, 0x60, retOff, 0x60, inSize, 0x60, inOff, 0x60, value, 0x73}
  1128  		contractCode = append(contractCode, addr[:]...)
  1129  		contractCode = append(contractCode, []byte{0x61, gas1, gas2, 0xf1, 0x60, 0x20, 0x60, 0x0, 0xf3}...)
  1130  		assert.Equal(t, contractCode, contractCodeBytecode)
  1131  	})
  1132  
  1133  	t.Run("Concat", func(t *testing.T) {
  1134  		assert.Equal(t,
  1135  			[]byte{0x01, 0x02, 0x03, 0x04},
  1136  			Concat([]byte{0x01, 0x02}, []byte{0x03, 0x04}))
  1137  	})
  1138  
  1139  	t.Run("Subslice", func(t *testing.T) {
  1140  		const size = 10
  1141  		data := make([]byte, size)
  1142  		for i := 0; i < size; i++ {
  1143  			data[i] = byte(i)
  1144  		}
  1145  		for n := uint64(0); n < size; n++ {
  1146  			data = data[:n]
  1147  			for offset := uint64(0); offset < size; offset++ {
  1148  				for length := uint64(0); length < size; length++ {
  1149  					_, err := subslice(data, offset, length)
  1150  					if offset < 0 || length < 0 || n < offset {
  1151  						assert.Error(t, err)
  1152  					} else {
  1153  						assert.NoError(t, err)
  1154  					}
  1155  				}
  1156  			}
  1157  		}
  1158  
  1159  		bs, err := subslice([]byte{1, 2, 3, 4, 5, 6, 7, 8}, 4, 32)
  1160  		require.NoError(t, err)
  1161  		assert.Equal(t, []byte{
  1162  			5, 6, 7, 8, 0, 0, 0, 0,
  1163  			0, 0, 0, 0, 0, 0, 0, 0,
  1164  			0, 0, 0, 0, 0, 0, 0, 0,
  1165  			0, 0, 0, 0, 0, 0, 0, 0,
  1166  		}, bs)
  1167  	})
  1168  
  1169  	t.Run("DataStackOverflow", func(t *testing.T) {
  1170  		st := acmstate.NewMemoryState()
  1171  		blockchain := new(engine.TestBlockchain)
  1172  		eventSink := exec.NewNoopEventSink()
  1173  		account1 := newAccount(t, st, "1, 2, 3")
  1174  		account2 := newAccount(t, st, "3, 2, 1")
  1175  
  1176  		/*
  1177  			pragma solidity ^0.5.4;
  1178  
  1179  			contract SimpleStorage {
  1180  				function get() public constant returns (address) {
  1181  					return get();
  1182  				}
  1183  			}
  1184  		*/
  1185  
  1186  		// This bytecode is compiled from Solidity contract above using remix.ethereum.org online compiler
  1187  		code, err := hex.DecodeString("608060405234801561001057600080fd5b5060d18061001f6000396000f300608060405260043610" +
  1188  			"603f576000357c0100000000000000000000000000000000000000000000000000000000900463ff" +
  1189  			"ffffff1680636d4ce63c146044575b600080fd5b348015604f57600080fd5b5060566098565b6040" +
  1190  			"51808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffff" +
  1191  			"ffffffffffff16815260200191505060405180910390f35b600060a06098565b9050905600a16562" +
  1192  			"7a7a72305820daacfba0c21afacb5b67f26bc8021de63eaa560db82f98357d4e513f3249cf350029")
  1193  		require.NoError(t, err)
  1194  
  1195  		// Run the contract initialisation code to obtain the contract code that would be mounted at account2
  1196  		params := engine.CallParams{
  1197  			Caller: account1,
  1198  			Callee: account2,
  1199  			Input:  code,
  1200  			Gas:    big.NewInt(1000000),
  1201  		}
  1202  		vm := New(engine.Options{
  1203  			DataStackMaxDepth: 4,
  1204  		})
  1205  
  1206  		code, err = vm.Execute(st, blockchain, eventSink, params, code)
  1207  		require.NoError(t, err)
  1208  
  1209  		// Input is the function hash of `get()`
  1210  		params.Input, err = hex.DecodeString("6d4ce63c")
  1211  		require.NoError(t, err)
  1212  
  1213  		_, ex := vm.Execute(st, blockchain, eventSink, params, code)
  1214  		require.Equal(t, errors.Codes.DataStackOverflow, errors.GetCode(ex), "Should be stack overflow")
  1215  	})
  1216  
  1217  	t.Run("CallStackOverflow", func(t *testing.T) {
  1218  		st := acmstate.NewMemoryState()
  1219  		blockchain := new(engine.TestBlockchain)
  1220  		eventSink := exec.NewNoopEventSink()
  1221  		txe := new(exec.TxExecution)
  1222  
  1223  		account1 := newAccount(t, st, "1, 2, 3")
  1224  		account2 := newAccount(t, st, "3, 2, 1")
  1225  
  1226  		// Sender accepts lot of gaz but we run on a caped call stack node
  1227  		/*
  1228  			pragma solidity ^0.5.4;
  1229  
  1230  			contract A {
  1231  			   function callMeBack() public {
  1232  					return require(msg.sender.call(bytes4(keccak256("callMeBack()")),this));
  1233  				}
  1234  			}
  1235  		*/
  1236  
  1237  		// This bytecode is compiled from Solidity contract above using remix.ethereum.org online compiler
  1238  		code, err := hex.DecodeString("608060405234801561001057600080fd5b5061017a806100206000396000f3006080604052600436" +
  1239  			"10610041576000357c01000000000000000000000000000000000000000000000000000000009004" +
  1240  			"63ffffffff168063692c3b7c14610046575b600080fd5b34801561005257600080fd5b5061005b61" +
  1241  			"005d565b005b3373ffffffffffffffffffffffffffffffffffffffff1660405180807f63616c6c4d" +
  1242  			"654261636b28290000000000000000000000000000000000000000815250600c0190506040518091" +
  1243  			"0390207c010000000000000000000000000000000000000000000000000000000090043060405182" +
  1244  			"63ffffffff167c010000000000000000000000000000000000000000000000000000000002815260" +
  1245  			"0401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffff" +
  1246  			"ffffffffffffff1681526020019150506000604051808303816000875af192505050151561014c57" +
  1247  			"600080fd5b5600a165627a7a723058209315a40abb8b23b7c2a340e938b01367b419a23818475a2e" +
  1248  			"ee80d09da3f7ba780029")
  1249  		require.NoError(t, err)
  1250  
  1251  		params := engine.CallParams{
  1252  			Caller: account1,
  1253  			Callee: account2,
  1254  			Input:  code,
  1255  			Gas:    big.NewInt(1000000),
  1256  		}
  1257  		options := engine.Options{
  1258  			CallStackMaxDepth: 2,
  1259  		}
  1260  		vm := New(options)
  1261  		// Run the contract initialisation code to obtain the contract code that would be mounted at account2
  1262  		contractCode, err := vm.Execute(st, blockchain, eventSink, params, code)
  1263  		require.NoError(t, err)
  1264  
  1265  		err = engine.InitEVMCode(st, account1, contractCode)
  1266  		require.NoError(t, err)
  1267  		err = engine.InitEVMCode(st, account2, contractCode)
  1268  		require.NoError(t, err)
  1269  
  1270  		// keccak256 hash of 'callMeBack()'
  1271  		params.Input, err = hex.DecodeString("692c3b7c")
  1272  		require.NoError(t, err)
  1273  
  1274  		_, err = vm.Execute(st, blockchain, txe, params, contractCode)
  1275  		// The TxExecution must be an exception to get the callerror
  1276  		txe.PushError(err)
  1277  		require.Error(t, err)
  1278  		callError := txe.CallError()
  1279  		require.Error(t, callError)
  1280  		require.Equal(t, errors.Codes.CallStackOverflow, errors.GetCode(callError))
  1281  		// Errors are post-order so first is deepest
  1282  		require.True(t, len(callError.NestedErrors) > 0)
  1283  		deepestErr := callError.NestedErrors[0]
  1284  		require.Equal(t, errors.Codes.CallStackOverflow, errors.GetCode(deepestErr))
  1285  		assert.Equal(t, options.CallStackMaxDepth, deepestErr.StackDepth)
  1286  		assert.Equal(t, account2, deepestErr.Callee)
  1287  		assert.Equal(t, account1, deepestErr.Caller)
  1288  	})
  1289  
  1290  	t.Run("ExtCodeHash", func(t *testing.T) {
  1291  		st := acmstate.NewMemoryState()
  1292  		account1 := newAccount(t, st, "1")
  1293  		account2 := newAccount(t, st, "101")
  1294  
  1295  		gas := big.NewInt(100000)
  1296  
  1297  		// The EXTCODEHASH of the account without code is c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
  1298  		//    what is the keccack256 hash of empty data.
  1299  		bytecode := MustSplice(PUSH20, account1, EXTCODEHASH, return1())
  1300  		output, err := call(vm, st, account1, account2, bytecode, nil, gas)
  1301  		assert.NoError(t, err)
  1302  		assert.Equal(t, hex.MustDecodeString("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), output)
  1303  
  1304  		// The EXTCODEHASH of a native account is hash of its name.
  1305  		bytecode = MustSplice(PUSH1, 0x03, EXTCODEHASH, return1())
  1306  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
  1307  		assert.NoError(t, err)
  1308  		assert.Equal(t, crypto.Keccak256([]byte("ripemd160Func")), output)
  1309  
  1310  		// EXTCODEHASH of non-existent account should be 0
  1311  		bytecode = MustSplice(PUSH1, 0xff, EXTCODEHASH, return1())
  1312  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
  1313  		assert.NoError(t, err)
  1314  		assert.Equal(t, Zero256[:], output)
  1315  
  1316  		// EXTCODEHASH is the hash of an account code
  1317  		acc := makeAccountWithCode(t, st, "trustedCode", MustSplice(BLOCKHASH, return1()))
  1318  		bytecode = MustSplice(PUSH20, acc, EXTCODEHASH, return1())
  1319  		output, err = call(vm, st, account1, account2, bytecode, nil, gas)
  1320  		assert.NoError(t, err)
  1321  		assert.Equal(t, hex.MustDecodeString("010da270094b5199d3e54f89afe4c66cdd658dd8111a41998714227e14e171bd"), output)
  1322  	})
  1323  
  1324  	// Tests logs and events.
  1325  	t.Run("TestLogEvents", func(t *testing.T) {
  1326  		expectedData := []byte{0x10}
  1327  		expectedHeight := uint64(0)
  1328  		expectedTopics := []Word256{
  1329  			Int64ToWord256(1),
  1330  			Int64ToWord256(2),
  1331  			Int64ToWord256(3),
  1332  			Int64ToWord256(4)}
  1333  
  1334  		st := acmstate.NewMemoryState()
  1335  		blockchain := new(engine.TestBlockchain)
  1336  		// Create accounts
  1337  		address1 := crypto.Address{1, 3, 5, 7, 9}
  1338  		address2 := crypto.Address{2, 4, 6, 8, 10}
  1339  
  1340  		err := engine.CreateAccount(st, address1)
  1341  		require.NoError(t, err)
  1342  		err = engine.CreateAccount(st, address2)
  1343  		require.NoError(t, err)
  1344  
  1345  		mstore8 := byte(MSTORE8)
  1346  		push1 := byte(PUSH1)
  1347  		log4 := byte(LOG4)
  1348  		stop := byte(STOP)
  1349  
  1350  		code := []byte{
  1351  			push1, 16, // data value
  1352  			push1, 0, // memory slot
  1353  			mstore8,
  1354  			push1, 4, // topic 4
  1355  			push1, 3, // topic 3
  1356  			push1, 2, // topic 2
  1357  			push1, 1, // topic 1
  1358  			push1, 1, // size of data
  1359  			push1, 0, // data starts at this offset
  1360  			log4,
  1361  			stop,
  1362  		}
  1363  
  1364  		txe := new(exec.TxExecution)
  1365  
  1366  		params := engine.CallParams{
  1367  			Caller: address1,
  1368  			Callee: address2,
  1369  			Gas:    big.NewInt(1000000),
  1370  		}
  1371  		_, err = vm.Execute(st, blockchain, txe, params, code)
  1372  		require.NoError(t, err)
  1373  
  1374  		for _, ev := range txe.Events {
  1375  			if ev.Log != nil {
  1376  				if !reflect.DeepEqual(ev.Log.Topics, expectedTopics) {
  1377  					t.Errorf("Event topics are wrong. Got: %v. Expected: %v", ev.Log.Topics, expectedTopics)
  1378  				}
  1379  				if !bytes.Equal(ev.Log.Data, expectedData) {
  1380  					t.Errorf("Event data is wrong. Got: %s. Expected: %s", ev.Log.Data, expectedData)
  1381  				}
  1382  				if ev.Header.Height != expectedHeight {
  1383  					t.Errorf("Event block height is wrong. Got: %d. Expected: %d", ev.Header.Height, expectedHeight)
  1384  				}
  1385  				return
  1386  			}
  1387  		}
  1388  		t.Fatalf("Did not see LogEvent")
  1389  	})
  1390  
  1391  	t.Run("BigModExp", func(t *testing.T) {
  1392  		st := acmstate.NewMemoryState()
  1393  		account1 := newAccount(t, st, "1")
  1394  		account2 := newAccount(t, st, "101")
  1395  
  1396  		// The solidity compiled contract. It calls bigmodexp with b,e,m inputs and compares the result with proof, where m is the mod, b the base, e the exp, and proof the expected result.
  1397  		bytecode := solidity.DeployedBytecode_BigMod
  1398  
  1399  		// The function "expmod" is an assertion. It takes the base, exponent, modulus, and the expected value and
  1400  		// returns 1 if the values match.
  1401  		spec, err := abi.ReadSpec(solidity.Abi_BigMod)
  1402  		require.NoError(t, err)
  1403  
  1404  		expModFunctionID := spec.Functions["expmod"].FunctionID
  1405  
  1406  		n := int64(10)
  1407  		for base := -n; base < n; base++ {
  1408  			for exp := -n; exp < n; exp++ {
  1409  				for mod := int64(1); mod < n; mod++ {
  1410  					b := big.NewInt(base)
  1411  					e := big.NewInt(exp)
  1412  					m := big.NewInt(mod)
  1413  					v := new(big.Int).Exp(b, e, m)
  1414  					if v == nil {
  1415  						continue
  1416  					}
  1417  
  1418  					input := MustSplice(expModFunctionID, // expmod function
  1419  						BigIntToWord256(b), BigIntToWord256(e), BigIntToWord256(m), // base^exp % mod
  1420  						BigIntToWord256(v)) // == expected
  1421  
  1422  					gas := big.NewInt(10000000)
  1423  					out, err := call(vm, st, account1, account2, bytecode, input, gas)
  1424  
  1425  					require.NoError(t, err)
  1426  
  1427  					require.Equal(t, One256, LeftPadWord256(out), "expected %d^%d mod %d == %d",
  1428  						base, exp, mod, e)
  1429  				}
  1430  			}
  1431  		}
  1432  	})
  1433  
  1434  	t.Run("SDIV", func(t *testing.T) {
  1435  		st := acmstate.NewMemoryState()
  1436  		blockchain := new(engine.TestBlockchain)
  1437  		eventSink := exec.NewNoopEventSink()
  1438  
  1439  		account1 := newAccount(t, st, "1")
  1440  		account2 := newAccount(t, st, "101")
  1441  
  1442  		tests := []struct {
  1443  			name     string
  1444  			bytecode []byte
  1445  			expected []byte
  1446  		}{
  1447  			{
  1448  				// (SDIV 7 3 )
  1449  				name:     "sdiv0",
  1450  				bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x07, SDIV, return1()),
  1451  				expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1452  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1453  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1454  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
  1455  			},
  1456  			{
  1457  				// (SDIV 7 (- 0 3) )
  1458  				name:     "sdiv1",
  1459  				bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x00, SUB, PUSH1, 0x07, SDIV, return1()),
  1460  				expected: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1461  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1462  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1463  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE},
  1464  			},
  1465  			{
  1466  				// (SDIV (- 0 7) 3 )
  1467  				name:     "sdiv2",
  1468  				bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x07, PUSH1, 0x00, SUB, SDIV, return1()),
  1469  				expected: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1470  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1471  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1472  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE},
  1473  			},
  1474  			{
  1475  				// (SDIV (- 0 7) (- 0 3) )
  1476  				name:     "sdiv3",
  1477  				bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x00, SUB, PUSH1, 0x07, PUSH1, 0x00, SUB, SDIV, return1()),
  1478  				expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1479  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1480  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1481  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
  1482  			},
  1483  		}
  1484  		for _, tt := range tests {
  1485  			params := engine.CallParams{
  1486  				Caller: account1,
  1487  				Callee: account2,
  1488  				Gas:    big.NewInt(1000000),
  1489  			}
  1490  			if output, err := vm.Execute(st, blockchain, eventSink, params, tt.bytecode); err != nil || !bytes.Equal(output, tt.expected) {
  1491  				t.Errorf("Reported error in %v.", tt.name)
  1492  				assert.NoError(t, err)
  1493  				assert.Equal(t, tt.expected, output)
  1494  			}
  1495  		}
  1496  	})
  1497  
  1498  	t.Run("SMOD", func(t *testing.T) {
  1499  		st := acmstate.NewMemoryState()
  1500  		blockchain := new(engine.TestBlockchain)
  1501  		eventSink := exec.NewNoopEventSink()
  1502  
  1503  		account1 := newAccount(t, st, "1")
  1504  		account2 := newAccount(t, st, "101")
  1505  
  1506  		tests := []struct {
  1507  			name     string
  1508  			bytecode []byte
  1509  			expected []byte
  1510  		}{
  1511  			{
  1512  				// (SMOD 7 3)
  1513  				name:     "smod0",
  1514  				bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x07, SMOD, return1()),
  1515  				expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1516  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1517  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1518  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
  1519  			},
  1520  			{
  1521  				// (SMOD 7 (- 0 3))
  1522  				name:     "smod1",
  1523  				bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x00, SUB, PUSH1, 0x07, SMOD, return1()),
  1524  				expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1525  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1526  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1527  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
  1528  			},
  1529  			{
  1530  				// (SMOD (- 0 7) 3)
  1531  				name:     "smod2",
  1532  				bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x07, PUSH1, 0x00, SUB, SMOD, return1()),
  1533  				expected: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1534  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1535  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1536  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
  1537  			},
  1538  			{
  1539  				// (SMOD (- 0 7) (- 0 3))
  1540  				name:     "smod3",
  1541  				bytecode: MustSplice(PUSH1, 0x03, PUSH1, 0x00, SUB, PUSH1, 0x07, PUSH1, 0x00, SUB, SMOD, return1()),
  1542  				expected: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1543  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1544  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1545  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
  1546  			},
  1547  		}
  1548  		for _, tt := range tests {
  1549  			params := engine.CallParams{
  1550  				Caller: account1,
  1551  				Callee: account2,
  1552  				Gas:    big.NewInt(1000000),
  1553  			}
  1554  			if output, err := vm.Execute(st, blockchain, eventSink, params, tt.bytecode); err != nil || !bytes.Equal(output, tt.expected) {
  1555  				t.Errorf("Reported error in %v.", tt.name)
  1556  				assert.NoError(t, err)
  1557  				assert.Equal(t, tt.expected, output)
  1558  			}
  1559  		}
  1560  	})
  1561  
  1562  	t.Run("SIGNEXTEND and MSTORE8", func(t *testing.T) {
  1563  		st := acmstate.NewMemoryState()
  1564  		blockchain := new(engine.TestBlockchain)
  1565  		eventSink := exec.NewNoopEventSink()
  1566  
  1567  		account1 := newAccount(t, st, "1")
  1568  		account2 := newAccount(t, st, "101")
  1569  
  1570  		tests := []struct {
  1571  			name     string
  1572  			bytecode []byte
  1573  			expected []byte
  1574  		}{
  1575  			{
  1576  				// 0x6A == 0b01101010
  1577  				name:     "signextend0",
  1578  				bytecode: MustSplice(PUSH3, 0x12, 0x2F, 0x6A, PUSH1, 0x00, SIGNEXTEND, return1()),
  1579  				expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1580  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1581  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1582  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6A},
  1583  			},
  1584  			{
  1585  				name: "signextend1",
  1586  				bytecode: MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1587  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1588  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1589  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1590  					PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1591  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1592  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1593  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, SIGNEXTEND, return1()),
  1594  				expected: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1595  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1596  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1597  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
  1598  			},
  1599  			{
  1600  				name: "mstore8",
  1601  				bytecode: MustSplice(PUSH32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1602  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1603  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1604  					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  1605  					PUSH1, 0x01, MSTORE8, PUSH1, 0x01, MLOAD, return1()),
  1606  				expected: []byte{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1607  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1608  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1609  					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  1610  			},
  1611  		}
  1612  		for _, tt := range tests {
  1613  			params := engine.CallParams{
  1614  				Caller: account1,
  1615  				Callee: account2,
  1616  				Gas:    big.NewInt(1000000),
  1617  			}
  1618  			if output, err := vm.Execute(st, blockchain, eventSink, params, tt.bytecode); err != nil || !bytes.Equal(output, tt.expected) {
  1619  				t.Errorf("Reported error in %v.", tt.name)
  1620  				assert.NoError(t, err)
  1621  				assert.Equal(t, tt.expected, output)
  1622  			}
  1623  		}
  1624  	})
  1625  
  1626  	t.Run("JUMPDEST", func(t *testing.T) {
  1627  		st := acmstate.NewMemoryState()
  1628  		blockchain := new(engine.TestBlockchain)
  1629  		eventSink := exec.NewNoopEventSink()
  1630  
  1631  		account1 := newAccount(t, st, "1")
  1632  		account2 := newAccount(t, st, "101")
  1633  
  1634  		tests := []struct {
  1635  			name         string
  1636  			bytecode     []byte
  1637  			expected_out []byte
  1638  			expected_err *errors.Code
  1639  		}{
  1640  			{
  1641  				name: "Jump_InsidePushWithJumpDest",
  1642  				bytecode: MustSplice(PUSH1, 0x04, PUSH1, 0x03, ADD, JUMP,
  1643  					PUSH6, JUMPDEST, 0x60, 0x01, 0x60, 0x01, 0x55, return1()),
  1644  				expected_err: errors.Codes.InvalidJumpDest,
  1645  			},
  1646  			{
  1647  				name: "Jumpi_InsidePushWithJumpDest",
  1648  				bytecode: MustSplice(PUSH1, 0x01, PUSH1, 0x06, PUSH1, 0x03, ADD, JUMPI,
  1649  					PUSH6, JUMPDEST, 0x60, 0x01, 0x60, 0x01, 0x55, return1()),
  1650  				expected_err: errors.Codes.InvalidJumpDest,
  1651  			},
  1652  		}
  1653  		for _, tt := range tests {
  1654  			params := engine.CallParams{
  1655  				Caller: account1,
  1656  				Callee: account2,
  1657  				Gas:    big.NewInt(1000000),
  1658  			}
  1659  			if output, err := vm.Execute(st, blockchain, eventSink, params, tt.bytecode); errors.GetCode(err) != tt.expected_err {
  1660  				t.Errorf("FAIL: %v.", tt.name)
  1661  				assert.Equal(t, tt.expected_err, errors.GetCode(err))
  1662  			} else if tt.expected_err == errors.Codes.None && !bytes.Equal(output, tt.expected_out) {
  1663  				t.Errorf("FAIL: %v.", tt.name)
  1664  				assert.Equal(t, tt.expected_out, output)
  1665  			}
  1666  		}
  1667  	})
  1668  }
  1669  
  1670  // helpers
  1671  
  1672  func newAccount(t testing.TB, st acmstate.ReaderWriter, name string) crypto.Address {
  1673  	address := engine.AddressFromName(name)
  1674  	err := engine.CreateAccount(st, address)
  1675  	require.NoError(t, err)
  1676  	return address
  1677  }
  1678  
  1679  func makeAccountWithCode(t testing.TB, st acmstate.ReaderWriter, name string, code []byte) crypto.Address {
  1680  	address := engine.AddressFromName(name)
  1681  	err := engine.CreateAccount(st, address)
  1682  	require.NoError(t, err)
  1683  	err = engine.InitEVMCode(st, address, code)
  1684  	require.NoError(t, err)
  1685  	addToBalance(t, st, address, 9999999)
  1686  	return address
  1687  }
  1688  
  1689  func addToBalance(t testing.TB, st acmstate.ReaderWriter, address crypto.Address, amount uint64) {
  1690  	err := engine.UpdateAccount(st, address, func(account *acm.Account) error {
  1691  		return account.AddToBalance(amount)
  1692  	})
  1693  	require.NoError(t, err)
  1694  }
  1695  
  1696  func call(vm *EVM, st acmstate.ReaderWriter, origin, callee crypto.Address, code []byte, input []byte,
  1697  	gas *big.Int) ([]byte, error) {
  1698  
  1699  	evs := new(exec.Events)
  1700  	out, err := vm.Execute(st, new(engine.TestBlockchain), evs, engine.CallParams{
  1701  		Caller: origin,
  1702  		Callee: callee,
  1703  		Input:  input,
  1704  		Gas:    gas,
  1705  	}, code)
  1706  
  1707  	if err != nil {
  1708  		return nil, &errors.CallError{
  1709  			CodedError:   errors.AsException(err),
  1710  			NestedErrors: evs.NestedCallErrors(),
  1711  		}
  1712  	}
  1713  	return out, nil
  1714  }
  1715  
  1716  // These code segment helpers exercise the MSTORE MLOAD MSTORE cycle to test
  1717  // both of the memory operations. Each MSTORE is done on the memory boundary
  1718  // (at MSIZE) which Solidity uses to find guaranteed unallocated memory.
  1719  
  1720  // storeAtEnd expects the value to be stored to be on top of the stack, it then
  1721  // stores that value at the current memory boundary
  1722  func storeAtEnd() []byte {
  1723  	// Pull in MSIZE (to carry forward to MLOAD), swap in value to store, store it at MSIZE
  1724  	return MustSplice(MSIZE, SWAP1, DUP2, MSTORE)
  1725  }
  1726  
  1727  func returnAfterStore() []byte {
  1728  	return MustSplice(PUSH1, 32, DUP2, RETURN)
  1729  }
  1730  
  1731  // Store the top element of the stack (which is a 32-byte word) in memory
  1732  // and return it. Useful for a simple return value.
  1733  func return1() []byte {
  1734  	return MustSplice(PUSH1, 0, MSTORE, returnWord())
  1735  }
  1736  
  1737  func returnWord() []byte {
  1738  	// PUSH1 => return size, PUSH1 => return offset, RETURN
  1739  	return MustSplice(PUSH1, 32, PUSH1, 0, RETURN)
  1740  }
  1741  
  1742  // Subscribes to an AccCall, runs the vm, returns the output any direct exception
  1743  // and then waits for any exceptions transmitted by Data in the AccCall
  1744  // event (in the case of no direct error from call we will block waiting for
  1745  // at least 1 AccCall event)
  1746  func runVM(st acmstate.ReaderWriter, caller, callee crypto.Address, code []byte, gas uint64) *exec.TxExecution {
  1747  	gasBefore := new(big.Int).SetUint64(gas)
  1748  	txe := new(exec.TxExecution)
  1749  	vm := New(engine.Options{
  1750  		DebugOpcodes: true,
  1751  	})
  1752  	bigGas := new(big.Int).SetUint64(gas)
  1753  	params := engine.CallParams{
  1754  		Caller: caller,
  1755  		Callee: callee,
  1756  		Gas:    bigGas,
  1757  	}
  1758  	output, err := vm.Execute(st, new(engine.TestBlockchain), txe, params, code)
  1759  	txe.PushError(err)
  1760  	for _, ev := range txe.ExceptionalCalls() {
  1761  		txe.PushError(ev.Header.Exception)
  1762  	}
  1763  	txe.Return(output, gasBefore.Sub(gasBefore, bigGas).Uint64())
  1764  	return txe
  1765  }
  1766  
  1767  // this is code to call another contract (hardcoded as addr)
  1768  func callContractCode(addr crypto.Address) []byte {
  1769  	gas1, gas2 := byte(0x1), byte(0x1)
  1770  	value := byte(0x69)
  1771  	inOff, inSize := byte(0x0), byte(0x0) // no call data
  1772  	retOff, retSize := byte(0x0), byte(0x20)
  1773  	// this is the code we want to run (send funds to an account and return)
  1774  	return MustSplice(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
  1775  		inOff, PUSH1, value, PUSH20, addr, PUSH2, gas1, gas2, CALL, PUSH1, retSize,
  1776  		PUSH1, retOff, RETURN)
  1777  }
  1778  
  1779  // Produce bytecode for a PUSH<N>, b_1, ..., b_N where the N is number of bytes
  1780  // contained in the unpadded word
  1781  func pushWord(word Word256) []byte {
  1782  	leadingZeros := byte(0)
  1783  	for leadingZeros < 32 {
  1784  		if word[leadingZeros] == 0 {
  1785  			leadingZeros++
  1786  		} else {
  1787  			return MustSplice(byte(PUSH32)-leadingZeros, word[leadingZeros:])
  1788  		}
  1789  	}
  1790  	return MustSplice(PUSH1, 0)
  1791  }