@@ -683,7 +683,7 @@ type CallArgs struct {
683
683
Data hexutil.Bytes `json:"data"`
684
684
}
685
685
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 ) {
687
687
defer func (start time.Time ) { log .Debug ("Executing EVM call finished" , "runtime" , time .Since (start )) }(time .Now ())
688
688
689
689
state , header , err := s .b .StateAndHeaderByNumber (ctx , blockNr )
@@ -700,14 +700,18 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
700
700
}
701
701
}
702
702
// Set default gas & gas price if none were set
703
- gas , gasPrice := uint64 (args .Gas ), args . GasPrice . ToInt ( )
703
+ gas := uint64 (args .Gas )
704
704
if gas == 0 {
705
705
gas = math .MaxUint64 / 2
706
706
}
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 ()
707
712
if gasPrice .Sign () == 0 {
708
713
gasPrice = new (big.Int ).SetUint64 (defaultGasPrice )
709
714
}
710
-
711
715
// Create new call message
712
716
msg := types .NewMessage (addr , args .To , 0 , args .Value .ToInt (), gas , gasPrice , args .Data , false )
713
717
@@ -748,7 +752,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
748
752
// Call executes the given transaction on the state for the given block number.
749
753
// It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values.
750
754
func (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 () )
752
756
return (hexutil .Bytes )(result ), err
753
757
}
754
758
@@ -771,13 +775,18 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (h
771
775
}
772
776
hi = block .GasLimit ()
773
777
}
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
+ }
774
783
cap = hi
775
784
776
785
// Create a helper to check if a gas allowance results in an executable transaction
777
786
executable := func (gas uint64 ) bool {
778
787
args .Gas = hexutil .Uint64 (gas )
779
788
780
- _ , _ , failed , err := s .doCall (ctx , args , rpc .PendingBlockNumber , 0 )
789
+ _ , _ , failed , err := s .doCall (ctx , args , rpc .PendingBlockNumber , 0 , gasCap )
781
790
if err != nil || failed {
782
791
return false
783
792
}
@@ -795,7 +804,7 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (h
795
804
// Reject the transaction as invalid if it still fails at the highest allowance
796
805
if hi == cap {
797
806
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 )
799
808
}
800
809
}
801
810
return hexutil .Uint64 (hi ), nil
0 commit comments