Skip to content

Commit fc270eb

Browse files
committed
Connect EVM with EVM: Add support for skipping FQ v2 config if already configured during migration
1 parent 9100268 commit fc270eb

2 files changed

Lines changed: 109 additions & 0 deletions

File tree

deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/Masterminds/semver/v3"
99

10+
"github.com/ethereum/go-ethereum/accounts/abi/bind"
1011
"github.com/ethereum/go-ethereum/common"
1112

1213
fqv2ops "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v2_0_0/operations/fee_quoter"
@@ -308,6 +309,10 @@ func UpdateLanesLogic(e cldf.Environment, mcmsConfig *proposalutils.TimelockConf
308309
if err != nil {
309310
return cldf.ChangesetOutput{}, fmt.Errorf("failed to convert v1.6 fee quoter destination updates for chain %d: %w", chainSel, err)
310311
}
312+
destCfgs, err = FilterOutExistingDestChainConfigs(e, dests.Address, chainSel, destCfgs)
313+
if err != nil {
314+
return cldf.ChangesetOutput{}, err
315+
}
311316
fqUpdate.DestChainConfigs = destCfgs
312317
}
313318
if prices, ok := feeQuoterPricesInput.UpdatesByChain[chainSel]; ok {
@@ -349,6 +354,38 @@ func UpdateLanesLogic(e cldf.Environment, mcmsConfig *proposalutils.TimelockConf
349354
return output, nil
350355
}
351356

357+
// FilterOutExistingDestChainConfigs queries the on-chain v2 FeeQuoter and removes
358+
// destination chain configs that are already enabled. This prevents overwriting existing
359+
// configurations during lane updates when a destination was previously configured.
360+
func FilterOutExistingDestChainConfigs(
361+
e cldf.Environment,
362+
fqAddr common.Address,
363+
chainSel uint64,
364+
destCfgs []fqv2ops.DestChainConfigArgs,
365+
) ([]fqv2ops.DestChainConfigArgs, error) {
366+
fqContract, err := fqv2ops.NewFeeQuoterContract(fqAddr, e.BlockChains.EVMChains()[chainSel].Client)
367+
if err != nil {
368+
return nil, fmt.Errorf("failed to bind v2 FeeQuoter on chain %d: %w", chainSel, err)
369+
}
370+
filtered := make([]fqv2ops.DestChainConfigArgs, 0, len(destCfgs))
371+
for _, destCfg := range destCfgs {
372+
existing, err := fqContract.GetDestChainConfig(&bind.CallOpts{Context: e.GetContext()}, destCfg.DestChainSelector)
373+
if err != nil {
374+
return nil, fmt.Errorf("failed to query existing dest chain config on chain %d for dest %d: %w",
375+
chainSel, destCfg.DestChainSelector, err)
376+
}
377+
if existing.IsEnabled {
378+
e.Logger.Infow("skipping dest chain config already present on v2 FeeQuoter",
379+
"sourceChain", chainSel,
380+
"destChain", destCfg.DestChainSelector,
381+
)
382+
continue
383+
}
384+
filtered = append(filtered, destCfg)
385+
}
386+
return filtered, nil
387+
}
388+
352389
func ConvertV16FeeQuoterDestUpdatesToV2(in []fee_quoter.FeeQuoterDestChainConfigArgs) ([]fqv2ops.DestChainConfigArgs, error) {
353390
out := make([]fqv2ops.DestChainConfigArgs, 0, len(in))
354391
for _, cfg := range in {

deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,78 @@ func TestUpdateBidirectionalLanesChangesetWithV2FeeQuoter(t *testing.T) {
543543
}
544544
}
545545

546+
func TestFilterOutExistingDestChainConfigs(t *testing.T) {
547+
t.Parallel()
548+
549+
deployedEnvironment, _ := testhelpers.NewMemoryEnvironment(t, func(testCfg *testhelpers.TestConfigs) {
550+
testCfg.Chains = 2
551+
})
552+
e := deployedEnvironment.Env
553+
554+
state, err := stateview.LoadOnchainState(e)
555+
require.NoError(t, err, "must load onchain state")
556+
557+
selectors := e.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chain_selectors.FamilyEVM))
558+
require.Len(t, selectors, 2, "must have 2 chains")
559+
560+
chainSel := selectors[0]
561+
otherChainSel := selectors[1]
562+
evmChain := e.BlockChains.EVMChains()[chainSel]
563+
564+
parsedABI, err := abi.JSON(strings.NewReader(fqv2ops.FeeQuoterABI))
565+
require.NoError(t, err, "must parse v2 FeeQuoter ABI")
566+
567+
// Deploy a v2 FeeQuoter with one destination already configured (otherChainSel)
568+
preConfiguredDest := fqv2ops.DestChainConfigArgs{
569+
DestChainSelector: otherChainSel,
570+
DestChainConfig: fqv2ops.DestChainConfig{
571+
IsEnabled: true,
572+
MaxDataBytes: 30_000,
573+
},
574+
}
575+
fqV2Addr, tx, _, err := bind.DeployContract(
576+
evmChain.DeployerKey,
577+
parsedABI,
578+
common.FromHex(fqv2ops.FeeQuoterBin),
579+
evmChain.Client,
580+
fqv2ops.StaticConfig{
581+
MaxFeeJuelsPerMsg: big.NewInt(1e18),
582+
LinkToken: state.Chains[chainSel].LinkToken.Address(),
583+
},
584+
[]common.Address{evmChain.DeployerKey.From},
585+
[]fqv2ops.TokenTransferFeeConfigArgs{},
586+
[]fqv2ops.DestChainConfigArgs{preConfiguredDest},
587+
)
588+
require.NoError(t, err, "must deploy v2 FeeQuoter")
589+
590+
_, err = evmChain.Confirm(tx)
591+
require.NoError(t, err, "must confirm v2 FeeQuoter deployment")
592+
593+
unconfiguredChainSel := uint64(999)
594+
595+
// Call FilterOutExistingDestChainConfigs with both destinations
596+
input := []fqv2ops.DestChainConfigArgs{
597+
{
598+
DestChainSelector: otherChainSel,
599+
DestChainConfig: fqv2ops.DestChainConfig{IsEnabled: true, MaxDataBytes: 50_000},
600+
},
601+
{
602+
DestChainSelector: unconfiguredChainSel,
603+
DestChainConfig: fqv2ops.DestChainConfig{IsEnabled: true, MaxDataBytes: 60_000},
604+
},
605+
}
606+
607+
filtered, err := v1_6.FilterOutExistingDestChainConfigs(e, fqV2Addr, chainSel, input)
608+
require.NoError(t, err, "FilterOutExistingDestChainConfigs must not error")
609+
610+
// Only the unconfigured chain should remain
611+
require.Len(t, filtered, 1, "must filter out the already-enabled destination")
612+
assert.Equal(t, unconfiguredChainSel, filtered[0].DestChainSelector,
613+
"remaining entry must be the unconfigured chain")
614+
assert.Equal(t, uint32(60_000), filtered[0].DestChainConfig.MaxDataBytes,
615+
"remaining entry must preserve original config")
616+
}
617+
546618
func TestUpdateBidirectionalLanesChangesetWithV2FeeQuoterWithMCMS(t *testing.T) {
547619
t.Parallel()
548620

0 commit comments

Comments
 (0)