github.com/MikyChow/arbitrum-go-ethereum@v0.0.0-20230306102812-078da49636de/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 "math/big" 21 "sync/atomic" 22 "time" 23 24 "github.com/holiman/uint256" 25 26 "github.com/MikyChow/arbitrum-go-ethereum/common" 27 "github.com/MikyChow/arbitrum-go-ethereum/crypto" 28 "github.com/MikyChow/arbitrum-go-ethereum/params" 29 ) 30 31 // emptyCodeHash is used by create to ensure deployment is disallowed to already 32 // deployed contract addresses (relevant after the account abstraction). 33 var emptyCodeHash = crypto.Keccak256Hash(nil) 34 35 type ( 36 // CanTransferFunc is the signature of a transfer guard function 37 CanTransferFunc func(StateDB, common.Address, *big.Int) bool 38 // TransferFunc is the signature of a transfer function 39 TransferFunc func(StateDB, common.Address, common.Address, *big.Int) 40 // GetHashFunc returns the n'th block hash in the blockchain 41 // and is used by the BLOCKHASH EVM op code. 42 GetHashFunc func(uint64) common.Hash 43 ) 44 45 func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { 46 var precompiles map[common.Address]PrecompiledContract 47 switch { 48 case evm.chainRules.IsArbitrum: 49 precompiles = PrecompiledContractsArbitrum 50 case evm.chainRules.IsBerlin: 51 precompiles = PrecompiledContractsBerlin 52 case evm.chainRules.IsIstanbul: 53 precompiles = PrecompiledContractsIstanbul 54 case evm.chainRules.IsByzantium: 55 precompiles = PrecompiledContractsByzantium 56 default: 57 precompiles = PrecompiledContractsHomestead 58 } 59 p, ok := precompiles[addr] 60 return p, ok 61 } 62 63 // BlockContext provides the EVM with auxiliary information. Once provided 64 // it shouldn't be modified. 65 type BlockContext struct { 66 // CanTransfer returns whether the account contains 67 // sufficient ether to transfer the value 68 CanTransfer CanTransferFunc 69 // Transfer transfers ether from one account to the other 70 Transfer TransferFunc 71 // GetHash returns the hash corresponding to n 72 GetHash GetHashFunc 73 74 // Block information 75 Coinbase common.Address // Provides information for COINBASE 76 GasLimit uint64 // Provides information for GASLIMIT 77 BlockNumber *big.Int // Provides information for NUMBER 78 Time *big.Int // Provides information for TIME 79 Difficulty *big.Int // Provides information for DIFFICULTY 80 BaseFee *big.Int // Provides information for BASEFEE 81 Random *common.Hash // Provides information for RANDOM 82 } 83 84 // TxContext provides the EVM with information about a transaction. 85 // All fields can change between transactions. 86 type TxContext struct { 87 // Message information 88 Origin common.Address // Provides information for ORIGIN 89 GasPrice *big.Int // Provides information for GASPRICE 90 } 91 92 // EVM is the Ethereum Virtual Machine base object and provides 93 // the necessary tools to run a contract on the given state with 94 // the provided context. It should be noted that any error 95 // generated through any of the calls should be considered a 96 // revert-state-and-consume-all-gas operation, no checks on 97 // specific errors should ever be performed. The interpreter makes 98 // sure that any errors generated are to be considered faulty code. 99 // 100 // The EVM should never be reused and is not thread safe. 101 type EVM struct { 102 ProcessingHook TxProcessingHook 103 104 // Context provides auxiliary blockchain related information 105 Context BlockContext 106 TxContext 107 // StateDB gives access to the underlying state 108 StateDB StateDB 109 // Depth is the current call stack 110 depth int 111 112 // chainConfig contains information about the current chain 113 chainConfig *params.ChainConfig 114 // chain rules contains the chain rules for the current epoch 115 chainRules params.Rules 116 // virtual machine configuration options used to initialise the 117 // evm. 118 Config Config 119 // global (to this context) ethereum virtual machine 120 // used throughout the execution of the tx. 121 interpreter *EVMInterpreter 122 // abort is used to abort the EVM calling operations 123 // NOTE: must be set atomically 124 abort int32 125 // callGasTemp holds the gas available for the current call. This is needed because the 126 // available gas is calculated in gasCall* according to the 63/64 rule and later 127 // applied in opCall*. 128 callGasTemp uint64 129 } 130 131 // NewEVM returns a new EVM. The returned EVM is not thread safe and should 132 // only ever be used *once*. 133 func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM { 134 evm := &EVM{ 135 Context: blockCtx, 136 TxContext: txCtx, 137 StateDB: statedb, 138 Config: config, 139 chainConfig: chainConfig, 140 chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil), 141 } 142 evm.ProcessingHook = DefaultTxProcessor{evm: evm} 143 evm.interpreter = NewEVMInterpreter(evm, config) 144 return evm 145 } 146 147 // Reset resets the EVM with a new transaction context.Reset 148 // This is not threadsafe and should only be done very cautiously. 149 func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) { 150 evm.TxContext = txCtx 151 evm.StateDB = statedb 152 } 153 154 // Cancel cancels any running EVM operation. This may be called concurrently and 155 // it's safe to be called multiple times. 156 func (evm *EVM) Cancel() { 157 atomic.StoreInt32(&evm.abort, 1) 158 } 159 160 // Cancelled returns true if Cancel has been called 161 func (evm *EVM) Cancelled() bool { 162 return atomic.LoadInt32(&evm.abort) == 1 163 } 164 165 // Interpreter returns the current interpreter 166 func (evm *EVM) Interpreter() *EVMInterpreter { 167 return evm.interpreter 168 } 169 170 // Call executes the contract associated with the addr with the given input as 171 // parameters. It also handles any necessary value transfer required and takes 172 // the necessary steps to create accounts and reverses the state in case of an 173 // execution error or failed value transfer. 174 func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { 175 // Fail if we're trying to execute above the call depth limit 176 if evm.depth > int(params.CallCreateDepth) { 177 return nil, gas, ErrDepth 178 } 179 // Fail if we're trying to transfer more than the available balance 180 if value.Sign() != 0 && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { 181 return nil, gas, ErrInsufficientBalance 182 } 183 snapshot := evm.StateDB.Snapshot() 184 p, isPrecompile := evm.precompile(addr) 185 186 if !evm.StateDB.Exist(addr) { 187 if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { 188 // Calling a non existing account, don't do anything, but ping the tracer 189 if evm.Config.Debug { 190 if evm.depth == 0 { 191 evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) 192 evm.Config.Tracer.CaptureEnd(ret, 0, 0, nil) 193 } else { 194 evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) 195 evm.Config.Tracer.CaptureExit(ret, 0, nil) 196 } 197 } 198 return nil, gas, nil 199 } 200 evm.StateDB.CreateAccount(addr) 201 } 202 evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value) 203 204 // Capture the tracer start/end events in debug mode 205 if evm.Config.Debug { 206 if evm.depth == 0 { 207 evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) 208 defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters 209 evm.Config.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err) 210 }(gas, time.Now()) 211 } else { 212 // Handle tracer events for entering and exiting a call frame 213 evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) 214 defer func(startGas uint64) { 215 evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) 216 }(gas) 217 } 218 } 219 220 if isPrecompile { 221 info := &AdvancedPrecompileCall{ 222 PrecompileAddress: addr, 223 ActingAsAddress: addr, 224 Caller: caller.Address(), 225 Value: value, 226 ReadOnly: false, 227 Evm: evm, 228 } 229 ret, gas, err = RunPrecompiledContract(p, input, gas, info) 230 } else { 231 // Initialise a new contract and set the code that is to be used by the EVM. 232 // The contract is a scoped environment for this execution context only. 233 code := evm.StateDB.GetCode(addr) 234 if len(code) == 0 { 235 ret, err = nil, nil // gas is unchanged 236 } else { 237 addrCopy := addr 238 // If the account has no code, we can abort here 239 // The depth-check is already done, and precompiles handled above 240 contract := NewContract(caller, AccountRef(addrCopy), value, gas) 241 contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), code) 242 ret, err = evm.interpreter.Run(contract, input, false) 243 gas = contract.Gas 244 } 245 } 246 // When an error was returned by the EVM or when setting the creation code 247 // above we revert to the snapshot and consume any gas remaining. Additionally 248 // when we're in homestead this also counts for code storage gas errors. 249 if err != nil { 250 evm.StateDB.RevertToSnapshot(snapshot) 251 if err != ErrExecutionReverted { 252 gas = 0 253 } 254 // TODO: consider clearing up unused snapshots: 255 //} else { 256 // evm.StateDB.DiscardSnapshot(snapshot) 257 } 258 return ret, gas, err 259 } 260 261 // CallCode executes the contract associated with the addr with the given input 262 // as parameters. It also handles any necessary value transfer required and takes 263 // the necessary steps to create accounts and reverses the state in case of an 264 // execution error or failed value transfer. 265 // 266 // CallCode differs from Call in the sense that it executes the given address' 267 // code with the caller as context. 268 func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { 269 // Fail if we're trying to execute above the call depth limit 270 if evm.depth > int(params.CallCreateDepth) { 271 return nil, gas, ErrDepth 272 } 273 // Fail if we're trying to transfer more than the available balance 274 // Note although it's noop to transfer X ether to caller itself. But 275 // if caller doesn't have enough balance, it would be an error to allow 276 // over-charging itself. So the check here is necessary. 277 if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { 278 return nil, gas, ErrInsufficientBalance 279 } 280 var snapshot = evm.StateDB.Snapshot() 281 282 // Invoke tracer hooks that signal entering/exiting a call frame 283 if evm.Config.Debug { 284 evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value) 285 defer func(startGas uint64) { 286 evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) 287 }(gas) 288 } 289 290 // It is allowed to call precompiles, even via delegatecall 291 if p, isPrecompile := evm.precompile(addr); isPrecompile { 292 info := &AdvancedPrecompileCall{ 293 PrecompileAddress: addr, 294 ActingAsAddress: caller.Address(), 295 Caller: caller.Address(), 296 Value: value, 297 ReadOnly: false, 298 Evm: evm, 299 } 300 ret, gas, err = RunPrecompiledContract(p, input, gas, info) 301 } else { 302 addrCopy := addr 303 // Initialise a new contract and set the code that is to be used by the EVM. 304 // The contract is a scoped environment for this execution context only. 305 contract := NewContract(caller, AccountRef(caller.Address()), value, gas) 306 contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) 307 ret, err = evm.interpreter.Run(contract, input, false) 308 gas = contract.Gas 309 } 310 if err != nil { 311 evm.StateDB.RevertToSnapshot(snapshot) 312 if err != ErrExecutionReverted { 313 gas = 0 314 } 315 } 316 return ret, gas, err 317 } 318 319 // DelegateCall executes the contract associated with the addr with the given input 320 // as parameters. It reverses the state in case of an execution error. 321 // 322 // DelegateCall differs from CallCode in the sense that it executes the given address' 323 // code with the caller as context and the caller is set to the caller of the caller. 324 func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { 325 // Fail if we're trying to execute above the call depth limit 326 if evm.depth > int(params.CallCreateDepth) { 327 return nil, gas, ErrDepth 328 } 329 var snapshot = evm.StateDB.Snapshot() 330 331 // Invoke tracer hooks that signal entering/exiting a call frame 332 if evm.Config.Debug { 333 evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, nil) 334 defer func(startGas uint64) { 335 evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) 336 }(gas) 337 } 338 339 // It is allowed to call precompiles, even via delegatecall 340 if p, isPrecompile := evm.precompile(addr); isPrecompile { 341 caller := caller.(*Contract) 342 info := &AdvancedPrecompileCall{ 343 PrecompileAddress: addr, 344 ActingAsAddress: caller.Address(), 345 Caller: caller.CallerAddress, 346 Value: caller.Value(), 347 ReadOnly: false, 348 Evm: evm, 349 } 350 ret, gas, err = RunPrecompiledContract(p, input, gas, info) 351 } else { 352 addrCopy := addr 353 // Initialise a new contract and make initialise the delegate values 354 contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate() 355 contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) 356 ret, err = evm.interpreter.Run(contract, input, false) 357 gas = contract.Gas 358 } 359 if err != nil { 360 evm.StateDB.RevertToSnapshot(snapshot) 361 if err != ErrExecutionReverted { 362 gas = 0 363 } 364 } 365 return ret, gas, err 366 } 367 368 // StaticCall executes the contract associated with the addr with the given input 369 // as parameters while disallowing any modifications to the state during the call. 370 // Opcodes that attempt to perform such modifications will result in exceptions 371 // instead of performing the modifications. 372 func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { 373 // Fail if we're trying to execute above the call depth limit 374 if evm.depth > int(params.CallCreateDepth) { 375 return nil, gas, ErrDepth 376 } 377 // We take a snapshot here. This is a bit counter-intuitive, and could probably be skipped. 378 // However, even a staticcall is considered a 'touch'. On mainnet, static calls were introduced 379 // after all empty accounts were deleted, so this is not required. However, if we omit this, 380 // then certain tests start failing; stRevertTest/RevertPrecompiledTouchExactOOG.json. 381 // We could change this, but for now it's left for legacy reasons 382 var snapshot = evm.StateDB.Snapshot() 383 384 // We do an AddBalance of zero here, just in order to trigger a touch. 385 // This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium, 386 // but is the correct thing to do and matters on other networks, in tests, and potential 387 // future scenarios 388 evm.StateDB.AddBalance(addr, big0) 389 390 // Invoke tracer hooks that signal entering/exiting a call frame 391 if evm.Config.Debug { 392 evm.Config.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil) 393 defer func(startGas uint64) { 394 evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) 395 }(gas) 396 } 397 398 if p, isPrecompile := evm.precompile(addr); isPrecompile { 399 info := &AdvancedPrecompileCall{ 400 PrecompileAddress: addr, 401 ActingAsAddress: addr, 402 Caller: caller.Address(), 403 Value: new(big.Int), 404 ReadOnly: true, 405 Evm: evm, 406 } 407 ret, gas, err = RunPrecompiledContract(p, input, gas, info) 408 } else { 409 // At this point, we use a copy of address. If we don't, the go compiler will 410 // leak the 'contract' to the outer scope, and make allocation for 'contract' 411 // even if the actual execution ends on RunPrecompiled above. 412 addrCopy := addr 413 // Initialise a new contract and set the code that is to be used by the EVM. 414 // The contract is a scoped environment for this execution context only. 415 contract := NewContract(caller, AccountRef(addrCopy), new(big.Int), gas) 416 contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) 417 // When an error was returned by the EVM or when setting the creation code 418 // above we revert to the snapshot and consume any gas remaining. Additionally 419 // when we're in Homestead this also counts for code storage gas errors. 420 ret, err = evm.interpreter.Run(contract, input, true) 421 gas = contract.Gas 422 } 423 if err != nil { 424 evm.StateDB.RevertToSnapshot(snapshot) 425 if err != ErrExecutionReverted { 426 gas = 0 427 } 428 } 429 return ret, gas, err 430 } 431 432 type codeAndHash struct { 433 code []byte 434 hash common.Hash 435 } 436 437 func (c *codeAndHash) Hash() common.Hash { 438 if c.hash == (common.Hash{}) { 439 c.hash = crypto.Keccak256Hash(c.code) 440 } 441 return c.hash 442 } 443 444 // create creates a new contract using code as deployment code. 445 func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, typ OpCode) ([]byte, common.Address, uint64, error) { 446 // Depth check execution. Fail if we're trying to execute above the 447 // limit. 448 if evm.depth > int(params.CallCreateDepth) { 449 return nil, common.Address{}, gas, ErrDepth 450 } 451 if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { 452 return nil, common.Address{}, gas, ErrInsufficientBalance 453 } 454 nonce := evm.StateDB.GetNonce(caller.Address()) 455 if nonce+1 < nonce { 456 return nil, common.Address{}, gas, ErrNonceUintOverflow 457 } 458 evm.StateDB.SetNonce(caller.Address(), nonce+1) 459 // We add this to the access list _before_ taking a snapshot. Even if the creation fails, 460 // the access-list change should not be rolled back 461 if evm.chainRules.IsBerlin { 462 evm.StateDB.AddAddressToAccessList(address) 463 } 464 // Ensure there's no existing contract already at the designated address 465 contractHash := evm.StateDB.GetCodeHash(address) 466 if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) { 467 return nil, common.Address{}, 0, ErrContractAddressCollision 468 } 469 // Create a new account on the state 470 snapshot := evm.StateDB.Snapshot() 471 evm.StateDB.CreateAccount(address) 472 if evm.chainRules.IsEIP158 { 473 evm.StateDB.SetNonce(address, 1) 474 } 475 evm.Context.Transfer(evm.StateDB, caller.Address(), address, value) 476 477 // Initialise a new contract and set the code that is to be used by the EVM. 478 // The contract is a scoped environment for this execution context only. 479 contract := NewContract(caller, AccountRef(address), value, gas) 480 contract.SetCodeOptionalHash(&address, codeAndHash) 481 482 if evm.Config.Debug { 483 if evm.depth == 0 { 484 evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value) 485 } else { 486 evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value) 487 } 488 } 489 490 start := time.Now() 491 492 ret, err := evm.interpreter.Run(contract, nil, false) 493 494 // Check whether the max code size has been exceeded, assign err if the case. 495 if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize { 496 err = ErrMaxCodeSizeExceeded 497 } 498 499 // Reject code starting with 0xEF if EIP-3541 is enabled. 500 if err == nil && len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsLondon { 501 err = ErrInvalidCode 502 } 503 504 // if the contract creation ran successfully and no errors were returned 505 // calculate the gas required to store the code. If the code could not 506 // be stored due to not enough gas set an error and let it be handled 507 // by the error checking condition below. 508 if err == nil { 509 createDataGas := uint64(len(ret)) * params.CreateDataGas 510 if contract.UseGas(createDataGas) { 511 evm.StateDB.SetCode(address, ret) 512 } else { 513 err = ErrCodeStoreOutOfGas 514 } 515 } 516 517 // When an error was returned by the EVM or when setting the creation code 518 // above we revert to the snapshot and consume any gas remaining. Additionally 519 // when we're in homestead this also counts for code storage gas errors. 520 if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) { 521 evm.StateDB.RevertToSnapshot(snapshot) 522 if err != ErrExecutionReverted { 523 contract.UseGas(contract.Gas) 524 } 525 } 526 527 if evm.Config.Debug { 528 if evm.depth == 0 { 529 evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) 530 } else { 531 evm.Config.Tracer.CaptureExit(ret, gas-contract.Gas, err) 532 } 533 } 534 return ret, address, contract.Gas, err 535 } 536 537 // Create creates a new contract using code as deployment code. 538 func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { 539 contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) 540 return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE) 541 } 542 543 // Create2 creates a new contract using code as deployment code. 544 // 545 // The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:] 546 // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. 547 func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { 548 codeAndHash := &codeAndHash{code: code} 549 contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes()) 550 return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2) 551 } 552 553 // ChainConfig returns the environment's chain configuration 554 func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }