@@ -84,7 +84,7 @@ func (s sortGasAndReward) Less(i, j int) bool {
8484// processBlock takes a blockFees structure with the blockNumber, the header and optionally
8585// the block field filled in, retrieves the block from the backend if not present yet and
8686// fills in the rest of the fields.
87- func (oracle * Oracle ) processBlock (bf * blockFees , percentiles []float64 ) {
87+ func (oracle * Oracle ) processBlock (bf * blockFees , percentiles []float64 , nonCongestedPrice * big. Int ) {
8888 chainconfig := oracle .backend .ChainConfig ()
8989 if bf .results .baseFee = bf .header .BaseFee ; bf .results .baseFee == nil {
9090 bf .results .baseFee = new (big.Int )
@@ -121,7 +121,12 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
121121
122122 sorter := make (sortGasAndReward , len (bf .block .Transactions ()))
123123 for i , tx := range bf .block .Transactions () {
124- reward , _ := tx .EffectiveGasTip (bf .block .BaseFee ())
124+ var reward * big.Int
125+ if nonCongestedPrice != nil {
126+ reward = nonCongestedPrice
127+ } else {
128+ reward , _ = tx .EffectiveGasTip (bf .block .BaseFee ())
129+ }
125130 sorter [i ] = txGasAndReward {gasUsed : bf .receipts [i ].GasUsed , reward : reward }
126131 }
127132 sort .Sort (sorter )
@@ -144,51 +149,54 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
144149// also returned if requested and available.
145150// Note: an error is only returned if retrieving the head header has failed. If there are no
146151// retrievable blocks in the specified range then zero block count is returned with no error.
147- func (oracle * Oracle ) resolveBlockRange (ctx context.Context , lastBlock rpc.BlockNumber , blocks int ) (* types.Block , []* types.Receipt , uint64 , int , error ) {
152+ func (oracle * Oracle ) resolveBlockRange (ctx context.Context , lastBlock rpc.BlockNumber , blocks int ) (* types.Block , []* types.Receipt , uint64 , int , * types. Header , error ) {
148153 var (
149154 headBlock rpc.BlockNumber
150155 pendingBlock * types.Block
151156 pendingReceipts types.Receipts
157+ headHeader * types.Header
152158 )
153159 // query either pending block or head header and set headBlock
154160 if lastBlock == rpc .PendingBlockNumber {
155161 if pendingBlock , pendingReceipts = oracle .backend .PendingBlockAndReceipts (); pendingBlock != nil {
156162 lastBlock = rpc .BlockNumber (pendingBlock .NumberU64 ())
157163 headBlock = lastBlock - 1
164+ headHeader = pendingBlock .Header ()
158165 } else {
159166 // pending block not supported by backend, process until latest block
160167 lastBlock = rpc .LatestBlockNumber
161168 blocks --
162169 if blocks == 0 {
163- return nil , nil , 0 , 0 , nil
170+ return nil , nil , 0 , 0 , nil , nil
164171 }
165172 }
166173 }
167174 if pendingBlock == nil {
168175 // if pending block is not fetched then we retrieve the head header to get the head block number
169176 if latestHeader , err := oracle .backend .HeaderByNumber (ctx , rpc .LatestBlockNumber ); err == nil {
170177 headBlock = rpc .BlockNumber (latestHeader .Number .Uint64 ())
178+ headHeader = latestHeader
171179 } else {
172- return nil , nil , 0 , 0 , err
180+ return nil , nil , 0 , 0 , nil , err
173181 }
174182 }
175183 if lastBlock == rpc .LatestBlockNumber {
176184 lastBlock = headBlock
177185 } else if pendingBlock == nil && lastBlock > headBlock {
178- return nil , nil , 0 , 0 , fmt .Errorf ("%w: requested %d, head %d" , errRequestBeyondHead , lastBlock , headBlock )
186+ return nil , nil , 0 , 0 , nil , fmt .Errorf ("%w: requested %d, head %d" , errRequestBeyondHead , lastBlock , headBlock )
179187 }
180188 if lastBlock == rpc .FinalizedBlockNumber {
181189 if latestFinalizedHeader , err := oracle .backend .HeaderByNumber (ctx , rpc .FinalizedBlockNumber ); err == nil {
182190 lastBlock = rpc .BlockNumber (latestFinalizedHeader .Number .Uint64 ())
183191 } else {
184- return nil , nil , 0 , 0 , err
192+ return nil , nil , 0 , 0 , nil , err
185193 }
186194 }
187195 // ensure not trying to retrieve before genesis
188196 if rpc .BlockNumber (blocks ) > lastBlock + 1 {
189197 blocks = int (lastBlock + 1 )
190198 }
191- return pendingBlock , pendingReceipts , uint64 (lastBlock ), blocks , nil
199+ return pendingBlock , pendingReceipts , uint64 (lastBlock ), blocks , headHeader , nil
192200}
193201
194202// FeeHistory returns data relevant for fee estimation based on the specified range of blocks.
@@ -230,12 +238,26 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLast
230238 pendingReceipts []* types.Receipt
231239 err error
232240 )
233- pendingBlock , pendingReceipts , lastBlock , blocks , err := oracle .resolveBlockRange (ctx , unresolvedLastBlock , blocks )
241+ pendingBlock , pendingReceipts , lastBlock , blocks , headHeader , err := oracle .resolveBlockRange (ctx , unresolvedLastBlock , blocks )
234242 if err != nil || blocks == 0 {
235243 return common .Big0 , nil , nil , nil , err
236244 }
237245 oldestBlock := lastBlock + 1 - uint64 (blocks )
238246
247+ // If pending txs are less than oracle.congestedThreshold, we consider the network to be non-congested and suggest
248+ // a minimal tip cap. This is to prevent users from overpaying for gas when the network is not congested and a few
249+ // high-priced txs are causing the suggested tip cap to be high.
250+ var nonCongestedPrice * big.Int
251+ pendingTxCount , _ := oracle .backend .StatsWithMinBaseFee (headHeader .BaseFee )
252+ if pendingTxCount < oracle .congestedThreshold {
253+ // Before Curie (EIP-1559), we need to return the total suggested gas price. After Curie we return defaultGasTipCap wei as the tip cap,
254+ // as the base fee is set separately or added manually for legacy transactions.
255+ nonCongestedPrice = oracle .defaultGasTipCap
256+ if ! oracle .backend .ChainConfig ().IsCurie (headHeader .Number ) {
257+ nonCongestedPrice = oracle .defaultBasePrice
258+ }
259+ }
260+
239261 var (
240262 next = oldestBlock
241263 results = make (chan * blockFees , blocks )
@@ -244,6 +266,7 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLast
244266 for i , p := range rewardPercentiles {
245267 binary .LittleEndian .PutUint64 (percentileKey [i * 8 :(i + 1 )* 8 ], math .Float64bits (p ))
246268 }
269+
247270 for i := 0 ; i < maxBlockFetchers && i < blocks ; i ++ {
248271 go func () {
249272 for {
@@ -257,7 +280,7 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLast
257280 if pendingBlock != nil && blockNumber >= pendingBlock .NumberU64 () {
258281 fees .block , fees .receipts = pendingBlock , pendingReceipts
259282 fees .header = fees .block .Header ()
260- oracle .processBlock (fees , rewardPercentiles )
283+ oracle .processBlock (fees , rewardPercentiles , nonCongestedPrice )
261284 results <- fees
262285 } else {
263286 cacheKey := struct {
@@ -279,7 +302,7 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLast
279302 fees .header , fees .err = oracle .backend .HeaderByNumber (ctx , rpc .BlockNumber (blockNumber ))
280303 }
281304 if fees .header != nil && fees .err == nil {
282- oracle .processBlock (fees , rewardPercentiles )
305+ oracle .processBlock (fees , rewardPercentiles , nonCongestedPrice )
283306 if fees .err == nil {
284307 oracle .historyCache .Add (cacheKey , fees .results )
285308 }
0 commit comments