Documentation
¶
Index ¶
- Variables
- func CantonTokenPoolDecimalsFromDataStore(ds datastore.DataStore, chainSelector uint64, poolRef datastore.AddressRef) (uint8, error)
- func IsCantonPoolNotOnLedgerErr(err error) bool
- type CantonOutboundDestFeeInput
- type CommitteeVerifierParams
- type ConfigureCommitteeVerifierAsDestInput
- type ConfigureCommitteeVerifierAsSourceInput
- type ConfigureLaneLegInput
- type DeployChainContractsParams
- type DeployLinkTokenFromFactoryParams
- type ExecutorParams
- type FeeQuoterParams
- type GlobalConfigParams
- type HardenCantonInboundLaneInput
- type RMNRemoteParams
- type RegisterNativeFeeTokenInTARInput
- type RegisterTokenPoolInput
Constants ¶
This section is empty.
Variables ¶
var ConfigureCommitteeVerifierAsDest = operations.NewSequence( "canton/ccip/committee_verifier/configure_as_dest", semver.MustParse("2.0.0"), "Configures inbound CommitteeVerifier settings for remote chains", func(b operations.Bundle, deps chain.BlockChains, input ConfigureCommitteeVerifierAsDestInput) (output sequences.OnChainOutput, err error) { chain, ok := deps.CantonChains()[input.ChainSelector] if !ok { return sequences.OnChainOutput{}, fmt.Errorf("chain with selector %d not found", input.ChainSelector) } signatureConfigs := make([]committeeverifier.SignatureConfig, 0, len(input.RemoteChains)) for remoteSelector, remoteConfig := range input.RemoteChains { signerKeys := make([]types.TEXT, len(remoteConfig.SignatureConfig.Signers)) for i, signer := range remoteConfig.SignatureConfig.Signers { signerBytes, err := hex.DecodeString(strings.TrimPrefix(signer, "0x")) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to decode signer key %d for remote chain %d: %w", i, remoteSelector, err) } signerKeys[i] = types.TEXT(hex.EncodeToString(signerBytes)) } signatureConfigs = append(signatureConfigs, committeeverifier.SignatureConfig{ SourceChainSelector: types.NUMERIC(strconv.FormatUint(remoteSelector, 10)), Threshold: types.INT64(remoteConfig.SignatureConfig.Threshold), SignerKeys: signerKeys, }) } var proposalOutputs []contract.ExerciseOutput for _, addressRef := range input.CommitteeVerifier { address := contracts.HexToInstanceAddress(addressRef.Address) raw, err := dsutils.GetRawInstanceAddressFromAddressRef(addressRef) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("committee verifier raw instance address: %w", err) } sigReport, err := operations.ExecuteOperation(b, committee_verifier.ApplySignatureConfigs, chain, contract.ChoiceInput[committeeverifier.ApplySignatureConfigs]{ InstanceAddress: address, RawInstanceAddress: raw.String(), MCMSEnabled: input.MCMSEnabled, Args: committeeverifier.ApplySignatureConfigs{ SourceChainSelectorsToRemove: nil, SignatureConfigs: signatureConfigs, }, }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to apply signature configs to CommitteeVerifier at address %s: %w", address.Hex(), err) } if input.MCMSEnabled && !sigReport.Output.Executed() { proposalOutputs = append(proposalOutputs, sigReport.Output) } } if !input.MCMSEnabled || len(proposalOutputs) == 0 { return sequences.OnChainOutput{}, nil } batchOp, err := contract.NewBatchOperationFromExercises(proposalOutputs) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("build MCMS batch for committee verifier dest configuration: %w", err) } if len(batchOp.Transactions) == 0 { return sequences.OnChainOutput{}, nil } return sequences.OnChainOutput{BatchOps: []mcms_types.BatchOperation{batchOp}}, nil }, )
var ConfigureCommitteeVerifierAsSource = operations.NewSequence( "canton/ccip/committee_verifier/configure_as_source", semver.MustParse("2.0.0"), "Configures the outbound CommitteeVerifier settings for remote chains", func(b operations.Bundle, deps chain.BlockChains, input ConfigureCommitteeVerifierAsSourceInput) (output sequences.OnChainOutput, err error) { chain, ok := deps.CantonChains()[input.ChainSelector] if !ok { return sequences.OnChainOutput{}, fmt.Errorf("chain with selector %d not found", input.ChainSelector) } remoteChainConfigArgs := make([]committeeverifier.RemoteChainConfigArgs, 0, len(input.RemoteChains)) allowListArgs := make([]committeeverifier.AllowListConfigArgs, 0, len(input.RemoteChains)) for remoteSelector, remoteConfig := range input.RemoteChains { remoteChainConfigArgs = append(remoteChainConfigArgs, committeeverifier.RemoteChainConfigArgs{ RemoteChainSelector: types.NUMERIC(strconv.FormatUint(remoteSelector, 10)), FeeUSDCents: types.NUMERIC(strconv.FormatUint(uint64(remoteConfig.FeeUSDCents), 10)), GasForVerification: types.INT64(remoteConfig.GasForVerification), PayloadSizeBytes: types.INT64(remoteConfig.PayloadSizeBytes), AllowListEnabled: types.BOOL(remoteConfig.AllowlistEnabled), }) allowListArgs = append(allowListArgs, committeeverifier.AllowListConfigArgs{ DestChainSelector: types.NUMERIC(strconv.FormatUint(remoteSelector, 10)), AllowListEnabled: types.BOOL(remoteConfig.AllowlistEnabled), AddedAllowListedSenders: convertPartySlice(remoteConfig.AddedAllowlistedSenders), RemovedAllowListedSenders: convertPartySlice(remoteConfig.RemovedAllowlistedSenders), }) } var proposalOutputs []contract.ExerciseOutput for _, addressRef := range input.CommitteeVerifier { address := contracts.HexToInstanceAddress(addressRef.Address) raw, err := dsutils.GetRawInstanceAddressFromAddressRef(addressRef) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("committee verifier raw instance address: %w", err) } remoteReport, err := operations.ExecuteOperation(b, committee_verifier.ApplyRemoteChainConfigUpdates, chain, contract.ChoiceInput[committeeverifier.ApplyRemoteChainConfigUpdates]{ InstanceAddress: address, RawInstanceAddress: raw.String(), MCMSEnabled: input.MCMSEnabled, Args: committeeverifier.ApplyRemoteChainConfigUpdates{ RemoteChainConfigArgs: remoteChainConfigArgs, }, }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to apply remote chain configs to CommitteeVerifier at address %s: %w", address.Hex(), err) } if input.MCMSEnabled && !remoteReport.Output.Executed() { proposalOutputs = append(proposalOutputs, remoteReport.Output) } allowListReport, err := operations.ExecuteOperation(b, committee_verifier.ApplyAllowListUpdates, chain, contract.ChoiceInput[committeeverifier.ApplyAllowListUpdates]{ InstanceAddress: address, RawInstanceAddress: raw.String(), MCMSEnabled: input.MCMSEnabled, Args: committeeverifier.ApplyAllowListUpdates{ AllowListConfigArgsItems: allowListArgs, Caller: types.PARTY(raw.Owner()), }, }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to apply allow list updates to CommitteeVerifier at address %s: %w", address.Hex(), err) } if input.MCMSEnabled && !allowListReport.Output.Executed() { proposalOutputs = append(proposalOutputs, allowListReport.Output) } } if !input.MCMSEnabled || len(proposalOutputs) == 0 { return sequences.OnChainOutput{}, nil } batchOp, err := contract.NewBatchOperationFromExercises(proposalOutputs) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("build MCMS batch for committee verifier source configuration: %w", err) } if len(batchOp.Transactions) == 0 { return sequences.OnChainOutput{}, nil } return sequences.OnChainOutput{BatchOps: []mcms_types.BatchOperation{batchOp}}, nil }, )
var ConfigureLaneLegAsDest = operations.NewSequence( "CantonConfigureLaneLegAsDest", semver.MustParse("2.0.0"), "Configures a lane lad as dest on CCIP 2.0.0", func(b operations.Bundle, deps chain.BlockChains, input lanes.UpdateLanesInput) (output sequences.OnChainOutput, err error) { b.Logger.Infof("Canton Configuring lane leg as dest. src: %+v, dest: %+v", input.Source, input.Dest) chain, ok := deps.CantonChains()[input.Dest.Selector] if !ok { return sequences.OnChainOutput{}, fmt.Errorf("chain with selector %d not found", input.Source.Selector) } sourceChain := input.Source destChain := input.Dest mcmsEnabled := len(chain.Participants[0].ReadAsPartyIDs) > 0 var proposalOutputs []contract.ExerciseOutput globalConfigRaw, err := dsutils.GetRawInstanceAddressFromAddressRef(destChain.CantonLaneConfig.GlobalConfig) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("global config raw instance address: %w", err) } laneMandatedInboundCCVs := make([]chainlinkapi.RawInstanceAddress, 0, len(destChain.LaneMandatedInboundCCVs)) for _, ccv := range destChain.LaneMandatedInboundCCVs { inboundCCV, err := dsutils.GetRawInstanceAddressFromAddressRef(ccv) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("getting lane mandated inbound CCV: %w", err) } laneMandatedInboundCCVs = append(laneMandatedInboundCCVs, inboundCCV.Binding()) } defaultInboundCCVs := make([]chainlinkapi.RawInstanceAddress, 0, len(destChain.DefaultInboundCCVs)) for _, ccv := range destChain.DefaultInboundCCVs { inboundCCV, err := dsutils.GetRawInstanceAddressFromAddressRef(ccv) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("getting lane mandated inbound CCV: %w", err) } defaultInboundCCVs = append(defaultInboundCCVs, inboundCCV.Binding()) } inboundOnRampAddresses := []types.TEXT{ types.TEXT(hex.EncodeToString(gethcommon.LeftPadBytes(sourceChain.OnRamp, 32))), } sourceChainConfigReport, err := operations.ExecuteOperation(b, global_config.ApplySourceChainConfigUpdates, chain, contract.ChoiceInput[core.ApplySourceChainConfigUpdates]{ InstanceAddress: globalConfigRaw.InstanceAddress(), RawInstanceAddress: globalConfigRaw.String(), MCMSEnabled: mcmsEnabled, Args: core.ApplySourceChainConfigUpdates{ SourceChainConfigUpdates: []core.SourceChainConfigArgs{ { SourceChainSelector: types.NUMERIC(strconv.FormatUint(sourceChain.Selector, 10)), IsEnabled: types.BOOL(!input.IsDisabled), OnRampAddresses: inboundOnRampAddresses, DefaultCCVs: defaultInboundCCVs, LaneMandatedCCVs: laneMandatedInboundCCVs, }, }, }, }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("applying source chain config updates to global config: %w", err) } if mcmsEnabled && !sourceChainConfigReport.Output.Executed() { proposalOutputs = append(proposalOutputs, sourceChainConfigReport.Output) } var cvBatchOps []mcms_types.BatchOperation if !mcmsEnabled { for _, verifierConfig := range input.Dest.CommitteeVerifiers { cvReport, err := operations.ExecuteSequence(b, ConfigureCommitteeVerifierAsDest, deps, ConfigureCommitteeVerifierAsDestInput{ ChainSelector: chain.Selector, MCMSEnabled: mcmsEnabled, CommitteeVerifierConfig: verifierConfig, }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("configuring committee verifier as dest: %w", err) } cvBatchOps = append(cvBatchOps, cvReport.Output.BatchOps...) } } if !mcmsEnabled { return sequences.OnChainOutput{}, nil } batchOp, err := contract.NewBatchOperationFromExercises(proposalOutputs) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("build MCMS batch for lane configuration: %w", err) } batchOps := cvBatchOps if len(batchOp.Transactions) > 0 { batchOps = append(batchOps, batchOp) } if len(batchOps) == 0 { return sequences.OnChainOutput{}, nil } return sequences.OnChainOutput{BatchOps: batchOps}, nil }, )
var ConfigureLaneLegAsSource = operations.NewSequence( "CantonConfigureLaneLegAsSource", semver.MustParse("2.0.0"), "Configures a lane leg as source on CCIP 2.0.0", func(b operations.Bundle, deps chain.BlockChains, input lanes.UpdateLanesInput) (output sequences.OnChainOutput, err error) { return configureLaneLegAsSource(b, deps, ConfigureLaneLegInput{Lane: input}) }, )
var ConfigureLaneLegAsSourceWithInput = operations.NewSequence( "CantonConfigureLaneLegAsSourceWithInput", semver.MustParse("2.0.0"), "Configures a lane leg as source on CCIP 2.0.0", configureLaneLegAsSource, )
var ConfigureTokenForTransfers = operations.NewSequence( "canton/token-adapter/configure-token-for-transfers", semver.MustParse("2.0.0"), "Configures a Canton token pool for cross-chain transfers", func(b operations.Bundle, chains chain.BlockChains, input tokenadapters.ConfigureTokenForTransfersInput) (ccipsequences.OnChainOutput, error) { if input.ExistingDataStore == nil { return ccipsequences.OnChainOutput{}, fmt.Errorf("existing datastore is required") } cantonChain, ok := chains.CantonChains()[input.ChainSelector] if !ok || len(cantonChain.Participants) == 0 { return ccipsequences.OnChainOutput{}, fmt.Errorf("canton chain with selector %d not found", input.ChainSelector) } participant := cantonChain.Participants[0] mcmsEnabled := len(participant.ReadAsPartyIDs) > 0 var batchOps []mcms_types.BatchOperation var proposalOutputs []contract.ExerciseOutput poolAddress := contracts.HexToInstanceAddress(input.TokenPoolAddress) logicalPoolType, err := resolveCantonTokenPoolType(input.PoolType) if err != nil { return ccipsequences.OnChainOutput{}, err } parsedPool, err := loadConfiguredCantonTokenPool( b.GetContext(), participant, input.ExistingDataStore, input.ChainSelector, logicalPoolType, poolAddress, b.Logger, ) if err != nil { return ccipsequences.OnChainOutput{}, err } factoryRefs := input.ExistingDataStore.Addresses().Filter( datastore.AddressRefByChainSelector(input.ChainSelector), datastore.AddressRefByType(datastore.ContractType(factoryops.ContractType)), ) factoryRef, err := dsutils.FactoryAddressRefFromRefs(input.ChainSelector, dsutils.QualifierCCIP, factoryRefs) if err != nil { return ccipsequences.OnChainOutput{}, err } factoryRaw, err := rawInstanceAddressFromAddressRef(factoryRef) if err != nil { return ccipsequences.OnChainOutput{}, fmt.Errorf("resolve CCIPFactory raw address: %w", err) } poolRaw := contracts.NewRawInstanceAddress(contracts.InstanceID(parsedPool.InstanceId), parsedPool.PoolOwner) out := ccipsequences.OnChainOutput{} committeeVerifierRefs := input.ExistingDataStore.Addresses().Filter( datastore.AddressRefByChainSelector(input.ChainSelector), datastore.AddressRefByType(datastore.ContractType(committee_verifier.ContractType)), datastore.AddressRefByVersion(committee_verifier.Version), ) updates := make([]tokenPoolChainUpdate, 0, len(input.RemoteChains)) for remoteSelector, remoteCfg := range input.RemoteChains { remoteSelectorKeyStr := strconv.FormatUint(remoteSelector, 10) remoteSelectorKey := types.NUMERIC(remoteSelectorKeyStr) if _, found := parsedPool.RemoteChainConfigs[remoteSelectorKey]; found { return out, fmt.Errorf("remote chain %d is already configured on token pool", remoteSelector) } inboundCCVs, err := resolveCommitteeVerifierRawAddresses(committeeVerifierRefs, remoteCfg.InboundCCVs) if err != nil { return out, fmt.Errorf("resolve inbound CCVs for remote chain %d: %w", remoteSelector, err) } outboundCCVs, err := resolveCommitteeVerifierRawAddresses(committeeVerifierRefs, remoteCfg.OutboundCCVs) if err != nil { return out, fmt.Errorf("resolve outbound CCVs for remote chain %d: %w", remoteSelector, err) } defaultOutboundBucket, _ := remoteCfg.GetOutboundRateLimitBuckets().DefaultBucket() defaultInboundBucket, _ := remoteCfg.GetInboundRateLimitBuckets().DefaultBucket() outboundDefaultCfg, inboundDefaultCfg := tokenadapters.GenerateTPRLConfigs( defaultOutboundBucket.RateLimit, defaultInboundBucket.RateLimit, uint8(parsedPool.Decimals), remoteCfg.RemoteDecimals, "canton", semver.MustParse("2.0.0"), lockReleasePoolType.String(), ) ffOutboundBucket, ffOutboundExists := remoteCfg.GetOutboundRateLimitBuckets().FastFinalityBucket() ffInboundBucket, ffInboundExists := remoteCfg.GetInboundRateLimitBuckets().FastFinalityBucket() customOutboundInput := defaultOutboundBucket.RateLimit customInboundInput := defaultInboundBucket.RateLimit if ffOutboundExists && ffInboundExists { customOutboundInput = ffOutboundBucket.RateLimit customInboundInput = ffInboundBucket.RateLimit } _, inboundCustomCfg := tokenadapters.GenerateTPRLConfigs( customOutboundInput, customInboundInput, uint8(parsedPool.Decimals), remoteCfg.RemoteDecimals, "canton", semver.MustParse("2.0.0"), lockReleasePoolType.String(), ) meta := rateLimiterPoolMeta{InstanceId: parsedPool.InstanceId, PoolOwner: parsedPool.PoolOwner} outboundRef, outboundRaw, err := deployTokenPoolRateLimiter( b, cantonChain, input.ChainSelector, factoryRaw, mcmsEnabled, input.ExistingDataStore, meta, input.TokenPoolAddress, remoteSelectorKeyStr, "outbound", outboundDefaultCfg, ratelimiter.RateLimitModeRateLimitMode_DefaultFinality, &proposalOutputs, ) if err != nil { return out, fmt.Errorf("deploy outbound rate limiter for remote chain %d: %w", remoteSelector, err) } out.Addresses = append(out.Addresses, outboundRef) inboundRef, inboundRaw, err := deployTokenPoolRateLimiter( b, cantonChain, input.ChainSelector, factoryRaw, mcmsEnabled, input.ExistingDataStore, meta, input.TokenPoolAddress, remoteSelectorKeyStr, "inbound", inboundDefaultCfg, ratelimiter.RateLimitModeRateLimitMode_DefaultFinality, &proposalOutputs, ) if err != nil { return out, fmt.Errorf("deploy inbound rate limiter for remote chain %d: %w", remoteSelector, err) } out.Addresses = append(out.Addresses, inboundRef) customRef, customInboundRaw, err := deployTokenPoolRateLimiter( b, cantonChain, input.ChainSelector, factoryRaw, mcmsEnabled, input.ExistingDataStore, meta, input.TokenPoolAddress, remoteSelectorKeyStr, "inbound-custom", inboundCustomCfg, ratelimiter.RateLimitModeRateLimitMode_CustomFinality, &proposalOutputs, ) if err != nil { return out, fmt.Errorf("deploy custom inbound rate limiter for remote chain %d: %w", remoteSelector, err) } out.Addresses = append(out.Addresses, customRef) remoteFamily, err := chain_selectors.GetSelectorFamily(remoteSelector) if err != nil { return out, fmt.Errorf("get remote chain family for %d: %w", remoteSelector, err) } remotePoolAddress := strings.ToLower(hex.EncodeToString(remoteCfg.RemotePool)) remoteTokenAddress := strings.ToLower(hex.EncodeToString(remoteCfg.RemoteToken)) if remoteFamily == chain_selectors.FamilyEVM { remotePoolAddress = strings.TrimPrefix(strings.ToLower(gethcommon.BytesToHash(remoteCfg.RemotePool).Hex()), "0x") remoteTokenAddress = strings.TrimPrefix(strings.ToLower(gethcommon.BytesToHash(remoteCfg.RemoteToken).Hex()), "0x") } updates = append(updates, tokenPoolChainUpdate{ RemoteChainSelector: remoteSelectorKey, RemotePools: []types.TEXT{types.TEXT(remotePoolAddress)}, RemoteTokenAddress: types.TEXT(remoteTokenAddress), InboundCCVs: inboundCCVs, OutboundCCVs: outboundCCVs, FinalityConfig: toCantonFinalityConfig(input.AllowedFinalityConfig), InboundRateLimiter: inboundRaw, InboundCustomBlockConfirmationsRateLimiter: customInboundRaw, OutboundRateLimiter: outboundRaw, }) } if len(updates) == 0 { if mcmsEnabled && len(proposalOutputs) > 0 { batchOp, err := contract.NewBatchOperationFromExercises(proposalOutputs) if err != nil { return out, fmt.Errorf("build MCMS batch for token pool configuration: %w", err) } if len(batchOp.Transactions) > 0 { batchOps = append(batchOps, batchOp) } } out.BatchOps = batchOps return out, nil } switch logicalPoolType { case lockReleasePoolType: lockReleaseUpdates := make([]lockreleasetokenpool.ChainUpdate, 0, len(updates)) for _, update := range updates { lockReleaseUpdates = append(lockReleaseUpdates, lockreleasetokenpool.ChainUpdate{ RemoteChainSelector: update.RemoteChainSelector, RemotePools: update.RemotePools, RemoteTokenAddress: update.RemoteTokenAddress, InboundCCVs: update.InboundCCVs, OutboundCCVs: update.OutboundCCVs, FinalityConfig: update.FinalityConfig, InboundRateLimiter: update.InboundRateLimiter, InboundCustomBlockConfirmationsRateLimiter: update.InboundCustomBlockConfirmationsRateLimiter, OutboundRateLimiter: update.OutboundRateLimiter, }) } applyReport, err := operations.ExecuteOperation(b, lock_release_token_pool.ApplyChainUpdates, cantonChain, contract.ChoiceInput[lockreleasetokenpool.ApplyChainUpdates]{ InstanceAddress: poolRaw.InstanceAddress(), RawInstanceAddress: poolRaw.String(), MCMSEnabled: mcmsEnabled, Args: lockreleasetokenpool.ApplyChainUpdates{ RemoteChainSelectorsToRemove: []types.NUMERIC{}, ChainsToAdd: lockReleaseUpdates, }, }) if err != nil { if strings.Contains(err.Error(), "ApplyChainUpdates: chain already exists:") { return out, nil } return out, fmt.Errorf("apply remote chain updates to lock/release pool: %w", err) } if mcmsEnabled && !applyReport.Output.Executed() { proposalOutputs = append(proposalOutputs, applyReport.Output) } case burnMintPoolType: burnMintUpdates := make([]burnminttokenpool.ChainUpdate, 0, len(updates)) for _, update := range updates { burnMintUpdates = append(burnMintUpdates, burnminttokenpool.ChainUpdate{ RemoteChainSelector: update.RemoteChainSelector, RemotePools: update.RemotePools, RemoteTokenAddress: update.RemoteTokenAddress, InboundCCVs: update.InboundCCVs, OutboundCCVs: update.OutboundCCVs, FinalityConfig: update.FinalityConfig, InboundRateLimiter: update.InboundRateLimiter, InboundCustomBlockConfirmationsRateLimiter: update.InboundCustomBlockConfirmationsRateLimiter, OutboundRateLimiter: update.OutboundRateLimiter, }) } applyReport, err := operations.ExecuteOperation(b, burn_mint_token_pool.ApplyChainUpdates, cantonChain, contract.ChoiceInput[burnminttokenpool.ApplyChainUpdates]{ InstanceAddress: poolRaw.InstanceAddress(), RawInstanceAddress: poolRaw.String(), MCMSEnabled: mcmsEnabled, Args: burnminttokenpool.ApplyChainUpdates{ RemoteChainSelectorsToRemove: []types.NUMERIC{}, ChainsToAdd: burnMintUpdates, }, }) if err != nil { if strings.Contains(err.Error(), "ApplyChainUpdates: chain already exists:") { return out, nil } return out, fmt.Errorf("apply remote chain updates to burn/mint pool: %w", err) } if mcmsEnabled && !applyReport.Output.Executed() { proposalOutputs = append(proposalOutputs, applyReport.Output) } default: return out, fmt.Errorf("unsupported Canton token pool type %q", logicalPoolType) } if mcmsEnabled && len(proposalOutputs) > 0 { batchOp, err := contract.NewBatchOperationFromExercises(proposalOutputs) if err != nil { return out, fmt.Errorf("build MCMS batch for token pool configuration: %w", err) } if len(batchOp.Transactions) > 0 { batchOps = append(batchOps, batchOp) } } out.BatchOps = batchOps return out, nil }, )
var DeployCCIPChainContractsFromFactory = operations.NewSequence( "canton/ccip/deploy_ccip_chain_contracts_from_factory", semver.MustParse("2.0.0"), "Deploys core CCIP contracts on Canton through CCIPFactory (excludes RMNRemote and CommitteeVerifier)", func(b operations.Bundle, deps canton.Chain, input DeployChainContractsParams) (sequences.OnChainOutput, error) { if input.RmnRemoteRawInstanceAddress == "" { return sequences.OnChainOutput{}, fmt.Errorf("RmnRemoteRawInstanceAddress is required for core CCIP factory deploy") } coreInput := input coreInput.CommitteeVerifiers = nil report, err := operations.ExecuteSequence(b, DeployChainContractsFromFactory, deps, coreInput) if err != nil { return sequences.OnChainOutput{}, err } return report.Output, nil }, )
DeployCCIPChainContractsFromFactory deploys CCIP contracts (no RMNRemote, no CommitteeVerifiers) via the ccip-qualified factory.
var DeployCCVFromFactory = operations.NewSequence( "canton/ccip/deploy_ccv_from_factory", semver.MustParse("2.0.0"), "Deploys CommitteeVerifier contracts on Canton through CCIPFactory", func(b operations.Bundle, deps canton.Chain, input DeployChainContractsParams) (sequences.OnChainOutput, error) { if len(input.CommitteeVerifiers) == 0 { return sequences.OnChainOutput{}, fmt.Errorf("at least one committee verifier is required") } if input.RmnRemoteRawInstanceAddress == "" { return sequences.OnChainOutput{}, fmt.Errorf("RmnRemoteRawInstanceAddress is required for CCV factory deploy") } ccipOwnerParty, err := requireCCIPOwnerParty(input) if err != nil { return sequences.OnChainOutput{}, err } ccvOwnerParty, err := requireCCVOwnerParty(input) if err != nil { return sequences.OnChainOutput{}, err } factoryRawInstanceAddress, err := rawInstanceAddressFromAddressRef(input.FactoryAddressRef) if err != nil { return sequences.OnChainOutput{}, err } var addresses []datastore.AddressRef var proposalOutputs []contract.ExerciseOutput for i, committeeVerifierParams := range input.CommitteeVerifiers { qualifier := committeeVerifierParams.Qualifier committeeVerifierOwner := ccvOwnerParty committeeVerifierInstanceID, err := ensureInstanceID(committeeVerifierParams.Template.InstanceId, "committeeverifier") if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to ensure CommitteeVerifier #%d instance ID: %w", i, err) } committeeVerifierTemplate := committeeverifier.CommitteeVerifier{ InstanceId: types.TEXT(committeeVerifierInstanceID), Owner: committeeVerifierOwner, CcipOwner: ccipOwnerParty, VersionTag: committeeVerifierParams.Template.VersionTag, AllowListAdmin: committeeVerifierParams.Template.AllowListAdmin, MessageSentObservers: committeeVerifierParams.Template.MessageSentObservers, StorageLocations: committeeVerifierParams.Template.StorageLocations, StorageLocationsAdmin: committeeVerifierParams.Template.StorageLocationsAdmin, PendingStorageLocationsAdmin: committeeVerifierParams.Template.PendingStorageLocationsAdmin, RemoteChainConfigs: committeeVerifierParams.Template.RemoteChainConfigs, SignerConfigs: committeeVerifierParams.Template.SignerConfigs, Deps: committeeverifier.CommitteeVerifierDeps{ RmnRemote: input.RmnRemoteRawInstanceAddress.Binding(), }, } deployReport, err := operations.ExecuteOperation(b, factoryops.DeployCommitteeVerifier, deps, newChoiceInput(factoryRawInstanceAddress, factorybindings.DeployCommitteeVerifier{Contract: committeeVerifierTemplate}, input.ProposalDriven)) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy CommitteeVerifier #%d from factory: %w", i, err) } proposalOutputs = appendExerciseOutput(proposalOutputs, deployReport.Output, input.ProposalDriven) committeeVerifierRawInstanceAddress := committeeVerifierInstanceID.RawInstanceAddress(committeeVerifierOwner) addresses = append(addresses, newAddressRef(deps.ChainSelector(), committeeVerifierRawInstanceAddress, committee_verifier.ContractType, committee_verifier.Version, qualifier)) } out := sequences.OnChainOutput{Addresses: addresses} if input.ProposalDriven { batchOp, err := contract.NewBatchOperationFromExercises(proposalOutputs) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to build CCV proposal batch: %w", err) } if len(batchOp.Transactions) > 0 { out.BatchOps = []mcms_types.BatchOperation{batchOp} } } return out, nil }, )
DeployCCVFromFactory deploys CommitteeVerifier contracts via a CCV-qualified CCIPFactory.
var DeployChainContracts = operations.NewSequence( "canton/ccip/deploy_chain_contracts", semver.MustParse("2.0.0"), "Deploys all required contracts for CCIP 2.0.0 to a Canton chain", func(b operations.Bundle, deps canton.Chain, input DeployChainContractsParams) (sequences.OnChainOutput, error) { var addresses []datastore.AddressRef rmnOwnerParty, err := requireRMNOwnerParty(input) if err != nil { return sequences.OnChainOutput{}, err } nativeInstrumentID, err := resolveNativeInstrumentID(b, deps, input.NativeInstrumentId) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to resolve native fee token instrument: %w", err) } deployRMNRemoteReport, err := operations.ExecuteOperation(b, rmn_remote.Deploy, deps, contract.DeployInput[core.RMNRemote]{ Template: rmnRemoteDeployTemplate(rmnOwnerParty, types.PARTY(input.CCIPOwnerParty), input.RMNRemote), OwnerParty: rmnOwnerParty, }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy RMNRemote: %w", err) } addresses = append(addresses, deployRMNRemoteReport.Output) rmnRemoteRawInstanceAddress, err := contracts.RawInstanceAddressFromString(deployRMNRemoteReport.Output.Labels.List()[0]) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to parse RMNRemote raw instance address: %w", err) } input.GlobalConfig.Template.CcipOwner = types.PARTY(input.CCIPOwnerParty) deployGlobalConfigReport, err := operations.ExecuteOperation(b, global_config.Deploy, deps, contract.DeployInput[core.GlobalConfig]{ Template: input.GlobalConfig.Template, OwnerParty: types.PARTY(input.CCIPOwnerParty), }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy GlobalConfig: %w", err) } addresses = append(addresses, deployGlobalConfigReport.Output) globalConfigRawInstanceAddress, err := contracts.RawInstanceAddressFromString(deployGlobalConfigReport.Output.Labels.List()[0]) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to parse GlobalConfig raw instance address: %w", err) } deployTokenAdminRegistryReport, err := operations.ExecuteOperation(b, token_admin_registry.Deploy, deps, contract.DeployInput[core.TokenAdminRegistry]{ Template: core.TokenAdminRegistry{ CcipOwner: types.PARTY(input.CCIPOwnerParty), EntryCount: 0, }, OwnerParty: types.PARTY(input.CCIPOwnerParty), }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy TokenAdminRegistry: %w", err) } addresses = append(addresses, deployTokenAdminRegistryReport.Output) tokenAdminRegistryRawInstanceAddress, err := contracts.RawInstanceAddressFromString(deployTokenAdminRegistryReport.Output.Labels.List()[0]) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to parse TokenAdminRegistry raw instance address: %w", err) } linkTokenId := input.FeeQuoterConfig.Template.LinkTokenInstrumentId if linkTokenId.Admin == "" { linkTokenId = splice_api_token_holding_v1.InstrumentId{ Admin: types.PARTY(input.CCIPOwnerParty), Id: types.TEXT("link-token"), } } deployFeeQuoterReport, err := operations.ExecuteOperation(b, fee_quoter.Deploy, deps, contract.DeployInput[core.FeeQuoter]{ Template: core.FeeQuoter{ CcipOwner: types.PARTY(input.CCIPOwnerParty), FeeTokens: types.SET{}, DestChainConfigs: nil, TokenTransferFeeConfigs: nil, UsdPerUnitGasByDestChainSelector: nil, UsdPerToken: nil, LinkTokenInstrumentId: linkTokenId, PriceUpdaters: input.FeeQuoterConfig.Template.PriceUpdaters, }, OwnerParty: types.PARTY(input.CCIPOwnerParty), }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy FeeQuoter: %w", err) } addresses = append(addresses, deployFeeQuoterReport.Output) feeQuoterRawInstanceAddress, err := contracts.RawInstanceAddressFromString(deployFeeQuoterReport.Output.Labels.List()[0]) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to parse FeeQuoter raw instance address: %w", err) } if input.FeeQuoterConfig.USDPerNative != nil { _, err = operations.ExecuteOperation(b, fee_quoter.UpdatePrices, deps, contract.ChoiceInput[core.UpdatePrices]{ InstanceAddress: feeQuoterRawInstanceAddress.InstanceAddress(), Args: core.UpdatePrices{ PriceUpdates: core.PriceUpdates{ TokenPriceUpdates: []core.TokenPriceUpdate{ { InstrumentId: nativeInstrumentID, UsdPerToken: types.NUMERIC(input.FeeQuoterConfig.USDPerNative.String()), }, }, }, }, }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to update native token price on FeeQuoter: %w", err) } } _, err = ensureNativeFeeTokenConfig( b, deps, tokenAdminRegistryRawInstanceAddress.InstanceAddress(), tokenAdminRegistryRawInstanceAddress, input.CCIPOwnerParty, nativeInstrumentID, false, ) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to ensure native fee token config: %w", err) } deployOffRampReport, err := operations.ExecuteOperation(b, offramp.Deploy, deps, contract.DeployInput[ccipruntime.OffRamp]{ Template: ccipruntime.OffRamp{ CcipOwner: types.PARTY(input.CCIPOwnerParty), Deps: ccipruntime.OffRampDeps{ GlobalConfig: globalConfigRawInstanceAddress.Binding(), RmnRemote: rmnRemoteRawInstanceAddress.Binding(), TokenAdminRegistry: tokenAdminRegistryRawInstanceAddress.Binding(), }, }, OwnerParty: types.PARTY(input.CCIPOwnerParty), }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy OffRamp: %w", err) } addresses = append(addresses, deployOffRampReport.Output) offRampRawInstanceAddress, err := contracts.RawInstanceAddressFromString(deployOffRampReport.Output.Labels.List()[0]) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to parse OffRamp raw instance address: %w", err) } deployOnRampReport, err := operations.ExecuteOperation(b, onramp.Deploy, deps, contract.DeployInput[ccipruntime.OnRamp]{ Template: ccipruntime.OnRamp{ CcipOwner: types.PARTY(input.CCIPOwnerParty), MaxUSDCentsPerMsg: types.NUMERIC("100000000"), Deps: ccipruntime.OnRampDeps{ GlobalConfig: globalConfigRawInstanceAddress.Binding(), RmnRemote: rmnRemoteRawInstanceAddress.Binding(), TokenAdminRegistry: tokenAdminRegistryRawInstanceAddress.Binding(), FeeQuoter: feeQuoterRawInstanceAddress.Binding(), }, }, OwnerParty: types.PARTY(input.CCIPOwnerParty), }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy OnRamp: %w", err) } addresses = append(addresses, deployOnRampReport.Output) onRampRawInstanceAddress, err := contracts.RawInstanceAddressFromString(deployOnRampReport.Output.Labels.List()[0]) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to parse OnRamp raw instance address: %w", err) } deployPerPartyRouterFactoryReport, err := operations.ExecuteOperation(b, per_party_router_factory.Deploy, deps, contract.DeployInput[ccipruntime.PerPartyRouterFactory]{ Template: ccipruntime.PerPartyRouterFactory{ CcipOwner: types.PARTY(input.CCIPOwnerParty), Deps: ccipruntime.PerPartyRouterDeps{ OnRamp: onRampRawInstanceAddress.Binding(), OffRamp: offRampRawInstanceAddress.Binding(), GlobalConfig: globalConfigRawInstanceAddress.Binding(), TokenAdminRegistry: tokenAdminRegistryRawInstanceAddress.Binding(), FeeQuoter: feeQuoterRawInstanceAddress.Binding(), RmnRemote: rmnRemoteRawInstanceAddress.Binding(), }, RegisteredRouters: nil, }, OwnerParty: types.PARTY(input.CCIPOwnerParty), }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy PerPartyRouterFactory: %w", err) } addresses = append(addresses, deployPerPartyRouterFactoryReport.Output) for i, committeeVerifier := range input.CommitteeVerifiers { committeeVerifier.Template.CcipOwner = types.PARTY(input.CCIPOwnerParty) deployCommitteeVerifierReport, err := operations.ExecuteOperation(b, committee_verifier.Deploy, deps, contract.DeployInput[committeeverifier.CommitteeVerifier]{ Template: committeeverifier.CommitteeVerifier{ Owner: committeeVerifier.Template.Owner, CcipOwner: types.PARTY(input.CCIPOwnerParty), VersionTag: committeeVerifier.Template.VersionTag, MessageSentObservers: committeeVerifier.Template.MessageSentObservers, StorageLocations: committeeVerifier.Template.StorageLocations, StorageLocationsAdmin: committeeVerifier.Template.StorageLocationsAdmin, PendingStorageLocationsAdmin: committeeVerifier.Template.PendingStorageLocationsAdmin, RemoteChainConfigs: committeeVerifier.Template.RemoteChainConfigs, SignerConfigs: committeeVerifier.Template.SignerConfigs, Deps: committeeverifier.CommitteeVerifierDeps{ RmnRemote: rmnRemoteRawInstanceAddress.Binding()}, }, OwnerParty: committeeVerifier.Template.Owner, Qualifier: &committeeVerifier.Qualifier, }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy CommitteeVerifier #%v: %w", i, err) } addresses = append(addresses, deployCommitteeVerifierReport.Output) } for i, params := range input.Executors { deployExecutorReport, err := operations.ExecuteOperation(b, executor.Deploy, deps, contract.DeployInput[executorBinding.Executor]{ Template: params.Template, OwnerParty: params.Template.Owner, Qualifier: ¶ms.Qualifier, }) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy Executor #%v: %w", i, err) } addresses = append(addresses, deployExecutorReport.Output) } return sequences.OnChainOutput{ Addresses: addresses, }, nil }, )
var DeployChainContractsFromFactory = operations.NewSequence( "canton/ccip/deploy_chain_contracts_from_factory", semver.MustParse("2.0.0"), "Deploys CCIP contracts on Canton through CCIPFactory choices", func(b operations.Bundle, deps canton.Chain, input DeployChainContractsParams) (sequences.OnChainOutput, error) { var addresses []datastore.AddressRef var proposalOutputs []contract.ExerciseOutput ccipOwnerParty, err := requireCCIPOwnerParty(input) if err != nil { return sequences.OnChainOutput{}, err } factoryRawInstanceAddress, err := rawInstanceAddressFromAddressRef(input.FactoryAddressRef) if err != nil { return sequences.OnChainOutput{}, err } rmnRemoteRawInstanceAddress, rmnAddressRef, rmnProposalOutputs, err := resolveOrDeployRMNRemote( b, deps, input, ) if err != nil { return sequences.OnChainOutput{}, err } if rmnAddressRef != nil { addresses = append(addresses, *rmnAddressRef) } proposalOutputs = append(proposalOutputs, rmnProposalOutputs...) globalConfigInstanceID, err := ensureInstanceID(input.GlobalConfig.Template.InstanceId, "globalconfig") if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to ensure GlobalConfig instance ID: %w", err) } globalConfigTemplate := core.GlobalConfig{ InstanceId: types.TEXT(globalConfigInstanceID), CcipOwner: ccipOwnerParty, ChainSelector: input.GlobalConfig.Template.ChainSelector, DestChainConfigs: nil, SourceChainConfigs: nil, } deployGlobalConfigReport, err := operations.ExecuteOperation(b, factoryops.DeployGlobalConfig, deps, newChoiceInput(factoryRawInstanceAddress, factorybindings.DeployGlobalConfig{Contract: globalConfigTemplate}, input.ProposalDriven)) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy GlobalConfig from factory: %w", err) } proposalOutputs = appendExerciseOutput(proposalOutputs, deployGlobalConfigReport.Output, input.ProposalDriven) globalConfigRawInstanceAddress := globalConfigInstanceID.RawInstanceAddress(ccipOwnerParty) addresses = append(addresses, newAddressRef(deps.ChainSelector(), globalConfigRawInstanceAddress, global_config.ContractType, global_config.Version, "")) tokenAdminRegistryInstanceID, err := ensureInstanceID("", "tokenadminregistry") if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to ensure TokenAdminRegistry instance ID: %w", err) } tokenAdminRegistryTemplate := core.TokenAdminRegistry{ InstanceId: types.TEXT(tokenAdminRegistryInstanceID), CcipOwner: ccipOwnerParty, EntryCount: 0, } deployTokenAdminRegistryReport, err := operations.ExecuteOperation(b, factoryops.DeployTokenAdminRegistry, deps, newChoiceInput(factoryRawInstanceAddress, factorybindings.DeployTokenAdminRegistry{Contract: tokenAdminRegistryTemplate}, input.ProposalDriven)) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy TokenAdminRegistry from factory: %w", err) } proposalOutputs = appendExerciseOutput(proposalOutputs, deployTokenAdminRegistryReport.Output, input.ProposalDriven) tokenAdminRegistryRawInstanceAddress := tokenAdminRegistryInstanceID.RawInstanceAddress(ccipOwnerParty) addresses = append(addresses, newAddressRef(deps.ChainSelector(), tokenAdminRegistryRawInstanceAddress, token_admin_registry.ContractType, token_admin_registry.Version, "")) if !input.ProposalDriven { nativeInstrumentID, err := resolveNativeInstrumentID(b, deps, input.NativeInstrumentId) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to resolve native fee token instrument: %w", err) } feeTokenConfigOutputs, err := ensureNativeFeeTokenConfig( b, deps, tokenAdminRegistryRawInstanceAddress.InstanceAddress(), tokenAdminRegistryRawInstanceAddress, input.CCIPOwnerParty, nativeInstrumentID, input.ProposalDriven, ) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to ensure native fee token config: %w", err) } proposalOutputs = append(proposalOutputs, feeTokenConfigOutputs...) } feeQuoterInstanceID, err := ensureInstanceID(input.FeeQuoterConfig.Template.InstanceId, "feequoter") if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to ensure FeeQuoter instance ID: %w", err) } linkTokenID := input.FeeQuoterConfig.Template.LinkTokenInstrumentId if linkTokenID.Admin == "" { linkTokenID = splice_api_token_holding_v1.InstrumentId{ Admin: ccipOwnerParty, Id: types.TEXT("link-token"), } } feeQuoterTemplate := core.FeeQuoter{ InstanceId: types.TEXT(feeQuoterInstanceID), CcipOwner: ccipOwnerParty, FeeTokens: types.SET{}, DestChainConfigs: nil, TokenTransferFeeConfigs: nil, UsdPerUnitGasByDestChainSelector: nil, UsdPerToken: nil, LinkTokenInstrumentId: linkTokenID, PriceUpdaters: input.FeeQuoterConfig.Template.PriceUpdaters, } deployFeeQuoterReport, err := operations.ExecuteOperation(b, factoryops.DeployFeeQuoter, deps, newChoiceInput(factoryRawInstanceAddress, factorybindings.DeployFeeQuoter{Contract: feeQuoterTemplate}, input.ProposalDriven)) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy FeeQuoter from factory: %w", err) } proposalOutputs = appendExerciseOutput(proposalOutputs, deployFeeQuoterReport.Output, input.ProposalDriven) feeQuoterRawInstanceAddress := feeQuoterInstanceID.RawInstanceAddress(ccipOwnerParty) addresses = append(addresses, newAddressRef(deps.ChainSelector(), feeQuoterRawInstanceAddress, fee_quoter.ContractType, fee_quoter.Version, "")) var ccvOwnerParty types.PARTY if len(input.CommitteeVerifiers) > 0 { ccvOwnerParty, err = requireCCVOwnerParty(input) if err != nil { return sequences.OnChainOutput{}, err } } for i, committeeVerifierParams := range input.CommitteeVerifiers { qualifier := committeeVerifierParams.Qualifier committeeVerifierOwner := ccvOwnerParty committeeVerifierInstanceID, err := ensureInstanceID(committeeVerifierParams.Template.InstanceId, "committeeverifier") if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to ensure CommitteeVerifier #%d instance ID: %w", i, err) } committeeVerifierTemplate := committeeverifier.CommitteeVerifier{ InstanceId: types.TEXT(committeeVerifierInstanceID), Owner: committeeVerifierOwner, CcipOwner: ccipOwnerParty, VersionTag: committeeVerifierParams.Template.VersionTag, AllowListAdmin: committeeVerifierParams.Template.AllowListAdmin, MessageSentObservers: committeeVerifierParams.Template.MessageSentObservers, StorageLocations: committeeVerifierParams.Template.StorageLocations, StorageLocationsAdmin: committeeVerifierParams.Template.StorageLocationsAdmin, PendingStorageLocationsAdmin: committeeVerifierParams.Template.PendingStorageLocationsAdmin, RemoteChainConfigs: committeeVerifierParams.Template.RemoteChainConfigs, SignerConfigs: committeeVerifierParams.Template.SignerConfigs, Deps: committeeverifier.CommitteeVerifierDeps{ RmnRemote: rmnRemoteRawInstanceAddress.Binding(), }, } deployCommitteeVerifierReport, err := operations.ExecuteOperation(b, factoryops.DeployCommitteeVerifier, deps, newChoiceInput(factoryRawInstanceAddress, factorybindings.DeployCommitteeVerifier{Contract: committeeVerifierTemplate}, input.ProposalDriven)) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy CommitteeVerifier #%d from factory: %w", i, err) } proposalOutputs = appendExerciseOutput(proposalOutputs, deployCommitteeVerifierReport.Output, input.ProposalDriven) committeeVerifierRawInstanceAddress := committeeVerifierInstanceID.RawInstanceAddress(committeeVerifierOwner) addresses = append(addresses, newAddressRef(deps.ChainSelector(), committeeVerifierRawInstanceAddress, committee_verifier.ContractType, committee_verifier.Version, qualifier)) } offRampInstanceID, err := ensureInstanceID("", "offramp") if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to ensure OffRamp instance ID: %w", err) } offRampTemplate := ccipruntime.OffRamp{ InstanceId: types.TEXT(offRampInstanceID), CcipOwner: ccipOwnerParty, Deps: ccipruntime.OffRampDeps{ GlobalConfig: globalConfigRawInstanceAddress.Binding(), RmnRemote: rmnRemoteRawInstanceAddress.Binding(), TokenAdminRegistry: tokenAdminRegistryRawInstanceAddress.Binding(), }, } deployOffRampReport, err := operations.ExecuteOperation(b, factoryops.DeployOffRamp, deps, newChoiceInput(factoryRawInstanceAddress, factorybindings.DeployOffRamp{Contract: offRampTemplate}, input.ProposalDriven)) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy OffRamp from factory: %w", err) } proposalOutputs = appendExerciseOutput(proposalOutputs, deployOffRampReport.Output, input.ProposalDriven) offRampRawInstanceAddress := offRampInstanceID.RawInstanceAddress(ccipOwnerParty) addresses = append(addresses, newAddressRef(deps.ChainSelector(), offRampRawInstanceAddress, offramp.ContractType, offramp.Version, "")) onRampInstanceID, err := ensureInstanceID("", "onramp") if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to ensure OnRamp instance ID: %w", err) } onRampTemplate := ccipruntime.OnRamp{ InstanceId: types.TEXT(onRampInstanceID), CcipOwner: ccipOwnerParty, MaxUSDCentsPerMsg: types.NUMERIC("100000000"), Deps: ccipruntime.OnRampDeps{ GlobalConfig: globalConfigRawInstanceAddress.Binding(), RmnRemote: rmnRemoteRawInstanceAddress.Binding(), TokenAdminRegistry: tokenAdminRegistryRawInstanceAddress.Binding(), FeeQuoter: feeQuoterRawInstanceAddress.Binding(), }, } deployOnRampReport, err := operations.ExecuteOperation(b, factoryops.DeployOnRamp, deps, newChoiceInput(factoryRawInstanceAddress, factorybindings.DeployOnRamp{Contract: onRampTemplate}, input.ProposalDriven)) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy OnRamp from factory: %w", err) } proposalOutputs = appendExerciseOutput(proposalOutputs, deployOnRampReport.Output, input.ProposalDriven) onRampRawInstanceAddress := onRampInstanceID.RawInstanceAddress(ccipOwnerParty) addresses = append(addresses, newAddressRef(deps.ChainSelector(), onRampRawInstanceAddress, onramp.ContractType, onramp.Version, "")) perPartyRouterFactoryInstanceID, err := ensureInstanceID("", "perpartyrouterfactory") if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to ensure PerPartyRouterFactory instance ID: %w", err) } perPartyRouterFactoryTemplate := ccipruntime.PerPartyRouterFactory{ InstanceId: types.TEXT(perPartyRouterFactoryInstanceID), CcipOwner: ccipOwnerParty, Deps: ccipruntime.PerPartyRouterDeps{ OnRamp: onRampRawInstanceAddress.Binding(), OffRamp: offRampRawInstanceAddress.Binding(), GlobalConfig: globalConfigRawInstanceAddress.Binding(), TokenAdminRegistry: tokenAdminRegistryRawInstanceAddress.Binding(), FeeQuoter: feeQuoterRawInstanceAddress.Binding(), RmnRemote: rmnRemoteRawInstanceAddress.Binding(), }, RegisteredRouters: nil, } deployPerPartyRouterFactoryReport, err := operations.ExecuteOperation(b, factoryops.DeployPerPartyRouterFactory, deps, newChoiceInput(factoryRawInstanceAddress, factorybindings.DeployPerPartyRouterFactory{Contract: perPartyRouterFactoryTemplate}, input.ProposalDriven)) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy PerPartyRouterFactory from factory: %w", err) } proposalOutputs = appendExerciseOutput(proposalOutputs, deployPerPartyRouterFactoryReport.Output, input.ProposalDriven) perPartyRouterFactoryRawInstanceAddress := perPartyRouterFactoryInstanceID.RawInstanceAddress(ccipOwnerParty) addresses = append(addresses, newAddressRef(deps.ChainSelector(), perPartyRouterFactoryRawInstanceAddress, per_party_router_factory.ContractType, per_party_router_factory.Version, "")) for i, params := range input.Executors { executorInstanceID, err := ensureInstanceID(params.Template.InstanceId, "executor") if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to ensure Executor #%d instance ID: %w", i, err) } executorTemplate := params.Template executorTemplate.InstanceId = types.TEXT(executorInstanceID) deployExecutorReport, err := operations.ExecuteOperation(b, factoryops.DeployExecutor, deps, newChoiceInput(factoryRawInstanceAddress, factorybindings.DeployExecutor{ Contract: executorTemplate, }, input.ProposalDriven)) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to deploy Executor #%d from factory: %w", i, err) } proposalOutputs = appendExerciseOutput(proposalOutputs, deployExecutorReport.Output, input.ProposalDriven) executorRawInstanceAddress := executorInstanceID.RawInstanceAddress(params.Template.Owner) addresses = append(addresses, newAddressRef(deps.ChainSelector(), executorRawInstanceAddress, executor.ContractType, executor.Version, params.Qualifier)) } out := sequences.OnChainOutput{Addresses: addresses} if input.ProposalDriven { batchOp, err := contract.NewBatchOperationFromExercises(proposalOutputs) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to build proposal batch for factory deploys: %w", err) } if len(batchOp.Transactions) > 0 { out.BatchOps = []mcms_types.BatchOperation{batchOp} } } return out, nil }, )
DeployChainContractsFromFactory is the factory-backed Canton deploy path. It assumes CCIPFactory has already been bootstrapped and targets that existing factory for all core CCIP contract deployments.
var DeployLinkTokenFromFactory = operations.NewSequence( "canton/ccip/deploy_link_token_from_factory", semver.MustParse("2.0.0"), "Deploys LinkRegistry on Canton through CCIPFactory", func(b operations.Bundle, deps canton.Chain, input DeployLinkTokenFromFactoryParams) (sequences.OnChainOutput, error) { if input.CCIPOwnerParty == "" { return sequences.OnChainOutput{}, fmt.Errorf("CCIPOwnerParty is required") } ccipOwnerParty := types.PARTY(input.CCIPOwnerParty) factoryRaw, err := rawInstanceAddressFromAddressRef(input.FactoryAddressRef) if err != nil { return sequences.OnChainOutput{}, err } instrumentID := input.InstrumentID if instrumentID.Admin == "" { instrumentID = splice_api_token_holding_v1.InstrumentId{ Admin: ccipOwnerParty, Id: types.TEXT(defaultCantonLinkTokenInstrumentID), } } if instrumentID.Admin != ccipOwnerParty { return sequences.OnChainOutput{}, fmt.Errorf("instrument admin must match ccipOwnerParty") } linkInstanceID, err := ensureInstanceID(input.LinkTokenInstanceID, "link-registry") if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("link token instance ID: %w", err) } deployReport, err := operations.ExecuteOperation(b, factoryops.DeployLinkToken, deps, newChoiceInput(factoryRaw, factorybindings.DeployLinkToken{ Contract: link.LinkRegistry{ RegistryAdmin: ccipOwnerParty, RegistryInstrumentId: instrumentID, InstanceId: types.TEXT(linkInstanceID), RegistryMeta: splice_api_token_metadata_v1.Metadata{}, }, }, input.ProposalDriven)) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("deploy LinkRegistry from factory: %w", err) } linkRawAddr := linkInstanceID.RawInstanceAddress(ccipOwnerParty) tokenEncodedAddress := contracts.EncodeInstrumentID(instrumentID).Hex() qualifier := stringsTrimOrDefault(input.TokenQualifier, "LINK") out := sequences.OnChainOutput{ Addresses: []datastore.AddressRef{ newAddressRef(deps.ChainSelector(), linkRawAddr, linkregistry.ContractType, linkregistry.Version, ""), { Address: tokenEncodedAddress, Labels: datastore.NewLabelSet( fmt.Sprintf("instrument-admin:%s", instrumentID.Admin), fmt.Sprintf("instrument-id:%s", instrumentID.Id), fmt.Sprintf("ccip-owner:%s", ccipOwnerParty), ), Type: datastore.ContractType("Token"), Version: linkregistry.Version, Qualifier: qualifier, ChainSelector: deps.ChainSelector(), }, }, } if input.ProposalDriven && !deployReport.Output.Executed() { batchOp, err := contract.NewBatchOperationFromExercises([]contract.ExerciseOutput{deployReport.Output}) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("build MCMS batch for link token deploy: %w", err) } if len(batchOp.Transactions) > 0 { out.BatchOps = []mcms_types.BatchOperation{batchOp} } } return out, nil }, )
DeployLinkTokenFromFactory emits an MCMS batch for DeployLinkToken when ProposalDriven is true.
var DeployRMNFromFactory = operations.NewSequence( "canton/ccip/deploy_rmn_from_factory", semver.MustParse("2.0.0"), "Deploys RMNRemote on Canton through the ccip CCIPFactory", func(b operations.Bundle, deps canton.Chain, input DeployChainContractsParams) (sequences.OnChainOutput, error) { ccipOwnerParty, err := requireCCIPOwnerParty(input) if err != nil { return sequences.OnChainOutput{}, err } factoryRawInstanceAddress, err := rawInstanceAddressFromAddressRef(input.FactoryAddressRef) if err != nil { return sequences.OnChainOutput{}, err } _, rmnAddressRef, proposalOutputs, err := deployRMNRemoteFromFactory( b, deps, input, factoryRawInstanceAddress, ccipOwnerParty, ) if err != nil { return sequences.OnChainOutput{}, err } out := sequences.OnChainOutput{Addresses: []datastore.AddressRef{*rmnAddressRef}} if input.ProposalDriven { batchOp, err := contract.NewBatchOperationFromExercises(proposalOutputs) if err != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to build RMN proposal batch: %w", err) } if len(batchOp.Transactions) > 0 { out.BatchOps = []mcms_types.BatchOperation{batchOp} } } return out, nil }, )
DeployRMNFromFactory deploys RMNRemote via the rmn-qualified CCIPFactory.
var DeployTokenPoolForToken = operations.NewSequence( "canton/token-adapter/deploy-token-pool-for-token", semver.MustParse("2.0.0"), "Deploys a Canton token pool and returns both the canonical and logical datastore refs", func(b operations.Bundle, chains chain.BlockChains, input tokenadapters.DeployTokenPoolInput) (ccipsequences.OnChainOutput, error) { if input.TokenPoolVersion == nil { return ccipsequences.OnChainOutput{}, fmt.Errorf("TokenPoolVersion is required") } if input.ExistingDataStore == nil { return ccipsequences.OnChainOutput{}, fmt.Errorf("existing datastore is required") } logicalPoolType, err := resolveCantonTokenPoolType(input.PoolType) if err != nil { return ccipsequences.OnChainOutput{}, err } qualifier := strings.TrimSpace(input.TokenPoolQualifier) if qualifier == "" { return ccipsequences.OnChainOutput{}, fmt.Errorf("token pool qualifier is required") } if input.TokenRef == nil { return ccipsequences.OnChainOutput{}, fmt.Errorf("tokenRef is required and must include instrument labels") } instrumentID, _, err := parseInstrumentIDFromTokenRefLabels(*input.TokenRef) if err != nil { return ccipsequences.OnChainOutput{}, err } matches := input.ExistingDataStore.Addresses().Filter( datastore.AddressRefByType(logicalPoolType), datastore.AddressRefByChainSelector(input.ChainSelector), datastore.AddressRefByQualifier(qualifier), datastore.AddressRefByVersion(input.TokenPoolVersion), ) if len(matches) > 1 { return ccipsequences.OnChainOutput{}, fmt.Errorf("multiple Canton token pools found with qualifier %q", qualifier) } if len(matches) == 1 { b.Logger.Infof("Canton token pool already deployed at %s", matches[0].Address) return ccipsequences.OnChainOutput{}, nil } cantonChain, ok := chains.CantonChains()[input.ChainSelector] if !ok || len(cantonChain.Participants) == 0 { return ccipsequences.OnChainOutput{}, fmt.Errorf("canton chain with selector %d not found", input.ChainSelector) } participant := cantonChain.Participants[0] mcmsEnabled := len(participant.ReadAsPartyIDs) > 0 var batchOps []mcms_types.BatchOperation var proposalOutputs []contract.ExerciseOutput factoryRefs := input.ExistingDataStore.Addresses().Filter( datastore.AddressRefByChainSelector(input.ChainSelector), datastore.AddressRefByType(datastore.ContractType(factoryops.ContractType)), ) factoryRef, err := dsutils.FactoryAddressRefFromRefs(input.ChainSelector, dsutils.QualifierCCIP, factoryRefs) if err != nil { return ccipsequences.OnChainOutput{}, err } factoryRaw, err := rawInstanceAddressFromAddressRef(factoryRef) if err != nil { return ccipsequences.OnChainOutput{}, fmt.Errorf("resolve CCIPFactory raw address: %w", err) } resolveRefAndRaw := func(name string, contractType datastore.ContractType, version *semver.Version) (datastore.AddressRef, contracts.RawInstanceAddress, error) { ref, err := input.ExistingDataStore.Addresses().Get(datastore.NewAddressRefKey( input.ChainSelector, contractType, version, "", )) if err != nil { return datastore.AddressRef{}, "", fmt.Errorf("resolve %s: %w", name, err) } raw, err := dsutils.GetRawInstanceAddressFromAddressRef(ref) if err != nil { return datastore.AddressRef{}, "", fmt.Errorf("resolve %s raw address: %w", name, err) } return ref, raw, nil } tokenAdminRegistryRef, tokenAdminRegistryRaw, err := resolveRefAndRaw("token admin registry", datastore.ContractType(token_admin_registry.ContractType), token_admin_registry.Version) if err != nil { return ccipsequences.OnChainOutput{}, err } _, rmnRemoteRaw, err := resolveRefAndRaw("rmn remote", datastore.ContractType(rmn_remote.ContractType), rmn_remote.Version) if err != nil { return ccipsequences.OnChainOutput{}, err } _, feeQuoterRaw, err := resolveRefAndRaw("fee quoter", datastore.ContractType(fee_quoter.ContractType), fee_quoter.Version) if err != nil { return ccipsequences.OnChainOutput{}, err } ccipOwnerParty, poolOwnerParty, err := resolveTokenPoolParties(input, participant) if err != nil { return ccipsequences.OnChainOutput{}, err } ccipOwner := types.PARTY(ccipOwnerParty) poolOwner := types.PARTY(poolOwnerParty) poolReceiveContext := splice_api_token_metadata_v1.ChoiceContext{ Values: map[string]splice_api_token_metadata_v1.AnyValue{}, } var ( rawPoolAddr contracts.RawInstanceAddress canonicalRef datastore.AddressRef ) switch logicalPoolType { case lockReleasePoolType: poolInstanceID := contracts.InstanceID(fmt.Sprintf("lockreleasetokenpool-%s", qualifier)) deployReport, err := operations.ExecuteOperation(b, factoryops.DeployLockReleaseTokenPool, cantonChain, newChoiceInput(factoryRaw, factorybindings.DeployLockReleaseTokenPool{ Contract: lockreleasetokenpool.LockReleaseTokenPool{ InstanceId: types.TEXT(poolInstanceID), CcipOwner: ccipOwner, PoolOwner: poolOwner, InstrumentId: instrumentID, Decimals: types.INT64(10), RemoteChainConfigs: map[types.NUMERIC]lockreleasetokenpool.RemoteChainConfig{}, TokenTransferFeeConfigs: map[types.NUMERIC]lockreleasetokenpool.TokenTransferFeeConfig{}, PoolReceiveContext: poolReceiveContext, TransferTimeout: lockreleasetokenpool.TransferTimeout{ RelativeHours: new(types.INT64(24)), }, Deps: lockreleasetokenpool.LockReleaseTokenPoolDeps{ TokenAdminRegistry: tokenAdminRegistryRaw.Binding(), RmnRemote: rmnRemoteRaw.Binding(), FeeQuoter: feeQuoterRaw.Binding(), }, }, }, mcmsEnabled)) if err != nil { return ccipsequences.OnChainOutput{}, fmt.Errorf("deploy Canton lock/release pool from factory: %w", err) } if mcmsEnabled && !deployReport.Output.Executed() { proposalOutputs = append(proposalOutputs, deployReport.Output) } rawPoolAddr = poolInstanceID.RawInstanceAddress(poolOwner) canonicalRef = newAddressRef(input.ChainSelector, rawPoolAddr, lock_release_token_pool.ContractType, lock_release_token_pool.Version, qualifier) case burnMintPoolType: poolInstanceID := contracts.InstanceID(fmt.Sprintf("burnminttokenpool-%s", qualifier)) deployReport, err := operations.ExecuteOperation(b, factoryops.DeployBurnMintTokenPool, cantonChain, newChoiceInput(factoryRaw, factorybindings.DeployBurnMintTokenPool{ Contract: burnminttokenpool.BurnMintTokenPool{ InstanceId: types.TEXT(poolInstanceID), CcipOwner: ccipOwner, PoolOwner: poolOwner, InstrumentId: instrumentID, Decimals: types.INT64(10), RemoteChainConfigs: map[types.NUMERIC]burnminttokenpool.RemoteChainConfig{}, TokenTransferFeeConfigs: map[types.NUMERIC]burnminttokenpool.TokenTransferFeeConfig{}, PoolReceiveContext: poolReceiveContext, TransferTimeout: burnminttokenpool.TransferTimeout{ RelativeHours: new(types.INT64(24)), }, Deps: burnminttokenpool.BurnMintTokenPoolDeps{ TokenAdminRegistry: tokenAdminRegistryRaw.Binding(), RmnRemote: rmnRemoteRaw.Binding(), FeeQuoter: feeQuoterRaw.Binding(), }, }, }, mcmsEnabled)) if err != nil { return ccipsequences.OnChainOutput{}, fmt.Errorf("deploy Canton burn/mint pool from factory: %w", err) } if mcmsEnabled && !deployReport.Output.Executed() { proposalOutputs = append(proposalOutputs, deployReport.Output) } rawPoolAddr = poolInstanceID.RawInstanceAddress(poolOwner) canonicalRef = newAddressRef(input.ChainSelector, rawPoolAddr, burn_mint_token_pool.ContractType, burn_mint_token_pool.Version, qualifier) default: return ccipsequences.OnChainOutput{}, fmt.Errorf("unsupported Canton token pool type %q", logicalPoolType) } regOut, err := operations.ExecuteSequence(b, RegisterTokenPool, cantonChain, RegisterTokenPoolInput{ TokenAdminRegistryInstanceAddress: contracts.HexToInstanceAddress(tokenAdminRegistryRef.Address), TokenAdminRegistryRawInstanceAddress: tokenAdminRegistryRaw, InstrumentId: instrumentID, PoolInstanceID: rawPoolAddr.InstanceID(), CcipParty: ccipOwnerParty, PoolOwnerParty: poolOwnerParty, PoolAdminParty: ccipOwnerParty, }) if err != nil { return ccipsequences.OnChainOutput{}, fmt.Errorf("register Canton token pool: %w", err) } batchOps = append(batchOps, regOut.Output.BatchOps...) logicalRef := datastore.AddressRef{ Address: canonicalRef.Address, Labels: canonicalRef.Labels, Type: logicalPoolType, Version: input.TokenPoolVersion, Qualifier: qualifier, ChainSelector: input.ChainSelector, } tokenAddress := strings.TrimSpace(input.TokenRef.Address) if tokenAddress == "" { return ccipsequences.OnChainOutput{}, fmt.Errorf("tokenRef.address is required") } tokenRef := datastore.AddressRef{ Address: tokenAddress, Type: datastore.ContractType("Token"), Version: input.TokenPoolVersion, Qualifier: qualifier, ChainSelector: input.ChainSelector, } if mcmsEnabled && len(proposalOutputs) > 0 { batchOp, err := contract.NewBatchOperationFromExercises(proposalOutputs) if err != nil { return ccipsequences.OnChainOutput{}, fmt.Errorf("build MCMS batch for token pool deployment: %w", err) } if len(batchOp.Transactions) > 0 { batchOps = append(batchOps, batchOp) } } return ccipsequences.OnChainOutput{ Addresses: []datastore.AddressRef{ logicalRef, canonicalRef, tokenRef, }, BatchOps: batchOps, }, nil }, )
var HardenCantonInboundLane = operations.NewSequence( "HardenCantonInboundLane", semver.MustParse("2.0.0"), "Applies Canton inbound lane hardening (fee quoter prices + invalid default inbound CCV + optional outbound dest fees)", hardenCantonInboundLane, )
var RegisterNativeFeeTokenInTAR = operations.NewSequence( "canton/ccip/register_native_fee_token_in_tar", semver.MustParse("2.0.0"), "Registers the native Canton fee token in TokenAdminRegistry (ProposeAdministrator, AcceptAdminRole)", registerNativeFeeTokenInTAR, )
var RegisterTokenPool = operations.NewSequence( "canton/ccip/register_token_pool", semver.MustParse("2.0.0"), "Registers a token pool with the TokenAdminRegistry (ProposeAdministrator, AcceptAdminRole, SetPool)", registerTokenPool, )
var SetTokenPoolRateLimits = operations.NewSequence( "canton/token-adapter/set-token-pool-rate-limits", semver.MustParse("2.0.0"), "Updates Canton lock/release pool rate limiter config for a remote chain", func(b operations.Bundle, chains chain.BlockChains, input tokenadapters.TPRLRemotes) (ccipsequences.OnChainOutput, error) { _ = b _ = chains _ = input return ccipsequences.OnChainOutput{}, fmt.Errorf( "SetTokenPoolRateLimits is disabled: initial Canton rate limiter setup happens during ConfigureTokenForTransfers", ) }, )
Canton wires rate limiters during initial remote-chain setup in ConfigureTokenForTransfers via ApplyChainUpdates, so this follow-up sequence is intentionally unused.
Functions ¶
func CantonTokenPoolDecimalsFromDataStore ¶
func CantonTokenPoolDecimalsFromDataStore( ds datastore.DataStore, chainSelector uint64, poolRef datastore.AddressRef, ) (uint8, error)
CantonTokenPoolDecimalsFromDataStore resolves pool decimals from address_refs when the pool contract is not yet active on the Canton ledger (e.g. deploy MCMS still pending).
func IsCantonPoolNotOnLedgerErr ¶
IsCantonPoolNotOnLedgerErr reports whether err is the standard "pool not yet deployed" ledger lookup failure.
Types ¶
type CantonOutboundDestFeeInput ¶
type CantonOutboundDestFeeInput struct {
Source *lanes.ChainDefinition
Dest *lanes.ChainDefinition
}
CantonOutboundDestFeeInput carries resolved lane legs for Canton→remote outbound dest fee hardening.
type CommitteeVerifierParams ¶
type CommitteeVerifierParams struct {
// Qualifier distinguishes between multiple deployments of the committee verifier on the same chain.
Qualifier string
Template committeeverifier.CommitteeVerifier
}
type ConfigureCommitteeVerifierAsDestInput ¶
type ConfigureCommitteeVerifierAsDestInput struct {
ChainSelector uint64
MCMSEnabled bool
lanes.CommitteeVerifierConfig[datastore.AddressRef]
}
type ConfigureCommitteeVerifierAsSourceInput ¶
type ConfigureCommitteeVerifierAsSourceInput struct {
ChainSelector uint64
MCMSEnabled bool
lanes.CommitteeVerifierConfig[datastore.AddressRef]
}
type ConfigureLaneLegInput ¶
type ConfigureLaneLegInput struct {
Lane lanes.UpdateLanesInput
DataStore datastore.DataStore
}
ConfigureLaneLegInput carries the lane update plus a datastore for fee quoter resolution.
type DeployChainContractsParams ¶
type DeployChainContractsParams struct {
// OwnerParty is the Canton instance owner (decentralized party); used for instanceId@owner addresses.
OwnerParty string
// CCIPOwnerParty is the operational ccipOwner on product templates (lanes, admin roles, etc.).
CCIPOwnerParty string
// CCVOwnerParty is the CommitteeVerifier signatory owner (ccvOwner); distinct from CCIPOwnerParty in dual-MCMS deploys.
CCVOwnerParty string
// RMNOwnerParty is the RMNRemote signatory owner (rmnOwner); distinct from CCIPOwnerParty in triple-MCMS deploys.
RMNOwnerParty string
CommitteeVerifiers []CommitteeVerifierParams
Executors []ExecutorParams
GlobalConfig GlobalConfigParams
RMNRemote RMNRemoteParams
FeeQuoterConfig FeeQuoterParams
// FactoryAddressRef is the ccip-qualified factory for core CCIP deploys.
FactoryAddressRef datastore.AddressRef
// RMNFactoryAddressRef is the rmn-qualified factory; required when DevenvBundledDeploy is true.
RMNFactoryAddressRef datastore.AddressRef
// ProposalDriven enables MCMS proposal generation for factory-backed deploys.
ProposalDriven bool
// RmnRemoteRawInstanceAddress is required for production split deploy paths.
RmnRemoteRawInstanceAddress contracts.RawInstanceAddress
// DevenvBundledDeploy runs RMN+CV+core in one sequence (devenv adapter only). Mutually exclusive with RmnRemoteRawInstanceAddress.
DevenvBundledDeploy bool
// The InstrumentId of the native token
NativeInstrumentId splice_api_token_holding_v1.InstrumentId
}
type DeployLinkTokenFromFactoryParams ¶
type DeployLinkTokenFromFactoryParams struct {
CCIPOwnerParty string `json:"ccipOwnerParty,omitempty" yaml:"ccipOwnerParty,omitempty"`
FactoryAddressRef datastore.AddressRef
ProposalDriven bool `json:"proposalDriven,omitempty" yaml:"proposalDriven,omitempty"`
LinkTokenInstanceID types.TEXT `json:"linkTokenInstanceId,omitempty" yaml:"linkTokenInstanceId,omitempty"`
InstrumentID splice_api_token_holding_v1.InstrumentId `json:"instrumentId,omitzero" yaml:"instrumentId,omitempty"`
TokenQualifier string `json:"tokenQualifier,omitempty" yaml:"tokenQualifier,omitempty"`
}
DeployLinkTokenFromFactoryParams deploys Canton LinkRegistry via the ccip-qualified CCIPFactory.
type ExecutorParams ¶
type ExecutorParams struct {
Qualifier string
Template executorBinding.Executor
}
type FeeQuoterParams ¶
type GlobalConfigParams ¶
type GlobalConfigParams struct {
Template core.GlobalConfig
}
type HardenCantonInboundLaneInput ¶
type HardenCantonInboundLaneInput struct {
CantonChainSelector uint64
RemoteSourceChainSelector uint64
GlobalConfigRef datastore.AddressRef
FeeQuoterRef datastore.AddressRef
DefaultInboundCCVs []datastore.AddressRef
RemoteOnRampAddress gethcommon.Address
TokenPrices map[string]*big.Int
USDPerUnitGas *big.Int
OutboundDestFees *CantonOutboundDestFeeInput
}
HardenCantonInboundLaneInput carries pre-resolved contract refs and lane hardening params. Emits FeeQuoter::UpdatePrices + GlobalConfig::ApplySourceChainConfigUpdates, and optionally Canton→remote outbound dest fee ops (GlobalConfig + FeeQuoter dest config).
type RMNRemoteParams ¶
RMNRemoteParams configures RMNRemote deploy. Set Template.CustomObservers (typically ccvOwner) so NOP verifiers can poll curse state via sourcereader.
type RegisterNativeFeeTokenInTARInput ¶
type RegisterNativeFeeTokenInTARInput struct {
TokenAdminRegistryInstanceAddress contracts.InstanceAddress
TokenAdminRegistryRawInstanceAddress contracts.RawInstanceAddress
InstrumentId splice_api_token_holding_v1.InstrumentId
CcipOwnerParty string
TokenQualifier string
ChainSelector uint64
CcipParticipantIndex int `json:"ccipParticipantIndex,omitempty"`
ProposalDriven bool
}
RegisterNativeFeeTokenInTARInput registers the Canton native fee token (typically Amulet) in the TokenAdminRegistry by creating a TokenConfig via ProposeAdministrator + AcceptAdminRole. No SetPool is performed — fee tokens are not CCIP transfer tokens.
type RegisterTokenPoolInput ¶
type RegisterTokenPoolInput struct {
// TokenAdminRegistryInstanceAddress is the instance address of the TokenAdminRegistry contract.
TokenAdminRegistryInstanceAddress contracts.InstanceAddress
// TokenAdminRegistryRawInstanceAddress is the raw instance address label for MCMS proposals.
TokenAdminRegistryRawInstanceAddress contracts.RawInstanceAddress
// InstrumentId identifies the token (admin party + token id).
InstrumentId splice_api_token_holding_v1.InstrumentId
// PoolInstanceID is the instance ID of the token pool.
PoolInstanceID string
// CcipParty is the CCIP owner party (registry owner; acts on ProposeAdministrator).
CcipParty string
// PoolOwnerParty is the token pool contract owner (recorded in PoolRegistration only).
PoolOwnerParty string
// PoolAdminParty is the TokenConfig admin (proposed/accepts admin role; acts on SetPool).
PoolAdminParty string
// CcipParticipantIndex selects which participant submits TAR registration choices.
// Zero value defaults to the first participant.
CcipParticipantIndex int `json:"ccipParticipantIndex,omitempty"`
}
RegisterTokenPoolInput is the input for registering a token pool with the TokenAdminRegistry.