Skip to content

feat: bridge --to (CCTP outbound) + activate - #20

Merged
anil-rome merged 1 commit into
mainfrom
feat-bridge-outbound-activate
Jul 22, 2026
Merged

feat: bridge --to (CCTP outbound) + activate#20
anil-rome merged 1 commit into
mainfrom
feat-bridge-outbound-activate

Conversation

@anil-rome

Copy link
Copy Markdown
Contributor

Completes the bridge for the from-home path in the outbound direction: bridge wUSDC out of Rome back to a destination chain's USDC, plus the one-time activate it requires.

Commands

  • rome bridge <chain> --to <dest> --amount <usdc> — burn wUSDC on Rome (RomeBridgeWithdraw / CCTP v2) → register → poll to attestation-ready → return a claim handle. --from = in, --to = out (exactly one). --recipient, --dry-run supported.
  • rome activate <chain> — one-time funding of the actor's external_auth PDA (via on-chain SimpleActivator), required before the first bridge-out. Idempotent (skips, no spend, if already active). EVM key only.

The design (per operator direction)

  • Claiming on the destination is the user's responsibility. Rome runs a sponsor for the inbound settle intent, but does not sponsor the outbound destination mint. The handle returns the transmitter, CCTP domain, and transfer id; the user calls MessageTransmitterV2.receiveMessage(message, attestation) (needs destination gas; permissionless delivery).
  • Activation is the deliberate cost of frictionless inbound. Inbound needs no per-user account; the first outbound does (CCTP creates a per-burn messageSentEventData account funded by the user's PDA). bridge --to pre-checks the PDA lamports with a pure-EVM account_lamports read and directs to rome activate — instead of the burn reverting deep in CCTP with Custom(1).

Validation

  • Funded-verified on Hadrian, end to end: rome activaterome bridge --to base-sepolia --amount 0.1 → burn tx 0xc4549892…9fbe SUCCESS (block 478012463) → attestation-ready → claim handle emitted. rome activate idempotent-skip confirmed live.
  • Root-caused the initial Custom(1) to the unfunded PDA (contract's documented ~15M-lamport reserve); fixed by activation (PDA 29.97M → burn lands).
  • 92 unit tests (+9), typecheck + build clean, MCP smoke green; bridge/activate remain off the MCP surface. Dry-run live-verified through the CLI.

Docs (fully wired)

  • docs/GUIDES.md — new "Bridge out" section: the in/out split, activation (why + how), claim responsibility, and how the on-chain bridge + off-chain bridge-api actually work.
  • docs/ARCHITECTURE.md — catalog rows for bridge --to + activate; file-tree + actions updated.

Feature PR, no version bump — pinned in a later release. Follow-ons: Wormhole (ETH) egress; a doctor activation line; an optional bridge claim convenience for the destination receiveMessage.

Bridge wUSDC out of Rome: burn on Rome (RomeBridgeWithdraw / CCTP v2) →
register → poll to attestation-ready → return a claim handle. Claiming on
the destination is the user's responsibility (MessageTransmitterV2.
receiveMessage, needs destination gas) — Rome sponsors the inbound settle
intent, never the outbound destination claim.

First outbound requires a funded external-auth PDA (CCTP creates a per-burn
messageSentEventData account). `rome activate` funds it once via the
on-chain SimpleActivator (idempotent); `bridge --to` pre-checks it with a
pure-EVM account_lamports read and directs to `rome activate` rather than
letting the burn revert deep in CCTP with Custom(1). EVM key only.

Funded-verified on Hadrian: activate -> burn 0.1 wUSDC -> Base Sepolia,
tx 0xc454...9fbe SUCCESS, attestation-ready, claim handle emitted.
92 unit tests; docs: GUIDES "Bridge out" + activation + claim responsibility.
@anil-rome
anil-rome merged commit 7d37866 into main Jul 22, 2026
6 checks passed
anil-rome added a commit that referenced this pull request Jul 22, 2026
Pins the released surface to main. Since v0.6.0: bridge --to (CCTP
outbound; user claims on the destination) + activate (one-time PDA
funding before the first outbound), rome-cli #20, funded-GREEN Hadrian.
Bumps package.json and the github install pins 0.6.0 -> 0.7.0.
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.

1 participant