Skip to content

Commit

Permalink
Implement the gas estimator components refactor (#12650)
Browse files Browse the repository at this point in the history
* Applied LimitMultiplier to chainSpecificGasLimit in all gas estimators

* Intial refactor

* Revert "Applied LimitMultiplier to chainSpecificGasLimit in all gas estimators"

This reverts commit e0c581c.

* Refactored L1GasOracle

* Fixed failing tests

* fixed linting issues

* Updated ethClient struct to be specific to l1Oracle

* Removed changes to broadcaster error handling

* fixed rollup tests

* Fixed remaining issues with PR

* updated changesets

* fixed linting issues

* minor fixes

* Deduplicated L1Oracle creation

* Changed L1Oracle to return pointer

* Update core/chains/evm/gas/rollups/arbitrum_l1_oracle.go

Co-authored-by: amit-momin <108959691+amit-momin@users.noreply.github.com>

* Added l1Oracle as a parameter to pass into gas estimators

* removed casting for direct call

* removed unused mocks

---------

Co-authored-by: amit-momin <108959691+amit-momin@users.noreply.github.com>
  • Loading branch information
silaslenihan and amit-momin committed Apr 18, 2024
1 parent 057ef81 commit 6991af2
Show file tree
Hide file tree
Showing 27 changed files with 1,443 additions and 1,151 deletions.
6 changes: 6 additions & 0 deletions .changeset/flat-guests-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"chainlink": minor
---

#internal Gas Estimator L1Oracles to be chain specific
#removed cmd/arbgas
74 changes: 8 additions & 66 deletions core/chains/evm/gas/arbitrum_estimator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@ package gas
import (
"context"
"fmt"
"math"
"math/big"
"slices"
"sync"
"time"

"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
pkgerrors "github.com/pkg/errors"

"github.com/smartcontractkit/chainlink-common/pkg/logger"
Expand All @@ -19,7 +15,7 @@ import (

feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups"
)

type ArbConfig interface {
Expand All @@ -28,19 +24,13 @@ type ArbConfig interface {
BumpMin() *assets.Wei
}

//go:generate mockery --quiet --name ethClient --output ./mocks/ --case=underscore --structname ETHClient
type ethClient interface {
CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
}

// arbitrumEstimator is an Estimator which extends SuggestedPriceEstimator to use getPricesInArbGas() for gas limit estimation.
type arbitrumEstimator struct {
services.StateMachine
cfg ArbConfig

EvmEstimator // *SuggestedPriceEstimator

client ethClient
pollPeriod time.Duration
logger logger.Logger

Expand All @@ -52,20 +42,23 @@ type arbitrumEstimator struct {
chInitialised chan struct{}
chStop services.StopChan
chDone chan struct{}

l1Oracle rollups.ArbL1GasOracle
}

func NewArbitrumEstimator(lggr logger.Logger, cfg ArbConfig, rpcClient rpcClient, ethClient ethClient) EvmEstimator {
func NewArbitrumEstimator(lggr logger.Logger, cfg ArbConfig, ethClient feeEstimatorClient, l1Oracle rollups.ArbL1GasOracle) EvmEstimator {
lggr = logger.Named(lggr, "ArbitrumEstimator")

return &arbitrumEstimator{
cfg: cfg,
EvmEstimator: NewSuggestedPriceEstimator(lggr, rpcClient, cfg),
client: ethClient,
EvmEstimator: NewSuggestedPriceEstimator(lggr, ethClient, cfg, l1Oracle),
pollPeriod: 10 * time.Second,
logger: lggr,
chForceRefetch: make(chan (chan struct{})),
chInitialised: make(chan struct{}),
chStop: make(chan struct{}),
chDone: make(chan struct{}),
l1Oracle: l1Oracle,
}
}

Expand Down Expand Up @@ -196,7 +189,7 @@ func (a *arbitrumEstimator) run() {
func (a *arbitrumEstimator) refreshPricesInArbGas() (t *time.Timer) {
t = time.NewTimer(utils.WithJitter(a.pollPeriod))

perL2Tx, perL1CalldataUnit, err := a.callGetPricesInArbGas()
perL2Tx, perL1CalldataUnit, err := a.l1Oracle.GetPricesInArbGas()
if err != nil {
a.logger.Warnw("Failed to refresh prices", "err", err)
return
Expand All @@ -210,54 +203,3 @@ func (a *arbitrumEstimator) refreshPricesInArbGas() (t *time.Timer) {
a.getPricesInArbGasMu.Unlock()
return
}

const (
// ArbGasInfoAddress is the address of the "Precompiled contract that exists in every Arbitrum chain."
// https://github.com/OffchainLabs/nitro/blob/f7645453cfc77bf3e3644ea1ac031eff629df325/contracts/src/precompiles/ArbGasInfo.sol
ArbGasInfoAddress = "0x000000000000000000000000000000000000006C"
// ArbGasInfo_getPricesInArbGas is the a hex encoded call to:
// `function getPricesInArbGas() external view returns (uint256, uint256, uint256);`
ArbGasInfo_getPricesInArbGas = "02199f34"
)

// callGetPricesInArbGas calls ArbGasInfo.getPricesInArbGas() on the precompile contract ArbGasInfoAddress.
//
// @return (per L2 tx, per L1 calldata unit, per storage allocation)
// function getPricesInArbGas() external view returns (uint256, uint256, uint256);
//
// https://github.com/OffchainLabs/nitro/blob/f7645453cfc77bf3e3644ea1ac031eff629df325/contracts/src/precompiles/ArbGasInfo.sol#L69
func (a *arbitrumEstimator) callGetPricesInArbGas() (perL2Tx uint32, perL1CalldataUnit uint32, err error) {
ctx, cancel := a.chStop.CtxCancel(evmclient.ContextWithDefaultTimeout())
defer cancel()

precompile := common.HexToAddress(ArbGasInfoAddress)
b, err := a.client.CallContract(ctx, ethereum.CallMsg{
To: &precompile,
Data: common.Hex2Bytes(ArbGasInfo_getPricesInArbGas),
}, big.NewInt(-1))
if err != nil {
return 0, 0, err
}

if len(b) != 3*32 { // returns (uint256, uint256, uint256);
err = fmt.Errorf("return data length (%d) different than expected (%d)", len(b), 3*32)
return
}
bPerL2Tx := new(big.Int).SetBytes(b[:32])
bPerL1CalldataUnit := new(big.Int).SetBytes(b[32:64])
// ignore perStorageAllocation
if !bPerL2Tx.IsUint64() || !bPerL1CalldataUnit.IsUint64() {
err = fmt.Errorf("returned integers are not uint64 (%s, %s)", bPerL2Tx.String(), bPerL1CalldataUnit.String())
return
}

perL2TxU64 := bPerL2Tx.Uint64()
perL1CalldataUnitU64 := bPerL1CalldataUnit.Uint64()
if perL2TxU64 > math.MaxUint32 || perL1CalldataUnitU64 > math.MaxUint32 {
err = fmt.Errorf("returned integers are not uint32 (%d, %d)", perL2TxU64, perL1CalldataUnitU64)
return
}
perL2Tx = uint32(perL2TxU64)
perL1CalldataUnit = uint32(perL1CalldataUnitU64)
return
}
119 changes: 65 additions & 54 deletions core/chains/evm/gas/arbitrum_estimator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
)

Expand Down Expand Up @@ -52,9 +53,10 @@ func TestArbitrumEstimator(t *testing.T) {
var bumpMin = assets.NewWei(big.NewInt(1))

t.Run("calling GetLegacyGas on unstarted estimator returns error", func(t *testing.T) {
rpcClient := mocks.NewRPCClient(t)
ethClient := mocks.NewETHClient(t)
o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, rpcClient, ethClient)
feeEstimatorClient := mocks.NewFeeEstimatorClient(t)
l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient)

o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle)
_, _, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice)
assert.EqualError(t, err, "estimator is not started")
})
Expand All @@ -64,21 +66,22 @@ func TestArbitrumEstimator(t *testing.T) {
zeros.Write(common.BigToHash(big.NewInt(0)).Bytes())
zeros.Write(common.BigToHash(big.NewInt(123455)).Bytes())
t.Run("calling GetLegacyGas on started estimator returns estimates", func(t *testing.T) {
rpcClient := mocks.NewRPCClient(t)
ethClient := mocks.NewETHClient(t)
rpcClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) {
feeEstimatorClient := mocks.NewFeeEstimatorClient(t)
l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient)

feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) {
res := args.Get(1).(*hexutil.Big)
(*big.Int)(res).SetInt64(42)
})
ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
feeEstimatorClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
callMsg := args.Get(1).(ethereum.CallMsg)
blockNumber := args.Get(2).(*big.Int)
assert.Equal(t, gas.ArbGasInfoAddress, callMsg.To.String())
assert.Equal(t, gas.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data))
assert.Equal(t, rollups.ArbGasInfoAddress, callMsg.To.String())
assert.Equal(t, rollups.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data))
assert.Equal(t, big.NewInt(-1), blockNumber)
}).Return(zeros.Bytes(), nil)

o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{v: maxGasLimit, bumpPercent: bumpPercent, bumpMin: bumpMin}, rpcClient, ethClient)
o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{v: maxGasLimit, bumpPercent: bumpPercent, bumpMin: bumpMin}, feeEstimatorClient, l1Oracle)
servicetest.RunHealthy(t, o)
gasPrice, chainSpecificGasLimit, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice)
require.NoError(t, err)
Expand All @@ -88,19 +91,20 @@ func TestArbitrumEstimator(t *testing.T) {
})

t.Run("gas price is lower than user specified max gas price", func(t *testing.T) {
client := mocks.NewRPCClient(t)
ethClient := mocks.NewETHClient(t)
o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, client, ethClient)
feeEstimatorClient := mocks.NewFeeEstimatorClient(t)
l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient)

o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle)

client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) {
feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) {
res := args.Get(1).(*hexutil.Big)
(*big.Int)(res).SetInt64(42)
})
ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
feeEstimatorClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
callMsg := args.Get(1).(ethereum.CallMsg)
blockNumber := args.Get(2).(*big.Int)
assert.Equal(t, gas.ArbGasInfoAddress, callMsg.To.String())
assert.Equal(t, gas.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data))
assert.Equal(t, rollups.ArbGasInfoAddress, callMsg.To.String())
assert.Equal(t, rollups.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data))
assert.Equal(t, big.NewInt(-1), blockNumber)
}).Return(zeros.Bytes(), nil)

Expand All @@ -113,19 +117,20 @@ func TestArbitrumEstimator(t *testing.T) {
})

t.Run("gas price is lower than global max gas price", func(t *testing.T) {
ethClient := mocks.NewETHClient(t)
client := mocks.NewRPCClient(t)
o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, client, ethClient)
feeEstimatorClient := mocks.NewFeeEstimatorClient(t)
l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient)

client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) {
o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle)

feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) {
res := args.Get(1).(*hexutil.Big)
(*big.Int)(res).SetInt64(120)
})
ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
feeEstimatorClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
callMsg := args.Get(1).(ethereum.CallMsg)
blockNumber := args.Get(2).(*big.Int)
assert.Equal(t, gas.ArbGasInfoAddress, callMsg.To.String())
assert.Equal(t, gas.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data))
assert.Equal(t, rollups.ArbGasInfoAddress, callMsg.To.String())
assert.Equal(t, rollups.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data))
assert.Equal(t, big.NewInt(-1), blockNumber)
}).Return(zeros.Bytes(), nil)

Expand All @@ -137,24 +142,26 @@ func TestArbitrumEstimator(t *testing.T) {
})

t.Run("calling BumpLegacyGas on unstarted arbitrum estimator returns error", func(t *testing.T) {
rpcClient := mocks.NewRPCClient(t)
ethClient := mocks.NewETHClient(t)
o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, rpcClient, ethClient)
feeEstimatorClient := mocks.NewFeeEstimatorClient(t)
l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient)

o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle)
_, _, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(42), gasLimit, assets.NewWeiI(10), nil)
assert.EqualError(t, err, "estimator is not started")
})

t.Run("calling GetLegacyGas on started estimator if initial call failed returns error", func(t *testing.T) {
client := mocks.NewRPCClient(t)
ethClient := mocks.NewETHClient(t)
o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, client, ethClient)
feeEstimatorClient := mocks.NewFeeEstimatorClient(t)
l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient)

client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(pkgerrors.New("kaboom"))
ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle)

feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(pkgerrors.New("kaboom"))
feeEstimatorClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
callMsg := args.Get(1).(ethereum.CallMsg)
blockNumber := args.Get(2).(*big.Int)
assert.Equal(t, gas.ArbGasInfoAddress, callMsg.To.String())
assert.Equal(t, gas.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data))
assert.Equal(t, rollups.ArbGasInfoAddress, callMsg.To.String())
assert.Equal(t, rollups.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data))
assert.Equal(t, big.NewInt(-1), blockNumber)
}).Return(zeros.Bytes(), nil)

Expand All @@ -165,17 +172,19 @@ func TestArbitrumEstimator(t *testing.T) {
})

t.Run("calling GetDynamicFee always returns error", func(t *testing.T) {
rpcClient := mocks.NewRPCClient(t)
ethClient := mocks.NewETHClient(t)
o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, rpcClient, ethClient)
feeEstimatorClient := mocks.NewFeeEstimatorClient(t)
l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient)

o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle)
_, err := o.GetDynamicFee(testutils.Context(t), maxGasPrice)
assert.EqualError(t, err, "dynamic fees are not implemented for this estimator")
})

t.Run("calling BumpDynamicFee always returns error", func(t *testing.T) {
rpcClient := mocks.NewRPCClient(t)
ethClient := mocks.NewETHClient(t)
o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, rpcClient, ethClient)
feeEstimatorClient := mocks.NewFeeEstimatorClient(t)
l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient)

o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle)
fee := gas.DynamicFee{
FeeCap: assets.NewWeiI(42),
TipCap: assets.NewWeiI(5),
Expand All @@ -185,9 +194,10 @@ func TestArbitrumEstimator(t *testing.T) {
})

t.Run("limit computes", func(t *testing.T) {
rpcClient := mocks.NewRPCClient(t)
ethClient := mocks.NewETHClient(t)
rpcClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) {
feeEstimatorClient := mocks.NewFeeEstimatorClient(t)
l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient)

feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) {
res := args.Get(1).(*hexutil.Big)
(*big.Int)(res).SetInt64(42)
})
Expand All @@ -201,15 +211,15 @@ func TestArbitrumEstimator(t *testing.T) {
b.Write(common.BigToHash(big.NewInt(perL2Tx)).Bytes())
b.Write(common.BigToHash(big.NewInt(perL1Calldata)).Bytes())
b.Write(common.BigToHash(big.NewInt(123455)).Bytes())
ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
feeEstimatorClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
callMsg := args.Get(1).(ethereum.CallMsg)
blockNumber := args.Get(2).(*big.Int)
assert.Equal(t, gas.ArbGasInfoAddress, callMsg.To.String())
assert.Equal(t, gas.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data))
assert.Equal(t, rollups.ArbGasInfoAddress, callMsg.To.String())
assert.Equal(t, rollups.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data))
assert.Equal(t, big.NewInt(-1), blockNumber)
}).Return(b.Bytes(), nil)

o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{v: maxGasLimit, bumpPercent: bumpPercent, bumpMin: bumpMin}, rpcClient, ethClient)
o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{v: maxGasLimit, bumpPercent: bumpPercent, bumpMin: bumpMin}, feeEstimatorClient, l1Oracle)
servicetest.RunHealthy(t, o)
gasPrice, chainSpecificGasLimit, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice)
require.NoError(t, err)
Expand All @@ -220,9 +230,10 @@ func TestArbitrumEstimator(t *testing.T) {
})

t.Run("limit exceeds max", func(t *testing.T) {
rpcClient := mocks.NewRPCClient(t)
ethClient := mocks.NewETHClient(t)
rpcClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) {
feeEstimatorClient := mocks.NewFeeEstimatorClient(t)
l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient)

feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) {
res := args.Get(1).(*hexutil.Big)
(*big.Int)(res).SetInt64(42)
})
Expand All @@ -235,15 +246,15 @@ func TestArbitrumEstimator(t *testing.T) {
b.Write(common.BigToHash(big.NewInt(perL2Tx)).Bytes())
b.Write(common.BigToHash(big.NewInt(perL1Calldata)).Bytes())
b.Write(common.BigToHash(big.NewInt(123455)).Bytes())
ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
feeEstimatorClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) {
callMsg := args.Get(1).(ethereum.CallMsg)
blockNumber := args.Get(2).(*big.Int)
assert.Equal(t, gas.ArbGasInfoAddress, callMsg.To.String())
assert.Equal(t, gas.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data))
assert.Equal(t, rollups.ArbGasInfoAddress, callMsg.To.String())
assert.Equal(t, rollups.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data))
assert.Equal(t, big.NewInt(-1), blockNumber)
}).Return(b.Bytes(), nil)

o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{v: maxGasLimit, bumpPercent: bumpPercent, bumpMin: bumpMin}, rpcClient, ethClient)
o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{v: maxGasLimit, bumpPercent: bumpPercent, bumpMin: bumpMin}, feeEstimatorClient, l1Oracle)
servicetest.RunHealthy(t, o)
gasPrice, chainSpecificGasLimit, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice)
require.Error(t, err, "expected error but got (%s, %d)", gasPrice, chainSpecificGasLimit)
Expand Down

0 comments on commit 6991af2

Please sign in to comment.