From a8eb00be5df6bb035add0eb0171675808b249988 Mon Sep 17 00:00:00 2001 From: Kyle Martin Date: Wed, 26 Mar 2025 16:19:06 -0400 Subject: [PATCH 1/8] Add changeset to add bidirectional lanes --- .../v1_6/cs_add_bidirectional_lanes.go | 228 ++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go diff --git a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go b/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go new file mode 100644 index 00000000000..981ef7d4067 --- /dev/null +++ b/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go @@ -0,0 +1,228 @@ +package v1_6 + +import ( + "fmt" + "math/big" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/fee_quoter" + "github.com/smartcontractkit/mcms" +) + +// AddBidirectionalLanesChangeset adds multiple bidirectional lanes to CCIP. +// It batches all lane additions into a single MCMS proposal. +var AddBidirectionalLanesChangeset = deployment.CreateChangeSet(addBidirectionalLanesLogic, addBidirectionalLanesPrecondition) + +// BidirectionalLaneDefinition indicates two chains that we want to connect. +type BidirectionalLaneDefinition [2]ChainDefinition + +// laneDefinition defines a lane between source and destination. +type laneDefinition struct { + // Source defines the source chain. + Source ChainDefinition + // Dest defines the destination chain. + Dest ChainDefinition +} + +// AddBidirectionalLanesConfig is a configuration struct for AddBidirectionalLanesChangeset. +type AddBidirectionalLanesConfig struct { + // MCMSConfig defines the MCMS configuration for the changeset. + MCMSConfig *changeset.MCMSConfig + // Lanes describes the lanes that we want to create. + Lanes []BidirectionalLaneDefinition + // TestRouter indicates if we want to enable these lanes on the test router. + TestRouter bool +} + +type addBidirectionalLanesChangesetConfigs struct { + UpdateFeeQuoterDestsConfig UpdateFeeQuoterDestsConfig + UpdateFeeQuoterPricesConfig UpdateFeeQuoterPricesConfig + UpdateOnRampDestsConfig UpdateOnRampDestsConfig + UpdateOffRampSourcesConfig UpdateOffRampSourcesConfig + UpdateRouterRampsConfig UpdateRouterRampsConfig +} + +func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChangesetConfigs { + onRampUpdatesByChain := make(map[uint64]map[uint64]OnRampDestinationUpdate) + offRampUpdatesByChain := make(map[uint64]map[uint64]OffRampSourceUpdate) + routerUpdatesByChain := make(map[uint64]RouterUpdates) + feeQuoterDestUpdatesByChain := make(map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig) + feeQuoterPriceUpdatesByChain := make(map[uint64]FeeQuoterPriceUpdatePerSource) + + for _, lane := range c.Lanes { + chainA := lane[0] + chainB := lane[1] + + laneAToB := laneDefinition{ + Source: chainA, + Dest: chainB, + } + laneBToA := laneDefinition{ + Source: chainB, + Dest: chainA, + } + + for _, laneDef := range []laneDefinition{laneAToB, laneBToA} { + // Setting the destination on the on ramp + if onRampUpdatesByChain[laneDef.Source.Selector] == nil { + onRampUpdatesByChain[laneDef.Source.Selector] = make(map[uint64]OnRampDestinationUpdate) + } + onRampUpdatesByChain[laneDef.Source.Selector][laneDef.Dest.Selector] = OnRampDestinationUpdate{ + IsEnabled: true, + TestRouter: c.TestRouter, + AllowListEnabled: laneDef.Dest.AllowListEnabled, + } + + // Setting the source on the off ramp + if offRampUpdatesByChain[laneDef.Dest.Selector] == nil { + offRampUpdatesByChain[laneDef.Dest.Selector] = make(map[uint64]OffRampSourceUpdate) + } + offRampUpdatesByChain[laneDef.Dest.Selector][laneDef.Source.Selector] = OffRampSourceUpdate{ + IsEnabled: true, + TestRouter: c.TestRouter, + IsRMNVerificationDisabled: laneDef.Source.RMNVerificationDisabled, + } + + // Setting the on ramp on the source router + routerUpdatesOnSource := routerUpdatesByChain[laneDef.Source.Selector] + if routerUpdatesByChain[laneDef.Source.Selector].OnRampUpdates == nil { + routerUpdatesOnSource.OnRampUpdates = make(map[uint64]bool) + } + routerUpdatesOnSource.OnRampUpdates[laneDef.Source.Selector] = true + routerUpdatesByChain[laneDef.Source.Selector] = routerUpdatesOnSource + + // Setting the off ramp on the dest router + routerUpdatesOnDest := routerUpdatesByChain[laneDef.Dest.Selector] + if routerUpdatesByChain[laneDef.Dest.Selector].OffRampUpdates == nil { + routerUpdatesOnDest.OffRampUpdates = make(map[uint64]bool) + } + routerUpdatesOnDest.OffRampUpdates[laneDef.Dest.Selector] = true + routerUpdatesByChain[laneDef.Dest.Selector] = routerUpdatesOnDest + + // Setting the fee quoter destination on the source chain + if feeQuoterDestUpdatesByChain[laneDef.Source.Selector] == nil { + feeQuoterDestUpdatesByChain[laneDef.Source.Selector] = make(map[uint64]fee_quoter.FeeQuoterDestChainConfig) + } + feeQuoterDestUpdatesByChain[laneDef.Source.Selector][laneDef.Dest.Selector] = laneDef.Dest.FeeQuoterDestChainConfig + + // setting the destination gas prices on the source chain + feeQuoterPriceUpdatesOnSource := feeQuoterPriceUpdatesByChain[laneDef.Source.Selector] + if feeQuoterPriceUpdatesOnSource.GasPrices == nil { + feeQuoterPriceUpdatesOnSource.GasPrices = make(map[uint64]*big.Int) + } + feeQuoterPriceUpdatesOnSource.GasPrices[laneDef.Dest.Selector] = laneDef.Dest.GasPrice + feeQuoterPriceUpdatesByChain[laneDef.Source.Selector] = feeQuoterPriceUpdatesOnSource + } + } + + return addBidirectionalLanesChangesetConfigs{ + UpdateFeeQuoterDestsConfig: UpdateFeeQuoterDestsConfig{ + MCMS: c.MCMSConfig, + UpdatesByChain: feeQuoterDestUpdatesByChain, + }, + UpdateFeeQuoterPricesConfig: UpdateFeeQuoterPricesConfig{ + MCMS: c.MCMSConfig, + PricesByChain: feeQuoterPriceUpdatesByChain, + }, + UpdateOnRampDestsConfig: UpdateOnRampDestsConfig{ + MCMS: c.MCMSConfig, + UpdatesByChain: onRampUpdatesByChain, + }, + UpdateOffRampSourcesConfig: UpdateOffRampSourcesConfig{ + MCMS: c.MCMSConfig, + UpdatesByChain: offRampUpdatesByChain, + }, + UpdateRouterRampsConfig: UpdateRouterRampsConfig{ + TestRouter: c.TestRouter, + MCMS: c.MCMSConfig, + UpdatesByChain: routerUpdatesByChain, + }, + } +} + +func addBidirectionalLanesPrecondition(e deployment.Environment, c AddBidirectionalLanesConfig) error { + configs := c.buildConfigs() + state, err := changeset.LoadOnchainState(e) + if err != nil { + return fmt.Errorf("failed to load onchain state: %w", err) + } + + err = configs.UpdateFeeQuoterDestsConfig.Validate(e) + if err != nil { + return fmt.Errorf("failed to validate UpdateFeeQuoterDestsConfig: %w", err) + } + + err = configs.UpdateFeeQuoterPricesConfig.Validate(e) + if err != nil { + return fmt.Errorf("failed to validate UpdateFeeQuoterPricesConfig: %w", err) + } + + err = configs.UpdateOnRampDestsConfig.Validate(e) + if err != nil { + return fmt.Errorf("failed to validate UpdateOnRampDestsConfig: %w", err) + } + + err = configs.UpdateOffRampSourcesConfig.Validate(e, state) + if err != nil { + return fmt.Errorf("failed to validate UpdateOffRampSourcesConfig: %w", err) + } + + err = configs.UpdateRouterRampsConfig.Validate(e, state) + if err != nil { + return fmt.Errorf("failed to validate UpdateRouterRampsConfig: %w", err) + } + + return nil +} + +func addBidirectionalLanesLogic(e deployment.Environment, c AddBidirectionalLanesConfig) (deployment.ChangesetOutput, error) { + proposals := make([]mcms.TimelockProposal, 0) + configs := c.buildConfigs() + + out, err := UpdateFeeQuoterDestsChangeset(e, configs.UpdateFeeQuoterDestsConfig) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to run UpdateFeeQuoterDestsChangeset: %w", err) + } + proposals = append(proposals, out.MCMSTimelockProposals...) + + out, err = UpdateFeeQuoterPricesChangeset(e, configs.UpdateFeeQuoterPricesConfig) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to run UpdateFeeQuoterPricesChangeset: %w", err) + } + proposals = append(proposals, out.MCMSTimelockProposals...) + + out, err = UpdateOnRampsDestsChangeset(e, configs.UpdateOnRampDestsConfig) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to run UpdateOnRampDestsChangeset: %w", err) + } + proposals = append(proposals, out.MCMSTimelockProposals...) + + out, err = UpdateOffRampSourcesChangeset(e, configs.UpdateOffRampSourcesConfig) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to run UpdateOffRampSourcesChangeset: %w", err) + } + proposals = append(proposals, out.MCMSTimelockProposals...) + + out, err = UpdateRouterRampsChangeset(e, configs.UpdateRouterRampsConfig) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to run UpdateRouterRampsChangeset: %w", err) + } + proposals = append(proposals, out.MCMSTimelockProposals...) + + state, err := changeset.LoadOnchainState(e) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) + } + proposal, err := aggregateProposals(e, state, proposals, nil, "Add multiple bidirectional lanes", c.MCMSConfig) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to aggregate proposals: %w", err) + } + if proposal == nil { + return deployment.ChangesetOutput{}, nil + } + + return deployment.ChangesetOutput{ + MCMSTimelockProposals: []mcms.TimelockProposal{*proposal}, + }, nil +} From 4e1de94164678000b0b8be06f3cc8223aed76e0a Mon Sep 17 00:00:00 2001 From: Kyle Martin Date: Fri, 28 Mar 2025 14:39:55 -0400 Subject: [PATCH 2/8] Add tests --- .../v1_6/cs_add_bidirectional_lanes.go | 13 +- .../v1_6/cs_add_bidirectional_lanes_test.go | 241 ++++++++++++++++++ 2 files changed, 250 insertions(+), 4 deletions(-) create mode 100644 deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes_test.go diff --git a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go b/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go index 981ef7d4067..601b22981fe 100644 --- a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go +++ b/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go @@ -89,7 +89,7 @@ func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChanges if routerUpdatesByChain[laneDef.Source.Selector].OnRampUpdates == nil { routerUpdatesOnSource.OnRampUpdates = make(map[uint64]bool) } - routerUpdatesOnSource.OnRampUpdates[laneDef.Source.Selector] = true + routerUpdatesOnSource.OnRampUpdates[laneDef.Dest.Selector] = true routerUpdatesByChain[laneDef.Source.Selector] = routerUpdatesOnSource // Setting the off ramp on the dest router @@ -97,7 +97,7 @@ func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChanges if routerUpdatesByChain[laneDef.Dest.Selector].OffRampUpdates == nil { routerUpdatesOnDest.OffRampUpdates = make(map[uint64]bool) } - routerUpdatesOnDest.OffRampUpdates[laneDef.Dest.Selector] = true + routerUpdatesOnDest.OffRampUpdates[laneDef.Source.Selector] = true routerUpdatesByChain[laneDef.Dest.Selector] = routerUpdatesOnDest // Setting the fee quoter destination on the source chain @@ -106,7 +106,7 @@ func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChanges } feeQuoterDestUpdatesByChain[laneDef.Source.Selector][laneDef.Dest.Selector] = laneDef.Dest.FeeQuoterDestChainConfig - // setting the destination gas prices on the source chain + // Setting the destination gas prices on the source chain feeQuoterPriceUpdatesOnSource := feeQuoterPriceUpdatesByChain[laneDef.Source.Selector] if feeQuoterPriceUpdatesOnSource.GasPrices == nil { feeQuoterPriceUpdatesOnSource.GasPrices = make(map[uint64]*big.Int) @@ -116,6 +116,11 @@ func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChanges } } + routerMCMSConfig := c.MCMSConfig + if c.TestRouter { + routerMCMSConfig = nil // Test router is never owned by MCMS + } + return addBidirectionalLanesChangesetConfigs{ UpdateFeeQuoterDestsConfig: UpdateFeeQuoterDestsConfig{ MCMS: c.MCMSConfig, @@ -135,7 +140,7 @@ func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChanges }, UpdateRouterRampsConfig: UpdateRouterRampsConfig{ TestRouter: c.TestRouter, - MCMS: c.MCMSConfig, + MCMS: routerMCMSConfig, UpdatesByChain: routerUpdatesByChain, }, } diff --git a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes_test.go b/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes_test.go new file mode 100644 index 00000000000..5b462a0ccf3 --- /dev/null +++ b/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes_test.go @@ -0,0 +1,241 @@ +package v1_6_test + +import ( + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" +) + +type laneDefinition struct { + Source v1_6.ChainDefinition + Dest v1_6.ChainDefinition +} + +func getAllPossibleLanes(chains []v1_6.ChainDefinition) []v1_6.BidirectionalLaneDefinition { + lanes := make([]v1_6.BidirectionalLaneDefinition, 0) + paired := make(map[uint64]map[uint64]bool) + + for i, chainA := range chains { + for j, chainB := range chains { + if i == j { + continue + } + if paired[chainA.Selector] != nil && paired[chainA.Selector][chainB.Selector] { + continue + } + if paired[chainB.Selector] != nil && paired[chainB.Selector][chainA.Selector] { + continue + } + + lanes = append(lanes, v1_6.BidirectionalLaneDefinition{chainA, chainB}) + if paired[chainA.Selector] == nil { + paired[chainA.Selector] = make(map[uint64]bool) + } + paired[chainA.Selector][chainB.Selector] = true + if paired[chainB.Selector] == nil { + paired[chainB.Selector] = make(map[uint64]bool) + } + paired[chainB.Selector][chainA.Selector] = true + } + } + + return lanes +} + +func getRemoteChains(chains []v1_6.ChainDefinition, currentIndex int) []v1_6.ChainDefinition { + remoteChains := make([]v1_6.ChainDefinition, 0, len(chains)-1) + for i, chain := range chains { + if i == currentIndex { + continue + } + remoteChains = append(remoteChains, chain) + } + return remoteChains +} + +func checkBidirectionalLaneConnectivity( + t *testing.T, + e deployment.Environment, + state changeset.CCIPOnChainState, + chainOne v1_6.ChainDefinition, + chainTwo v1_6.ChainDefinition, + testRouter bool, +) { + lanes := []laneDefinition{ + { + Source: chainOne, + Dest: chainTwo, + }, + { + Source: chainTwo, + Dest: chainOne, + }, + } + for _, lane := range lanes { + onRamp := state.Chains[lane.Source.Selector].OnRamp + offRamp := state.Chains[lane.Dest.Selector].OffRamp + feeQuoterOnSrc := state.Chains[lane.Source.Selector].FeeQuoter + routerOnSrc := state.Chains[lane.Source.Selector].Router + routerOnDest := state.Chains[lane.Dest.Selector].Router + if testRouter { + routerOnSrc = state.Chains[lane.Source.Selector].TestRouter + routerOnDest = state.Chains[lane.Dest.Selector].TestRouter + } + + destChainConfig, err := onRamp.GetDestChainConfig(nil, lane.Dest.Selector) + require.NoError(t, err, "must get dest chain config from onRamp") + require.Equal(t, routerOnSrc.Address().Hex(), destChainConfig.Router.Hex(), "router must equal expected") + require.Equal(t, lane.Dest.AllowListEnabled, destChainConfig.AllowlistEnabled, "allowListEnabled must equal expected") + + srcChainConfig, err := offRamp.GetSourceChainConfig(nil, lane.Source.Selector) + require.NoError(t, err, "must get src chain config from offRamp") + require.True(t, srcChainConfig.IsEnabled, "src chain config must be enabled") + require.Equal(t, lane.Source.RMNVerificationDisabled, srcChainConfig.IsRMNVerificationDisabled, "rmnVerificationDisabled must equal expected") + require.Equal(t, common.LeftPadBytes(state.Chains[lane.Source.Selector].OnRamp.Address().Bytes(), 32), srcChainConfig.OnRamp, "remote onRamp must be set on offRamp") + require.Equal(t, routerOnDest.Address().Hex(), srcChainConfig.Router.Hex(), "router must equal expected") + + isOffRamp, err := routerOnSrc.IsOffRamp(nil, lane.Dest.Selector, state.Chains[lane.Source.Selector].OffRamp.Address()) + require.NoError(t, err, "must check if router has offRamp") + require.True(t, isOffRamp, "router must have offRamp") + onRampOnRouter, err := routerOnSrc.GetOnRamp(nil, lane.Dest.Selector) + require.NoError(t, err, "must get onRamp from router") + require.Equal(t, state.Chains[lane.Source.Selector].OnRamp.Address().Hex(), onRampOnRouter.Hex(), "onRamp must equal expected") + + isOffRamp, err = routerOnDest.IsOffRamp(nil, lane.Source.Selector, state.Chains[lane.Dest.Selector].OffRamp.Address()) + require.NoError(t, err, "must check if router has offRamp") + require.True(t, isOffRamp, "router must have offRamp") + onRampOnRouter, err = routerOnDest.GetOnRamp(nil, lane.Source.Selector) + require.NoError(t, err, "must get onRamp from router") + require.Equal(t, state.Chains[lane.Dest.Selector].OnRamp.Address().Hex(), onRampOnRouter.Hex(), "onRamp must equal expected") + + feeQuoterDestConfig, err := feeQuoterOnSrc.GetDestChainConfig(nil, lane.Dest.Selector) + require.NoError(t, err, "must get dest chain config from feeQuoter") + require.Equal(t, lane.Dest.FeeQuoterDestChainConfig, feeQuoterDestConfig, "feeQuoter dest chain config must equal expected") + + price, err := feeQuoterOnSrc.GetDestinationChainGasPrice(nil, lane.Dest.Selector) + require.NoError(t, err, "must get price from feeQuoter") + require.Equal(t, lane.Dest.GasPrice, price.Value, "price must equal expected") + } +} + +func TestAddBidirectionalLanesChangeset(t *testing.T) { + t.Parallel() + + type test struct { + Msg string + TestRouter bool + MCMS *changeset.MCMSConfig + } + + mcmsConfig := &changeset.MCMSConfig{ + MinDelay: 0 * time.Second, + MCMSAction: timelock.Schedule, + } + + tests := []test{ + { + Msg: "Use production router (with MCMS)", + TestRouter: false, + MCMS: mcmsConfig, + }, + { + Msg: "Use test router (without MCMS)", + TestRouter: true, + MCMS: nil, + }, + { + Msg: "Use test router (with MCMS for other contracts)", + TestRouter: true, + MCMS: mcmsConfig, + }, + } + + for _, test := range tests { + t.Run(test.Msg, func(t *testing.T) { + deployedEnvironment, _ := testhelpers.NewMemoryEnvironment(t, func(testCfg *testhelpers.TestConfigs) { + testCfg.Chains = 3 + }) + e := deployedEnvironment.Env + + state, err := changeset.LoadOnchainState(e) + require.NoError(t, err, "must load onchain state") + + selectors := e.AllChainSelectors() + + timelockContracts := make(map[uint64]*proposalutils.TimelockExecutionContracts, len(selectors)) + for _, selector := range selectors { + // Assemble map of addresses required for Timelock scheduling & execution + timelockContracts[selector] = &proposalutils.TimelockExecutionContracts{ + Timelock: state.Chains[selector].Timelock, + CallProxy: state.Chains[selector].CallProxy, + } + } + + if test.MCMS != nil { + contractsToTransfer := make(map[uint64][]common.Address, len(selectors)) + for _, selector := range selectors { + contractsToTransfer[selector] = []common.Address{ + state.Chains[selector].OnRamp.Address(), + state.Chains[selector].OffRamp.Address(), + state.Chains[selector].Router.Address(), + state.Chains[selector].FeeQuoter.Address(), + } + } + e, err = commonchangeset.Apply(t, e, timelockContracts, + commonchangeset.Configure( + deployment.CreateLegacyChangeSet(commoncs.TransferToMCMSWithTimelock), + commoncs.TransferToMCMSWithTimelockConfig{ + ContractsByChain: contractsToTransfer, + MinDelay: 0 * time.Second, + }, + ), + ) + require.NoError(t, err, "must apply TransferToMCMSWithTimelock") + } + + chains := make([]v1_6.ChainDefinition, len(selectors)) + for i, selector := range selectors { + chains[i] = v1_6.ChainDefinition{ + ConnectionConfig: v1_6.ConnectionConfig{ + RMNVerificationDisabled: true, + AllowListEnabled: false, + }, + Selector: selector, + GasPrice: big.NewInt(1e17), + FeeQuoterDestChainConfig: v1_6.DefaultFeeQuoterDestChainConfig(true), + } + } + + e, err = commonchangeset.Apply(t, e, timelockContracts, + commonchangeset.Configure( + v1_6.AddBidirectionalLanesChangeset, + v1_6.AddBidirectionalLanesConfig{ + TestRouter: test.TestRouter, + MCMSConfig: test.MCMS, + Lanes: getAllPossibleLanes(chains), + }, + ), + ) + require.NoError(t, err, "must apply AddBidirectionalLanesChangeset") + + for i, chain := range chains { + remoteChains := getRemoteChains(chains, i) + for _, remoteChain := range remoteChains { + checkBidirectionalLaneConnectivity(t, e, state, chain, remoteChain, test.TestRouter) + } + } + }) + } +} From 9b9f0a96773fba18f59c645d601dc28ed9d64fb9 Mon Sep 17 00:00:00 2001 From: Kyle Martin Date: Fri, 28 Mar 2025 14:53:46 -0400 Subject: [PATCH 3/8] Fix --- .../changeset/v1_6/cs_add_bidirectional_lanes.go | 3 ++- .../v1_6/cs_add_bidirectional_lanes_test.go | 13 ++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go b/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go index 601b22981fe..42d84d2dba7 100644 --- a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go +++ b/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go @@ -6,6 +6,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/fee_quoter" "github.com/smartcontractkit/mcms" ) @@ -28,7 +29,7 @@ type laneDefinition struct { // AddBidirectionalLanesConfig is a configuration struct for AddBidirectionalLanesChangeset. type AddBidirectionalLanesConfig struct { // MCMSConfig defines the MCMS configuration for the changeset. - MCMSConfig *changeset.MCMSConfig + MCMSConfig *proposalutils.TimelockConfig // Lanes describes the lanes that we want to create. Lanes []BidirectionalLaneDefinition // TestRouter indicates if we want to enable these lanes on the test router. diff --git a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes_test.go b/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes_test.go index 5b462a0ccf3..53b0324853c 100644 --- a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes_test.go +++ b/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes_test.go @@ -6,7 +6,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/mcms/types" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/deployment" @@ -136,12 +136,12 @@ func TestAddBidirectionalLanesChangeset(t *testing.T) { type test struct { Msg string TestRouter bool - MCMS *changeset.MCMSConfig + MCMS *proposalutils.TimelockConfig } - mcmsConfig := &changeset.MCMSConfig{ + mcmsConfig := &proposalutils.TimelockConfig{ MinDelay: 0 * time.Second, - MCMSAction: timelock.Schedule, + MCMSAction: types.TimelockActionSchedule, } tests := []test{ @@ -198,7 +198,10 @@ func TestAddBidirectionalLanesChangeset(t *testing.T) { deployment.CreateLegacyChangeSet(commoncs.TransferToMCMSWithTimelock), commoncs.TransferToMCMSWithTimelockConfig{ ContractsByChain: contractsToTransfer, - MinDelay: 0 * time.Second, + MCMSConfig: proposalutils.TimelockConfig{ + MinDelay: 0 * time.Second, + MCMSAction: types.TimelockActionSchedule, + }, }, ), ) From 2c7392e14aabe011d350f094766c305c9242b901 Mon Sep 17 00:00:00 2001 From: Kyle Martin Date: Fri, 28 Mar 2025 15:02:32 -0400 Subject: [PATCH 4/8] Goimports --- deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go b/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go index 42d84d2dba7..3b9e4adaf0d 100644 --- a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go +++ b/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go @@ -4,11 +4,12 @@ import ( "fmt" "math/big" + "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/fee_quoter" - "github.com/smartcontractkit/mcms" ) // AddBidirectionalLanesChangeset adds multiple bidirectional lanes to CCIP. From 5059146e9086fc4115d6b3a2a3563beb34c4d991 Mon Sep 17 00:00:00 2001 From: Kyle Martin Date: Tue, 1 Apr 2025 16:19:53 -0400 Subject: [PATCH 5/8] Comments --- ...es.go => cs_update_bidirectional_lanes.go} | 51 +++-- ... => cs_update_bidirectional_lanes_test.go} | 185 ++++++++++++++++-- 2 files changed, 203 insertions(+), 33 deletions(-) rename deployment/ccip/changeset/v1_6/{cs_add_bidirectional_lanes.go => cs_update_bidirectional_lanes.go} (82%) rename deployment/ccip/changeset/v1_6/{cs_add_bidirectional_lanes_test.go => cs_update_bidirectional_lanes_test.go} (60%) diff --git a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go similarity index 82% rename from deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go rename to deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go index 3b9e4adaf0d..430d52eba48 100644 --- a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes.go +++ b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go @@ -12,12 +12,17 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/fee_quoter" ) -// AddBidirectionalLanesChangeset adds multiple bidirectional lanes to CCIP. -// It batches all lane additions into a single MCMS proposal. -var AddBidirectionalLanesChangeset = deployment.CreateChangeSet(addBidirectionalLanesLogic, addBidirectionalLanesPrecondition) +// UpdateBidirectionalLanesChangeset enables or disables multiple bidirectional lanes on CCIP. +// It batches all lane updates into a single MCMS proposal. +var UpdateBidirectionalLanesChangeset = deployment.CreateChangeSet(updateBidirectionalLanesLogic, updateBidirectionalLanesPrecondition) // BidirectionalLaneDefinition indicates two chains that we want to connect. -type BidirectionalLaneDefinition [2]ChainDefinition +type BidirectionalLaneDefinition struct { + // IsDisabled indicates if the lane should be disabled. + // We use IsDisabled instead of IsEnabled because enabling a lane should be the default action. + IsDisabled bool + Chains [2]ChainDefinition +} // laneDefinition defines a lane between source and destination. type laneDefinition struct { @@ -27,8 +32,8 @@ type laneDefinition struct { Dest ChainDefinition } -// AddBidirectionalLanesConfig is a configuration struct for AddBidirectionalLanesChangeset. -type AddBidirectionalLanesConfig struct { +// UpdateBidirectionalLanesConfig is a configuration struct for UpdateBidirectionalLanesChangeset. +type UpdateBidirectionalLanesConfig struct { // MCMSConfig defines the MCMS configuration for the changeset. MCMSConfig *proposalutils.TimelockConfig // Lanes describes the lanes that we want to create. @@ -37,7 +42,7 @@ type AddBidirectionalLanesConfig struct { TestRouter bool } -type addBidirectionalLanesChangesetConfigs struct { +type updateBidirectionalLanesChangesetConfigs struct { UpdateFeeQuoterDestsConfig UpdateFeeQuoterDestsConfig UpdateFeeQuoterPricesConfig UpdateFeeQuoterPricesConfig UpdateOnRampDestsConfig UpdateOnRampDestsConfig @@ -45,7 +50,7 @@ type addBidirectionalLanesChangesetConfigs struct { UpdateRouterRampsConfig UpdateRouterRampsConfig } -func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChangesetConfigs { +func (c UpdateBidirectionalLanesConfig) BuildConfigs() updateBidirectionalLanesChangesetConfigs { onRampUpdatesByChain := make(map[uint64]map[uint64]OnRampDestinationUpdate) offRampUpdatesByChain := make(map[uint64]map[uint64]OffRampSourceUpdate) routerUpdatesByChain := make(map[uint64]RouterUpdates) @@ -53,8 +58,9 @@ func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChanges feeQuoterPriceUpdatesByChain := make(map[uint64]FeeQuoterPriceUpdatePerSource) for _, lane := range c.Lanes { - chainA := lane[0] - chainB := lane[1] + isEnabled := !lane.IsDisabled + chainA := lane.Chains[0] + chainB := lane.Chains[1] laneAToB := laneDefinition{ Source: chainA, @@ -71,7 +77,7 @@ func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChanges onRampUpdatesByChain[laneDef.Source.Selector] = make(map[uint64]OnRampDestinationUpdate) } onRampUpdatesByChain[laneDef.Source.Selector][laneDef.Dest.Selector] = OnRampDestinationUpdate{ - IsEnabled: true, + IsEnabled: isEnabled, TestRouter: c.TestRouter, AllowListEnabled: laneDef.Dest.AllowListEnabled, } @@ -81,7 +87,7 @@ func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChanges offRampUpdatesByChain[laneDef.Dest.Selector] = make(map[uint64]OffRampSourceUpdate) } offRampUpdatesByChain[laneDef.Dest.Selector][laneDef.Source.Selector] = OffRampSourceUpdate{ - IsEnabled: true, + IsEnabled: isEnabled, TestRouter: c.TestRouter, IsRMNVerificationDisabled: laneDef.Source.RMNVerificationDisabled, } @@ -91,7 +97,7 @@ func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChanges if routerUpdatesByChain[laneDef.Source.Selector].OnRampUpdates == nil { routerUpdatesOnSource.OnRampUpdates = make(map[uint64]bool) } - routerUpdatesOnSource.OnRampUpdates[laneDef.Dest.Selector] = true + routerUpdatesOnSource.OnRampUpdates[laneDef.Dest.Selector] = isEnabled routerUpdatesByChain[laneDef.Source.Selector] = routerUpdatesOnSource // Setting the off ramp on the dest router @@ -99,7 +105,7 @@ func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChanges if routerUpdatesByChain[laneDef.Dest.Selector].OffRampUpdates == nil { routerUpdatesOnDest.OffRampUpdates = make(map[uint64]bool) } - routerUpdatesOnDest.OffRampUpdates[laneDef.Source.Selector] = true + routerUpdatesOnDest.OffRampUpdates[laneDef.Source.Selector] = isEnabled routerUpdatesByChain[laneDef.Dest.Selector] = routerUpdatesOnDest // Setting the fee quoter destination on the source chain @@ -123,7 +129,7 @@ func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChanges routerMCMSConfig = nil // Test router is never owned by MCMS } - return addBidirectionalLanesChangesetConfigs{ + return updateBidirectionalLanesChangesetConfigs{ UpdateFeeQuoterDestsConfig: UpdateFeeQuoterDestsConfig{ MCMS: c.MCMSConfig, UpdatesByChain: feeQuoterDestUpdatesByChain, @@ -148,8 +154,8 @@ func (c AddBidirectionalLanesConfig) buildConfigs() addBidirectionalLanesChanges } } -func addBidirectionalLanesPrecondition(e deployment.Environment, c AddBidirectionalLanesConfig) error { - configs := c.buildConfigs() +func updateBidirectionalLanesPrecondition(e deployment.Environment, c UpdateBidirectionalLanesConfig) error { + configs := c.BuildConfigs() state, err := changeset.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) @@ -183,45 +189,50 @@ func addBidirectionalLanesPrecondition(e deployment.Environment, c AddBidirectio return nil } -func addBidirectionalLanesLogic(e deployment.Environment, c AddBidirectionalLanesConfig) (deployment.ChangesetOutput, error) { +func updateBidirectionalLanesLogic(e deployment.Environment, c UpdateBidirectionalLanesConfig) (deployment.ChangesetOutput, error) { proposals := make([]mcms.TimelockProposal, 0) - configs := c.buildConfigs() + configs := c.BuildConfigs() out, err := UpdateFeeQuoterDestsChangeset(e, configs.UpdateFeeQuoterDestsConfig) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to run UpdateFeeQuoterDestsChangeset: %w", err) } proposals = append(proposals, out.MCMSTimelockProposals...) + e.Logger.Info("Destination configs updated on FeeQuoters") out, err = UpdateFeeQuoterPricesChangeset(e, configs.UpdateFeeQuoterPricesConfig) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to run UpdateFeeQuoterPricesChangeset: %w", err) } proposals = append(proposals, out.MCMSTimelockProposals...) + e.Logger.Info("Gas prices updated on FeeQuoters") out, err = UpdateOnRampsDestsChangeset(e, configs.UpdateOnRampDestsConfig) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to run UpdateOnRampDestsChangeset: %w", err) } proposals = append(proposals, out.MCMSTimelockProposals...) + e.Logger.Info("Destination configs updated on OnRamps") out, err = UpdateOffRampSourcesChangeset(e, configs.UpdateOffRampSourcesConfig) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to run UpdateOffRampSourcesChangeset: %w", err) } proposals = append(proposals, out.MCMSTimelockProposals...) + e.Logger.Info("Source configs updated on OffRamps") out, err = UpdateRouterRampsChangeset(e, configs.UpdateRouterRampsConfig) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to run UpdateRouterRampsChangeset: %w", err) } proposals = append(proposals, out.MCMSTimelockProposals...) + e.Logger.Info("Ramps updated on Routers") state, err := changeset.LoadOnchainState(e) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - proposal, err := aggregateProposals(e, state, proposals, nil, "Add multiple bidirectional lanes", c.MCMSConfig) + proposal, err := aggregateProposals(e, state, proposals, nil, "Update multiple bidirectional lanes", c.MCMSConfig) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to aggregate proposals: %w", err) } diff --git a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes_test.go b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes_test.go similarity index 60% rename from deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes_test.go rename to deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes_test.go index 53b0324853c..b16ecb86431 100644 --- a/deployment/ccip/changeset/v1_6/cs_add_bidirectional_lanes_test.go +++ b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes_test.go @@ -16,6 +16,7 @@ import ( commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/fee_quoter" ) type laneDefinition struct { @@ -23,7 +24,7 @@ type laneDefinition struct { Dest v1_6.ChainDefinition } -func getAllPossibleLanes(chains []v1_6.ChainDefinition) []v1_6.BidirectionalLaneDefinition { +func getAllPossibleLanes(chains []v1_6.ChainDefinition, disable bool) []v1_6.BidirectionalLaneDefinition { lanes := make([]v1_6.BidirectionalLaneDefinition, 0) paired := make(map[uint64]map[uint64]bool) @@ -39,7 +40,10 @@ func getAllPossibleLanes(chains []v1_6.ChainDefinition) []v1_6.BidirectionalLane continue } - lanes = append(lanes, v1_6.BidirectionalLaneDefinition{chainA, chainB}) + lanes = append(lanes, v1_6.BidirectionalLaneDefinition{ + Chains: [2]v1_6.ChainDefinition{chainA, chainB}, + IsDisabled: disable, + }) if paired[chainA.Selector] == nil { paired[chainA.Selector] = make(map[uint64]bool) } @@ -72,6 +76,7 @@ func checkBidirectionalLaneConnectivity( chainOne v1_6.ChainDefinition, chainTwo v1_6.ChainDefinition, testRouter bool, + disable bool, ) { lanes := []laneDefinition{ { @@ -96,29 +101,41 @@ func checkBidirectionalLaneConnectivity( destChainConfig, err := onRamp.GetDestChainConfig(nil, lane.Dest.Selector) require.NoError(t, err, "must get dest chain config from onRamp") - require.Equal(t, routerOnSrc.Address().Hex(), destChainConfig.Router.Hex(), "router must equal expected") + routerAddr := routerOnSrc.Address().Hex() + if disable { + routerAddr = common.HexToAddress("0x0").Hex() + } + require.Equal(t, routerAddr, destChainConfig.Router.Hex(), "router must equal expected") require.Equal(t, lane.Dest.AllowListEnabled, destChainConfig.AllowlistEnabled, "allowListEnabled must equal expected") srcChainConfig, err := offRamp.GetSourceChainConfig(nil, lane.Source.Selector) require.NoError(t, err, "must get src chain config from offRamp") - require.True(t, srcChainConfig.IsEnabled, "src chain config must be enabled") + require.Equal(t, !disable, srcChainConfig.IsEnabled, "isEnabled must be expected") require.Equal(t, lane.Source.RMNVerificationDisabled, srcChainConfig.IsRMNVerificationDisabled, "rmnVerificationDisabled must equal expected") require.Equal(t, common.LeftPadBytes(state.Chains[lane.Source.Selector].OnRamp.Address().Bytes(), 32), srcChainConfig.OnRamp, "remote onRamp must be set on offRamp") require.Equal(t, routerOnDest.Address().Hex(), srcChainConfig.Router.Hex(), "router must equal expected") isOffRamp, err := routerOnSrc.IsOffRamp(nil, lane.Dest.Selector, state.Chains[lane.Source.Selector].OffRamp.Address()) require.NoError(t, err, "must check if router has offRamp") - require.True(t, isOffRamp, "router must have offRamp") + require.Equal(t, !disable, isOffRamp, "isOffRamp result must equal expected") onRampOnRouter, err := routerOnSrc.GetOnRamp(nil, lane.Dest.Selector) require.NoError(t, err, "must get onRamp from router") - require.Equal(t, state.Chains[lane.Source.Selector].OnRamp.Address().Hex(), onRampOnRouter.Hex(), "onRamp must equal expected") + onRampAddr := state.Chains[lane.Source.Selector].OnRamp.Address().Hex() + if disable { + onRampAddr = common.HexToAddress("0x0").Hex() + } + require.Equal(t, onRampAddr, onRampOnRouter.Hex(), "onRamp must equal expected") isOffRamp, err = routerOnDest.IsOffRamp(nil, lane.Source.Selector, state.Chains[lane.Dest.Selector].OffRamp.Address()) require.NoError(t, err, "must check if router has offRamp") - require.True(t, isOffRamp, "router must have offRamp") + require.Equal(t, !disable, isOffRamp, "isOffRamp result must equal expected") onRampOnRouter, err = routerOnDest.GetOnRamp(nil, lane.Source.Selector) require.NoError(t, err, "must get onRamp from router") - require.Equal(t, state.Chains[lane.Dest.Selector].OnRamp.Address().Hex(), onRampOnRouter.Hex(), "onRamp must equal expected") + onRampAddr = state.Chains[lane.Dest.Selector].OnRamp.Address().Hex() + if disable { + onRampAddr = common.HexToAddress("0x0").Hex() + } + require.Equal(t, onRampAddr, onRampOnRouter.Hex(), "onRamp must equal expected") feeQuoterDestConfig, err := feeQuoterOnSrc.GetDestChainConfig(nil, lane.Dest.Selector) require.NoError(t, err, "must get dest chain config from feeQuoter") @@ -130,13 +147,128 @@ func checkBidirectionalLaneConnectivity( } } -func TestAddBidirectionalLanesChangeset(t *testing.T) { +func TestBuildConfigs(t *testing.T) { + selectors := []uint64{1, 2} + + chains := make([]v1_6.ChainDefinition, len(selectors)) + for i, selector := range selectors { + chains[i] = v1_6.ChainDefinition{ + ConnectionConfig: v1_6.ConnectionConfig{ + RMNVerificationDisabled: true, + AllowListEnabled: false, + }, + Selector: selector, + GasPrice: big.NewInt(1e17), + FeeQuoterDestChainConfig: v1_6.DefaultFeeQuoterDestChainConfig(true), + } + } + + cfg := v1_6.UpdateBidirectionalLanesConfig{ + TestRouter: false, + MCMSConfig: &proposalutils.TimelockConfig{ + MinDelay: 0 * time.Second, + MCMSAction: types.TimelockActionSchedule, + }, + Lanes: getAllPossibleLanes(chains, false), + } + + configs := cfg.BuildConfigs() + + require.Equal(t, configs.UpdateFeeQuoterDestsConfig, v1_6.UpdateFeeQuoterDestsConfig{ + UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{ + 1: { + 2: v1_6.DefaultFeeQuoterDestChainConfig(true), + }, + 2: { + 1: v1_6.DefaultFeeQuoterDestChainConfig(true), + }, + }, + MCMS: cfg.MCMSConfig, + }) + require.Equal(t, configs.UpdateFeeQuoterPricesConfig, v1_6.UpdateFeeQuoterPricesConfig{ + PricesByChain: map[uint64]v1_6.FeeQuoterPriceUpdatePerSource{ + 1: { + GasPrices: map[uint64]*big.Int{ + 2: big.NewInt(1e17), + }, + }, + 2: { + GasPrices: map[uint64]*big.Int{ + 1: big.NewInt(1e17), + }, + }, + }, + MCMS: cfg.MCMSConfig, + }) + require.Equal(t, configs.UpdateOffRampSourcesConfig, v1_6.UpdateOffRampSourcesConfig{ + UpdatesByChain: map[uint64]map[uint64]v1_6.OffRampSourceUpdate{ + 1: { + 2: { + IsEnabled: true, + TestRouter: false, + IsRMNVerificationDisabled: true, + }, + }, + 2: { + 1: { + IsEnabled: true, + TestRouter: false, + IsRMNVerificationDisabled: true, + }, + }, + }, + MCMS: cfg.MCMSConfig, + }) + require.Equal(t, configs.UpdateOnRampDestsConfig, v1_6.UpdateOnRampDestsConfig{ + UpdatesByChain: map[uint64]map[uint64]v1_6.OnRampDestinationUpdate{ + 1: { + 2: { + IsEnabled: true, + TestRouter: false, + AllowListEnabled: false, + }, + }, + 2: { + 1: { + IsEnabled: true, + TestRouter: false, + AllowListEnabled: false, + }, + }, + }, + MCMS: cfg.MCMSConfig, + }) + require.Equal(t, configs.UpdateRouterRampsConfig, v1_6.UpdateRouterRampsConfig{ + UpdatesByChain: map[uint64]v1_6.RouterUpdates{ + 1: { + OnRampUpdates: map[uint64]bool{ + 2: true, + }, + OffRampUpdates: map[uint64]bool{ + 2: true, + }, + }, + 2: { + OnRampUpdates: map[uint64]bool{ + 1: true, + }, + OffRampUpdates: map[uint64]bool{ + 1: true, + }, + }, + }, + MCMS: cfg.MCMSConfig, + }) +} + +func TestUpdateBidirectionalLanesChangeset(t *testing.T) { t.Parallel() type test struct { Msg string TestRouter bool MCMS *proposalutils.TimelockConfig + Disable bool } mcmsConfig := &proposalutils.TimelockConfig{ @@ -145,6 +277,12 @@ func TestAddBidirectionalLanesChangeset(t *testing.T) { } tests := []test{ + { + Msg: "Use production router (with MCMS) & disable afterwards", + TestRouter: false, + MCMS: mcmsConfig, + Disable: true, + }, { Msg: "Use production router (with MCMS)", TestRouter: false, @@ -223,11 +361,11 @@ func TestAddBidirectionalLanesChangeset(t *testing.T) { e, err = commonchangeset.Apply(t, e, timelockContracts, commonchangeset.Configure( - v1_6.AddBidirectionalLanesChangeset, - v1_6.AddBidirectionalLanesConfig{ + v1_6.UpdateBidirectionalLanesChangeset, + v1_6.UpdateBidirectionalLanesConfig{ TestRouter: test.TestRouter, MCMSConfig: test.MCMS, - Lanes: getAllPossibleLanes(chains), + Lanes: getAllPossibleLanes(chains, false), }, ), ) @@ -236,7 +374,28 @@ func TestAddBidirectionalLanesChangeset(t *testing.T) { for i, chain := range chains { remoteChains := getRemoteChains(chains, i) for _, remoteChain := range remoteChains { - checkBidirectionalLaneConnectivity(t, e, state, chain, remoteChain, test.TestRouter) + checkBidirectionalLaneConnectivity(t, e, state, chain, remoteChain, test.TestRouter, false) + } + } + + if test.Disable { + e, err = commonchangeset.Apply(t, e, timelockContracts, + commonchangeset.Configure( + v1_6.UpdateBidirectionalLanesChangeset, + v1_6.UpdateBidirectionalLanesConfig{ + TestRouter: test.TestRouter, + MCMSConfig: test.MCMS, + Lanes: getAllPossibleLanes(chains, true), + }, + ), + ) + require.NoError(t, err, "must apply AddBidirectionalLanesChangeset") + + for i, chain := range chains { + remoteChains := getRemoteChains(chains, i) + for _, remoteChain := range remoteChains { + checkBidirectionalLaneConnectivity(t, e, state, chain, remoteChain, test.TestRouter, true) + } } } }) From a05304793156ef533328216ce79731c4e2281136 Mon Sep 17 00:00:00 2001 From: Kyle Martin Date: Tue, 1 Apr 2025 16:59:56 -0400 Subject: [PATCH 6/8] Lint --- .../cs_update_bidirectional_lanes_test.go | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes_test.go b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes_test.go index b16ecb86431..fbf7dafacdc 100644 --- a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes_test.go +++ b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes_test.go @@ -174,7 +174,7 @@ func TestBuildConfigs(t *testing.T) { configs := cfg.BuildConfigs() - require.Equal(t, configs.UpdateFeeQuoterDestsConfig, v1_6.UpdateFeeQuoterDestsConfig{ + require.Equal(t, v1_6.UpdateFeeQuoterDestsConfig{ UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{ 1: { 2: v1_6.DefaultFeeQuoterDestChainConfig(true), @@ -184,8 +184,8 @@ func TestBuildConfigs(t *testing.T) { }, }, MCMS: cfg.MCMSConfig, - }) - require.Equal(t, configs.UpdateFeeQuoterPricesConfig, v1_6.UpdateFeeQuoterPricesConfig{ + }, configs.UpdateFeeQuoterDestsConfig) + require.Equal(t, v1_6.UpdateFeeQuoterPricesConfig{ PricesByChain: map[uint64]v1_6.FeeQuoterPriceUpdatePerSource{ 1: { GasPrices: map[uint64]*big.Int{ @@ -199,8 +199,8 @@ func TestBuildConfigs(t *testing.T) { }, }, MCMS: cfg.MCMSConfig, - }) - require.Equal(t, configs.UpdateOffRampSourcesConfig, v1_6.UpdateOffRampSourcesConfig{ + }, configs.UpdateFeeQuoterPricesConfig) + require.Equal(t, v1_6.UpdateOffRampSourcesConfig{ UpdatesByChain: map[uint64]map[uint64]v1_6.OffRampSourceUpdate{ 1: { 2: { @@ -218,8 +218,8 @@ func TestBuildConfigs(t *testing.T) { }, }, MCMS: cfg.MCMSConfig, - }) - require.Equal(t, configs.UpdateOnRampDestsConfig, v1_6.UpdateOnRampDestsConfig{ + }, configs.UpdateOffRampSourcesConfig) + require.Equal(t, v1_6.UpdateOnRampDestsConfig{ UpdatesByChain: map[uint64]map[uint64]v1_6.OnRampDestinationUpdate{ 1: { 2: { @@ -237,8 +237,8 @@ func TestBuildConfigs(t *testing.T) { }, }, MCMS: cfg.MCMSConfig, - }) - require.Equal(t, configs.UpdateRouterRampsConfig, v1_6.UpdateRouterRampsConfig{ + }, configs.UpdateOnRampDestsConfig) + require.Equal(t, v1_6.UpdateRouterRampsConfig{ UpdatesByChain: map[uint64]v1_6.RouterUpdates{ 1: { OnRampUpdates: map[uint64]bool{ @@ -258,7 +258,7 @@ func TestBuildConfigs(t *testing.T) { }, }, MCMS: cfg.MCMSConfig, - }) + }, configs.UpdateRouterRampsConfig) } func TestUpdateBidirectionalLanesChangeset(t *testing.T) { From ff7bdd7ac372547cac44c1a15f56c69030b33e00 Mon Sep 17 00:00:00 2001 From: Kyle Martin Date: Wed, 2 Apr 2025 16:44:26 -0400 Subject: [PATCH 7/8] Fix link --- .../ccip/changeset/v1_6/cs_update_bidirectional_lanes.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go index 430d52eba48..3a1fd117399 100644 --- a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go +++ b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go @@ -42,7 +42,7 @@ type UpdateBidirectionalLanesConfig struct { TestRouter bool } -type updateBidirectionalLanesChangesetConfigs struct { +type UpdateBidirectionalLanesChangesetConfigs struct { UpdateFeeQuoterDestsConfig UpdateFeeQuoterDestsConfig UpdateFeeQuoterPricesConfig UpdateFeeQuoterPricesConfig UpdateOnRampDestsConfig UpdateOnRampDestsConfig @@ -50,7 +50,7 @@ type updateBidirectionalLanesChangesetConfigs struct { UpdateRouterRampsConfig UpdateRouterRampsConfig } -func (c UpdateBidirectionalLanesConfig) BuildConfigs() updateBidirectionalLanesChangesetConfigs { +func (c UpdateBidirectionalLanesConfig) BuildConfigs() UpdateBidirectionalLanesChangesetConfigs { onRampUpdatesByChain := make(map[uint64]map[uint64]OnRampDestinationUpdate) offRampUpdatesByChain := make(map[uint64]map[uint64]OffRampSourceUpdate) routerUpdatesByChain := make(map[uint64]RouterUpdates) @@ -129,7 +129,7 @@ func (c UpdateBidirectionalLanesConfig) BuildConfigs() updateBidirectionalLanesC routerMCMSConfig = nil // Test router is never owned by MCMS } - return updateBidirectionalLanesChangesetConfigs{ + return UpdateBidirectionalLanesChangesetConfigs{ UpdateFeeQuoterDestsConfig: UpdateFeeQuoterDestsConfig{ MCMS: c.MCMSConfig, UpdatesByChain: feeQuoterDestUpdatesByChain, From f63a767dece487458de99b8c638c4cf88cb99b19 Mon Sep 17 00:00:00 2001 From: Kyle Martin Date: Thu, 3 Apr 2025 08:33:22 -0400 Subject: [PATCH 8/8] Fix build --- deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go index 3a1fd117399..fa372868270 100644 --- a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go +++ b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go @@ -232,7 +232,7 @@ func updateBidirectionalLanesLogic(e deployment.Environment, c UpdateBidirection if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - proposal, err := aggregateProposals(e, state, proposals, nil, "Update multiple bidirectional lanes", c.MCMSConfig) + proposal, err := proposalutils.AggregateProposals(e, state.EVMMCMSStateByChain(), proposals, nil, "Update multiple bidirectional lanes", c.MCMSConfig) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to aggregate proposals: %w", err) }