LockRelease Token Pool Deployment (Canton)

This guide assumes you have a token instrument live on Canton with supply minted on-ledger, supporting the CIP-56 TransferFactory interface and transfer pre-approvals.

LockRelease is for fixed total supply tokens where cross-chain transfers are backed by locked liquidity — not mint/burn. On send, tokens lock to the pool owner; on receive, the pool releases from its holdings.

Scope: Deploy pool, fund liquidity, register on TAR, enable a lane. Excludes EDS setup and end-to-end transfer tests.

Prerequisites

  • Instrument with known InstrumentId = { admin, id } supporting TransferFactory and pre-approvals.
  • Token liquidity held by the pool owner party for expected release volume.
  • CCIP DAR packages from contracts/dars/v2_0_0.
  • CCIP contract references from Chainlink ops.

Step 1 — Deploy the LockRelease Token Pool

Create one LockReleaseTokenPool. Signatory: poolOwner.

ArgumentGuidance
instanceIdUnique string, e.g. acme-eur-lr-pool
poolOwnerRecommended: instrument admin
ccipOwnerChainlink CCIP owner party
instrumentIdUnderlying asset InstrumentId
decimals10
rateLimitAdminOptional
remoteChainConfigsEmpty — configure via ApplyChainUpdates (Step 4)
tokenTransferFeeConfigsOptional per-destination fees
poolReceiveContextEmpty at creation — set preapproval in Step 2
transferTimeoutIndefinite
depstokenAdminRegistry, rmnRemote, feeQuoter

See BurnMint deployment guide for transfer-fee fields and CCIP hosted addresses table (same values apply).

After creation, pool address: {instanceId}@{poolOwner}.

Step 2 — Fund the pool and configure pre-approval

The pool releases from the pool owner's holdings — no on-pool "add liquidity" choice. Ensure sufficient holdings before enabling inbound transfers. Holdings are supplied at execution via EDS context.

Set pool receive preapproval

Record the token's transfer preapproval in poolReceiveContext so inbound transfers to the pool owner succeed atomically on send:

curl --request POST \
  --url https://<your-participant>/api/json/v2/commands/submit-and-wait-for-transaction-tree \
  --header "authorization: Bearer $JWT" \
  --header 'content-type: application/json' \
  --data '{
  "commands": [
    {
      "ExerciseCommand": {
        "templateId": "#ccip-lock-release-token-pool:CCIP.LockReleaseTokenPool:LockReleaseTokenPool",
        "contractId": "<POOL_CONTRACT_ID>",
        "choice": "AddPoolReceiveContextContractValue",
        "choiceArgument": {
          "contextKey": "transfer-preapproval",
          "referredContract": "<PREAPPROVAL_CONTRACT_ID>"
        }
      }
    }
  ],
  "commandId": "set-pool-receive-preapproval",
  "actAs": ["<POOL_OWNER_PARTY>"]
}'
FieldValue
contextKeyKey the TransferFactory expects, e.g. transfer-preapproval
referredContractContractId of the pool owner's transfer preapproval

Related choices: AddPoolReceiveContextNonContractValue, RemovePoolReceiveContextValue, ClearPoolReceiveContext.

Step 3 — Register on the Token Admin Registry

Same three-step flow as BurnMint: fetch TAR disclosure from Global EDS, then ProposeAdministratorAcceptAdminRoleSetPool.

See Step 2 of the BurnMint guide for the curl example and choice details.

Step 4 — Enable a lane

Deploy three RateLimiter contracts (inbound default, inbound custom, outbound), then call ApplyChainUpdates on the pool.

See Step 3 of the BurnMint guide for the ChainUpdate field reference.

Step 5 — Go live

Verification checklist

  1. TAR maps instrument to pool with your party as admin.
  2. Pool at {instanceId}@{poolOwner} with matching InstrumentId.
  3. Pool owner holds sufficient liquidity; receive preapproval set in poolReceiveContext.
  4. Lane rate limiters in place.

Stand up EDS

The reference EDS supports LockRelease, including holdings and TransferFactory context for pre-approvals.

Test transactions

See CCIP on Canton — Overview and CCIP Explorer.

What's next

Get the latest Chainlink content straight to your inbox.