@@ -11,20 +11,28 @@ import (
1111 "github.com/smartcontractkit/chainlink-deployments-framework/datastore"
1212 "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
1313 "github.com/smartcontractkit/chainlink-evm/pkg/utils"
14+ mcms_types "github.com/smartcontractkit/mcms/types"
1415
1516 "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_0_0/adapters"
17+ adaptersv1_5_0 "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_0/adapters"
18+ "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_remote"
1619 "github.com/smartcontractkit/chainlink-ccip/deployment/deploy"
20+ "github.com/smartcontractkit/chainlink-ccip/deployment/fastcurse"
1721 "github.com/smartcontractkit/chainlink-ccip/deployment/testhelpers"
22+ "github.com/smartcontractkit/chainlink-ccip/deployment/utils/changesets"
23+ "github.com/smartcontractkit/chainlink-ccip/deployment/utils/mcms"
1824
1925 "github.com/smartcontractkit/chainlink-deployments-framework/engine/test/environment"
2026 cldf_ops "github.com/smartcontractkit/chainlink-deployments-framework/operations"
2127 "github.com/stretchr/testify/require"
2228
2329 "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/rmn_contract"
30+ deploymentutils "github.com/smartcontractkit/chainlink-ccip/deployment/utils"
2431
2532 "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/utils/operations/contract"
2633 routerops1_2 "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_2_0/operations/router"
2734 rmnops1_5 "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_0/operations/rmn"
35+ adaptersv1_6_0 "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_6_0/adapters"
2836 rmnremoteops1_6 "github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_6_0/operations/rmn_remote"
2937)
3038
@@ -36,6 +44,7 @@ func TestFastCurse(t *testing.T) {
3644 )
3745 require .NoError (t , err )
3846 bundle := env .OperationsBundle
47+ var rmnAddress , rmnRemoteAddress common.Address
3948 // deploy RMN 1.5 on chain1 and RMN 1.6 on chain2, set up routers, etc.
4049 chain := env .BlockChains .EVMChains ()[chain1 ]
4150 deployRMNOp , err := cldf_ops .ExecuteOperation (bundle , rmnops1_5 .Deploy , chain , contract.DeployInput [rmnops1_5.ConstructorArgs ]{
@@ -65,6 +74,7 @@ func TestFastCurse(t *testing.T) {
6574 ChainSelector : chain1 ,
6675 Address : deployRMNOp .Output .Address ,
6776 }))
77+ rmnAddress = common .HexToAddress (deployRMNOp .Output .Address )
6878 // deploy RMNRemote 1.6 on chain2
6979 chain = env .BlockChains .EVMChains ()[chain2 ]
7080 deployRMNRemoteOp , err := cldf_ops .ExecuteOperation (bundle , rmnremoteops1_6 .Deploy , chain , contract.DeployInput [rmnremoteops1_6.ConstructorArgs ]{
@@ -82,6 +92,7 @@ func TestFastCurse(t *testing.T) {
8292 ChainSelector : chain2 ,
8393 Address : deployRMNRemoteOp .Output .Address ,
8494 }))
95+ rmnRemoteAddress = common .HexToAddress (deployRMNRemoteOp .Output .Address )
8596 // deploy router in both chains
8697 for _ , sel := range []uint64 {chain1 , chain2 } {
8798 evmChain := env .BlockChains .EVMChains ()[sel ]
@@ -168,9 +179,165 @@ func TestFastCurse(t *testing.T) {
168179 // store addresses in ds
169180 allAddrRefs , err := output .DataStore .Addresses ().Fetch ()
170181 require .NoError (t , err )
182+ timelockAddrs := make (map [uint64 ]string )
171183 for _ , addrRef := range allAddrRefs {
172184 require .NoError (t , ds .Addresses ().Add (addrRef ))
185+ if addrRef .Type == datastore .ContractType (deploymentutils .RBACTimelock ) {
186+ timelockAddrs [addrRef .ChainSelector ] = addrRef .Address
187+ }
173188 }
174-
189+ // update env datastore
175190 env .DataStore = ds .Seal ()
191+ // transfer ownership of RMN and RMNRemote to respective MCMS
192+ transferOwnershipInput := deploy.TransferOwnershipInput {
193+ ChainInputs : []deploy.TransferOwnershipPerChainInput {
194+ {
195+ ChainSelector : chain1 ,
196+ ContractRef : []datastore.AddressRef {
197+ {
198+ Type : datastore .ContractType (rmnops1_5 .ContractType ),
199+ Version : semver .MustParse ("1.5.0" ),
200+ },
201+ },
202+ ProposedOwner : timelockAddrs [chain1 ],
203+ },
204+ {
205+ ChainSelector : chain2 ,
206+ ContractRef : []datastore.AddressRef {
207+ {
208+ Type : datastore .ContractType (rmnremoteops1_6 .ContractType ),
209+ Version : semver .MustParse ("1.6.0" ),
210+ },
211+ },
212+ ProposedOwner : timelockAddrs [chain2 ],
213+ },
214+ },
215+ AdapterVersion : semver .MustParse ("1.0.0" ),
216+ MCMS : mcms.Input {
217+ OverridePreviousRoot : false ,
218+ ValidUntil : 3759765795 ,
219+ TimelockDelay : mcms_types .MustParseDuration ("0s" ),
220+ TimelockAction : mcms_types .TimelockActionSchedule ,
221+ MCMSAddressRef : datastore.AddressRef {
222+ Type : datastore .ContractType (deploymentutils .ProposerManyChainMultisig ),
223+ Qualifier : "test" ,
224+ Version : semver .MustParse ("1.0.0" ),
225+ },
226+ TimelockAddressRef : datastore.AddressRef {
227+ Type : datastore .ContractType (deploymentutils .RBACTimelock ),
228+ Qualifier : "test" ,
229+ Version : semver .MustParse ("1.0.0" ),
230+ },
231+ Description : "Transfer ownership to timelock for fast curse test" ,
232+ },
233+ }
234+
235+ // register chain adapter
236+ cr := deploy .GetTransferOwnershipRegistry ()
237+ evmAdapter := & adapters.EVMTransferOwnershipAdapter {}
238+ cr .RegisterAdapter (chainsel .FamilyEVM , transferOwnershipInput .AdapterVersion , evmAdapter )
239+ mcmsRegistry := changesets .NewMCMSReaderRegistry ()
240+ evmMCMSReader := & adapters.EVMMCMSReader {}
241+ mcmsRegistry .RegisterMCMSReader (chainsel .FamilyEVM , evmMCMSReader )
242+ transferOwnershipChangeset := deploy .TransferOwnershipChangeset (cr , mcmsRegistry )
243+ output , err = transferOwnershipChangeset .Apply (* env , transferOwnershipInput )
244+ require .NoError (t , err )
245+ require .Greater (t , len (output .Reports ), 0 )
246+ require .Equal (t , 1 , len (output .MCMSTimelockProposals ))
247+ testhelpers .ProcessTimelockProposals (t , * env , output .MCMSTimelockProposals , false )
248+ t .Logf ("Transferred ownership of RMN and RMNRemote to respective MCMS" )
249+ // now generate a curse proposal
250+ curseCfg := fastcurse.RMNCurseConfig {
251+ CurseActions : []fastcurse.CurseActionInput {
252+ {
253+ IsGlobalCurse : false ,
254+ ChainSelector : chain1 ,
255+ SubjectChainSelector : chain2 ,
256+ Version : semver .MustParse ("1.5.0" ),
257+ },
258+ {
259+ IsGlobalCurse : false ,
260+ ChainSelector : chain2 ,
261+ SubjectChainSelector : chain1 ,
262+ Version : semver .MustParse ("1.6.0" ),
263+ },
264+ },
265+ Force : false ,
266+ MCMS : mcms.Input {
267+ OverridePreviousRoot : false ,
268+ ValidUntil : 3759765795 ,
269+ TimelockDelay : mcms_types .MustParseDuration ("0s" ),
270+ TimelockAction : mcms_types .TimelockActionSchedule ,
271+ MCMSAddressRef : datastore.AddressRef {
272+ Type : datastore .ContractType (deploymentutils .ProposerManyChainMultisig ),
273+ Qualifier : "test" ,
274+ Version : semver .MustParse ("1.0.0" ),
275+ },
276+ TimelockAddressRef : datastore.AddressRef {
277+ Type : datastore .ContractType (deploymentutils .RBACTimelock ),
278+ Qualifier : "test" ,
279+ Version : semver .MustParse ("1.0.0" ),
280+ },
281+ Description : "Curse proposal for fast curse test" ,
282+ },
283+ }
284+ curseReg := fastcurse .GetCurseRegistry ()
285+ adv1_6_0 := adaptersv1_6_0 .NewCurseAdapter ()
286+ adv1_5_0 := adaptersv1_5_0 .NewCurseAdapter ()
287+ crInput1_6_0 := fastcurse.CurseRegistryInput {
288+ CursingFamily : chainsel .FamilyEVM ,
289+ CursingVersion : semver .MustParse ("1.6.0" ),
290+ SubjectFamily : chainsel .FamilyEVM ,
291+ CurseAdapter : adaptersv1_6_0 .NewCurseAdapter (),
292+ CurseSubjectAdapter : adaptersv1_6_0 .NewCurseAdapter (),
293+ }
294+ crInput1_5_0 := fastcurse.CurseRegistryInput {
295+ CursingFamily : chainsel .FamilyEVM ,
296+ CursingVersion : semver .MustParse ("1.5.0" ),
297+ SubjectFamily : chainsel .FamilyEVM ,
298+ CurseAdapter : adaptersv1_5_0 .NewCurseAdapter (),
299+ CurseSubjectAdapter : adaptersv1_5_0 .NewCurseAdapter (),
300+ }
301+ curseReg .RegisterNewCurse (crInput1_6_0 )
302+ curseReg .RegisterNewCurse (crInput1_5_0 )
303+ curseChangeset := fastcurse .CurseChangeset (curseReg , mcmsRegistry )
304+ output , err = curseChangeset .Apply (* env , curseCfg )
305+ require .NoError (t , err )
306+ require .Greater (t , len (output .Reports ), 0 )
307+ require .Equal (t , 1 , len (output .MCMSTimelockProposals ))
308+ testhelpers .ProcessTimelockProposals (t , * env , output .MCMSTimelockProposals , false )
309+
310+ // check that the subjects were actually cursed
311+ rmnC , err := rmn_contract .NewRMNContract (rmnAddress , evmChain1 .Client )
312+ require .NoError (t , err )
313+ isCursed , err := rmnC .IsCursed (nil , adv1_5_0 .SelectorToSubject (chain2 ))
314+ require .NoError (t , err )
315+ require .True (t , isCursed , "subject on chain2 should be cursed on rmn in chain1" )
316+
317+ rmnRemoteC , err := rmn_remote .NewRMNRemote (rmnRemoteAddress , evmChain2 .Client )
318+ require .NoError (t , err )
319+ isCursed , err = rmnRemoteC .IsCursed (nil , adv1_6_0 .SelectorToSubject (chain1 ))
320+ require .NoError (t , err )
321+ require .True (t , isCursed , "subject on chain1 should be cursed on rmnremote in chain2" )
322+ t .Logf ("Subjects successfully cursed %x on chain1 %d and %x on chain2 %d" , adv1_5_0 .SelectorToSubject (chain2 ), chain1 , adv1_6_0 .SelectorToSubject (chain1 ), chain2 )
323+
324+ // Now uncurse the subjects
325+ // reset the operation bundle to clear any cached values
326+ env .OperationsBundle = cldf_ops .NewBundle (env .GetContext , env .Logger , cldf_ops .NewMemoryReporter ())
327+ uncurseChangeset := fastcurse .UncurseChangeset (curseReg , mcmsRegistry )
328+ output , err = uncurseChangeset .Apply (* env , curseCfg )
329+ require .NoError (t , err )
330+ require .Greater (t , len (output .Reports ), 0 )
331+ require .Equal (t , 1 , len (output .MCMSTimelockProposals ))
332+ testhelpers .ProcessTimelockProposals (t , * env , output .MCMSTimelockProposals , false )
333+
334+ // check that the subjects were actually uncursed
335+ isCursed , err = rmnC .IsCursed (nil , adv1_5_0 .SelectorToSubject (chain2 ))
336+ require .NoError (t , err )
337+ require .False (t , isCursed , "subject on chain2 should be uncursed on rmn in chain1" )
338+
339+ isCursed , err = rmnRemoteC .IsCursed (nil , adv1_6_0 .SelectorToSubject (chain1 ))
340+ require .NoError (t , err )
341+ require .False (t , isCursed , "subject on chain1 should be uncursed on rmnremote in chain2" )
342+ t .Logf ("Subjects successfully uncursed %x on chain1 %d and %x on chain2 %d" , adv1_5_0 .SelectorToSubject (chain2 ), chain1 , adv1_6_0 .SelectorToSubject (chain1 ), chain2 )
176343}
0 commit comments