Repository: scroll-tech/scroll
Pull request #1664: Fix bug sequencer submission strategy and log commit price
Author: login: ranchalp
Labels: name: bump-version
description: Bump the version tag for deployment
Created: 2025-05-23T08:03:34Z | Merged: 2025-05-23T09:02:49Z

### Purpose or design rationale of this PR

Fix bug sequencer submission strategy and log commit price

### PR title

Your PR title must follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) (as we are doing squash merge for each PR), so it must start with one of the following [types](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#type):

- [ ] build: Changes that affect the build system or external dependencies (example scopes: yarn, eslint, typescript)
- [ ] ci: Changes to our CI configuration files and scripts (example scopes: vercel, github, cypress)
- [ ] docs: Documentation-only changes
- [ ] feat: A new feature
- [x] fix: A bug fix
- [ ] perf: A code change that improves performance
- [ ] refactor: A code change that doesn't fix a bug, or add a feature, or improves performance
- [ ] style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
- [ ] test: Adding missing tests or correcting existing tests


### Deployment tag versioning

Has `tag` in `common/version.go` been updated or have you added `bump-version` label to this PR?

- [ ] No, this PR doesn't involve a new deployment, git tag, docker image tag
- [x] Yes


### Breaking change label

Does this PR have the `breaking-change` label?

- [x] No, this PR is not a breaking change
- [ ] Yes


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Added a new metric to track the commit price for batch submissions, improving monitoring capabilities.

- **Bug Fixes**
  - Improved validation for batch submission strategies to ensure correct configuration and error handling.
  - Enhanced accuracy of metrics reporting for batch submission fees.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/common/version/version.go b/common/version/version.go
index cb1ff7acc6..419c8716ad 100644
--- a/common/version/version.go
+++ b/common/version/version.go
@@ -5,7 +5,7 @@ import (
 	"runtime/debug"
 )
 
-var tag = "v4.5.16"
+var tag = "v4.5.17"
 
 var commit = func() string {
 	if info, ok := debug.ReadBuildInfo(); ok {
diff --git a/rollup/internal/controller/relayer/l1_relayer.go b/rollup/internal/controller/relayer/l1_relayer.go
index 0088b14102..d9f0835d52 100644
--- a/rollup/internal/controller/relayer/l1_relayer.go
+++ b/rollup/internal/controller/relayer/l1_relayer.go
@@ -179,13 +179,13 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() {
 				return
 			}
 
-			hash, err := r.gasOracleSender.SendTransaction(block.Hash, &r.cfg.GasPriceOracleContractAddress, data, nil)
+			txHash, _, err := r.gasOracleSender.SendTransaction(block.Hash, &r.cfg.GasPriceOracleContractAddress, data, nil)
 			if err != nil {
 				log.Error("Failed to send gas oracle update tx to layer2", "block.Hash", block.Hash, "block.Height", block.Number, "block.BaseFee", baseFee, "block.BlobBaseFee", blobBaseFee, "err", err)
 				return
 			}
 
-			err = r.l1BlockOrm.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, block.Hash, types.GasOracleImporting, hash.String())
+			err = r.l1BlockOrm.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, block.Hash, types.GasOracleImporting, txHash.String())
 			if err != nil {
 				log.Error("UpdateGasOracleStatusAndOracleTxHash failed", "block.Hash", block.Hash, "block.Height", block.Number, "err", err)
 				return
@@ -195,7 +195,7 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() {
 			r.lastBlobBaseFee = blobBaseFee
 			r.metrics.rollupL1RelayerLatestBaseFee.Set(float64(r.lastBaseFee))
 			r.metrics.rollupL1RelayerLatestBlobBaseFee.Set(float64(r.lastBlobBaseFee))
-			log.Info("Update l1 base fee", "txHash", hash.String(), "baseFee", baseFee, "blobBaseFee", blobBaseFee)
+			log.Info("Update l1 base fee", "txHash", txHash.String(), "baseFee", baseFee, "blobBaseFee", blobBaseFee)
 		}
 	}
 }
diff --git a/rollup/internal/controller/relayer/l2_relayer.go b/rollup/internal/controller/relayer/l2_relayer.go
index 418762a470..8c74418fad 100644
--- a/rollup/internal/controller/relayer/l2_relayer.go
+++ b/rollup/internal/controller/relayer/l2_relayer.go
@@ -104,10 +104,15 @@ type StrategyParams struct {
 }
 
 // bestParams maps your 2h/5h/12h windows to their best rules.
+// Timeouts are in seconds, 2, 5 and 12 hours (and same + 20 mins to account for
+// time to create batch currently roughly, as time is measured from block creation)
 var bestParams = map[uint64]StrategyParams{
-	2 * 3600:  {BaselineType: PctMin, BaselineParam: 0.10, Gamma: 0.4, Beta: 8, RelaxType: Exponential},
-	5 * 3600:  {BaselineType: PctMin, BaselineParam: 0.30, Gamma: 0.6, Beta: 20, RelaxType: Sigmoid},
-	12 * 3600: {BaselineType: PctMin, BaselineParam: 0.50, Gamma: 0.5, Beta: 20, RelaxType: Sigmoid},
+	7200:  {BaselineType: PctMin, BaselineParam: 0.10, Gamma: 0.4, Beta: 8, RelaxType: Exponential},
+	8400:  {BaselineType: PctMin, BaselineParam: 0.10, Gamma: 0.4, Beta: 8, RelaxType: Exponential},
+	18000: {BaselineType: PctMin, BaselineParam: 0.30, Gamma: 0.6, Beta: 20, RelaxType: Sigmoid},
+	19200: {BaselineType: PctMin, BaselineParam: 0.30, Gamma: 0.6, Beta: 20, RelaxType: Sigmoid},
+	42800: {BaselineType: PctMin, BaselineParam: 0.50, Gamma: 0.5, Beta: 20, RelaxType: Sigmoid},
+	44400: {BaselineType: PctMin, BaselineParam: 0.50, Gamma: 0.5, Beta: 20, RelaxType: Sigmoid},
 }
 
 // NewLayer2Relayer will return a new instance of Layer2RelayerClient
@@ -147,6 +152,11 @@ func NewLayer2Relayer(ctx context.Context, l2Client *ethclient.Client, db *gorm.
 		return nil, fmt.Errorf("invalid service type for l2_relayer: %v", serviceType)
 	}
 
+	strategy, ok := bestParams[uint64(cfg.BatchSubmission.TimeoutSec)]
+	if !ok {
+		return nil, fmt.Errorf("invalid timeout for batch submission: %v", cfg.BatchSubmission.TimeoutSec)
+	}
+
 	layer2Relayer := &Layer2Relayer{
 		ctx: ctx,
 		db:  db,
@@ -164,7 +174,7 @@ func NewLayer2Relayer(ctx context.Context, l2Client *ethclient.Client, db *gorm.
 		l1RollupABI:    bridgeAbi.ScrollChainABI,
 
 		l2GasOracleABI: bridgeAbi.L2GasPriceOracleABI,
-		batchStrategy:  bestParams[uint64(cfg.BatchSubmission.TimeoutSec)],
+		batchStrategy:  strategy,
 		cfg:            cfg,
 		chainCfg:       chainCfg,
 	}
@@ -271,11 +281,11 @@ func (r *Layer2Relayer) commitGenesisBatch(batchHash string, batchHeader []byte,
 	}
 
 	// submit genesis batch to L1 rollup contract
-	txHash, err := r.commitSender.SendTransaction(batchHash, &r.cfg.RollupContractAddress, calldata, nil)
+	txHash, _, err := r.commitSender.SendTransaction(batchHash, &r.cfg.RollupContractAddress, calldata, nil)
 	if err != nil {
 		return fmt.Errorf("failed to send import genesis batch tx to L1, error: %v", err)
 	}
-	log.Info("importGenesisBatch transaction sent", "contract", r.cfg.RollupContractAddress, "txHash", txHash.String(), "batchHash", batchHash)
+	log.Info("importGenesisBatch transaction sent", "contract", r.cfg.RollupContractAddress, "txHash", txHash, "batchHash", batchHash)
 
 	// wait for confirmation
 	// we assume that no other transactions are sent before initializeGenesis completes
@@ -336,11 +346,11 @@ func (r *Layer2Relayer) ProcessPendingBatches() {
 	var forceSubmit bool
 
 	startChunk, err := r.chunkOrm.GetChunkByIndex(r.ctx, dbBatches[0].StartChunkIndex)
-	oldestBlockTimestamp := time.Unix(int64(startChunk.StartBlockTime), 0)
 	if err != nil {
 		log.Error("failed to get first chunk", "err", err, "batch index", dbBatches[0].Index, "chunk index", dbBatches[0].StartChunkIndex)
 		return
 	}
+	oldestBlockTimestamp := time.Unix(int64(startChunk.StartBlockTime), 0)
 
 	// if the batch with the oldest index is too old, we force submit all batches that we have so far in the next step
 	if r.cfg.BatchSubmission.TimeoutSec > 0 && time.Since(oldestBlockTimestamp) > time.Duration(r.cfg.BatchSubmission.TimeoutSec)*time.Second {
@@ -467,7 +477,7 @@ func (r *Layer2Relayer) ProcessPendingBatches() {
 		return
 	}
 
-	txHash, err := r.commitSender.SendTransaction(r.contextIDFromBatches(batchesToSubmit), &r.cfg.RollupContractAddress, calldata, blobs)
+	txHash, blobBaseFee, err := r.commitSender.SendTransaction(r.contextIDFromBatches(batchesToSubmit), &r.cfg.RollupContractAddress, calldata, blobs)
 	if err != nil {
 		if errors.Is(err, sender.ErrTooManyPendingBlobTxs) {
 			r.metrics.rollupL2RelayerProcessPendingBatchErrTooManyPendingBlobTxsTotal.Inc()
@@ -508,6 +518,7 @@ func (r *Layer2Relayer) ProcessPendingBatches() {
 	r.metrics.rollupL2RelayerProcessPendingBatchSuccessTotal.Add(float64(len(batchesToSubmit)))
 	r.metrics.rollupL2RelayerProcessBatchesPerTxCount.Set(float64(len(batchesToSubmit)))
 	r.metrics.rollupL2RelayerCommitLatency.Set(time.Since(oldestBlockTimestamp).Seconds())
+	r.metrics.rollupL2RelayerCommitPrice.Set(float64(blobBaseFee))
 
 	log.Info("Sent the commitBatches tx to layer1", "batches count", len(batchesToSubmit), "start index", firstBatch.Index, "start hash", firstBatch.Hash, "end index", lastBatch.Index, "end hash", lastBatch.Hash, "tx hash", txHash.String())
 }
@@ -691,7 +702,7 @@ func (r *Layer2Relayer) finalizeBundle(bundle *orm.Bundle, withProof bool) error
 		return fmt.Errorf("unsupported codec version in finalizeBundle, bundle index: %v, version: %d", bundle.Index, bundle.CodecVersion)
 	}
 
-	txHash, err := r.finalizeSender.SendTransaction("finalizeBundle-"+bundle.Hash, &r.cfg.RollupContractAddress, calldata, nil)
+	txHash, _, err := r.finalizeSender.SendTransaction("finalizeBundle-"+bundle.Hash, &r.cfg.RollupContractAddress, calldata, nil)
 	if err != nil {
 		log.Error("finalizeBundle in layer1 failed", "with proof", withProof, "index", bundle.Index,
 			"start batch index", bundle.StartBatchIndex, "end batch index", bundle.EndBatchIndex,
diff --git a/rollup/internal/controller/relayer/l2_relayer_metrics.go b/rollup/internal/controller/relayer/l2_relayer_metrics.go
index 00e550588f..b6c883ceaa 100644
--- a/rollup/internal/controller/relayer/l2_relayer_metrics.go
+++ b/rollup/internal/controller/relayer/l2_relayer_metrics.go
@@ -31,6 +31,7 @@ type l2RelayerMetrics struct {
 	rollupL2RelayerTargetBlobPrice  prometheus.Gauge
 	rollupL2RelayerCommitLatency    prometheus.Gauge
 	rollupL2RelayerBacklogCounts    prometheus.Gauge
+	rollupL2RelayerCommitPrice      prometheus.Gauge
 }
 
 var (
@@ -125,6 +126,10 @@ func initL2RelayerMetrics(reg prometheus.Registerer) *l2RelayerMetrics {
 				Name: "rollup_l2_relayer_backlog_counts",
 				Help: "The number of pending batches in the backlog",
 			}),
+			rollupL2RelayerCommitPrice: promauto.With(reg).NewGauge(prometheus.GaugeOpts{
+				Name: "rollup_l2_relayer_commit_price",
+				Help: "The commit price for the L2 relayer's submission strategy",
+			}),
 		}
 	})
 	return l2RelayerMetric
diff --git a/rollup/internal/controller/sender/sender.go b/rollup/internal/controller/sender/sender.go
index 1b8ccd3aa2..d5a4db5d3b 100644
--- a/rollup/internal/controller/sender/sender.go
+++ b/rollup/internal/controller/sender/sender.go
@@ -171,7 +171,7 @@ func (s *Sender) getFeeData(target *common.Address, data []byte, sidecar *gethTy
 }
 
 // SendTransaction send a signed L2tL1 transaction.
-func (s *Sender) SendTransaction(contextID string, target *common.Address, data []byte, blobs []*kzg4844.Blob) (common.Hash, error) {
+func (s *Sender) SendTransaction(contextID string, target *common.Address, data []byte, blobs []*kzg4844.Blob) (common.Hash, uint64, error) {
 	s.metrics.sendTransactionTotal.WithLabelValues(s.service, s.name).Inc()
 	var (
 		feeData *FeeData
@@ -190,37 +190,37 @@ func (s *Sender) SendTransaction(contextID string, target *common.Address, data
 			numPendingTransactions, err = s.pendingTransactionOrm.GetCountPendingTransactionsBySenderType(s.ctx, s.senderType)
 			if err != nil {
 				log.Error("failed to count pending transactions", "err: %w", err)
-				return common.Hash{}, fmt.Errorf("failed to count pending transactions, err: %w", err)
+				return common.Hash{}, 0, fmt.Errorf("failed to count pending transactions, err: %w", err)
 			}
 			if numPendingTransactions >= s.config.MaxPendingBlobTxs {
-				return common.Hash{}, ErrTooManyPendingBlobTxs
+				return common.Hash{}, 0, ErrTooManyPendingBlobTxs
 			}
 
 		}
 		sidecar, err = makeSidecar(blobs)
 		if err != nil {
 			log.Error("failed to make sidecar for blob transaction", "error", err)
-			return common.Hash{}, fmt.Errorf("failed to make sidecar for blob transaction, err: %w", err)
+			return common.Hash{}, 0, fmt.Errorf("failed to make sidecar for blob transaction, err: %w", err)
 		}
 	}
 
 	blockNumber, baseFee, blobBaseFee, err := s.getBlockNumberAndBaseFeeAndBlobFee(s.ctx)
 	if err != nil {
 		log.Error("failed to get block number and base fee", "error", err)
-		return common.Hash{}, fmt.Errorf("failed to get block number and base fee, err: %w", err)
+		return common.Hash{}, 0, fmt.Errorf("failed to get block number and base fee, err: %w", err)
 	}
 
 	if feeData, err = s.getFeeData(target, data, sidecar, baseFee, blobBaseFee); err != nil {
 		s.metrics.sendTransactionFailureGetFee.WithLabelValues(s.service, s.name).Inc()
 		log.Error("failed to get fee data", "from", s.transactionSigner.GetAddr().String(), "nonce", s.transactionSigner.GetNonce(), "err", err)
-		return common.Hash{}, fmt.Errorf("failed to get fee data, err: %w", err)
+		return common.Hash{}, 0, fmt.Errorf("failed to get fee data, err: %w", err)
 	}
 
 	signedTx, err := s.createTx(feeData, target, data, sidecar, s.transactionSigner.GetNonce())
 	if err != nil {
 		s.metrics.sendTransactionFailureSendTx.WithLabelValues(s.service, s.name).Inc()
 		log.Error("failed to create signed tx (non-resubmit case)", "from", s.transactionSigner.GetAddr().String(), "nonce", s.transactionSigner.GetNonce(), "err", err)
-		return common.Hash{}, fmt.Errorf("failed to create signed transaction, err: %w", err)
+		return common.Hash{}, 0, fmt.Errorf("failed to create signed transaction, err: %w", err)
 	}
 
 	// Insert the transaction into the pending transaction table.
@@ -228,14 +228,14 @@ func (s *Sender) SendTransaction(contextID string, target *common.Address, data
 	// This case will be handled by the checkPendingTransaction function.
 	if err = s.pendingTransactionOrm.InsertPendingTransaction(s.ctx, contextID, s.getSenderMeta(), signedTx, blockNumber); err != nil {
 		log.Error("failed to insert transaction", "from", s.transactionSigner.GetAddr().String(), "nonce", s.transactionSigner.GetNonce(), "err", err)
-		return common.Hash{}, fmt.Errorf("failed to insert transaction, err: %w", err)
+		return common.Hash{}, 0, fmt.Errorf("failed to insert transaction, err: %w", err)
 	}
 
 	if err := s.client.SendTransaction(s.ctx, signedTx); err != nil {
 		// Delete the transaction from the pending transaction table if it fails to send.
 		if updateErr := s.pendingTransactionOrm.DeleteTransactionByTxHash(s.ctx, signedTx.Hash()); updateErr != nil {
 			log.Error("failed to delete transaction", "tx hash", signedTx.Hash().String(), "from", s.transactionSigner.GetAddr().String(), "nonce", signedTx.Nonce(), "err", updateErr)
-			return common.Hash{}, fmt.Errorf("failed to delete transaction, err: %w", updateErr)
+			return common.Hash{}, 0, fmt.Errorf("failed to delete transaction, err: %w", updateErr)
 		}
 
 		log.Error("failed to send tx", "tx hash", signedTx.Hash().String(), "from", s.transactionSigner.GetAddr().String(), "nonce", signedTx.Nonce(), "err", err)
@@ -244,12 +244,12 @@ func (s *Sender) SendTransaction(contextID string, target *common.Address, data
 		if strings.Contains(err.Error(), "nonce too low") {
 			s.resetNonce(context.Background())
 		}
-		return common.Hash{}, fmt.Errorf("failed to send transaction, err: %w", err)
+		return common.Hash{}, 0, fmt.Errorf("failed to send transaction, err: %w", err)
 	}
 
 	s.transactionSigner.SetNonce(signedTx.Nonce() + 1)
 
-	return signedTx.Hash(), nil
+	return signedTx.Hash(), blobBaseFee, nil
 }
 
 func (s *Sender) createTx(feeData *FeeData, target *common.Address, data []byte, sidecar *gethTypes.BlobTxSidecar, nonce uint64) (*gethTypes.Transaction, error) {
diff --git a/rollup/internal/controller/sender/sender_test.go b/rollup/internal/controller/sender/sender_test.go
index 80164170a0..7ca8da5c8d 100644
--- a/rollup/internal/controller/sender/sender_test.go
+++ b/rollup/internal/controller/sender/sender_test.go
@@ -187,7 +187,7 @@ func testSendAndRetrieveTransaction(t *testing.T) {
 		if txBlob[i] != nil {
 			blobs = []*kzg4844.Blob{txBlob[i]}
 		}
-		hash, err := s.SendTransaction("0", &common.Address{}, nil, blobs)
+		hash, _, err := s.SendTransaction("0", &common.Address{}, nil, blobs)
 		assert.NoError(t, err)
 		txs, err := s.pendingTransactionOrm.GetPendingOrReplacedTransactionsBySenderType(context.Background(), s.senderType, 1)
 		assert.NoError(t, err)
@@ -545,10 +545,10 @@ func testResubmitNonceGappedTransaction(t *testing.T) {
 		if txBlob[i] != nil {
 			blobs = []*kzg4844.Blob{txBlob[i]}
 		}
-		_, err = s.SendTransaction("test-1", &common.Address{}, nil, blobs)
+		_, _, err = s.SendTransaction("test-1", &common.Address{}, nil, blobs)
 		assert.NoError(t, err)
 
-		_, err = s.SendTransaction("test-2", &common.Address{}, nil, blobs)
+		_, _, err = s.SendTransaction("test-2", &common.Address{}, nil, blobs)
 		assert.NoError(t, err)
 
 		s.checkPendingTransaction()
@@ -589,7 +589,7 @@ func testCheckPendingTransactionTxConfirmed(t *testing.T) {
 			return nil
 		})
 
-		_, err = s.SendTransaction("test", &common.Address{}, nil, randBlobs(1))
+		_, _, err = s.SendTransaction("test", &common.Address{}, nil, randBlobs(1))
 		assert.NoError(t, err)
 
 		txs, err := s.pendingTransactionOrm.GetPendingOrReplacedTransactionsBySenderType(context.Background(), s.senderType, 1)
@@ -631,7 +631,7 @@ func testCheckPendingTransactionResubmitTxConfirmed(t *testing.T) {
 			return nil
 		})
 
-		originTxHash, err := s.SendTransaction("test", &common.Address{}, nil, randBlobs(1))
+		originTxHash, _, err := s.SendTransaction("test", &common.Address{}, nil, randBlobs(1))
 		assert.NoError(t, err)
 
 		txs, err := s.pendingTransactionOrm.GetPendingOrReplacedTransactionsBySenderType(context.Background(), s.senderType, 1)
@@ -691,7 +691,7 @@ func testCheckPendingTransactionReplacedTxConfirmed(t *testing.T) {
 			return nil
 		})
 
-		txHash, err := s.SendTransaction("test", &common.Address{}, nil, randBlobs(1))
+		txHash, _, err := s.SendTransaction("test", &common.Address{}, nil, randBlobs(1))
 		assert.NoError(t, err)
 
 		txs, err := s.pendingTransactionOrm.GetPendingOrReplacedTransactionsBySenderType(context.Background(), s.senderType, 1)
@@ -761,7 +761,7 @@ func testCheckPendingTransactionTxMultipleTimesWithOnlyOneTxPending(t *testing.T
 			return nil
 		})
 
-		_, err = s.SendTransaction("test", &common.Address{}, nil, randBlobs(1))
+		_, _, err = s.SendTransaction("test", &common.Address{}, nil, randBlobs(1))
 		assert.NoError(t, err)
 
 		txs, err := s.pendingTransactionOrm.GetPendingOrReplacedTransactionsBySenderType(context.Background(), s.senderType, 1)
@@ -835,7 +835,7 @@ func testBlobTransactionWithBlobhashOpContractCall(t *testing.T) {
 	assert.NoError(t, err)
 	defer s.Stop()
 
-	_, err = s.SendTransaction("0", &testContractsAddress, data, blobs)
+	_, _, err = s.SendTransaction("0", &testContractsAddress, data, blobs)
 	assert.NoError(t, err)
 
 	var txHash common.Hash
@@ -893,10 +893,10 @@ func testSendBlobCarryingTxOverLimit(t *testing.T) {
 	assert.NoError(t, err)
 
 	for i := 0; i < int(cfgCopy.MaxPendingBlobTxs); i++ {
-		_, err = s.SendTransaction("0", &common.Address{}, nil, randBlobs(1))
+		_, _, err = s.SendTransaction("0", &common.Address{}, nil, randBlobs(1))
 		assert.NoError(t, err)
 	}
-	_, err = s.SendTransaction("0", &common.Address{}, nil, randBlobs(1))
+	_, _, err = s.SendTransaction("0", &common.Address{}, nil, randBlobs(1))
 	assert.ErrorIs(t, err, ErrTooManyPendingBlobTxs)
 	s.Stop()
 }


Reviews:
user: login: colinlyguo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T08:06:03Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between ae34020c34eed341bead1a5df5fac223b4ff66a1 and 4771437745af7dc105662527cca48a8059f6e88f.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `rollup/internal/controller/relayer/l2_relayer.go` (4 hunks)
* `rollup/internal/controller/relayer/l2_relayer_metrics.go` (2 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (1)</summary>

<details>
<summary>rollup/internal/controller/relayer/l2_relayer.go (1)</summary><blockquote>

<details>
<summary>rollup/internal/config/relayer.go (1)</summary>

* `BatchSubmission` (34-43)

</details>

</blockquote></details>

</details><details>
<summary>🪛 golangci-lint (1.64.8)</summary>

<details>
<summary>rollup/internal/controller/relayer/l2_relayer.go</summary>

1130-1130: cannot use target (variable of type *big.Int) as float64 value in argument to r.metrics.rollupL2RelayerCommitPrice.Set

(typecheck)

</details>

</details>
<details>
<summary>🪛 GitHub Actions: Rollup</summary>

<details>
<summary>rollup/internal/controller/relayer/l2_relayer.go</summary>

[error] 1130-1130: Type mismatch error: cannot use target (variable of type *big.Int) as float64 value in argument to r.metrics.rollupL2RelayerCommitPrice.Set

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: tests

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>rollup/internal/controller/relayer/l2_relayer_metrics.go (1)</summary>

`34-34`: **LGTM! Clean metric addition.**

The new `rollupL2RelayerCommitPrice` metric is properly declared and initialized following the established patterns in the codebase. The naming and help text clearly indicate its purpose for tracking the L2 relayer's submission strategy commit price.




Also applies to: 129-132

</details>
<details>
<summary>rollup/internal/controller/relayer/l2_relayer.go (2)</summary>

`107-116`: **Good expansion of batch submission strategies.**

The addition of offset timeout keys (adding 20 minutes to account for batch creation time) provides more granular strategy options. The comment clearly explains the rationale, and the parameter values maintain consistency with the original strategies.

---

`155-158`: **Excellent improvement to strategy validation.**

Adding explicit validation when selecting a batch submission strategy prevents potential runtime panics from invalid map access. This defensive programming approach will help catch configuration errors early.




Also applies to: 177-177

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-23T08:07:53Z
user: login: ranchalp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T08:15:37Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 8b5c670a185a2afa444adb057599d0444b0cb56d and 48ce121f8a4342886a2a69c4ba22ad024288e449.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `rollup/internal/controller/relayer/l1_relayer.go` (2 hunks)
* `rollup/internal/controller/relayer/l2_relayer.go` (8 hunks)
* `rollup/internal/controller/sender/sender.go` (3 hunks)
* `rollup/internal/controller/sender/sender_test.go` (8 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* rollup/internal/controller/relayer/l1_relayer.go

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* rollup/internal/controller/relayer/l2_relayer.go

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 golangci-lint (1.64.8)</summary>

<details>
<summary>rollup/internal/controller/sender/sender.go</summary>

193-193: not enough return values
	have (nil, error)
	want ("github.com/scroll-tech/go-ethereum/common".Hash, error, uint64)

(typecheck)

---

196-196: not enough return values
	have (nil, error)
	want ("github.com/scroll-tech/go-ethereum/common".Hash, error, uint64)

(typecheck)

---

203-203: not enough return values
	have (nil, error)
	want ("github.com/scroll-tech/go-ethereum/common".Hash, error, uint64)

(typecheck)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: tests

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>rollup/internal/controller/sender/sender.go (2)</summary>

`174-174`: **LGTM: Method signature updated to return blobBaseFee.**

The addition of the third return value `uint64` (blobBaseFee) aligns with the PR objective to add logging for commit price metrics.

---

`252-252`: **LGTM: Successful return correctly implements new signature.**

The successful return statement properly returns all three values: transaction hash, nil error, and blobBaseFee.

</details>
<details>
<summary>rollup/internal/controller/sender/sender_test.go (1)</summary>

`190-190`: **LGTM: Test calls properly updated for new method signature.**

All calls to `SendTransaction` correctly capture the additional `blobBaseFee` return value using `_` to ignore it, which is appropriate for test scenarios that don't need to validate the metric value.



Also applies to: 548-548, 551-551, 592-592, 634-634, 694-694, 764-764, 838-838, 896-896, 899-899

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-23T08:39:39Z
user: login: jonastheis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T08:44:18Z
user: login: colinlyguo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T08:52:14Z
user: login: ranchalp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T08:56:31Z
user: login: colinlyguo
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T08:59:03Z
user: login: jonastheis
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T09:00:09Z

Review comments:
diff_hunk: @@ -1118,6 +1127,7 @@ func (r *Layer2Relayer) skipSubmitByFee(oldest time.Time, metrics *l2RelayerMetr
 		)
 	}
 
+	r.metrics.rollupL2RelayerCommitPrice.Set(target)
path: rollup/internal/controller/relayer/l2_relayer.go
user: login: colinlyguo
body: Should we track this metric when `forceSubmit == true`?
created_at: 2025-05-23T08:06:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1118,6 +1127,7 @@ func (r *Layer2Relayer) skipSubmitByFee(oldest time.Time, metrics *l2RelayerMetr
 		)
 	}
 
+	r.metrics.rollupL2RelayerCommitPrice.Set(target)
path: rollup/internal/controller/relayer/l2_relayer.go
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix type mismatch error in metric setting.**

The code is trying to pass a `*big.Int` to a function expecting `float64`. This will cause a compilation error.



Apply this fix to convert the big.Int to float64:

```diff
-	r.metrics.rollupL2RelayerCommitPrice.Set(target)
+	targetFloat, _ := target.Float64()
+	r.metrics.rollupL2RelayerCommitPrice.Set(targetFloat)
```

This follows the same pattern used earlier in the function for `rollupL2RelayerTargetBlobPrice` (lines 1117-1120).


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
-   r.metrics.rollupL2RelayerCommitPrice.Set(target)
+   targetFloat, _ := target.Float64()
+   r.metrics.rollupL2RelayerCommitPrice.Set(targetFloat)
```

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 golangci-lint (1.64.8)</summary>

1130-1130: cannot use target (variable of type *big.Int) as float64 value in argument to r.metrics.rollupL2RelayerCommitPrice.Set

(typecheck)

</details>
<details>
<summary>🪛 GitHub Actions: Rollup</summary>

[error] 1130-1130: Type mismatch error: cannot use target (variable of type *big.Int) as float64 value in argument to r.metrics.rollupL2RelayerCommitPrice.Set

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In rollup/internal/controller/relayer/l2_relayer.go at line 1130, the code
attempts to set a metric using a *big.Int value directly, causing a type
mismatch error since the metric expects a float64. Fix this by converting the
*big.Int value to float64 before passing it to the Set method, following the
same conversion pattern used earlier in the function for
rollupL2RelayerTargetBlobPrice around lines 1117-1120.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-23T08:07:52Z
author_association: NONE
diff_hunk: @@ -1118,6 +1127,7 @@ func (r *Layer2Relayer) skipSubmitByFee(oldest time.Time, metrics *l2RelayerMetr
 		)
 	}
 
+	r.metrics.rollupL2RelayerCommitPrice.Set(target)
path: rollup/internal/controller/relayer/l2_relayer.go
user: login: ranchalp
body: true, thanks.
created_at: 2025-05-23T08:15:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -190,52 +190,52 @@ func (s *Sender) SendTransaction(contextID string, target *common.Address, data
 			numPendingTransactions, err = s.pendingTransactionOrm.GetCountPendingTransactionsBySenderType(s.ctx, s.senderType)
 			if err != nil {
 				log.Error("failed to count pending transactions", "err: %w", err)
-				return common.Hash{}, fmt.Errorf("failed to count pending transactions, err: %w", err)
+				return nil, fmt.Errorf("failed to count pending transactions, err: %w", err)
path: rollup/internal/controller/sender/sender.go
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix compilation errors: Update error returns to match new method signature.**

All error return statements need to return 3 values to match the new method signature `(common.Hash, error, uint64)`. Currently they only return 2 values, causing compilation failures as confirmed by static analysis.



Apply this fix to all error return statements:

```diff
-		return nil, fmt.Errorf("failed to count pending transactions, err: %w", err)
+		return nil, fmt.Errorf("failed to count pending transactions, err: %w", err), 0
```

```diff
-		return nil, ErrTooManyPendingBlobTxs
+		return nil, ErrTooManyPendingBlobTxs, 0
```

```diff
-		return nil, fmt.Errorf("failed to make sidecar for blob transaction, err: %w", err)
+		return nil, fmt.Errorf("failed to make sidecar for blob transaction, err: %w", err), 0
```

```diff
-		return nil, fmt.Errorf("failed to get block number and base fee, err: %w", err)
+		return nil, fmt.Errorf("failed to get block number and base fee, err: %w", err), 0
```

```diff
-		return nil, fmt.Errorf("failed to get fee data, err: %w", err)
+		return nil, fmt.Errorf("failed to get fee data, err: %w", err), 0
```

```diff
-		return nil, fmt.Errorf("failed to create signed transaction, err: %w", err)
+		return nil, fmt.Errorf("failed to create signed transaction, err: %w", err), 0
```

```diff
-		return nil, fmt.Errorf("failed to insert transaction, err: %w", err)
+		return nil, fmt.Errorf("failed to insert transaction, err: %w", err), 0
```

```diff
-			return nil, fmt.Errorf("failed to delete transaction, err: %w", updateErr)
+			return nil, fmt.Errorf("failed to delete transaction, err: %w", updateErr), 0
```

```diff
-		return nil, fmt.Errorf("failed to send transaction, err: %w", err)
+		return nil, fmt.Errorf("failed to send transaction, err: %w", err), 0
```


Also applies to: 196-196, 203-203, 210-210, 216-216, 223-223, 231-231, 238-238, 247-247

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 golangci-lint (1.64.8)</summary>

193-193: not enough return values
	have (nil, error)
	want ("github.com/scroll-tech/go-ethereum/common".Hash, error, uint64)

(typecheck)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In rollup/internal/controller/sender/sender.go at lines 193, 196, 203, 210, 216,
223, 231, 238, and 247, update all error return statements to return three
values instead of two to match the new method signature (common.Hash, error,
uint64). Specifically, modify each return statement to include a zero value for
common.Hash, the error itself, and a zero value for uint64, ensuring the
function compiles without errors.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit ae2bcb9
created_at: 2025-05-23T08:39:38Z
author_association: NONE
diff_hunk: @@ -244,12 +244,12 @@ func (s *Sender) SendTransaction(contextID string, target *common.Address, data
 		if strings.Contains(err.Error(), "nonce too low") {
 			s.resetNonce(context.Background())
 		}
-		return common.Hash{}, fmt.Errorf("failed to send transaction, err: %w", err)
+		return common.Hash{}, fmt.Errorf("failed to send transaction, err: %w", err), 0
 	}
 
 	s.transactionSigner.SetNonce(signedTx.Nonce() + 1)
 
-	return signedTx.Hash(), nil
+	return signedTx.Hash(), nil, blobBaseFee
path: rollup/internal/controller/sender/sender.go
user: login: jonastheis
body: Go idiomatic is having the error as the last element of the return values
created_at: 2025-05-23T08:44:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -244,12 +244,12 @@ func (s *Sender) SendTransaction(contextID string, target *common.Address, data
 		if strings.Contains(err.Error(), "nonce too low") {
 			s.resetNonce(context.Background())
 		}
-		return common.Hash{}, fmt.Errorf("failed to send transaction, err: %w", err)
+		return common.Hash{}, fmt.Errorf("failed to send transaction, err: %w", err), 0
path: rollup/internal/controller/sender/sender.go
user: login: colinlyguo
body: ```suggestion
		return common.Hash{}, 0, fmt.Errorf("failed to send transaction, err: %w", err)
```
created_at: 2025-05-23T08:52:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -244,12 +244,12 @@ func (s *Sender) SendTransaction(contextID string, target *common.Address, data
 		if strings.Contains(err.Error(), "nonce too low") {
 			s.resetNonce(context.Background())
 		}
-		return common.Hash{}, fmt.Errorf("failed to send transaction, err: %w", err)
+		return common.Hash{}, fmt.Errorf("failed to send transaction, err: %w", err), 0
path: rollup/internal/controller/sender/sender.go
user: login: ranchalp
body: Concurrently fixed locally
created_at: 2025-05-23T08:56:31Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-05-23T08:03:41Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: rate limited by coderabbit.ai -->

> [!WARNING]
> ## Rate limit exceeded
> 
> @ranchalp has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait **10 minutes and 46 seconds** before requesting another review.
> 
> <details>
> <summary>⌛ How to resolve this issue?</summary>
> 
> After the wait time has elapsed, a review can be triggered using the `@coderabbitai review` command as a PR comment. Alternatively, push new commits to this PR.
> 
> We recommend that you space out your commits to avoid hitting the rate limit.
> 
> </details>
> 
> 
> <details>
> <summary>🚦 How do rate limits work?</summary>
> 
> CodeRabbit enforces hourly rate limits for each developer per organization.
> 
> Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.
> 
> Please see our [FAQ](https://docs.coderabbit.ai/faq) for further information.
> 
> </details>
> 
> <details>
> <summary>📥 Commits</summary>
> 
> Reviewing files that changed from the base of the PR and between 48ce121f8a4342886a2a69c4ba22ad024288e449 and d1a18932c91fd0de72cf00dc32d8e104f3c433fc.
> 
> </details>
> 
> <details>
> <summary>📒 Files selected for processing (4)</summary>
> 
> * `rollup/internal/controller/relayer/l1_relayer.go` (2 hunks)
> * `rollup/internal/controller/relayer/l2_relayer.go` (8 hunks)
> * `rollup/internal/controller/sender/sender.go` (3 hunks)
> * `rollup/internal/controller/sender/sender_test.go` (8 hunks)
> 
> </details>

<!-- end of auto-generated comment: rate limited by coderabbit.ai -->
<!-- walkthrough_start -->

```markdown
## Walkthrough

This update expands the batch submission strategy timeouts in the Layer 2 relayer, introducing additional offset timeout keys and enforcing explicit validation when selecting a strategy. It also adds a new Prometheus metric to track the commit price. The `SendTransaction` method signature was changed to return an additional `blobBaseFee` value, and all call sites were updated accordingly. Minor logging and metrics improvements were made in the relayer's processing logic.

## Changes

| File(s)                                                                                  | Change Summary                                                                                                 |
|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|
| rollup/internal/controller/relayer/l2_relayer.go                                        | Expanded `bestParams` map with additional timeout keys offset by +20 minutes; explicit batch strategy lookup with error handling; updated `SendTransaction` calls to capture new return value; added metric setting for commit price; minor logging and error handling adjustments. |
| rollup/internal/controller/relayer/l2_relayer_metrics.go                                | Added a new Prometheus gauge metric `rollupL2RelayerCommitPrice` to the metrics struct and initialized it.      |
| rollup/internal/controller/sender/sender.go                                             | Updated `SendTransaction` method signature to return an additional `blobBaseFee` value; updated error returns to `nil` error where appropriate. |
| rollup/internal/controller/sender/sender_test.go                                        | Updated all `SendTransaction` calls in tests to capture the new third return value, ignoring it with `_`.       |
| rollup/internal/controller/relayer/l1_relayer.go                                        | Renamed transaction hash variable from `hash` to `txHash` and updated `SendTransaction` calls to capture three return values. |
| common/version/version.go                                                                | Updated version tag from "v4.5.16" to "v4.5.17".                                                              |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Config
    participant L2Relayer
    participant Sender
    participant Metrics

    Config->>L2Relayer: Provide batch submission timeout
    L2Relayer->>L2Relayer: Lookup batch strategy in bestParams
    alt Timeout invalid
        L2Relayer->>Config: Return error
    else Timeout valid
        L2Relayer->>Sender: SendTransaction(...) returns (txHash, err, blobBaseFee)
        alt Transaction success
            L2Relayer->>Metrics: Set rollupL2RelayerCommitPrice(blobBaseFee)
        end
    end
```

## Possibly related PRs

- [scroll-tech/scroll#1564](https://github.com/scroll-tech/scroll/pull/1564): Refactors and improves the `SendTransaction` method and its usage in the sender package, directly related to the signature change and usage updates.
- [scroll-tech/scroll#1659](https://github.com/scroll-tech/scroll/pull/1659): Extends batch submission timeout keys and adds validation and metrics around the batch submission strategy, building on the same logic modified here.
- [scroll-tech/scroll#1531](https://github.com/scroll-tech/scroll/pull/1531): Modifies transaction sending and gas price handling in the sender package, related but focusing on gas price adjustment logic.

## Suggested reviewers

- colinlyguo
- jonastheis
- Thegaram

## Poem

> 🐇 Hopping through code with a metric in hand,  
> Timeouts doubled, strategies planned.  
> Transactions sent with a fee now known,  
> Commit prices tracked, in logs they're shown.  
> A rabbit’s work, precise and bright,  
> Coding through day and into night! ✨
```

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=scroll-tech/scroll&utm_content=1664):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: codecov-commenter
created_at: 2025-05-23T09:03:21Z
body: ## [Codecov](https://app.codecov.io/gh/scroll-tech/scroll/pull/1664?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech) Report
Attention: Patch coverage is `51.72414%` with `14 lines` in your changes missing coverage. Please review.
> Project coverage is 40.90%. Comparing base [(`ae34020`)](https://app.codecov.io/gh/scroll-tech/scroll/commit/ae34020c34eed341bead1a5df5fac223b4ff66a1?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech) to head [(`d1a1893`)](https://app.codecov.io/gh/scroll-tech/scroll/commit/d1a18932c91fd0de72cf00dc32d8e104f3c433fc?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech).
> Report is 1 commits behind head on develop.

| [Files with missing lines](https://app.codecov.io/gh/scroll-tech/scroll/pull/1664?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech) | Patch % | Lines |
|---|---|---|
| [rollup/internal/controller/sender/sender.go](https://app.codecov.io/gh/scroll-tech/scroll/pull/1664?src=pr&el=tree&filepath=rollup%2Finternal%2Fcontroller%2Fsender%2Fsender.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech#diff-cm9sbHVwL2ludGVybmFsL2NvbnRyb2xsZXIvc2VuZGVyL3NlbmRlci5nbw==) | 27.27% | [8 Missing :warning: ](https://app.codecov.io/gh/scroll-tech/scroll/pull/1664?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech) |
| [rollup/internal/controller/relayer/l1\_relayer.go](https://app.codecov.io/gh/scroll-tech/scroll/pull/1664?src=pr&el=tree&filepath=rollup%2Finternal%2Fcontroller%2Frelayer%2Fl1_relayer.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech#diff-cm9sbHVwL2ludGVybmFsL2NvbnRyb2xsZXIvcmVsYXllci9sMV9yZWxheWVyLmdv) | 0.00% | [3 Missing :warning: ](https://app.codecov.io/gh/scroll-tech/scroll/pull/1664?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech) |
| [rollup/internal/controller/relayer/l2\_relayer.go](https://app.codecov.io/gh/scroll-tech/scroll/pull/1664?src=pr&el=tree&filepath=rollup%2Finternal%2Fcontroller%2Frelayer%2Fl2_relayer.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech#diff-cm9sbHVwL2ludGVybmFsL2NvbnRyb2xsZXIvcmVsYXllci9sMl9yZWxheWVyLmdv) | 72.72% | [2 Missing and 1 partial :warning: ](https://app.codecov.io/gh/scroll-tech/scroll/pull/1664?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech) |

<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff             @@
##           develop    #1664      +/-   ##
===========================================
+ Coverage    40.86%   40.90%   +0.04%     
===========================================
  Files          225      225              
  Lines        18061    18072      +11     
===========================================
+ Hits          7380     7392      +12     
+ Misses        9965     9964       -1     
  Partials       716      716              
```

| [Flag](https://app.codecov.io/gh/scroll-tech/scroll/pull/1664/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech) | Coverage Δ | |
|---|---|---|
| [rollup](https://app.codecov.io/gh/scroll-tech/scroll/pull/1664/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech) | `49.91% <51.72%> (+0.14%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/scroll-tech/scroll/pull/1664?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scroll-tech).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE