diff --git a/deployment/common/changeset/internal/evm/mcms.go b/deployment/common/changeset/internal/evm/mcms.go index 8346f0d0e75..a310706ea6f 100644 --- a/deployment/common/changeset/internal/evm/mcms.go +++ b/deployment/common/changeset/internal/evm/mcms.go @@ -13,6 +13,16 @@ import ( "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" ) +// DeployMCMSOption is a function that modifies a TypeAndVersion before or after deployment. +type DeployMCMSOption func(*deployment.TypeAndVersion) + +// WithLabel is a functional option that sets a label on the TypeAndVersion. +func WithLabel(label string) DeployMCMSOption { + return func(tv *deployment.TypeAndVersion) { + tv.AddLabel(label) + } +} + // MCMSWithTimelockEVMDeploy holds a bundle of MCMS contract deploys. type MCMSWithTimelockEVMDeploy struct { Canceller *deployment.ContractDeploy[*bindings.ManyChainMultiSig] @@ -28,6 +38,7 @@ func deployMCMSWithConfigEVM( chain deployment.Chain, ab deployment.AddressBook, mcmConfig mcmsTypes.Config, + options ...DeployMCMSOption, ) (*deployment.ContractDeploy[*bindings.ManyChainMultiSig], error) { groupQuorums, groupParents, signerAddresses, signerGroups, err := evmMcms.ExtractSetConfigInputs(&mcmConfig) if err != nil { @@ -40,8 +51,14 @@ func deployMCMSWithConfigEVM( chain.DeployerKey, chain.Client, ) + + tv := deployment.NewTypeAndVersion(contractType, deployment.Version1_0_0) + for _, option := range options { + option(&tv) + } + return deployment.ContractDeploy[*bindings.ManyChainMultiSig]{ - Address: mcmAddr, Contract: mcm, Tx: tx, Tv: deployment.NewTypeAndVersion(contractType, deployment.Version1_0_0), Err: err2, + Address: mcmAddr, Contract: mcm, Tx: tx, Tv: tv, Err: err2, } }) if err != nil { @@ -74,15 +91,20 @@ func DeployMCMSWithTimelockContractsEVM( ab deployment.AddressBook, config commontypes.MCMSWithTimelockConfigV2, ) (*MCMSWithTimelockEVMDeploy, error) { - bypasser, err := deployMCMSWithConfigEVM(commontypes.BypasserManyChainMultisig, lggr, chain, ab, config.Bypasser) + opts := []DeployMCMSOption{} + if config.Label != nil { + opts = append(opts, WithLabel(*config.Label)) + } + + bypasser, err := deployMCMSWithConfigEVM(commontypes.BypasserManyChainMultisig, lggr, chain, ab, config.Bypasser, opts...) if err != nil { return nil, err } - canceller, err := deployMCMSWithConfigEVM(commontypes.CancellerManyChainMultisig, lggr, chain, ab, config.Canceller) + canceller, err := deployMCMSWithConfigEVM(commontypes.CancellerManyChainMultisig, lggr, chain, ab, config.Canceller, opts...) if err != nil { return nil, err } - proposer, err := deployMCMSWithConfigEVM(commontypes.ProposerManyChainMultisig, lggr, chain, ab, config.Proposer) + proposer, err := deployMCMSWithConfigEVM(commontypes.ProposerManyChainMultisig, lggr, chain, ab, config.Proposer, opts...) if err != nil { return nil, err } @@ -104,8 +126,14 @@ func DeployMCMSWithTimelockContractsEVM( []common.Address{canceller.Address, proposer.Address, bypasser.Address}, // cancellers []common.Address{bypasser.Address}, // bypassers ) + + tv := deployment.NewTypeAndVersion(commontypes.RBACTimelock, deployment.Version1_0_0) + if config.Label != nil { + tv.AddLabel(*config.Label) + } + return deployment.ContractDeploy[*bindings.RBACTimelock]{ - Address: timelock, Contract: cc, Tx: tx2, Tv: deployment.NewTypeAndVersion(commontypes.RBACTimelock, deployment.Version1_0_0), Err: err2, + Address: timelock, Contract: cc, Tx: tx2, Tv: tv, Err: err2, } }) if err != nil { @@ -120,8 +148,14 @@ func DeployMCMSWithTimelockContractsEVM( chain.Client, timelock.Address, ) + + tv := deployment.NewTypeAndVersion(commontypes.CallProxy, deployment.Version1_0_0) + if config.Label != nil { + tv.AddLabel(*config.Label) + } + return deployment.ContractDeploy[*bindings.CallProxy]{ - Address: callProxy, Contract: cc, Tx: tx2, Tv: deployment.NewTypeAndVersion(commontypes.CallProxy, deployment.Version1_0_0), Err: err2, + Address: callProxy, Contract: cc, Tx: tx2, Tv: tv, Err: err2, } }) if err != nil { diff --git a/deployment/common/changeset/internal/evm/mcms_test.go b/deployment/common/changeset/internal/evm/mcms_test.go new file mode 100644 index 00000000000..7d7ef8e2b47 --- /dev/null +++ b/deployment/common/changeset/internal/evm/mcms_test.go @@ -0,0 +1,73 @@ +package mcmsnew_test + +import ( + "encoding/json" + "testing" + + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestDeployMCMSWithConfig(t *testing.T) { + lggr := logger.TestLogger(t) + + chains, _ := memory.NewMemoryChainsWithChainIDs(t, []uint64{ + chainsel.TEST_90000001.EvmChainID, + }, 1) + ab := deployment.NewMemoryAddressBook() + + // 1) Test WITHOUT a label + mcmNoLabel, err := internal.DeployMCMSWithConfig( + types.ProposerManyChainMultisig, + lggr, + chains[chainsel.TEST_90000001.Selector], + ab, + proposalutils.SingleGroupMCMS(t), + ) + require.NoError(t, err) + require.Empty(t, mcmNoLabel.Tv.Labels, "expected no label to be set") + + // 2) Test WITH a label + label := "SA" + mcmWithLabel, err := internal.DeployMCMSWithConfig( + types.ProposerManyChainMultisig, + lggr, + chains[chainsel.TEST_90000001.Selector], + ab, + proposalutils.SingleGroupMCMS(t), + internal.WithLabel(label), + ) + require.NoError(t, err) + require.NotNil(t, mcmWithLabel.Tv.Labels, "expected labels to be set") + require.Contains(t, mcmWithLabel.Tv.Labels, label, "label mismatch") +} + +func TestDeployMCMSWithTimelockContracts(t *testing.T) { + lggr := logger.TestLogger(t) + chains, _ := memory.NewMemoryChainsWithChainIDs(t, []uint64{ + chainsel.TEST_90000001.EvmChainID, + }, 1) + ab := deployment.NewMemoryAddressBook() + _, err := internal.DeployMCMSWithTimelockContracts(lggr, + chains[chainsel.TEST_90000001.Selector], + ab, proposalutils.SingleGroupTimelockConfig(t)) + require.NoError(t, err) + addresses, err := ab.AddressesForChain(chainsel.TEST_90000001.Selector) + require.NoError(t, err) + require.Len(t, addresses, 5) + mcmsState, err := state.MaybeLoadMCMSWithTimelockChainState(chains[chainsel.TEST_90000001.Selector], addresses) + require.NoError(t, err) + v, err := mcmsState.GenerateMCMSWithTimelockView() + require.NoError(t, err) + b, err := json.MarshalIndent(v, "", " ") + require.NoError(t, err) + t.Log(string(b)) +} diff --git a/deployment/common/types/types.go b/deployment/common/types/types.go index 5d8386ee674..c82559276e7 100644 --- a/deployment/common/types/types.go +++ b/deployment/common/types/types.go @@ -65,6 +65,7 @@ type MCMSWithTimelockConfigV2 struct { Bypasser mcmstypes.Config Proposer mcmstypes.Config TimelockMinDelay *big.Int + Label *string } type OCRParameters struct {