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
35 changes: 29 additions & 6 deletions deployment/ops/ccip_router/op_deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,18 +177,40 @@ var setOnRampsHandler = func(b cld_ops.Bundle, deps sui_ops.OpTxDeps, input SetO
return sui_ops.OpTxResult[SetOnRampsObjects]{}, err
}

opts := deps.GetCallOpts()
opts.Signer = deps.Signer
tx, err := routerPackage.SetOnRamps(
b.GetContext(),
opts,
encodedCall, err := routerPackage.Encoder().SetOnRamps(
bind.Object{Id: input.OwnerCapObjectId},
bind.Object{Id: input.RouterStateObjectId},
input.DestChainSelectors,
input.OnRampAddresses,
)
if err != nil {
return sui_ops.OpTxResult[SetOnRampsObjects]{}, fmt.Errorf("failed to execute set_on_ramps: %w", err)
return sui_ops.OpTxResult[SetOnRampsObjects]{}, fmt.Errorf("failed to encode SetOnRamps call: %w", err)
}
call, err := sui_ops.ToTransactionCall(encodedCall, input.RouterStateObjectId)
if err != nil {
return sui_ops.OpTxResult[SetOnRampsObjects]{}, fmt.Errorf("failed to convert encoded call to TransactionCall: %w", err)
}
if deps.Signer == nil {
b.Logger.Infow("Skipping execution of SetOnRamps on Router as per no Signer provided",
"destChainSelectors", input.DestChainSelectors,
"onRampAddresses", input.OnRampAddresses)
return sui_ops.OpTxResult[SetOnRampsObjects]{
Digest: "",
PackageId: input.RouterPackageId,
Objects: SetOnRampsObjects{},
Call: call,
}, nil
}

opts := deps.GetCallOpts()
opts.Signer = deps.Signer
tx, err := routerPackage.Bound().ExecuteTransaction(
b.GetContext(),
opts,
encodedCall,
)
if err != nil {
return sui_ops.OpTxResult[SetOnRampsObjects]{}, fmt.Errorf("failed to execute SetOnRamps on Router: %w", err)
}

b.Logger.Infow("On-ramps set successfully",
Expand All @@ -199,6 +221,7 @@ var setOnRampsHandler = func(b cld_ops.Bundle, deps sui_ops.OpTxDeps, input SetO
Digest: tx.Digest,
PackageId: input.RouterPackageId,
Objects: SetOnRampsObjects{},
Call: call,
}, nil
}

Expand Down
1 change: 1 addition & 0 deletions deployment/ops/ccip_router/op_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ var AllOperationsRouter = []cld_ops.Operation[any, any, any]{
*TransferOwnershipOp.AsUntyped(),
*AcceptOwnershipOp.AsUntyped(),
*ExecuteOwnershipTransferOp.AsUntyped(),
*SetOnRampsOp.AsUntyped(),
}
76 changes: 76 additions & 0 deletions integration-tests/mcms/mcms_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
ccipops "github.com/smartcontractkit/chainlink-sui/deployment/ops/ccip"
offrampops "github.com/smartcontractkit/chainlink-sui/deployment/ops/ccip_offramp"
onrampops "github.com/smartcontractkit/chainlink-sui/deployment/ops/ccip_onramp"
routerops "github.com/smartcontractkit/chainlink-sui/deployment/ops/ccip_router"
mcmsops "github.com/smartcontractkit/chainlink-sui/deployment/ops/mcms"
ownershipops "github.com/smartcontractkit/chainlink-sui/deployment/ops/ownership"
)
Expand All @@ -39,6 +40,7 @@ func (s *CCIPMCMSTestSuite) Test_CCIP_MCMS() {
s.T().Run("Execute config proposal against CCIP from MCMS", func(t *testing.T) {
RunTestCCIPFeeQuoterProposal(s)
RunCCIPRampsProposal(s)
RunTestRouterProposal(s)
})
}

Expand Down Expand Up @@ -120,6 +122,8 @@ func RunTestCCIPOwnershipTransfer(s *CCIPMCMSTestSuite) {
require.NoError(s.T(), err, "transferring ownership of CCIP OffRamp to MCMS")
require.NotEmpty(s.T(), tx, "Transaction should not be empty")

s.T().Logf("✅ Transferred ownership of CCIP OffRamp to MCMS in tx: %s", tx.Digest)

// 2. Proposal execution with acceptance from MCMS (through bypasser)
input := ownershipops.AcceptCCIPOwnershipInput{
// MCMS related
Expand Down Expand Up @@ -162,6 +166,8 @@ func RunTestCCIPOwnershipTransfer(s *CCIPMCMSTestSuite) {
s.Require().NoError(err, "executing ownership transfer of OnRamp to MCMS")
_, err = ccipOffRampContract.ExecuteOwnershipTransferToMcms(s.T().Context(), s.deps.GetCallOpts(), bind.Object{Id: s.ccipObjects.CCIPObjectRefObjectId}, bind.Object{Id: s.ccipOfframpObjects.OwnerCapId}, bind.Object{Id: s.ccipOfframpObjects.StateObjectId}, bind.Object{Id: s.registryObj}, s.mcmsPackageID)
s.Require().NoError(err, "executing ownership transfer of OffRamp to MCMS")
_, err = ccipRouterContract.ExecuteOwnershipTransferToMcms(s.T().Context(), s.deps.GetCallOpts(), bind.Object{Id: s.ccipRouterObjects.OwnerCapObjectId}, bind.Object{Id: s.ccipRouterObjects.RouterStateObjectId}, bind.Object{Id: s.registryObj}, s.mcmsPackageID)
s.Require().NoError(err, "executing ownership transfer of Router to MCMS")
Comment on lines +169 to +170
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@RodrigoAD shouldn't we have a sequence for this too? Similar to accept ownership.

Copy link
Member

Choose a reason for hiding this comment

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


// 4. Verify the new owner is MCMS
newOwner, err := ccipContract.DevInspect().Owner(s.T().Context(), s.deps.GetCallOpts(), bind.Object{Id: s.ccipObjects.CCIPObjectRefObjectId})
Expand All @@ -175,6 +181,10 @@ func RunTestCCIPOwnershipTransfer(s *CCIPMCMSTestSuite) {
newOwnerOffRamp, err := ccipOffRampContract.DevInspect().Owner(s.T().Context(), s.deps.GetCallOpts(), bind.Object{Id: s.ccipOfframpObjects.StateObjectId})
s.Require().NoError(err, "getting new owner of OffRamp state object")
s.Require().Equal(s.mcmsPackageID, newOwnerOffRamp, "new owner of OffRamp should be MCMS")

newOwnerRouter, err := ccipRouterContract.DevInspect().Owner(s.T().Context(), s.deps.GetCallOpts(), bind.Object{Id: s.ccipRouterObjects.RouterStateObjectId})
s.Require().NoError(err, "getting new owner of Router state object")
s.Require().Equal(s.mcmsPackageID, newOwnerRouter, "new owner of Router should be MCMS")
}

func RunTestCCIPFeeQuoterProposal(s *CCIPMCMSTestSuite) {
Expand Down Expand Up @@ -470,3 +480,69 @@ func RunCCIPRampsProposal(s *CCIPMCMSTestSuite) {
require.Contains(s.T(), actualAllowedSenders, expectedSender, "allowed senders should contain expected sender")
}
}

func RunTestRouterProposal(s *CCIPMCMSTestSuite) {
// 1. Build configs
expectedDestChainSelectors := []uint64{
cselectors.ETHEREUM_TESTNET_SEPOLIA.Selector,
cselectors.ETHEREUM_TESTNET_SEPOLIA_ARBITRUM_1.Selector,
}
expectedOnRampAddresses := []string{
"0x1111111111111111111111111111111111111111111111111111111111111111",
"0x2222222222222222222222222222222222222222222222222222222222222222",
}

// 2. Run ops to generate proposal
input := mcmsops.ProposalGenerateInput{
Defs: []cld_ops.Definition{
routerops.SetOnRampsOp.Def(),
},
Inputs: []any{
routerops.SetOnRampsInput{
RouterPackageId: s.ccipRouterPackageId,
RouterStateObjectId: s.ccipRouterObjects.RouterStateObjectId,
OwnerCapObjectId: s.ccipRouterObjects.OwnerCapObjectId,
DestChainSelectors: expectedDestChainSelectors,
OnRampAddresses: expectedOnRampAddresses,
},
},
// MCMS related
MmcsPackageID: s.mcmsPackageID,
McmsStateObjID: s.mcmsObj,
TimelockObjID: s.timelockObj,
AccountObjID: s.accountObj,
RegistryObjID: s.registryObj,
// Proposal
Role: suisdk.TimelockRoleBypasser,
ChainSelector: uint64(s.chainSelector),
Delay: 0,
}
routerReport, err := cld_ops.ExecuteSequence(s.bundle, mcmsops.MCMSDynamicProposalGenerateSeq, s.deps, input)
s.Require().NoError(err, "executing router proposal sequence")

timelockProposal := routerReport.Output

// 3. Execute proposal
s.ExecuteProposalE2e(&timelockProposal, s.bypasserConfig, 0)

// 4. Assert changes in contracts

// Create router contract instance
routerContract, err := module_router.NewRouter(s.ccipRouterPackageId, s.client)
require.NoError(s.T(), err, "creating router contract")

routerStateObj := bind.Object{Id: s.ccipRouterObjects.RouterStateObjectId}

// Verify OnRamp addresses are set correctly
for i, destChainSelector := range expectedDestChainSelectors {
// Verify chain is supported
isSupported, err := routerContract.DevInspect().IsChainSupported(s.T().Context(), s.deps.GetCallOpts(), routerStateObj, destChainSelector)
require.NoError(s.T(), err, "checking if chain is supported")
require.True(s.T(), isSupported, "chain %d should be supported", destChainSelector)

// Verify OnRamp address matches expected
actualOnRampAddress, err := routerContract.DevInspect().GetOnRamp(s.T().Context(), s.deps.GetCallOpts(), routerStateObj, destChainSelector)
require.NoError(s.T(), err, "getting on-ramp address for chain %d", destChainSelector)
require.Equal(s.T(), expectedOnRampAddresses[i], actualOnRampAddress, "on-ramp address for chain %d should match", destChainSelector)
}
}
Loading