Skip to main content
Bridge Kit lets you customize fees to collect from your end users. This guide explains which fees apply, how funds move through a transaction, and the best practices to follow when implementing custom fees. For how to implement fees in code, see Collect a Transfer Fee.
Note: Circle keeps 10% of the custom fee you collect from your end users.

Fees breakdown

Every transfer can incur the following fees:
  • Your custom fee: The extra amount you charge on top of the transfer. Circle keeps 10% of this amount. The remaining 90% goes to the fee recipient you configure on the source blockchain.
  • CCTP protocol fee: For Fast Transfers only, CCTP collects ~1 bps of the transfer amount before forwarding the remaining funds to the destination. Standard Transfers (SLOW speed) do not incur this fee. For how to configure the transfer speed, see Configure Transfer Speed and Maximum Cost.

Funds flow

The following example shows what happens when a user initiates a 1,000 USDC Fast Transfer with a 1% custom fee:
  1. The user initiates a 1000 USDC transfer on the source blockchain.
  2. You add a 10 USDC (1%) custom fee.
  3. The source wallet signs a transaction for 1,010 USDC (transfer amount + custom fee).
  4. The 10 USDC custom fee is split on the source blockchain:
    • Circle receives 1 USDC (10%) .
    • Your fee recipient receives 9 USDC (remaining 90%).
  5. The 1000 USDC transfer amount is forwarded to CCTP.
  6. CCTP takes a 0.10 USDC (1 bps on the transfer amount) protocol fee for a Fast Transfer.
  7. The destination wallet receives 999.90 USDC on the destination blockchain.
This flow is illustrated in the following diagram:

Best practices

Follow these best practices when implementing custom fees:
  • Treat the custom fee as an amount added on top of the transfer. Do not subtract it from the transfer amount.
  • Validate that the user’s wallet balance covers both the transfer and the custom fee. The following code shows an example balance check:
TypeScript
const requiredBalance = parseFloat(amount) + parseFloat(customFee);
if (userBalance < requiredBalance) {
  throw new Error(`Insufficient balance. Need ${requiredBalance} USDC`);
}
  • Use a fee recipient address on the source blockchain. Do not use an address on the destination.
  • In your UI, display the following to the user before they confirm the transaction:
    • The total source wallet debit: transfer amount + custom fee
    • The full fee breakdown: transfer amount, custom fee, CCTP Fast Transfer fee (if applicable)
  • Return human-readable decimal strings. For example, 10 rather than 10000000 for 10 USDC. Bridge Kit handles base-unit conversion internally.