github.com/ethereum/go-ethereum@v1.16.1/core/vm/instructions_test.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package vm
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"fmt"
    23  	"math/big"
    24  	"os"
    25  	"strings"
    26  	"testing"
    27  
    28  	"github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/common/math"
    30  	"github.com/ethereum/go-ethereum/core/state"
    31  	"github.com/ethereum/go-ethereum/core/types"
    32  	"github.com/ethereum/go-ethereum/crypto"
    33  	"github.com/ethereum/go-ethereum/params"
    34  	"github.com/holiman/uint256"
    35  )
    36  
    37  type TwoOperandTestcase struct {
    38  	X        string
    39  	Y        string
    40  	Expected string
    41  }
    42  
    43  type twoOperandParams struct {
    44  	x string
    45  	y string
    46  }
    47  
    48  var alphabetSoup = "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
    49  var commonParams []*twoOperandParams
    50  var twoOpMethods map[string]executionFunc
    51  
    52  func init() {
    53  	// Params is a list of common edgecases that should be used for some common tests
    54  	params := []string{
    55  		"0000000000000000000000000000000000000000000000000000000000000000", // 0
    56  		"0000000000000000000000000000000000000000000000000000000000000001", // +1
    57  		"0000000000000000000000000000000000000000000000000000000000000005", // +5
    58  		"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", // + max -1
    59  		"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // + max
    60  		"8000000000000000000000000000000000000000000000000000000000000000", // - max
    61  		"8000000000000000000000000000000000000000000000000000000000000001", // - max+1
    62  		"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", // - 5
    63  		"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // - 1
    64  	}
    65  	// Params are combined so each param is used on each 'side'
    66  	commonParams = make([]*twoOperandParams, len(params)*len(params))
    67  	for i, x := range params {
    68  		for j, y := range params {
    69  			commonParams[i*len(params)+j] = &twoOperandParams{x, y}
    70  		}
    71  	}
    72  	twoOpMethods = map[string]executionFunc{
    73  		"add":     opAdd,
    74  		"sub":     opSub,
    75  		"mul":     opMul,
    76  		"div":     opDiv,
    77  		"sdiv":    opSdiv,
    78  		"mod":     opMod,
    79  		"smod":    opSmod,
    80  		"exp":     opExp,
    81  		"signext": opSignExtend,
    82  		"lt":      opLt,
    83  		"gt":      opGt,
    84  		"slt":     opSlt,
    85  		"sgt":     opSgt,
    86  		"eq":      opEq,
    87  		"and":     opAnd,
    88  		"or":      opOr,
    89  		"xor":     opXor,
    90  		"byte":    opByte,
    91  		"shl":     opSHL,
    92  		"shr":     opSHR,
    93  		"sar":     opSAR,
    94  	}
    95  }
    96  
    97  func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) {
    98  	var (
    99  		evm   = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
   100  		stack = newstack()
   101  		pc    = uint64(0)
   102  	)
   103  
   104  	for i, test := range tests {
   105  		x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.X))
   106  		y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Y))
   107  		expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected))
   108  		stack.push(x)
   109  		stack.push(y)
   110  		opFn(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
   111  		if len(stack.data) != 1 {
   112  			t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.data))
   113  		}
   114  		actual := stack.pop()
   115  
   116  		if actual.Cmp(expected) != 0 {
   117  			t.Errorf("Testcase %v %d, %v(%x, %x): expected  %x, got %x", name, i, name, x, y, expected, actual)
   118  		}
   119  	}
   120  }
   121  
   122  func TestByteOp(t *testing.T) {
   123  	tests := []TwoOperandTestcase{
   124  		{"ABCDEF0908070605040302010000000000000000000000000000000000000000", "00", "AB"},
   125  		{"ABCDEF0908070605040302010000000000000000000000000000000000000000", "01", "CD"},
   126  		{"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", "00", "00"},
   127  		{"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", "01", "CD"},
   128  		{"0000000000000000000000000000000000000000000000000000000000102030", "1F", "30"},
   129  		{"0000000000000000000000000000000000000000000000000000000000102030", "1E", "20"},
   130  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "20", "00"},
   131  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "FFFFFFFFFFFFFFFF", "00"},
   132  	}
   133  	testTwoOperandOp(t, tests, opByte, "byte")
   134  }
   135  
   136  func TestSHL(t *testing.T) {
   137  	// Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shl-shift-left
   138  	tests := []TwoOperandTestcase{
   139  		{"0000000000000000000000000000000000000000000000000000000000000001", "01", "0000000000000000000000000000000000000000000000000000000000000002"},
   140  		{"0000000000000000000000000000000000000000000000000000000000000001", "ff", "8000000000000000000000000000000000000000000000000000000000000000"},
   141  		{"0000000000000000000000000000000000000000000000000000000000000001", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
   142  		{"0000000000000000000000000000000000000000000000000000000000000001", "0101", "0000000000000000000000000000000000000000000000000000000000000000"},
   143  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
   144  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},
   145  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "8000000000000000000000000000000000000000000000000000000000000000"},
   146  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
   147  		{"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
   148  		{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},
   149  	}
   150  	testTwoOperandOp(t, tests, opSHL, "shl")
   151  }
   152  
   153  func TestSHR(t *testing.T) {
   154  	// Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shr-logical-shift-right
   155  	tests := []TwoOperandTestcase{
   156  		{"0000000000000000000000000000000000000000000000000000000000000001", "00", "0000000000000000000000000000000000000000000000000000000000000001"},
   157  		{"0000000000000000000000000000000000000000000000000000000000000001", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
   158  		{"8000000000000000000000000000000000000000000000000000000000000000", "01", "4000000000000000000000000000000000000000000000000000000000000000"},
   159  		{"8000000000000000000000000000000000000000000000000000000000000000", "ff", "0000000000000000000000000000000000000000000000000000000000000001"},
   160  		{"8000000000000000000000000000000000000000000000000000000000000000", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
   161  		{"8000000000000000000000000000000000000000000000000000000000000000", "0101", "0000000000000000000000000000000000000000000000000000000000000000"},
   162  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
   163  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
   164  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "0000000000000000000000000000000000000000000000000000000000000001"},
   165  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
   166  		{"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
   167  	}
   168  	testTwoOperandOp(t, tests, opSHR, "shr")
   169  }
   170  
   171  func TestSAR(t *testing.T) {
   172  	// Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#sar-arithmetic-shift-right
   173  	tests := []TwoOperandTestcase{
   174  		{"0000000000000000000000000000000000000000000000000000000000000001", "00", "0000000000000000000000000000000000000000000000000000000000000001"},
   175  		{"0000000000000000000000000000000000000000000000000000000000000001", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
   176  		{"8000000000000000000000000000000000000000000000000000000000000000", "01", "c000000000000000000000000000000000000000000000000000000000000000"},
   177  		{"8000000000000000000000000000000000000000000000000000000000000000", "ff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
   178  		{"8000000000000000000000000000000000000000000000000000000000000000", "0100", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
   179  		{"8000000000000000000000000000000000000000000000000000000000000000", "0101", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
   180  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
   181  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
   182  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
   183  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
   184  		{"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
   185  		{"4000000000000000000000000000000000000000000000000000000000000000", "fe", "0000000000000000000000000000000000000000000000000000000000000001"},
   186  		{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "f8", "000000000000000000000000000000000000000000000000000000000000007f"},
   187  		{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "fe", "0000000000000000000000000000000000000000000000000000000000000001"},
   188  		{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "0000000000000000000000000000000000000000000000000000000000000000"},
   189  		{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
   190  	}
   191  
   192  	testTwoOperandOp(t, tests, opSAR, "sar")
   193  }
   194  
   195  func TestAddMod(t *testing.T) {
   196  	var (
   197  		evm   = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
   198  		stack = newstack()
   199  		pc    = uint64(0)
   200  	)
   201  	tests := []struct {
   202  		x        string
   203  		y        string
   204  		z        string
   205  		expected string
   206  	}{
   207  		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   208  			"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
   209  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   210  			"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
   211  		},
   212  	}
   213  	// x + y = 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd
   214  	// in 256 bit repr, fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd
   215  
   216  	for i, test := range tests {
   217  		x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.x))
   218  		y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.y))
   219  		z := new(uint256.Int).SetBytes(common.Hex2Bytes(test.z))
   220  		expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.expected))
   221  		stack.push(z)
   222  		stack.push(y)
   223  		stack.push(x)
   224  		opAddmod(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
   225  		actual := stack.pop()
   226  		if actual.Cmp(expected) != 0 {
   227  			t.Errorf("Testcase %d, expected  %x, got %x", i, expected, actual)
   228  		}
   229  	}
   230  }
   231  
   232  // utility function to fill the json-file with testcases
   233  // Enable this test to generate the 'testcases_xx.json' files
   234  func TestWriteExpectedValues(t *testing.T) {
   235  	t.Skip("Enable this test to create json test cases.")
   236  
   237  	// getResult is a convenience function to generate the expected values
   238  	getResult := func(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase {
   239  		var (
   240  			evm   = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
   241  			stack = newstack()
   242  			pc    = uint64(0)
   243  		)
   244  		result := make([]TwoOperandTestcase, len(args))
   245  		for i, param := range args {
   246  			x := new(uint256.Int).SetBytes(common.Hex2Bytes(param.x))
   247  			y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y))
   248  			stack.push(x)
   249  			stack.push(y)
   250  			opFn(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
   251  			actual := stack.pop()
   252  			result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)}
   253  		}
   254  		return result
   255  	}
   256  
   257  	for name, method := range twoOpMethods {
   258  		data, err := json.Marshal(getResult(commonParams, method))
   259  		if err != nil {
   260  			t.Fatal(err)
   261  		}
   262  		_ = os.WriteFile(fmt.Sprintf("testdata/testcases_%v.json", name), data, 0644)
   263  		if err != nil {
   264  			t.Fatal(err)
   265  		}
   266  	}
   267  }
   268  
   269  // TestJsonTestcases runs through all the testcases defined as json-files
   270  func TestJsonTestcases(t *testing.T) {
   271  	for name := range twoOpMethods {
   272  		data, err := os.ReadFile(fmt.Sprintf("testdata/testcases_%v.json", name))
   273  		if err != nil {
   274  			t.Fatal("Failed to read file", err)
   275  		}
   276  		var testcases []TwoOperandTestcase
   277  		json.Unmarshal(data, &testcases)
   278  		testTwoOperandOp(t, testcases, twoOpMethods[name], name)
   279  	}
   280  }
   281  
   282  func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
   283  	var (
   284  		evm   = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
   285  		stack = newstack()
   286  		scope = &ScopeContext{nil, stack, nil}
   287  	)
   288  	// convert args
   289  	intArgs := make([]*uint256.Int, len(args))
   290  	for i, arg := range args {
   291  		intArgs[i] = new(uint256.Int).SetBytes(common.Hex2Bytes(arg))
   292  	}
   293  	pc := uint64(0)
   294  	bench.ResetTimer()
   295  	for i := 0; i < bench.N; i++ {
   296  		for _, arg := range intArgs {
   297  			stack.push(arg)
   298  		}
   299  		op(&pc, evm.interpreter, scope)
   300  		stack.pop()
   301  	}
   302  	bench.StopTimer()
   303  
   304  	for i, arg := range args {
   305  		want := new(uint256.Int).SetBytes(common.Hex2Bytes(arg))
   306  		if have := intArgs[i]; !want.Eq(have) {
   307  			bench.Fatalf("input #%d mutated, have %x want %x", i, have, want)
   308  		}
   309  	}
   310  }
   311  
   312  func BenchmarkOpAdd64(b *testing.B) {
   313  	x := "ffffffff"
   314  	y := "fd37f3e2bba2c4f"
   315  
   316  	opBenchmark(b, opAdd, x, y)
   317  }
   318  
   319  func BenchmarkOpAdd128(b *testing.B) {
   320  	x := "ffffffffffffffff"
   321  	y := "f5470b43c6549b016288e9a65629687"
   322  
   323  	opBenchmark(b, opAdd, x, y)
   324  }
   325  
   326  func BenchmarkOpAdd256(b *testing.B) {
   327  	x := "0802431afcbce1fc194c9eaa417b2fb67dc75a95db0bc7ec6b1c8af11df6a1da9"
   328  	y := "a1f5aac137876480252e5dcac62c354ec0d42b76b0642b6181ed099849ea1d57"
   329  
   330  	opBenchmark(b, opAdd, x, y)
   331  }
   332  
   333  func BenchmarkOpSub64(b *testing.B) {
   334  	x := "51022b6317003a9d"
   335  	y := "a20456c62e00753a"
   336  
   337  	opBenchmark(b, opSub, x, y)
   338  }
   339  
   340  func BenchmarkOpSub128(b *testing.B) {
   341  	x := "4dde30faaacdc14d00327aac314e915d"
   342  	y := "9bbc61f5559b829a0064f558629d22ba"
   343  
   344  	opBenchmark(b, opSub, x, y)
   345  }
   346  
   347  func BenchmarkOpSub256(b *testing.B) {
   348  	x := "4bfcd8bb2ac462735b48a17580690283980aa2d679f091c64364594df113ea37"
   349  	y := "97f9b1765588c4e6b69142eb00d20507301545acf3e1238c86c8b29be227d46e"
   350  
   351  	opBenchmark(b, opSub, x, y)
   352  }
   353  
   354  func BenchmarkOpMul(b *testing.B) {
   355  	x := alphabetSoup
   356  	y := alphabetSoup
   357  
   358  	opBenchmark(b, opMul, x, y)
   359  }
   360  
   361  func BenchmarkOpDiv256(b *testing.B) {
   362  	x := "ff3f9014f20db29ae04af2c2d265de17"
   363  	y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
   364  	opBenchmark(b, opDiv, x, y)
   365  }
   366  
   367  func BenchmarkOpDiv128(b *testing.B) {
   368  	x := "fdedc7f10142ff97"
   369  	y := "fbdfda0e2ce356173d1993d5f70a2b11"
   370  	opBenchmark(b, opDiv, x, y)
   371  }
   372  
   373  func BenchmarkOpDiv64(b *testing.B) {
   374  	x := "fcb34eb3"
   375  	y := "f97180878e839129"
   376  	opBenchmark(b, opDiv, x, y)
   377  }
   378  
   379  func BenchmarkOpSdiv(b *testing.B) {
   380  	x := "ff3f9014f20db29ae04af2c2d265de17"
   381  	y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
   382  
   383  	opBenchmark(b, opSdiv, x, y)
   384  }
   385  
   386  func BenchmarkOpMod(b *testing.B) {
   387  	x := alphabetSoup
   388  	y := alphabetSoup
   389  
   390  	opBenchmark(b, opMod, x, y)
   391  }
   392  
   393  func BenchmarkOpSmod(b *testing.B) {
   394  	x := alphabetSoup
   395  	y := alphabetSoup
   396  
   397  	opBenchmark(b, opSmod, x, y)
   398  }
   399  
   400  func BenchmarkOpExp(b *testing.B) {
   401  	x := alphabetSoup
   402  	y := alphabetSoup
   403  
   404  	opBenchmark(b, opExp, x, y)
   405  }
   406  
   407  func BenchmarkOpSignExtend(b *testing.B) {
   408  	x := alphabetSoup
   409  	y := alphabetSoup
   410  
   411  	opBenchmark(b, opSignExtend, x, y)
   412  }
   413  
   414  func BenchmarkOpLt(b *testing.B) {
   415  	x := alphabetSoup
   416  	y := alphabetSoup
   417  
   418  	opBenchmark(b, opLt, x, y)
   419  }
   420  
   421  func BenchmarkOpGt(b *testing.B) {
   422  	x := alphabetSoup
   423  	y := alphabetSoup
   424  
   425  	opBenchmark(b, opGt, x, y)
   426  }
   427  
   428  func BenchmarkOpSlt(b *testing.B) {
   429  	x := alphabetSoup
   430  	y := alphabetSoup
   431  
   432  	opBenchmark(b, opSlt, x, y)
   433  }
   434  
   435  func BenchmarkOpSgt(b *testing.B) {
   436  	x := alphabetSoup
   437  	y := alphabetSoup
   438  
   439  	opBenchmark(b, opSgt, x, y)
   440  }
   441  
   442  func BenchmarkOpEq(b *testing.B) {
   443  	x := alphabetSoup
   444  	y := alphabetSoup
   445  
   446  	opBenchmark(b, opEq, x, y)
   447  }
   448  func BenchmarkOpEq2(b *testing.B) {
   449  	x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
   450  	y := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201fffffffe"
   451  	opBenchmark(b, opEq, x, y)
   452  }
   453  func BenchmarkOpAnd(b *testing.B) {
   454  	x := alphabetSoup
   455  	y := alphabetSoup
   456  
   457  	opBenchmark(b, opAnd, x, y)
   458  }
   459  
   460  func BenchmarkOpOr(b *testing.B) {
   461  	x := alphabetSoup
   462  	y := alphabetSoup
   463  
   464  	opBenchmark(b, opOr, x, y)
   465  }
   466  
   467  func BenchmarkOpXor(b *testing.B) {
   468  	x := alphabetSoup
   469  	y := alphabetSoup
   470  
   471  	opBenchmark(b, opXor, x, y)
   472  }
   473  
   474  func BenchmarkOpByte(b *testing.B) {
   475  	x := alphabetSoup
   476  	y := alphabetSoup
   477  
   478  	opBenchmark(b, opByte, x, y)
   479  }
   480  
   481  func BenchmarkOpAddmod(b *testing.B) {
   482  	x := alphabetSoup
   483  	y := alphabetSoup
   484  	z := alphabetSoup
   485  
   486  	opBenchmark(b, opAddmod, x, y, z)
   487  }
   488  
   489  func BenchmarkOpMulmod(b *testing.B) {
   490  	x := alphabetSoup
   491  	y := alphabetSoup
   492  	z := alphabetSoup
   493  
   494  	opBenchmark(b, opMulmod, x, y, z)
   495  }
   496  
   497  func BenchmarkOpSHL(b *testing.B) {
   498  	x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
   499  	y := "ff"
   500  
   501  	opBenchmark(b, opSHL, x, y)
   502  }
   503  func BenchmarkOpSHR(b *testing.B) {
   504  	x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
   505  	y := "ff"
   506  
   507  	opBenchmark(b, opSHR, x, y)
   508  }
   509  func BenchmarkOpSAR(b *testing.B) {
   510  	x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
   511  	y := "ff"
   512  
   513  	opBenchmark(b, opSAR, x, y)
   514  }
   515  func BenchmarkOpIsZero(b *testing.B) {
   516  	x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
   517  	opBenchmark(b, opIszero, x)
   518  }
   519  
   520  func TestOpMstore(t *testing.T) {
   521  	var (
   522  		evm   = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
   523  		stack = newstack()
   524  		mem   = NewMemory()
   525  	)
   526  	mem.Resize(64)
   527  	pc := uint64(0)
   528  	v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
   529  	stack.push(new(uint256.Int).SetBytes(common.Hex2Bytes(v)))
   530  	stack.push(new(uint256.Int))
   531  	opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
   532  	if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v {
   533  		t.Fatalf("Mstore fail, got %v, expected %v", got, v)
   534  	}
   535  	stack.push(new(uint256.Int).SetUint64(0x1))
   536  	stack.push(new(uint256.Int))
   537  	opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
   538  	if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
   539  		t.Fatalf("Mstore failed to overwrite previous value")
   540  	}
   541  }
   542  
   543  func BenchmarkOpMstore(bench *testing.B) {
   544  	var (
   545  		evm   = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
   546  		stack = newstack()
   547  		mem   = NewMemory()
   548  	)
   549  	mem.Resize(64)
   550  	pc := uint64(0)
   551  	memStart := new(uint256.Int)
   552  	value := new(uint256.Int).SetUint64(0x1337)
   553  
   554  	bench.ResetTimer()
   555  	for i := 0; i < bench.N; i++ {
   556  		stack.push(value)
   557  		stack.push(memStart)
   558  		opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
   559  	}
   560  }
   561  
   562  func TestOpTstore(t *testing.T) {
   563  	var (
   564  		statedb, _   = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
   565  		evm          = NewEVM(BlockContext{}, statedb, params.TestChainConfig, Config{})
   566  		stack        = newstack()
   567  		mem          = NewMemory()
   568  		caller       = common.Address{}
   569  		to           = common.Address{1}
   570  		contract     = NewContract(caller, to, new(uint256.Int), 0, nil)
   571  		scopeContext = ScopeContext{mem, stack, contract}
   572  		value        = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700")
   573  	)
   574  
   575  	// Add a stateObject for the caller and the contract being called
   576  	statedb.CreateAccount(caller)
   577  	statedb.CreateAccount(to)
   578  
   579  	pc := uint64(0)
   580  	// push the value to the stack
   581  	stack.push(new(uint256.Int).SetBytes(value))
   582  	// push the location to the stack
   583  	stack.push(new(uint256.Int))
   584  	opTstore(&pc, evm.interpreter, &scopeContext)
   585  	// there should be no elements on the stack after TSTORE
   586  	if stack.len() != 0 {
   587  		t.Fatal("stack wrong size")
   588  	}
   589  	// push the location to the stack
   590  	stack.push(new(uint256.Int))
   591  	opTload(&pc, evm.interpreter, &scopeContext)
   592  	// there should be one element on the stack after TLOAD
   593  	if stack.len() != 1 {
   594  		t.Fatal("stack wrong size")
   595  	}
   596  	val := stack.peek()
   597  	if !bytes.Equal(val.Bytes(), value) {
   598  		t.Fatal("incorrect element read from transient storage")
   599  	}
   600  }
   601  
   602  func BenchmarkOpKeccak256(bench *testing.B) {
   603  	var (
   604  		evm   = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
   605  		stack = newstack()
   606  		mem   = NewMemory()
   607  	)
   608  	mem.Resize(32)
   609  	pc := uint64(0)
   610  	start := new(uint256.Int)
   611  
   612  	bench.ResetTimer()
   613  	for i := 0; i < bench.N; i++ {
   614  		stack.push(uint256.NewInt(32))
   615  		stack.push(start)
   616  		opKeccak256(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
   617  	}
   618  }
   619  
   620  func TestCreate2Addresses(t *testing.T) {
   621  	type testcase struct {
   622  		origin   string
   623  		salt     string
   624  		code     string
   625  		expected string
   626  	}
   627  
   628  	for i, tt := range []testcase{
   629  		{
   630  			origin:   "0x0000000000000000000000000000000000000000",
   631  			salt:     "0x0000000000000000000000000000000000000000",
   632  			code:     "0x00",
   633  			expected: "0x4d1a2e2bb4f88f0250f26ffff098b0b30b26bf38",
   634  		},
   635  		{
   636  			origin:   "0xdeadbeef00000000000000000000000000000000",
   637  			salt:     "0x0000000000000000000000000000000000000000",
   638  			code:     "0x00",
   639  			expected: "0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3",
   640  		},
   641  		{
   642  			origin:   "0xdeadbeef00000000000000000000000000000000",
   643  			salt:     "0xfeed000000000000000000000000000000000000",
   644  			code:     "0x00",
   645  			expected: "0xD04116cDd17beBE565EB2422F2497E06cC1C9833",
   646  		},
   647  		{
   648  			origin:   "0x0000000000000000000000000000000000000000",
   649  			salt:     "0x0000000000000000000000000000000000000000",
   650  			code:     "0xdeadbeef",
   651  			expected: "0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e",
   652  		},
   653  		{
   654  			origin:   "0x00000000000000000000000000000000deadbeef",
   655  			salt:     "0xcafebabe",
   656  			code:     "0xdeadbeef",
   657  			expected: "0x60f3f640a8508fC6a86d45DF051962668E1e8AC7",
   658  		},
   659  		{
   660  			origin:   "0x00000000000000000000000000000000deadbeef",
   661  			salt:     "0xcafebabe",
   662  			code:     "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
   663  			expected: "0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C",
   664  		},
   665  		{
   666  			origin:   "0x0000000000000000000000000000000000000000",
   667  			salt:     "0x0000000000000000000000000000000000000000",
   668  			code:     "0x",
   669  			expected: "0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0",
   670  		},
   671  	} {
   672  		origin := common.BytesToAddress(common.FromHex(tt.origin))
   673  		salt := common.BytesToHash(common.FromHex(tt.salt))
   674  		code := common.FromHex(tt.code)
   675  		codeHash := crypto.Keccak256(code)
   676  		address := crypto.CreateAddress2(origin, salt, codeHash)
   677  		/*
   678  			stack          := newstack()
   679  			// salt, but we don't need that for this test
   680  			stack.push(big.NewInt(int64(len(code)))) //size
   681  			stack.push(big.NewInt(0)) // memstart
   682  			stack.push(big.NewInt(0)) // value
   683  			gas, _ := gasCreate2(params.GasTable{}, nil, nil, stack, nil, 0)
   684  			fmt.Printf("Example %d\n* address `0x%x`\n* salt `0x%x`\n* init_code `0x%x`\n* gas (assuming no mem expansion): `%v`\n* result: `%s`\n\n", i,origin, salt, code, gas, address.String())
   685  		*/
   686  		expected := common.BytesToAddress(common.FromHex(tt.expected))
   687  		if !bytes.Equal(expected.Bytes(), address.Bytes()) {
   688  			t.Errorf("test %d: expected %s, got %s", i, expected.String(), address.String())
   689  		}
   690  	}
   691  }
   692  
   693  func TestRandom(t *testing.T) {
   694  	type testcase struct {
   695  		name   string
   696  		random common.Hash
   697  	}
   698  
   699  	for _, tt := range []testcase{
   700  		{name: "empty hash", random: common.Hash{}},
   701  		{name: "1", random: common.Hash{0}},
   702  		{name: "emptyCodeHash", random: types.EmptyCodeHash},
   703  		{name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})},
   704  	} {
   705  		var (
   706  			evm   = NewEVM(BlockContext{Random: &tt.random}, nil, params.TestChainConfig, Config{})
   707  			stack = newstack()
   708  			pc    = uint64(0)
   709  		)
   710  		opRandom(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
   711  		if len(stack.data) != 1 {
   712  			t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
   713  		}
   714  		actual := stack.pop()
   715  		expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.random.Bytes()))
   716  		if overflow {
   717  			t.Errorf("Testcase %v: invalid overflow", tt.name)
   718  		}
   719  		if actual.Cmp(expected) != 0 {
   720  			t.Errorf("Testcase %v: expected  %x, got %x", tt.name, expected, actual)
   721  		}
   722  	}
   723  }
   724  
   725  func TestBlobHash(t *testing.T) {
   726  	type testcase struct {
   727  		name   string
   728  		idx    uint64
   729  		expect common.Hash
   730  		hashes []common.Hash
   731  	}
   732  	var (
   733  		zero  = common.Hash{0}
   734  		one   = common.Hash{1}
   735  		two   = common.Hash{2}
   736  		three = common.Hash{3}
   737  	)
   738  	for _, tt := range []testcase{
   739  		{name: "[{1}]", idx: 0, expect: one, hashes: []common.Hash{one}},
   740  		{name: "[1,{2},3]", idx: 2, expect: three, hashes: []common.Hash{one, two, three}},
   741  		{name: "out-of-bounds (empty)", idx: 10, expect: zero, hashes: []common.Hash{}},
   742  		{name: "out-of-bounds", idx: 25, expect: zero, hashes: []common.Hash{one, two, three}},
   743  		{name: "out-of-bounds (nil)", idx: 25, expect: zero, hashes: nil},
   744  	} {
   745  		var (
   746  			evm   = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
   747  			stack = newstack()
   748  			pc    = uint64(0)
   749  		)
   750  		evm.SetTxContext(TxContext{BlobHashes: tt.hashes})
   751  		stack.push(uint256.NewInt(tt.idx))
   752  		opBlobHash(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
   753  		if len(stack.data) != 1 {
   754  			t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
   755  		}
   756  		actual := stack.pop()
   757  		expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.expect.Bytes()))
   758  		if overflow {
   759  			t.Errorf("Testcase %v: invalid overflow", tt.name)
   760  		}
   761  		if actual.Cmp(expected) != 0 {
   762  			t.Errorf("Testcase %v: expected  %x, got %x", tt.name, expected, actual)
   763  		}
   764  	}
   765  }
   766  
   767  func TestOpMCopy(t *testing.T) {
   768  	// Test cases from https://eips.ethereum.org/EIPS/eip-5656#test-cases
   769  	for i, tc := range []struct {
   770  		dst, src, len string
   771  		pre           string
   772  		want          string
   773  		wantGas       uint64
   774  	}{
   775  		{ // MCOPY 0 32 32 - copy 32 bytes from offset 32 to offset 0.
   776  			dst: "0x0", src: "0x20", len: "0x20",
   777  			pre:     "0000000000000000000000000000000000000000000000000000000000000000 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
   778  			want:    "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
   779  			wantGas: 6,
   780  		},
   781  
   782  		{ // MCOPY 0 0 32 - copy 32 bytes from offset 0 to offset 0.
   783  			dst: "0x0", src: "0x0", len: "0x20",
   784  			pre:     "0101010101010101010101010101010101010101010101010101010101010101",
   785  			want:    "0101010101010101010101010101010101010101010101010101010101010101",
   786  			wantGas: 6,
   787  		},
   788  		{ // MCOPY 0 1 8 - copy 8 bytes from offset 1 to offset 0 (overlapping).
   789  			dst: "0x0", src: "0x1", len: "0x8",
   790  			pre:     "000102030405060708 000000000000000000000000000000000000000000000000",
   791  			want:    "010203040506070808 000000000000000000000000000000000000000000000000",
   792  			wantGas: 6,
   793  		},
   794  		{ // MCOPY 1 0 8 - copy 8 bytes from offset 0 to offset 1 (overlapping).
   795  			dst: "0x1", src: "0x0", len: "0x8",
   796  			pre:     "000102030405060708 000000000000000000000000000000000000000000000000",
   797  			want:    "000001020304050607 000000000000000000000000000000000000000000000000",
   798  			wantGas: 6,
   799  		},
   800  		// Tests below are not in the EIP, but maybe should be added
   801  		{ // MCOPY 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF 0 - copy zero bytes from out-of-bounds index(overlapping).
   802  			dst: "0xFFFFFFFFFFFF", src: "0xFFFFFFFFFFFF", len: "0x0",
   803  			pre:     "11",
   804  			want:    "11",
   805  			wantGas: 3,
   806  		},
   807  		{ // MCOPY 0xFFFFFFFFFFFF 0 0 - copy zero bytes from start of mem to out-of-bounds.
   808  			dst: "0xFFFFFFFFFFFF", src: "0x0", len: "0x0",
   809  			pre:     "11",
   810  			want:    "11",
   811  			wantGas: 3,
   812  		},
   813  		{ // MCOPY 0 0xFFFFFFFFFFFF 0 - copy zero bytes from out-of-bounds to start of mem
   814  			dst: "0x0", src: "0xFFFFFFFFFFFF", len: "0x0",
   815  			pre:     "11",
   816  			want:    "11",
   817  			wantGas: 3,
   818  		},
   819  		{ // MCOPY - copy 1 from space outside of uint64  space
   820  			dst: "0x0", src: "0x10000000000000000", len: "0x1",
   821  			pre: "0",
   822  		},
   823  		{ // MCOPY - copy 1 from 0 to space outside of uint64
   824  			dst: "0x10000000000000000", src: "0x0", len: "0x1",
   825  			pre: "0",
   826  		},
   827  		{ // MCOPY - copy nothing from 0 to space outside of uint64
   828  			dst: "0x10000000000000000", src: "0x0", len: "0x0",
   829  			pre:     "",
   830  			want:    "",
   831  			wantGas: 3,
   832  		},
   833  		{ // MCOPY - copy 1 from 0x20 to 0x10, with no prior allocated mem
   834  			dst: "0x10", src: "0x20", len: "0x1",
   835  			pre: "",
   836  			// 64 bytes
   837  			want:    "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
   838  			wantGas: 12,
   839  		},
   840  		{ // MCOPY - copy 1 from 0x19 to 0x10, with no prior allocated mem
   841  			dst: "0x10", src: "0x19", len: "0x1",
   842  			pre: "",
   843  			// 32 bytes
   844  			want:    "0x0000000000000000000000000000000000000000000000000000000000000000",
   845  			wantGas: 9,
   846  		},
   847  	} {
   848  		var (
   849  			evm   = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
   850  			stack = newstack()
   851  			pc    = uint64(0)
   852  		)
   853  		data := common.FromHex(strings.ReplaceAll(tc.pre, " ", ""))
   854  		// Set pre
   855  		mem := NewMemory()
   856  		mem.Resize(uint64(len(data)))
   857  		mem.Set(0, uint64(len(data)), data)
   858  		// Push stack args
   859  		len, _ := uint256.FromHex(tc.len)
   860  		src, _ := uint256.FromHex(tc.src)
   861  		dst, _ := uint256.FromHex(tc.dst)
   862  
   863  		stack.push(len)
   864  		stack.push(src)
   865  		stack.push(dst)
   866  		wantErr := (tc.wantGas == 0)
   867  		// Calc mem expansion
   868  		var memorySize uint64
   869  		if memSize, overflow := memoryMcopy(stack); overflow {
   870  			if wantErr {
   871  				continue
   872  			}
   873  			t.Errorf("overflow")
   874  		} else {
   875  			var overflow bool
   876  			if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow {
   877  				t.Error(ErrGasUintOverflow)
   878  			}
   879  		}
   880  		// and the dynamic cost
   881  		var haveGas uint64
   882  		if dynamicCost, err := gasMcopy(evm, nil, stack, mem, memorySize); err != nil {
   883  			t.Error(err)
   884  		} else {
   885  			haveGas = GasFastestStep + dynamicCost
   886  		}
   887  		// Expand mem
   888  		if memorySize > 0 {
   889  			mem.Resize(memorySize)
   890  		}
   891  		// Do the copy
   892  		opMcopy(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
   893  		want := common.FromHex(strings.ReplaceAll(tc.want, " ", ""))
   894  		if have := mem.store; !bytes.Equal(want, have) {
   895  			t.Errorf("case %d: \nwant: %#x\nhave: %#x\n", i, want, have)
   896  		}
   897  		wantGas := tc.wantGas
   898  		if haveGas != wantGas {
   899  			t.Errorf("case %d: gas wrong, want %d have %d\n", i, wantGas, haveGas)
   900  		}
   901  	}
   902  }
   903  
   904  // TestPush sanity-checks how code with immediates are handled when the code size is
   905  // smaller than the size of the immediate.
   906  func TestPush(t *testing.T) {
   907  	code := common.FromHex("0011223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121")
   908  
   909  	push32 := makePush(32, 32)
   910  
   911  	scope := &ScopeContext{
   912  		Memory: nil,
   913  		Stack:  newstack(),
   914  		Contract: &Contract{
   915  			Code: code,
   916  		},
   917  	}
   918  	for i, want := range []string{
   919  		"0x11223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1",
   920  		"0x223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1",
   921  		"0x3344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1",
   922  		"0x44556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1",
   923  		"0x556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1",
   924  		"0x6677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a1",
   925  		"0x77889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a191",
   926  		"0x889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181",
   927  		"0x9900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a1918171",
   928  		"0xaabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a191817161",
   929  		"0xaabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151",
   930  		"0xbbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a1918171615141",
   931  		"0xccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a191817161514131",
   932  		"0xddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121",
   933  		"0xeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a1918171615141312100",
   934  		"0xff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a191817161514131210000",
   935  		"0x102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121000000",
   936  		"0x2030405060708090a0b0c0d0e0ff1e1d1c1b1a1918171615141312100000000",
   937  		"0x30405060708090a0b0c0d0e0ff1e1d1c1b1a191817161514131210000000000",
   938  		"0x405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121000000000000",
   939  		"0x5060708090a0b0c0d0e0ff1e1d1c1b1a1918171615141312100000000000000",
   940  		"0x60708090a0b0c0d0e0ff1e1d1c1b1a191817161514131210000000000000000",
   941  		"0x708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121000000000000000000",
   942  		"0x8090a0b0c0d0e0ff1e1d1c1b1a1918171615141312100000000000000000000",
   943  		"0x90a0b0c0d0e0ff1e1d1c1b1a191817161514131210000000000000000000000",
   944  		"0xa0b0c0d0e0ff1e1d1c1b1a19181716151413121000000000000000000000000",
   945  		"0xb0c0d0e0ff1e1d1c1b1a1918171615141312100000000000000000000000000",
   946  		"0xc0d0e0ff1e1d1c1b1a191817161514131210000000000000000000000000000",
   947  		"0xd0e0ff1e1d1c1b1a19181716151413121000000000000000000000000000000",
   948  		"0xe0ff1e1d1c1b1a1918171615141312100000000000000000000000000000000",
   949  		"0xff1e1d1c1b1a191817161514131210000000000000000000000000000000000",
   950  		"0xf1e1d1c1b1a19181716151413121000000000000000000000000000000000000",
   951  		"0xe1d1c1b1a1918171615141312100000000000000000000000000000000000000",
   952  		"0xd1c1b1a191817161514131210000000000000000000000000000000000000000",
   953  		"0xc1b1a19181716151413121000000000000000000000000000000000000000000",
   954  		"0xb1a1918171615141312100000000000000000000000000000000000000000000",
   955  		"0xa191817161514131210000000000000000000000000000000000000000000000",
   956  		"0x9181716151413121000000000000000000000000000000000000000000000000",
   957  		"0x8171615141312100000000000000000000000000000000000000000000000000",
   958  		"0x7161514131210000000000000000000000000000000000000000000000000000",
   959  		"0x6151413121000000000000000000000000000000000000000000000000000000",
   960  		"0x5141312100000000000000000000000000000000000000000000000000000000",
   961  		"0x4131210000000000000000000000000000000000000000000000000000000000",
   962  		"0x3121000000000000000000000000000000000000000000000000000000000000",
   963  		"0x2100000000000000000000000000000000000000000000000000000000000000",
   964  		"0x0",
   965  	} {
   966  		pc := new(uint64)
   967  		*pc = uint64(i)
   968  		push32(pc, nil, scope)
   969  		res := scope.Stack.pop()
   970  		if have := res.Hex(); have != want {
   971  			t.Fatalf("case %d, have %v want %v", i, have, want)
   972  		}
   973  	}
   974  }