ChainSafe / ChainSafe/canton-middleware
feat: USDCx outbound — burn via BridgeUserAgreement + release tracking
- Dominant language
- Go
- Stars
- 1
- Forks
- 1
- Avg merge
- 40m
- Merged PRs (30d)
- 1
Description
# Goal
USDCx outbound bridging (Canton USDCx -> Ethereum USDC): burn on Canton via `BridgeUserAgreement_Burn`, Circle releases USDC on Ethereum (minus fee); relayer tracks the release.
# Mechanics (confirmed, July 2026)
- `BridgeUserAgreement_Burn` takes destination domain (0 = Ethereum), amount (max 6 dp), Ethereum recipient address, a UUID request id, and the holding contract ids to burn.
- It is a **user-party choice**: custodial users -> middleware signs directly; external-key users -> prepare/execute signing flow (same pattern as `pkg/transfer`).
- Factory + disclosed contracts from the DA Utilities burn-mint-factory registry endpoint.
- Circle validates the burn and releases USDC to the Ethereum recipient; timing is Circle-controlled; a Circle withdrawal fee applies.
# Flow
1. Dapp calls `POST /api/v2/bridge/withdraw/prepare` (external key) or the custodial variant; api-server builds `BridgeUserAgreement_Burn`.
2. `execute` submits the burn and registers the transfer with the relayer (`bridge_key=xreserve`, `stage=""`, metadata: `burn_request_id`).
3. xreserve adapter `Step`: `"" -> awaiting_release` — watch Ethereum for the xReserve release matching `burn_request_id` -> `completed` with the release tx hash. The adapter never submits anything; it only observes Circle.
# Work items
- [ ] Burn command builder (choice args + disclosed contracts via burn-mint-factory endpoint)
- [ ] Prepare/execute wiring for external keys; direct exercise for custodial
- [ ] Holding selection for the burn amount (UTXO-style holdings; reuse existing holding-selection logic if applicable)
- [ ] Transfer registration on execute (`burn_request_id` in metadata)
- [ ] `bridges/xreserve` withdrawal `Step`: release watcher on the xReserve contract
- [ ] Fee surfacing: `GET /api/v2/bridge/tokens` and the withdraw response show Circle's fee and "timing controlled by Circle"
- [ ] Devstack: stub release (scripted ERC-20 transfer from a fake xReserve) so e2e covers the stage machine
- [ ] e2e: burn (custodial + external-key) -> release stub -> transfer completed
# Depends on
- xreserve inbound adapter (shares circle/ledger clients, config, onboarding)
- Bridge API (prepare/execute endpoints, registration)
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the Bridge API prepare/execute endpoints, the existing pkg/transfer signing pattern, and the inbound xreserve adapter. Then trace bridges/xreserve, holding selection, and transfer registration using burn_request_id. Done means custodial and external-key burns reach a completed transfer after the devstack release stub, with fees and Circle-controlled timing surfaced.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend-api-design, blockchain
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100