diff --git a/.changeset/rotten-timers-give.md b/.changeset/rotten-timers-give.md new file mode 100644 index 00000000000..ef474a17d56 --- /dev/null +++ b/.changeset/rotten-timers-give.md @@ -0,0 +1,6 @@ +--- +"chainlink": minor +--- + +Support multiple chains evm clients for TXM gas estimator to fetch L1 gas oracle +#added diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go index fa40dca6b85..7c8d61def80 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go @@ -415,7 +415,7 @@ func makeTestEvmTxm( keyStore keystore.Eth) (txmgr.TxManager, gas.EvmFeeEstimator) { config, dbConfig, evmConfig := MakeTestConfigs(t) - estimator, err := gas.NewEstimator(logger.TestLogger(t), ethClient, config.ChainType(), evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.TestLogger(t), ethClient, config.ChainType(), evmConfig.GasEstimator(), nil) require.NoError(t, err, "failed to create gas estimator") lggr := logger.TestLogger(t) diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index 69011d0025a..0505449943e 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -815,6 +815,7 @@ func (d *DAOracle) setFrom(f *DAOracle) { if v := f.OracleType; v != nil { d.OracleType = v } + if v := f.OracleAddress; v != nil { d.OracleAddress = v } diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index a162cdd014a..6a7b7c1a1ef 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" pkgerrors "github.com/pkg/errors" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" @@ -54,7 +53,7 @@ type feeEstimatorClient interface { } // NewEstimator returns the estimator for a given config -func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, chaintype chaintype.ChainType, geCfg evmconfig.GasEstimator) (EvmFeeEstimator, error) { +func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, chaintype chaintype.ChainType, geCfg evmconfig.GasEstimator, clientsByChainID map[string]rollups.DAClient) (EvmFeeEstimator, error) { bh := geCfg.BlockHistory() s := geCfg.Mode() lggr.Infow(fmt.Sprintf("Initializing EVM gas estimator in mode: %s", s), @@ -82,14 +81,11 @@ func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, chaintype ch df := geCfg.EIP1559DynamicFees() // create l1Oracle only if it is supported for the chain - var l1Oracle rollups.L1Oracle - if rollups.IsRollupWithL1Support(chaintype) { - var err error - l1Oracle, err = rollups.NewL1GasOracle(lggr, ethClient, chaintype, geCfg.DAOracle()) - if err != nil { - return nil, fmt.Errorf("failed to initialize L1 oracle: %w", err) - } + l1Oracle, err := rollups.NewL1GasOracle(lggr, ethClient, chaintype, geCfg.DAOracle(), clientsByChainID) + if err != nil { + return nil, fmt.Errorf("failed to initialize L1 oracle: %w", err) } + var newEstimator func(logger.Logger) EvmEstimator switch s { case "Arbitrum": diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go index 936a4810569..3cc83ec7034 100644 --- a/core/chains/evm/gas/models_test.go +++ b/core/chains/evm/gas/models_test.go @@ -72,8 +72,9 @@ func TestWrappedEvmEstimator(t *testing.T) { assert.Nil(t, l1Oracle) // expect l1Oracle + daOracle := rollups.CreateTestDAOracle(t, toml.DAOracleOPStack, "0x420000000000000000000000000000000000000F", "") - oracle, err := rollups.NewL1GasOracle(lggr, nil, chaintype.ChainOptimismBedrock, daOracle) + oracle, err := rollups.NewL1GasOracle(lggr, nil, chaintype.ChainOptimismBedrock, daOracle, nil) require.NoError(t, err) // cast oracle to L1Oracle interface estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) diff --git a/core/chains/evm/gas/rollups/l1_oracle.go b/core/chains/evm/gas/rollups/l1_oracle.go index 6eb965dc160..18c326ab8f6 100644 --- a/core/chains/evm/gas/rollups/l1_oracle.go +++ b/core/chains/evm/gas/rollups/l1_oracle.go @@ -10,7 +10,6 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/rpc" - "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -34,6 +33,12 @@ type l1OracleClient interface { BatchCallContext(ctx context.Context, b []rpc.BatchElem) error } +// DAClient is interface of client connections for additional chains layers +type DAClient interface { + SuggestGasPrice(ctx context.Context) (*big.Int, error) + FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) +} + type priceEntry struct { price *assets.Wei timestamp time.Time @@ -50,13 +55,20 @@ func IsRollupWithL1Support(chainType chaintype.ChainType) bool { return slices.Contains(supportedChainTypes, chainType) } -func NewL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType, daOracle evmconfig.DAOracle) (L1Oracle, error) { +func NewL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType, daOracle evmconfig.DAOracle, clientsByChainID map[string]DAClient) (L1Oracle, error) { if !IsRollupWithL1Support(chainType) { return nil, nil } + var l1Oracle L1Oracle var err error + + // TODO(CCIP-3551) the actual usage of the clientsByChainID should update the check accordingly, potentially return errors instead of logging. Going forward all configs should specify a DAOracle config. This is a fall back to maintain backwards compat. if daOracle != nil { + if clientsByChainID == nil { + lggr.Debugf("clientsByChainID map is missing") + } + oracleType := daOracle.OracleType() if oracleType == nil { return nil, errors.New("required field OracleType is nil in non-nil DAOracle config") @@ -80,7 +92,6 @@ func NewL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chai } } - // Going forward all configs should specify a DAOracle config. This is a fall back to maintain backwards compat. switch chainType { case chaintype.ChainArbitrum: l1Oracle, err = NewArbitrumL1GasOracle(lggr, ethClient) diff --git a/core/chains/evm/gas/rollups/l1_oracle_test.go b/core/chains/evm/gas/rollups/l1_oracle_test.go index 5c8dac1b4f6..9c36878a153 100644 --- a/core/chains/evm/gas/rollups/l1_oracle_test.go +++ b/core/chains/evm/gas/rollups/l1_oracle_test.go @@ -31,7 +31,7 @@ func TestL1Oracle(t *testing.T) { ethClient := mocks.NewL1OracleClient(t) daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, utils.RandomAddress().String(), "") - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainCelo, daOracle) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainCelo, daOracle, nil) require.NoError(t, err) assert.Nil(t, oracle) }) @@ -39,7 +39,7 @@ func TestL1Oracle(t *testing.T) { t.Run("DAOracle config is nil, falls back to using chainType", func(t *testing.T) { ethClient := mocks.NewL1OracleClient(t) - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum, nil) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum, nil, nil) require.NoError(t, err) assert.NotNil(t, oracle) }) @@ -48,7 +48,7 @@ func TestL1Oracle(t *testing.T) { ethClient := mocks.NewL1OracleClient(t) daOracle := CreateTestDAOracle(t, "", utils.RandomAddress().String(), "") - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum, daOracle) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum, daOracle, nil) require.NoError(t, err) assert.NotNil(t, oracle) assert.Equal(t, oracle.Name(), "L1GasOracle(arbitrum)") @@ -58,7 +58,7 @@ func TestL1Oracle(t *testing.T) { ethClient := mocks.NewL1OracleClient(t) daOracle := CreateTestDAOracle(t, "", utils.RandomAddress().String(), "") - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainZkSync, daOracle) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainZkSync, daOracle, nil) require.NoError(t, err) assert.NotNil(t, oracle) assert.Equal(t, oracle.Name(), "L1GasOracle(zkSync)") @@ -72,7 +72,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { ethClient := mocks.NewL1OracleClient(t) daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, utils.RandomAddress().String(), "") - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle, nil) require.NoError(t, err) _, err = oracle.GasPrice(tests.Context(t)) @@ -96,7 +96,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) daOracle := CreateTestDAOracle(t, toml.DAOracleArbitrum, "0x0000000000000000000000000000000000000000", "") - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum, daOracle) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainArbitrum, daOracle, nil) require.NoError(t, err) servicetest.RunHealthy(t, oracle) @@ -126,7 +126,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainKroma, daOracle) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainKroma, daOracle, nil) require.NoError(t, err) servicetest.RunHealthy(t, oracle) @@ -156,7 +156,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainOptimismBedrock, daOracle, nil) require.NoError(t, err) servicetest.RunHealthy(t, oracle) @@ -185,7 +185,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) daOracle := CreateTestDAOracle(t, toml.DAOracleOPStack, oracleAddress, "") - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainScroll, daOracle) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainScroll, daOracle, nil) require.NoError(t, err) servicetest.RunHealthy(t, oracle) @@ -223,7 +223,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { }).Return(common.BigToHash(gasPerPubByteL2).Bytes(), nil) daOracle := CreateTestDAOracle(t, toml.DAOracleZKSync, utils.RandomAddress().String(), "") - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainZkSync, daOracle) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainZkSync, daOracle, nil) require.NoError(t, err) servicetest.RunHealthy(t, oracle) @@ -250,7 +250,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { // chainType here shouldn't matter for now since we're checking daOracleConfig oracle type first. Later // we can consider limiting the chainType to only those that support custom calldata. - oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainZkSync, daOracleConfig) + oracle, err := NewL1GasOracle(logger.Test(t), ethClient, chaintype.ChainZkSync, daOracleConfig, nil) require.NoError(t, err) servicetest.RunHealthy(t, oracle) diff --git a/core/chains/evm/gas/rollups/op_l1_oracle_test.go b/core/chains/evm/gas/rollups/op_l1_oracle_test.go index 0b67cc7178d..75450d72522 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle_test.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle_test.go @@ -288,7 +288,6 @@ func TestOPL1Oracle_CalculateFjordGasPrice(t *testing.T) { blobBaseFeeScalar := big.NewInt(5) decimals := big.NewInt(6) oracleAddress := utils.RandomAddress().String() - t.Parallel() t.Run("correctly fetches gas price if chain has upgraded to Fjord", func(t *testing.T) { diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index c47ca85737b..b70e2fed671 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -101,7 +101,7 @@ func TestTxm_SendNativeToken_DoesNotSendToZero(t *testing.T) { keyStore := cltest.NewKeyStore(t, db).Eth() ethClient := testutils.NewEthClientMockWithDefaultChain(t) - estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config.ChainType(), evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config.ChainType(), evmConfig.GasEstimator(), nil) require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), keyStore) require.NoError(t, err) @@ -127,7 +127,7 @@ func TestTxm_CreateTransaction(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) - estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config.ChainType(), evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config.ChainType(), evmConfig.GasEstimator(), nil) require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst.Eth()) require.NoError(t, err) @@ -409,7 +409,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config.ChainType(), evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config.ChainType(), evmConfig.GasEstimator(), nil) require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), etKeyStore) require.NoError(t, err) @@ -507,7 +507,7 @@ func TestTxm_Lifecycle(t *testing.T) { keyChangeCh := make(chan struct{}) unsub := cltest.NewAwaiter() kst.On("SubscribeToKeyChanges", mock.Anything).Return(keyChangeCh, unsub.ItHappened) - estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config.ChainType(), evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, config.ChainType(), evmConfig.GasEstimator(), nil) require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst) require.NoError(t, err) @@ -562,7 +562,7 @@ func TestTxm_Reset(t *testing.T) { ethClient.On("PendingNonceAt", mock.Anything, addr).Return(uint64(128), nil).Maybe() ethClient.On("PendingNonceAt", mock.Anything, addr2).Return(uint64(44), nil).Maybe() - estimator, err := gas.NewEstimator(logger.Test(t), ethClient, cfg.EVM().ChainType(), cfg.EVM().GasEstimator()) + estimator, err := gas.NewEstimator(logger.Test(t), ethClient, cfg.EVM().ChainType(), cfg.EVM().GasEstimator(), nil) require.NoError(t, err) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, cfg.EVM(), cfg.EVM().GasEstimator(), cfg.EVM().Transactions(), gcfg.Database(), gcfg.Database().Listener(), kst.Eth()) require.NoError(t, err) diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index 277d6283690..d8eed88dedf 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -10,6 +10,8 @@ import ( gotoml "github.com/pelletier/go-toml/v2" "go.uber.org/multierr" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" + common "github.com/smartcontractkit/chainlink-common/pkg/chains" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -173,7 +175,7 @@ func (o ChainOpts) Validate() error { return err } -func NewTOMLChain(ctx context.Context, chain *toml.EVMConfig, opts ChainRelayOpts) (Chain, error) { +func NewTOMLChain(ctx context.Context, chain *toml.EVMConfig, opts ChainRelayOpts, clientsByChainID map[string]rollups.DAClient) (Chain, error) { err := opts.Validate() if err != nil { return nil, err @@ -185,10 +187,10 @@ func NewTOMLChain(ctx context.Context, chain *toml.EVMConfig, opts ChainRelayOpt } cfg := evmconfig.NewTOMLChainScopedConfig(chain, l) // note: per-chain validation is not necessary at this point since everything is checked earlier on boot. - return newChain(ctx, cfg, chain.Nodes, opts) + return newChain(ctx, cfg, chain.Nodes, opts, clientsByChainID) } -func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Node, opts ChainRelayOpts) (*chain, error) { +func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Node, opts ChainRelayOpts, clientsByChainID map[string]rollups.DAClient) (*chain, error) { chainID := cfg.EVM().ChainID() l := opts.Logger var client evmclient.Client @@ -243,7 +245,7 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod } // note: gas estimator is started as a part of the txm - txm, gasEstimator, err := newEvmTxm(opts.DS, cfg.EVM(), opts.AppConfig.EVMRPCEnabled(), opts.AppConfig.Database(), opts.AppConfig.Database().Listener(), client, l, logPoller, opts, headTracker) + txm, gasEstimator, err := newEvmTxm(opts.DS, cfg.EVM(), opts.AppConfig.EVMRPCEnabled(), opts.AppConfig.Database(), opts.AppConfig.Database().Listener(), client, l, logPoller, opts, headTracker, clientsByChainID) if err != nil { return nil, fmt.Errorf("failed to instantiate EvmTxm for chain with ID %s: %w", chainID.String(), err) } diff --git a/core/chains/legacyevm/evm_txm.go b/core/chains/legacyevm/evm_txm.go index ec7098ab56c..5af3799ec7b 100644 --- a/core/chains/legacyevm/evm_txm.go +++ b/core/chains/legacyevm/evm_txm.go @@ -7,6 +7,7 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -24,6 +25,7 @@ func newEvmTxm( logPoller logpoller.LogPoller, opts ChainRelayOpts, headTracker httypes.HeadTracker, + clientsByChainID map[string]rollups.DAClient, ) (txm txmgr.TxManager, estimator gas.EvmFeeEstimator, err error, @@ -45,7 +47,7 @@ func newEvmTxm( // build estimator from factory if opts.GenGasEstimator == nil { - if estimator, err = gas.NewEstimator(lggr, client, cfg.ChainType(), cfg.GasEstimator()); err != nil { + if estimator, err = gas.NewEstimator(lggr, client, cfg.ChainType(), cfg.GasEstimator(), clientsByChainID); err != nil { return nil, nil, fmt.Errorf("failed to initialize estimator: %w", err) } } else { diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index d37e812a19d..f5a3aaa7b59 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -1405,6 +1405,7 @@ func TestConfig_full(t *testing.T) { if got.EVM[c].GasEstimator.DAOracle.OracleAddress == nil { got.EVM[c].GasEstimator.DAOracle.OracleAddress = new(types.EIP55Address) } + if got.EVM[c].GasEstimator.DAOracle.CustomGasPriceCalldata == nil { got.EVM[c].GasEstimator.DAOracle.CustomGasPriceCalldata = new(string) } diff --git a/core/services/headreporter/prometheus_reporter_test.go b/core/services/headreporter/prometheus_reporter_test.go index d6fc0f8e938..ab85bac1ac0 100644 --- a/core/services/headreporter/prometheus_reporter_test.go +++ b/core/services/headreporter/prometheus_reporter_test.go @@ -109,7 +109,7 @@ func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainCon config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) keyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - estimator, err := gas.NewEstimator(logger.TestLogger(t), ethClient, config.ChainType(), evmConfig.GasEstimator()) + estimator, err := gas.NewEstimator(logger.TestLogger(t), ethClient, config.ChainType(), evmConfig.GasEstimator(), nil) require.NoError(t, err) lggr := logger.TestLogger(t) lpOpts := logpoller.Opts{ diff --git a/core/services/relay/evm/relayer_extender.go b/core/services/relay/evm/relayer_extender.go index 884597df718..0d01494169f 100644 --- a/core/services/relay/evm/relayer_extender.go +++ b/core/services/relay/evm/relayer_extender.go @@ -7,6 +7,8 @@ import ( "go.uber.org/multierr" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" ) @@ -55,6 +57,8 @@ func NewLegacyChains(ctx context.Context, opts legacyevm.ChainRelayOpts) (result } } + // map with lazy initialization for the txm to access evm clients for different chain + var clientsByChainID = make(map[string]rollups.DAClient) for i := range enabled { cid := enabled[i].ChainID.String() privOpts := legacyevm.ChainRelayOpts{ @@ -64,12 +68,13 @@ func NewLegacyChains(ctx context.Context, opts legacyevm.ChainRelayOpts) (result } privOpts.Logger.Infow(fmt.Sprintf("Loading chain %s", cid), "evmChainID", cid) - chain, err2 := legacyevm.NewTOMLChain(ctx, enabled[i], privOpts) + chain, err2 := legacyevm.NewTOMLChain(ctx, enabled[i], privOpts, clientsByChainID) if err2 != nil { err = multierr.Combine(err, fmt.Errorf("failed to create chain %s: %w", cid, err2)) continue } + clientsByChainID[cid] = chain.Client() result = append(result, chain) } return