Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions common/testcontainers/testcontainers.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,17 @@ func (t *TestcontainerApps) GetPoSL1EndPoint() (string, error) {
return contrainer.PortEndpoint(context.Background(), "8545/tcp", "http")
}

// GetPoSL1Client returns a ethclient by dialing running PoS L1 client
func (t *TestcontainerApps) GetPoSL1Client() (*ethclient.Client, error) {
// GetPoSL1Client returns a raw rpc client and an ethclient by dialing the L1 node
func (t *TestcontainerApps) GetPoSL1Client() (*rpc.Client, *ethclient.Client, error) {
endpoint, err := t.GetPoSL1EndPoint()
if err != nil {
return nil, err
return nil, nil, err
}
rpcClient, err := rpc.Dial(endpoint)
if err != nil {
return nil, nil, fmt.Errorf("failed to dial L1 rpc endpoint, endpoint: %s, err: %w", endpoint, err)
}
return ethclient.Dial(endpoint)
return rpcClient, ethclient.NewClient(rpcClient), nil
}

// GetDBEndPoint returns the endpoint of the running postgres container
Expand Down Expand Up @@ -219,14 +223,13 @@ func (t *TestcontainerApps) GetGormDBClient() (*gorm.DB, error) {
return database.InitDB(dbCfg)
}

// GetL2GethClient returns a ethclient by dialing running L2Geth
func (t *TestcontainerApps) GetL2GethClient() (*ethclient.Client, error) {

// GetL2GethClient returns a raw rpc client and an ethclient by dialing the L2 node
func (t *TestcontainerApps) GetL2GethClient() (*rpc.Client, *ethclient.Client, error) {
rpcCli, err := t.GetL2Client()
if err != nil {
return nil, err
return nil, nil, err
}
return ethclient.NewClient(rpcCli), nil
return rpcCli, ethclient.NewClient(rpcCli), nil
}

// GetL2GethClient returns a rpc client by dialing running L2Geth
Expand Down
4 changes: 2 additions & 2 deletions common/testcontainers/testcontainers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ func TestNewTestcontainerApps(t *testing.T) {
endpoint, err = testApps.GetL2GethEndPoint()
assert.NoError(t, err)
assert.NotEmpty(t, endpoint)
ethclient, err = testApps.GetL2GethClient()
_, ethclient, err = testApps.GetL2GethClient()
assert.NoError(t, err)
assert.NotNil(t, ethclient)

assert.NoError(t, testApps.StartPoSL1Container())
endpoint, err = testApps.GetPoSL1EndPoint()
assert.NoError(t, err)
assert.NotEmpty(t, endpoint)
ethclient, err = testApps.GetPoSL1Client()
_, ethclient, err = testApps.GetPoSL1Client()
assert.NoError(t, err)
assert.NotNil(t, ethclient)

Expand Down
2 changes: 1 addition & 1 deletion common/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"runtime/debug"
)

var tag = "v4.7.5"
var tag = "v4.7.6"

var commit = func() string {
if info, ok := debug.ReadBuildInfo(); ok {
Expand Down
7 changes: 4 additions & 3 deletions rollup/cmd/gas_oracle/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,13 @@ func action(ctx *cli.Context) error {
registry := prometheus.DefaultRegisterer
observability.Server(ctx, db)

l1client, err := ethclient.Dial(cfg.L1Config.Endpoint)
l1RpcClient, err := rpc.Dial(cfg.L1Config.Endpoint)
if err != nil {
log.Crit("failed to connect l1 geth", "config file", cfgFile, "error", err)
log.Crit("failed to dial raw RPC client to L1 endpoint", "endpoint", cfg.L1Config.Endpoint, "error", err)
}
l1client := ethclient.NewClient(l1RpcClient)

l1watcher := watcher.NewL1WatcherClient(ctx.Context, l1client, cfg.L1Config.StartHeight, db, registry)
l1watcher := watcher.NewL1WatcherClient(ctx.Context, l1RpcClient, cfg.L1Config.StartHeight, db, registry)

l1relayer, err := relayer.NewLayer1Relayer(ctx.Context, db, cfg.L1Config.RelayerConfig, relayer.ServiceTypeL1GasOracle, registry)
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion rollup/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/s3 v1.80.0
github.com/consensys/gnark-crypto v0.16.0
github.com/crate-crypto/go-kzg-4844 v1.1.0
github.com/ethereum/go-ethereum v1.10.26
github.com/gin-gonic/gin v1.9.1
github.com/go-resty/resty/v2 v2.7.0
github.com/holiman/uint256 v1.3.2
Expand Down Expand Up @@ -51,7 +52,7 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect
github.com/fjl/memsize v0.0.2 // indirect
Expand Down
6 changes: 4 additions & 2 deletions rollup/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,15 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s=
github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs=
github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s=
github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA=
github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
Expand Down
4 changes: 4 additions & 0 deletions rollup/internal/config/relayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ type GasOracleConfig struct {
L1BaseFeeDefault uint64 `json:"l1_base_fee_default"`
L1BlobBaseFeeDefault uint64 `json:"l1_blob_base_fee_default"`

// Limit values for gas oracle updates
L1BaseFeeLimit uint64 `json:"l1_base_fee_limit"`
L1BlobBaseFeeLimit uint64 `json:"l1_blob_base_fee_limit"`

// L1BlobBaseFeeThreshold the threshold of L1 blob base fee to enter the default gas price mode
L1BlobBaseFeeThreshold uint64 `json:"l1_blob_base_fee_threshold"`
}
Expand Down
11 changes: 11 additions & 0 deletions rollup/internal/controller/relayer/l1_relayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() {
} else if err != nil {
return
}
// set limit
if baseFee > r.cfg.GasOracleConfig.L1BaseFeeLimit {
log.Error("L1 base fee exceed max limit, set to max limit", "baseFee", baseFee, "maxLimit", r.cfg.GasOracleConfig.L1BaseFeeLimit)
r.metrics.rollupL1RelayerGasPriceOracleFeeOverLimitTotal.Inc()
baseFee = r.cfg.GasOracleConfig.L1BaseFeeLimit
}
if blobBaseFee > r.cfg.GasOracleConfig.L1BlobBaseFeeLimit {
log.Error("L1 blob base fee exceed max limit, set to max limit", "blobBaseFee", blobBaseFee, "maxLimit", r.cfg.GasOracleConfig.L1BlobBaseFeeLimit)
r.metrics.rollupL1RelayerGasPriceOracleFeeOverLimitTotal.Inc()
blobBaseFee = r.cfg.GasOracleConfig.L1BlobBaseFeeLimit
}
Comment on lines +176 to +186
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Fee capping logic requires validation of limit values.

This enforcement logic unconditionally compares fees against configured limits without checking if the limits are valid (non-zero). As noted in the config file review, if L1BaseFeeLimit or L1BlobBaseFeeLimit are 0 (their default values when unconfigured), this code will cap all non-zero fees to 0, breaking the gas oracle.

Add validation before the comparison:

 		}
+		// Only enforce limits if they are configured (non-zero)
+		if r.cfg.GasOracleConfig.L1BaseFeeLimit > 0 && baseFee > r.cfg.GasOracleConfig.L1BaseFeeLimit {
-		if baseFee > r.cfg.GasOracleConfig.L1BaseFeeLimit {
 			log.Error("L1 base fee exceed max limit, set to max limit", "baseFee", baseFee, "maxLimit", r.cfg.GasOracleConfig.L1BaseFeeLimit)
 			r.metrics.rollupL1RelayerGasPriceOracleFeeOverLimitTotal.Inc()
 			baseFee = r.cfg.GasOracleConfig.L1BaseFeeLimit
 		}
+		if r.cfg.GasOracleConfig.L1BlobBaseFeeLimit > 0 && blobBaseFee > r.cfg.GasOracleConfig.L1BlobBaseFeeLimit {
-		if blobBaseFee > r.cfg.GasOracleConfig.L1BlobBaseFeeLimit {
 			log.Error("L1 blob base fee exceed max limit, set to max limit", "blobBaseFee", blobBaseFee, "maxLimit", r.cfg.GasOracleConfig.L1BlobBaseFeeLimit)
 			r.metrics.rollupL1RelayerGasPriceOracleFeeOverLimitTotal.Inc()
 			blobBaseFee = r.cfg.GasOracleConfig.L1BlobBaseFeeLimit
 		}

Alternative: Validate limits at initialization time in NewLayer1Relayer (line 50) to ensure they're configured with sensible values before the relayer starts.

📝 Committable suggestion

‼️ 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.

Suggested change
// set limit
if baseFee > r.cfg.GasOracleConfig.L1BaseFeeLimit {
log.Error("L1 base fee exceed max limit, set to max limit", "baseFee", baseFee, "maxLimit", r.cfg.GasOracleConfig.L1BaseFeeLimit)
r.metrics.rollupL1RelayerGasPriceOracleFeeOverLimitTotal.Inc()
baseFee = r.cfg.GasOracleConfig.L1BaseFeeLimit
}
if blobBaseFee > r.cfg.GasOracleConfig.L1BlobBaseFeeLimit {
log.Error("L1 blob base fee exceed max limit, set to max limit", "blobBaseFee", blobBaseFee, "maxLimit", r.cfg.GasOracleConfig.L1BlobBaseFeeLimit)
r.metrics.rollupL1RelayerGasPriceOracleFeeOverLimitTotal.Inc()
blobBaseFee = r.cfg.GasOracleConfig.L1BlobBaseFeeLimit
}
// set limit
// Only enforce limits if they are configured (non-zero)
if r.cfg.GasOracleConfig.L1BaseFeeLimit > 0 && baseFee > r.cfg.GasOracleConfig.L1BaseFeeLimit {
log.Error("L1 base fee exceed max limit, set to max limit", "baseFee", baseFee, "maxLimit", r.cfg.GasOracleConfig.L1BaseFeeLimit)
r.metrics.rollupL1RelayerGasPriceOracleFeeOverLimitTotal.Inc()
baseFee = r.cfg.GasOracleConfig.L1BaseFeeLimit
}
if r.cfg.GasOracleConfig.L1BlobBaseFeeLimit > 0 && blobBaseFee > r.cfg.GasOracleConfig.L1BlobBaseFeeLimit {
log.Error("L1 blob base fee exceed max limit, set to max limit", "blobBaseFee", blobBaseFee, "maxLimit", r.cfg.GasOracleConfig.L1BlobBaseFeeLimit)
r.metrics.rollupL1RelayerGasPriceOracleFeeOverLimitTotal.Inc()
blobBaseFee = r.cfg.GasOracleConfig.L1BlobBaseFeeLimit
}
🤖 Prompt for AI Agents
In rollup/internal/controller/relayer/l1_relayer.go around lines 176 to 186, the
fee capping compares baseFee and blobBaseFee against configured limits without
validating those limits, so a zero (unset) limit will incorrectly cap fees to 0;
update the logic to first check that r.cfg.GasOracleConfig.L1BaseFeeLimit and
L1BlobBaseFeeLimit are > 0 before applying the cap (skip capping and avoid
incrementing the over-limit metric when the limit is non-positive), and/or add
validation in NewLayer1Relayer (around line 50) to enforce sensible, non-zero
defaults or return an error if limits are unset so the relayer never runs with
zero limits.

data, err := r.l1GasOracleABI.Pack("setL1BaseFeeAndBlobBaseFee", new(big.Int).SetUint64(baseFee), new(big.Int).SetUint64(blobBaseFee))
if err != nil {
log.Error("Failed to pack setL1BaseFeeAndBlobBaseFee", "block.Hash", block.Hash, "block.Height", block.Number, "block.BaseFee", baseFee, "block.BlobBaseFee", blobBaseFee, "err", err)
Expand Down
15 changes: 10 additions & 5 deletions rollup/internal/controller/relayer/l1_relayer_metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import (
)

type l1RelayerMetrics struct {
rollupL1RelayerGasPriceOraclerRunTotal prometheus.Counter
rollupL1RelayerLatestBaseFee prometheus.Gauge
rollupL1RelayerLatestBlobBaseFee prometheus.Gauge
rollupL1UpdateGasOracleConfirmedTotal prometheus.Counter
rollupL1UpdateGasOracleConfirmedFailedTotal prometheus.Counter
rollupL1RelayerGasPriceOraclerRunTotal prometheus.Counter
rollupL1RelayerLatestBaseFee prometheus.Gauge
rollupL1RelayerLatestBlobBaseFee prometheus.Gauge
rollupL1UpdateGasOracleConfirmedTotal prometheus.Counter
rollupL1UpdateGasOracleConfirmedFailedTotal prometheus.Counter
rollupL1RelayerGasPriceOracleFeeOverLimitTotal prometheus.Counter
}

var (
Expand Down Expand Up @@ -43,6 +44,10 @@ func initL1RelayerMetrics(reg prometheus.Registerer) *l1RelayerMetrics {
Name: "rollup_layer1_update_gas_oracle_confirmed_failed_total",
Help: "The total number of updating layer1 gas oracle confirmed failed",
}),
rollupL1RelayerGasPriceOracleFeeOverLimitTotal: promauto.With(reg).NewCounter(prometheus.CounterOpts{
Name: "rollup_layer1_gas_price_oracle_fee_over_limit_total",
Help: "The total number of layer1 gas price oracle fee over limit",
}),
}
})
return l1RelayerMetric
Expand Down
2 changes: 1 addition & 1 deletion rollup/internal/controller/relayer/relayer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func setupEnv(t *testing.T) {
cfg.L2Config.RelayerConfig.ChainMonitor.BaseURL = "http://localhost:" + svrPort

// Create l2geth client.
l2Cli, err = testApps.GetL2GethClient()
_, l2Cli, err = testApps.GetL2GethClient()
assert.NoError(t, err)

templateBlockTrace1, err := os.ReadFile("../../../testdata/blockTrace_02.json")
Expand Down
3 changes: 2 additions & 1 deletion rollup/internal/controller/sender/estimategas.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sender

import (
"errors"
"fmt"
"math/big"

"github.com/scroll-tech/go-ethereum"
Expand Down Expand Up @@ -118,7 +119,7 @@ func (s *Sender) estimateGasLimit(to *common.Address, data []byte, sidecar *type

gasLimitWithoutAccessList, err := s.client.EstimateGas(s.ctx, msg)
if err != nil {
log.Error("estimateGasLimit EstimateGas failure without access list", "error", err)
log.Error("estimateGasLimit EstimateGas failure without access list", "error", err, "msg", fmt.Sprintf("%+v", msg))
return 0, nil, err
}

Expand Down
20 changes: 15 additions & 5 deletions rollup/internal/controller/sender/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/holiman/uint256"
"github.com/prometheus/client_golang/prometheus"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/consensus/misc"
"github.com/scroll-tech/go-ethereum/common/hexutil"
gethTypes "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/crypto/kzg4844"
"github.com/scroll-tech/go-ethereum/ethclient"
Expand Down Expand Up @@ -67,7 +67,8 @@ type FeeData struct {
// Sender Transaction sender to send transaction to l1/l2
type Sender struct {
config *config.SenderConfig
gethClient *gethclient.Client
rpcClient *rpc.Client // Raw RPC client
gethClient *gethclient.Client // Client to use for CreateAccessList
client *ethclient.Client // The client to retrieve on chain data (read-only)
writeClients []*ethclient.Client // The clients to send transactions to (write operations)
transactionSigner *TransactionSigner
Expand Down Expand Up @@ -141,6 +142,7 @@ func NewSender(ctx context.Context, config *config.SenderConfig, signerConfig *c
sender := &Sender{
ctx: ctx,
config: config,
rpcClient: rpcClient,
gethClient: gethclient.New(rpcClient),
client: client,
writeClients: writeClients,
Expand Down Expand Up @@ -839,10 +841,18 @@ func (s *Sender) getBlockNumberAndTimestampAndBaseFeeAndBlobFee(ctx context.Cont
baseFee = header.BaseFee.Uint64()
}

var blobBaseFee uint64
if excess := header.ExcessBlobGas; excess != nil {
blobBaseFee = misc.CalcBlobFee(*excess).Uint64()
// Leave it up to the L1 node to compute the correct blob base fee.
// Previously we would compute it locally using `CalcBlobFee`, but
// that approach requires syncing any future L1 configuration changes.
// Note: The fetched blob base fee might not correspond to the block
// that we fetched in the previous step, but this is acceptable.
var blobBaseFeeHex hexutil.Big
if err := s.rpcClient.CallContext(ctx, &blobBaseFeeHex, "eth_blobBaseFee"); err != nil {
return 0, 0, 0, 0, fmt.Errorf("failed to call eth_blobBaseFee, err: %w", err)
}
// A correct L1 node could not return a value that overflows uint64
blobBaseFee := blobBaseFeeHex.ToInt().Uint64()

// header.Number.Uint64() returns the pendingBlockNumber, so we minus 1 to get the latestBlockNumber.
return header.Number.Uint64() - 1, header.Time, baseFee, blobBaseFee, nil
}
Expand Down
2 changes: 1 addition & 1 deletion rollup/internal/controller/sender/sender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func setupEnv(t *testing.T) {
assert.NoError(t, err)
assert.NoError(t, migrate.ResetDB(sqlDB))

l1Client, err := testApps.GetPoSL1Client()
_, l1Client, err := testApps.GetPoSL1Client()
assert.NoError(t, err)

chainID, err := l1Client.ChainID(context.Background())
Expand Down
25 changes: 18 additions & 7 deletions rollup/internal/controller/watcher/l1_watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package watcher
import (
"context"
"errors"
"fmt"
"math/big"

"github.com/prometheus/client_golang/prometheus"
"github.com/scroll-tech/go-ethereum/consensus/misc"
"github.com/scroll-tech/go-ethereum/common/hexutil"
gethTypes "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/rpc"
"gorm.io/gorm"

"scroll-tech/common/types"
Expand All @@ -20,7 +22,8 @@ import (
// L1WatcherClient will listen for smart contract events from Eth L1.
type L1WatcherClient struct {
ctx context.Context
client *ethclient.Client
rpcClient *rpc.Client // Raw RPC client
client *ethclient.Client // Go SDK RPC client
l1BlockOrm *orm.L1Block

// The height of the block that the watcher has retrieved header rlp
Expand All @@ -30,7 +33,7 @@ type L1WatcherClient struct {
}

// NewL1WatcherClient returns a new instance of L1WatcherClient.
func NewL1WatcherClient(ctx context.Context, client *ethclient.Client, startHeight uint64, db *gorm.DB, reg prometheus.Registerer) *L1WatcherClient {
func NewL1WatcherClient(ctx context.Context, rpcClient *rpc.Client, startHeight uint64, db *gorm.DB, reg prometheus.Registerer) *L1WatcherClient {
l1BlockOrm := orm.NewL1Block(db)
savedL1BlockHeight, err := l1BlockOrm.GetLatestL1BlockHeight(ctx)
if err != nil {
Expand All @@ -43,7 +46,8 @@ func NewL1WatcherClient(ctx context.Context, client *ethclient.Client, startHeig

return &L1WatcherClient{
ctx: ctx,
client: client,
rpcClient: rpcClient,
client: ethclient.NewClient(rpcClient),
l1BlockOrm: l1BlockOrm,

processedBlockHeight: savedL1BlockHeight,
Expand Down Expand Up @@ -78,10 +82,17 @@ func (w *L1WatcherClient) FetchBlockHeader(blockHeight uint64) error {
baseFee = block.BaseFee.Uint64()
}

var blobBaseFee uint64
if excess := block.ExcessBlobGas; excess != nil {
blobBaseFee = misc.CalcBlobFee(*excess).Uint64()
// Leave it up to the L1 node to compute the correct blob base fee.
// Previously we would compute it locally using `CalcBlobFee`, but
// that approach requires syncing any future L1 configuration changes.
// Note: The fetched blob base fee might not correspond to the block
// that we fetched in the previous step, but this is acceptable.
var blobBaseFeeHex hexutil.Big
if err := w.rpcClient.CallContext(w.ctx, &blobBaseFeeHex, "eth_blobBaseFee"); err != nil {
return fmt.Errorf("failed to call eth_blobBaseFee, err: %w", err)
}
// A correct L1 node could not return a value that overflows uint64
blobBaseFee := blobBaseFeeHex.ToInt().Uint64()

l1Block := orm.L1Block{
Number: blockHeight,
Expand Down
4 changes: 2 additions & 2 deletions rollup/internal/controller/watcher/l1_watcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import (

func setupL1Watcher(t *testing.T) (*L1WatcherClient, *gorm.DB) {
db := setupDB(t)
client, err := testApps.GetPoSL1Client()
rawClient, _, err := testApps.GetPoSL1Client()
assert.NoError(t, err)
l1Cfg := cfg.L1Config
watcher := NewL1WatcherClient(context.Background(), client, l1Cfg.StartHeight, db, nil)
watcher := NewL1WatcherClient(context.Background(), rawClient, l1Cfg.StartHeight, db, nil)
return watcher, db
}

Expand Down
10 changes: 6 additions & 4 deletions rollup/tests/bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/rpc"
"github.com/stretchr/testify/assert"
"gorm.io/gorm"

Expand All @@ -37,8 +38,9 @@ var (
rollupApp *bcmd.MockApp

// clients
l1Client *ethclient.Client
l2Client *ethclient.Client
l1RawClient *rpc.Client
l1Client *ethclient.Client
l2Client *ethclient.Client

l1Auth *bind.TransactOpts
l2Auth *bind.TransactOpts
Expand Down Expand Up @@ -91,9 +93,9 @@ func setupEnv(t *testing.T) {
assert.NoError(t, testApps.StartPoSL1Container())
rollupApp = bcmd.NewRollupApp(testApps, "../conf/config.json")

l1Client, err = testApps.GetPoSL1Client()
l1RawClient, l1Client, err = testApps.GetPoSL1Client()
assert.NoError(t, err)
l2Client, err = testApps.GetL2GethClient()
_, l2Client, err = testApps.GetL2GethClient()
assert.NoError(t, err)
l1GethChainID, err = l1Client.ChainID(context.Background())
assert.NoError(t, err)
Expand Down
4 changes: 2 additions & 2 deletions rollup/tests/gas_oracle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func testImportL1GasPrice(t *testing.T) {
// Create L1Watcher
startHeight, err := l1Client.BlockNumber(context.Background())
assert.NoError(t, err)
l1Watcher := watcher.NewL1WatcherClient(context.Background(), l1Client, startHeight-1, db, nil)
l1Watcher := watcher.NewL1WatcherClient(context.Background(), l1RawClient, startHeight-1, db, nil)

// fetch new blocks
number, err := l1Client.BlockNumber(context.Background())
Expand Down Expand Up @@ -110,7 +110,7 @@ func testImportDefaultL1GasPriceDueToL1GasPriceSpike(t *testing.T) {
// Create L1Watcher
startHeight, err := l1Client.BlockNumber(context.Background())
assert.NoError(t, err)
l1Watcher := watcher.NewL1WatcherClient(context.Background(), l1Client, startHeight-2, db, nil)
l1Watcher := watcher.NewL1WatcherClient(context.Background(), l1RawClient, startHeight-2, db, nil)

// fetch new blocks
number, err := l1Client.BlockNumber(context.Background())
Expand Down
Loading
Loading