diff --git a/pages/fraxnet/addresses/fraxnet-custodians.mdx b/pages/fraxnet/addresses/fraxnet-custodians.mdx index 5bdf182..2a534fb 100644 --- a/pages/fraxnet/addresses/fraxnet-custodians.mdx +++ b/pages/fraxnet/addresses/fraxnet-custodians.mdx @@ -1,5 +1,5 @@ --- -title: Frax tokens +title: FraxNet Custodians lang: en-US --- diff --git a/pages/fraxnet/addresses/fraxnet-deposit.mdx b/pages/fraxnet/addresses/fraxnet-deposit.mdx index 3bfb436..2e271c2 100644 --- a/pages/fraxnet/addresses/fraxnet-deposit.mdx +++ b/pages/fraxnet/addresses/fraxnet-deposit.mdx @@ -1,11 +1,8 @@ --- -title: Fraxtal contracts +title: FraxNet X-Chain Minting/Redeeming lang: en-US --- -import * as mainnet from '~/misc/constants/mainnet'; -import * as testnet from '~/misc/constants/testnet'; - # FraxNet Cross Chain Minting and Redeeming Contracts ### Ethereum Mainnet diff --git a/pages/fraxnet/api/_meta.json b/pages/fraxnet/api/_meta.json index 8c07ca2..3323bc1 100644 --- a/pages/fraxnet/api/_meta.json +++ b/pages/fraxnet/api/_meta.json @@ -2,6 +2,7 @@ "index": "Overview", "frxusd-endpoints": "frxUSD Endpoints", "branded-endpoints": "SaaS Stablecoin Endpoints", + "status": "Tracking & Status", "cctp-relay": "CCTP Relay", "reference": "Reference" } diff --git a/pages/fraxnet/api/branded-endpoints.mdx b/pages/fraxnet/api/branded-endpoints.mdx index afd85bd..43616f3 100644 --- a/pages/fraxnet/api/branded-endpoints.mdx +++ b/pages/fraxnet/api/branded-endpoints.mdx @@ -9,6 +9,8 @@ These endpoints handle Stablecoins as a Service (SaaS) operations: minting SaaS > Branded stablecoin endpoints (`/branded/*`) only support EVM chains. Solana EIDs are not accepted. +The `process*` endpoints behave the same way as their [standard frxUSD counterparts](/fraxnet/api/frxusd-endpoints): execution is handed to the orchestrator, responses include an `executionId`, calls are idempotent, and the [`pending`](/fraxnet/api/frxusd-endpoints#pending-response) and [`alreadyProcessed`](/fraxnet/api/frxusd-endpoints#already-processed-response) response shapes apply. Set your HTTP client timeout to at least 90 seconds. + --- ## `GET /branded/fetchAddress` @@ -62,10 +64,14 @@ Process a USDC deposit for a branded token. Mints frxUSD, mints the branded toke "processDepositTx": "0x...", "depositAddress": "0x...", "asset": "0x...", - "usdcAmount": "1000000" + "usdcAmount": "1000000", + "executionId": "badfe4dc-1eb0-49fb-9f44-1672260a76bf", + "orchestrator": "fn-orc" } ``` +The cross-chain delivery leg continues after the response returns — track it with [`GET /status?id=`](/fraxnet/api/status). + --- ## `GET /branded/processRedemption` @@ -86,20 +92,23 @@ Redeem a branded stablecoin back to frxUSD, then to USDC, and relay the USDC to ```json { "ok": true, - "createFraxNetDepositTx": "0x...", - "contractAlreadyDeployed": false, + "createFraxNetDepositTx": "skipped - contract already deployed", + "contractAlreadyDeployed": true, "processRedemptionTx": "0x...", "depositAddress": "0x...", "asset": "0x...", "brandedTokenAmount": "1000000", "cctpRelay": { - "status": "pending_attestation", - "jobId": "0x...", - "destDomain": 13 - } + "status": "delegated_to_orchestrator", + "executionId": "badfe4dc-1eb0-49fb-9f44-1672260a76bf" + }, + "executionId": "badfe4dc-1eb0-49fb-9f44-1672260a76bf", + "orchestrator": "fn-orc" } ``` +The `cctpRelay` object follows the same semantics as [`/processRedemption`](/fraxnet/api/frxusd-endpoints#the-cctprelay-object): `delegated_to_orchestrator` means the USDC delivery is tracked through the `executionId`; `not_applicable` means the payout destination is Ethereum and no relay is needed. **The `processRedemptionTx` hash is no longer usable as a relay `jobId`** — use the `executionId`. + --- ## Branded Deposit Flow (USDC → Branded Token) @@ -107,8 +116,9 @@ Redeem a branded stablecoin back to frxUSD, then to USDC, and relay the USDC to 1. Call `/branded/fetchAddress` to get the deposit address 2. Send USDC to the deposit address on Ethereum via CCTP `depositForBurn` from the source chain 3. Call `/scheduleCCTPRelay` to relay the CCTP message to Ethereum -4. Poll `/jobStatus` until `complete` +4. Poll `GET /status?id=` until the relay job is `complete` 5. Call `/branded/processDeposit` to mint frxUSD, mint the branded token, and send it cross-chain +6. Poll `GET /status?id=` until `execution.status` is `completed` ## Branded Redemption Flow (Branded Token → USDC) @@ -116,4 +126,4 @@ Redeem a branded stablecoin back to frxUSD, then to USDC, and relay the USDC to 2. Approve and bridge branded tokens from the source chain to the deposit address on Ethereum via the `CrossChainRouter` 3. Wait for LayerZero settlement (~1-5 minutes) 4. Call `/branded/processRedemption` to redeem the branded token to frxUSD to USDC, and relay USDC via CCTP -5. Poll `/jobStatus` until USDC arrives (~20+ minutes) +5. Poll `GET /status?id=` until `execution.status` is `completed` (~20+ minutes for USDC to arrive) diff --git a/pages/fraxnet/api/cctp-relay.mdx b/pages/fraxnet/api/cctp-relay.mdx index 40d5cdd..707383c 100644 --- a/pages/fraxnet/api/cctp-relay.mdx +++ b/pages/fraxnet/api/cctp-relay.mdx @@ -5,7 +5,11 @@ lang: en-US # CCTP Relay -The Orchestration API includes a built-in CCTP relay service that handles Circle attestation polling and message relay on destination chains. Relay jobs are automatically created by `/processRedemption` and `/branded/processRedemption`, or can be manually scheduled. +The Orchestration API includes a built-in CCTP relay service that handles Circle attestation polling and message relay on destination chains. Use it to relay a `depositForBurn` transaction you submitted yourself — for example, moving USDC to Ethereum before calling a `process*` endpoint. + +> Cross-chain redemptions processed through the orchestrator do **not** create relay jobs — their USDC delivery is tracked through the `executionId` returned by `/processRedemption` and `/branded/processRedemption`. The endpoints on this page apply to manually scheduled relays. + +Relay `jobId`s are held in memory and do not survive a service restart. For anything with an `executionId`, prefer [`GET /status`](/fraxnet/api/status). --- @@ -28,21 +32,35 @@ Manually schedule a CCTP relay for an existing `depositForBurn` transaction. "jobId": "0x...", "sourceDomain": 13, "destDomain": 0, - "status": "pending_attestation" + "status": "waiting_for_finality" } ``` +The `jobId` equals the `txHash`. If a job already exists for that transaction, the response instead includes `"alreadyScheduled": true` with the existing job's status: + +```json +{ + "ok": true, + "alreadyScheduled": true, + "jobId": "0x...", + "destDomain": 0, + "status": "PendingAttestation" +} +``` + +(Note the `status` casing differs in the already-scheduled variant.) + --- ## `GET /jobStatus` -Check the status of a CCTP relay job. +Check the status of a CCTP relay job. `GET /status?id=` returns the same `job` object. ### Parameters | Name | Type | Required | Description | | --- | --- | --- | --- | -| `jobId` | `string` | Yes | Job ID returned by other endpoints | +| `jobId` | `string` | Yes | Job ID returned by `/scheduleCCTPRelay` | ### Response @@ -51,6 +69,7 @@ Check the status of a CCTP relay job. "ok": true, "job": { "job_id": "0x...", + "message_hex": "000000010000000d...", "dest_domain": 13, "status": "complete", "relay_tx": "0x...", @@ -60,6 +79,8 @@ Check the status of a CCTP relay job. } ``` +`message_hex` is the raw CCTP message parsed from the burn transaction's `MessageSent` event (informational, no `0x` prefix). + --- ## `GET /activeJobs` @@ -74,7 +95,8 @@ Summary of all CCTP relay jobs and their statuses. No parameters required. "total_jobs": 42, "total_active": 5, "counts": { - "pending_attestation": 3, + "waiting_for_finality": 1, + "pending_attestation": 2, "relaying": 2, "complete": 30, "already_relayed": 5, @@ -87,20 +109,31 @@ Summary of all CCTP relay jobs and their statuses. No parameters required. "dest_domain": 0, "created_at": 1709729600 } + ], + "failed_jobs": [ + { + "job_id": "0x...", + "error": "receiveMessage submission failed: ...", + "dest_domain": 13, + "created_at": 1709729000 + } ] } ``` +`total_active` counts jobs in `waiting_for_finality`, `pending_attestation`, and `relaying`. + --- ## Job Status Lifecycle | Status | Description | | --- | --- | +| `waiting_for_finality` | Transient initial state at job creation | | `pending_attestation` | Polling Circle's attestation API for signature | | `relaying` | Submitting `receiveMessage()` on the destination chain | | `complete` | USDC delivered on destination | | `already_relayed` | Message was relayed by another party | | `failed` | Unrecoverable error | -The relay worker polls Circle's attestation API every 15 seconds for up to ~25 minutes. Circle's attestation API handles finality internally, returning `pending_confirmations` until sufficient block finality is reached, then `complete` with the attestation signature. +The relay worker polls Circle's attestation API every 15 seconds for up to ~35 minutes. Circle's attestation API handles finality internally, returning `pending_confirmations` until sufficient block finality is reached, then `complete` with the attestation signature. If attestation times out but the message was already relayed by another party, the job resolves to `already_relayed` rather than `failed`. diff --git a/pages/fraxnet/api/frxusd-endpoints.mdx b/pages/fraxnet/api/frxusd-endpoints.mdx index 13a7ec0..e54fd39 100644 --- a/pages/fraxnet/api/frxusd-endpoints.mdx +++ b/pages/fraxnet/api/frxusd-endpoints.mdx @@ -7,6 +7,8 @@ lang: en-US These endpoints handle standard frxUSD cross-chain operations: minting frxUSD from USDC deposits, and redeeming frxUSD back to USDC with cross-chain relay via CCTP. +The `process*` endpoints hand execution to the [orchestrator](/fraxnet/api) and wait synchronously for up to ~75 seconds. Set your HTTP client timeout to at least 90 seconds, and handle the [`pending`](#pending-response) and [`alreadyProcessed`](#already-processed-response) response shapes described below. All `process*` calls are idempotent — retrying converges on the same execution. + ## `GET /health` Health check returning plain text `ok`. @@ -62,10 +64,16 @@ Process a USDC deposit at the deposit address on Ethereum. Mints frxUSD and send "contractAlreadyDeployed": false, "processDepositTx": "0x...", "depositAddress": "0x...", - "usdcAmount": "1000000" + "usdcAmount": "1000000", + "executionId": "badfe4dc-1eb0-49fb-9f44-1672260a76bf", + "orchestrator": "fn-orc" } ``` +When the deposit contract is already deployed, `createFraxNetDepositTx` is the literal string `"skipped - contract already deployed"` and `contractAlreadyDeployed` is `true`. + +`processDepositTx` is the confirmed mint transaction on Ethereum. The cross-chain LayerZero delivery leg continues after the response returns — track it to completion with [`GET /status?id=`](/fraxnet/api/status). + --- ## `GET /processRedemption` @@ -85,19 +93,82 @@ Redeem frxUSD at the deposit address on Ethereum to USDC, then relay the USDC to ```json { "ok": true, - "createFraxNetDepositTx": "0x...", - "contractAlreadyDeployed": false, + "createFraxNetDepositTx": "skipped - contract already deployed", + "contractAlreadyDeployed": true, "processRedemptionTx": "0x...", "depositAddress": "0x...", "frxUSDAmount": "1000000000000000000", "cctpRelay": { - "status": "pending_attestation", - "jobId": "0x...", - "destDomain": 13 - } + "status": "delegated_to_orchestrator", + "executionId": "badfe4dc-1eb0-49fb-9f44-1672260a76bf" + }, + "executionId": "badfe4dc-1eb0-49fb-9f44-1672260a76bf", + "orchestrator": "fn-orc" } ``` +### The `cctpRelay` object + +| `cctpRelay.status` | Meaning | +| --- | --- | +| `delegated_to_orchestrator` | The USDC delivery to the destination chain is handled by the orchestrator as part of the same execution. Poll `GET /status?id=` until `execution.status` is `completed`. | +| `not_applicable` | The payout destination is Ethereum itself — no CCTP relay is needed. | +| `waiting_for_finality` | Legacy (pre-orchestrator) shape: a local relay job was created and `cctpRelay.jobId` / `cctpRelay.destDomain` are present. Poll `GET /status?id=`. | + +> **Breaking change for existing integrators:** cross-chain redemptions no longer create a local CCTP relay job, so the `processRedemptionTx` hash can no longer be used as a `jobId` — polling `/jobStatus` with it returns `"No job found"` even though delivery is proceeding normally. Track delivery with the `executionId` instead. + +--- + +## Pending Response + +If processing takes longer than the synchronous wait window (~75 seconds) — most commonly a first-time deposit that must also deploy the deposit contract — the API returns: + +```json +{ + "ok": false, + "pending": true, + "executionId": "badfe4dc-1eb0-49fb-9f44-1672260a76bf", + "orchestrator": "fn-orc", + "error": "Processing accepted and in progress; re-request to continue" +} +``` + +This is **not a failure**: processing continues in the background. Either re-issue the identical call (it converges on the same execution and returns the final result once ready) or poll `GET /status?id=`. + +## Already Processed Response + +The orchestrator also detects and processes funded deposit addresses autonomously. If the deposit you ask about was already processed, the API answers with the transaction that actually moved the funds: + +```json +{ + "ok": true, + "alreadyProcessed": true, + "processDepositTx": "0x...", + "depositAddress": "0x...", + "usdcAmount": "3000000", + "executionId": "badfe4dc-1eb0-49fb-9f44-1672260a76bf" +} +``` + +Treat this as success and do not retry. + +--- + +## Deposit Flow (USDC → frxUSD) + +1. Call `/fetchAddress` to get the deposit address for your beneficiary and target chain +2. Send USDC to the deposit address on Ethereum (directly, or from another chain via CCTP `depositForBurn` + `/scheduleCCTPRelay`) +3. Call `/processDeposit` to mint frxUSD and send it to the target chain via LayerZero +4. Poll `GET /status?id=` until `execution.status` is `completed` + +## Redemption Flow (frxUSD → USDC) + +1. Call `/fetchAddress` to get the deposit address +2. Bridge frxUSD from the source chain to the deposit address on Ethereum (LayerZero OFT send) +3. Wait for LayerZero settlement (~1-5 minutes) +4. Call `/processRedemption` to redeem frxUSD to USDC and relay it to the target chain via CCTP +5. Poll `GET /status?id=` until `execution.status` is `completed` (~20+ minutes for cross-chain delivery) + --- ## Deposit Address Verification @@ -117,3 +188,5 @@ const address = await factory.getDeploymentAddress( ethers.constants.HashZero // ATA (zero for EVM) ); ``` + +Solana targets (EID 30168) are not supported by the API — their address derivation requires the target's USDC associated token account (ATA) as the third parameter. diff --git a/pages/fraxnet/api/index.mdx b/pages/fraxnet/api/index.mdx index 4087ccb..51eb8ed 100644 --- a/pages/fraxnet/api/index.mdx +++ b/pages/fraxnet/api/index.mdx @@ -5,10 +5,21 @@ lang: en-US # Orchestration API -The FraxNet Orchestration API enables cross-chain redemptions and branded stablecoin operations using [LayerZero OFT ↗](https://docs.layerzero.network) and [Circle CCTP v2 ↗](https://developers.circle.com/cctp). Two product lines are supported: +The FraxNet Orchestration API enables cross-chain minting and redemptions for frxUSD and branded stablecoins using [LayerZero OFT ↗](https://docs.layerzero.network) and [Circle CCTP v2 ↗](https://developers.circle.com/cctp). Two product lines are supported: -1. **Standard frxUSD** — Bridge frxUSD from remote chains to Ethereum, redeem to USDC, and relay to any CCTP-supported chain. -2. **Stablecoins as a Service (SaaS)** — Deposit USDC to mint SaaS stablecoins or redeem them back to USDC. +1. **Standard frxUSD** — Deposit USDC to mint frxUSD on any supported chain, or bridge frxUSD back to Ethereum, redeem to USDC, and relay to any CCTP-supported chain. +2. **Stablecoins as a Service (SaaS)** — Deposit USDC to mint SaaS (branded) stablecoins or redeem them back to USDC. + +## Architecture + +Behind the API, all deposit and redemption processing is executed by the **FraxNet Orchestrator** — a durable backend service that runs every operation as an *execution*: an ordered set of persisted steps (deploy the deposit contract if needed, submit the mint or redemption, confirm it on-chain, then track the cross-chain delivery leg to completion). Execution state survives restarts, long cross-chain waits are handled with durable timers, and ambiguous outcomes are parked for operator review instead of being guessed at. + +What this means for integrators: + +- **Calls are idempotent.** Repeat calls, double-clicks, and webhook replays for the same deposit converge onto a single execution — you can safely retry any `process*` request. +- **Every successful `process*` response includes an `executionId`** (and `"orchestrator": "fn-orc"`). Use it with [`GET /status`](/fraxnet/api/status) to track the operation end-to-end, including the cross-chain delivery leg. +- **Deposits are also detected autonomously.** The orchestrator scans deposit addresses on-chain, so a funded deposit address is typically processed within seconds even without an API call. If the orchestrator got there first, your `process*` call simply returns the result of the existing execution — including the real transaction hash — instead of failing. +- **Process calls are synchronous up to ~75 seconds.** If processing takes longer (for example, a first-time deposit that must also deploy the deposit contract), the API returns a `pending` response with the `executionId` so you can poll. Set your HTTP client timeout to at least 90 seconds for the `process*` endpoints. ## Base URL @@ -22,6 +33,8 @@ All endpoints use **GET** requests with query parameters. No authentication is r ## Response Format +All endpoints return HTTP 200 with a JSON body (except `GET /health`, which returns plain text). Success and failure are signalled in the body, not the status code. + Success responses include `"ok": true`: ```json @@ -40,17 +53,29 @@ Failure responses include `"ok": false` with an error message: } ``` +Two additional boolean flags can appear and should drive your handling logic: + +| Flag | Appears with | Meaning | +| --- | --- | --- | +| `"pending": true` | `"ok": false` | Processing was accepted and is still in progress — **not a failure**. Retry the same call or poll `/status` with the returned `executionId`. | +| `"alreadyProcessed": true` | `"ok": true` | The deposit was already processed (for example, by the orchestrator's scanner). Treat as success; do not retry. | + +New response fields may be added over time — parsers should ignore unknown fields. + ## Endpoint Summary | Endpoint | Description | | --- | --- | | `GET /health` | Health check | +| `GET /rpcHealth` | RPC and attestation-service connectivity check | | `GET /fetchAddress` | Get deposit address for frxUSD operations | | `GET /processDeposit` | Process USDC deposit to mint frxUSD | | `GET /processRedemption` | Redeem frxUSD to USDC and relay via CCTP | | `GET /branded/fetchAddress` | Get deposit address for branded stablecoin operations | | `GET /branded/processDeposit` | Process USDC deposit to mint branded stablecoin | | `GET /branded/processRedemption` | Redeem branded stablecoin to USDC and relay via CCTP | +| `GET /status` | Unified status lookup — accepts an `executionId` or a relay `jobId` | +| `GET /executionStatus` | Orchestrator execution status by `executionId` | | `GET /scheduleCCTPRelay` | Manually schedule a CCTP relay | | `GET /jobStatus` | Check CCTP relay job status | | `GET /activeJobs` | Summary of all relay jobs | @@ -61,7 +86,8 @@ Failure responses include `"ok": false` with an error message: | Contract | Address | | --- | --- | -| FraxNet Factory | `0xA3D62f83C433e2A56Af392E08a705A52DEd63696` | +| FraxNetDepositFactory | `0xA3D62f83C433e2A56Af392E08a705A52DEd63696` | +| Branded Factory | `0x63E89638743a409e2389F06A3f778a4570314d7D` | | frxUSD Token | `0xcacd6fd266af91b8aed52accc382b4e165586e29` | | USDC | `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` | diff --git a/pages/fraxnet/api/reference.mdx b/pages/fraxnet/api/reference.mdx index 19d6685..f7c6e0a 100644 --- a/pages/fraxnet/api/reference.mdx +++ b/pages/fraxnet/api/reference.mdx @@ -23,6 +23,9 @@ lang: en-US | Unichain | 30320 | | Sonic | 30332 | | Ink | 30339 | +| Somnia | 30380 | + +Solana (EID 30168) is **not supported** as a target by the API. ### CCTP Domain IDs @@ -41,15 +44,29 @@ lang: en-US | Sei | 16 | | Ink | 21 | +## Response Handling + +How to react to each response shape from the `process*` endpoints: + +| You observe | What to do | +| --- | --- | +| `"ok": true` | Success — track the delivery leg via `executionId` if needed | +| `"ok": true, "alreadyProcessed": true` | Success — the deposit was already processed; do not retry | +| `"ok": false, "pending": true` | In progress — retry the same call or poll `/status?id=` | +| `"ok": false` with a balance-is-0 or address-mismatch error | Fix the precondition (wait for funds to arrive, or use the correct deposit address) | +| `"ok": false` with any other `error` and an `executionId` | Contact support with the `executionId` | + ## Common Errors | Error | Cause | Solution | | --- | --- | --- | | `"Missing 'beneficiary' parameter"` | Invalid or missing address | Provide a valid 40-character hex address | -| `"Deposit address mismatch"` | Address doesn't match on-chain calculation | Use the address returned by `/fetchAddress` or `/branded/fetchAddress` | -| `"frxUSD balance at depositAddress is 0"` | Funds haven't arrived yet | Wait longer for LayerZero settlement | -| `"USDC balance at depositAddress is 0"` | CCTP relay not complete | Wait for the relay job to reach `complete` status | -| `"InsufficientFee"` | Not enough native ETH for LayerZero messaging | Ensure the relayer wallet is funded | +| `"Deposit address mismatch. Provided: 0x..., Expected from on-chain: 0x..."` | Address doesn't match the on-chain CREATE2 derivation | Use the address returned by `/fetchAddress` or `/branded/fetchAddress` | +| `"frxUSD balance at depositAddress 0x... is 0. Expected balance > 0."` | Funds haven't arrived yet | Wait longer for LayerZero settlement | +| `"USDC balance at depositAddress 0x... is 0. Expected balance > 0."` | CCTP relay not complete | Wait for the relay job to reach `complete` status | +| `"Processing accepted and in progress; re-request to continue"` | Processing outlived the ~75s synchronous window (`pending: true`) | Not an error — retry the same call or poll `/status` | +| `"No job found for jobId '...'"` | Unknown or expired relay job ID — job IDs are in-memory and do not survive restarts; orchestrated redemptions never create one | Track via `executionId` where available | +| `"No execution found for executionId '...'"` | Unknown execution ID | Check the ID against the `process*` response that issued it | ## Troubleshooting @@ -62,12 +79,20 @@ https://layerzeroscan.com/tx/{your-bridge-tx-hash} ### CCTP relay stuck on `pending_attestation`? -Circle's attestation API handles finality internally and can take 20+ minutes. This is normal behavior. +Circle's attestation API handles finality internally and can take 20+ minutes; the relay worker polls for up to ~35 minutes. This is normal behavior. + +### Execution stuck in `sleeping`? + +`sleeping` means the orchestrator is durably waiting on an external leg — a CCTP attestation, a LayerZero delivery, or a bridge confirmation. Check `current_step` and `timeline` in the [`/status`](/fraxnet/api/status) response to see which leg is in flight. If `extended_wait` is `true`, the wait has exceeded its normal budget but is still being monitored and self-heals when the external service catches up. + +### Got `"ok": false` after a redemption but the transaction succeeded? + +If the response includes `pending: true` or an `executionId`, processing is continuing — poll `/status`. A repeat of the identical call is always safe: it converges on the existing execution rather than double-processing. ### How long does a full round-trip take? -- **Deposit flow** (USDC → branded token): ~25-35 minutes (CCTP relay + processing) -- **Redemption flow** (branded token → USDC): ~25-35 minutes (LayerZero settlement + CCTP relay) +- **Deposit flow** (USDC → frxUSD/branded token): ~25-35 minutes (CCTP relay + processing) +- **Redemption flow** (frxUSD/branded token → USDC): ~25-35 minutes (LayerZero settlement + CCTP relay) ## Resources diff --git a/pages/fraxnet/api/status.mdx b/pages/fraxnet/api/status.mdx new file mode 100644 index 0000000..34091ee --- /dev/null +++ b/pages/fraxnet/api/status.mdx @@ -0,0 +1,130 @@ +--- +title: Tracking & Status +lang: en-US +--- + +# Tracking & Status + +The API hands out two kinds of tracking identifiers: + +| Identifier | Format | Issued by | Durability | +| --- | --- | --- | --- | +| `executionId` | UUID (e.g. `badfe4dc-1eb0-...`) | All `process*` endpoints | Durable — persisted by the orchestrator | +| `jobId` | 66-character `0x` hash | `/scheduleCCTPRelay` (and legacy redemption responses) | Ephemeral — held in memory and lost if the service restarts | + +**Prefer the `executionId` wherever you have one.** It tracks the full operation — contract deployment, mint or redemption, confirmation, and the cross-chain delivery leg — and survives service restarts. + +--- + +## `GET /status` + +Unified status lookup — the recommended endpoint for all tracking. Accepts either identifier type and dispatches automatically, so callers never need to know which subsystem produced an ID. + +### Parameters + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `id` | `string` | Yes | A relay `jobId` (`0x` + 64 hex chars) **or** an `executionId` (UUID) | + +### Response + +The top-level key tells you which subsystem answered. For a relay `jobId`: + +```json +{ + "ok": true, + "job": { + "job_id": "0x...", + "dest_domain": 13, + "status": "complete", + "relay_tx": "0x...", + "error": null, + "created_at": 1709500000 + } +} +``` + +For an `executionId`: + +```json +{ + "ok": true, + "orchestrator": "fn-orc", + "execution": { + "execution_id": "badfe4dc-1eb0-49fb-9f44-1672260a76bf", + "status": "sleeping", + "flow": "REDEEM_RECEIVE_EVM", + "current_step": "wait_cctp_attestation", + "steps": { "completed": 4, "total": 6 }, + "tx_hashes": { + "fraxnet_redemption_tx_hash": "0x...", + "cctp_receive_dest_tx_hash": "0x..." + }, + "timeline": [ + { + "sequence": 0, + "name": "wait_lz_inbound_delivery", + "status": "completed", + "tx_hash": "0x...", + "external_status": "DELIVERED" + } + ], + "attempts": 1, + "last_error": null, + "extended_wait": false, + "sleep_until": "2026-07-28T12:34:56+00:00" + } +} +``` + +### Errors + +```json +{ "ok": false, "error": "No relay job found for id '0x...'" } +{ "ok": false, "error": "No execution found for executionId 'abc'" } +``` + +--- + +## `GET /executionStatus` + +Orchestrator execution status by `executionId`. Equivalent to the execution branch of `/status`; kept as a dedicated endpoint for explicit lookups. + +### Parameters + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `executionId` | `uuid` | Yes | The `executionId` from a `process*` response | + +### Response + +Same `{ "ok": true, "orchestrator": "fn-orc", "execution": { ... } }` shape as `/status` above. + +--- + +## Execution Status Lifecycle + +| Status | Terminal | Meaning | +| --- | --- | --- | +| `pending` | No | Queued, waiting for the executor to pick it up | +| `running` | No | A step is executing right now | +| `sleeping` | No | Waiting durably — for example, polling a CCTP attestation or a LayerZero delivery | +| `completed` | Yes | All legs done, including the cross-chain delivery | +| `failed` | Yes | Unrecoverable failure — contact support with the `executionId` | +| `needs_review` | Yes | Parked for operator review — contact support with the `executionId` | + +Recommended polling cadence: every 10-15 seconds. On-chain legs typically confirm within a couple of minutes; cross-chain delivery legs (CCTP attestation, LayerZero) commonly take 15-35 minutes. + +## Execution Response Fields + +| Field | Description | +| --- | --- | +| `status` | Lifecycle status (table above) | +| `flow` | Flow identifier, e.g. `REDEEM_RECEIVE_EVM` — which sequence of steps this execution runs | +| `current_step` | The step currently executing or waiting | +| `steps` | `{ completed, total }` progress counters (skipped legs are excluded) | +| `tx_hashes` | Per-leg transaction hashes as they land: `deposit_deploy_tx_hash`, `fraxnet_mint_tx_hash`, `fraxnet_redemption_tx_hash`, `cctp_receive_tx_hash`, `cctp_receive_dest_tx_hash`, `lz_delivery_tx_hash` | +| `timeline` | Ordered per-step entries (`name`, `status`, `tx_hash`, ...) — the authoritative progress record | +| `last_error` | Most recent error message, if any | +| `extended_wait` | `true` when a cross-chain wait has exceeded its normal budget and is being watched on a slower cadence — still in flight and self-healing, no action needed | +| `sleep_until` | When the current durable wait next wakes | diff --git a/pages/fraxnet/contracts/fraxnetDeposit.mdx b/pages/fraxnet/contracts/fraxnetDeposit.mdx index 7374084..a450992 100644 --- a/pages/fraxnet/contracts/fraxnetDeposit.mdx +++ b/pages/fraxnet/contracts/fraxnetDeposit.mdx @@ -123,7 +123,7 @@ function scaleDownTo1e6(uint256 amount1e18) public pure returns (uint256) ## Dependencies -- [`FraxNetDepositFactory`](./FraxNetDepositFactory.sol) +- [`FraxNetDepositFactory`](/fraxnet/contracts/fraxnetDepositFactory) - `IRemoteHop`, `IFrxUSDCustodian`, `IRWAUSDCRedeemer`, `ITokenMessenger` ## Notes diff --git a/pages/fraxnet/contracts/fraxnetDepositFactory.mdx b/pages/fraxnet/contracts/fraxnetDepositFactory.mdx index 1084b18..d1706e6 100644 --- a/pages/fraxnet/contracts/fraxnetDepositFactory.mdx +++ b/pages/fraxnet/contracts/fraxnetDepositFactory.mdx @@ -134,8 +134,8 @@ This ensures deterministic address generation per target chain and address. ## Dependencies -* [`FraxNetDeposit`](./FraxNetDeposit.sol): Proxy child contract -* [`FraxBeacon`](./FraxBeacon.sol): Beacon controlling logic +* [`FraxNetDeposit`](/fraxnet/contracts/fraxnetDeposit): Proxy child contract +* [`FraxBeacon`](/fraxnet/contracts/fraxBeacon): Beacon controlling logic * LayerZero + CCTP + RWA ecosystem interfaces ## Notes diff --git a/pages/fraxnet/contracts/frxUsdCustodians.mdx b/pages/fraxnet/contracts/frxUsdCustodians.mdx index 065d8a0..3c0536a 100644 --- a/pages/fraxnet/contracts/frxUsdCustodians.mdx +++ b/pages/fraxnet/contracts/frxUsdCustodians.mdx @@ -1,7 +1,7 @@ --- -∂title: FrxUSDCustodian +title: FrxUSDCustodian lang: en-US ------------ +--- # FrxUSDCustodian diff --git a/pages/fraxnet/contracts/proxyArchitecture.mdx b/pages/fraxnet/contracts/proxyArchitecture.mdx index f66c36b..c31c5bf 100644 --- a/pages/fraxnet/contracts/proxyArchitecture.mdx +++ b/pages/fraxnet/contracts/proxyArchitecture.mdx @@ -1,9 +1,9 @@ --- -title: FraxnetDeposit +title: Proxy Architecture lang: en-US --- -## Proxy Architecture +# Proxy Architecture FraxNet Deposit contracts are built using an upgradeable proxy architecture to ensure long-term flexibility, security, and compliance. This design allows the core logic of the contracts to be upgraded without changing the contract addresses that users and integrators interact with. By separating the implementation (logic) from the proxy (state and interface), the Frax team can deploy improvements, fix bugs, or adapt to evolving regulatory requirements—such as Genius Act compliance for custodians—without disrupting existing integrations or user experience. @@ -11,10 +11,10 @@ FraxNet Deposit contracts are built using an upgradeable proxy architecture to e ![Screenshot 2025-07-10 at 11.27.29 AM](https://hackmd.io/_uploads/Skht2IpHgg.png) -# Deposit Flow Overview +## Deposit Flow Overview ![Screenshot 2025-07-10 at 11.29.00 AM](https://hackmd.io/_uploads/B14qn8aBll.png) -# Redemption Flow Overview +## Redemption Flow Overview ![Screenshot 2025-07-10 at 11.29.09 AM](https://hackmd.io/_uploads/B1icn86Blg.png) diff --git a/pages/fraxnet/contracts/rwaRedemptionCoordinator.mdx b/pages/fraxnet/contracts/rwaRedemptionCoordinator.mdx index 10142d1..70b3df3 100644 --- a/pages/fraxnet/contracts/rwaRedemptionCoordinator.mdx +++ b/pages/fraxnet/contracts/rwaRedemptionCoordinator.mdx @@ -1,5 +1,5 @@ --- -title: # RWARedemptionCoordinator +title: RWARedemptionCoordinator lang: en-US --- @@ -101,8 +101,8 @@ function scaleDownTo1e6(uint256 amount1e18) public pure returns (uint256) ## Dependencies -- [`FrxUSDCustodian`](./FrxUSDCustodian.sol) -- [`IRWAUSDCRedeemer`](./interfaces/IRWAUSDCRedeemer.sol) +- [`FrxUSDCustodian`](/fraxnet/contracts/frxUsdCustodians) +- [`IRWAUSDCRedeemer`](https://etherscan.io/address/0x19D7Df1387e7722FcCcE2aab4B7FfC72e6592934#code) ## Notes diff --git a/pages/fraxnet/index.mdx b/pages/fraxnet/index.mdx index 3c040d0..c1cdab2 100644 --- a/pages/fraxnet/index.mdx +++ b/pages/fraxnet/index.mdx @@ -7,7 +7,7 @@ lang: en-US FraxNet is a cross-chain interoperability layer purpose-built by Frax Finance to enable trust-minimized minting and redemption of frxUSD across supported networks and financial institutions: -1. FraxNet uses proven cross chain messaging standards like [LayerZero ↗](https://docs.layerzero.network/v2/concepts/getting-started/what-is-layerzero) and [CCTP ↗](https://developers.circle.com/cctp/evm-smart-contracts#messagetransmitterv2-mainnet) in order to facilitate the seemless transfer of assets across a plethora of chains. +1. FraxNet uses proven cross chain messaging standards like [LayerZero ↗](https://docs.layerzero.network/v2/concepts/getting-started/what-is-layerzero) and [CCTP ↗](https://developers.circle.com/cctp/evm-smart-contracts#messagetransmitterv2-mainnet) in order to facilitate the seamless transfer of assets across a wide range of chains. 2. Built for protocol-native bridging, FraxNet contracts allow users to mint and redeem natively across chains without custodial or synthetic bridges. The assets on destination chains are canonical, fungible, and redeemable 1:1. 3. Users of FraxNet have the ability to complete KYB/KYC and participate in revenue share from the T‑Bill yield that compliant stablecoins backed under the [GENIUS Act ↗](https://www.investopedia.com/the-genius-act-impact-on-stablecoins-11765112) must hold as reserves, allowing them to earn passive returns in alignment with regulatory standards (e.g. short-term U.S. Treasury bills) while maintaining trust‑minimal, legally compliant collateral. 4. Users who complete KYB/KYC will be able to redeem frxUSD directly to their linked U.S. bank accounts via ACH wire, enabling seamless, on-chain-to-off-chain conversion of tokenized dollars into traditional fiat—bridging DeFi and regulated financial infrastructure.