@@ -683,7 +683,7 @@ type CallArgs struct {
683683 Data hexutil.Bytes `json:"data"`
684684}
685685
686- func (s * PublicBlockChainAPI ) doCall (ctx context.Context , args CallArgs , blockNr rpc.BlockNumber , timeout time.Duration ) ([]byte , uint64 , bool , error ) {
686+ func (s * PublicBlockChainAPI ) doCall (ctx context.Context , args CallArgs , blockNr rpc.BlockNumber , timeout time.Duration , globalGasCap * big. Int ) ([]byte , uint64 , bool , error ) {
687687 defer func (start time.Time ) { log .Debug ("Executing EVM call finished" , "runtime" , time .Since (start )) }(time .Now ())
688688
689689 state , header , err := s .b .StateAndHeaderByNumber (ctx , blockNr )
@@ -700,14 +700,18 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
700700 }
701701 }
702702 // Set default gas & gas price if none were set
703- gas , gasPrice := uint64 (args .Gas ), args . GasPrice . ToInt ( )
703+ gas := uint64 (args .Gas )
704704 if gas == 0 {
705705 gas = math .MaxUint64 / 2
706706 }
707+ if globalGasCap != nil && globalGasCap .Uint64 () < gas {
708+ log .Warn ("Caller gas above allowance, capping" , "requested" , gas , "cap" , globalGasCap )
709+ gas = globalGasCap .Uint64 ()
710+ }
711+ gasPrice := args .GasPrice .ToInt ()
707712 if gasPrice .Sign () == 0 {
708713 gasPrice = new (big.Int ).SetUint64 (defaultGasPrice )
709714 }
710-
711715 // Create new call message
712716 msg := types .NewMessage (addr , args .To , 0 , args .Value .ToInt (), gas , gasPrice , args .Data , false )
713717
@@ -748,7 +752,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
748752// Call executes the given transaction on the state for the given block number.
749753// It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values.
750754func (s * PublicBlockChainAPI ) Call (ctx context.Context , args CallArgs , blockNr rpc.BlockNumber ) (hexutil.Bytes , error ) {
751- result , _ , _ , err := s .doCall (ctx , args , blockNr , 5 * time .Second )
755+ result , _ , _ , err := s .doCall (ctx , args , blockNr , 5 * time .Second , s . b . RPCGasCap () )
752756 return (hexutil .Bytes )(result ), err
753757}
754758
@@ -771,13 +775,18 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (h
771775 }
772776 hi = block .GasLimit ()
773777 }
778+ gasCap := s .b .RPCGasCap ()
779+ if gasCap != nil && hi > gasCap .Uint64 () {
780+ log .Warn ("Caller gas above allowance, capping" , "requested" , hi , "cap" , gasCap )
781+ hi = gasCap .Uint64 ()
782+ }
774783 cap = hi
775784
776785 // Create a helper to check if a gas allowance results in an executable transaction
777786 executable := func (gas uint64 ) bool {
778787 args .Gas = hexutil .Uint64 (gas )
779788
780- _ , _ , failed , err := s .doCall (ctx , args , rpc .PendingBlockNumber , 0 )
789+ _ , _ , failed , err := s .doCall (ctx , args , rpc .PendingBlockNumber , 0 , gasCap )
781790 if err != nil || failed {
782791 return false
783792 }
@@ -795,7 +804,7 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (h
795804 // Reject the transaction as invalid if it still fails at the highest allowance
796805 if hi == cap {
797806 if ! executable (hi ) {
798- return 0 , fmt .Errorf ("gas required exceeds allowance or always failing transaction" )
807+ return 0 , fmt .Errorf ("gas required exceeds allowance (%d) or always failing transaction" , cap )
799808 }
800809 }
801810 return hexutil .Uint64 (hi ), nil
0 commit comments