Skip to main content

Overview

Different protocols use different fee models for cross-chain swaps. This reference provides the exact formulas and calculations used by each protocol.

THORChain Fee Structure

THORChain fees consist of three main components: affiliate fees, outbound fees, and liquidity fees (slippage).

Fee Components

Fee TypeDescriptionCalculationVariable
Affiliate FeeRevenue share to integrator(inputAmount × affiliateBps) / 10000Optional
Outbound FeeNetwork fee for destinationFixed per chain from APIRequired
Liquidity FeePool slippage cost(inputAmount × slippageBps) / 10000Required

Formula

// Affiliate Fee
affiliateFee = (inputAmount * affiliateBps) / 10000;

// Outbound Fee
outboundFee = fixedOutboundFee; // From inbound_addresses API

// Liquidity Fee (Slippage)
liquidityFee = (inputAmount * slippageBps) / 10000;

// Total Fee
totalFee = affiliateFee + outboundFee + liquidityFee;

// Expected Output
expectedOutput = theoreticalOutput - totalFee;

Example Calculation

Swap 1 BTC → ETH.USDC with 30 BPS affiliate fee and 150 BPS slippage:
const inputAmount = 100000000; // 1 BTC in satoshis
const affiliateBps = 30;
const slippageBps = 150;
const outboundFee = 100000; // 0.001 BTC from API
const theoreticalOutput = 65000000000; // 65,000 USDC

// Calculate fees
const affiliateFee = (100000000 * 30) / 10000;
// = 300000 (0.003 BTC)

const liquidityFee = (100000000 * 150) / 10000;
// = 1500000 (0.015 BTC)

const totalFee = 300000 + 100000 + 1500000;
// = 1900000 (0.019 BTC)

// Expected output
const expectedOutput = 65000000000 - (1900000 * 65000); // Convert to USDC
// ≈ 64876500000 (64,876.5 USDC)

Basis Points (BPS) Explained

BPSPercentageDecimal
10.01%0.0001
100.1%0.001
300.3%0.003
1001%0.01
1501.5%0.015
3003%0.03
10000100%1.0

Slippage Calculation

const slippageBps = params.slippage_bps || params.liquidity_tolerance_bps || 150;

// Validate maximum
if (slippageBps >= 10000) {
  throw new Error("INVALID_TOLERANCE_BPS");
}

// Calculate slippage fee
const slippageFee = (inputAmount * slippageBps) / 10000;
Default Slippage: 150 BPS (1.5%) Maximum Slippage: 9999 BPS (99.99%)

Streaming Swap Fee Impact

Streaming swaps reduce slippage by splitting large swaps into smaller chunks:
// Single swap
const singleSwapSlippage = 500; // BPS

// Streaming swap (10 chunks)
const streamingQuantity = 10;
const avgSlippagePerChunk = 50; // BPS
const totalStreamingSlippage = 50 * 10; // Still 500 BPS total, but better execution
Benefits:
  • Reduced price impact per sub-swap
  • Better average execution price
  • Lower total slippage for large amounts

MAYAChain Fee Structure

MAYAChain uses a similar fee model to THORChain with some differences.

Fee Components

Same as THORChain but with MAYAChain-specific parameters:
// Affiliate Fee
affiliateFee = (inputAmount * affiliateBps) / 10000;

// Outbound Fee
outboundFee = fixedOutboundFee; // From inbound_addresses API

// Liquidity Fee (Slippage)
liquidityFee = (inputAmount * toleranceBps) / 10000;

// Total Fee
totalFee = affiliateFee + outboundFee + liquidityFee;

// Expected Output
expectedOutput = theoreticalOutput - totalFee;

CACAO Decimal Handling

Critical: MAYA.CACAO uses 10 decimals instead of 8!
const decimals = asset === 'MAYA.CACAO' ? 10 : 8;
const normalizedAmount = (amount / Math.pow(10, decimals)) * 1e8;

// Example: 10 CACAO
const amount = '100000000000'; // 10 CACAO (10 decimals)
const normalized = (100000000000 / 1e10) * 1e8;
// = 1000000000 (in standard 1e8 format)

Tolerance Parameter Validation

MAYAChain requires only one tolerance parameter:
if (params.tolerance_bps && params.liquidity_tolerance_bps) {
  throw new Error("CONFLICTING_TOLERANCE_PARAMS");
}

const tolerance = params.tolerance_bps || params.liquidity_tolerance_bps || 150;

Chainflip Fee Structure

Chainflip uses multiple fee types with different multipliers.

Fee Types

TypeDisplay NameMultiplierDescription
INGRESSDeposit Fee1xFee to deposit to Chainflip vault
NETWORKNetwork Fee1xBlockchain network fees
EGRESSBroadcast Fee1xFee to send from vault to destination
BROKERAffiliate Fee1.5xPartner commission (multiplied by 1.5)

Formula

// Sum all fees with multipliers
const totalFee = fees.reduce((sum, fee) => {
  const multiplier = fee.type === 'BROKER' ? 1.5 : 1;
  return sum + (fee.amount * multiplier);
}, 0);

// Expected Output
expectedOutput = inputAmount * exchangeRate - totalFee;

Example Calculation

const fees = [
  { type: 'INGRESS', amount: 5000 },   // 0.00005 BTC
  { type: 'NETWORK', amount: 3000 },   // 0.00003 BTC
  { type: 'EGRESS', amount: 8000 },    // 0.00008 BTC
  { type: 'BROKER', amount: 10000 }    // 0.0001 BTC
];

const totalFee = fees.reduce((sum, fee) => {
  const multiplier = fee.type === 'BROKER' ? 1.5 : 1;
  return sum + (fee.amount * multiplier);
}, 0);

// Calculation:
// INGRESS: 5000 * 1 = 5000
// NETWORK: 3000 * 1 = 3000
// EGRESS: 8000 * 1 = 8000
// BROKER: 10000 * 1.5 = 15000
// Total: 31000 satoshis (0.00031 BTC)

DCA (Dollar Cost Averaging) Impact

Chainflip supports DCA to reduce price impact:
const dcaParams = {
  numberOfChunks: 5,
  chunkIntervalBlocks: 2
};

// Fees are applied per chunk, but overall impact is reduced
const feePerChunk = totalFee / numberOfChunks;

Boost Fee

Optional boost fee for faster execution:
const boostFeeBps = 10; // 0.1%
const boostFee = (inputAmount * boostFeeBps) / 10000;

// Total with boost
const totalWithBoost = totalFee + boostFee;

Low Liquidity Warning

When lowLiquidityWarning: true:
const recommendedSlippage = quote.recommendedSlippageTolerancePercent;
const recommendedSlippageBps = recommendedSlippage * 100;

// Use higher slippage for low liquidity pools
const adjustedSlippage = Math.max(slippageBps, recommendedSlippageBps);

Relay Fee Structure

Relay uses a comprehensive fee model with multiple components.

Fee Components

Fee TypeDescriptionSource
GasBlockchain gas feesPer transaction
RelayerBridge relayer feePer bridge
Relayer GasGas for relayer operationsPer bridge
Relayer ServiceService fee for relayingPer bridge
AppApplication/affiliate feeOptional

Formula

// Extract fees from response
const { gas, relayer, relayerGas, relayerService, app } = quote.fees;

// Total USD cost
const totalFeeUSD =
  (gas?.usd || 0) +
  (relayer?.usd || 0) +
  (relayerGas?.usd || 0) +
  (relayerService?.usd || 0) +
  (app?.usd || 0);

// Output calculation
expectedOutput = quote.details.currencyOut.amount;

Example Calculation

const fees = {
  gas: { usd: 5.50, amount: '2000000000000000' },
  relayer: { usd: 2.00, amount: '800000000000000' },
  relayerGas: { usd: 1.50, amount: '600000000000000' },
  relayerService: { usd: 1.00, amount: '400000000000000' },
  app: { usd: 0.50, amount: '200000000000000' }
};

const totalFeeUSD = 5.50 + 2.00 + 1.50 + 1.00 + 0.50;
// = 10.50 USD

App Fee Configuration

Set custom affiliate fees:
const appFees = {
  recipient: '0xClientFeeAddress...',
  fee: '30' // BPS (0.3%)
};

// Applied to total transaction value
const appFeeAmount = (inputAmount * 30) / 10000;

Price Impact Calculation

Relay differentiates between total impact and swap impact:
const totalImpact = {
  usd: 25.50,
  percent: 1.275  // (25.50 / 2000) * 100
};

const swapImpact = {
  usd: 15.30,
  percent: 0.765  // (15.30 / 2000) * 100
};

// totalImpact = fees + slippage
// swapImpact = slippage only

Multi-Step Route Fees

Each step in a multi-hop route has separate fees:
const route = {
  steps: [
    { action: 'approve', estimatedFees: { gas: { usd: 2.0 } } },
    { action: 'bridge', estimatedFees: { gas: { usd: 5.0 }, relayer: { usd: 3.0 } } },
    { action: 'swap', estimatedFees: { gas: { usd: 4.0 } } }
  ]
};

// Total fees
const totalFees = route.steps.reduce((sum, step) => {
  return sum + Object.values(step.estimatedFees).reduce((s, f) => s + f.usd, 0);
}, 0);
// = 14.0 USD

NEAR Fee Structure

NEAR uses a simplified fee model based on USD value difference.

Formula

// Single network fee combining all costs
networkFee = quote.amountInUsd - quote.amountOutUsd;

// Expected output
expectedOutput = quote.amountOut;

Example Calculation

const quote = {
  amountIn: '1000000000',        // 1000 USDC
  amountInUsd: 1000.00,
  amountOut: '20150000000000000', // 0.02015 ETH
  amountOutUsd: 985.50
};

// Network fee in USD
const networkFee = 1000.00 - 985.50;
// = 14.50 USD

// Represents all protocol costs combined

Gas Fees

NEAR uses fixed gas amounts:
// ft_transfer (token transfers)
const ftTransferGas = '30000000000000'; // 30 TGas

// Attached deposit (required for token operations)
const attachedDeposit = '1'; // 1 yoctoNEAR

Fee Comparison Example

Same swap across different protocols:

Scenario: 1 BTC → ETH.USDC

ProtocolAffiliateOutboundLiquidityOtherTotal USD
THORChain$20 (30 BPS)$65$100 (150 BPS)-$185
MAYAChain$20 (30 BPS)$60$95 (150 BPS)-$175
Chainflip$30 (BROKER)--$25 (fees)$55
Relay---$45 (all)$45
Note: Actual fees vary based on network conditions, liquidity, and current rates.

Fee Optimization Strategies

Minimize Slippage

// For stable pairs, use lower slippage
const stablePairSlippage = 50; // 0.5%

// For volatile pairs, use higher slippage
const volatilePairSlippage = 300; // 3%

// For large amounts, use streaming swaps (THORChain/MAYA)
const streamingParams = {
  streaming_quantity: 10,
  streaming_interval: 3
};

Choose Optimal Protocol

// Compare total fees across protocols
function selectOptimalProtocol(quotes) {
  return quotes.reduce((best, quote) => {
    const currentFees = quote.fees.reduce((sum, f) => sum + f.usd, 0);
    const bestFees = best.fees.reduce((sum, f) => sum + f.usd, 0);
    return currentFees < bestFees ? quote : best;
  });
}

Balance Speed vs Cost

// Fast but potentially higher fees
const fastestQuote = quotes.reduce((fastest, q) =>
  q.total_swap_seconds < fastest.total_swap_seconds ? q : fastest
);

// Cheapest but potentially slower
const cheapestQuote = quotes.reduce((cheapest, q) => {
  const qFees = q.fees.reduce((sum, f) => sum + f.usd, 0);
  const cheapestFees = cheapest.fees.reduce((sum, f) => sum + f.usd, 0);
  return qFees < cheapestFees ? q : cheapest;
});

Best Practices

  1. Always display total fees in USD for user transparency
  2. Break down fee components to help users understand costs
  3. Show price impact separately from network fees
  4. Use protocol-recommended slippage for low liquidity pools
  5. Cache outbound fees from THORChain/MAYA APIs (update hourly)
  6. Account for decimal differences (especially MAYA.CACAO’s 10 decimals)
  7. Multiply BROKER fees by 1.5x for Chainflip calculations
  8. Compare effective rates (output/input) across protocols, not just fees
  9. Warn users about high price impact (>5%) before swap execution
  10. Update gas prices frequently (every 1-2 minutes) for accurate estimates