sequences

package
v0.0.0-...-346157b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 27, 2026 License: MIT Imports: 53 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
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([]ccvs.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, ccvs.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[ccvs.ApplySignatureConfigs]{
				InstanceAddress:    address,
				RawInstanceAddress: raw.String(),
				MCMSEnabled:        input.MCMSEnabled,
				Args: ccvs.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
	},
)
View Source
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([]ccvs.RemoteChainConfigArgs, 0, len(input.RemoteChains))
		allowListArgs := make([]ccvs.AllowListConfigArgs, 0, len(input.RemoteChains))
		for remoteSelector, remoteConfig := range input.RemoteChains {
			remoteChainConfigArgs = append(remoteChainConfigArgs, ccvs.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, ccvs.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[ccvs.ApplyRemoteChainConfigUpdates]{
				InstanceAddress:    address,
				RawInstanceAddress: raw.String(),
				MCMSEnabled:        input.MCMSEnabled,
				Args: ccvs.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[ccvs.ApplyAllowListUpdates]{
				InstanceAddress:    address,
				RawInstanceAddress: raw.String(),
				MCMSEnabled:        input.MCMSEnabled,
				Args: ccvs.ApplyAllowListUpdates{
					AllowListConfigArgsItems: allowListArgs,
				},
			})
			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
	},
)
View Source
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 source. 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([]mcms.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([]mcms.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[common.ApplySourceChainConfigUpdates]{
			InstanceAddress:    globalConfigRaw.InstanceAddress(),
			RawInstanceAddress: globalConfigRaw.String(),
			MCMSEnabled:        mcmsEnabled,
			Args: common.ApplySourceChainConfigUpdates{
				SourceChainConfigUpdates: []common.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
	},
)
View Source
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})
	},
)
View Source
var ConfigureLaneLegAsSourceWithInput = operations.NewSequence(
	"CantonConfigureLaneLegAsSourceWithInput",
	semver.MustParse("2.0.0"),
	"Configures a lane leg as source on CCIP 2.0.0",
	configureLaneLegAsSource,
)
View Source
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, logicalPoolType, poolAddress)
		if err != nil {
			return ccipsequences.OnChainOutput{}, err
		}

		registryRef, err := input.ExistingDataStore.Addresses().Get(datastore.NewAddressRefKey(
			input.ChainSelector,
			datastore.ContractType(token_admin_registry.ContractType),
			token_admin_registry.Version,
			"",
		))
		if err != nil {
			return ccipsequences.OnChainOutput{}, fmt.Errorf("resolve token admin registry: %w", err)
		}
		tarRaw, err := dsutils.GetRawInstanceAddressFromAddressRef(registryRef)
		if err != nil {
			return ccipsequences.OnChainOutput{}, fmt.Errorf("resolve token admin registry raw address: %w", err)
		}
		regOut, err := operations.ExecuteSequence(b, RegisterTokenPool, cantonChain, RegisterTokenPoolInput{
			TokenAdminRegistryInstanceAddress:    contracts.HexToInstanceAddress(registryRef.Address),
			TokenAdminRegistryRawInstanceAddress: tarRaw,
			InstrumentId:                         parsedPool.InstrumentId,
			PoolInstanceID:                       string(parsedPool.InstanceId),
			CcipParty:                            string(parsedPool.CcipOwner),
			PoolOwnerParty:                       string(parsedPool.PoolOwner),
		})
		if err != nil {
			return ccipsequences.OnChainOutput{}, fmt.Errorf("register token pool with token admin registry: %w", err)
		}
		batchOps = append(batchOps, regOut.Output.BatchOps...)

		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,
				common.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,
				common.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,
				common.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.BytesToAddress(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
	},
)
View Source
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.

View Source
var DeployCCVFromFactory = operations.NewSequence(
	"canton/ccip/deploy_ccv_from_factory",
	semver.MustParse("0.1.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 := requireOwnerParties(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 := ccvsbindings.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: ccvsbindings.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.

View Source
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
		}

		deployRMNRemoteReport, err := operations.ExecuteOperation(b, rmn_remote.Deploy, deps, contract.DeployInput[rmn.RMNRemote]{
			Template: rmn.RMNRemote{
				RmnOwner:        rmnOwnerParty,
				CcipOwner:       types.PARTY(input.CCIPOwnerParty),
				CursedSubjects:  input.RMNRemote.Template.CursedSubjects,
				CustomObservers: input.RMNRemote.Template.CustomObservers,
			},
			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[common.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[tokenadminregistry.TokenAdminRegistry]{
			Template: tokenadminregistry.TokenAdminRegistry{
				Owner:      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[feequoter.FeeQuoter]{
			Template: feequoter.FeeQuoter{
				Owner:                            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[feequoter.UpdatePrices]{
				InstanceAddress: feeQuoterRawInstanceAddress.InstanceAddress(),
				Args: feequoter.UpdatePrices{
					PriceUpdates: feequoter.PriceUpdates{
						TokenPriceUpdates: []feequoter.TokenPriceUpdate{
							{
								InstrumentId: input.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(),
				input.CCIPOwnerParty,
				input.NativeInstrumentId,
			)
			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[offrampBinding.OffRamp]{
			Template: offrampBinding.OffRamp{
				CcipOwner: types.PARTY(input.CCIPOwnerParty),
				Deps: offrampBinding.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[onrampBinding.OnRamp]{
			Template: onrampBinding.OnRamp{
				CcipOwner:         types.PARTY(input.CCIPOwnerParty),
				MaxUSDCentsPerMsg: types.NUMERIC("100000000"),
				Deps: onrampBinding.OnRampDeps{
					GlobalConfig:       globalConfigRawInstanceAddress.Binding(),
					RmnRemote:          rmnRemoteRawInstanceAddress.Binding(),
					TokenAdminRegistry: tokenAdminRegistryRawInstanceAddress.Binding(),
					FeeQuoter:          feeQuoterRawInstanceAddress.Binding(),
					CcvRegistry:        mcms.RawInstanceAddress{},
				},
			},
			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[perpartyrouter.PerPartyRouterFactory]{
			Template: perpartyrouter.PerPartyRouterFactory{
				CcipOwner: types.PARTY(input.CCIPOwnerParty),
				Deps: perpartyrouter.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[ccvs.CommitteeVerifier]{
				Template: ccvs.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: ccvs.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:  &params.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
	},
)
View Source
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

		ownerParty, ccipOwnerParty, err := requireOwnerParties(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 := common.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(ownerParty)
		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 := tokenadminregistry.TokenAdminRegistry{
			InstanceId: types.TEXT(tokenAdminRegistryInstanceID),
			Owner:      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(ownerParty)
		addresses = append(addresses, newAddressRef(deps.ChainSelector(), tokenAdminRegistryRawInstanceAddress, token_admin_registry.ContractType, token_admin_registry.Version, ""))

		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: ownerParty,
				Id:    types.TEXT("link-token"),
			}
		}
		feeQuoterTemplate := feequoter.FeeQuoter{
			InstanceId:                       types.TEXT(feeQuoterInstanceID),
			Owner:                            ownerParty,
			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(ownerParty)
		addresses = append(addresses, newAddressRef(deps.ChainSelector(), feeQuoterRawInstanceAddress, fee_quoter.ContractType, fee_quoter.Version, ""))

		var firstCommitteeVerifierBinding mcms.RawInstanceAddress
		if len(input.CommitteeVerifiers) == 0 {
			if input.CcvRegistryBinding.Unpack == "" {
				return sequences.OnChainOutput{}, fmt.Errorf("CcvRegistryBinding is required when CommitteeVerifiers is empty")
			}
			firstCommitteeVerifierBinding = input.CcvRegistryBinding
		}
		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 := ccvsbindings.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: ccvsbindings.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)
			if i == 0 {
				firstCommitteeVerifierBinding = committeeVerifierRawInstanceAddress.Binding()
			}
			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 := offrampBinding.OffRamp{
			InstanceId: types.TEXT(offRampInstanceID),
			CcipOwner:  ccipOwnerParty,
			Deps: offrampBinding.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(ownerParty)
		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 := onrampBinding.OnRamp{
			InstanceId:        types.TEXT(onRampInstanceID),
			CcipOwner:         ccipOwnerParty,
			MaxUSDCentsPerMsg: types.NUMERIC("100000000"),
			Deps: onrampBinding.OnRampDeps{
				GlobalConfig:       globalConfigRawInstanceAddress.Binding(),
				RmnRemote:          rmnRemoteRawInstanceAddress.Binding(),
				TokenAdminRegistry: tokenAdminRegistryRawInstanceAddress.Binding(),
				FeeQuoter:          feeQuoterRawInstanceAddress.Binding(),
				CcvRegistry:        firstCommitteeVerifierBinding,
			},
		}
		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(ownerParty)
		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 := perpartyrouter.PerPartyRouterFactory{
			InstanceId: types.TEXT(perPartyRouterFactoryInstanceID),
			CcipOwner:  ccipOwnerParty,
			Deps: perpartyrouter.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(ownerParty)
		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.

View Source
var DeployRMNFromFactory = operations.NewSequence(
	"canton/ccip/deploy_rmn_from_factory",
	semver.MustParse("0.1.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.

View Source
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

		if logicalPoolType == burnMintPoolType {
			return ccipsequences.OnChainOutput{}, fmt.Errorf(
				"burn/mint token pools must be deployed through CCIPFactory; factory does not yet expose DeployBurnMintTokenPool",
			)
		}

		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)
		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.TokenTransferFeeConfig2{},
				PoolReceiveContext: splice_api_token_metadata_v1.ChoiceContext{
					Values: map[string]splice_api_token_metadata_v1.AnyValue{},
				},
				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)

		regOut, err := operations.ExecuteSequence(b, RegisterTokenPool, cantonChain, RegisterTokenPoolInput{
			TokenAdminRegistryInstanceAddress:    contracts.HexToInstanceAddress(tokenAdminRegistryRef.Address),
			TokenAdminRegistryRawInstanceAddress: tokenAdminRegistryRaw,
			InstrumentId:                         instrumentID,
			PoolInstanceID:                       rawPoolAddr.InstanceID(),
			CcipParty:                            participant.PartyID,
			PoolOwnerParty:                       participant.PartyID,
		})
		if err != nil {
			return ccipsequences.OnChainOutput{}, fmt.Errorf("register Canton token pool: %w", err)
		}
		batchOps = append(batchOps, regOut.Output.BatchOps...)

		canonicalRef := newAddressRef(input.ChainSelector, rawPoolAddr, lock_release_token_pool.ContractType, lock_release_token_pool.Version, qualifier)
		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
	},
)
View Source
var RegisterTokenPool = operations.NewSequence(
	"canton/ccip/register_token_pool",
	semver.MustParse("1.0.0"),
	"Registers a token pool with the TokenAdminRegistry (ProposeAdministrator, AcceptAdminRole, SetPool)",
	registerTokenPool,
)
View Source
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

This section is empty.

Types

type CommitteeVerifierParams

type CommitteeVerifierParams struct {
	// Qualifier distinguishes between multiple deployments of the committee verifier on the same chain.
	Qualifier string
	Template  ccvs.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
	// CcvRegistryBinding is required for OnRamp deps when CommitteeVerifiers is empty (CCV deployed separately).
	CcvRegistryBinding mcms.RawInstanceAddress
	// 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 ExecutorParams

type ExecutorParams struct {
	Qualifier string
	Template  executorBinding.Executor
}

type FeeQuoterParams

type FeeQuoterParams struct {
	Template feequoter.FeeQuoter
	// The price of the native token to be set on the FeeQuoter.
	// If not-nil, native will be added as a fee token and the price will be set.
	USDPerNative *big.Int
}

type GlobalConfigParams

type GlobalConfigParams struct {
	Template common.GlobalConfig
}

type RMNRemoteParams

type RMNRemoteParams struct {
	Template rmn.RMNRemote
}

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 (acts on ProposeAdministrator).
	CcipParty string
	// PoolOwnerParty is the token pool owner party (acts on AcceptAdminRole and SetPool).
	PoolOwnerParty string
}

RegisterTokenPoolInput is the input for registering a token pool with the TokenAdminRegistry.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL