Skip to content

docs(canton): fix CCT prerequisites, BurnMintFactory coverage, and ApplyChainUpdates example - #4306

Open
SyedAsadKazmi wants to merge 3 commits into
mainfrom
docs/canton-cct-addresses-and-factory
Open

SyedAsadKazmi wants to merge 3 commits into
mainfrom
docs/canton-cct-addresses-and-factory

Conversation

@SyedAsadKazmi

Copy link
Copy Markdown
Collaborator
  • Prerequisites (all CCT guides): DAR bullets now link the contracts/dars/released folder, require upload and vetting (link to Upgradability), and add the CommitteeVerifier DAR required for executing incoming transfers.
  • BurnMint guide, factory coverage: new sections for custom tokens:
    • Pin the BurnMintFactory on the TAR via SetBurnMintFactory (LinkRegistry as the reference implementation)
    • Factory contract shape: top-level instanceId create argument required for EDS ACS indexing
    • Serving the factory from EDS: address vs url mode; testnet token-standard backend is https://api.utilities.digitalasset-staging.com (not a validator scan-proxy URL); url mode resolves registry instruments only
  • Both guides: full ApplyChainUpdates JSON example: remoteChainSelectorsToRemove + chainsToAdd (list of ChainUpdate records, each carrying its own remoteChainSelector), not the pool's remoteChainConfigs create field.
  • EDS concept page: fix dead lzrnd TAR address in the batch example (live: nbehb); add [factory].type row to the config reference.

@vercel

vercel Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
documentation Ready Ready Preview Oct 17, 2026 12:50am UTC

Request Review

@Giuliano-1

Copy link
Copy Markdown
Collaborator

@SyedAsadKazmi can we also be more specific in https://docs.chain.link/ccip/canton/concepts/manual-execution that the manual exec using the SDK the accept holding si implicit to the manual exec command

| `map key / instance_address` | Each pool keyed by instance address hex; map key **must** equal `instance_address`. |
| `type` | `burnMint` or `lockRelease`. |
| `pool_owner` | Pool owner party (should equal `instrumentId.admin`). |
| `[factory].type` | BurnMint pools only: `address` (EDS reads the factory from the ACS — needs `template_id`, `party`, `instance_address`) or `url` (DA registry resolves it — needs `token_standard_url`). See the [BurnMint guide](/ccip/canton/tutorials/cross-chain-tokens/burn-mint-token-pool#serve-the-factory-from-your-eds). |

@Giuliano-1 Giuliano-1 Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Maybe we can add an example config like this one I had shared with a customer (review it to make sure its good):

[server]
  host = "0.0.0.0"
  port = 8088

[node]
  url = "FILL THIS"
  max_retries = 10

[node.auth]
  type = 'clientCredentials'
  user_id = 'FILL THIS'
  # Keycloak realm only serves openid-configuration (no RFC 8414 oauth-authorization-server),
  # so use the explicit token endpoint instead of discovery.
  token_url = 'FILL THIS'
  client_id = 'FILL THIS'
  # client_secret is injected via CANTON_LEDGER_CLIENT_SECRET env var
  # (Vault -> ExternalSecret -> secretKeyRef). Do not set it here.

# ccip_api, ccv_api, and executor_api are not needed for the USD1 token pool use-case.
# token_pool_api is enabled (Phase 2) — BurnMintTokenPool is registered on the TAR.
[ccip_api]
  enabled = false

[ccv_api]
  enabled = false

[executor_api]
  enabled = false


[token_pool_api]
  enabled = true

  # instance_address is the Keccak256 hash of the raw instance address string "<pool_instance_id>@<pool_owner_party>"
  [token_pool_api.token_pools."FILLTHIS"]
    party_id         = "FILLTHIS"
    instance_address = "FILLTHIS"
    type             = "burnMint"
    pool_owner       = "FILLTHIS"

    # Factory resolution via DA's utility-registry backend.
    [token_pool_api.token_pools."FILLTHIS".factory]
      type               = "url"
      token_standard_url = "https://api.utilities.digitalasset.com" # mainnet one 
      # token_standard_auth is NOT set — DA's endpoint is public (security: [])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Also its not the DA registry that resolves it but our TP EDS that's resolving the Registry EDS. Unless I'm misunderstanding what you're saying, but its a bit confusing.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added the example, with three corrections verified against the EDS code: token_url doesn't exist (auth_url + RFC 8414 discovery is the supported path), there's no CANTON_LEDGER_CLIENT_SECRET env var (secrets go in a layered config_secrets.toml via CONFIG_FILE), and chain_selector is required.

Wording fixed too: the EDS is now the actor ("EDS calls the DA registry backend's getBurnMintFactory endpoint").

Refs: auth config, secrets pattern

- **Burn/mint authority** — `instrumentId.admin == poolOwner` (enforced by the BurnMint template and by the starter kit).
- **BurnMint token pool DAR** on your participant — [`ccip-burn-mint-token-pool-2.1.0.dar`](https://github.com/smartcontractkit/chainlink-canton/blob/main/contracts/dars/released/ccip-burn-mint-token-pool-v2-2.1.0.dar) (bundles its CCIP dependencies — the only DAR you upload).
- **BurnMint token pool DAR** uploaded **and vetted** on your participant — [`ccip-burn-mint-token-pool-2.1.0.dar`](https://github.com/smartcontractkit/chainlink-canton/blob/main/contracts/dars/released/ccip-burn-mint-token-pool-v2-2.1.0.dar) from the [`contracts/dars/released`](https://github.com/smartcontractkit/chainlink-canton/tree/main/contracts/dars/released) folder (bundles its CCIP dependencies — the only DAR you upload). Vet every released version you depend on — see [Upgradability](/ccip/canton/concepts/upgradability).
- To **execute** incoming transfers, the CommitteeVerifier DAR — [`ccip-committee-verifier-v2-2.0.0.dar`](https://github.com/smartcontractkit/chainlink-canton/blob/main/contracts/dars/released/ccip-committee-verifier-v2-2.0.0.dar) — uploaded and vetted on your participant as well.

@Giuliano-1 Giuliano-1 Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is also bundled within the releases. Should always just say upload the official release, your Canton node will automatically resolve the correct versions to vet.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

De-pinned the links, thanks!

Two corrections:

  1. The CCV package is not bundled in the pool DARs (PACKAGE_INFO.md shows it as a separate release), so the separate upload bullet stays.

  2. And dars.upload defaults to vetAllPackages = false (Canton docs), so the docs keep saying "uploaded and vetted" rather than promising automatic resolution.

BurnMint pools do not burn or mint instrument supply themselves — they call a **`BurnMintFactory`** (`Splice.Api.Token.BurnMintV1.BurnMintFactory`) recorded on the instrument's `TokenConfig`. The factory contract implements the actual burn (send) and mint (execute) operations against your token.

- **Registry instruments** (created via Digital Asset's [Registry utility](https://docs.digitalasset.com/registry/overview)) already have a factory — the registry resolves it automatically. No action needed.
- **Custom tokens** must deploy their own `BurnMintFactory` contract and pin it on the TAR via the `SetBurnMintFactory` choice. The reference implementation is [`LinkRegistry`](https://github.com/smartcontractkit/chainlink-canton/blob/main/contracts/link/daml/Link/Token.daml) (`#link:Link.Token:LinkRegistry`) — the factory backing LINK on Canton, which implements both `TransferFactory` and `BurnMintFactory`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Link token isn't currently a registry issued asset btw. That's still a tod this month by John.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good context. The docs never claimed LINK was registry-issued, so nothing to fix, but the wording is sharper now: custom tokens = "any instrument not created via the Registry utility," and LinkRegistry is described as a custom-token factory.

- [Starter kit setup](/ccip/canton/tutorials/source/prerequisites) for `cct:*` scripts (`.env`, `canton-config.json`, ledger auth)
- The token pool DAR for your pool type on your participant — [`ccip-burn-mint-token-pool-2.1.0.dar`](https://github.com/smartcontractkit/chainlink-canton/blob/main/contracts/dars/released/ccip-burn-mint-token-pool-v2-2.1.0.dar) or [`ccip-lock-release-token-pool-2.1.0.dar`](https://github.com/smartcontractkit/chainlink-canton/blob/main/contracts/dars/released/ccip-lock-release-token-pool-v2-2.1.0.dar) (each bundles its CCIP dependencies — the only DAR you upload).
- The token pool DAR for your pool type, uploaded **and vetted** on your participant — [`ccip-burn-mint-token-pool-2.1.0.dar`](https://github.com/smartcontractkit/chainlink-canton/blob/main/contracts/dars/released/ccip-burn-mint-token-pool-v2-2.1.0.dar) or [`ccip-lock-release-token-pool-2.1.0.dar`](https://github.com/smartcontractkit/chainlink-canton/blob/main/contracts/dars/released/ccip-lock-release-token-pool-v2-2.1.0.dar) from the [`contracts/dars/released`](https://github.com/smartcontractkit/chainlink-canton/tree/main/contracts/dars/released) folder (each bundles its CCIP dependencies — the only DAR you upload). Vet **every released version** of the packages you depend on — see [Upgradability](/ccip/canton/concepts/upgradability).
- To **execute** incoming transfers, the CommitteeVerifier DAR — [`ccip-committee-verifier-v2-2.0.0.dar`](https://github.com/smartcontractkit/chainlink-canton/blob/main/contracts/dars/released/ccip-committee-verifier-v2-2.0.0.dar) — uploaded and vetted on your participant as well.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Here too should just point to the official release. Like you did for TP.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done: package names (ccip-burn-mint-token-pool-v2 / ccip-lock-release-token-pool-v2
/ ccip-committee-verifier-v2) + a link to the contracts/dars/released folder, no version pins.

- Token liquidity held by the pool owner party for expected release volume.
- **LockRelease token pool DAR** on your participant — [`ccip-lock-release-token-pool-2.1.0.dar`](https://github.com/smartcontractkit/chainlink-canton/blob/main/contracts/dars/released/ccip-lock-release-token-pool-v2-2.1.0.dar) (bundles its CCIP dependencies — the only DAR you upload).
- **LockRelease token pool DAR** uploaded **and vetted** on your participant — [`ccip-lock-release-token-pool-2.1.0.dar`](https://github.com/smartcontractkit/chainlink-canton/blob/main/contracts/dars/released/ccip-lock-release-token-pool-v2-2.1.0.dar) from the [`contracts/dars/released`](https://github.com/smartcontractkit/chainlink-canton/tree/main/contracts/dars/released) folder (bundles its CCIP dependencies — the only DAR you upload). Vet every released version you depend on — see [Upgradability](/ccip/canton/concepts/upgradability).
- To **execute** incoming transfers, the CommitteeVerifier DAR — [`ccip-committee-verifier-v2-2.0.0.dar`](https://github.com/smartcontractkit/chainlink-canton/blob/main/contracts/dars/released/ccip-committee-verifier-v2-2.0.0.dar) — uploaded and vetted on your participant as well.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need to be repeating this so many times? Is there maybe a hierarchy of docs that this rolls up into?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed. The DAR guidance now lives once in the CCT index's "Prerequisites (all CCT
guides)
" section; both guides link to it with a single line.

@SyedAsadKazmi
SyedAsadKazmi force-pushed the docs/canton-cct-addresses-and-factory branch from 8625109 to d442c8c Compare October 15, 2026 10:25
@SyedAsadKazmi

Copy link
Copy Markdown
Collaborator Author

@SyedAsadKazmi can we also be more specific in https://docs.chain.link/ccip/canton/concepts/manual-execution that the manual exec using the SDK the accept holding si implicit to the manual exec command

@Giuliano-1, verified in code: the SDK never calls accept. The release runs inside the same Execute transaction (CCIPReceiver.daml). BurnMint pools (the default testnet pool) mint holdings directly via BurnMintFactory, so no TransferInstruction exists. LockRelease pools complete immediately with a preapproval; without one a pending TransferInstruction remains, and the SDK does not accept it for you.

Docs now say "holdings arrive with execution" instead of the old separate-accept-step claim.

@Giuliano-1
Giuliano-1 marked this pull request as ready for review October 16, 2026 20:47
@Giuliano-1
Giuliano-1 requested review from a team as code owners October 16, 2026 20:47

This branch was successfully deployed

1 active deployment
Preview — 2cc66d3e Deployed Oct 17, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants