github.com/ava-labs/subnet-evm@v0.6.4/accounts/abi/bind/backends/simulated.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2015 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package backends 28 29 import ( 30 "context" 31 "errors" 32 "fmt" 33 "math/big" 34 "sync" 35 "time" 36 37 "github.com/ava-labs/subnet-evm/eth" 38 "github.com/ava-labs/subnet-evm/vmerrs" 39 40 "github.com/ava-labs/subnet-evm/accounts/abi" 41 "github.com/ava-labs/subnet-evm/accounts/abi/bind" 42 "github.com/ava-labs/subnet-evm/consensus/dummy" 43 "github.com/ava-labs/subnet-evm/core" 44 "github.com/ava-labs/subnet-evm/core/bloombits" 45 "github.com/ava-labs/subnet-evm/core/rawdb" 46 "github.com/ava-labs/subnet-evm/core/state" 47 "github.com/ava-labs/subnet-evm/core/types" 48 "github.com/ava-labs/subnet-evm/core/vm" 49 "github.com/ava-labs/subnet-evm/eth/filters" 50 "github.com/ava-labs/subnet-evm/interfaces" 51 "github.com/ava-labs/subnet-evm/params" 52 "github.com/ava-labs/subnet-evm/rpc" 53 "github.com/ethereum/go-ethereum/common" 54 "github.com/ethereum/go-ethereum/common/hexutil" 55 "github.com/ethereum/go-ethereum/common/math" 56 "github.com/ethereum/go-ethereum/ethdb" 57 "github.com/ethereum/go-ethereum/event" 58 "github.com/ethereum/go-ethereum/log" 59 ) 60 61 // Verify that SimulatedBackend implements required interfaces 62 var ( 63 _ bind.AcceptedContractCaller = (*SimulatedBackend)(nil) 64 _ bind.ContractBackend = (*SimulatedBackend)(nil) 65 _ bind.DeployBackend = (*SimulatedBackend)(nil) 66 67 _ interfaces.ChainReader = (*SimulatedBackend)(nil) 68 _ interfaces.ChainStateReader = (*SimulatedBackend)(nil) 69 _ interfaces.TransactionReader = (*SimulatedBackend)(nil) 70 _ interfaces.TransactionSender = (*SimulatedBackend)(nil) 71 _ interfaces.ContractCaller = (*SimulatedBackend)(nil) 72 _ interfaces.GasEstimator = (*SimulatedBackend)(nil) 73 _ interfaces.GasPricer = (*SimulatedBackend)(nil) 74 _ interfaces.LogFilterer = (*SimulatedBackend)(nil) 75 _ interfaces.AcceptedStateReader = (*SimulatedBackend)(nil) 76 _ interfaces.AcceptedContractCaller = (*SimulatedBackend)(nil) 77 ) 78 79 var ( 80 errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block") 81 errBlockDoesNotExist = errors.New("block does not exist in blockchain") 82 errTransactionDoesNotExist = errors.New("transaction does not exist") 83 ) 84 85 // SimulatedBackend implements bind.ContractBackend, simulating a blockchain in 86 // the background. Its main purpose is to allow for easy testing of contract bindings. 87 // Simulated backend implements the following interfaces: 88 // ChainReader, ChainStateReader, ContractBackend, ContractCaller, ContractFilterer, ContractTransactor, 89 // DeployBackend, GasEstimator, GasPricer, LogFilterer, AcceptedContractCaller, TransactionReader, and TransactionSender 90 type SimulatedBackend struct { 91 database ethdb.Database // In memory database to store our testing data 92 blockchain *core.BlockChain // Ethereum blockchain to handle the consensus 93 94 mu sync.Mutex 95 acceptedBlock *types.Block // Currently accepted block that will be imported on request 96 acceptedState *state.StateDB // Currently accepted state that will be the active on request 97 98 events *filters.EventSystem // for filtering log events live 99 filterSystem *filters.FilterSystem // for filtering database logs 100 101 config *params.ChainConfig 102 } 103 104 // NewSimulatedBackendWithDatabase creates a new binding backend based on the given database 105 // and uses a simulated blockchain for testing purposes. 106 // A simulated backend always uses chainID 1337. 107 func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend { 108 copyConfig := *params.TestChainConfig 109 copyConfig.ChainID = big.NewInt(1337) 110 genesis := core.Genesis{ 111 Config: ©Config, 112 GasLimit: gasLimit, 113 Alloc: alloc, 114 } 115 cacheConfig := &core.CacheConfig{} 116 blockchain, _ := core.NewBlockChain(database, cacheConfig, &genesis, dummy.NewCoinbaseFaker(), vm.Config{}, common.Hash{}, false) 117 118 backend := &SimulatedBackend{ 119 database: database, 120 blockchain: blockchain, 121 config: genesis.Config, 122 } 123 124 filterBackend := &filterBackend{database, blockchain, backend} 125 backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{}) 126 backend.events = filters.NewEventSystem(backend.filterSystem) 127 128 header := backend.blockchain.CurrentBlock() 129 block := backend.blockchain.GetBlock(header.Hash(), header.Number.Uint64()) 130 131 backend.rollback(block) 132 return backend 133 } 134 135 // NewSimulatedBackend creates a new binding backend using a simulated blockchain 136 // for testing purposes. 137 // A simulated backend always uses chainID 1337. 138 func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend { 139 return NewSimulatedBackendWithDatabase(rawdb.NewMemoryDatabase(), alloc, gasLimit) 140 } 141 142 // Close terminates the underlying blockchain's update loop. 143 func (b *SimulatedBackend) Close() error { 144 b.blockchain.Stop() 145 return nil 146 } 147 148 // Commit imports all the accepted transactions as a single block and starts a 149 // fresh new state. 150 func (b *SimulatedBackend) Commit(accept bool) common.Hash { 151 b.mu.Lock() 152 defer b.mu.Unlock() 153 154 if _, err := b.blockchain.InsertChain([]*types.Block{b.acceptedBlock}); err != nil { 155 panic(err) // This cannot happen unless the simulator is wrong, fail in that case 156 } 157 if accept { 158 if err := b.blockchain.Accept(b.acceptedBlock); err != nil { 159 panic(err) 160 } 161 b.blockchain.DrainAcceptorQueue() 162 } 163 blockHash := b.acceptedBlock.Hash() 164 165 // Using the last inserted block here makes it possible to build on a side 166 // chain after a fork. 167 b.rollback(b.acceptedBlock) 168 169 return blockHash 170 } 171 172 // Rollback aborts all accepted transactions, reverting to the last committed state. 173 func (b *SimulatedBackend) Rollback() { 174 b.mu.Lock() 175 defer b.mu.Unlock() 176 177 header := b.blockchain.CurrentBlock() 178 block := b.blockchain.GetBlock(header.Hash(), header.Number.Uint64()) 179 180 b.rollback(block) 181 } 182 183 func (b *SimulatedBackend) rollback(parent *types.Block) { 184 blocks, _, _ := core.GenerateChain(b.config, parent, dummy.NewFaker(), b.database, 1, 10, func(int, *core.BlockGen) {}) 185 186 b.acceptedBlock = blocks[0] 187 b.acceptedState, _ = state.New(b.acceptedBlock.Root(), b.blockchain.StateCache(), nil) 188 } 189 190 // Fork creates a side-chain that can be used to simulate reorgs. 191 // 192 // This function should be called with the ancestor block where the new side 193 // chain should be started. Transactions (old and new) can then be applied on 194 // top and Commit-ed. 195 // 196 // Note, the side-chain will only become canonical (and trigger the events) when 197 // it becomes longer. Until then CallContract will still operate on the current 198 // canonical chain. 199 // 200 // There is a % chance that the side chain becomes canonical at the same length 201 // to simulate live network behavior. 202 func (b *SimulatedBackend) Fork(ctx context.Context, parent common.Hash) error { 203 b.mu.Lock() 204 defer b.mu.Unlock() 205 206 if len(b.acceptedBlock.Transactions()) != 0 { 207 return errors.New("accepted block dirty") 208 } 209 block, err := b.blockByHash(ctx, parent) 210 if err != nil { 211 return err 212 } 213 b.rollback(block) 214 return nil 215 } 216 217 // stateByBlockNumber retrieves a state by a given blocknumber. 218 func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (*state.StateDB, error) { 219 if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number) == 0 { 220 return b.blockchain.State() 221 } 222 block, err := b.blockByNumber(ctx, blockNumber) 223 if err != nil { 224 return nil, err 225 } 226 return b.blockchain.StateAt(block.Root()) 227 } 228 229 // CodeAt returns the code associated with a certain account in the blockchain. 230 func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { 231 b.mu.Lock() 232 defer b.mu.Unlock() 233 234 stateDB, err := b.stateByBlockNumber(ctx, blockNumber) 235 if err != nil { 236 return nil, err 237 } 238 return stateDB.GetCode(contract), nil 239 } 240 241 // BalanceAt returns the wei balance of a certain account in the blockchain. 242 func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (*big.Int, error) { 243 b.mu.Lock() 244 defer b.mu.Unlock() 245 246 stateDB, err := b.stateByBlockNumber(ctx, blockNumber) 247 if err != nil { 248 return nil, err 249 } 250 return stateDB.GetBalance(contract), nil 251 } 252 253 // NonceAt returns the nonce of a certain account in the blockchain. 254 func (b *SimulatedBackend) NonceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (uint64, error) { 255 b.mu.Lock() 256 defer b.mu.Unlock() 257 258 stateDB, err := b.stateByBlockNumber(ctx, blockNumber) 259 if err != nil { 260 return 0, err 261 } 262 return stateDB.GetNonce(contract), nil 263 } 264 265 // StorageAt returns the value of key in the storage of an account in the blockchain. 266 func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) { 267 b.mu.Lock() 268 defer b.mu.Unlock() 269 270 stateDB, err := b.stateByBlockNumber(ctx, blockNumber) 271 if err != nil { 272 return nil, err 273 } 274 val := stateDB.GetState(contract, key) 275 return val[:], nil 276 } 277 278 // TransactionReceipt returns the receipt of a transaction. 279 func (b *SimulatedBackend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { 280 b.mu.Lock() 281 defer b.mu.Unlock() 282 283 receipt, _, _, _ := rawdb.ReadReceipt(b.database, txHash, b.config) 284 if receipt == nil { 285 return nil, interfaces.NotFound 286 } 287 return receipt, nil 288 } 289 290 // TransactionByHash checks the pool of accepted transactions in addition to the 291 // blockchain. The isAccepted return value indicates whether the transaction has been 292 // mined yet. Note that the transaction may not be part of the canonical chain even if 293 // it's not accepted. 294 func (b *SimulatedBackend) TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) { 295 b.mu.Lock() 296 defer b.mu.Unlock() 297 298 tx := b.acceptedBlock.Transaction(txHash) 299 if tx != nil { 300 return tx, true, nil 301 } 302 tx, _, _, _ = rawdb.ReadTransaction(b.database, txHash) 303 if tx != nil { 304 return tx, false, nil 305 } 306 return nil, false, interfaces.NotFound 307 } 308 309 // BlockByHash retrieves a block based on the block hash. 310 func (b *SimulatedBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 311 b.mu.Lock() 312 defer b.mu.Unlock() 313 314 return b.blockByHash(ctx, hash) 315 } 316 317 // blockByHash retrieves a block based on the block hash without Locking. 318 func (b *SimulatedBackend) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 319 if hash == b.acceptedBlock.Hash() { 320 return b.acceptedBlock, nil 321 } 322 323 block := b.blockchain.GetBlockByHash(hash) 324 if block != nil { 325 return block, nil 326 } 327 328 return nil, errBlockDoesNotExist 329 } 330 331 // BlockByNumber retrieves a block from the database by number, caching it 332 // (associated with its hash) if found. 333 func (b *SimulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { 334 b.mu.Lock() 335 defer b.mu.Unlock() 336 337 return b.blockByNumber(ctx, number) 338 } 339 340 // blockByNumber retrieves a block from the database by number, caching it 341 // (associated with its hash) if found without Lock. 342 func (b *SimulatedBackend) blockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { 343 if number == nil || number.Cmp(b.acceptedBlock.Number()) == 0 { 344 return b.blockByHash(ctx, b.blockchain.CurrentBlock().Hash()) 345 } 346 347 block := b.blockchain.GetBlockByNumber(uint64(number.Int64())) 348 if block == nil { 349 return nil, errBlockDoesNotExist 350 } 351 352 return block, nil 353 } 354 355 // HeaderByHash returns a block header from the current canonical chain. 356 func (b *SimulatedBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { 357 b.mu.Lock() 358 defer b.mu.Unlock() 359 360 if hash == b.acceptedBlock.Hash() { 361 return b.acceptedBlock.Header(), nil 362 } 363 364 header := b.blockchain.GetHeaderByHash(hash) 365 if header == nil { 366 return nil, errBlockDoesNotExist 367 } 368 369 return header, nil 370 } 371 372 // HeaderByNumber returns a block header from the current canonical chain. If number is 373 // nil, the latest known header is returned. 374 func (b *SimulatedBackend) HeaderByNumber(ctx context.Context, block *big.Int) (*types.Header, error) { 375 b.mu.Lock() 376 defer b.mu.Unlock() 377 378 if block == nil || block.Cmp(b.acceptedBlock.Number()) == 0 { 379 return b.blockchain.CurrentHeader(), nil 380 } 381 382 return b.blockchain.GetHeaderByNumber(uint64(block.Int64())), nil 383 } 384 385 // TransactionCount returns the number of transactions in a given block. 386 func (b *SimulatedBackend) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) { 387 b.mu.Lock() 388 defer b.mu.Unlock() 389 390 if blockHash == b.acceptedBlock.Hash() { 391 return uint(b.acceptedBlock.Transactions().Len()), nil 392 } 393 394 block := b.blockchain.GetBlockByHash(blockHash) 395 if block == nil { 396 return uint(0), errBlockDoesNotExist 397 } 398 399 return uint(block.Transactions().Len()), nil 400 } 401 402 // TransactionInBlock returns the transaction for a specific block at a specific index. 403 func (b *SimulatedBackend) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { 404 b.mu.Lock() 405 defer b.mu.Unlock() 406 407 if blockHash == b.acceptedBlock.Hash() { 408 transactions := b.acceptedBlock.Transactions() 409 if uint(len(transactions)) < index+1 { 410 return nil, errTransactionDoesNotExist 411 } 412 413 return transactions[index], nil 414 } 415 416 block := b.blockchain.GetBlockByHash(blockHash) 417 if block == nil { 418 return nil, errBlockDoesNotExist 419 } 420 421 transactions := block.Transactions() 422 if uint(len(transactions)) < index+1 { 423 return nil, errTransactionDoesNotExist 424 } 425 426 return transactions[index], nil 427 } 428 429 // AcceptedCodeAt returns the code associated with an account in the accepted state. 430 func (b *SimulatedBackend) AcceptedCodeAt(ctx context.Context, contract common.Address) ([]byte, error) { 431 b.mu.Lock() 432 defer b.mu.Unlock() 433 434 return b.acceptedState.GetCode(contract), nil 435 } 436 437 func newRevertError(result *core.ExecutionResult) *revertError { 438 reason, errUnpack := abi.UnpackRevert(result.Revert()) 439 err := errors.New("execution reverted") 440 if errUnpack == nil { 441 err = fmt.Errorf("execution reverted: %v", reason) 442 } 443 return &revertError{ 444 error: err, 445 reason: hexutil.Encode(result.Revert()), 446 } 447 } 448 449 // revertError is an API error that encompasses an EVM revert with JSON error 450 // code and a binary data blob. 451 type revertError struct { 452 error 453 reason string // revert reason hex encoded 454 } 455 456 // ErrorCode returns the JSON error code for a revert. 457 // See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal 458 func (e *revertError) ErrorCode() int { 459 return 3 460 } 461 462 // ErrorData returns the hex encoded revert reason. 463 func (e *revertError) ErrorData() interface{} { 464 return e.reason 465 } 466 467 // CallContract executes a contract call. 468 func (b *SimulatedBackend) CallContract(ctx context.Context, call interfaces.CallMsg, blockNumber *big.Int) ([]byte, error) { 469 b.mu.Lock() 470 defer b.mu.Unlock() 471 472 if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number) != 0 { 473 return nil, errBlockNumberUnsupported 474 } 475 stateDB, err := b.blockchain.State() 476 if err != nil { 477 return nil, err 478 } 479 res, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), stateDB) 480 if err != nil { 481 return nil, err 482 } 483 // If the result contains a revert reason, try to unpack and return it. 484 if len(res.Revert()) > 0 { 485 return nil, newRevertError(res) 486 } 487 return res.Return(), res.Err 488 } 489 490 // AcceptedCallContract executes a contract call on the accepted state. 491 func (b *SimulatedBackend) AcceptedCallContract(ctx context.Context, call interfaces.CallMsg) ([]byte, error) { 492 b.mu.Lock() 493 defer b.mu.Unlock() 494 defer b.acceptedState.RevertToSnapshot(b.acceptedState.Snapshot()) 495 496 res, err := b.callContract(ctx, call, b.acceptedBlock.Header(), b.acceptedState) 497 if err != nil { 498 return nil, err 499 } 500 // If the result contains a revert reason, try to unpack and return it. 501 if len(res.Revert()) > 0 { 502 return nil, newRevertError(res) 503 } 504 return res.Return(), res.Err 505 } 506 507 // AcceptedNonceAt implements AcceptedStateReader.AcceptedNonceAt, retrieving 508 // the nonce currently accepted for the account. 509 func (b *SimulatedBackend) AcceptedNonceAt(ctx context.Context, account common.Address) (uint64, error) { 510 b.mu.Lock() 511 defer b.mu.Unlock() 512 513 return b.acceptedState.GetOrNewStateObject(account).Nonce(), nil 514 } 515 516 // SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated 517 // chain doesn't have miners, we just return a gas price of 1 for any call. 518 func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) { 519 b.mu.Lock() 520 defer b.mu.Unlock() 521 522 if b.acceptedBlock.Header().BaseFee != nil { 523 return b.acceptedBlock.Header().BaseFee, nil 524 } 525 return big.NewInt(1), nil 526 } 527 528 // SuggestGasTipCap implements ContractTransactor.SuggestGasTipCap. Since the simulated 529 // chain doesn't have miners, we just return a gas tip of 1 for any call. 530 func (b *SimulatedBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { 531 return big.NewInt(1), nil 532 } 533 534 // EstimateGas executes the requested code against the currently accepted block/state and 535 // returns the used amount of gas. 536 func (b *SimulatedBackend) EstimateGas(ctx context.Context, call interfaces.CallMsg) (uint64, error) { 537 b.mu.Lock() 538 defer b.mu.Unlock() 539 540 // Determine the lowest and highest possible gas limits to binary search in between 541 var ( 542 lo uint64 = params.TxGas - 1 543 hi uint64 544 cap uint64 545 ) 546 if call.Gas >= params.TxGas { 547 hi = call.Gas 548 } else { 549 hi = b.acceptedBlock.GasLimit() 550 } 551 // Normalize the max fee per gas the call is willing to spend. 552 var feeCap *big.Int 553 if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) { 554 return 0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") 555 } else if call.GasPrice != nil { 556 feeCap = call.GasPrice 557 } else if call.GasFeeCap != nil { 558 feeCap = call.GasFeeCap 559 } else { 560 feeCap = common.Big0 561 } 562 // Recap the highest gas allowance with account's balance. 563 if feeCap.BitLen() != 0 { 564 balance := b.acceptedState.GetBalance(call.From) // from can't be nil 565 available := new(big.Int).Set(balance) 566 if call.Value != nil { 567 if call.Value.Cmp(available) >= 0 { 568 return 0, core.ErrInsufficientFundsForTransfer 569 } 570 available.Sub(available, call.Value) 571 } 572 allowance := new(big.Int).Div(available, feeCap) 573 if allowance.IsUint64() && hi > allowance.Uint64() { 574 transfer := call.Value 575 if transfer == nil { 576 transfer = new(big.Int) 577 } 578 log.Info("Gas estimation capped by limited funds", "original", hi, "balance", balance, 579 "sent", transfer, "feecap", feeCap, "fundable", allowance) 580 hi = allowance.Uint64() 581 } 582 } 583 cap = hi 584 585 // Create a helper to check if a gas allowance results in an executable transaction 586 executable := func(gas uint64) (bool, *core.ExecutionResult, error) { 587 call.Gas = gas 588 589 snapshot := b.acceptedState.Snapshot() 590 res, err := b.callContract(ctx, call, b.acceptedBlock.Header(), b.acceptedState) 591 b.acceptedState.RevertToSnapshot(snapshot) 592 593 if err != nil { 594 if errors.Is(err, core.ErrIntrinsicGas) { 595 return true, nil, nil // Special case, raise gas limit 596 } 597 return true, nil, err // Bail out 598 } 599 return res.Failed(), res, nil 600 } 601 // Execute the binary search and hone in on an executable gas limit 602 for lo+1 < hi { 603 mid := (hi + lo) / 2 604 failed, _, err := executable(mid) 605 606 // If the error is not nil(consensus error), it means the provided message 607 // call or transaction will never be accepted no matter how much gas it is 608 // assigned. Return the error directly, don't struggle any more 609 if err != nil { 610 return 0, err 611 } 612 if failed { 613 lo = mid 614 } else { 615 hi = mid 616 } 617 } 618 // Reject the transaction as invalid if it still fails at the highest allowance 619 if hi == cap { 620 failed, result, err := executable(hi) 621 if err != nil { 622 return 0, err 623 } 624 if failed { 625 if result != nil && result.Err != vmerrs.ErrOutOfGas { 626 if len(result.Revert()) > 0 { 627 return 0, newRevertError(result) 628 } 629 return 0, result.Err 630 } 631 // Otherwise, the specified gas cap is too low 632 return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap) 633 } 634 } 635 return hi, nil 636 } 637 638 // callContract implements common code between normal and accepted contract calls. 639 // state is modified during execution, make sure to copy it if necessary. 640 func (b *SimulatedBackend) callContract(ctx context.Context, call interfaces.CallMsg, header *types.Header, stateDB *state.StateDB) (*core.ExecutionResult, error) { 641 // Gas prices post 1559 need to be initialized 642 if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) { 643 return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") 644 } 645 head := b.blockchain.CurrentHeader() 646 if !b.blockchain.Config().IsSubnetEVM(head.Time) { 647 // If there's no basefee, then it must be a non-1559 execution 648 if call.GasPrice == nil { 649 call.GasPrice = new(big.Int) 650 } 651 call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice 652 } else { 653 // A basefee is provided, necessitating 1559-type execution 654 if call.GasPrice != nil { 655 // User specified the legacy gas field, convert to 1559 gas typing 656 call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice 657 } else { 658 // User specified 1559 gas fields (or none), use those 659 if call.GasFeeCap == nil { 660 call.GasFeeCap = new(big.Int) 661 } 662 if call.GasTipCap == nil { 663 call.GasTipCap = new(big.Int) 664 } 665 // Backfill the legacy gasPrice for EVM execution, unless we're all zeroes 666 call.GasPrice = new(big.Int) 667 if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 { 668 call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, head.BaseFee), call.GasFeeCap) 669 } 670 } 671 } 672 // Ensure message is initialized properly. 673 if call.Gas == 0 { 674 call.Gas = 50000000 675 } 676 if call.Value == nil { 677 call.Value = new(big.Int) 678 } 679 680 // Set infinite balance to the fake caller account. 681 from := stateDB.GetOrNewStateObject(call.From) 682 from.SetBalance(math.MaxBig256) 683 684 // Execute the call. 685 msg := &core.Message{ 686 From: call.From, 687 To: call.To, 688 Value: call.Value, 689 GasLimit: call.Gas, 690 GasPrice: call.GasPrice, 691 GasFeeCap: call.GasFeeCap, 692 GasTipCap: call.GasTipCap, 693 Data: call.Data, 694 AccessList: call.AccessList, 695 SkipAccountChecks: true, 696 } 697 698 // Create a new environment which holds all relevant information 699 // about the transaction and calling mechanisms. 700 txContext := core.NewEVMTxContext(msg) 701 evmContext := core.NewEVMBlockContext(header, b.blockchain, nil) 702 vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true}) 703 gasPool := new(core.GasPool).AddGas(math.MaxUint64) 704 705 return core.ApplyMessage(vmEnv, msg, gasPool) 706 } 707 708 // SendTransaction updates the accepted block to include the given transaction. 709 func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error { 710 b.mu.Lock() 711 defer b.mu.Unlock() 712 713 // Get the last block 714 block, err := b.blockByHash(ctx, b.acceptedBlock.ParentHash()) 715 if err != nil { 716 return errors.New("could not fetch parent") 717 } 718 // Check transaction validity 719 signer := types.MakeSigner(b.blockchain.Config(), block.Number(), block.Time()) 720 sender, err := types.Sender(signer, tx) 721 if err != nil { 722 return fmt.Errorf("invalid transaction: %v", err) 723 } 724 nonce := b.acceptedState.GetNonce(sender) 725 if tx.Nonce() != nonce { 726 return fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce) 727 } 728 // Include tx in chain 729 blocks, _, err := core.GenerateChain(b.config, block, dummy.NewETHFaker(), b.database, 1, 10, func(number int, block *core.BlockGen) { 730 for _, tx := range b.acceptedBlock.Transactions() { 731 block.AddTxWithChain(b.blockchain, tx) 732 } 733 block.AddTxWithChain(b.blockchain, tx) 734 }) 735 if err != nil { 736 return err 737 } 738 stateDB, err := b.blockchain.State() 739 if err != nil { 740 return err 741 } 742 b.acceptedBlock = blocks[0] 743 b.acceptedState, _ = state.New(b.acceptedBlock.Root(), stateDB.Database(), nil) 744 return nil 745 } 746 747 // FilterLogs executes a log filter operation, blocking during execution and 748 // returning all the results in one batch. 749 // 750 // TODO(karalabe): Deprecate when the subscription one can return past data too. 751 func (b *SimulatedBackend) FilterLogs(ctx context.Context, query interfaces.FilterQuery) ([]types.Log, error) { 752 var filter *filters.Filter 753 if query.BlockHash != nil { 754 // Block filter requested, construct a single-shot filter 755 filter = b.filterSystem.NewBlockFilter(*query.BlockHash, query.Addresses, query.Topics) 756 } else { 757 // Initialize unset filter boundaries to run from genesis to chain head 758 from := int64(0) 759 if query.FromBlock != nil { 760 from = query.FromBlock.Int64() 761 } 762 to := int64(-1) 763 if query.ToBlock != nil { 764 to = query.ToBlock.Int64() 765 } 766 // Construct the range filter 767 filter = b.filterSystem.NewRangeFilter(from, to, query.Addresses, query.Topics) 768 } 769 // Run the filter and return all the logs 770 logs, err := filter.Logs(ctx) 771 if err != nil { 772 return nil, err 773 } 774 res := make([]types.Log, len(logs)) 775 for i, nLog := range logs { 776 res[i] = *nLog 777 } 778 return res, nil 779 } 780 781 // SubscribeFilterLogs creates a background log filtering operation, returning a 782 // subscription immediately, which can be used to stream the found events. 783 func (b *SimulatedBackend) SubscribeFilterLogs(ctx context.Context, query interfaces.FilterQuery, ch chan<- types.Log) (interfaces.Subscription, error) { 784 // Subscribe to contract events 785 sink := make(chan []*types.Log) 786 787 sub, err := b.events.SubscribeLogs(query, sink) 788 if err != nil { 789 return nil, err 790 } 791 // Since we're getting logs in batches, we need to flatten them into a plain stream 792 return event.NewSubscription(func(quit <-chan struct{}) error { 793 defer sub.Unsubscribe() 794 for { 795 select { 796 case logs := <-sink: 797 for _, nlog := range logs { 798 select { 799 case ch <- *nlog: 800 case err := <-sub.Err(): 801 return err 802 case <-quit: 803 return nil 804 } 805 } 806 case err := <-sub.Err(): 807 return err 808 case <-quit: 809 return nil 810 } 811 } 812 }), nil 813 } 814 815 // SubscribeNewHead returns an event subscription for a new header. 816 func (b *SimulatedBackend) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (interfaces.Subscription, error) { 817 // subscribe to a new head 818 sink := make(chan *types.Header) 819 sub := b.events.SubscribeNewHeads(sink) 820 821 return event.NewSubscription(func(quit <-chan struct{}) error { 822 defer sub.Unsubscribe() 823 for { 824 select { 825 case head := <-sink: 826 select { 827 case ch <- head: 828 case err := <-sub.Err(): 829 return err 830 case <-quit: 831 return nil 832 } 833 case err := <-sub.Err(): 834 return err 835 case <-quit: 836 return nil 837 } 838 } 839 }), nil 840 } 841 842 // AdjustTime adds a time shift to the simulated clock. 843 // It can only be called on empty blocks. 844 func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error { 845 b.mu.Lock() 846 defer b.mu.Unlock() 847 848 if len(b.acceptedBlock.Transactions()) != 0 { 849 return errors.New("Could not adjust time on non-empty block") 850 } 851 block := b.blockchain.GetBlockByHash(b.acceptedBlock.ParentHash()) 852 if block == nil { 853 return errors.New("could not find parent") 854 } 855 856 blocks, _, _ := core.GenerateChain(b.config, block, dummy.NewFaker(), b.database, 1, 10, func(number int, block *core.BlockGen) { 857 block.OffsetTime(int64(adjustment.Seconds())) 858 }) 859 stateDB, err := b.blockchain.State() 860 if err != nil { 861 return err 862 } 863 b.acceptedBlock = blocks[0] 864 b.acceptedState, _ = state.New(b.acceptedBlock.Root(), stateDB.Database(), nil) 865 return nil 866 } 867 868 // Blockchain returns the underlying blockchain. 869 func (b *SimulatedBackend) Blockchain() *core.BlockChain { 870 return b.blockchain 871 } 872 873 // filterBackend implements filters.Backend to support filtering for logs without 874 // taking bloom-bits acceleration structures into account. 875 type filterBackend struct { 876 db ethdb.Database 877 bc *core.BlockChain 878 backend *SimulatedBackend 879 } 880 881 func (fb *filterBackend) SubscribeChainAcceptedEvent(ch chan<- core.ChainEvent) event.Subscription { 882 return fb.bc.SubscribeChainAcceptedEvent(ch) 883 } 884 885 func (fb *filterBackend) SubscribeAcceptedLogsEvent(ch chan<- []*types.Log) event.Subscription { 886 return fb.bc.SubscribeAcceptedLogsEvent(ch) 887 } 888 889 func (fb *filterBackend) SubscribeAcceptedTransactionEvent(ch chan<- core.NewTxsEvent) event.Subscription { 890 return fb.bc.SubscribeAcceptedTransactionEvent(ch) 891 } 892 893 func (fb *filterBackend) IsAllowUnfinalizedQueries() bool { 894 return false 895 } 896 897 func (fb *filterBackend) LastAcceptedBlock() *types.Block { 898 return fb.bc.LastAcceptedBlock() 899 } 900 901 func (fb *filterBackend) GetMaxBlocksPerRequest() int64 { 902 return eth.DefaultSettings.MaxBlocksPerRequest 903 } 904 905 func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db } 906 907 func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") } 908 909 func (fb *filterBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { 910 switch number { 911 case rpc.PendingBlockNumber, rpc.FinalizedBlockNumber: 912 if block := fb.backend.acceptedBlock; block != nil { 913 return block.Header(), nil 914 } 915 return nil, nil 916 case rpc.LatestBlockNumber: 917 return fb.bc.CurrentHeader(), nil 918 default: 919 return fb.bc.GetHeaderByNumber(uint64(number.Int64())), nil 920 } 921 } 922 923 func (fb *filterBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { 924 return fb.bc.GetHeaderByHash(hash), nil 925 } 926 927 func (fb *filterBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { 928 if body := fb.bc.GetBody(hash); body != nil { 929 return body, nil 930 } 931 return nil, errors.New("block body not found") 932 } 933 934 func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { 935 number := rawdb.ReadHeaderNumber(fb.db, hash) 936 if number == nil { 937 return nil, nil 938 } 939 header := rawdb.ReadHeader(fb.db, hash, *number) 940 if header == nil { 941 return nil, nil 942 } 943 return rawdb.ReadReceipts(fb.db, hash, *number, header.Time, fb.bc.Config()), nil 944 } 945 946 func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) { 947 logs := rawdb.ReadLogs(fb.db, hash, number) 948 return logs, nil 949 } 950 951 func (fb *filterBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { 952 return nullSubscription() 953 } 954 955 func (fb *filterBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { 956 return fb.bc.SubscribeChainEvent(ch) 957 } 958 959 func (fb *filterBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { 960 return fb.bc.SubscribeRemovedLogsEvent(ch) 961 } 962 963 func (fb *filterBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { 964 return fb.bc.SubscribeLogsEvent(ch) 965 } 966 967 func (fb *filterBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { 968 return nullSubscription() 969 } 970 971 func (fb *filterBackend) BloomStatus() (uint64, uint64) { return 4096, 0 } 972 973 func (fb *filterBackend) ServiceFilter(ctx context.Context, ms *bloombits.MatcherSession) { 974 panic("not supported") 975 } 976 977 func (fb *filterBackend) ChainConfig() *params.ChainConfig { 978 panic("not supported") 979 } 980 981 func (fb *filterBackend) CurrentHeader() *types.Header { 982 panic("not supported") 983 } 984 985 func nullSubscription() event.Subscription { 986 return event.NewSubscription(func(quit <-chan struct{}) error { 987 <-quit 988 return nil 989 }) 990 }