github.com/klaytn/klaytn@v1.12.1/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 27 "github.com/holiman/uint256" 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 // BlockContext provides the EVM with auxiliary information. Once provided 94 // it shouldn't be modified. 95 type BlockContext 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 // Block information 105 Coinbase common.Address // Provides information for COINBASE 106 Rewardbase common.Address // Provides information for rewardbase when deferredTxfee is false 107 GasLimit uint64 // Provides information for GASLIMIT 108 BlockNumber *big.Int // Provides information for NUMBER 109 Time *big.Int // Provides information for TIME 110 BlockScore *big.Int // Provides information for DIFFICULTY 111 BaseFee *big.Int // Provides information for BASEFEE 112 Random common.Hash // Provides information for RANDOM 113 } 114 115 // TxContext provides the EVM with information about a transaction. 116 // All fields can change between transactions. 117 type TxContext struct { 118 // Message information 119 Origin common.Address // Provides information for ORIGIN 120 GasPrice *big.Int // Provides information for GASPRICE 121 } 122 123 // EVM is the Ethereum Virtual Machine base object and provides 124 // the necessary tools to run a contract on the given state with 125 // the provided context. It should be noted that any error 126 // generated through any of the calls should be considered a 127 // revert-state-and-consume-all-gas operation, no checks on 128 // specific errors should ever be performed. The interpreter makes 129 // sure that any errors generated are to be considered faulty code. 130 // 131 // The EVM should never be reused and is not thread safe. 132 type EVM struct { 133 // Context provides auxiliary blockchain related information 134 Context BlockContext 135 TxContext 136 // StateDB gives access to the underlying state 137 StateDB StateDB 138 // Depth is the current call stack 139 depth int 140 141 // chainConfig contains information about the current chain 142 chainConfig *params.ChainConfig 143 // chain rules contains the chain rules for the current epoch 144 chainRules params.Rules 145 // virtual machine configuration options used to initialise the 146 // evm. 147 Config *Config 148 // global (to this context) ethereum virtual machine 149 // used throughout the execution of the tx. 150 interpreter *EVMInterpreter 151 // abort is used to abort the EVM calling operations 152 // NOTE: must be set atomically 153 abort int32 154 // callGasTemp holds the gas available for the current call. This is needed because the 155 // available gas is calculated in gasCall* according to the 63/64 rule and later 156 // applied in opCall*. 157 callGasTemp uint64 158 159 // opcodeComputationCostSum is the sum of computation cost of opcodes. 160 opcodeComputationCostSum uint64 161 } 162 163 // NewEVM returns a new EVM. The returned EVM is not thread safe and should 164 // only ever be used *once*. 165 func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, vmConfig *Config) *EVM { 166 evm := &EVM{ 167 Context: blockCtx, 168 TxContext: txCtx, 169 StateDB: statedb, 170 Config: vmConfig, 171 chainConfig: chainConfig, 172 chainRules: chainConfig.Rules(blockCtx.BlockNumber), 173 } 174 175 if vmConfig.RunningEVM != nil { 176 vmConfig.RunningEVM <- evm 177 } 178 179 // If internal transaction tracing is enabled, creates a tracer for a transaction 180 if vmConfig.EnableInternalTxTracing { 181 vmConfig.Debug = true 182 vmConfig.Tracer = NewInternalTxTracer() 183 } 184 185 evm.interpreter = NewEVMInterpreter(evm) 186 187 return evm 188 } 189 190 // Reset resets the EVM with a new transaction context.Reset 191 // This is not threadsafe and should only be done very cautiously. 192 func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) { 193 evm.TxContext = txCtx 194 evm.StateDB = statedb 195 } 196 197 // Cancel cancels any running EVM operation. This may be called concurrently and 198 // it's safe to be called multiple times. 199 func (evm *EVM) Cancel(reason int32) { 200 for { 201 abort := atomic.LoadInt32(&evm.abort) 202 swapped := atomic.CompareAndSwapInt32(&evm.abort, abort, abort|reason) 203 if swapped { 204 break 205 } 206 } 207 } 208 209 func (evm *EVM) IsPrefetching() bool { 210 return evm.Config.Prefetching 211 } 212 213 // Cancelled returns true if Cancel has been called 214 func (evm *EVM) Cancelled() bool { 215 return atomic.LoadInt32(&evm.abort) == 1 216 } 217 218 // Call executes the contract associated with the addr with the given input as 219 // parameters. It also handles any necessary value transfer required and takes 220 // the necessary steps to create accounts and reverses the state in case of an 221 // execution error or failed value transfer. 222 func (evm *EVM) Call(caller types.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { 223 if evm.Config.NoRecursion && evm.depth > 0 { 224 return nil, gas, nil 225 } 226 227 // Fail if we're trying to execute above the call depth limit 228 if evm.depth > int(params.CallCreateDepth) { 229 return nil, gas, ErrDepth // TODO-Klaytn-Issue615 230 } 231 // Fail if we're trying to transfer more than the available balance 232 if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { 233 return nil, gas, ErrInsufficientBalance // TODO-Klaytn-Issue615 234 } 235 236 var ( 237 to = AccountRef(addr) 238 snapshot = evm.StateDB.Snapshot() 239 debug = evm.Config.Debug 240 ) 241 242 // Filter out invalid precompiled address calls, and create a precompiled contract object if it is not exist. 243 if common.IsPrecompiledContractAddress(addr) { 244 precompiles := evm.GetPrecompiledContractMap(caller.Address()) 245 if precompiles[addr] == nil || value.Sign() != 0 { 246 // Return an error if an enabled precompiled address is called or a value is transferred to a precompiled address. 247 if debug { 248 if evm.depth == 0 { 249 evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) 250 evm.Config.Tracer.CaptureEnd(ret, 0, nil) 251 } else { 252 evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) 253 evm.Config.Tracer.CaptureExit(ret, 0, nil) 254 } 255 } 256 return nil, gas, kerrors.ErrPrecompiledContractAddress 257 } 258 // create an account object of the enabled precompiled address if not exist. 259 if !evm.StateDB.Exist(addr) { 260 evm.StateDB.CreateSmartContractAccount(addr, params.CodeFormatEVM, evm.chainRules) 261 } 262 } 263 264 // The logic below creates an EOA account if not exist. 265 // However, it does not create a contract account since `Call` is not proper method to create a contract. 266 if !evm.StateDB.Exist(addr) { 267 if value.Sign() == 0 { 268 // Calling a non-existing account (probably contract), don't do anything, but ping the tracer 269 if debug { 270 if evm.depth == 0 { 271 evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) 272 evm.Config.Tracer.CaptureEnd(ret, 0, nil) 273 } else { 274 evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) 275 evm.Config.Tracer.CaptureExit(ret, 0, nil) 276 } 277 } 278 return nil, gas, nil 279 } 280 // If non-existing address is called with a value, an object of the address is created. 281 evm.StateDB.CreateEOA(addr, false, accountkey.NewAccountKeyLegacy()) 282 } 283 evm.Context.Transfer(evm.StateDB, caller.Address(), to.Address(), value) 284 285 if debug { 286 if evm.depth == 0 { 287 evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) 288 defer func(startGas uint64) { // Lazy evaluation of the parameters 289 evm.Config.Tracer.CaptureEnd(ret, startGas-gas, err) 290 }(gas) 291 } else { 292 // Handle tracer events for entering and exiting a call frame 293 evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) 294 defer func(startGas uint64) { 295 evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) 296 }(gas) 297 } 298 } 299 300 if isProgramAccount(evm, caller.Address(), addr, evm.StateDB) { 301 // Initialise a new contract and set the code that is to be used by the EVM. 302 // The contract is a scoped environment for this execution context only. 303 contract := NewContract(caller, to, value, gas) 304 contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 305 ret, err = run(evm, contract, input) 306 gas = contract.Gas 307 } 308 309 // When an error was returned by the EVM or when setting the creation code 310 // above we revert to the snapshot and consume any gas remaining. Additionally 311 // when we're in homestead this also counts for code storage gas errors. 312 if err != nil { 313 evm.StateDB.RevertToSnapshot(snapshot) 314 if err != ErrExecutionReverted { 315 gas = 0 316 } 317 } 318 319 return ret, gas, err 320 } 321 322 // CallCode executes the contract associated with the addr with the given input 323 // as parameters. It also handles any necessary value transfer required and takes 324 // the necessary steps to create accounts and reverses the state in case of an 325 // execution error or failed value transfer. 326 // 327 // CallCode differs from Call in the sense that it executes the given address' 328 // code with the caller as context. 329 func (evm *EVM) CallCode(caller types.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { 330 if evm.Config.NoRecursion && evm.depth > 0 { 331 return nil, gas, nil 332 } 333 334 // Fail if we're trying to execute above the call depth limit 335 if evm.depth > int(params.CallCreateDepth) { 336 return nil, gas, ErrDepth // TODO-Klaytn-Issue615 337 } 338 // Note although it's noop to transfer X ether to caller itself. But 339 // if caller doesn't have enough balance, it would be an error to allow 340 // over-charging itself. So the check here is necessary. 341 if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { 342 return nil, gas, ErrInsufficientBalance // TODO-Klaytn-Issue615 343 } 344 345 if !isProgramAccount(evm, caller.Address(), addr, evm.StateDB) { 346 logger.Debug("Returning since the addr is not a program account", "addr", addr) 347 return nil, gas, nil 348 } 349 350 var ( 351 snapshot = evm.StateDB.Snapshot() 352 to = AccountRef(caller.Address()) 353 ) 354 355 // Invoke tracer hooks that signal entering/exiting a call frame 356 if evm.Config.Debug { 357 evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value) 358 defer func(startGas uint64) { 359 evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) 360 }(gas) 361 } 362 363 // Initialise a new contract and set the code that is to be used by the EVM. 364 // The contract is a scoped environment for this execution context only. 365 contract := NewContract(caller, to, value, gas) 366 contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 367 368 ret, err = run(evm, contract, input) 369 if err != nil { 370 evm.StateDB.RevertToSnapshot(snapshot) 371 if err != ErrExecutionReverted { 372 contract.UseGas(contract.Gas) 373 } 374 } 375 return ret, contract.Gas, err 376 } 377 378 // DelegateCall executes the contract associated with the addr with the given input 379 // as parameters. It reverses the state in case of an execution error. 380 // 381 // DelegateCall differs from CallCode in the sense that it executes the given address' 382 // code with the caller as context and the caller is set to the caller of the caller. 383 func (evm *EVM) DelegateCall(caller types.ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { 384 if evm.Config.NoRecursion && evm.depth > 0 { 385 return nil, gas, nil 386 } 387 // Fail if we're trying to execute above the call depth limit 388 if evm.depth > int(params.CallCreateDepth) { 389 return nil, gas, ErrDepth // TODO-Klaytn-Issue615 390 } 391 392 if !isProgramAccount(evm, caller.Address(), addr, evm.StateDB) { 393 logger.Debug("Returning since the addr is not a program account", "addr", addr) 394 return nil, gas, nil 395 } 396 397 var ( 398 snapshot = evm.StateDB.Snapshot() 399 to = AccountRef(caller.Address()) 400 ) 401 402 // Invoke tracer hooks that signal entering/exiting a call frame 403 if evm.Config.Debug { 404 // NOTE: caller must, at all times be a contract. It should never happen 405 // that caller is something other than a Contract. 406 parent := caller.(*Contract) 407 // DELEGATECALL inherits value from parent call 408 evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, parent.value) 409 defer func(startGas uint64) { 410 evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) 411 }(gas) 412 } 413 414 // Initialise a new contract and make initialise the delegate values 415 contract := NewContract(caller, to, nil, gas).AsDelegate() 416 contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 417 418 ret, err = run(evm, contract, input) 419 if err != nil { 420 evm.StateDB.RevertToSnapshot(snapshot) 421 if err != ErrExecutionReverted { 422 contract.UseGas(contract.Gas) 423 } 424 } 425 return ret, contract.Gas, err 426 } 427 428 // StaticCall executes the contract associated with the addr with the given input 429 // as parameters while disallowing any modifications to the state during the call. 430 // Opcodes that attempt to perform such modifications will result in exceptions 431 // instead of performing the modifications. 432 func (evm *EVM) StaticCall(caller types.ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { 433 if evm.Config.NoRecursion && evm.depth > 0 { 434 return nil, gas, nil 435 } 436 // Fail if we're trying to execute above the call depth limit 437 if evm.depth > int(params.CallCreateDepth) { 438 return nil, gas, ErrDepth // TODO-Klaytn-Issue615 439 } 440 // Make sure the readonly is only set if we aren't in readonly yet 441 // this makes also sure that the readonly flag isn't removed for 442 // child calls. 443 if !evm.interpreter.readOnly { 444 evm.interpreter.readOnly = true 445 defer func() { evm.interpreter.readOnly = false }() 446 } 447 448 if !isProgramAccount(evm, caller.Address(), addr, evm.StateDB) { 449 logger.Debug("Returning since the addr is not a program account", "addr", addr) 450 return nil, gas, nil 451 } 452 453 var ( 454 to = AccountRef(addr) 455 snapshot = evm.StateDB.Snapshot() 456 ) 457 458 // Invoke tracer hooks that signal entering/exiting a call frame 459 if evm.Config.Debug { 460 evm.Config.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil) 461 defer func(startGas uint64) { 462 evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) 463 }(gas) 464 } 465 466 // Initialise a new contract and set the code that is to be used by the EVM. 467 // The contract is a scoped environment for this execution context only. 468 contract := NewContract(caller, to, new(big.Int), gas) 469 contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 470 471 // When an error was returned by the EVM or when setting the creation code 472 // above we revert to the snapshot and consume any gas remaining. Additionally 473 // when we're in Homestead this also counts for code storage gas errors. 474 ret, err = run(evm, contract, input) 475 if err != nil { 476 evm.StateDB.RevertToSnapshot(snapshot) 477 if err != ErrExecutionReverted { 478 contract.UseGas(contract.Gas) 479 } 480 } 481 return ret, contract.Gas, err 482 } 483 484 type codeAndHash struct { 485 code []byte 486 hash common.Hash 487 } 488 489 func (c *codeAndHash) Hash() common.Hash { 490 if c.hash == (common.Hash{}) { 491 c.hash = crypto.Keccak256Hash(c.code) 492 } 493 return c.hash 494 } 495 496 // Create creates a new contract using code as deployment code. 497 func (evm *EVM) create(caller types.ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, typ OpCode, humanReadable bool, codeFormat params.CodeFormat) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { 498 // Depth check execution. Fail if we're trying to execute above the 499 // limit. 500 if evm.depth > int(params.CallCreateDepth) { 501 return nil, common.Address{}, gas, ErrDepth // TODO-Klaytn-Issue615 502 } 503 if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { 504 return nil, common.Address{}, gas, ErrInsufficientBalance // TODO-Klaytn-Issue615 505 } 506 507 // Increasing nonce since a failed tx with one of following error will be loaded on a block. 508 evm.StateDB.IncNonce(caller.Address()) 509 510 // We add this to the access list _before_ taking a snapshot. Even if the creation fails, 511 // the access-list change should not be rolled back 512 if evm.chainRules.IsKore { 513 evm.StateDB.AddAddressToAccessList(address) 514 } 515 516 // Ensure there's no existing contract already at the designated address 517 contractHash := evm.StateDB.GetCodeHash(address) 518 519 // The early Klaytn design tried to support the account creation with a user selected address, 520 // so the account overwriting was restricted. 521 // Because the feature was postponed for a long time and the restriction can be abused to prevent SCA creation, 522 // Klaytn enables SCA overwriting over EOA like Ethereum after Shanghai compatible hardfork. 523 // NOTE: The following code should be re-considered when Klaytn enables TxTypeAccountCreation 524 if evm.chainRules.IsShanghai { 525 if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) { 526 return nil, common.Address{}, 0, ErrContractAddressCollision 527 } 528 } else if evm.StateDB.Exist(address) { 529 return nil, common.Address{}, 0, ErrContractAddressCollision 530 } 531 532 if common.IsPrecompiledContractAddress(address) { 533 return nil, common.Address{}, gas, kerrors.ErrPrecompiledContractAddress 534 } 535 536 // Create a new account on the state 537 snapshot := evm.StateDB.Snapshot() 538 // TODO-Klaytn-Accounts: for now, smart contract accounts cannot withdraw KLAYs via ValueTransfer 539 // because the account key is set to AccountKeyFail by default. 540 // Need to make a decision of the key type. 541 evm.StateDB.CreateSmartContractAccountWithKey(address, humanReadable, accountkey.NewAccountKeyFail(), codeFormat, evm.chainRules) 542 evm.StateDB.SetNonce(address, 1) 543 if value.Sign() != 0 { 544 evm.Context.Transfer(evm.StateDB, caller.Address(), address, value) 545 } 546 // Initialise a new contract and set the code that is to be used by the EVM. 547 // The contract is a scoped environment for this execution context only. 548 contract := NewContract(caller, AccountRef(address), value, gas) 549 contract.SetCodeOptionalHash(&address, codeAndHash) 550 551 if evm.Config.NoRecursion && evm.depth > 0 { 552 return nil, address, gas, nil 553 } 554 555 if evm.Config.Debug { 556 if evm.depth == 0 { 557 evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value) 558 } else { 559 evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value) 560 } 561 } 562 563 ret, err = evm.interpreter.Run(contract, nil) 564 565 // check whether the max code size has been exceeded 566 maxCodeSizeExceeded := len(ret) > params.MaxCodeSize 567 // if the contract creation ran successfully and no errors were returned 568 // calculate the gas required to store the code. If the code could not 569 // be stored due to not enough gas set an error and let it be handled 570 // by the error checking condition below. 571 if err == nil && !maxCodeSizeExceeded { 572 createDataGas := uint64(len(ret)) * params.CreateDataGas 573 if contract.UseGas(createDataGas) { 574 if evm.StateDB.SetCode(address, ret) != nil { 575 // `err` is returned to `vmerr` in `StateTransition.TransitionDb()`. 576 // Then, `vmerr` will be used to make a receipt status using `getReceiptStatusFromVMerr()`. 577 // Since `getReceiptStatusFromVMerr()` uses a map to determine the receipt status, 578 // this `err` should be an error variable declared in vm/errors.go. 579 // TODO-Klaytn: Make a package of error variables containing all exported error variables. 580 // After the above TODO-Klaytn is resolved, we can return the error returned by `SetCode()` directly. 581 err = ErrFailedOnSetCode 582 } 583 } else { 584 err = ErrCodeStoreOutOfGas // TODO-Klaytn-Issue615 585 } 586 } 587 588 // When an error was returned by the EVM or when setting the creation code 589 // above we revert to the snapshot and consume any gas remaining. 590 if maxCodeSizeExceeded || err != nil { 591 evm.StateDB.RevertToSnapshot(snapshot) 592 if err != ErrExecutionReverted { 593 contract.UseGas(contract.Gas) 594 } 595 } 596 // Assign err if contract code size exceeds the max while the err is still empty. 597 if maxCodeSizeExceeded && err == nil { 598 err = ErrMaxCodeSizeExceeded // TODO-Klaytn-Issue615 599 } 600 601 // Reject code starting with 0xEF if EIP-3541 is enabled. 602 if err == nil && len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsKore { 603 err = ErrInvalidCode 604 } 605 606 if evm.Config.Debug { 607 if evm.depth == 0 { 608 evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, err) 609 } else { 610 evm.Config.Tracer.CaptureExit(ret, gas-contract.Gas, err) 611 } 612 } 613 614 return ret, address, contract.Gas, err 615 } 616 617 // Create creates a new contract using code as deployment code. 618 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) { 619 codeAndHash := &codeAndHash{code: code} 620 contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) 621 return evm.create(caller, codeAndHash, gas, value, contractAddr, CREATE, false, codeFormat) 622 } 623 624 // Create2 creates a new contract using code as deployment code. 625 // 626 // The different between Create2 with Create is Create2 uses sha3(0xff ++ msg.sender ++ salt ++ sha3(init_code))[12:] 627 // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. 628 func (evm *EVM) Create2(caller types.ContractRef, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int, codeFormat params.CodeFormat) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { 629 codeAndHash := &codeAndHash{code: code} 630 contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes()) 631 return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2, false, codeFormat) 632 } 633 634 // CreateWithAddress creates a new contract using code as deployment code with given address and humanReadable. 635 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) { 636 codeAndHash := &codeAndHash{code: code} 637 codeAndHash.Hash() 638 return evm.create(caller, codeAndHash, gas, value, contractAddr, CREATE, humanReadable, codeFormat) 639 } 640 641 func (evm *EVM) GetPrecompiledContractMap(addr common.Address) map[common.Address]PrecompiledContract { 642 // VmVersion means that the contract uses the precompiled contract map at the deployment time. 643 // Also, it follows old map's gas price & computation cost. 644 645 // Get vmVersion from addr only if the addr is a contract address. 646 // If new "VmVersion" is added, add new if clause below 647 if vmVersion, ok := evm.StateDB.GetVmVersion(addr); ok && vmVersion == params.VmVersion0 { 648 // Without VmVersion0, precompiled contract address 0x09-0x0b won't work properly 649 // with the contracts deployed before istanbulHF 650 return PrecompiledContractsByzantium 651 } 652 653 switch { 654 case evm.chainRules.IsCancun: 655 return PrecompiledContractsCancun 656 case evm.chainRules.IsKore: 657 return PrecompiledContractsKore 658 case evm.chainRules.IsIstanbul: 659 return PrecompiledContractsIstanbul 660 default: 661 return PrecompiledContractsByzantium 662 } 663 } 664 665 // ChainConfig returns the environment's chain configuration 666 func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } 667 668 // Interpreter returns the EVM interpreter 669 func (evm *EVM) Interpreter() *EVMInterpreter { return evm.interpreter } 670 671 func (evm *EVM) GetOpCodeComputationCost() uint64 { return evm.opcodeComputationCostSum }