github.com/klaytn/klaytn@v1.10.2/blockchain/vm/evm.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2015 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from core/vm/evm.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package vm
    22  
    23  import (
    24  	"math/big"
    25  	"sync/atomic"
    26  	"time"
    27  
    28  	"github.com/klaytn/klaytn/blockchain/types"
    29  	"github.com/klaytn/klaytn/blockchain/types/accountkey"
    30  	"github.com/klaytn/klaytn/common"
    31  	"github.com/klaytn/klaytn/crypto"
    32  	"github.com/klaytn/klaytn/kerrors"
    33  	"github.com/klaytn/klaytn/params"
    34  )
    35  
    36  // emptyCodeHash is used by create to ensure deployment is disallowed to already
    37  // deployed contract addresses (relevant after the account abstraction).
    38  var emptyCodeHash = crypto.Keccak256Hash(nil)
    39  
    40  const (
    41  	CancelByCtxDone = 1 << iota
    42  	CancelByTotalTimeLimit
    43  )
    44  
    45  type (
    46  	// CanTransferFunc is the signature of a transfer guard function
    47  	CanTransferFunc func(StateDB, common.Address, *big.Int) bool
    48  	// TransferFunc is the signature of a transfer function
    49  	TransferFunc func(StateDB, common.Address, common.Address, *big.Int)
    50  	// GetHashFunc returns the nth block hash in the blockchain
    51  	// and is used by the BLOCKHASH EVM op code.
    52  	GetHashFunc func(uint64) common.Hash
    53  )
    54  
    55  // isProgramAccount returns true if the address is one of the following:
    56  // - an address of precompiled contracts
    57  // - an address of program accounts
    58  func isProgramAccount(evm *EVM, caller common.Address, addr common.Address, db StateDB) bool {
    59  	_, exists := evm.GetPrecompiledContractMap(caller)[addr]
    60  	return exists || db.IsProgramAccount(addr)
    61  }
    62  
    63  // run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
    64  func run(evm *EVM, contract *Contract, input []byte) ([]byte, error) {
    65  	if contract.CodeAddr != nil {
    66  		precompiles := evm.GetPrecompiledContractMap(contract.CallerAddress)
    67  		if p := precompiles[*contract.CodeAddr]; p != nil {
    68  			///////////////////////////////////////////////////////
    69  			// OpcodeComputationCostLimit: The below code is commented and will be usd for debugging purposes.
    70  			//var startTime time.Time
    71  			//if opDebug {
    72  			//	startTime = time.Now()
    73  			//}
    74  			///////////////////////////////////////////////////////
    75  			ret, computationCost, err := RunPrecompiledContract(p, input, contract, evm) // TODO-Klaytn-Issue615
    76  			///////////////////////////////////////////////////////
    77  			// OpcodeComputationCostLimit: The below code is commented and will be usd for debugging purposes.
    78  			//if opDebug {
    79  			//	//fmt.Println("running precompiled contract...", "addr", contract.CodeAddr.String(), "computationCost", computationCost)
    80  			//	elapsedTime := uint64(time.Since(startTime).Nanoseconds())
    81  			//	addr := int(contract.CodeAddr.Bytes()[19])
    82  			//	precompiledCnt[addr] += 1
    83  			//	precompiledTime[addr] += elapsedTime
    84  			//}
    85  			///////////////////////////////////////////////////////
    86  			evm.opcodeComputationCostSum += computationCost
    87  			return ret, err
    88  		}
    89  	}
    90  	return evm.interpreter.Run(contract, input)
    91  }
    92  
    93  // Context provides the EVM with auxiliary information. Once provided
    94  // it shouldn't be modified.
    95  type Context struct {
    96  	// CanTransfer returns whether the account contains
    97  	// sufficient KLAY to transfer the value
    98  	CanTransfer CanTransferFunc
    99  	// Transfer transfers KLAY from one account to the other
   100  	Transfer TransferFunc
   101  	// GetHash returns the hash corresponding to n
   102  	GetHash GetHashFunc
   103  
   104  	// Message information
   105  	Origin   common.Address // Provides information for ORIGIN
   106  	GasPrice *big.Int       // Provides information for GASPRICE
   107  
   108  	// Block information
   109  	Coinbase    common.Address // Provides information for COINBASE
   110  	GasLimit    uint64         // Provides information for GASLIMIT
   111  	BlockNumber *big.Int       // Provides information for NUMBER
   112  	Time        *big.Int       // Provides information for TIME
   113  	BlockScore  *big.Int       // Provides information for DIFFICULTY
   114  	BaseFee     *big.Int       // Provides information for BASEFEE
   115  }
   116  
   117  // EVM is the Ethereum Virtual Machine base object and provides
   118  // the necessary tools to run a contract on the given state with
   119  // the provided context. It should be noted that any error
   120  // generated through any of the calls should be considered a
   121  // revert-state-and-consume-all-gas operation, no checks on
   122  // specific errors should ever be performed. The interpreter makes
   123  // sure that any errors generated are to be considered faulty code.
   124  //
   125  // The EVM should never be reused and is not thread safe.
   126  type EVM struct {
   127  	// Context provides auxiliary blockchain related information
   128  	Context
   129  	// StateDB gives access to the underlying state
   130  	StateDB StateDB
   131  	// Depth is the current call stack
   132  	depth int
   133  
   134  	// chainConfig contains information about the current chain
   135  	chainConfig *params.ChainConfig
   136  	// chain rules contains the chain rules for the current epoch
   137  	chainRules params.Rules
   138  	// virtual machine configuration options used to initialise the
   139  	// evm.
   140  	vmConfig *Config
   141  	// global (to this context) ethereum virtual machine
   142  	// used throughout the execution of the tx.
   143  	interpreter *Interpreter
   144  	// abort is used to abort the EVM calling operations
   145  	// NOTE: must be set atomically
   146  	abort int32
   147  	// callGasTemp holds the gas available for the current call. This is needed because the
   148  	// available gas is calculated in gasCall* according to the 63/64 rule and later
   149  	// applied in opCall*.
   150  	callGasTemp uint64
   151  
   152  	// opcodeComputationCostSum is the sum of computation cost of opcodes.
   153  	opcodeComputationCostSum uint64
   154  }
   155  
   156  // NewEVM returns a new EVM. The returned EVM is not thread safe and should
   157  // only ever be used *once*.
   158  func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig *Config) *EVM {
   159  	evm := &EVM{
   160  		Context:     ctx,
   161  		StateDB:     statedb,
   162  		vmConfig:    vmConfig,
   163  		chainConfig: chainConfig,
   164  		chainRules:  chainConfig.Rules(ctx.BlockNumber),
   165  	}
   166  
   167  	if vmConfig.RunningEVM != nil {
   168  		vmConfig.RunningEVM <- evm
   169  	}
   170  
   171  	// If internal transaction tracing is enabled, creates a tracer for a transaction
   172  	if vmConfig.EnableInternalTxTracing {
   173  		vmConfig.Debug = true
   174  		vmConfig.Tracer = NewInternalTxTracer()
   175  	}
   176  
   177  	evm.interpreter = NewEVMInterpreter(evm, vmConfig)
   178  	return evm
   179  }
   180  
   181  // Cancel cancels any running EVM operation. This may be called concurrently and
   182  // it's safe to be called multiple times.
   183  func (evm *EVM) Cancel(reason int32) {
   184  	for {
   185  		abort := atomic.LoadInt32(&evm.abort)
   186  		swapped := atomic.CompareAndSwapInt32(&evm.abort, abort, abort|reason)
   187  		if swapped {
   188  			break
   189  		}
   190  	}
   191  }
   192  
   193  func (evm *EVM) IsPrefetching() bool {
   194  	return evm.vmConfig.Prefetching
   195  }
   196  
   197  // Cancelled returns true if Cancel has been called
   198  func (evm *EVM) Cancelled() bool {
   199  	return atomic.LoadInt32(&evm.abort) == 1
   200  }
   201  
   202  // Call executes the contract associated with the addr with the given input as
   203  // parameters. It also handles any necessary value transfer required and takes
   204  // the necessary steps to create accounts and reverses the state in case of an
   205  // execution error or failed value transfer.
   206  func (evm *EVM) Call(caller types.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
   207  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   208  		return nil, gas, nil
   209  	}
   210  
   211  	// Fail if we're trying to execute above the call depth limit
   212  	if evm.depth > int(params.CallCreateDepth) {
   213  		return nil, gas, ErrDepth // TODO-Klaytn-Issue615
   214  	}
   215  	// Fail if we're trying to transfer more than the available balance
   216  	if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
   217  		return nil, gas, ErrInsufficientBalance // TODO-Klaytn-Issue615
   218  	}
   219  
   220  	var (
   221  		to       = AccountRef(addr)
   222  		snapshot = evm.StateDB.Snapshot()
   223  	)
   224  
   225  	// Filter out invalid precompiled address calls, and create a precompiled contract object if it is not exist.
   226  	if common.IsPrecompiledContractAddress(addr) {
   227  		precompiles := evm.GetPrecompiledContractMap(caller.Address())
   228  		if precompiles[addr] == nil || value.Sign() != 0 {
   229  			// Return an error if an enabled precompiled address is called or a value is transferred to a precompiled address.
   230  			if evm.vmConfig.Debug && evm.depth == 0 {
   231  				evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
   232  				evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
   233  			}
   234  			return nil, gas, kerrors.ErrPrecompiledContractAddress
   235  		}
   236  		// create an account object of the enabled precompiled address if not exist.
   237  		if !evm.StateDB.Exist(addr) {
   238  			evm.StateDB.CreateSmartContractAccount(addr, params.CodeFormatEVM, evm.chainRules)
   239  		}
   240  	}
   241  
   242  	// The logic below creates an EOA account if not exist.
   243  	// However, it does not create a contract account since `Call` is not proper method to create a contract.
   244  	if !evm.StateDB.Exist(addr) {
   245  		if value.Sign() == 0 {
   246  			// Calling a non-existing account (probably contract), don't do anything, but ping the tracer
   247  			if evm.vmConfig.Debug && evm.depth == 0 {
   248  				evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
   249  				evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
   250  			}
   251  			return nil, gas, nil
   252  		}
   253  		// If non-existing address is called with a value, an object of the address is created.
   254  		evm.StateDB.CreateEOA(addr, false, accountkey.NewAccountKeyLegacy())
   255  	}
   256  	evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
   257  
   258  	if !isProgramAccount(evm, caller.Address(), addr, evm.StateDB) {
   259  		return ret, gas, nil
   260  	}
   261  
   262  	// Initialise a new contract and set the code that is to be used by the EVM.
   263  	// The contract is a scoped environment for this execution context only.
   264  	contract := NewContract(caller, to, value, gas)
   265  	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
   266  
   267  	start := time.Now()
   268  
   269  	// Capture the tracer start/end events in debug mode
   270  	if evm.vmConfig.Debug && evm.depth == 0 {
   271  		evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
   272  
   273  		defer func() { // Lazy evaluation of the parameters
   274  			evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
   275  		}()
   276  	}
   277  	ret, err = run(evm, contract, input)
   278  
   279  	// When an error was returned by the EVM or when setting the creation code
   280  	// above we revert to the snapshot and consume any gas remaining. Additionally
   281  	// when we're in homestead this also counts for code storage gas errors.
   282  	if err != nil {
   283  		evm.StateDB.RevertToSnapshot(snapshot)
   284  		if err != ErrExecutionReverted {
   285  			contract.UseGas(contract.Gas)
   286  		}
   287  	}
   288  	return ret, contract.Gas, err
   289  }
   290  
   291  // CallCode executes the contract associated with the addr with the given input
   292  // as parameters. It also handles any necessary value transfer required and takes
   293  // the necessary steps to create accounts and reverses the state in case of an
   294  // execution error or failed value transfer.
   295  //
   296  // CallCode differs from Call in the sense that it executes the given address'
   297  // code with the caller as context.
   298  func (evm *EVM) CallCode(caller types.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
   299  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   300  		return nil, gas, nil
   301  	}
   302  
   303  	// Fail if we're trying to execute above the call depth limit
   304  	if evm.depth > int(params.CallCreateDepth) {
   305  		return nil, gas, ErrDepth // TODO-Klaytn-Issue615
   306  	}
   307  	// Fail if we're trying to transfer more than the available balance
   308  	if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
   309  		return nil, gas, ErrInsufficientBalance // TODO-Klaytn-Issue615
   310  	}
   311  
   312  	if !isProgramAccount(evm, caller.Address(), addr, evm.StateDB) {
   313  		logger.Debug("Returning since the addr is not a program account", "addr", addr)
   314  		return nil, gas, nil
   315  	}
   316  
   317  	var (
   318  		snapshot = evm.StateDB.Snapshot()
   319  		to       = AccountRef(caller.Address())
   320  	)
   321  	// Initialise a new contract and set the code that is to be used by the EVM.
   322  	// The contract is a scoped environment for this execution context only.
   323  	contract := NewContract(caller, to, value, gas)
   324  	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
   325  
   326  	ret, err = run(evm, contract, input)
   327  	if err != nil {
   328  		evm.StateDB.RevertToSnapshot(snapshot)
   329  		if err != ErrExecutionReverted {
   330  			contract.UseGas(contract.Gas)
   331  		}
   332  	}
   333  	return ret, contract.Gas, err
   334  }
   335  
   336  // DelegateCall executes the contract associated with the addr with the given input
   337  // as parameters. It reverses the state in case of an execution error.
   338  //
   339  // DelegateCall differs from CallCode in the sense that it executes the given address'
   340  // code with the caller as context and the caller is set to the caller of the caller.
   341  func (evm *EVM) DelegateCall(caller types.ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
   342  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   343  		return nil, gas, nil
   344  	}
   345  	// Fail if we're trying to execute above the call depth limit
   346  	if evm.depth > int(params.CallCreateDepth) {
   347  		return nil, gas, ErrDepth // TODO-Klaytn-Issue615
   348  	}
   349  
   350  	if !isProgramAccount(evm, caller.Address(), addr, evm.StateDB) {
   351  		logger.Debug("Returning since the addr is not a program account", "addr", addr)
   352  		return nil, gas, nil
   353  	}
   354  
   355  	var (
   356  		snapshot = evm.StateDB.Snapshot()
   357  		to       = AccountRef(caller.Address())
   358  	)
   359  
   360  	// Initialise a new contract and make initialise the delegate values
   361  	contract := NewContract(caller, to, nil, gas).AsDelegate()
   362  	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
   363  
   364  	ret, err = run(evm, contract, input)
   365  	if err != nil {
   366  		evm.StateDB.RevertToSnapshot(snapshot)
   367  		if err != ErrExecutionReverted {
   368  			contract.UseGas(contract.Gas)
   369  		}
   370  	}
   371  	return ret, contract.Gas, err
   372  }
   373  
   374  // StaticCall executes the contract associated with the addr with the given input
   375  // as parameters while disallowing any modifications to the state during the call.
   376  // Opcodes that attempt to perform such modifications will result in exceptions
   377  // instead of performing the modifications.
   378  func (evm *EVM) StaticCall(caller types.ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
   379  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   380  		return nil, gas, nil
   381  	}
   382  	// Fail if we're trying to execute above the call depth limit
   383  	if evm.depth > int(params.CallCreateDepth) {
   384  		return nil, gas, ErrDepth // TODO-Klaytn-Issue615
   385  	}
   386  	// Make sure the readonly is only set if we aren't in readonly yet
   387  	// this makes also sure that the readonly flag isn't removed for
   388  	// child calls.
   389  	if !evm.interpreter.readOnly {
   390  		evm.interpreter.readOnly = true
   391  		defer func() { evm.interpreter.readOnly = false }()
   392  	}
   393  
   394  	if !isProgramAccount(evm, caller.Address(), addr, evm.StateDB) {
   395  		logger.Debug("Returning since the addr is not a program account", "addr", addr)
   396  		return nil, gas, nil
   397  	}
   398  
   399  	var (
   400  		to       = AccountRef(addr)
   401  		snapshot = evm.StateDB.Snapshot()
   402  	)
   403  	// Initialise a new contract and set the code that is to be used by the EVM.
   404  	// The contract is a scoped environment for this execution context only.
   405  	contract := NewContract(caller, to, new(big.Int), gas)
   406  	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
   407  
   408  	// When an error was returned by the EVM or when setting the creation code
   409  	// above we revert to the snapshot and consume any gas remaining. Additionally
   410  	// when we're in Homestead this also counts for code storage gas errors.
   411  	ret, err = run(evm, contract, input)
   412  	if err != nil {
   413  		evm.StateDB.RevertToSnapshot(snapshot)
   414  		if err != ErrExecutionReverted {
   415  			contract.UseGas(contract.Gas)
   416  		}
   417  	}
   418  	return ret, contract.Gas, err
   419  }
   420  
   421  type codeAndHash struct {
   422  	code []byte
   423  	hash common.Hash
   424  }
   425  
   426  func (c *codeAndHash) Hash() common.Hash {
   427  	if c.hash == (common.Hash{}) {
   428  		c.hash = crypto.Keccak256Hash(c.code)
   429  	}
   430  	return c.hash
   431  }
   432  
   433  // Create creates a new contract using code as deployment code.
   434  func (evm *EVM) create(caller types.ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, humanReadable bool, codeFormat params.CodeFormat) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
   435  	// Depth check execution. Fail if we're trying to execute above the
   436  	// limit.
   437  	if evm.depth > int(params.CallCreateDepth) {
   438  		return nil, common.Address{}, gas, ErrDepth // TODO-Klaytn-Issue615
   439  	}
   440  	if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
   441  		return nil, common.Address{}, gas, ErrInsufficientBalance // TODO-Klaytn-Issue615
   442  	}
   443  
   444  	// Increasing nonce since a failed tx with one of following error will be loaded on a block.
   445  	evm.StateDB.IncNonce(caller.Address())
   446  
   447  	// We add this to the access list _before_ taking a snapshot. Even if the creation fails,
   448  	// the access-list change should not be rolled back
   449  	if evm.chainRules.IsKore {
   450  		evm.StateDB.AddAddressToAccessList(address)
   451  	}
   452  
   453  	if evm.StateDB.Exist(address) {
   454  		return nil, common.Address{}, 0, ErrContractAddressCollision // TODO-Klaytn-Issue615
   455  	}
   456  	if common.IsPrecompiledContractAddress(address) {
   457  		return nil, common.Address{}, gas, kerrors.ErrPrecompiledContractAddress
   458  	}
   459  
   460  	// Create a new account on the state
   461  	snapshot := evm.StateDB.Snapshot()
   462  	// TODO-Klaytn-Accounts: for now, smart contract accounts cannot withdraw KLAYs via ValueTransfer
   463  	//   because the account key is set to AccountKeyFail by default.
   464  	//   Need to make a decision of the key type.
   465  	evm.StateDB.CreateSmartContractAccountWithKey(address, humanReadable, accountkey.NewAccountKeyFail(), codeFormat, evm.chainRules)
   466  	evm.StateDB.SetNonce(address, 1)
   467  	if value.Sign() != 0 {
   468  		evm.Transfer(evm.StateDB, caller.Address(), address, value)
   469  	}
   470  	// Initialise a new contract and set the code that is to be used by the EVM.
   471  	// The contract is a scoped environment for this execution context only.
   472  	contract := NewContract(caller, AccountRef(address), value, gas)
   473  	contract.SetCodeOptionalHash(&address, codeAndHash)
   474  
   475  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   476  		return nil, address, gas, nil
   477  	}
   478  
   479  	if evm.vmConfig.Debug && evm.depth == 0 {
   480  		evm.vmConfig.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.code, gas, value)
   481  	}
   482  	start := time.Now()
   483  
   484  	ret, err = run(evm, contract, nil)
   485  
   486  	// check whether the max code size has been exceeded
   487  	maxCodeSizeExceeded := len(ret) > params.MaxCodeSize
   488  	// if the contract creation ran successfully and no errors were returned
   489  	// calculate the gas required to store the code. If the code could not
   490  	// be stored due to not enough gas set an error and let it be handled
   491  	// by the error checking condition below.
   492  	if err == nil && !maxCodeSizeExceeded {
   493  		createDataGas := uint64(len(ret)) * params.CreateDataGas
   494  		if contract.UseGas(createDataGas) {
   495  			if evm.StateDB.SetCode(address, ret) != nil {
   496  				// `err` is returned to `vmerr` in `StateTransition.TransitionDb()`.
   497  				// Then, `vmerr` will be used to make a receipt status using `getReceiptStatusFromVMerr()`.
   498  				// Since `getReceiptStatusFromVMerr()` uses a map to determine the receipt status,
   499  				// this `err` should be an error variable declared in vm/errors.go.
   500  				// TODO-Klaytn: Make a package of error variables containing all exported error variables.
   501  				// After the above TODO-Klaytn is resolved, we can return the error returned by `SetCode()` directly.
   502  				err = ErrFailedOnSetCode
   503  			}
   504  		} else {
   505  			err = ErrCodeStoreOutOfGas // TODO-Klaytn-Issue615
   506  		}
   507  	}
   508  
   509  	// When an error was returned by the EVM or when setting the creation code
   510  	// above we revert to the snapshot and consume any gas remaining.
   511  	if maxCodeSizeExceeded || err != nil {
   512  		evm.StateDB.RevertToSnapshot(snapshot)
   513  		if err != ErrExecutionReverted {
   514  			contract.UseGas(contract.Gas)
   515  		}
   516  	}
   517  	// Assign err if contract code size exceeds the max while the err is still empty.
   518  	if maxCodeSizeExceeded && err == nil {
   519  		err = ErrMaxCodeSizeExceeded // TODO-Klaytn-Issue615
   520  	}
   521  
   522  	// Reject code starting with 0xEF if EIP-3541 is enabled.
   523  	if err == nil && len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsKore {
   524  		err = ErrInvalidCode
   525  	}
   526  
   527  	if evm.vmConfig.Debug && evm.depth == 0 {
   528  		evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
   529  	}
   530  	return ret, address, contract.Gas, err
   531  }
   532  
   533  // Create creates a new contract using code as deployment code.
   534  func (evm *EVM) Create(caller types.ContractRef, code []byte, gas uint64, value *big.Int, codeFormat params.CodeFormat) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
   535  	codeAndHash := &codeAndHash{code: code}
   536  	contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address()))
   537  	return evm.create(caller, codeAndHash, gas, value, contractAddr, false, codeFormat)
   538  }
   539  
   540  // Create2 creates a new contract using code as deployment code.
   541  //
   542  // The different between Create2 with Create is Create2 uses sha3(0xff ++ msg.sender ++ salt ++ sha3(init_code))[12:]
   543  // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
   544  func (evm *EVM) Create2(caller types.ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int, codeFormat params.CodeFormat) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
   545  	codeAndHash := &codeAndHash{code: code}
   546  	contractAddr = crypto.CreateAddress2(caller.Address(), common.BigToHash(salt), codeAndHash.Hash().Bytes())
   547  	return evm.create(caller, codeAndHash, gas, endowment, contractAddr, false, codeFormat)
   548  }
   549  
   550  // CreateWithAddress creates a new contract using code as deployment code with given address and humanReadable.
   551  func (evm *EVM) CreateWithAddress(caller types.ContractRef, code []byte, gas uint64, value *big.Int, contractAddr common.Address, humanReadable bool, codeFormat params.CodeFormat) ([]byte, common.Address, uint64, error) {
   552  	codeAndHash := &codeAndHash{code: code}
   553  	codeAndHash.Hash()
   554  	return evm.create(caller, codeAndHash, gas, value, contractAddr, humanReadable, codeFormat)
   555  }
   556  
   557  func (evm *EVM) GetPrecompiledContractMap(addr common.Address) map[common.Address]PrecompiledContract {
   558  	// VmVersion means that the contract uses the precompiled contract map at the deployment time.
   559  	// Also, it follows old map's gas price & computation cost.
   560  
   561  	// Get vmVersion from addr only if the addr is a contract address.
   562  	// If new "VmVersion" is added, add new if clause below
   563  	if vmVersion, ok := evm.StateDB.GetVmVersion(addr); ok && vmVersion == params.VmVersion0 {
   564  		// Without VmVersion0, precompiled contract address 0x09-0x0b won't work properly
   565  		// with the contracts deployed before istanbulHF
   566  		return PrecompiledContractsByzantiumCompatible
   567  	}
   568  
   569  	switch {
   570  	case evm.chainRules.IsKore:
   571  		return PrecompiledContractsKore
   572  	case evm.chainRules.IsIstanbul:
   573  		return PrecompiledContractsIstanbulCompatible
   574  	default:
   575  		return PrecompiledContractsByzantiumCompatible
   576  	}
   577  }
   578  
   579  // ChainConfig returns the environment's chain configuration
   580  func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
   581  
   582  // Interpreter returns the EVM interpreter
   583  func (evm *EVM) Interpreter() *Interpreter { return evm.interpreter }
   584  
   585  func (evm *EVM) GetOpCodeComputationCost() uint64 { return evm.opcodeComputationCostSum }