github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/core/vm/evm.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package vm 18 19 import ( 20 "encoding/binary" 21 "math/big" 22 "sync/atomic" 23 "time" 24 25 abipkg "github.com/ethereum/go-ethereum/accounts/abi" 26 "github.com/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/common/hexutil" 28 "github.com/ethereum/go-ethereum/consensus" 29 "github.com/ethereum/go-ethereum/contract_comm/errors" 30 "github.com/ethereum/go-ethereum/core/types" 31 "github.com/ethereum/go-ethereum/crypto" 32 "github.com/ethereum/go-ethereum/log" 33 "github.com/ethereum/go-ethereum/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 // systemCaller is the caller when the EVM is invoked from the within the blockchain system. 41 var systemCaller = AccountRef(common.HexToAddress("0x0")) 42 43 type ( 44 // CanTransferFunc is the signature of a transfer guard function 45 CanTransferFunc func(StateDB, common.Address, *big.Int) bool 46 // TransferFunc is the signature of a transfer function 47 TransferFunc func(StateDB, common.Address, common.Address, *big.Int) 48 // GetHashFunc returns the nth block hash in the blockchain 49 // and is used by the BLOCKHASH EVM op code. 50 GetHashFunc func(uint64) common.Hash 51 // GetHeaderByNumber returns the header of the nth block in the chain. 52 GetHeaderByNumberFunc func(uint64) *types.Header 53 // VerifySealFunc returns true if the given header contains a valid seal 54 // according to the engine's consensus rules. 55 VerifySealFunc func(*types.Header) bool 56 ) 57 58 // run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter. 59 func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) { 60 if contract.CodeAddr != nil { 61 precompiles := PrecompiledContractsHomestead 62 if evm.ChainConfig().IsByzantium(evm.BlockNumber) { 63 precompiles = PrecompiledContractsByzantium 64 } 65 if p := precompiles[*contract.CodeAddr]; p != nil { 66 return RunPrecompiledContract(p, input, contract, evm) 67 } 68 } 69 for _, interpreter := range evm.interpreters { 70 if interpreter.CanRun(contract.Code) { 71 if evm.interpreter != interpreter { 72 // Ensure that the interpreter pointer is set back 73 // to its current value upon return. 74 defer func(i Interpreter) { 75 evm.interpreter = i 76 }(evm.interpreter) 77 evm.interpreter = interpreter 78 } 79 return interpreter.Run(contract, input, readOnly) 80 } 81 } 82 return nil, ErrNoCompatibleInterpreter 83 } 84 85 // Context provides the EVM with auxiliary information. Once provided 86 // it shouldn't be modified. 87 type Context struct { 88 // CanTransfer returns whether the account contains 89 // sufficient ether to transfer the value 90 CanTransfer CanTransferFunc 91 // Transfer transfers ether from one account to the other 92 Transfer TransferFunc 93 // GetHash returns the hash corresponding to n 94 GetHash GetHashFunc 95 // GetParentSealBitmap returns the parent seal bitmap corresponding to n 96 GetHeaderByNumber GetHeaderByNumberFunc 97 // VerifySeal verifies or returns an error for the given header 98 VerifySeal VerifySealFunc 99 100 // Message information 101 Origin common.Address // Provides information for ORIGIN 102 GasPrice *big.Int // Provides information for GASPRICE 103 104 // Block information 105 Coinbase common.Address // Provides information for COINBASE 106 GasLimit uint64 // Provides information for GASLIMIT 107 BlockNumber *big.Int // Provides information for NUMBER 108 Time *big.Int // Provides information for TIME 109 Difficulty *big.Int // Provides information for DIFFICULTY 110 111 Header *types.Header 112 113 Engine consensus.Engine 114 } 115 116 // EVM is the Ethereum Virtual Machine base object and provides 117 // the necessary tools to run a contract on the given state with 118 // the provided context. It should be noted that any error 119 // generated through any of the calls should be considered a 120 // revert-state-and-consume-all-gas operation, no checks on 121 // specific errors should ever be performed. The interpreter makes 122 // sure that any errors generated are to be considered faulty code. 123 // 124 // The EVM should never be reused and is not thread safe. 125 type EVM struct { 126 // Context provides auxiliary blockchain related information 127 Context 128 // StateDB gives access to the underlying state 129 StateDB StateDB 130 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 interpreters []Interpreter 144 interpreter Interpreter 145 // abort is used to abort the EVM calling operations 146 // NOTE: must be set atomically 147 abort int32 148 // callGasTemp holds the gas available for the current call. This is needed because the 149 // available gas is calculated in gasCall* according to the 63/64 rule and later 150 // applied in opCall*. 151 callGasTemp uint64 152 153 DontMeterGas bool 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 interpreters: make([]Interpreter, 0, 1), 166 DontMeterGas: false, 167 } 168 169 if chainConfig.IsEWASM(ctx.BlockNumber) { 170 // to be implemented by EVM-C and Wagon PRs. 171 // if vmConfig.EWASMInterpreter != "" { 172 // extIntOpts := strings.Split(vmConfig.EWASMInterpreter, ":") 173 // path := extIntOpts[0] 174 // options := []string{} 175 // if len(extIntOpts) > 1 { 176 // options = extIntOpts[1..] 177 // } 178 // evm.interpreters = append(evm.interpreters, NewEVMVCInterpreter(evm, vmConfig, options)) 179 // } else { 180 // evm.interpreters = append(evm.interpreters, NewEWASMInterpreter(evm, vmConfig)) 181 // } 182 panic("No supported ewasm interpreter yet.") 183 } 184 185 // vmConfig.EVMInterpreter will be used by EVM-C, it won't be checked here 186 // as we always want to have the built-in EVM as the failover option. 187 evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig)) 188 evm.interpreter = evm.interpreters[0] 189 190 return evm 191 } 192 193 // Cancel cancels any running EVM operation. This may be called concurrently and 194 // it's safe to be called multiple times. 195 func (evm *EVM) Cancel() { 196 atomic.StoreInt32(&evm.abort, 1) 197 } 198 199 // Interpreter returns the current interpreter 200 func (evm *EVM) Interpreter() Interpreter { 201 return evm.interpreter 202 } 203 204 func (evm *EVM) GetStateDB() StateDB { 205 return evm.StateDB 206 } 207 208 func (evm *EVM) GetHeader() *types.Header { 209 return evm.Context.Header 210 } 211 212 // Call executes the contract associated with the addr with the given input as 213 // parameters. It also handles any necessary value transfer required and takes 214 // the necessary steps to create accounts and reverses the state in case of an 215 // execution error or failed value transfer. 216 func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { 217 if evm.vmConfig.NoRecursion && evm.depth > 0 { 218 return nil, gas, nil 219 } 220 221 // Fail if we're trying to execute above the call depth limit 222 if evm.depth > int(params.CallCreateDepth) { 223 return nil, gas, ErrDepth 224 } 225 // Fail if we're trying to transfer more than the available balance 226 if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { 227 return nil, gas, ErrInsufficientBalance 228 } 229 230 var ( 231 to = AccountRef(addr) 232 snapshot = evm.StateDB.Snapshot() 233 ) 234 if !evm.StateDB.Exist(addr) { 235 precompiles := PrecompiledContractsHomestead 236 if evm.ChainConfig().IsByzantium(evm.BlockNumber) { 237 precompiles = PrecompiledContractsByzantium 238 } 239 if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 { 240 // Calling a non existing account, don't do anything, but ping the tracer 241 if evm.vmConfig.Debug && evm.depth == 0 { 242 evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) 243 evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil) 244 } 245 return nil, gas, nil 246 } 247 evm.StateDB.CreateAccount(addr) 248 } 249 gas, err = evm.TobinTransfer(evm.StateDB, caller.Address(), to.Address(), gas, value) 250 if err != nil { 251 log.Error("Failed to transfer with tobin tax", "err", err) 252 return nil, gas, err 253 } 254 // Initialise a new contract and set the code that is to be used by the EVM. 255 // The contract is a scoped environment for this execution context only. 256 contract := NewContract(caller, to, value, gas) 257 contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 258 259 // Even if the account has no code, we need to continue because it might be a precompile 260 start := time.Now() 261 262 // Capture the tracer start/end events in debug mode 263 if evm.vmConfig.Debug && evm.depth == 0 { 264 evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) 265 266 defer func() { // Lazy evaluation of the parameters 267 evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) 268 }() 269 } 270 ret, err = run(evm, contract, input, false) 271 272 // When an error was returned by the EVM or when setting the creation code 273 // above we revert to the snapshot and consume any gas remaining. Additionally 274 // when we're in homestead this also counts for code storage gas errors. 275 if err != nil { 276 evm.StateDB.RevertToSnapshot(snapshot) 277 if err != errExecutionReverted { 278 contract.UseGas(contract.Gas) 279 } 280 } 281 return ret, contract.Gas, err 282 } 283 284 // CallCode executes the contract associated with the addr with the given input 285 // as parameters. It also handles any necessary value transfer required and takes 286 // the necessary steps to create accounts and reverses the state in case of an 287 // execution error or failed value transfer. 288 // 289 // CallCode differs from Call in the sense that it executes the given address' 290 // code with the caller as context. 291 func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { 292 if evm.vmConfig.NoRecursion && evm.depth > 0 { 293 return nil, gas, nil 294 } 295 296 // Fail if we're trying to execute above the call depth limit 297 if evm.depth > int(params.CallCreateDepth) { 298 return nil, gas, ErrDepth 299 } 300 // Fail if we're trying to transfer more than the available balance 301 if !evm.CanTransfer(evm.StateDB, caller.Address(), value) { 302 return nil, gas, ErrInsufficientBalance 303 } 304 305 var ( 306 snapshot = evm.StateDB.Snapshot() 307 to = AccountRef(caller.Address()) 308 ) 309 // initialise a new contract and set the code that is to be used by the 310 // EVM. The contract is a scoped environment for this execution context 311 // only. 312 contract := NewContract(caller, to, value, gas) 313 contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 314 315 ret, err = run(evm, contract, input, false) 316 if err != nil { 317 evm.StateDB.RevertToSnapshot(snapshot) 318 if err != errExecutionReverted { 319 contract.UseGas(contract.Gas) 320 } 321 } 322 return ret, contract.Gas, err 323 } 324 325 // DelegateCall executes the contract associated with the addr with the given input 326 // as parameters. It reverses the state in case of an execution error. 327 // 328 // DelegateCall differs from CallCode in the sense that it executes the given address' 329 // code with the caller as context and the caller is set to the caller of the caller. 330 func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { 331 if evm.vmConfig.NoRecursion && evm.depth > 0 { 332 return nil, gas, nil 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 337 } 338 339 var ( 340 snapshot = evm.StateDB.Snapshot() 341 to = AccountRef(caller.Address()) 342 ) 343 344 // Initialise a new contract and make initialise the delegate values 345 contract := NewContract(caller, to, nil, gas).AsDelegate() 346 contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 347 348 ret, err = run(evm, contract, input, false) 349 if err != nil { 350 evm.StateDB.RevertToSnapshot(snapshot) 351 if err != errExecutionReverted { 352 contract.UseGas(contract.Gas) 353 } 354 } 355 return ret, contract.Gas, err 356 } 357 358 // StaticCall executes the contract associated with the addr with the given input 359 // as parameters while disallowing any modifications to the state during the call. 360 // Opcodes that attempt to perform such modifications will result in exceptions 361 // instead of performing the modifications. 362 func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { 363 if evm.vmConfig.NoRecursion && evm.depth > 0 { 364 return nil, gas, nil 365 } 366 // Fail if we're trying to execute above the call depth limit 367 if evm.depth > int(params.CallCreateDepth) { 368 return nil, gas, ErrDepth 369 } 370 371 var ( 372 to = AccountRef(addr) 373 snapshot = evm.StateDB.Snapshot() 374 ) 375 // Initialise a new contract and set the code that is to be used by the 376 // EVM. The contract is a scoped environment for this execution context 377 // only. 378 contract := NewContract(caller, to, new(big.Int), gas) 379 contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) 380 381 // We do an AddBalance of zero here, just in order to trigger a touch. 382 // This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium, 383 // but is the correct thing to do and matters on other networks, in tests, and potential 384 // future scenarios 385 evm.StateDB.AddBalance(addr, bigZero) 386 387 // When an error was returned by the EVM or when setting the creation code 388 // above we revert to the snapshot and consume any gas remaining. Additionally 389 // when we're in Homestead this also counts for code storage gas errors. 390 ret, err = run(evm, contract, input, true) 391 if err != nil { 392 evm.StateDB.RevertToSnapshot(snapshot) 393 if err != errExecutionReverted { 394 contract.UseGas(contract.Gas) 395 } 396 } 397 return ret, contract.Gas, err 398 } 399 400 type codeAndHash struct { 401 code []byte 402 hash common.Hash 403 } 404 405 func (c *codeAndHash) Hash() common.Hash { 406 if c.hash == (common.Hash{}) { 407 c.hash = crypto.Keccak256Hash(c.code) 408 } 409 return c.hash 410 } 411 412 // create creates a new contract using code as deployment code. 413 func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) { 414 // Depth check execution. Fail if we're trying to execute above the 415 // limit. 416 if evm.depth > int(params.CallCreateDepth) { 417 return nil, common.Address{}, gas, ErrDepth 418 } 419 if !evm.CanTransfer(evm.StateDB, caller.Address(), value) { 420 return nil, common.Address{}, gas, ErrInsufficientBalance 421 } 422 nonce := evm.StateDB.GetNonce(caller.Address()) 423 evm.StateDB.SetNonce(caller.Address(), nonce+1) 424 425 // Ensure there's no existing contract already at the designated address 426 contractHash := evm.StateDB.GetCodeHash(address) 427 if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) { 428 return nil, common.Address{}, 0, ErrContractAddressCollision 429 } 430 // Create a new account on the state 431 snapshot := evm.StateDB.Snapshot() 432 evm.StateDB.CreateAccount(address) 433 if evm.ChainConfig().IsEIP158(evm.BlockNumber) { 434 evm.StateDB.SetNonce(address, 1) 435 } 436 gas, err := evm.TobinTransfer(evm.StateDB, caller.Address(), address, gas, value) 437 if err != nil { 438 log.Error("Failed to transfer with tobin tax", "err", err) 439 return nil, address, gas, err 440 } 441 442 // initialise a new contract and set the code that is to be used by the 443 // EVM. The contract is a scoped environment for this execution context 444 // only. 445 contract := NewContract(caller, AccountRef(address), value, gas) 446 contract.SetCodeOptionalHash(&address, codeAndHash) 447 448 if evm.vmConfig.NoRecursion && evm.depth > 0 { 449 return nil, address, gas, nil 450 } 451 452 if evm.vmConfig.Debug && evm.depth == 0 { 453 evm.vmConfig.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.code, gas, value) 454 } 455 start := time.Now() 456 457 ret, err := run(evm, contract, nil, false) 458 459 // check whether the max code size has been exceeded 460 maxCodeSizeExceeded := evm.ChainConfig().IsEIP158(evm.BlockNumber) && len(ret) > params.MaxCodeSize 461 // if the contract creation ran successfully and no errors were returned 462 // calculate the gas required to store the code. If the code could not 463 // be stored due to not enough gas set an error and let it be handled 464 // by the error checking condition below. 465 if err == nil && !maxCodeSizeExceeded { 466 createDataGas := uint64(len(ret)) * params.CreateDataGas 467 if contract.UseGas(createDataGas) { 468 evm.StateDB.SetCode(address, ret) 469 } else { 470 err = ErrCodeStoreOutOfGas 471 } 472 } 473 474 // When an error was returned by the EVM or when setting the creation code 475 // above we revert to the snapshot and consume any gas remaining. Additionally 476 // when we're in homestead this also counts for code storage gas errors. 477 if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) { 478 evm.StateDB.RevertToSnapshot(snapshot) 479 if err != errExecutionReverted { 480 contract.UseGas(contract.Gas) 481 } 482 } 483 // Assign err if contract code size exceeds the max while the err is still empty. 484 if maxCodeSizeExceeded && err == nil { 485 err = errMaxCodeSizeExceeded 486 } 487 if evm.vmConfig.Debug && evm.depth == 0 { 488 evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) 489 } 490 return ret, address, contract.Gas, err 491 492 } 493 494 // Create creates a new contract using code as deployment code. 495 func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { 496 contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) 497 return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr) 498 } 499 500 // Create2 creates a new contract using code as deployment code. 501 // 502 // The different between Create2 with Create is Create2 uses sha3(0xff ++ msg.sender ++ salt ++ sha3(init_code))[12:] 503 // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. 504 func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { 505 codeAndHash := &codeAndHash{code: code} 506 contractAddr = crypto.CreateAddress2(caller.Address(), common.BigToHash(salt), codeAndHash.Hash().Bytes()) 507 return evm.create(caller, codeAndHash, gas, endowment, contractAddr) 508 } 509 510 // ChainConfig returns the environment's chain configuration 511 func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } 512 513 // TobinTransfer performs a transfer that may take a tax from the sent amount and give it to the reserve. 514 // If the calculation or transfer of the tax amount fails for any reason, the regular transfer goes ahead. 515 // NB: Gas is not charged or accounted for this calculation. 516 func (evm *EVM) TobinTransfer(db StateDB, sender, recipient common.Address, gas uint64, amount *big.Int) (leftOverGas uint64, err error) { 517 518 if amount.Cmp(big.NewInt(0)) != 0 { 519 reserveAddress, err := GetRegisteredAddressWithEvm(params.ReserveRegistryId, evm) 520 if err != nil && err != errors.ErrSmartContractNotDeployed && err != errors.ErrRegistryContractNotDeployed { 521 log.Trace("TobinTransfer: Error fetching Reserve address", "error", err) 522 } 523 524 if err == nil { 525 ret, _, err := evm.Call(AccountRef(sender), *reserveAddress, params.TobinTaxFunctionSelector, params.MaxGasForGetOrComputeTobinTax, big.NewInt(0)) 526 if err != nil { 527 log.Trace("TobinTransfer: Error calling getOrComputeTobinTaxFunctionSelector", "error", err) 528 } 529 530 // Expected size of ret is 64 bytes because getOrComputeTobinTax() returns two uint256 values, 531 // each of which is equivalent to 32 bytes 532 if err == nil && binary.Size(ret) == 64 { 533 numerator := new(big.Int).SetBytes(ret[0:32]) 534 denominator := new(big.Int).SetBytes(ret[32:64]) 535 tobinTax := new(big.Int).Div(new(big.Int).Mul(numerator, amount), denominator) 536 537 evm.Context.Transfer(db, sender, recipient, new(big.Int).Sub(amount, tobinTax)) 538 evm.Context.Transfer(db, sender, *reserveAddress, tobinTax) 539 return gas, nil 540 } 541 } 542 } 543 544 // Complete a normal transfer if the amount is 0 or the tobin tax value is unable to be fetched and parsed. 545 // We transfer even when the amount is 0 because state trie clearing [EIP161] is necessary at the end of a transaction 546 evm.Context.Transfer(db, sender, recipient, amount) 547 return gas, nil 548 } 549 550 func (evm *EVM) StaticCallFromSystem(contractAddress common.Address, abi abipkg.ABI, funcName string, args []interface{}, returnObj interface{}, gas uint64) (uint64, error) { 551 staticCall := func(transactionData []byte) ([]byte, uint64, error) { 552 return evm.StaticCall(systemCaller, contractAddress, transactionData, gas) 553 } 554 555 return evm.handleABICall(abi, funcName, args, returnObj, staticCall) 556 } 557 558 func (evm *EVM) CallFromSystem(contractAddress common.Address, abi abipkg.ABI, funcName string, args []interface{}, returnObj interface{}, gas uint64, value *big.Int) (uint64, error) { 559 call := func(transactionData []byte) ([]byte, uint64, error) { 560 return evm.Call(systemCaller, contractAddress, transactionData, gas, value) 561 } 562 return evm.handleABICall(abi, funcName, args, returnObj, call) 563 } 564 565 func (evm *EVM) handleABICall(abi abipkg.ABI, funcName string, args []interface{}, returnObj interface{}, call func([]byte) ([]byte, uint64, error)) (uint64, error) { 566 transactionData, err := abi.Pack(funcName, args...) 567 if err != nil { 568 log.Error("Error in generating the ABI encoding for the function call", "err", err, "funcName", funcName, "args", args) 569 return 0, err 570 } 571 572 ret, leftoverGas, err := call(transactionData) 573 574 if err != nil { 575 log.Error("Error in calling the EVM", "funcName", funcName, "transactionData", hexutil.Encode(transactionData), "err", err) 576 return leftoverGas, err 577 } 578 579 log.Trace("EVM call successful", "funcName", funcName, "transactionData", hexutil.Encode(transactionData), "ret", hexutil.Encode(ret)) 580 581 if returnObj != nil { 582 if err := abi.Unpack(returnObj, funcName, ret); err != nil { 583 // `ErrEmptyOutput` is expected when when syncing & importing blocks 584 // before a contract has been deployed 585 if err == abipkg.ErrEmptyOutput { 586 log.Trace("Error in unpacking EVM call return bytes", "err", err) 587 } else { 588 log.Error("Error in unpacking EVM call return bytes", "err", err) 589 } 590 return leftoverGas, err 591 } 592 } 593 594 return leftoverGas, nil 595 }