diff --git a/common/version/version.go b/common/version/version.go index ba510f3d8c..801661cb3f 100644 --- a/common/version/version.go +++ b/common/version/version.go @@ -5,7 +5,7 @@ import ( "runtime/debug" ) -var tag = "v4.7.9" +var tag = "v4.7.10" var commit = func() string { if info, ok := debug.ReadBuildInfo(); ok { diff --git a/rollup/conf/config.json b/rollup/conf/config.json index 537ac144b4..f4f382022f 100644 --- a/rollup/conf/config.json +++ b/rollup/conf/config.json @@ -58,7 +58,8 @@ "min_batches": 1, "max_batches": 6, "timeout": 7200, - "backlog_max": 75 + "backlog_max": 75, + "blob_fee_tolerance": 500000000 }, "gas_oracle_config": { "min_gas_price": 0, diff --git a/rollup/internal/config/relayer.go b/rollup/internal/config/relayer.go index 55f6393db9..2e50969ada 100644 --- a/rollup/internal/config/relayer.go +++ b/rollup/internal/config/relayer.go @@ -48,6 +48,10 @@ type BatchSubmission struct { TimeoutSec int64 `json:"timeout"` // The maximum number of pending batches to keep in the backlog. BacklogMax int64 `json:"backlog_max"` + // BlobFeeTolerance is the absolute tolerance (in wei) added to the target blob fee. + // If the current fee is below target + tolerance, we proceed with submission. + // This prevents skipping submission when the price difference is negligible. + BlobFeeTolerance uint64 `json:"blob_fee_tolerance"` } // ChainMonitor this config is used to get batch status from chain_monitor API. diff --git a/rollup/internal/controller/relayer/l2_relayer.go b/rollup/internal/controller/relayer/l2_relayer.go index 27cb11543f..c3ddbdac4f 100644 --- a/rollup/internal/controller/relayer/l2_relayer.go +++ b/rollup/internal/controller/relayer/l2_relayer.go @@ -1255,16 +1255,20 @@ func (r *Layer2Relayer) skipSubmitByFee(oldest time.Time, metrics *l2RelayerMetr target := calculateTargetPrice(windowSec, r.batchStrategy, oldest, hist) current := hist[len(hist)-1] + // apply absolute tolerance offset to target + tolerance := new(big.Int).SetUint64(r.cfg.BatchSubmission.BlobFeeTolerance) + threshold := new(big.Int).Add(target, tolerance) + currentFloat, _ := current.Float64() targetFloat, _ := target.Float64() metrics.rollupL2RelayerCurrentBlobPrice.Set(currentFloat) metrics.rollupL2RelayerTargetBlobPrice.Set(targetFloat) - // if current fee > target and still inside the timeout window, skip - if current.Cmp(target) > 0 && time.Since(oldest) < time.Duration(windowSec)*time.Second { + // if current fee > threshold (target + tolerance) and still inside the timeout window, skip + if current.Cmp(threshold) > 0 && time.Since(oldest) < time.Duration(windowSec)*time.Second { return true, fmt.Errorf( - "blob-fee above target & window not yet passed; current=%s target=%s age=%s", - current.String(), target.String(), time.Since(oldest), + "blob-fee above threshold & window not yet passed; current=%s target=%s threshold=%s tolerance=%s age=%s", + current.String(), target.String(), threshold.String(), tolerance.String(), time.Since(oldest), ) }