Skip to content

fix: select the fast-transfer fee tier explicitly instead of by array order - #178

Open
bars26 wants to merge 1 commit into
circlefin:masterfrom
bars26:fix/fast-transfer-fee-tier-selection
Open

bars26 wants to merge 1 commit into
circlefin:masterfrom
bars26:fix/fast-transfer-fee-tier-selection

Conversation

@bars26

@bars26 bars26 commented Sep 10, 2026

Copy link
Copy Markdown

What

getBufferedFastTransferFee in src/hooks/use-cross-chain-transfer.ts reads the fee from the first element of the response:

const feePayload = (await response.json()) as FastTransferFeeResponse[];
const feeEntry = feePayload[0];

The /v2/burn/USDC/fees/{src}/{dst} endpoint returns one entry per finality tier, e.g.:

[{ "finalityThreshold": 1000, "minimumFee": 1 }, { "finalityThreshold": 2000, "minimumFee": 0 }]

getBufferedFastTransferFee is only called for fast transfers, which burn with minFinalityThreshold = FAST_FINALITY_THRESHOLD (1000). Taking [0] assumes the fast tier is always first. It currently is, but that ordering is not documented. If the standard tier (minimumFee: 0) is returned first, a fast transfer computes maxFee = 0 and the on-chain depositForBurn reverts, because a fast transfer's maxFee must cover the tier's minimum fee.

FastTransferFeeResponse also does not model finalityThreshold, so there is nothing to select on today.

Fix

  • Add finalityThreshold to FastTransferFeeResponse.
  • Pick the entry for the tier actually being burned (finalityThreshold <= FAST_FINALITY_THRESHOLD), falling back to feePayload[0] so behaviour is unchanged when nothing matches.
 interface FastTransferFeeResponse {
+  finalityThreshold: number;
   minimumFee: number | string;
 }
-    const feeEntry = feePayload[0];
+    // Select the fee for the tier we actually burn at (fast transfers pass
+    // minFinalityThreshold = FAST_FINALITY_THRESHOLD) rather than trusting the
+    // order of the response array.
+    const feeEntry =
+      feePayload.find(
+        (entry) => entry.finalityThreshold <= FAST_FINALITY_THRESHOLD,
+      ) ?? feePayload[0];

One file. No dependency, ABI, or API changes.

🤖 Generated with Claude Code

… order

getBufferedFastTransferFee read feePayload[0], assuming the fast finality
tier is always first in the /v2/burn/USDC/fees response. That ordering is
undocumented; if the standard tier (minimumFee 0) comes first a fast
transfer would burn with maxFee 0 and revert on-chain. Model
finalityThreshold on the response type and pick the tier that matches the
burn (FAST_FINALITY_THRESHOLD), falling back to feePayload[0].

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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