Skip to content

fix(cctp): pay Circle's Fast Transfer fee instead of offering zero - #210

Merged
0xdevcollins merged 1 commit into
mainfrom
fix/cctp-fast-transfer-fee
Aug 9, 2026
Merged

0xdevcollins merged 1 commit into
mainfrom
fix/cctp-fast-transfer-fee

Conversation

@0xdevcollins

Copy link
Copy Markdown
Owner

Why a payment sits at SOURCE_LOCKED with attestation: null while the checkout says "8–20 seconds".

The cause

selectCrypto built every EVM burn with speed: 'fast' and maxFee: 0n hardcoded.

Circle does not reject that combination. It accepts the burn, then holds the message at pending_confirmations and waits for hard finality instead. The only place this is visible is Iris's own response:

{ "status": "pending_confirmations",
  "cctpVersion": 2,
  "delayReason": "insufficient_fee" }

So every EVM payment took the slow path — fifteen-plus minutes — while the UI promised seconds, and nothing in our logs explained it.

The fix

Circle publishes the price per route:

GET /v2/burn/USDC/fees/0/27
[{"finalityThreshold":1000,"minimumFee":1},
 {"finalityThreshold":2000,"minimumFee":0}]

1 basis point for fast on Ethereum → Stellar; free for standard.

BurnFeeService reads that, caches per route for five minutes, and converts basis points into a maxFee. Two details that matter:

  • Rounds up, never to zero. 1 bp of a one-cent payment is 0.0001 USDC, which truncates to nothing in 6-decimal subunits — and maxFee: 0 is the exact condition being fixed. One extra subunit beats a quarter-hour settlement.
  • Falls back to standard finality when the lookup fails, rather than asking for fast and being demoted anyway. Slower, but it's what actually happens, and it's logged.

Verified live

A 15 USDC burn now carries maxFee: 1500 subunits at minFinalityThreshold: 1000. Previously 0.

Tests: 317 (+14) — the rounding floor, the fallback, per-route caching, and both selectCrypto paths. 0 lint errors.

Note on the in-flight payment

A burn already submitted with maxFee: 0 is not lost — it settles on hard finality (~15–20 min on Sepolia) and the worker will pick it up. This only changes burns built from here on.

Every EVM payment took the slow path. `selectCrypto` built its burn with
`speed: 'fast'` and `maxFee: 0n` hardcoded, and Circle does not reject that
combination — it accepts the burn, then holds the message at
`pending_confirmations` with `delayReason: insufficient_fee` and waits for hard
finality instead. So the checkout promised "8–20 seconds via Circle CCTP V2"
and delivered fifteen-plus minutes, with nothing in our logs to say why. The
demotion is only visible in Iris's own response.

Circle publishes the price per route. For Ethereum → Stellar it is 1 basis
point on the fast tier and nothing on standard:

    GET /v2/burn/USDC/fees/0/27
    [{"finalityThreshold":1000,"minimumFee":1},
     {"finalityThreshold":2000,"minimumFee":0}]

`BurnFeeService` reads that, caches it for five minutes per route, and converts
basis points into a `maxFee` for the amount. The conversion rounds up and never
returns zero for a non-zero rate: 1 bp of a one-cent payment is 0.0001 USDC,
which truncates to nothing in 6-decimal subunits — and a maxFee of zero is the
exact condition being fixed. One extra subunit is cheaper than a quarter-hour
settlement.

When the lookup fails the burn drops to standard finality rather than asking
for fast and being demoted anyway. Slower, but it is what actually happens, and
it is logged.

Verified live: a 15 USDC burn now carries maxFee 1500 subunits at
minFinalityThreshold 1000, where it previously carried 0.

Tests: 317 (+14), covering the rounding floor, the fallback, per-route caching
and the two selectCrypto paths.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 9, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
useroutr-www Ready Ready Preview Aug 9, 2026 11:00pm

@0xdevcollins
0xdevcollins merged commit f155d71 into main Aug 9, 2026
7 checks passed
@0xdevcollins
0xdevcollins deleted the fix/cctp-fast-transfer-fee branch August 9, 2026 23:01

This branch was successfully deployed

1 active deployment
Preview – useroutr-www — 9322a571 Deployed Aug 9, 2026 by vercel[bot]
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