diff --git a/deployment/ccip/changeset/cs_chain_contracts.go b/deployment/ccip/changeset/cs_chain_contracts.go index a05296e0bd7..11bcef5b0d4 100644 --- a/deployment/ccip/changeset/cs_chain_contracts.go +++ b/deployment/ccip/changeset/cs_chain_contracts.go @@ -11,10 +11,10 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" chain_selectors "github.com/smartcontractkit/chain-selectors" + mcmslib "github.com/smartcontractkit/mcms" + mcmssdk "github.com/smartcontractkit/mcms/sdk" + mcmstypes "github.com/smartcontractkit/mcms/types" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -143,9 +143,12 @@ func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManag if err != nil { return deployment.ChangesetOutput{}, err } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + + batches := []mcmstypes.BatchOperation{} + timelocks := make(map[uint64]string) + proposers := make(map[uint64]string) + inspectors := make(map[uint64]mcmssdk.Inspector) + for chainSel, updates := range cfg.UpdatesByChain { txOpts := e.Chains[chainSel].DeployerKey if cfg.MCMS != nil { @@ -200,39 +203,51 @@ func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManag } } if cfg.MCMS != nil { - ops := make([]mcms.Operation, 0) + mcmsTransactions := make([]mcmstypes.Transaction, 0) if authTx != nil { - ops = append(ops, mcms.Operation{ - To: nm.Address(), - Data: authTx.Data(), - Value: big.NewInt(0), - }) + mcmsTx, err := proposalutils.TransactionForChain(chainSel, nm.Address().Hex(), authTx.Data(), big.NewInt(0), + string(NonceManager), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to create transaction for chain %d: %w", chainSel, err) + } + + mcmsTransactions = append(mcmsTransactions, mcmsTx) } if prevRampsTx != nil { - ops = append(ops, mcms.Operation{ - To: nm.Address(), - Data: prevRampsTx.Data(), - Value: big.NewInt(0), - }) + mcmsTx, err := proposalutils.TransactionForChain(chainSel, nm.Address().Hex(), prevRampsTx.Data(), big.NewInt(0), + string(NonceManager), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to create transaction for chain %d: %w", chainSel, err) + } + + mcmsTransactions = append(mcmsTransactions, mcmsTx) } - if len(ops) == 0 { + if len(mcmsTransactions) == 0 { return deployment.ChangesetOutput{}, errors.New("no operations to batch") } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: ops, + + batches = append(batches, mcmstypes.BatchOperation{ + ChainSelector: mcmstypes.ChainSelector(chainSel), + Transactions: mcmsTransactions, }) - timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() - proposers[chainSel] = s.Chains[chainSel].ProposerMcm + + timelocks[chainSel] = s.Chains[chainSel].Timelock.Address().Hex() + proposers[chainSel] = s.Chains[chainSel].ProposerMcm.Address().Hex() + inspectors[chainSel], err = proposalutils.McmsInspectorForChain(e, chainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get inspector for chain %d: %w", chainSel, err) + } } } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - p, err := proposalutils.BuildProposalFromBatches( + proposal, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), timelocks, proposers, + inspectors, batches, "Update nonce manager for previous ramps and authorized callers", cfg.MCMS.MinDelay, @@ -240,9 +255,8 @@ func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManag if err != nil { return deployment.ChangesetOutput{}, err } - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil + + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } type OnRampDestinationUpdate struct { @@ -314,9 +328,12 @@ func UpdateOnRampsDestsChangeset(e deployment.Environment, cfg UpdateOnRampDests if err != nil { return deployment.ChangesetOutput{}, err } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + + batches := []mcmstypes.BatchOperation{} + timelocks := make(map[uint64]string) + proposers := make(map[uint64]string) + inspectors := make(map[uint64]mcmssdk.Inspector) + for chainSel, updates := range cfg.UpdatesByChain { txOpts := e.Chains[chainSel].DeployerKey txOpts.Context = e.GetContext() @@ -350,26 +367,31 @@ func UpdateOnRampsDestsChangeset(e deployment.Environment, cfg UpdateOnRampDests if err != nil { return deployment.ChangesetOutput{}, err } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: onRamp.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() - proposers[chainSel] = s.Chains[chainSel].ProposerMcm + + batchOperation, err := proposalutils.BatchOperationForChain(chainSel, onRamp.Address().Hex(), tx.Data(), + big.NewInt(0), string(OnRamp), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, err + } + batches = append(batches, batchOperation) + + timelocks[chainSel] = s.Chains[chainSel].Timelock.Address().Hex() + proposers[chainSel] = s.Chains[chainSel].ProposerMcm.Address().Hex() + inspectors[chainSel], err = proposalutils.McmsInspectorForChain(e, chainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get inspector for chain %d: %w", chainSel, err) + } } } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - p, err := proposalutils.BuildProposalFromBatches( + + proposal, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), timelocks, proposers, + inspectors, batches, "Update onramp destinations", cfg.MCMS.MinDelay, @@ -377,9 +399,8 @@ func UpdateOnRampsDestsChangeset(e deployment.Environment, cfg UpdateOnRampDests if err != nil { return deployment.ChangesetOutput{}, err } - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil + + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } type OnRampDynamicConfigUpdate struct { @@ -422,9 +443,12 @@ func UpdateOnRampDynamicConfigChangeset(e deployment.Environment, cfg UpdateOnRa if err := cfg.Validate(e, state); err != nil { return deployment.ChangesetOutput{}, err } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + + batches := []mcmstypes.BatchOperation{} + timelocks := make(map[uint64]string) + proposers := make(map[uint64]string) + inspectors := make(map[uint64]mcmssdk.Inspector) + for chainSel, update := range cfg.UpdatesByChain { txOps := e.Chains[chainSel].DeployerKey if cfg.MCMS != nil { @@ -458,33 +482,35 @@ func UpdateOnRampDynamicConfigChangeset(e deployment.Environment, cfg UpdateOnRa if err != nil { return deployment.ChangesetOutput{}, err } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: onRamp.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[chainSel] = state.Chains[chainSel].Timelock.Address() - proposers[chainSel] = state.Chains[chainSel].ProposerMcm + + batchOperation, err := proposalutils.BatchOperationForChain(chainSel, onRamp.Address().Hex(), tx.Data(), + big.NewInt(0), string(OnRamp), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, err + } + batches = append(batches, batchOperation) + + timelocks[chainSel] = state.Chains[chainSel].Timelock.Address().Hex() + proposers[chainSel] = state.Chains[chainSel].ProposerMcm.Address().Hex() + inspectors[chainSel], err = proposalutils.McmsInspectorForChain(e, chainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get inspector for chain %d: %w", chainSel, err) + } } } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - proposal, err := proposalutils.BuildProposalFromBatches( - timelocks, proposers, batches, + + proposal, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), timelocks, proposers, inspectors, batches, "update onramp dynamic config", cfg.MCMS.MinDelay) if err != nil { return deployment.ChangesetOutput{}, err } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*proposal}, - }, nil + + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } type OnRampAllowListUpdate struct { @@ -559,9 +585,12 @@ func UpdateOnRampAllowListChangeset(e deployment.Environment, cfg UpdateOnRampAl if err != nil { return deployment.ChangesetOutput{}, err } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + + batches := []mcmstypes.BatchOperation{} + timelocks := make(map[uint64]string) + proposers := make(map[uint64]string) + inspectors := make(map[uint64]mcmssdk.Inspector) + for srcSel, updates := range cfg.UpdatesByChain { txOps := e.Chains[srcSel].DeployerKey if cfg.MCMS != nil { @@ -611,26 +640,31 @@ func UpdateOnRampAllowListChangeset(e deployment.Environment, cfg UpdateOnRampAl if err != nil { return deployment.ChangesetOutput{}, err } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(srcSel), - Batch: []mcms.Operation{ - { - To: onRamp.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[srcSel] = onchain.Chains[srcSel].Timelock.Address() - proposers[srcSel] = onchain.Chains[srcSel].ProposerMcm + + batchOperation, err := proposalutils.BatchOperationForChain(srcSel, onRamp.Address().Hex(), tx.Data(), + big.NewInt(0), string(OnRamp), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, err + } + batches = append(batches, batchOperation) + + timelocks[srcSel] = onchain.Chains[srcSel].Timelock.Address().Hex() + proposers[srcSel] = onchain.Chains[srcSel].ProposerMcm.Address().Hex() + inspectors[srcSel], err = proposalutils.McmsInspectorForChain(e, srcSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get inspector for chain %d: %w", srcSel, err) + } } } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - proposal, err := proposalutils.BuildProposalFromBatches( + + proposal, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), timelocks, proposers, + inspectors, batches, "update onramp allowlist", cfg.MCMS.MinDelay, @@ -638,9 +672,8 @@ func UpdateOnRampAllowListChangeset(e deployment.Environment, cfg UpdateOnRampAl if err != nil { return deployment.ChangesetOutput{}, err } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*proposal}, - }, nil + + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } type WithdrawOnRampFeeTokensConfig struct { @@ -691,9 +724,12 @@ func WithdrawOnRampFeeTokensChangeset(e deployment.Environment, cfg WithdrawOnRa if err := cfg.Validate(e, state); err != nil { return deployment.ChangesetOutput{}, err } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + + batches := []mcmstypes.BatchOperation{} + timelocks := make(map[uint64]string) + proposers := make(map[uint64]string) + inspectors := make(map[uint64]mcmssdk.Inspector) + for chainSel, feeTokens := range cfg.FeeTokensByChain { txOps := e.Chains[chainSel].DeployerKey onRamp := state.Chains[chainSel].OnRamp @@ -706,26 +742,31 @@ func WithdrawOnRampFeeTokensChangeset(e deployment.Environment, cfg WithdrawOnRa if err != nil { return deployment.ChangesetOutput{}, err } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: onRamp.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[chainSel] = state.Chains[chainSel].Timelock.Address() - proposers[chainSel] = state.Chains[chainSel].ProposerMcm + + batchOperation, err := proposalutils.BatchOperationForChain(chainSel, onRamp.Address().Hex(), tx.Data(), + big.NewInt(0), string(OnRamp), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, err + } + batches = append(batches, batchOperation) + + timelocks[chainSel] = state.Chains[chainSel].Timelock.Address().Hex() + proposers[chainSel] = state.Chains[chainSel].ProposerMcm.Address().Hex() + inspectors[chainSel], err = proposalutils.McmsInspectorForChain(e, chainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get inspector for chain %d: %w", chainSel, err) + } } } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - proposal, err := proposalutils.BuildProposalFromBatches( + + proposal, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), timelocks, proposers, + inspectors, batches, "withdraw onramp fee tokens", cfg.MCMS.MinDelay, @@ -733,9 +774,8 @@ func WithdrawOnRampFeeTokensChangeset(e deployment.Environment, cfg WithdrawOnRa if err != nil { return deployment.ChangesetOutput{}, err } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*proposal}, - }, nil + + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } type UpdateFeeQuoterPricesConfig struct { @@ -831,9 +871,12 @@ func UpdateFeeQuoterPricesChangeset(e deployment.Environment, cfg UpdateFeeQuote if err != nil { return deployment.ChangesetOutput{}, err } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + + batches := []mcmstypes.BatchOperation{} + timelocks := make(map[uint64]string) + proposers := make(map[uint64]string) + inspectors := make(map[uint64]mcmssdk.Inspector) + for chainSel, initialPrice := range cfg.PricesByChain { txOpts := e.Chains[chainSel].DeployerKey if cfg.MCMS != nil { @@ -866,27 +909,31 @@ func UpdateFeeQuoterPricesChangeset(e deployment.Environment, cfg UpdateFeeQuote if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("error updating prices for chain %s: %w", e.Chains[chainSel].String(), err) } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: fq.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() - proposers[chainSel] = s.Chains[chainSel].ProposerMcm + + batchOperation, err := proposalutils.BatchOperationForChain(chainSel, fq.Address().Hex(), tx.Data(), + big.NewInt(0), string(FeeQuoter), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, err + } + batches = append(batches, batchOperation) + + timelocks[chainSel] = s.Chains[chainSel].Timelock.Address().Hex() + proposers[chainSel] = s.Chains[chainSel].ProposerMcm.Address().Hex() + inspectors[chainSel], err = proposalutils.McmsInspectorForChain(e, chainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get inspector for chain %d: %w", chainSel, err) + } } } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - p, err := proposalutils.BuildProposalFromBatches( + proposal, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), timelocks, proposers, + inspectors, batches, "Update fq prices", cfg.MCMS.MinDelay, @@ -894,9 +941,8 @@ func UpdateFeeQuoterPricesChangeset(e deployment.Environment, cfg UpdateFeeQuote if err != nil { return deployment.ChangesetOutput{}, err } - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil + + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } type UpdateFeeQuoterDestsConfig struct { @@ -956,9 +1002,12 @@ func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoter if err != nil { return deployment.ChangesetOutput{}, err } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + + batches := []mcmstypes.BatchOperation{} + timelocks := make(map[uint64]string) + proposers := make(map[uint64]string) + inspectors := make(map[uint64]mcmssdk.Inspector) + for chainSel, updates := range cfg.UpdatesByChain { txOpts := e.Chains[chainSel].DeployerKey txOpts.Context = e.GetContext() @@ -982,27 +1031,30 @@ func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoter return deployment.ChangesetOutput{}, err } } else { - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: fq.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() - proposers[chainSel] = s.Chains[chainSel].ProposerMcm + batchOperation, err := proposalutils.BatchOperationForChain(chainSel, fq.Address().Hex(), tx.Data(), + big.NewInt(0), string(FeeQuoter), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, err + } + batches = append(batches, batchOperation) + + timelocks[chainSel] = s.Chains[chainSel].Timelock.Address().Hex() + proposers[chainSel] = s.Chains[chainSel].ProposerMcm.Address().Hex() + inspectors[chainSel], err = proposalutils.McmsInspectorForChain(e, chainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get inspector for chain %d: %w", chainSel, err) + } } } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - p, err := proposalutils.BuildProposalFromBatches( + proposal, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), timelocks, proposers, + inspectors, batches, "Update fq destinations", cfg.MCMS.MinDelay, @@ -1010,9 +1062,8 @@ func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoter if err != nil { return deployment.ChangesetOutput{}, err } - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil + + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } type OffRampSourceUpdate struct { @@ -1078,9 +1129,12 @@ func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSo if err := cfg.Validate(e, state); err != nil { return deployment.ChangesetOutput{}, err } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + + batches := []mcmstypes.BatchOperation{} + timelocks := make(map[uint64]string) + proposers := make(map[uint64]string) + inspectors := make(map[uint64]mcmssdk.Inspector) + for chainSel, updates := range cfg.UpdatesByChain { txOpts := e.Chains[chainSel].DeployerKey txOpts.Context = e.GetContext() @@ -1116,27 +1170,31 @@ func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSo if err != nil { return deployment.ChangesetOutput{}, err } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: offRamp.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[chainSel] = state.Chains[chainSel].Timelock.Address() - proposers[chainSel] = state.Chains[chainSel].ProposerMcm + + batchOperation, err := proposalutils.BatchOperationForChain(chainSel, offRamp.Address().Hex(), tx.Data(), + big.NewInt(0), string(OffRamp), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, err + } + batches = append(batches, batchOperation) + + timelocks[chainSel] = state.Chains[chainSel].Timelock.Address().Hex() + proposers[chainSel] = state.Chains[chainSel].ProposerMcm.Address().Hex() + inspectors[chainSel], err = proposalutils.McmsInspectorForChain(e, chainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get inspector for chain %d: %w", chainSel, err) + } } } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - p, err := proposalutils.BuildProposalFromBatches( + proposal, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), timelocks, proposers, + inspectors, batches, "Update offramp sources", cfg.MCMS.MinDelay, @@ -1144,9 +1202,8 @@ func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSo if err != nil { return deployment.ChangesetOutput{}, err } - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil + + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } type RouterUpdates struct { @@ -1237,9 +1294,12 @@ func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsC if err := cfg.Validate(e, state); err != nil { return deployment.ChangesetOutput{}, err } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + + batches := []mcmstypes.BatchOperation{} + timelocks := make(map[uint64]string) + proposers := make(map[uint64]string) + inspectors := make(map[uint64]mcmssdk.Inspector) + for chainSel, update := range cfg.UpdatesByChain { txOpts := e.Chains[chainSel].DeployerKey txOpts.Context = e.GetContext() @@ -1293,27 +1353,31 @@ func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsC if err != nil { return deployment.ChangesetOutput{}, err } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: routerC.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[chainSel] = state.Chains[chainSel].Timelock.Address() - proposers[chainSel] = state.Chains[chainSel].ProposerMcm + + batchOperation, err := proposalutils.BatchOperationForChain(chainSel, routerC.Address().Hex(), tx.Data(), + big.NewInt(0), string(Router), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, err + } + batches = append(batches, batchOperation) + + timelocks[chainSel] = state.Chains[chainSel].Timelock.Address().Hex() + proposers[chainSel] = state.Chains[chainSel].ProposerMcm.Address().Hex() + inspectors[chainSel], err = proposalutils.McmsInspectorForChain(e, chainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get inspector for chain %d: %w", chainSel, err) + } } } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - p, err := proposalutils.BuildProposalFromBatches( + proposal, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), timelocks, proposers, + inspectors, batches, "Update router offramps", cfg.MCMS.MinDelay, @@ -1321,9 +1385,8 @@ func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsC if err != nil { return deployment.ChangesetOutput{}, err } - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil + + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } type SetOCR3OffRampConfig struct { @@ -1406,9 +1469,12 @@ func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig) if err := cfg.Validate(e, state); err != nil { return deployment.ChangesetOutput{}, err } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + + batches := []mcmstypes.BatchOperation{} + timelocks := make(map[uint64]string) + proposers := make(map[uint64]string) + inspectors := make(map[uint64]mcmssdk.Inspector) + for _, remote := range cfg.RemoteChainSels { donID, err := internal.DonIDForChain( state.Chains[cfg.HomeChainSel].CapabilityRegistry, @@ -1444,26 +1510,31 @@ func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig) if err != nil { return deployment.ChangesetOutput{}, err } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(remote), - Batch: []mcms.Operation{ - { - To: offRamp.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[remote] = state.Chains[remote].Timelock.Address() - proposers[remote] = state.Chains[remote].ProposerMcm + + batchOperation, err := proposalutils.BatchOperationForChain(remote, offRamp.Address().Hex(), tx.Data(), + big.NewInt(0), string(OffRamp), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, err + } + batches = append(batches, batchOperation) + + timelocks[remote] = state.Chains[remote].Timelock.Address().Hex() + proposers[remote] = state.Chains[remote].ProposerMcm.Address().Hex() + inspectors[remote], err = proposalutils.McmsInspectorForChain(e, remote) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get inspector for chain %d: %w", remote, err) + } } } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - p, err := proposalutils.BuildProposalFromBatches( + + proposal, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), timelocks, proposers, + inspectors, batches, "Update OCR3 config", cfg.MCMS.MinDelay, @@ -1471,10 +1542,9 @@ func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig) if err != nil { return deployment.ChangesetOutput{}, err } + e.Logger.Info("Proposing OCR3 config update for", cfg.RemoteChainSels) - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } type UpdateDynamicConfigOffRampConfig struct { @@ -1532,9 +1602,12 @@ func UpdateDynamicConfigOffRampChangeset(e deployment.Environment, cfg UpdateDyn if err != nil { return deployment.ChangesetOutput{}, err } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) + + batches := []mcmstypes.BatchOperation{} + timelocks := make(map[uint64]string) + proposers := make(map[uint64]string) + inspectors := make(map[uint64]mcmssdk.Inspector) + for chainSel, params := range cfg.Updates { chain := e.Chains[chainSel] txOpts := e.Chains[chainSel].DeployerKey @@ -1557,38 +1630,41 @@ func UpdateDynamicConfigOffRampChangeset(e deployment.Environment, cfg UpdateDyn if err != nil { return deployment.ChangesetOutput{}, err } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: offRamp.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[chainSel] = state.Chains[chainSel].Timelock.Address() - proposers[chainSel] = state.Chains[chainSel].ProposerMcm + + batchOperation, err := proposalutils.BatchOperationForChain(chainSel, offRamp.Address().Hex(), tx.Data(), + big.NewInt(0), string(OffRamp), []string{}) + if err != nil { + return deployment.ChangesetOutput{}, err + } + batches = append(batches, batchOperation) + + timelocks[chainSel] = state.Chains[chainSel].Timelock.Address().Hex() + proposers[chainSel] = state.Chains[chainSel].ProposerMcm.Address().Hex() + inspectors[chainSel], err = proposalutils.McmsInspectorForChain(e, chainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to get inspector for chain %d: %w", chainSel, err) + } } } if cfg.MCMS == nil { return deployment.ChangesetOutput{}, nil } - p, err := proposalutils.BuildProposalFromBatches( + + proposal, err := proposalutils.BuildProposalFromBatchesV2( + e.GetContext(), timelocks, proposers, + inspectors, batches, "Update offramp dynamic config", cfg.MCMS.MinDelay, ) - if err != nil { return deployment.ChangesetOutput{}, err } + e.Logger.Infow("Proposing offramp dynamic config update", "config", cfg.Updates) - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil + return deployment.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } func isOCR3ConfigSetOnOffRamp( diff --git a/deployment/common/proposalutils/mcms_test_helpers.go b/deployment/common/proposalutils/mcms_test_helpers.go index c49dddcc301..0284c95bdf7 100644 --- a/deployment/common/proposalutils/mcms_test_helpers.go +++ b/deployment/common/proposalutils/mcms_test_helpers.go @@ -3,6 +3,7 @@ package proposalutils import ( "crypto/ecdsa" "math/big" + "slices" "testing" "time" @@ -267,7 +268,8 @@ func ExecuteMCMSTimelockProposalV2(t *testing.T, env deployment.Environment, tim // build a "chainSelector => executor" map executorsMap := map[mcmstypes.ChainSelector]mcmssdk.TimelockExecutor{} - for _, op := range timelockProposal.Operations { + callProxies := make([]string, len(timelockProposal.Operations)) + for i, op := range timelockProposal.Operations { family, err := chainsel.GetSelectorFamily(uint64(op.ChainSelector)) require.NoError(t, err) @@ -276,10 +278,13 @@ func ExecuteMCMSTimelockProposalV2(t *testing.T, env deployment.Environment, tim executorsMap[op.ChainSelector] = mcmsevmsdk.NewTimelockExecutor( env.Chains[uint64(op.ChainSelector)].Client, env.Chains[uint64(op.ChainSelector)].DeployerKey) + callProxies[i] = findCallProxyAddress(t, env, uint64(op.ChainSelector)) + case chainsel.FamilySolana: executorsMap[op.ChainSelector] = mcmssolanasdk.NewTimelockExecutor( env.SolChains[uint64(op.ChainSelector)].Client, *env.SolChains[uint64(op.ChainSelector)].DeployerKey) + default: require.FailNow(t, "unsupported chain family") } @@ -295,7 +300,12 @@ func ExecuteMCMSTimelockProposalV2(t *testing.T, env deployment.Environment, tim // execute each operation sequentially var tx = mcmstypes.TransactionResult{} for i, op := range timelockProposal.Operations { - tx, err = timelockExecutable.Execute(env.GetContext(), i, opts...) + opOpts := slices.Clone(opts) + if callProxies[i] != "" { + opOpts = append(opOpts, mcmslib.WithCallProxy(callProxies[i])) + } + + tx, err = timelockExecutable.Execute(env.GetContext(), i, opOpts...) require.NoError(t, err) family, err := chainsel.GetSelectorFamily(uint64(op.ChainSelector)) @@ -328,3 +338,17 @@ func SingleGroupTimelockConfigV2(t *testing.T) commontypes.MCMSWithTimelockConfi TimelockMinDelay: big.NewInt(0), } } + +func findCallProxyAddress(t *testing.T, env deployment.Environment, chainSelector uint64) string { + addressesForChain, err := env.ExistingAddresses.AddressesForChain(chainSelector) + require.NoError(t, err) + + for address, tvStr := range addressesForChain { + if tvStr.Type == commontypes.CallProxy && tvStr.Version == deployment.Version1_0_0 { + return address + } + } + + require.FailNow(t, "unable to find call proxy address") + return "" +}