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

     1  package evm
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"math/big"
     9  	"strings"
    10  
    11  	"github.com/hyperledger/burrow/acm"
    12  	. "github.com/hyperledger/burrow/binary"
    13  	"github.com/hyperledger/burrow/crypto"
    14  	"github.com/hyperledger/burrow/encoding"
    15  	"github.com/hyperledger/burrow/execution/engine"
    16  	"github.com/hyperledger/burrow/execution/errors"
    17  	"github.com/hyperledger/burrow/execution/evm/abi"
    18  	. "github.com/hyperledger/burrow/execution/evm/asm"
    19  	"github.com/hyperledger/burrow/execution/exec"
    20  	"github.com/hyperledger/burrow/permission"
    21  	"github.com/hyperledger/burrow/txs"
    22  )
    23  
    24  type Contract struct {
    25  	*EVM
    26  	*Code
    27  }
    28  
    29  func (c *Contract) Call(state engine.State, params engine.CallParams) ([]byte, error) {
    30  	return engine.Call(state, params, c.execute)
    31  }
    32  
    33  // Executes the EVM code passed in the appropriate context
    34  func (c *Contract) execute(st engine.State, params engine.CallParams) ([]byte, error) {
    35  	c.debugf("(%d) (%s) %s (code=%d) gas: %v (d) %X\n",
    36  		st.CallFrame.CallStackDepth(), params.Caller, params.Callee, c.Length(), *params.Gas, params.Input)
    37  
    38  	if c.Length() == 0 {
    39  		return nil, nil
    40  	}
    41  
    42  	if c.options.DumpTokens {
    43  		dumpTokens(c.options.Nonce, params.Caller, params.Callee, c.GetBytecode())
    44  	}
    45  
    46  	// Program counter - the index into code that tracks current instruction
    47  	var pc uint64
    48  	// Return data from a call
    49  	var returnData []byte
    50  
    51  	// Maybe serves 3 purposes: 1. provides 'capture first error semantics', 2. reduces clutter of error handling
    52  	// particular for 1, 3. acts a shared error sink for stack, memory, and the main execute loop
    53  	maybe := new(errors.Maybe)
    54  
    55  	// Provide stack and memory storage - passing in the callState as an error provider
    56  	stack := NewStack(maybe, c.options.DataStackInitialCapacity, c.options.DataStackMaxDepth, params.Gas)
    57  	memory := c.options.MemoryProvider(maybe)
    58  
    59  	for {
    60  		// Check for any error in this frame.
    61  		if maybe.Error() != nil {
    62  			return nil, maybe.Error()
    63  		}
    64  
    65  		var op = c.GetSymbol(pc)
    66  		c.debugf("(pc) %-3d (op) %-14s (st) %-4d (gas) %d", pc, op.String(), stack.Len(), params.Gas)
    67  		// Use BaseOp gas.
    68  		maybe.PushError(engine.UseGasNegative(params.Gas, engine.GasBaseOp))
    69  
    70  		switch op {
    71  
    72  		case ADD: // 0x01
    73  			x, y := stack.PopBigInt(), stack.PopBigInt()
    74  			sum := new(big.Int).Add(x, y)
    75  			res := stack.PushBigInt(sum)
    76  			c.debugf(" %v + %v = %v (%v)\n", x, y, sum, res)
    77  
    78  		case MUL: // 0x02
    79  			x, y := stack.PopBigInt(), stack.PopBigInt()
    80  			prod := new(big.Int).Mul(x, y)
    81  			res := stack.PushBigInt(prod)
    82  			c.debugf(" %v * %v = %v (%v)\n", x, y, prod, res)
    83  
    84  		case SUB: // 0x03
    85  			x, y := stack.PopBigInt(), stack.PopBigInt()
    86  			diff := new(big.Int).Sub(x, y)
    87  			res := stack.PushBigInt(diff)
    88  			c.debugf(" %v - %v = %v (%v)\n", x, y, diff, res)
    89  
    90  		case DIV: // 0x04
    91  			x, y := stack.PopBigInt(), stack.PopBigInt()
    92  			if y.Sign() == 0 {
    93  				stack.Push(Zero256)
    94  				c.debugf(" %v / %v = %v\n", x, y, 0)
    95  			} else {
    96  				div := new(big.Int).Div(x, y)
    97  				res := stack.PushBigInt(div)
    98  				c.debugf(" %v / %v = %v (%v)\n", x, y, div, res)
    99  			}
   100  
   101  		case SDIV: // 0x05
   102  			x, y := stack.PopBigIntSigned(), stack.PopBigIntSigned()
   103  			if y.Sign() == 0 {
   104  				stack.Push(Zero256)
   105  				c.debugf(" %v / %v = %v\n", x, y, 0)
   106  			} else {
   107  				div := new(big.Int).Quo(x, y)
   108  				res := stack.PushBigInt(div)
   109  				c.debugf(" %v / %v = %v (%v)\n", x, y, div, res)
   110  			}
   111  
   112  		case MOD: // 0x06
   113  			x, y := stack.PopBigInt(), stack.PopBigInt()
   114  			if y.Sign() == 0 {
   115  				stack.Push(Zero256)
   116  				c.debugf(" %v %% %v = %v\n", x, y, 0)
   117  			} else {
   118  				mod := new(big.Int).Mod(x, y)
   119  				res := stack.PushBigInt(mod)
   120  				c.debugf(" %v %% %v = %v (%v)\n", x, y, mod, res)
   121  			}
   122  
   123  		case SMOD: // 0x07
   124  			x, y := stack.PopBigIntSigned(), stack.PopBigIntSigned()
   125  			if y.Sign() == 0 {
   126  				stack.Push(Zero256)
   127  				c.debugf(" %v %% %v = %v\n", x, y, 0)
   128  			} else {
   129  				mod := new(big.Int).Rem(x, y)
   130  				res := stack.PushBigInt(mod)
   131  				c.debugf(" %v %% %v = %v (%v)\n", x, y, mod, res)
   132  			}
   133  
   134  		case ADDMOD: // 0x08
   135  			x, y, z := stack.PopBigInt(), stack.PopBigInt(), stack.PopBigInt()
   136  			if z.Sign() == 0 {
   137  				stack.Push(Zero256)
   138  				c.debugf(" %v %% %v = %v\n", x, y, 0)
   139  			} else {
   140  				add := new(big.Int).Add(x, y)
   141  				mod := add.Mod(add, z)
   142  				res := stack.PushBigInt(mod)
   143  				c.debugf(" %v + %v %% %v = %v (%v)\n", x, y, z, mod, res)
   144  			}
   145  
   146  		case MULMOD: // 0x09
   147  			x, y, z := stack.PopBigInt(), stack.PopBigInt(), stack.PopBigInt()
   148  			if z.Sign() == 0 {
   149  				stack.Push(Zero256)
   150  				c.debugf(" %v %% %v = %v\n", x, y, 0)
   151  			} else {
   152  				mul := new(big.Int).Mul(x, y)
   153  				mod := mul.Mod(mul, z)
   154  				res := stack.PushBigInt(mod)
   155  				c.debugf(" %v * %v %% %v = %v (%v)\n", x, y, z, mod, res)
   156  			}
   157  
   158  		case EXP: // 0x0A
   159  			x, y := stack.PopBigInt(), stack.PopBigInt()
   160  			pow := new(big.Int).Exp(x, y, nil)
   161  			res := stack.PushBigInt(pow)
   162  			c.debugf(" %v ** %v = %v (%v)\n", x, y, pow, res)
   163  
   164  		case SIGNEXTEND: // 0x0B
   165  			back := stack.PopBigInt().Uint64()
   166  			if back < Word256Bytes-1 {
   167  				bits := uint((back + 1) * 8)
   168  				stack.PushBigInt(SignExtend(stack.PopBigInt(), bits))
   169  			}
   170  			// Continue leaving the sign extension argument on the stack. This makes sign-extending a no-op if embedded
   171  			// integer is already one word wide
   172  
   173  		case LT: // 0x10
   174  			x, y := stack.PopBigInt(), stack.PopBigInt()
   175  			if x.Cmp(y) < 0 {
   176  				stack.Push(One256)
   177  				c.debugf(" %v < %v = %v\n", x, y, 1)
   178  			} else {
   179  				stack.Push(Zero256)
   180  				c.debugf(" %v < %v = %v\n", x, y, 0)
   181  			}
   182  
   183  		case GT: // 0x11
   184  			x, y := stack.PopBigInt(), stack.PopBigInt()
   185  			if x.Cmp(y) > 0 {
   186  				stack.Push(One256)
   187  				c.debugf(" %v > %v = %v\n", x, y, 1)
   188  			} else {
   189  				stack.Push(Zero256)
   190  				c.debugf(" %v > %v = %v\n", x, y, 0)
   191  			}
   192  
   193  		case SLT: // 0x12
   194  			x, y := stack.PopBigIntSigned(), stack.PopBigIntSigned()
   195  			if x.Cmp(y) < 0 {
   196  				stack.Push(One256)
   197  				c.debugf(" %v < %v = %v\n", x, y, 1)
   198  			} else {
   199  				stack.Push(Zero256)
   200  				c.debugf(" %v < %v = %v\n", x, y, 0)
   201  			}
   202  
   203  		case SGT: // 0x13
   204  			x, y := stack.PopBigIntSigned(), stack.PopBigIntSigned()
   205  			if x.Cmp(y) > 0 {
   206  				stack.Push(One256)
   207  				c.debugf(" %v > %v = %v\n", x, y, 1)
   208  			} else {
   209  				stack.Push(Zero256)
   210  				c.debugf(" %v > %v = %v\n", x, y, 0)
   211  			}
   212  
   213  		case EQ: // 0x14
   214  			x, y := stack.Pop(), stack.Pop()
   215  			if bytes.Equal(x[:], y[:]) {
   216  				stack.Push(One256)
   217  				c.debugf(" %v == %v = %v\n", x, y, 1)
   218  			} else {
   219  				stack.Push(Zero256)
   220  				c.debugf(" %v == %v = %v\n", x, y, 0)
   221  			}
   222  
   223  		case ISZERO: // 0x15
   224  			x := stack.Pop()
   225  			if x.IsZero() {
   226  				stack.Push(One256)
   227  				c.debugf(" %v == 0 = %v\n", x, 1)
   228  			} else {
   229  				stack.Push(Zero256)
   230  				c.debugf(" %v == 0 = %v\n", x, 0)
   231  			}
   232  
   233  		case AND: // 0x16
   234  			x, y := stack.Pop(), stack.Pop()
   235  			z := [32]byte{}
   236  			for i := 0; i < 32; i++ {
   237  				z[i] = x[i] & y[i]
   238  			}
   239  			stack.Push(z)
   240  			c.debugf(" %v & %v = %v\n", x, y, z)
   241  
   242  		case OR: // 0x17
   243  			x, y := stack.Pop(), stack.Pop()
   244  			z := [32]byte{}
   245  			for i := 0; i < 32; i++ {
   246  				z[i] = x[i] | y[i]
   247  			}
   248  			stack.Push(z)
   249  			c.debugf(" %v | %v = %v\n", x, y, z)
   250  
   251  		case XOR: // 0x18
   252  			x, y := stack.Pop(), stack.Pop()
   253  			z := [32]byte{}
   254  			for i := 0; i < 32; i++ {
   255  				z[i] = x[i] ^ y[i]
   256  			}
   257  			stack.Push(z)
   258  			c.debugf(" %v ^ %v = %v\n", x, y, z)
   259  
   260  		case NOT: // 0x19
   261  			x := stack.Pop()
   262  			z := [32]byte{}
   263  			for i := 0; i < 32; i++ {
   264  				z[i] = ^x[i]
   265  			}
   266  			stack.Push(z)
   267  			c.debugf(" !%v = %v\n", x, z)
   268  
   269  		case BYTE: // 0x1A
   270  			idx := stack.Pop64()
   271  			val := stack.Pop()
   272  			res := byte(0)
   273  			if idx < 32 {
   274  				res = val[idx]
   275  			}
   276  			stack.Push64(uint64(res))
   277  			c.debugf(" => 0x%X\n", res)
   278  
   279  		case SHL: //0x1B
   280  			shift, x := stack.PopBigInt(), stack.PopBigInt()
   281  
   282  			if shift.Cmp(Big256) >= 0 {
   283  				reset := big.NewInt(0)
   284  				stack.PushBigInt(reset)
   285  				c.debugf(" %v << %v = %v\n", x, shift, reset)
   286  			} else {
   287  				shiftedValue := x.Lsh(x, uint(shift.Uint64()))
   288  				stack.PushBigInt(shiftedValue)
   289  				c.debugf(" %v << %v = %v\n", x, shift, shiftedValue)
   290  			}
   291  
   292  		case SHR: //0x1C
   293  			shift, x := stack.PopBigInt(), stack.PopBigInt()
   294  
   295  			if shift.Cmp(Big256) >= 0 {
   296  				reset := big.NewInt(0)
   297  				stack.PushBigInt(reset)
   298  				c.debugf(" %v << %v = %v\n", x, shift, reset)
   299  			} else {
   300  				shiftedValue := x.Rsh(x, uint(shift.Uint64()))
   301  				stack.PushBigInt(shiftedValue)
   302  				c.debugf(" %v << %v = %v\n", x, shift, shiftedValue)
   303  			}
   304  
   305  		case SAR: //0x1D
   306  			shift, x := stack.PopBigInt(), stack.PopBigIntSigned()
   307  
   308  			if shift.Cmp(Big256) >= 0 {
   309  				reset := big.NewInt(0)
   310  				if x.Sign() < 0 {
   311  					reset.SetInt64(-1)
   312  				}
   313  				stack.PushBigInt(reset)
   314  				c.debugf(" %v << %v = %v\n", x, shift, reset)
   315  			} else {
   316  				shiftedValue := x.Rsh(x, uint(shift.Uint64()))
   317  				stack.PushBigInt(shiftedValue)
   318  				c.debugf(" %v << %v = %v\n", x, shift, shiftedValue)
   319  			}
   320  
   321  		case SHA3: // 0x20
   322  			maybe.PushError(engine.UseGasNegative(params.Gas, engine.GasSha3))
   323  			offset, size := stack.PopBigInt(), stack.PopBigInt()
   324  			data := memory.Read(offset, size)
   325  			data = crypto.Keccak256(data)
   326  			stack.PushBytes(data)
   327  			c.debugf(" => (%v) %X\n", size, data)
   328  
   329  		case ADDRESS: // 0x30
   330  			stack.Push(params.Callee.Word256())
   331  			c.debugf(" => %v\n", params.Callee)
   332  
   333  		case BALANCE: // 0x31
   334  			address := stack.PopAddress()
   335  			maybe.PushError(engine.UseGasNegative(params.Gas, engine.GasGetAccount))
   336  			balance := engine.MustGetAccount(st.CallFrame, maybe, address).Balance
   337  			stack.Push64(balance)
   338  			c.debugf(" => %v (%v)\n", balance, address)
   339  
   340  		case ORIGIN: // 0x32
   341  			stack.Push(params.Origin.Word256())
   342  			c.debugf(" => %v\n", params.Origin)
   343  
   344  		case CALLER: // 0x33
   345  			stack.Push(params.Caller.Word256())
   346  			c.debugf(" => %v\n", params.Caller)
   347  
   348  		case CALLVALUE: // 0x34
   349  			stack.PushBigInt(&params.Value)
   350  			c.debugf(" => %v\n", params.Value)
   351  
   352  		case CALLDATALOAD: // 0x35
   353  			offset := stack.Pop64()
   354  			data := maybe.Bytes(subslice(params.Input, offset, 32))
   355  			res := LeftPadWord256(data)
   356  			stack.Push(res)
   357  			c.debugf(" => 0x%v\n", res)
   358  
   359  		case CALLDATASIZE: // 0x36
   360  			stack.Push64(uint64(len(params.Input)))
   361  			c.debugf(" => %d\n", len(params.Input))
   362  
   363  		case CALLDATACOPY: // 0x37
   364  			memOff := stack.PopBigInt()
   365  			inputOff := stack.Pop64()
   366  			length := stack.Pop64()
   367  			data := maybe.Bytes(subslice(params.Input, inputOff, length))
   368  			memory.Write(memOff, data)
   369  			c.debugf(" => [%v, %v, %v] %X\n", memOff, inputOff, length, data)
   370  
   371  		case CODESIZE: // 0x38
   372  			l := uint64(c.Length())
   373  			stack.Push64(l)
   374  			c.debugf(" => %d\n", l)
   375  
   376  		case CODECOPY: // 0x39
   377  			memOff := stack.PopBigInt()
   378  			codeOff := stack.Pop64()
   379  			length := stack.Pop64()
   380  			data := maybe.Bytes(subslice(c.GetBytecode(), codeOff, length))
   381  			memory.Write(memOff, data)
   382  			c.debugf(" => [%v, %v, %v] %X\n", memOff, codeOff, length, data)
   383  
   384  		case GASPRICE_DEPRECATED: // 0x3A
   385  			stack.Push(Zero256)
   386  			c.debugf(" => %v (GASPRICE IS DEPRECATED)\n", Zero256)
   387  
   388  		case EXTCODESIZE: // 0x3B
   389  			address := stack.PopAddress()
   390  			maybe.PushError(engine.UseGasNegative(params.Gas, engine.GasGetAccount))
   391  			acc := engine.MustGetAccount(st.CallFrame, maybe, address)
   392  			if acc == nil {
   393  				stack.Push(Zero256)
   394  				c.debugf(" => 0\n")
   395  			} else {
   396  				length := uint64(len(acc.Code()))
   397  				stack.Push64(length)
   398  				c.debugf(" => %d\n", length)
   399  			}
   400  		case EXTCODECOPY: // 0x3C
   401  			address := stack.PopAddress()
   402  			maybe.PushError(engine.UseGasNegative(params.Gas, engine.GasGetAccount))
   403  			acc := engine.MustGetAccount(st.CallFrame, maybe, address)
   404  			if acc == nil {
   405  				maybe.PushError(errors.Codes.UnknownAddress)
   406  			} else {
   407  				code := acc.EVMCode
   408  				memOff := stack.PopBigInt()
   409  				codeOff := stack.Pop64()
   410  				length := stack.Pop64()
   411  				data := maybe.Bytes(subslice(code, codeOff, length))
   412  				memory.Write(memOff, data)
   413  				c.debugf(" => [%v, %v, %v] %X\n", memOff, codeOff, length, data)
   414  			}
   415  
   416  		case RETURNDATASIZE: // 0x3D
   417  			stack.Push64(uint64(len(returnData)))
   418  			c.debugf(" => %d\n", len(returnData))
   419  
   420  		case RETURNDATACOPY: // 0x3E
   421  			memOff, outputOff, length := stack.PopBigInt(), stack.PopBigInt(), stack.PopBigInt()
   422  			end := new(big.Int).Add(outputOff, length)
   423  
   424  			if end.BitLen() > 64 || uint64(len(returnData)) < end.Uint64() {
   425  				maybe.PushError(errors.Codes.ReturnDataOutOfBounds)
   426  				continue
   427  			}
   428  
   429  			memory.Write(memOff, returnData)
   430  			c.debugf(" => [%v, %v, %v] %X\n", memOff, outputOff, length, returnData)
   431  
   432  		case EXTCODEHASH: // 0x3F
   433  			address := stack.PopAddress()
   434  
   435  			acc := engine.GetAccount(st.CallFrame, maybe, address)
   436  			if acc == nil {
   437  				// In case the account does not exist 0 is pushed to the stack.
   438  				stack.Push64(0)
   439  			} else {
   440  				// keccak256 hash of a contract's code
   441  				var extcodehash Word256
   442  				if len(acc.CodeHash) > 0 {
   443  					copy(extcodehash[:], acc.CodeHash)
   444  				} else {
   445  					copy(extcodehash[:], crypto.Keccak256(acc.Code()))
   446  				}
   447  				stack.Push(extcodehash)
   448  			}
   449  
   450  		case BLOCKHASH: // 0x40
   451  			blockNumber := stack.Pop64()
   452  
   453  			lastBlockHeight := st.Blockchain.LastBlockHeight()
   454  			if blockNumber >= lastBlockHeight {
   455  				c.debugf(" => attempted to get block hash of a non-existent block: %v", blockNumber)
   456  				maybe.PushError(errors.Codes.InvalidBlockNumber)
   457  			} else if lastBlockHeight-blockNumber > MaximumAllowedBlockLookBack {
   458  				c.debugf(" => attempted to get block hash of a block %d outside of the allowed range "+
   459  					"(must be within %d blocks)", blockNumber, MaximumAllowedBlockLookBack)
   460  				maybe.PushError(errors.Codes.BlockNumberOutOfRange)
   461  			} else {
   462  				hash := maybe.Bytes(st.Blockchain.BlockHash(blockNumber))
   463  				blockHash := LeftPadWord256(hash)
   464  				stack.Push(blockHash)
   465  				c.debugf(" => 0x%v\n", blockHash)
   466  			}
   467  
   468  		case COINBASE: // 0x41
   469  			stack.Push(Zero256)
   470  			c.debugf(" => 0x%v (NOT SUPPORTED)\n", stack.Peek())
   471  
   472  		case TIMESTAMP: // 0x42
   473  			blockTime := st.Blockchain.LastBlockTime().Unix()
   474  			stack.Push64(uint64(blockTime))
   475  			c.debugf(" => %d\n", blockTime)
   476  
   477  		case BLOCKHEIGHT: // 0x43
   478  			number := st.Blockchain.LastBlockHeight()
   479  			stack.Push64(number)
   480  			c.debugf(" => %d\n", number)
   481  
   482  		case DIFFICULTY: // 0x44
   483  			// ~ hashes per solution - by convention we'll use unity since there are no misses if you are proposer
   484  			stack.Push(One256)
   485  			c.debugf(" => %v\n", One256)
   486  
   487  		case GASLIMIT: // 0x45
   488  			stack.PushBigInt(params.Gas)
   489  			c.debugf(" => %v\n", *params.Gas)
   490  
   491  		case CHAINID: // 0x46
   492  			id := encoding.GetEthChainID(st.Blockchain.ChainID())
   493  			stack.PushBigInt(id)
   494  			c.debugf(" => %X\n", id)
   495  
   496  		case POP: // 0x50
   497  			popped := stack.Pop()
   498  			c.debugf(" => 0x%v\n", popped)
   499  
   500  		case MLOAD: // 0x51
   501  			offset := stack.PopBigInt()
   502  			data := memory.Read(offset, BigWord256Bytes)
   503  			stack.Push(LeftPadWord256(data))
   504  			c.debugf(" => 0x%X @ 0x%v\n", data, offset)
   505  
   506  		case MSTORE: // 0x52
   507  			offset, data := stack.PopBigInt(), stack.Pop()
   508  			memory.Write(offset, data.Bytes())
   509  			c.debugf(" => 0x%v @ 0x%v\n", data, offset)
   510  
   511  		case MSTORE8: // 0x53
   512  			offset := stack.PopBigInt()
   513  			val64 := stack.PopBigInt().Uint64()
   514  			val := byte(val64 & 0xFF)
   515  			memory.Write(offset, []byte{val})
   516  			c.debugf(" => [%v] 0x%X\n", offset, val)
   517  
   518  		case SLOAD: // 0x54
   519  			loc := stack.Pop()
   520  			data := LeftPadWord256(maybe.Bytes(st.CallFrame.GetStorage(params.Callee, loc)))
   521  			stack.Push(data)
   522  			c.debugf("%v {0x%v = 0x%v}\n", params.Callee, loc, data)
   523  
   524  		case SSTORE: // 0x55
   525  			loc, data := stack.Pop(), stack.Pop()
   526  			maybe.PushError(engine.UseGasNegative(params.Gas, engine.GasStorageUpdate))
   527  			maybe.PushError(st.CallFrame.SetStorage(params.Callee, loc, data.Bytes()))
   528  			c.debugf("%v {%v := %v}\n", params.Callee, loc, data)
   529  
   530  		case JUMP: // 0x56
   531  			to := stack.Pop64()
   532  			maybe.PushError(c.jump(to, &pc))
   533  			continue
   534  
   535  		case JUMPI: // 0x57
   536  			pos := stack.Pop64()
   537  			cond := stack.Pop()
   538  			if !cond.IsZero() {
   539  				maybe.PushError(c.jump(pos, &pc))
   540  				continue
   541  			} else {
   542  				c.debugf(" ~> false\n")
   543  			}
   544  
   545  		case PC: // 0x58
   546  			stack.Push64(pc)
   547  
   548  		case MSIZE: // 0x59
   549  			// Note: Solidity will write to this offset expecting to find guaranteed
   550  			// free memory to be allocated for it if a subsequent MSTORE is made to
   551  			// this offset.
   552  			capacity := memory.Capacity()
   553  			stack.PushBigInt(capacity)
   554  			c.debugf(" => 0x%X\n", capacity)
   555  
   556  		case GAS: // 0x5A
   557  			stack.PushBigInt(params.Gas)
   558  			c.debugf(" => %X\n", params.Gas)
   559  
   560  		case JUMPDEST: // 0x5B
   561  			c.debugf("\n")
   562  			// Do nothing
   563  
   564  		case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
   565  			a := uint64(op - PUSH1 + 1)
   566  			codeSegment := maybe.Bytes(subslice(c.GetBytecode(), pc+1, a))
   567  			res := LeftPadWord256(codeSegment)
   568  			stack.Push(res)
   569  			pc += a
   570  			c.debugf(" => 0x%v\n", res)
   571  
   572  		case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
   573  			n := int(op - DUP1 + 1)
   574  			stack.Dup(n)
   575  			c.debugf(" => [%d] 0x%v\n", n, stack.Peek())
   576  
   577  		case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
   578  			n := int(op - SWAP1 + 2)
   579  			stack.Swap(n)
   580  			c.debugf(" => [%d] %v\n", n, stack.Peek())
   581  
   582  		case LOG0, LOG1, LOG2, LOG3, LOG4:
   583  			n := int(op - LOG0)
   584  			topics := make([]Word256, n)
   585  			offset, size := stack.PopBigInt(), stack.PopBigInt()
   586  			for i := 0; i < n; i++ {
   587  				topics[i] = stack.Pop()
   588  			}
   589  			data := memory.Read(offset, size)
   590  			maybe.PushError(st.EventSink.Log(&exec.LogEvent{
   591  				Address: params.Callee,
   592  				Topics:  topics,
   593  				Data:    data,
   594  			}))
   595  			c.debugf(" => T:%v D:%X\n", topics, data)
   596  
   597  		case CREATE, CREATE2: // 0xF0, 0xFB
   598  			returnData = nil
   599  			contractValue := stack.PopBigInt()
   600  			offset, size := stack.PopBigInt(), stack.PopBigInt()
   601  			input := memory.Read(offset, size)
   602  
   603  			// TODO charge for gas to create account _ the code length * GasCreateByte
   604  			maybe.PushError(engine.UseGasNegative(params.Gas, engine.GasCreateAccount))
   605  
   606  			var newAccountAddress crypto.Address
   607  			if op == CREATE {
   608  				c.sequence++
   609  				nonce := make([]byte, txs.HashLength+uint64Length)
   610  				copy(nonce, c.options.Nonce)
   611  				binary.BigEndian.PutUint64(nonce[txs.HashLength:], c.sequence)
   612  				newAccountAddress = crypto.NewContractAddress(params.Callee, nonce)
   613  			} else if op == CREATE2 {
   614  				salt := stack.Pop()
   615  				code := engine.MustGetAccount(st.CallFrame, maybe, params.Callee).EVMCode
   616  				newAccountAddress = crypto.NewContractAddress2(params.Callee, salt, code)
   617  			}
   618  
   619  			// Check the CreateContract permission for this account
   620  			if maybe.PushError(engine.EnsurePermission(st.CallFrame, params.Callee, permission.CreateContract)) {
   621  				continue
   622  			}
   623  
   624  			// Establish a frame in which the putative account exists
   625  			childCallFrame, err := st.CallFrame.NewFrame()
   626  			maybe.PushError(err)
   627  			maybe.PushError(engine.CreateAccount(childCallFrame, newAccountAddress))
   628  
   629  			// Run the input to get the contract code.
   630  			// NOTE: no need to copy 'input' as per Call contract.
   631  			ret, callErr := c.Contract(input).Call(
   632  				engine.State{
   633  					CallFrame:  childCallFrame,
   634  					Blockchain: st.Blockchain,
   635  					EventSink:  st.EventSink,
   636  				},
   637  				engine.CallParams{
   638  					Origin: params.Origin,
   639  					Caller: params.Callee,
   640  					Callee: newAccountAddress,
   641  					Input:  input,
   642  					Value:  *contractValue,
   643  					Gas:    params.Gas,
   644  				})
   645  			if callErr != nil {
   646  				stack.Push(Zero256)
   647  				// Note we both set the return buffer and return the result normally in order to service the error to
   648  				// EVM caller
   649  				returnData = ret
   650  			} else {
   651  				// Update the account with its initialised contract code
   652  				maybe.PushError(engine.InitChildCode(childCallFrame, newAccountAddress, params.Callee, ret))
   653  				maybe.PushError(childCallFrame.Sync())
   654  				stack.PushAddress(newAccountAddress)
   655  			}
   656  
   657  		case CALL, CALLCODE, DELEGATECALL, STATICCALL: // 0xF1, 0xF2, 0xF4, 0xFA
   658  			returnData = nil
   659  
   660  			if maybe.PushError(engine.EnsurePermission(st.CallFrame, params.Callee, permission.Call)) {
   661  				continue
   662  			}
   663  			// Pull arguments off stack:
   664  			gasLimit := stack.PopBigInt()
   665  			target := stack.PopAddress()
   666  			value := params.Value
   667  			// NOTE: for DELEGATECALL value is preserved from the original
   668  			// caller, as such it is not stored on stack as an argument
   669  			// for DELEGATECALL and should not be popped.  Instead previous
   670  			// caller value is used.  for CALL and CALLCODE value is stored
   671  			// on stack and needs to be overwritten from the given value.
   672  			if op != DELEGATECALL && op != STATICCALL {
   673  				value = *stack.PopBigInt()
   674  			}
   675  			// inputs
   676  			inOffset, inSize := stack.PopBigInt(), stack.PopBigInt()
   677  			// outputs
   678  			retOffset := stack.PopBigInt()
   679  			retSize := stack.Pop64()
   680  			c.debugf(" => %v\n", target)
   681  
   682  			var err error
   683  			returnData, err = engine.CallFromSite(st, c.externalDispatcher, params, engine.CallParams{
   684  				CallType: callTypeFromOpCode(op),
   685  				Callee:   target,
   686  				Input:    memory.Read(inOffset, inSize),
   687  				Value:    value,
   688  				Gas:      gasLimit,
   689  			})
   690  			// Push result
   691  			if err != nil {
   692  				c.debugf("error from nested sub-call (depth: %v): %s\n", st.CallFrame.CallStackDepth(), err)
   693  				// So we can return nested errors.CodedError if the top level return is an errors.CodedError
   694  				stack.Push(Zero256)
   695  
   696  			} else {
   697  				stack.Push(One256)
   698  			}
   699  
   700  			code := errors.GetCode(err)
   701  			if code == errors.Codes.None || code == errors.Codes.ExecutionReverted {
   702  				memory.Write(retOffset, RightPadBytes(returnData, int(retSize)))
   703  			} else {
   704  				maybe.PushError(err)
   705  			}
   706  
   707  			// TODO: decide how to handle this
   708  			// Apply refund of any unused gas
   709  			params.Gas.Add(params.Gas, gasLimit)
   710  
   711  			c.debugf("resume %s (%v)\n", params.Callee, params.Gas)
   712  
   713  		case RETURN: // 0xF3
   714  			offset, size := stack.PopBigInt(), stack.PopBigInt()
   715  			output := memory.Read(offset, size)
   716  			c.debugf(" => [%v, %v] (%d) 0x%X\n", offset, size, len(output), output)
   717  			return output, maybe.Error()
   718  
   719  		case REVERT: // 0xFD
   720  			offset, size := stack.PopBigInt(), stack.PopBigInt()
   721  			output := memory.Read(offset, size)
   722  			c.debugf(" => [%v, %v] (%d) 0x%X\n", offset, size, len(output), output)
   723  			maybe.PushError(newRevertException(output))
   724  			return output, maybe.Error()
   725  
   726  		case INVALID: // 0xFE
   727  			maybe.PushError(errors.Codes.ExecutionAborted)
   728  			return nil, maybe.Error()
   729  
   730  		case SELFDESTRUCT: // 0xFF
   731  			receiver := stack.PopAddress()
   732  			maybe.PushError(engine.UseGasNegative(params.Gas, engine.GasGetAccount))
   733  			if engine.GetAccount(st.CallFrame, maybe, receiver) == nil {
   734  				// If receiver address doesn't exist, try to create it
   735  				maybe.PushError(engine.UseGasNegative(params.Gas, engine.GasCreateAccount))
   736  				if maybe.PushError(st.CallFrame.CreateAccount(params.Callee, receiver)) {
   737  					continue
   738  				}
   739  			}
   740  			balance := engine.MustGetAccount(st.CallFrame, maybe, params.Callee).Balance
   741  			maybe.PushError(engine.UpdateAccount(st.CallFrame, receiver, func(account *acm.Account) error {
   742  				return account.AddToBalance(balance)
   743  			}))
   744  			maybe.PushError(engine.RemoveAccount(st.CallFrame, params.Callee))
   745  			c.debugf(" => (%X) %v\n", receiver[:4], balance)
   746  			return nil, maybe.Error()
   747  
   748  		case STOP: // 0x00
   749  			c.debugf("\n")
   750  			return nil, maybe.Error()
   751  
   752  		default:
   753  			c.debugf("(pc) %-3v Unknown opcode %v\n", pc, op)
   754  			maybe.PushError(errors.Errorf(errors.Codes.Generic, "unknown opcode %v", op))
   755  			return nil, maybe.Error()
   756  		}
   757  		pc++
   758  	}
   759  	return nil, maybe.Error()
   760  }
   761  
   762  func (c *Contract) jump(to uint64, pc *uint64) error {
   763  	dest := c.GetSymbol(to)
   764  	if dest != JUMPDEST || c.IsPushData(to) {
   765  		c.debugf(" ~> %v invalid jump dest %v\n", to, dest)
   766  		return errors.Codes.InvalidJumpDest
   767  	}
   768  	c.debugf(" ~> %v\n", to)
   769  	*pc = to
   770  	return nil
   771  }
   772  
   773  // Returns a subslice from offset of length length and a bool
   774  // (true iff slice was possible). If the subslice
   775  // extends past the end of data it returns A COPY of the segment at the end of
   776  // data padded with zeroes on the right. If offset == len(data) it returns all
   777  // zeroes. if offset > len(data) it returns a false
   778  func subslice(data []byte, offset, length uint64) ([]byte, error) {
   779  	size := uint64(len(data))
   780  	if size < offset || offset < 0 || length < 0 {
   781  		return nil, errors.Errorf(errors.Codes.InputOutOfBounds,
   782  			"subslice could not slice data of size %d at offset %d for length %d", size, offset, length)
   783  	}
   784  	if size < offset+length {
   785  		// Extract slice from offset to end padding to requested length
   786  		ret := make([]byte, length)
   787  		copy(ret, data[offset:])
   788  		return ret, nil
   789  	}
   790  	return data[offset : offset+length], nil
   791  }
   792  
   793  // Dump the bytecode being sent to the EVM in the current working directory
   794  func dumpTokens(nonce []byte, caller, callee crypto.Address, code []byte) {
   795  	var tokensString string
   796  	tokens, err := acm.Bytecode(code).Tokens()
   797  	if err != nil {
   798  		tokensString = fmt.Sprintf("error generating tokens from bytecode: %v", err)
   799  	} else {
   800  		tokensString = strings.Join(tokens, "\n")
   801  	}
   802  	txHashString := "nil-nonce"
   803  	if len(nonce) >= 4 {
   804  		txHashString = fmt.Sprintf("nonce-%X", nonce[:4])
   805  	}
   806  	callerString := "caller-none"
   807  	if caller != crypto.ZeroAddress {
   808  		callerString = fmt.Sprintf("caller-%v", caller)
   809  	}
   810  	calleeString := "callee-none"
   811  	if callee != crypto.ZeroAddress {
   812  		calleeString = fmt.Sprintf("callee-%v", caller)
   813  	}
   814  	_ = ioutil.WriteFile(fmt.Sprintf("tokens_%s_%s_%s.asm", txHashString, callerString, calleeString),
   815  		[]byte(tokensString), 0777)
   816  }
   817  
   818  func newRevertException(ret []byte) errors.CodedError {
   819  	code := errors.Codes.ExecutionReverted
   820  	if len(ret) > 0 {
   821  		// Attempt decode
   822  		reason, err := abi.UnpackRevert(ret)
   823  		if err == nil {
   824  			return errors.Errorf(code, "with reason '%s'", *reason)
   825  		}
   826  	}
   827  	return code
   828  }
   829  
   830  func callTypeFromOpCode(o OpCode) exec.CallType {
   831  	switch o {
   832  	case CALL:
   833  		return exec.CallTypeCall
   834  	case CALLCODE:
   835  		return exec.CallTypeCode
   836  	case STATICCALL:
   837  		return exec.CallTypeStatic
   838  	case DELEGATECALL:
   839  		return exec.CallTypeDelegate
   840  	default:
   841  		return exec.CallTypeInvalid
   842  	}
   843  }