github.com/dim4egster/coreth@v0.10.2/core/vm/evm.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2014 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package vm
    28  
    29  import (
    30  	"math/big"
    31  	"sync/atomic"
    32  	"time"
    33  
    34  	"github.com/dim4egster/coreth/constants"
    35  	"github.com/dim4egster/coreth/params"
    36  	"github.com/dim4egster/coreth/precompile"
    37  	"github.com/dim4egster/coreth/vmerrs"
    38  	"github.com/ethereum/go-ethereum/common"
    39  	"github.com/ethereum/go-ethereum/crypto"
    40  	"github.com/holiman/uint256"
    41  )
    42  
    43  var (
    44  	_ precompile.PrecompileAccessibleState = &EVM{}
    45  	_ precompile.BlockContext              = &BlockContext{}
    46  )
    47  
    48  // IsProhibited returns true if [addr] is the blackhole address or is
    49  // with a range reserved for precompiled contracts.
    50  func IsProhibited(addr common.Address) bool {
    51  	if addr == constants.BlackholeAddr {
    52  		return true
    53  	}
    54  	for _, reservedRange := range precompile.ReservedRanges {
    55  		if reservedRange.Contains(addr) {
    56  			return true
    57  		}
    58  	}
    59  	return false
    60  }
    61  
    62  // TODO: deprecate after Banff activation.
    63  func (evm *EVM) isProhibitedWithTimestamp(addr common.Address) error {
    64  	if addr != NativeAssetCallAddr {
    65  		return nil
    66  	}
    67  
    68  	// Return error depending on the phase
    69  	switch {
    70  	case evm.chainRules.IsApricotPhasePost6: // If we are in the soft fork, return the soft error
    71  		return vmerrs.ErrToAddrProhibitedSoft
    72  	case evm.chainRules.IsApricotPhase6: // If we are in Phase6, return nil
    73  		return nil
    74  	case evm.chainRules.IsApricotPhasePre6: // If we are in PrePhase6, return Prohibited6
    75  		return vmerrs.ErrToAddrProhibited6
    76  	default: // Prior to Pre6, don't alter behavior at all
    77  		return nil
    78  	}
    79  }
    80  
    81  // emptyCodeHash is used by create to ensure deployment is disallowed to already
    82  // deployed contract addresses (relevant after the account abstraction).
    83  var emptyCodeHash = crypto.Keccak256Hash(nil)
    84  
    85  type (
    86  	// CanTransferFunc is the signature of a transfer guard function
    87  	CanTransferFunc   func(StateDB, common.Address, *big.Int) bool
    88  	CanTransferMCFunc func(StateDB, common.Address, common.Address, common.Hash, *big.Int) bool
    89  	// TransferFunc is the signature of a transfer function
    90  	TransferFunc   func(StateDB, common.Address, common.Address, *big.Int)
    91  	TransferMCFunc func(StateDB, common.Address, common.Address, common.Hash, *big.Int)
    92  	// GetHashFunc returns the n'th block hash in the blockchain
    93  	// and is used by the BLOCKHASH EVM op code.
    94  	GetHashFunc func(uint64) common.Hash
    95  )
    96  
    97  func (evm *EVM) precompile(addr common.Address) (precompile.StatefulPrecompiledContract, bool) {
    98  	var precompiles map[common.Address]precompile.StatefulPrecompiledContract
    99  	switch {
   100  	case evm.chainRules.IsBanff:
   101  		precompiles = PrecompiledContractsBanff
   102  	case evm.chainRules.IsApricotPhase2:
   103  		precompiles = PrecompiledContractsApricotPhase2
   104  	case evm.chainRules.IsIstanbul:
   105  		precompiles = PrecompiledContractsIstanbul
   106  	case evm.chainRules.IsByzantium:
   107  		precompiles = PrecompiledContractsByzantium
   108  	default:
   109  		precompiles = PrecompiledContractsHomestead
   110  	}
   111  
   112  	// Check the existing precompiles first
   113  	p, ok := precompiles[addr]
   114  	if ok {
   115  		return p, true
   116  	}
   117  
   118  	// Otherwise, check the chain rules for the additionally configured precompiles.
   119  	p, ok = evm.chainRules.Precompiles[addr]
   120  	return p, ok
   121  }
   122  
   123  // BlockContext provides the EVM with auxiliary information. Once provided
   124  // it shouldn't be modified.
   125  type BlockContext struct {
   126  	// CanTransfer returns whether the account contains
   127  	// sufficient ether to transfer the value
   128  	CanTransfer CanTransferFunc
   129  	// CanTransferMC returns whether the account contains
   130  	// sufficient multicoin balance to transfer the value
   131  	CanTransferMC CanTransferMCFunc
   132  	// Transfer transfers ether from one account to the other
   133  	Transfer TransferFunc
   134  	// TransferMultiCoin transfers multicoin from one account to the other
   135  	TransferMultiCoin TransferMCFunc
   136  	// GetHash returns the hash corresponding to n
   137  	GetHash GetHashFunc
   138  
   139  	// Block information
   140  	Coinbase    common.Address // Provides information for COINBASE
   141  	GasLimit    uint64         // Provides information for GASLIMIT
   142  	BlockNumber *big.Int       // Provides information for NUMBER
   143  	Time        *big.Int       // Provides information for TIME
   144  	Difficulty  *big.Int       // Provides information for DIFFICULTY
   145  	BaseFee     *big.Int       // Provides information for BASEFEE
   146  }
   147  
   148  func (b *BlockContext) Number() *big.Int {
   149  	return b.BlockNumber
   150  }
   151  
   152  func (b *BlockContext) Timestamp() *big.Int {
   153  	return b.Time
   154  }
   155  
   156  // TxContext provides the EVM with information about a transaction.
   157  // All fields can change between transactions.
   158  type TxContext struct {
   159  	// Message information
   160  	Origin   common.Address // Provides information for ORIGIN
   161  	GasPrice *big.Int       // Provides information for GASPRICE
   162  }
   163  
   164  // EVM is the Ethereum Virtual Machine base object and provides
   165  // the necessary tools to run a contract on the given state with
   166  // the provided context. It should be noted that any error
   167  // generated through any of the calls should be considered a
   168  // revert-state-and-consume-all-gas operation, no checks on
   169  // specific errors should ever be performed. The interpreter makes
   170  // sure that any errors generated are to be considered faulty code.
   171  //
   172  // The EVM should never be reused and is not thread safe.
   173  type EVM struct {
   174  	// Context provides auxiliary blockchain related information
   175  	Context BlockContext
   176  	TxContext
   177  	// StateDB gives access to the underlying state
   178  	StateDB StateDB
   179  	// Depth is the current call stack
   180  	depth int
   181  
   182  	// chainConfig contains information about the current chain
   183  	chainConfig *params.ChainConfig
   184  	// chain rules contains the chain rules for the current epoch
   185  	chainRules params.Rules
   186  	// virtual machine configuration options used to initialise the
   187  	// evm.
   188  	Config Config
   189  	// global (to this context) ethereum virtual machine
   190  	// used throughout the execution of the tx.
   191  	interpreter *EVMInterpreter
   192  	// abort is used to abort the EVM calling operations
   193  	// NOTE: must be set atomically
   194  	abort int32
   195  	// callGasTemp holds the gas available for the current call. This is needed because the
   196  	// available gas is calculated in gasCall* according to the 63/64 rule and later
   197  	// applied in opCall*.
   198  	callGasTemp uint64
   199  }
   200  
   201  // NewEVM returns a new EVM. The returned EVM is not thread safe and should
   202  // only ever be used *once*.
   203  func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM {
   204  	evm := &EVM{
   205  		Context:     blockCtx,
   206  		TxContext:   txCtx,
   207  		StateDB:     statedb,
   208  		Config:      config,
   209  		chainConfig: chainConfig,
   210  		chainRules:  chainConfig.AvalancheRules(blockCtx.BlockNumber, blockCtx.Time),
   211  	}
   212  	evm.interpreter = NewEVMInterpreter(evm, config)
   213  	return evm
   214  }
   215  
   216  // Reset resets the EVM with a new transaction context.Reset
   217  // This is not threadsafe and should only be done very cautiously.
   218  func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) {
   219  	evm.TxContext = txCtx
   220  	evm.StateDB = statedb
   221  }
   222  
   223  // Cancel cancels any running EVM operation. This may be called concurrently and
   224  // it's safe to be called multiple times.
   225  func (evm *EVM) Cancel() {
   226  	atomic.StoreInt32(&evm.abort, 1)
   227  }
   228  
   229  // Cancelled returns true if Cancel has been called
   230  func (evm *EVM) Cancelled() bool {
   231  	return atomic.LoadInt32(&evm.abort) == 1
   232  }
   233  
   234  // GetStateDB returns the evm's StateDB
   235  func (evm *EVM) GetStateDB() precompile.StateDB {
   236  	return evm.StateDB
   237  }
   238  
   239  // GetBlockContext returns the evm's BlockContext
   240  func (evm *EVM) GetBlockContext() precompile.BlockContext {
   241  	return &evm.Context
   242  }
   243  
   244  // Interpreter returns the current interpreter
   245  func (evm *EVM) Interpreter() *EVMInterpreter {
   246  	return evm.interpreter
   247  }
   248  
   249  // Call executes the contract associated with the addr with the given input as
   250  // parameters. It also handles any necessary value transfer required and takes
   251  // the necessary steps to create accounts and reverses the state in case of an
   252  // execution error or failed value transfer.
   253  func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
   254  	if prohibitErr := evm.isProhibitedWithTimestamp(addr); prohibitErr != nil {
   255  		return nil, gas, prohibitErr
   256  	}
   257  	// Fail if we're trying to execute above the call depth limit
   258  	if evm.depth > int(params.CallCreateDepth) {
   259  		return nil, gas, vmerrs.ErrDepth
   260  	}
   261  	// Fail if we're trying to transfer more than the available balance
   262  	// Note: it is not possible for a negative value to be passed in here due to the fact
   263  	// that [value] will be popped from the stack and decoded to a *big.Int, which will
   264  	// always yield a positive result.
   265  	if value.Sign() != 0 && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
   266  		return nil, gas, vmerrs.ErrInsufficientBalance
   267  	}
   268  	snapshot := evm.StateDB.Snapshot()
   269  	p, isPrecompile := evm.precompile(addr)
   270  
   271  	if !evm.StateDB.Exist(addr) {
   272  		if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 {
   273  			// Calling a non existing account, don't do anything, but ping the tracer
   274  			if evm.Config.Debug {
   275  				if evm.depth == 0 {
   276  					evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
   277  					evm.Config.Tracer.CaptureEnd(ret, 0, 0, nil)
   278  				} else {
   279  					evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
   280  					evm.Config.Tracer.CaptureExit(ret, 0, nil)
   281  				}
   282  			}
   283  			return nil, gas, nil
   284  		}
   285  		evm.StateDB.CreateAccount(addr)
   286  	}
   287  	evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)
   288  
   289  	// Capture the tracer start/end events in debug mode
   290  	if evm.Config.Debug {
   291  		if evm.depth == 0 {
   292  			evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
   293  			defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters
   294  				evm.Config.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err)
   295  			}(gas, time.Now())
   296  		} else {
   297  			// Handle tracer events for entering and exiting a call frame
   298  			evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
   299  			defer func(startGas uint64) {
   300  				evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
   301  			}(gas)
   302  		}
   303  	}
   304  
   305  	if isPrecompile {
   306  		ret, gas, err = RunStatefulPrecompiledContract(p, evm, caller.Address(), addr, input, gas, evm.interpreter.readOnly)
   307  	} else {
   308  		// Initialise a new contract and set the code that is to be used by the EVM.
   309  		// The contract is a scoped environment for this execution context only.
   310  		code := evm.StateDB.GetCode(addr)
   311  		if len(code) == 0 {
   312  			ret, err = nil, nil // gas is unchanged
   313  		} else {
   314  			addrCopy := addr
   315  			// If the account has no code, we can abort here
   316  			// The depth-check is already done, and precompiles handled above
   317  			contract := NewContract(caller, AccountRef(addrCopy), value, gas)
   318  			contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), code)
   319  			ret, err = evm.interpreter.Run(contract, input, false)
   320  			gas = contract.Gas
   321  		}
   322  	}
   323  	// When an error was returned by the EVM or when setting the creation code
   324  	// above we revert to the snapshot and consume any gas remaining. Additionally
   325  	// when we're in homestead this also counts for code storage gas errors.
   326  	if err != nil {
   327  		evm.StateDB.RevertToSnapshot(snapshot)
   328  		if err != vmerrs.ErrExecutionReverted {
   329  			gas = 0
   330  		}
   331  		// TODO: consider clearing up unused snapshots:
   332  		//} else {
   333  		//	evm.StateDB.DiscardSnapshot(snapshot)
   334  	}
   335  	return ret, gas, err
   336  }
   337  
   338  // This allows the user transfer balance of a specified coinId in addition to a normal Call().
   339  func (evm *EVM) CallExpert(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int, coinID common.Hash, value2 *big.Int) (ret []byte, leftOverGas uint64, err error) {
   340  	if prohibitErr := evm.isProhibitedWithTimestamp(addr); prohibitErr != nil {
   341  		return nil, gas, prohibitErr
   342  	}
   343  	// Fail if we're trying to execute above the call depth limit
   344  	if evm.depth > int(params.CallCreateDepth) {
   345  		return nil, gas, vmerrs.ErrDepth
   346  	}
   347  
   348  	// Fail if we're trying to transfer more than the available balance
   349  	// Note: it is not possible for a negative value to be passed in here due to the fact
   350  	// that [value] will be popped from the stack and decoded to a *big.Int, which will
   351  	// always yield a positive result.
   352  	if value.Sign() != 0 && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
   353  		return nil, gas, vmerrs.ErrInsufficientBalance
   354  	}
   355  
   356  	if value2.Sign() != 0 && !evm.Context.CanTransferMC(evm.StateDB, caller.Address(), addr, coinID, value2) {
   357  		return nil, gas, vmerrs.ErrInsufficientBalance
   358  	}
   359  
   360  	snapshot := evm.StateDB.Snapshot()
   361  	//p, isPrecompile := evm.precompile(addr)
   362  
   363  	if !evm.StateDB.Exist(addr) {
   364  		//if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 {
   365  		//	// Calling a non existing account, don't do anything, but ping the tracer
   366  		//	if evm.Config.Debug && evm.depth == 0 {
   367  		//		evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
   368  		//		evm.Config.Tracer.CaptureEnd(ret, 0, 0, nil)
   369  		//	}
   370  		//	return nil, gas, nil
   371  		//}
   372  		evm.StateDB.CreateAccount(addr)
   373  	}
   374  	evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)
   375  	evm.Context.TransferMultiCoin(evm.StateDB, caller.Address(), addr, coinID, value2)
   376  
   377  	// Capture the tracer start/end events in debug mode
   378  	if evm.Config.Debug && evm.depth == 0 {
   379  		evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
   380  		defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters
   381  			evm.Config.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err)
   382  		}(gas, time.Now())
   383  	}
   384  
   385  	//if isPrecompile {
   386  	//	ret, gas, err = RunPrecompiledContract(p, input, gas)
   387  	//} else {
   388  	// Initialise a new contract and set the code that is to be used by the EVM.
   389  	// The contract is a scoped environment for this execution context only.
   390  	code := evm.StateDB.GetCode(addr)
   391  	if len(code) == 0 {
   392  		ret, err = nil, nil // gas is unchanged
   393  	} else {
   394  		addrCopy := addr
   395  		// If the account has no code, we can abort here
   396  		// The depth-check is already done, and precompiles handled above
   397  		contract := NewContract(caller, AccountRef(addrCopy), value, gas)
   398  		contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), code)
   399  		ret, err = evm.interpreter.Run(contract, input, false)
   400  		gas = contract.Gas
   401  	}
   402  	//}
   403  	// When an error was returned by the EVM or when setting the creation code
   404  	// above we revert to the snapshot and consume any gas remaining. Additionally
   405  	// when we're in homestead this also counts for code storage gas errors.
   406  	if err != nil {
   407  		evm.StateDB.RevertToSnapshot(snapshot)
   408  		if err != vmerrs.ErrExecutionReverted {
   409  			gas = 0
   410  		}
   411  		// TODO: consider clearing up unused snapshots:
   412  		//} else {
   413  		//	evm.StateDB.DiscardSnapshot(snapshot)
   414  	}
   415  	return ret, gas, err
   416  }
   417  
   418  // CallCode executes the contract associated with the addr with the given input
   419  // as parameters. It also handles any necessary value transfer required and takes
   420  // the necessary steps to create accounts and reverses the state in case of an
   421  // execution error or failed value transfer.
   422  //
   423  // CallCode differs from Call in the sense that it executes the given address'
   424  // code with the caller as context.
   425  func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
   426  	if prohibitErr := evm.isProhibitedWithTimestamp(addr); prohibitErr != nil {
   427  		return nil, gas, prohibitErr
   428  	}
   429  	// Fail if we're trying to execute above the call depth limit
   430  	if evm.depth > int(params.CallCreateDepth) {
   431  		return nil, gas, vmerrs.ErrDepth
   432  	}
   433  	// Fail if we're trying to transfer more than the available balance
   434  	// Note although it's noop to transfer X ether to caller itself. But
   435  	// if caller doesn't have enough balance, it would be an error to allow
   436  	// over-charging itself. So the check here is necessary.
   437  	// Note: it is not possible for a negative value to be passed in here due to the fact
   438  	// that [value] will be popped from the stack and decoded to a *big.Int, which will
   439  	// always yield a positive result.
   440  	if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
   441  		return nil, gas, vmerrs.ErrInsufficientBalance
   442  	}
   443  	var snapshot = evm.StateDB.Snapshot()
   444  
   445  	// Invoke tracer hooks that signal entering/exiting a call frame
   446  	if evm.Config.Debug {
   447  		evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value)
   448  		defer func(startGas uint64) {
   449  			evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
   450  		}(gas)
   451  	}
   452  
   453  	// It is allowed to call precompiles, even via delegatecall
   454  	if p, isPrecompile := evm.precompile(addr); isPrecompile {
   455  		ret, gas, err = RunStatefulPrecompiledContract(p, evm, caller.Address(), addr, input, gas, evm.interpreter.readOnly)
   456  	} else {
   457  		addrCopy := addr
   458  		// Initialise a new contract and set the code that is to be used by the EVM.
   459  		// The contract is a scoped environment for this execution context only.
   460  		contract := NewContract(caller, AccountRef(caller.Address()), value, gas)
   461  		contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
   462  		ret, err = evm.interpreter.Run(contract, input, false)
   463  		gas = contract.Gas
   464  	}
   465  	if err != nil {
   466  		evm.StateDB.RevertToSnapshot(snapshot)
   467  		if err != vmerrs.ErrExecutionReverted {
   468  			gas = 0
   469  		}
   470  	}
   471  	return ret, gas, err
   472  }
   473  
   474  // DelegateCall executes the contract associated with the addr with the given input
   475  // as parameters. It reverses the state in case of an execution error.
   476  //
   477  // DelegateCall differs from CallCode in the sense that it executes the given address'
   478  // code with the caller as context and the caller is set to the caller of the caller.
   479  func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
   480  	if prohibitErr := evm.isProhibitedWithTimestamp(addr); prohibitErr != nil {
   481  		return nil, gas, prohibitErr
   482  	}
   483  	// Fail if we're trying to execute above the call depth limit
   484  	if evm.depth > int(params.CallCreateDepth) {
   485  		return nil, gas, vmerrs.ErrDepth
   486  	}
   487  	var snapshot = evm.StateDB.Snapshot()
   488  
   489  	// Invoke tracer hooks that signal entering/exiting a call frame
   490  	if evm.Config.Debug {
   491  		evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, nil)
   492  		defer func(startGas uint64) {
   493  			evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
   494  		}(gas)
   495  	}
   496  
   497  	// It is allowed to call precompiles, even via delegatecall
   498  	if p, isPrecompile := evm.precompile(addr); isPrecompile {
   499  		ret, gas, err = RunStatefulPrecompiledContract(p, evm, caller.Address(), addr, input, gas, evm.interpreter.readOnly)
   500  	} else {
   501  		addrCopy := addr
   502  		// Initialise a new contract and make initialise the delegate values
   503  		contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate()
   504  		contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
   505  		ret, err = evm.interpreter.Run(contract, input, false)
   506  		gas = contract.Gas
   507  	}
   508  	if err != nil {
   509  		evm.StateDB.RevertToSnapshot(snapshot)
   510  		if err != vmerrs.ErrExecutionReverted {
   511  			gas = 0
   512  		}
   513  	}
   514  	return ret, gas, err
   515  }
   516  
   517  // StaticCall executes the contract associated with the addr with the given input
   518  // as parameters while disallowing any modifications to the state during the call.
   519  // Opcodes that attempt to perform such modifications will result in exceptions
   520  // instead of performing the modifications.
   521  func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
   522  	if prohibitErr := evm.isProhibitedWithTimestamp(addr); prohibitErr != nil {
   523  		return nil, gas, prohibitErr
   524  	}
   525  	// Fail if we're trying to execute above the call depth limit
   526  	if evm.depth > int(params.CallCreateDepth) {
   527  		return nil, gas, vmerrs.ErrDepth
   528  	}
   529  	// We take a snapshot here. This is a bit counter-intuitive, and could probably be skipped.
   530  	// However, even a staticcall is considered a 'touch'. On mainnet, static calls were introduced
   531  	// after all empty accounts were deleted, so this is not required. However, if we omit this,
   532  	// then certain tests start failing; stRevertTest/RevertPrecompiledTouchExactOOG.json.
   533  	// We could change this, but for now it's left for legacy reasons
   534  	var snapshot = evm.StateDB.Snapshot()
   535  
   536  	// We do an AddBalance of zero here, just in order to trigger a touch.
   537  	// This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium,
   538  	// but is the correct thing to do and matters on other networks, in tests, and potential
   539  	// future scenarios
   540  	evm.StateDB.AddBalance(addr, big0)
   541  
   542  	// Invoke tracer hooks that signal entering/exiting a call frame
   543  	if evm.Config.Debug {
   544  		evm.Config.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil)
   545  		defer func(startGas uint64) {
   546  			evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
   547  		}(gas)
   548  	}
   549  
   550  	if p, isPrecompile := evm.precompile(addr); isPrecompile {
   551  		ret, gas, err = RunStatefulPrecompiledContract(p, evm, caller.Address(), addr, input, gas, true)
   552  	} else {
   553  		// At this point, we use a copy of address. If we don't, the go compiler will
   554  		// leak the 'contract' to the outer scope, and make allocation for 'contract'
   555  		// even if the actual execution ends on RunPrecompiled above.
   556  		addrCopy := addr
   557  		// Initialise a new contract and set the code that is to be used by the EVM.
   558  		// The contract is a scoped environment for this execution context only.
   559  		contract := NewContract(caller, AccountRef(addrCopy), new(big.Int), gas)
   560  		contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
   561  		// When an error was returned by the EVM or when setting the creation code
   562  		// above we revert to the snapshot and consume any gas remaining. Additionally
   563  		// when we're in Homestead this also counts for code storage gas errors.
   564  		ret, err = evm.interpreter.Run(contract, input, true)
   565  		gas = contract.Gas
   566  	}
   567  	if err != nil {
   568  		evm.StateDB.RevertToSnapshot(snapshot)
   569  		if err != vmerrs.ErrExecutionReverted {
   570  			gas = 0
   571  		}
   572  	}
   573  	return ret, gas, err
   574  }
   575  
   576  type codeAndHash struct {
   577  	code []byte
   578  	hash common.Hash
   579  }
   580  
   581  func (c *codeAndHash) Hash() common.Hash {
   582  	if c.hash == (common.Hash{}) {
   583  		c.hash = crypto.Keccak256Hash(c.code)
   584  	}
   585  	return c.hash
   586  }
   587  
   588  // create creates a new contract using code as deployment code.
   589  func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, typ OpCode) ([]byte, common.Address, uint64, error) {
   590  	// Depth check execution. Fail if we're trying to execute above the
   591  	// limit.
   592  	if evm.depth > int(params.CallCreateDepth) {
   593  		return nil, common.Address{}, gas, vmerrs.ErrDepth
   594  	}
   595  	// Note: it is not possible for a negative value to be passed in here due to the fact
   596  	// that [value] will be popped from the stack and decoded to a *big.Int, which will
   597  	// always yield a positive result.
   598  	if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
   599  		return nil, common.Address{}, gas, vmerrs.ErrInsufficientBalance
   600  	}
   601  	// If there is any collision with a prohibited address, return an error instead
   602  	// of allowing the contract to be created.
   603  	if IsProhibited(address) {
   604  		return nil, common.Address{}, gas, vmerrs.ErrAddrProhibited
   605  	}
   606  	nonce := evm.StateDB.GetNonce(caller.Address())
   607  	if nonce+1 < nonce {
   608  		return nil, common.Address{}, gas, vmerrs.ErrNonceUintOverflow
   609  	}
   610  	evm.StateDB.SetNonce(caller.Address(), nonce+1)
   611  	// We add this to the access list _before_ taking a snapshot. Even if the creation fails,
   612  	// the access-list change should not be rolled back
   613  	if evm.chainRules.IsApricotPhase2 {
   614  		evm.StateDB.AddAddressToAccessList(address)
   615  	}
   616  	// Ensure there's no existing contract already at the designated address
   617  	contractHash := evm.StateDB.GetCodeHash(address)
   618  	if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) {
   619  		return nil, common.Address{}, 0, vmerrs.ErrContractAddressCollision
   620  	}
   621  	// Create a new account on the state
   622  	snapshot := evm.StateDB.Snapshot()
   623  	evm.StateDB.CreateAccount(address)
   624  	if evm.chainRules.IsEIP158 {
   625  		evm.StateDB.SetNonce(address, 1)
   626  	}
   627  	evm.Context.Transfer(evm.StateDB, caller.Address(), address, value)
   628  
   629  	// Initialise a new contract and set the code that is to be used by the EVM.
   630  	// The contract is a scoped environment for this execution context only.
   631  	contract := NewContract(caller, AccountRef(address), value, gas)
   632  	contract.SetCodeOptionalHash(&address, codeAndHash)
   633  
   634  	if evm.Config.Debug {
   635  		if evm.depth == 0 {
   636  			evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
   637  		} else {
   638  			evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
   639  		}
   640  	}
   641  
   642  	start := time.Now()
   643  
   644  	ret, err := evm.interpreter.Run(contract, nil, false)
   645  
   646  	// Check whether the max code size has been exceeded, assign err if the case.
   647  	if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize {
   648  		err = vmerrs.ErrMaxCodeSizeExceeded
   649  	}
   650  
   651  	// Reject code starting with 0xEF if EIP-3541 is enabled.
   652  	if err == nil && len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsApricotPhase3 {
   653  		err = vmerrs.ErrInvalidCode
   654  	}
   655  
   656  	// if the contract creation ran successfully and no errors were returned
   657  	// calculate the gas required to store the code. If the code could not
   658  	// be stored due to not enough gas set an error and let it be handled
   659  	// by the error checking condition below.
   660  	if err == nil {
   661  		createDataGas := uint64(len(ret)) * params.CreateDataGas
   662  		if contract.UseGas(createDataGas) {
   663  			evm.StateDB.SetCode(address, ret)
   664  		} else {
   665  			err = vmerrs.ErrCodeStoreOutOfGas
   666  		}
   667  	}
   668  
   669  	// When an error was returned by the EVM or when setting the creation code
   670  	// above we revert to the snapshot and consume any gas remaining. Additionally
   671  	// when we're in homestead this also counts for code storage gas errors.
   672  	if err != nil && (evm.chainRules.IsHomestead || err != vmerrs.ErrCodeStoreOutOfGas) {
   673  		evm.StateDB.RevertToSnapshot(snapshot)
   674  		if err != vmerrs.ErrExecutionReverted {
   675  			contract.UseGas(contract.Gas)
   676  		}
   677  	}
   678  
   679  	if evm.Config.Debug {
   680  		if evm.depth == 0 {
   681  			evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
   682  		} else {
   683  			evm.Config.Tracer.CaptureExit(ret, gas-contract.Gas, err)
   684  		}
   685  	}
   686  	return ret, address, contract.Gas, err
   687  }
   688  
   689  // Create creates a new contract using code as deployment code.
   690  func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
   691  	contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address()))
   692  	return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE)
   693  }
   694  
   695  // Create2 creates a new contract using code as deployment code.
   696  //
   697  // The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
   698  // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
   699  func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
   700  	codeAndHash := &codeAndHash{code: code}
   701  	contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes())
   702  	return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2)
   703  }
   704  
   705  // ChainConfig returns the environment's chain configuration
   706  func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
   707  
   708  func (evm *EVM) NativeAssetCall(caller common.Address, input []byte, suppliedGas uint64, gasCost uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
   709  	if suppliedGas < gasCost {
   710  		return nil, 0, vmerrs.ErrOutOfGas
   711  	}
   712  	remainingGas = suppliedGas - gasCost
   713  
   714  	if readOnly {
   715  		return nil, remainingGas, vmerrs.ErrExecutionReverted
   716  	}
   717  
   718  	to, assetID, assetAmount, callData, err := UnpackNativeAssetCallInput(input)
   719  	if err != nil {
   720  		return nil, remainingGas, vmerrs.ErrExecutionReverted
   721  	}
   722  
   723  	// Note: it is not possible for a negative assetAmount to be passed in here due to the fact that decoding a
   724  	// byte slice into a *big.Int type will always return a positive value.
   725  	if assetAmount.Sign() != 0 && !evm.Context.CanTransferMC(evm.StateDB, caller, to, assetID, assetAmount) {
   726  		return nil, remainingGas, vmerrs.ErrInsufficientBalance
   727  	}
   728  
   729  	snapshot := evm.StateDB.Snapshot()
   730  
   731  	if !evm.StateDB.Exist(to) {
   732  		if remainingGas < params.CallNewAccountGas {
   733  			return nil, 0, vmerrs.ErrOutOfGas
   734  		}
   735  		remainingGas -= params.CallNewAccountGas
   736  		evm.StateDB.CreateAccount(to)
   737  	}
   738  
   739  	// Increment the call depth which is restricted to 1024
   740  	evm.depth++
   741  	defer func() { evm.depth-- }()
   742  
   743  	// Send [assetAmount] of [assetID] to [to] address
   744  	evm.Context.TransferMultiCoin(evm.StateDB, caller, to, assetID, assetAmount)
   745  	ret, remainingGas, err = evm.Call(AccountRef(caller), to, callData, remainingGas, new(big.Int))
   746  
   747  	// When an error was returned by the EVM or when setting the creation code
   748  	// above we revert to the snapshot and consume any gas remaining. Additionally
   749  	// when we're in homestead this also counts for code storage gas errors.
   750  	if err != nil {
   751  		evm.StateDB.RevertToSnapshot(snapshot)
   752  		if err != vmerrs.ErrExecutionReverted {
   753  			remainingGas = 0
   754  		}
   755  		// TODO: consider clearing up unused snapshots:
   756  		//} else {
   757  		//	evm.StateDB.DiscardSnapshot(snapshot)
   758  	}
   759  	return ret, remainingGas, err
   760  }