@@ -41,6 +41,7 @@ import (
4141 "github.com/celo-org/celo-blockchain/eth/filters"
4242 "github.com/celo-org/celo-blockchain/ethdb"
4343 "github.com/celo-org/celo-blockchain/event"
44+ "github.com/celo-org/celo-blockchain/log"
4445 "github.com/celo-org/celo-blockchain/params"
4546 "github.com/celo-org/celo-blockchain/rpc"
4647)
@@ -501,6 +502,38 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
501502 vmRunner := b .blockchain .NewEVMRunner (b .pendingBlock .Header (), b .pendingState )
502503 hi = blockchain_parameters .GetBlockGasLimitOrDefault (vmRunner )
503504 }
505+ // Normalize the max fee per gas the call is willing to spend.
506+ var feeCap * big.Int
507+ if call .GasPrice != nil && (call .GasFeeCap != nil || call .GasTipCap != nil ) {
508+ return 0 , errors .New ("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified" )
509+ } else if call .GasPrice != nil {
510+ feeCap = call .GasPrice
511+ } else if call .GasFeeCap != nil {
512+ feeCap = call .GasFeeCap
513+ } else {
514+ feeCap = common .Big0
515+ }
516+ // Recap the highest gas allowance with account's balance.
517+ if feeCap .BitLen () != 0 {
518+ balance := b .pendingState .GetBalance (call .From ) // from can't be nil
519+ available := new (big.Int ).Set (balance )
520+ if call .Value != nil {
521+ if call .Value .Cmp (available ) >= 0 {
522+ return 0 , errors .New ("insufficient funds for transfer" )
523+ }
524+ available .Sub (available , call .Value )
525+ }
526+ allowance := new (big.Int ).Div (available , feeCap )
527+ if allowance .IsUint64 () && hi > allowance .Uint64 () {
528+ transfer := call .Value
529+ if transfer == nil {
530+ transfer = new (big.Int )
531+ }
532+ log .Warn ("Gas estimation capped by limited funds" , "original" , hi , "balance" , balance ,
533+ "sent" , transfer , "feecap" , feeCap , "fundable" , allowance )
534+ hi = allowance .Uint64 ()
535+ }
536+ }
504537 cap = hi
505538
506539 // Create a helper to check if a gas allowance results in an executable transaction
@@ -607,10 +640,10 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
607640 // Execute the call.
608641 msg := callMsg {call }
609642
610- // Create a new environment which holds all relevant information
611- // about the transaction and calling mechanisms.
612643 txContext := core .NewEVMTxContext (msg )
613644 evmContext := core .NewEVMBlockContext (block .Header (), b .blockchain , nil )
645+ // Create a new environment which holds all relevant information
646+ // about the transaction and calling mechanisms.
614647 vmEnv := vm .NewEVM (evmContext , txContext , stateDB , b .config , vm.Config {NoBaseFee : true })
615648 gasPool := new (core.GasPool ).AddGas (math .MaxUint64 )
616649 vmRunner := b .blockchain .NewEVMRunner (block .Header (), stateDB )
@@ -766,7 +799,7 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
766799 defer b .mu .Unlock ()
767800
768801 if len (b .pendingBlock .Transactions ()) != 0 {
769- return errors .New ("could not adjust time on non-empty block" )
802+ return errors .New ("Could not adjust time on non-empty block" )
770803 }
771804
772805 blocks , _ := core .GenerateChain (b .config , b .blockchain .CurrentBlock (), mockEngine .NewFaker (), b .database , 1 , func (number int , block * core.BlockGen ) {
0 commit comments