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 }