ChainSafe / ChainSafe/canton-middleware

feat: USDCx outbound — burn via BridgeUserAgreement + release tracking

Open
#359 0 comments 0 reactions 0 assignees View on GitHub
CIP-0086: Phase 2 Deliverable: D3 Type: Feature
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.