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