Skip to content

chore: port mcms helpers from chainlink/deployment#923

Open
ecPablo wants to merge 4 commits intomainfrom
ecpablo/port-mcms-helpers-core
Open

chore: port mcms helpers from chainlink/deployment#923
ecPablo wants to merge 4 commits intomainfrom
ecpablo/port-mcms-helpers-core

Conversation

@ecPablo
Copy link
Copy Markdown
Contributor

@ecPablo ecPablo commented Apr 10, 2026

We are porting the code in https://github.com/smartcontractkit/chainlink/blob/develop/deployment/common/proposalutils/mcms_helpers.go to CLDF in order to remove deps on core repo for some downstream consumers. The functions were splitted in separate files to keep them under semantically meaningful names. Also added unit tests and fixed some obvious issues pointed out by copilot, but in general keeping the logic as close as possible to what we have in core today.

  1. McmsInspectorForChain in core repo -> moved to experimental/proposalutils/inspectors.go in CLDF.
  2. BatchOperationForChain and TransactionForChain moved to experimental/proposalutils/operations.goin CLDF
  3. test_helpers.go and types.go are moved as is from core repo to CLDF

Followup PRs in core will attempt to replace usages with these. So we can delete the mcms_helpers.go from core

AI Summary

This pull request ports the proposalutils helpers from the chainlink/deployment repository into the chainlink-deployments-framework, making them part of the framework and improving proposal creation, inspection, and testing across multiple blockchain environments. The main changes include adding utility functions for proposal operations, inspectors, and test helpers, as well as defining relevant types and constants for MCMS (Many Chain Multisig) and timelock configurations.

New proposal utilities and helpers:

  • Added experimental/proposalutils/inspectors.go providing functions to build MCMS inspectors for different chains, supporting optional timelock actions and mass inspector creation.
  • Added experimental/proposalutils/operations.go with helpers to create transactions and batch operations for different chain families (EVM, Solana), abstracting over chain-specific details.

Testing support:

  • Added experimental/proposalutils/test_helpers.go containing test helpers for signing and executing MCMS proposals and timelock proposals, as well as generating single-group configs and finding call proxy addresses for tests.

Types and constants:

  • Added experimental/proposalutils/types.go defining types and constants for MCMS roles, contract types, and configuration structures (including gas boost config), supporting both legacy and new MCMS config formats.

Changelog:

  • Updated the changeset to document the addition of proposalutils helpers to the framework.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 10, 2026

🦋 Changeset detected

Latest commit: 7485acd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
chainlink-deployments-framework Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

This comment was marked as resolved.

This comment was marked as resolved.

This comment was marked as low quality.

@ecPablo ecPablo force-pushed the ecpablo/port-mcms-helpers-core branch from 1302167 to 4dc6446 Compare April 10, 2026 20:17
@cl-sonarqube-production
Copy link
Copy Markdown

@ecPablo ecPablo marked this pull request as ready for review April 13, 2026 14:19
@ecPablo ecPablo requested a review from a team as a code owner April 13, 2026 14:19
Copilot AI review requested due to automatic review settings April 13, 2026 14:19
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +154 to +158
family, err := chainsel.GetSelectorFamily(uint64(chainSelector))
if err != nil {
return fmt.Errorf("[ExecuteMCMSProposalV2] failed to get chain family for selector %d: %w", chainSelector, err)
}

Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ExecuteMCMSProposalV2 determines the chain family but only confirms transactions for EVM and Aptos; all other families (e.g., TON, TRON, Sui) will silently skip confirmation, which can leave tests in an incorrect state (transactions unconfirmed) while still returning nil. Consider switching on family with an explicit default error, or routing confirmation through a shared helper similar to engine/test/internal/mcmsutils/executor.go:360-392 so each supported family is handled intentionally (including NOOP where appropriate, e.g., Solana).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comments raises a good point: should we apply these improvements now or keep the code as close as possible to what we have in core to separate the migrations steps (i.e., move to CLDF then refactor).

Comment on lines +192 to +196
family, err := chainsel.GetSelectorFamily(uint64(op.ChainSelector))
if err != nil {
return fmt.Errorf("[ExecuteMCMSProposalV2] failed to get chain family for selector %d: %w", op.ChainSelector, err)
}

Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as the SetRoot loop: after computing family, the code only has confirmation branches for EVM and Aptos. For any other chain family present in the proposal, the operation tx will not be confirmed and the helper may still report success. Add an explicit default branch (or shared confirmation helper) so non-(EVM/Aptos/Solana) families don’t get silently skipped.

Copilot uses AI. Check for mistakes.
ajaskolski
ajaskolski previously approved these changes Apr 13, 2026
Copy link
Copy Markdown
Contributor

@gustavogama-cll gustavogama-cll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we're moving to a different repository, should we drop the "v2" suffixes? They're kind of useless by now (though it might make the migration of client code harder...)

cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
)

type MCMSRole string
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we should probably separate the MCMSRole type functions and constants from the rest

type MCMSRole string

const (
BypasserManyChainMultisig cldf.ContractType = "BypasserManyChainMultiSig"
Copy link
Copy Markdown
Contributor

@gustavogama-cll gustavogama-cll Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit/noaction: we need a better place for these mcms contract types

// LinkToken is the burn/mint link token. It should be used everywhere for
// new deployments. Corresponds to
// https://github.com/smartcontractkit/chainlink/blob/develop/core/gethwrappers/shared/generated/link_token/link_token.go#L34
LinkToken cldf.ContractType = "LinkToken"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit/noaction: and this one

@ecPablo ecPablo dismissed stale reviews from ajaskolski and DimitriosNaikopoulos via d36a3a3 April 13, 2026 17:12
Copilot AI review requested due to automatic review settings April 13, 2026 19:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +308 to +316
func SingleGroupTimelockConfig(t *testing.T) proposalutils.MCMSWithTimelockConfig {
t.Helper()

return proposalutils.MCMSWithTimelockConfig{
Canceller: SingleGroupMCMS(t),
Bypasser: SingleGroupMCMS(t),
Proposer: SingleGroupMCMS(t),
TimelockMinDelay: big.NewInt(0),
}
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SingleGroupTimelockConfig returns proposalutils.MCMSWithTimelockConfig, but that type’s Canceller/Bypasser/Proposer fields are mcmstypes.Config while SingleGroupMCMS returns config.Config. This won’t compile (type mismatch). Consider returning MCMSWithTimelockConfigLegacy here, or switching to SingleGroupMCMSV2 and the non-legacy config type consistently.

Copilot uses AI. Check for mistakes.
Comment on lines +319 to +327
func SingleGroupTimelockConfigV2(t *testing.T) proposalutils.MCMSWithTimelockConfigV2 {
t.Helper()

return proposalutils.MCMSWithTimelockConfigV2{
Canceller: SingleGroupMCMSV2(t),
Bypasser: SingleGroupMCMSV2(t),
Proposer: SingleGroupMCMSV2(t),
TimelockMinDelay: big.NewInt(0),
}
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SingleGroupTimelockConfigV2 references proposalutils.MCMSWithTimelockConfigV2, but there is no such type in experimental/proposalutils/types.go (only MCMSWithTimelockConfigLegacy and MCMSWithTimelockConfig). This will not compile; either add/rename the type to MCMSWithTimelockConfigV2 or update this helper to return the existing MCMSWithTimelockConfig.

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +55
// MCMSWithTimelockConfigV2 holds the configuration for an MCMS with timelock.
// Unlike the legacy MCMSWithTimelockConfig type above, this variant uses the
// newer mcmstypes.Config definitions.
type MCMSWithTimelockConfig struct {
Canceller mcmstypes.Config `json:"canceller"`
Bypasser mcmstypes.Config `json:"bypasser"`
Proposer mcmstypes.Config `json:"proposer"`
TimelockMinDelay *big.Int `json:"timelockMinDelay"`
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says MCMSWithTimelockConfigV2, but the type declared is MCMSWithTimelockConfig and the “legacy … type above” is actually named MCMSWithTimelockConfigLegacy. Please align the comment/type names (and any callers) to avoid confusion and mismatched expectations about which config struct to use.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants