mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-04-23 03:00:50 -04:00
feat(gas-oracle): add gas price update after Curie (#1344)
This commit is contained in:
@@ -5,7 +5,7 @@ import (
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
var tag = "v4.4.7"
|
||||
var tag = "v4.4.8"
|
||||
|
||||
var commit = func() string {
|
||||
if info, ok := debug.ReadBuildInfo(); ok {
|
||||
|
||||
@@ -101,7 +101,7 @@ var L2MessageQueueMetaData = &bind.MetaData{
|
||||
|
||||
// L1GasPriceOracleMetaData contains all meta data concerning the L1GasPriceOracle contract.
|
||||
var L1GasPriceOracleMetaData = &bind.MetaData{
|
||||
ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"l1BaseFee\",\"type\":\"uint256\"}],\"name\":\"L1BaseFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"overhead\",\"type\":\"uint256\"}],\"name\":\"OverheadUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"scalar\",\"type\":\"uint256\"}],\"name\":\"ScalarUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_oldWhitelist\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newWhitelist\",\"type\":\"address\"}],\"name\":\"UpdateWhitelist\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"getL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"getL1GasUsed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1BaseFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"overhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"scalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l1BaseFee\",\"type\":\"uint256\"}],\"name\":\"setL1BaseFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"}],\"name\":\"setOverhead\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"}],\"name\":\"setScalar\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newWhitelist\",\"type\":\"address\"}],\"name\":\"updateWhitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"whitelist\",\"outputs\":[{\"internalType\":\"contract IWhitelist\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]\n",
|
||||
ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"scalar\",\"type\":\"uint256\"}],\"name\":\"BlobScalarUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"scalar\",\"type\":\"uint256\"}],\"name\":\"CommitScalarUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"l1BaseFee\",\"type\":\"uint256\"}],\"name\":\"L1BaseFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"l1BlobBaseFee\",\"type\":\"uint256\"}],\"name\":\"L1BlobBaseFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"overhead\",\"type\":\"uint256\"}],\"name\":\"OverheadUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"scalar\",\"type\":\"uint256\"}],\"name\":\"ScalarUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"blobScalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"commitScalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"getL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"getL1GasUsed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1BaseFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1BlobBaseFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"overhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"scalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l1BaseFee\",\"type\":\"uint256\"}],\"name\":\"setL1BaseFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l1BaseFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l1BlobBaseFee\",\"type\":\"uint256\"}],\"name\":\"setL1BaseFeeAndBlobBaseFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
|
||||
}
|
||||
|
||||
// IL1ScrollMessengerL2MessageProof is an auto generated low-level Go binding around an user-defined struct.
|
||||
|
||||
@@ -36,7 +36,8 @@ type Layer1Relayer struct {
|
||||
gasOracleSender *sender.Sender
|
||||
l1GasOracleABI *abi.ABI
|
||||
|
||||
lastGasPrice uint64
|
||||
lastBaseFee uint64
|
||||
lastBlobBaseFee uint64
|
||||
minGasPrice uint64
|
||||
gasPriceDiff uint64
|
||||
l1BaseFeeWeight float64
|
||||
@@ -130,37 +131,45 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() {
|
||||
block := blocks[0]
|
||||
|
||||
if types.GasOracleStatus(block.GasOracleStatus) == types.GasOraclePending {
|
||||
expectedDelta := r.lastGasPrice * r.gasPriceDiff / gasPriceDiffPrecision
|
||||
if r.lastGasPrice > 0 && expectedDelta == 0 {
|
||||
expectedDelta = 1
|
||||
}
|
||||
|
||||
latestL2Height, err := r.l2BlockOrm.GetL2BlocksLatestHeight(r.ctx)
|
||||
if err != nil {
|
||||
log.Warn("Failed to fetch latest L2 block height from db", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
var isBernoulli = r.chainCfg.IsBernoulli(new(big.Int).SetUint64(latestL2Height))
|
||||
var isBernoulli = block.BlobBaseFee > 0 && r.chainCfg.IsBernoulli(new(big.Int).SetUint64(latestL2Height))
|
||||
var isCurie = block.BlobBaseFee > 0 && r.chainCfg.IsCurie(new(big.Int).SetUint64(latestL2Height))
|
||||
|
||||
var baseFee uint64
|
||||
if isBernoulli && block.BlobBaseFee != 0 {
|
||||
var blobBaseFee uint64
|
||||
if isCurie {
|
||||
baseFee = block.BaseFee
|
||||
blobBaseFee = block.BlobBaseFee
|
||||
} else if isBernoulli {
|
||||
baseFee = uint64(math.Ceil(r.l1BaseFeeWeight*float64(block.BaseFee) + r.l1BlobBaseFeeWeight*float64(block.BlobBaseFee)))
|
||||
} else {
|
||||
baseFee = block.BaseFee
|
||||
}
|
||||
|
||||
// last is undefined or (baseFee >= minGasPrice && exceed diff)
|
||||
if r.lastGasPrice == 0 || (baseFee >= r.minGasPrice && (baseFee >= r.lastGasPrice+expectedDelta || baseFee <= r.lastGasPrice-expectedDelta)) {
|
||||
data, err := r.l1GasOracleABI.Pack("setL1BaseFee", new(big.Int).SetUint64(baseFee))
|
||||
if err != nil {
|
||||
log.Error("Failed to pack setL1BaseFee", "block.Hash", block.Hash, "block.Height", block.Number, "block.BaseFee", baseFee, "isBernoulli", isBernoulli, "err", err)
|
||||
return
|
||||
if r.shouldUpdateGasOracle(baseFee, blobBaseFee, isCurie) {
|
||||
var data []byte
|
||||
if isCurie {
|
||||
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, "isBernoulli", isBernoulli, "isCurie", isCurie, "err", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
data, err = r.l1GasOracleABI.Pack("setL1BaseFee", new(big.Int).SetUint64(baseFee))
|
||||
if err != nil {
|
||||
log.Error("Failed to pack setL1BaseFee", "block.Hash", block.Hash, "block.Height", block.Number, "block.BaseFee", baseFee, "block.BlobBaseFee", blobBaseFee, "isBernoulli", isBernoulli, "isCurie", isCurie, "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
hash, err := r.gasOracleSender.SendTransaction(block.Hash, &r.cfg.GasPriceOracleContractAddress, data, nil, 0)
|
||||
if err != nil {
|
||||
log.Error("Failed to send setL1BaseFee tx to layer2 ", "block.Hash", block.Hash, "block.Height", block.Number, "err", err)
|
||||
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, "isBernoulli", isBernoulli, "isCurie", isCurie, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -169,9 +178,12 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() {
|
||||
log.Error("UpdateGasOracleStatusAndOracleTxHash failed", "block.Hash", block.Hash, "block.Height", block.Number, "err", err)
|
||||
return
|
||||
}
|
||||
r.lastGasPrice = baseFee
|
||||
r.metrics.rollupL1RelayerLastGasPrice.Set(float64(r.lastGasPrice))
|
||||
log.Info("Update l1 base fee", "txHash", hash.String(), "baseFee", baseFee, "isBernoulli", isBernoulli)
|
||||
|
||||
r.lastBaseFee = baseFee
|
||||
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, "isBernoulli", isBernoulli, "isCurie", isCurie)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,3 +231,34 @@ func (r *Layer1Relayer) StopSenders() {
|
||||
r.gasOracleSender.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Layer1Relayer) shouldUpdateGasOracle(baseFee uint64, blobBaseFee uint64, isCurie bool) bool {
|
||||
// Right after restarting.
|
||||
if r.lastBaseFee == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
expectedBaseFeeDelta := r.lastBaseFee*r.gasPriceDiff/gasPriceDiffPrecision + 1
|
||||
if baseFee >= r.minGasPrice && (baseFee >= r.lastBaseFee+expectedBaseFeeDelta || baseFee+expectedBaseFeeDelta <= r.lastBaseFee) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Omitting blob base fee checks before Curie.
|
||||
if !isCurie {
|
||||
return false
|
||||
}
|
||||
|
||||
// Right after enabling Curie.
|
||||
if r.lastBlobBaseFee == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
expectedBlobBaseFeeDelta := r.lastBlobBaseFee * r.gasPriceDiff / gasPriceDiffPrecision
|
||||
// Plus a minimum of 0.01 gwei, since the blob base fee is usually low, preventing short-time flunctuation.
|
||||
expectedBlobBaseFeeDelta += 10000000
|
||||
if blobBaseFee >= r.minGasPrice && (blobBaseFee >= r.lastBlobBaseFee+expectedBlobBaseFeeDelta || blobBaseFee+expectedBlobBaseFeeDelta <= r.lastBlobBaseFee) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ import (
|
||||
|
||||
type l1RelayerMetrics struct {
|
||||
rollupL1RelayerGasPriceOraclerRunTotal prometheus.Counter
|
||||
rollupL1RelayerLastGasPrice prometheus.Gauge
|
||||
rollupL1RelayerLatestBaseFee prometheus.Gauge
|
||||
rollupL1RelayerLatestBlobBaseFee prometheus.Gauge
|
||||
rollupL1UpdateGasOracleConfirmedTotal prometheus.Counter
|
||||
rollupL1UpdateGasOracleConfirmedFailedTotal prometheus.Counter
|
||||
}
|
||||
@@ -26,9 +27,13 @@ func initL1RelayerMetrics(reg prometheus.Registerer) *l1RelayerMetrics {
|
||||
Name: "rollup_layer1_gas_price_oracler_total",
|
||||
Help: "The total number of layer1 gas price oracler run total",
|
||||
}),
|
||||
rollupL1RelayerLastGasPrice: promauto.With(reg).NewGauge(prometheus.GaugeOpts{
|
||||
Name: "rollup_layer1_gas_price_latest_gas_price",
|
||||
Help: "The latest gas price of rollup relayer l1",
|
||||
rollupL1RelayerLatestBaseFee: promauto.With(reg).NewGauge(prometheus.GaugeOpts{
|
||||
Name: "rollup_layer1_latest_base_fee",
|
||||
Help: "The latest base fee of l1 rollup relayer",
|
||||
}),
|
||||
rollupL1RelayerLatestBlobBaseFee: promauto.With(reg).NewGauge(prometheus.GaugeOpts{
|
||||
Name: "rollup_layer1_latest_blob_base_fee",
|
||||
Help: "The latest blob base fee of l1 rollup relayer",
|
||||
}),
|
||||
rollupL1UpdateGasOracleConfirmedTotal: promauto.With(reg).NewCounter(prometheus.CounterOpts{
|
||||
Name: "rollup_layer1_update_gas_oracle_confirmed_total",
|
||||
|
||||
@@ -309,7 +309,7 @@ func (r *Layer2Relayer) ProcessGasPriceOracle() {
|
||||
}
|
||||
|
||||
// last is undefine or (suggestGasPriceUint64 >= minGasPrice && exceed diff)
|
||||
if r.lastGasPrice == 0 || (suggestGasPriceUint64 >= r.minGasPrice && (suggestGasPriceUint64 >= r.lastGasPrice+expectedDelta || suggestGasPriceUint64 <= r.lastGasPrice-expectedDelta)) {
|
||||
if r.lastGasPrice == 0 || (suggestGasPriceUint64 >= r.minGasPrice && (suggestGasPriceUint64 >= r.lastGasPrice+expectedDelta || suggestGasPriceUint64+expectedDelta <= r.lastGasPrice)) {
|
||||
data, err := r.l2GasOracleABI.Pack("setL2BaseFee", suggestGasPrice)
|
||||
if err != nil {
|
||||
log.Error("Failed to pack setL2BaseFee", "batch.Hash", batch.Hash, "GasPrice", suggestGasPrice.Uint64(), "err", err)
|
||||
|
||||
@@ -319,10 +319,10 @@ func testAccessListTransactionGasLimit(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
if txType == LegacyTxType { // Legacy transactions can not have an access list.
|
||||
assert.Equal(t, uint64(43956), gasLimit)
|
||||
assert.Equal(t, uint64(43935), gasLimit)
|
||||
assert.Nil(t, accessList)
|
||||
} else { // Dynamic fee and blob transactions can have an access list.
|
||||
assert.Equal(t, uint64(43479), gasLimit)
|
||||
assert.Equal(t, uint64(43458), gasLimit)
|
||||
assert.NotNil(t, accessList)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.24;
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
import {BatchHeaderV0Codec} from "../../../contracts/src/libraries/codec/BatchHeaderV0Codec.sol";
|
||||
import {BatchHeaderV1Codec} from "../../../contracts/src/libraries/codec/BatchHeaderV1Codec.sol";
|
||||
@@ -82,14 +82,25 @@ contract MockBridge {
|
||||
/// point evaluation precompile
|
||||
uint256 constant BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513;
|
||||
|
||||
uint256 public l1BaseFee;
|
||||
uint256 public l1BlobBaseFee;
|
||||
uint256 public l2BaseFee;
|
||||
uint256 public lastFinalizedBatchIndex;
|
||||
mapping(uint256 => bytes32) public committedBatches;
|
||||
mapping(uint256 => bytes32) public finalizedStateRoots;
|
||||
mapping(uint256 => bytes32) public withdrawRoots;
|
||||
|
||||
function setL2BaseFee(uint256 _newL2BaseFee) external {
|
||||
l2BaseFee = _newL2BaseFee;
|
||||
function setL1BaseFee(uint256 _l1BaseFee) external {
|
||||
l1BaseFee = _l1BaseFee;
|
||||
}
|
||||
|
||||
function setL1BaseFeeAndBlobBaseFee(uint256 _l1BaseFee, uint256 _l1BlobBaseFee) external {
|
||||
l1BaseFee = _l1BaseFee;
|
||||
l1BlobBaseFee = _l1BlobBaseFee;
|
||||
}
|
||||
|
||||
function setL2BaseFee(uint256 _l2BaseFee) external {
|
||||
l2BaseFee = _l2BaseFee;
|
||||
}
|
||||
|
||||
/*****************************
|
||||
|
||||
@@ -40,8 +40,8 @@ var (
|
||||
l1Client *ethclient.Client
|
||||
l2Client *ethclient.Client
|
||||
|
||||
// l1Auth
|
||||
l1Auth *bind.TransactOpts
|
||||
l2Auth *bind.TransactOpts
|
||||
)
|
||||
|
||||
func setupDB(t *testing.T) *gorm.DB {
|
||||
@@ -82,6 +82,7 @@ func setupEnv(t *testing.T) {
|
||||
var (
|
||||
err error
|
||||
l1GethChainID *big.Int
|
||||
l2GethChainID *big.Int
|
||||
)
|
||||
|
||||
testApps = tc.NewTestcontainerApps()
|
||||
@@ -96,6 +97,8 @@ func setupEnv(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
l1GethChainID, err = l1Client.ChainID(context.Background())
|
||||
assert.NoError(t, err)
|
||||
l2GethChainID, err = l2Client.ChainID(context.Background())
|
||||
assert.NoError(t, err)
|
||||
|
||||
l1Cfg, l2Cfg := rollupApp.Config.L1Config, rollupApp.Config.L2Config
|
||||
l1Cfg.Confirmations = 0
|
||||
@@ -103,17 +106,16 @@ func setupEnv(t *testing.T) {
|
||||
l2Cfg.Confirmations = 0
|
||||
l2Cfg.RelayerConfig.SenderConfig.Confirmations = 0
|
||||
|
||||
l1Auth, err = bind.NewKeyedTransactorWithChainID(rollupApp.Config.L2Config.RelayerConfig.CommitSenderPrivateKey, l1GethChainID)
|
||||
l1Auth, err = bind.NewKeyedTransactorWithChainID(l2Cfg.RelayerConfig.CommitSenderPrivateKey, l1GethChainID)
|
||||
assert.NoError(t, err)
|
||||
rollupApp.Config.L1Config.Endpoint, err = testApps.GetPoSL1EndPoint()
|
||||
assert.NoError(t, err)
|
||||
rollupApp.Config.L2Config.RelayerConfig.SenderConfig.Endpoint, err = testApps.GetPoSL1EndPoint()
|
||||
|
||||
l2Auth, err = bind.NewKeyedTransactorWithChainID(l1Cfg.RelayerConfig.GasOracleSenderPrivateKey, l2GethChainID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
port, err := rand.Int(rand.Reader, big.NewInt(10000))
|
||||
assert.NoError(t, err)
|
||||
svrPort := strconv.FormatInt(port.Int64()+40000, 10)
|
||||
rollupApp.Config.L2Config.RelayerConfig.ChainMonitor.BaseURL = "http://localhost:" + svrPort
|
||||
l2Cfg.RelayerConfig.ChainMonitor.BaseURL = "http://localhost:" + svrPort
|
||||
}
|
||||
|
||||
func mockChainMonitorServer(baseURL string) (*http.Server, error) {
|
||||
@@ -137,7 +139,7 @@ func prepareContracts(t *testing.T) {
|
||||
// L1 ScrolChain contract
|
||||
nonce, err := l1Client.PendingNonceAt(context.Background(), l1Auth.From)
|
||||
assert.NoError(t, err)
|
||||
scrollChainAddress := crypto.CreateAddress(l1Auth.From, nonce)
|
||||
mockL1ContractAddress := crypto.CreateAddress(l1Auth.From, nonce)
|
||||
tx := types.NewContractCreation(nonce, big.NewInt(0), 10000000, big.NewInt(1000000000), common.FromHex(mock_bridge.MockBridgeMetaData.Bin))
|
||||
signedTx, err := l1Auth.Signer(l1Auth.From, tx)
|
||||
assert.NoError(t, err)
|
||||
@@ -145,23 +147,51 @@ func prepareContracts(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Eventually(t, func() bool {
|
||||
_, isPending, err := l1Client.TransactionByHash(context.Background(), signedTx.Hash())
|
||||
_, isPending, getErr := l1Client.TransactionByHash(context.Background(), signedTx.Hash())
|
||||
return getErr == nil && !isPending
|
||||
}, 30*time.Second, time.Second)
|
||||
|
||||
assert.Eventually(t, func() bool {
|
||||
receipt, getErr := l1Client.TransactionReceipt(context.Background(), signedTx.Hash())
|
||||
return getErr == nil && receipt.Status == gethTypes.ReceiptStatusSuccessful
|
||||
}, 30*time.Second, time.Second)
|
||||
|
||||
assert.Eventually(t, func() bool {
|
||||
code, getErr := l1Client.CodeAt(context.Background(), mockL1ContractAddress, nil)
|
||||
return getErr == nil && len(code) > 0
|
||||
}, 30*time.Second, time.Second)
|
||||
|
||||
// L2 ScrolChain contract
|
||||
nonce, err = l2Client.PendingNonceAt(context.Background(), l2Auth.From)
|
||||
assert.NoError(t, err)
|
||||
mockL2ContractAddress := crypto.CreateAddress(l2Auth.From, nonce)
|
||||
tx = types.NewContractCreation(nonce, big.NewInt(0), 2000000, big.NewInt(1000000000), common.FromHex(mock_bridge.MockBridgeMetaData.Bin))
|
||||
signedTx, err = l2Auth.Signer(l2Auth.From, tx)
|
||||
assert.NoError(t, err)
|
||||
err = l2Client.SendTransaction(context.Background(), signedTx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Eventually(t, func() bool {
|
||||
_, isPending, err := l2Client.TransactionByHash(context.Background(), signedTx.Hash())
|
||||
return err == nil && !isPending
|
||||
}, 30*time.Second, time.Second)
|
||||
|
||||
assert.Eventually(t, func() bool {
|
||||
receipt, err := l1Client.TransactionReceipt(context.Background(), signedTx.Hash())
|
||||
receipt, err := l2Client.TransactionReceipt(context.Background(), signedTx.Hash())
|
||||
return err == nil && receipt.Status == gethTypes.ReceiptStatusSuccessful
|
||||
}, 30*time.Second, time.Second)
|
||||
|
||||
assert.Eventually(t, func() bool {
|
||||
code, err := l1Client.CodeAt(context.Background(), scrollChainAddress, nil)
|
||||
code, err := l2Client.CodeAt(context.Background(), mockL2ContractAddress, nil)
|
||||
return err == nil && len(code) > 0
|
||||
}, 30*time.Second, time.Second)
|
||||
|
||||
l1Config, l2Config := rollupApp.Config.L1Config, rollupApp.Config.L2Config
|
||||
l1Config.ScrollChainContractAddress = scrollChainAddress
|
||||
l2Config.RelayerConfig.RollupContractAddress = scrollChainAddress
|
||||
l1Config.ScrollChainContractAddress = mockL1ContractAddress
|
||||
l2Config.RelayerConfig.RollupContractAddress = mockL1ContractAddress
|
||||
|
||||
l2Config.RelayerConfig.GasPriceOracleContractAddress = mockL1ContractAddress
|
||||
l1Config.RelayerConfig.GasPriceOracleContractAddress = mockL2ContractAddress
|
||||
}
|
||||
|
||||
func TestFunction(t *testing.T) {
|
||||
@@ -182,5 +212,6 @@ func TestFunction(t *testing.T) {
|
||||
|
||||
// l1/l2 gas oracle
|
||||
t.Run("TestImportL1GasPrice", testImportL1GasPrice)
|
||||
t.Run("TestImportL1GasPriceAfterCurie", testImportL1GasPriceAfterCurie)
|
||||
t.Run("TestImportL2GasPrice", testImportL2GasPrice)
|
||||
}
|
||||
|
||||
@@ -64,6 +64,51 @@ func testImportL1GasPrice(t *testing.T) {
|
||||
assert.Equal(t, types.GasOracleStatus(blocks[0].GasOracleStatus), types.GasOracleImporting)
|
||||
}
|
||||
|
||||
func testImportL1GasPriceAfterCurie(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
defer database.CloseDB(db)
|
||||
|
||||
prepareContracts(t)
|
||||
|
||||
l1Cfg := rollupApp.Config.L1Config
|
||||
|
||||
// Create L1Relayer
|
||||
l1Relayer, err := relayer.NewLayer1Relayer(context.Background(), db, l1Cfg.RelayerConfig, ¶ms.ChainConfig{BernoulliBlock: big.NewInt(0), CurieBlock: big.NewInt(0)}, relayer.ServiceTypeL1GasOracle, nil)
|
||||
assert.NoError(t, err)
|
||||
defer l1Relayer.StopSenders()
|
||||
|
||||
// Create L1Watcher
|
||||
startHeight, err := l1Client.BlockNumber(context.Background())
|
||||
assert.NoError(t, err)
|
||||
l1Watcher := watcher.NewL1WatcherClient(context.Background(), l1Client, startHeight-1, 0, l1Cfg.L1MessageQueueAddress, l1Cfg.ScrollChainContractAddress, db, nil)
|
||||
|
||||
// fetch new blocks
|
||||
number, err := l1Client.BlockNumber(context.Background())
|
||||
assert.Greater(t, number, startHeight-1)
|
||||
assert.NoError(t, err)
|
||||
err = l1Watcher.FetchBlockHeader(number)
|
||||
assert.NoError(t, err)
|
||||
|
||||
l1BlockOrm := orm.NewL1Block(db)
|
||||
// check db status
|
||||
latestBlockHeight, err := l1BlockOrm.GetLatestL1BlockHeight(context.Background())
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, number, latestBlockHeight)
|
||||
blocks, err := l1BlockOrm.GetL1Blocks(context.Background(), map[string]interface{}{"number": latestBlockHeight})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(blocks), 1)
|
||||
assert.Empty(t, blocks[0].OracleTxHash)
|
||||
assert.Equal(t, types.GasOracleStatus(blocks[0].GasOracleStatus), types.GasOraclePending)
|
||||
|
||||
// relay gas price
|
||||
l1Relayer.ProcessGasPriceOracle()
|
||||
blocks, err = l1BlockOrm.GetL1Blocks(context.Background(), map[string]interface{}{"number": latestBlockHeight})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(blocks), 1)
|
||||
assert.NotEmpty(t, blocks[0].OracleTxHash)
|
||||
assert.Equal(t, types.GasOracleStatus(blocks[0].GasOracleStatus), types.GasOracleImporting)
|
||||
}
|
||||
|
||||
func testImportL2GasPrice(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
defer database.CloseDB(db)
|
||||
|
||||
Reference in New Issue
Block a user