> ## Content Index
> Fetch the complete content index at: https://stablecoininsider.org/llms.txt
> Use this file to discover other available public pages before exploring further.

# How to Pay Circle Bridge Kit Fees on the Source Chain (2026)
- URL: https://stablecoininsider.org/how-to-pay-circle-bridge-kit-fees-on-source/
- Published: 2026-10-12T12:01:00.000Z
- Updated: 2026-10-12T12:45:32.000Z
- Description: Receive-exact USDC with Circle Bridge Kit: estimate → opaque quote → bridge, totalDebit vs amountReceived, and when source-paid fees beat destination deduction.
- Author: Alexandra
- Tags: Fintech, Stablecoins

Default Circle Bridge Kit forwarding takes Fast Transfer and Forwarding Service fees out of the destination mint. That is fine for treasury rebalances. It breaks checkout and payroll flows where the recipient must land the exact USDC amount you promised.

This Stablecoin Insider how-to covers **Circle Bridge Kit fees** paid on the source chain: **config.feePayment: 'source'** with **useForwarder: true**, the opaque Fee Service quote, **estimate → bridge**, **TokenMessengerWithFees**, and the SLOW-only constraint on Avalanche, Polygon PoS, Sei, and XDC. It is a follow-on to Stablecoin Insider's [How to Transfer USDC with Circle Bridge Kit](https://stablecoininsider.org/how-to-transfer-usdc-with-circle-bridge-kit/) (kit.bridge basics). No Fee Service credentials were available for a live quote, so live fee numbers from Arc's tutorial sample stay labeled as docs examples.

### Key Takeaways

- feePayment:'source' + useForwarder:true delivers receive-exact USDC on destination.
- Call kit.estimate, pass the opaque quote into kit.bridge before it expires.
- Source wallet pays totalDebit (amount + feeTotal); amountReceived equals amount.
- On Avalanche, Polygon PoS, Sei, and XDC sources, set transferSpeed:'SLOW'.
- No customFee with source fees; live Fee Service quotes need route credentials.

🧭

What this guide is: a package and docs audit of @circle-fin/bridge-kit 1.15.2 receive-exact / source-paid fees (npm latest as of 11 October 2026), checked against the published README, index.d.mts types, Arc App Kit pay-fees-on-source and use-forwarding-service tutorials, plus a TypeScript dry-run that confirmed kit.estimate narrows to ReceiveExactEstimateResult when feePayment is 'source'. No mainnet funds moved. Live Fee Service quotes: unavailable (no Circle Fee Service / adapter credentials in this environment).

## What source-paid Circle Bridge Kit fees change

By default, CCTP Fast Transfer and Forwarding Service fees are taken from the amount minted on the destination chain. Arc's [pay fees on the source chain](https://docs.arc.io/app-kit/tutorials/bridge/pay-fees-on-source) tutorial states the alternative: pay those fees upfront on the source chain so the recipient receives the exact bridge amount.

The published [Bridge Kit 1.15.2 README](https://cdn.jsdelivr.net/npm/@circle-fin/bridge-kit@1.15.2/README.md) calls this receive-exact forwarding. Bridge Kit obtains a short-lived signed Fee Service quote, approves amount + feeTotal in source-chain USDC, and burns exactly amount through **TokenMessengerWithFees**. The destination mint is not reduced.

That is a different product promise than destination-deducted forwarding. Destination-paid mode is simpler for one wallet that owns both legs. Source-paid mode is for merchants, payroll, and custodial payouts that advertise "you receive N USDC" and cannot silently shave basis points at mint.

[How to Transfer USDC with Circle Bridge Kit (2026)Sibling how-to for kit.bridge basics, FAST vs SLOW, and useForwarder without source-paid fees.![](https://stablecoininsider.org/favicon.ico)Stablecoin Insider](https://stablecoininsider.org/how-to-transfer-usdc-with-circle-bridge-kit/)

## npm and API facts Stablecoin Insider checked on 11 October 2026

Stablecoin Insider pulled registry metadata, the downloads API, and the 1.15.2 tarball the same afternoon this post was drafted. Numbers below are point-in-time, not projections.

| Fact                                  | Value                                                                                                 | Source                                                                                |
| ------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| Package / version                     | [@circle-fin/bridge-kit](https://cdn.jsdelivr.net/npm/@circle-fin/bridge-kit@1.15.2/README.md) 1.15.2 | npm registry (published 30 Sep 2026)                                                  |
| Weekly downloads (4–10 Oct 2026)      | [17,447](https://api.npmjs.org/downloads/point/2026-10-04:2026-10-10/@circle-fin/bridge-kit)          | npm downloads API point range                                                         |
| Monthly downloads (10 Sep–9 Oct 2026) | [78,438](https://api.npmjs.org/downloads/point/last-month/@circle-fin/bridge-kit)                     | npm downloads API last-month                                                          |
| Node engines                          | \>= 20.0.0                                                                                            | package.json engines                                                                  |
| Fee dependency                        | @circle-fin/provider-fee-v1 ^0.3.2                                                                    | package.json dependencies                                                             |
| Receive-exact since                   | 1.14.0 (types @since)                                                                                 | [index.d.mts](https://cdn.jsdelivr.net/npm/@circle-fin/bridge-kit@1.15.2/index.d.mts) |

Source: [Bridge Kit README on jsDelivr](https://cdn.jsdelivr.net/npm/@circle-fin/bridge-kit@1.15.2/README.md), [npm downloads API for 4–10 October 2026](https://api.npmjs.org/downloads/point/2026-10-04:2026-10-10/@circle-fin/bridge-kit) (17,447 downloads), and [last-month downloads](https://api.npmjs.org/downloads/point/last-month/@circle-fin/bridge-kit) (78,438 for 10 September–9 October 2026).

Naming note for engineers reading both surfaces: Arc App Kit tutorials call the pre-flight method **kit.estimateBridge**. The published npm class **BridgeKit** exposes **kit.estimate** (and **kit.bridge**). Stablecoin Insider's Node dry-run on 1.15.2 confirmed **typeof BridgeKit.prototype.estimateBridge === 'undefined'** while estimate, bridge, findSourceFeeProvider, and getSupportedChains are present. Code samples below use the npm method names.

## The receive-exact API shape: feePayment, useForwarder, quote

Stablecoin Insider unpacked the 1.15.2 tarball and read [package/index.d.mts](https://cdn.jsdelivr.net/npm/@circle-fin/bridge-kit@1.15.2/index.d.mts). BridgeConfig.feePayment is optional 'source' | 'destination'. When feePayment is 'source', TypeScript overloads kit.estimate to return **ReceiveExactEstimateResult** (amountReceived, feeTotal, feeItems, totalDebit, quoteExpiry, quote). Arc's tutorial describes the same two-step flow: estimate with feePayment source, then bridge with the same params plus the quote.

```
import { BridgeKit } from '@circle-fin/bridge-kit'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'

const kit = new BridgeKit()
const adapter = createViemAdapterFromPrivateKey({
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
})

const params = {
  from: { adapter, chain: 'Ethereum' },
  to: {
    chain: 'Base',
    recipientAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
    useForwarder: true, // required with feePayment: 'source'
  },
  amount: '100',
  config: {
    transferSpeed: 'FAST',
    feePayment: 'source',
  },
} as const

const estimate = await kit.estimate(params)
// ReceiveExactEstimateResult: amountReceived, feeTotal, totalDebit, quoteExpiry, quote
const result = await kit.bridge({
  ...params,
  quote: estimate.quote, // opaque 0x-prefixed hex; do not decode or log
})
```

That pattern matches both the [README receive-exact section](https://cdn.jsdelivr.net/npm/@circle-fin/bridge-kit@1.15.2/README.md) and Arc's [pay-fees-on-source tutorial](https://docs.arc.io/app-kit/tutorials/bridge/pay-fees-on-source) (which names the estimate method estimateBridge). **useForwarder: true is mandatory**. Arc's docs say omitting it (or setting false) throws a validation error. The [Forwarding Service tutorial](https://docs.arc.io/app-kit/tutorials/bridge/use-forwarding-service) explains why: the forwarder fetches the attestation and submits the destination mint, so the recipient does not need a destination signer.

## What EstimateResult fields mean (and the Arc sample numbers)

When feePayment is source, the estimate is a ReceiveExactEstimateResult. Fields Stablecoin Insider verified in types:

- **amountReceived**: exact USDC the destination recipient receives (equals amount)
- **feeTotal**: total source-chain USDC fee (sum of feeItems)
- **totalDebit**: amountReceived + feeTotal (what the source wallet must hold and approve)
- **fees**: familiar breakdown (forwarder / provider)
- **feeItems**: signed Fee Service line items (FORWARD, PRE\_FINALITY) with args / argsHash
- **quoteExpiry**: TIMESTAMP (expiresAt unix seconds) or BLOCK\_NUMBER (expiresAtBlock + optional blockEstimatedAt)
- **quote**: opaque signed hex; pass through unchanged

Arc's tutorial shows a worked Sepolia → Arc Testnet sample for 1.00 USDC. In that docs example, amountReceived is "1.0", feeTotal is "0.076527", totalDebit is "1.076527", with feeItems FORWARD "0.076397" and PRE\_FINALITY "0.00013", and quoteExpiry mode BLOCK\_NUMBER at expiresAtBlock 45947392\. Those figures are **documentation examples from Arc**, not a live quote Stablecoin Insider fetched. Live Fee Service quotes were **unavailable** in this environment (no adapter private key / Fee Service credentials), so production UIs must call kit.estimate on the real route and render the returned totalDebit.

⚠️

Quote opacity and expiry: treat quote as sensitive raw bytes. Bridge Kit validates a supplied quote before and after approval and fails closed if it is invalid, mismatched, expired, or too close to expiry. It never silently replaces a caller-supplied quote. On failure, call estimate again and retry. Omitting quote lets the SDK fetch and refresh for you.

## How to pay Circle Bridge Kit fees on the source chain (step by step)

### Step 1: Install Bridge Kit 1.15.2+ and an EVM adapter

Receive-exact types are marked @since 1.14.0\. Stablecoin Insider tested against 1.15.2\. Node.js >= 20 is required.

```
npm install @circle-fin/bridge-kit@1.15.2 @circle-fin/adapter-viem-v2 viem
# engines: node >= 20.0.0
```

### Step 2: Confirm the source chain supports source fees

A chain qualifies when it configures a TokenMessengerWithFees wrapper. List them:

```
const sourceFeeChains = kit.getSupportedChains({ sourceFeeSupported: true })
console.log(sourceFeeChains.map((c) => c.chain))
// Arc tutorial form: kit.getSupportedChains("bridge", { sourceFeeSupported: true })
```

BridgeKit also exposes findSourceFeeProvider on the prototype (confirmed in Stablecoin Insider's dry-run). Use it when you need the provider that can honor feePayment source for a given route.

### Step 3: Estimate with feePayment source and useForwarder true

Build the same params object you will later pass to bridge. Set config.feePayment to 'source' and to.useForwarder to true. Call kit.estimate. Narrow on 'amountReceived' in estimate (or rely on the TypeScript overload) before you show totalDebit to the user.

### Step 4: Bridge with the opaque quote (or omit it for SDK refresh)

Pass quote: estimate.quote into kit.bridge with identical from / to / amount / config. If the quote is near expiry, re-estimate. Prefer omitting quote only when you accept SDK-managed fetch and refresh; for checkout UIs, Stablecoin Insider prefers an explicit estimate → user confirm → bridge with that quote so the on-screen totalDebit matches the burn.

### Step 5: Use SLOW on Standard Transfer-only sources

transferSpeed defaults to FAST. Arc's [requirements section](https://docs.arc.io/app-kit/tutorials/bridge/pay-fees-on-source) states that some source chains support only CCTP Standard Transfer, naming **Avalanche, Polygon PoS, Sei, XDC, and their testnets**. On those chains, keep feePayment source and set transferSpeed: 'SLOW'. Using FAST (or omitting transferSpeed) can fail with a Quote API error such as PRE\_FINALITY\_UNAVAILABLE (often HTTP 422).

```
await kit.bridge({
  from: { adapter, chain: 'Avalanche' },
  to: {
    recipientAddress: '0xRecipient',
    chain: 'Base',
    useForwarder: true,
  },
  amount: '1.00',
  config: {
    feePayment: 'source',
    transferSpeed: 'SLOW', // required on Standard-only sources
  },
})
```

For product trade-offs between Fast and Standard outside the source-fee path, see Stablecoin Insider's [CCTP Fast vs Standard guide](https://stablecoininsider.org/how-to-choose-cctp-fast-vs-standard-transfer/).

## TokenMessengerWithFees vs manual depositForBurn

Under the hood, source-paid burns do not call plain TokenMessengerV2.depositForBurn with maxFee and minFinalityThreshold. Types document adapter action cctp.v2.depositForBurnWithFees on **TokenMessengerWithFees**: the wrapper collects fees via FeeManager against a signed QuoteClaim, then delegates to unmodified TokenMessengerV2\. When hookData is present (GenericExecutor FORWARD path), the contract method is depositForBurnWithHookAndFees.

Unlike depositForBurn, TokenMessengerWithFees methods do not take maxFee or minFinalityThreshold. Fee and finality behavior are derived from the signed quote. That is why quote expiry races matter: once the quote is stale, the on-chain call is designed to reject rather than invent a new fee.

| Attribute                     | Source-paid Bridge Kit                       | Manual CCTP depositForBurn + self-mint                       |
| ----------------------------- | -------------------------------------------- | ------------------------------------------------------------ |
| Recipient amount              | Exact amount (amountReceived == amount)      | You choose; mint is burn minus whatever you allow            |
| Fee collection                | Upfront USDC on source via Fee Service quote | Usually maxFee ceiling; destination or your relayer pays gas |
| Burn contract                 | TokenMessengerWithFees (+ Fees methods)      | TokenMessengerV2.depositForBurn                              |
| maxFee / minFinalityThreshold | Omitted; bound in signed quote               | You set both on the burn                                     |
| Destination mint              | Forwarding Service required (useForwarder)   | Your bot submits receiveMessage                              |
| Custom developer fee          | Not supported with feePayment source         | Your own skim if you wrap the burn                           |
| Attestation ownership         | Orbit / Forwarding Service                   | You poll Iris and mint                                       |

Source: [Bridge Kit 1.15.2 index.d.mts](https://cdn.jsdelivr.net/npm/@circle-fin/bridge-kit@1.15.2/index.d.mts) (depositForBurnWithFees remarks), [README](https://cdn.jsdelivr.net/npm/@circle-fin/bridge-kit@1.15.2/README.md), [Arc pay-fees-on-source](https://docs.arc.io/app-kit/tutorials/bridge/pay-fees-on-source), and Circle's [CCTP overview](https://developers.circle.com/cctp) / [CCTP fees](https://developers.circle.com/cctp/concepts/fees).

## When source-paid fees beat destination-deducted forwarding

Stablecoin Insider's take is operational, not a fee forecast. Source-paid fees win when:

- The recipient contract or user is owed an exact USDC amount (invoices, payroll, OTC settlement).
- The destination wallet cannot hold spare USDC to cover a shaved mint.
- Your UI already shows a locked receive amount and cannot re-quote after the user confirms.
- You are bridging into Arc or another app where gas is USDC-denominated and the receiver must spend the full credited amount immediately.

Destination-deducted forwarding still wins for same-owner rebalances, when the source EOA is USDC-rich but gas-poor and you would rather shave the mint than acquire source gas plus feeTotal, and when you need config.customFee (Arc and the README both say custom fees are incompatible with feePayment source; the SDK throws by design).

## Who this fails for (named downsides)

- **EOA gas on source.** Source-paid mode spends source-chain native gas for approve + burn and also locks feeTotal in USDC. A recipient-funded gas model does not erase the source gas bill.
- **Quote expiry races.** Quotes are short-lived (TIMESTAMP or BLOCK\_NUMBER). Slow user confirmation UIs that cache quote across a long wait will fail closed. Re-estimate; do not patch the hex.
- **SLOW-only chains.** Avalanche, Polygon PoS, Sei, and XDC (and testnets) need transferSpeed SLOW with source fees. FAST yields PRE\_FINALITY\_UNAVAILABLE-class Quote API errors.
- **No customFee.** Integrators who skim 90/10 developer fees must stay on the destination fee path.
- **EVM-first receive-exact.** README states the initial release supports EVM sources, EVM destinations, and source-chain USDC fee payment. Do not assume Solana source fees without re-reading the version you pin.
- **429 / 503 Fee Service responses.** README: on 429, caller-managed exponential backoff; 503 SERVICE\_NOT\_ENABLED means the source route is disabled and should not be retried.
- **Partial forwarder errors.** Arc notes that if the burn confirms but the Forwarding Service returns no destination tx hash, the SDK can return an error-state BridgeResult that still includes the burn step (retryable). Inspect result.state and result.steps before re-burning.

💡

Stablecoin Insider's take: pay Circle Bridge Kit fees on the source chain when the product promise is receive-exact USDC. Treat the Fee Service quote like a signed FX ticket: opaque, short-lived, and fatal if edited. Keep destination-deducted forwarding for owner-operated rebalances, and keep manual CCTP when you need a custom burn wrapper or your own attestation worker. Estimate first, confirm totalDebit, pass the quote, and force SLOW on Avalanche / Polygon / Sei / XDC sources.

## Where this sits next to aggregators and plain bridges

Source-paid Bridge Kit is still CCTP burn-and-mint, not a liquidity bridge and not a multi-bridge quote engine. For wrapped-asset routes and multi-bridge comparisons, use Stablecoin Insider's [best crypto cross-chain bridges in 2026](https://stablecoininsider.org/best-crypto-cross-chain-bridges-in-2026/) and [best cross-chain aggregators for 2026](https://stablecoininsider.org/best-cross-chain-aggregators-for-2026/). When the asset or route leaves Circle's CCTP set, compare [LI.FI](https://stablecoininsider.org/lifi-cross-chain-aggregator-2026/). For a Solana-specific USDC walkthrough outside Bridge Kit fees, see [how to bridge USDC from Ethereum to Solana](https://stablecoininsider.org/how-to-bridge-usdc-from-ethereum-to-solana-step-by-step-2026/).

---

If you still need the basic kit.bridge path without source fees, start with the sibling guide, then return here when the recipient must receive the exact amount.

[Open Arc: Pay fees on the source chain](https://docs.arc.io/app-kit/tutorials/bridge/pay-fees-on-source)

Need the Bridge Kit one-liner before you add feePayment source? Read the sibling transfer guide.

[How to Transfer USDC with Circle Bridge Kit ](https://stablecoininsider.org/how-to-transfer-usdc-with-circle-bridge-kit/) 

[How to Choose CCTP Fast vs Standard TransferDecision guide for transferSpeed FAST vs SLOW before you lock source-paid fees.![](https://stablecoininsider.org/favicon.ico)Stablecoin Insider](https://stablecoininsider.org/how-to-choose-cctp-fast-vs-standard-transfer/)

## FAQ

#### What does feePayment source do in Circle Bridge Kit?

It pays Fast Transfer and Forwarding Service fees upfront in source-chain USDC so the destination recipient receives the exact bridge amount. You must also set useForwarder: true.

#### Is the method called estimate or estimateBridge?

On npm @circle-fin/bridge-kit 1.15.2 the method is kit.estimate (BridgeKit.prototype.estimateBridge is undefined). Arc App Kit tutorials document kit.estimateBridge for the same two-step estimate-then-bridge flow.

#### What is TokenMessengerWithFees?

It is the CCTP wrapper that collects a signed Fee Service quote on the source chain, then delegates the burn to TokenMessengerV2\. Bridge Kit uses depositForBurnWithFees / depositForBurnWithHookAndFees instead of plain depositForBurn with maxFee.

#### Why do Avalanche and Polygon need transferSpeed SLOW?

Arc's pay-fees-on-source docs list Avalanche, Polygon PoS, Sei, XDC, and their testnets as Standard Transfer-only sources. FAST (the default) can return PRE\_FINALITY\_UNAVAILABLE from the Quote API.

#### Can I combine customFee with source-paid fees?

No. Arc and the Bridge Kit README state custom fees are not supported with feePayment source; the SDK throws. Collect integrator fees only on the destination fee path.

#### What happens if the Fee Service quote expires?

Bridge Kit fails closed. It does not silently replace a caller-supplied quote. Call estimate again and pass the new quote. quoteExpiry is either a unix TIMESTAMP or a source-chain BLOCK\_NUMBER.

#### Did Stablecoin Insider run a live Fee Service quote?

No. Live quotes were unavailable without Fee Service / adapter credentials. Arc's published sample (1.00 USDC with feeTotal 0.076527) is cited as a documentation example only.

#### When should I still use manual CCTP instead?

When you need a custom burn wrapper, your own attestation worker, unsupported routes, or gas accounting inside a larger contract flow. Circle still positions Bridge Kit for app integrations and raw CCTP for full backend control.

---

This content is provided for informational and educational purposes only and does not constitute financial, investment, legal, or tax advice; no material herein should be interpreted as a recommendation, endorsement, or solicitation to buy or sell.