Problem
scripts/setup/bootstrap-usdcx.go creates a CIP56.TransferFactory::CIP56TransferFactory contract whose TransferFactory_Transfer choice creates CIP56Holding contracts atomically. On Canton devnet, DA's factory creates Utility.Registry.App.V0.Model.Transfer::TransferOffer contracts (pending state) — the receiver must exercise TransferInstruction_Accept to complete the transfer.
Local E2E tests pass because they never hit the offer/accept path. Devnet fails because they do.
Depends On
#257 (must know the correct template names and constructor fields first)
Changes Required
Option A (preferred — no Daml change): If utility_registry_app_v0 contains a bootstrappable factory template that creates TransferOffer contracts, update bootstrap-usdcx.go to create an instance of that template instead of CIP56TransferFactory. The utility_registry_app_v0 DARs are already deployed to both P1 and P2.
Option B (fallback — Daml change): Modify contracts/canton-erc20/daml/cip56-token/src/CIP56/TransferFactory.daml so TransferFactory_Transfer creates a Utility.Registry.App.V0.Model.Transfer::TransferOffer contract instead of a CIP56Holding. Rebuild the DAR.
In both cases, also bootstrap the required TransferRule contract(s) for the instrument. The accept choiceContext endpoint (see #259) queries these contracts from ACS.
Verification
After running updated bootstrap:
Problem
scripts/setup/bootstrap-usdcx.gocreates aCIP56.TransferFactory::CIP56TransferFactorycontract whoseTransferFactory_Transferchoice createsCIP56Holdingcontracts atomically. On Canton devnet, DA's factory createsUtility.Registry.App.V0.Model.Transfer::TransferOffercontracts (pending state) — the receiver must exerciseTransferInstruction_Acceptto complete the transfer.Local E2E tests pass because they never hit the offer/accept path. Devnet fails because they do.
Depends On
#257 (must know the correct template names and constructor fields first)
Changes Required
Option A (preferred — no Daml change): If
utility_registry_app_v0contains a bootstrappable factory template that createsTransferOffercontracts, updatebootstrap-usdcx.goto create an instance of that template instead ofCIP56TransferFactory. Theutility_registry_app_v0DARs are already deployed to both P1 and P2.Option B (fallback — Daml change): Modify
contracts/canton-erc20/daml/cip56-token/src/CIP56/TransferFactory.damlsoTransferFactory_Transfercreates aUtility.Registry.App.V0.Model.Transfer::TransferOffercontract instead of aCIP56Holding. Rebuild the DAR.In both cases, also bootstrap the required
TransferRulecontract(s) for the instrument. The accept choiceContext endpoint (see #259) queries these contracts from ACS.Verification
After running updated bootstrap:
scripts/testing/list-all-contracts.goshowsTransferOffercontracts appearing on the ledger after aTransferFactory_Transfercallscripts/testing/find-transfer-rule.gofinds theTransferRulecontract for the USDCx instrument