Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 11 additions & 13 deletions chains/evm/deployment/fastcurse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import (
"github.com/smartcontractkit/chainlink-evm/pkg/utils"
mcms_types "github.com/smartcontractkit/mcms/types"

"github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_remote"

"github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_0_0/adapters"
rmnproxyops "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_0_0/operations/rmn_proxy"
adaptersv1_5_0 "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_0/adapters"
"github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_remote"
"github.com/smartcontractkit/chainlink-ccip/deployment/deploy"
"github.com/smartcontractkit/chainlink-ccip/deployment/fastcurse"
"github.com/smartcontractkit/chainlink-ccip/deployment/testhelpers"
Expand All @@ -28,6 +29,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/rmn_contract"

deploymentutils "github.com/smartcontractkit/chainlink-ccip/deployment/utils"

"github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/utils/operations/contract"
Expand Down Expand Up @@ -160,16 +162,14 @@ func TestFastCurse(t *testing.T) {
Bypasser: testhelpers.SingleGroupMCMS(),
Proposer: testhelpers.SingleGroupMCMS(),
TimelockMinDelay: big.NewInt(0),
Qualifier: ptr.String("test"),
TimelockAdmin: evmChain1.DeployerKey.From,
Qualifier: ptr.String(deploymentutils.CLLQualifier),
},
chain2: {
Canceller: testhelpers.SingleGroupMCMS(),
Bypasser: testhelpers.SingleGroupMCMS(),
Proposer: testhelpers.SingleGroupMCMS(),
TimelockMinDelay: big.NewInt(0),
Qualifier: ptr.String("test"),
TimelockAdmin: evmChain2.DeployerKey.From,
Qualifier: ptr.String(deploymentutils.CLLQualifier),
},
},
})
Expand Down Expand Up @@ -216,7 +216,7 @@ func TestFastCurse(t *testing.T) {
ValidUntil: 3759765795,
TimelockDelay: mcms_types.MustParseDuration("0s"),
TimelockAction: mcms_types.TimelockActionSchedule,
Qualifier: "test",
Qualifier: deploymentutils.CLLQualifier,
Description: "Transfer ownership to timelock for fast curse test",
},
}
Expand Down Expand Up @@ -251,7 +251,7 @@ func TestFastCurse(t *testing.T) {
ValidUntil: 3759765795,
TimelockDelay: mcms_types.MustParseDuration("0s"),
TimelockAction: mcms_types.TimelockActionSchedule,
Qualifier: "test",
Qualifier: deploymentutils.CLLQualifier,
Description: "Curse proposal for fast curse test",
},
}
Expand Down Expand Up @@ -440,14 +440,12 @@ func TestFastCurseGlobalCurseOnChain(t *testing.T) {
cs := deploy.DeployMCMS(dReg, nil)
mcmsChainInput := make(map[uint64]deploy.MCMSDeploymentConfigPerChain)
for _, sel := range []uint64{chain1, chain2, chain3} {
evmChain := env.BlockChains.EVMChains()[sel]
mcmsChainInput[sel] = deploy.MCMSDeploymentConfigPerChain{
Canceller: testhelpers.SingleGroupMCMS(),
Bypasser: testhelpers.SingleGroupMCMS(),
Proposer: testhelpers.SingleGroupMCMS(),
TimelockMinDelay: big.NewInt(0),
Qualifier: ptr.String("test"),
TimelockAdmin: evmChain.DeployerKey.From,
Qualifier: ptr.String(deploymentutils.CLLQualifier),
}
}
output, err := cs.Apply(*env, deploy.MCMSDeploymentConfig{
Expand Down Expand Up @@ -507,7 +505,7 @@ func TestFastCurseGlobalCurseOnChain(t *testing.T) {
ValidUntil: 3759765795,
TimelockDelay: mcms_types.MustParseDuration("0s"),
TimelockAction: mcms_types.TimelockActionSchedule,
Qualifier: "test",
Qualifier: deploymentutils.CLLQualifier,
Description: "Transfer ownership to timelock for fast curse test",
},
}
Expand Down Expand Up @@ -536,7 +534,7 @@ func TestFastCurseGlobalCurseOnChain(t *testing.T) {
ValidUntil: 3759765795,
TimelockDelay: mcms_types.MustParseDuration("0s"),
TimelockAction: mcms_types.TimelockActionSchedule,
Qualifier: "test",
Qualifier: deploymentutils.CLLQualifier,
Description: "Curse proposal for fast curse test",
},
}
Expand Down Expand Up @@ -652,7 +650,7 @@ func TestFastCurseGlobalCurseOnChain(t *testing.T) {
ValidUntil: 3759765795,
TimelockDelay: mcms_types.MustParseDuration("0s"),
TimelockAction: mcms_types.TimelockActionSchedule,
Qualifier: "test",
Qualifier: deploymentutils.CLLQualifier,
Description: "Curse proposal for fast curse test",
},
}
Expand Down
39 changes: 34 additions & 5 deletions chains/evm/deployment/v1_0_0/adapters/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ import (

cldf_chain "github.com/smartcontractkit/chainlink-deployments-framework/chain"
"github.com/smartcontractkit/chainlink-deployments-framework/chain/evm/operations/contract"
cldf_datastore "github.com/smartcontractkit/chainlink-deployments-framework/datastore"
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
cldf_ops "github.com/smartcontractkit/chainlink-deployments-framework/operations"

ccipapi "github.com/smartcontractkit/chainlink-ccip/deployment/deploy"
"github.com/smartcontractkit/chainlink-ccip/deployment/utils"
datastore_utils "github.com/smartcontractkit/chainlink-ccip/deployment/utils/datastore"
sequtil "github.com/smartcontractkit/chainlink-ccip/deployment/utils/sequences"

evm_datastore_utils "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/utils/datastore"
ops "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_0_0/operations"
seq "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_0_0/sequences"
)
Expand Down Expand Up @@ -150,6 +153,7 @@ func (d *EVMDeployer) DeployMCMS() *cldf_ops.Sequence[ccipapi.MCMSDeploymentConf
}
output.Addresses = append(output.Addresses, report.Output.Addresses...)
cancellerAddr := report.Output.Addresses[0]

// deploy timelock — always use the deployer key as the initial admin
// so we can manage roles immediately after deployment
timelockAddr, err := contract.MaybeDeployContract(b, ops.OpDeployTimelock, evmChain, contract.DeployInput[ops.OpDeployTimelockInput]{
Expand Down Expand Up @@ -200,11 +204,36 @@ func (d *EVMDeployer) DeployMCMS() *cldf_ops.Sequence[ccipapi.MCMSDeploymentConf
b.Logger.Infof("Granted Executor role on Timelock %s to Call Proxy %s on chain %s", timelockAddr, callProxyAddr, evmChain.Name)

// Determine the final ADMIN_ROLE holder for the timelock.
// If in.TimelockAdmin is zero, the timelock becomes its own admin.
// Otherwise, hand admin to the specified address.
finalAdmin := common.HexToAddress(timelockAddr.Address)
if in.TimelockAdmin != (common.Address{}) {
finalAdmin = in.TimelockAdmin
// CLLCCIP is always self-governed (its timelock is its own admin).
// Every other MCMS instance MUST use the existing CLLCCIP RBACTimelock as its
// admin — if CLLCCIP has not been deployed yet, fail fast.
isCLLCCIP := in.Qualifier != nil && *in.Qualifier == utils.CLLQualifier
finalAdmin := common.HexToAddress(timelockAddr.Address) // default: self-governed (CLLCCIP case)
if !isCLLCCIP {
existingDS := cldf_datastore.NewMemoryDataStore()
for _, ref := range in.ExistingAddresses {
_ = existingDS.Addresses().Add(ref)
}
cllTimelockAddr, lookupErr := datastore_utils.FindAndFormatRef(
existingDS.Seal(),
cldf_datastore.AddressRef{
Type: cldf_datastore.ContractType(utils.RBACTimelock),
Qualifier: utils.CLLQualifier,
},
in.ChainSelector,
evm_datastore_utils.ToEVMAddress,
)
if lookupErr != nil || cllTimelockAddr == (common.Address{}) {
qualifier := ""
if in.Qualifier != nil {
qualifier = *in.Qualifier
}
return sequtil.OnChainOutput{}, fmt.Errorf(
"cannot deploy MCMS with qualifier %q on chain %d: CLLCCIP RBACTimelock must be deployed first (it will be set as admin)",
qualifier, in.ChainSelector,
)
}
finalAdmin = cllTimelockAddr
}

// If finalAdmin differs from the deployer key we need to transfer the ADMIN_ROLE.
Expand Down
Loading
Loading