Skip to main content

Fee Calculations

Complete guide to understanding and calculating fees in Pons Network.

Fee Overview

Pons Network uses dynamic fees - just like Ethereum gas! Pay more for faster execution, or save money with lower fees.

Fee Breakdown

User sends: 15.00 tokens
Network Fee (~0.01%)Cross-chain relay
Expected AmountArrives at Smart Account
Protocol Fee (~0.1%)Pons treasury
Indexer FeeIndexer operator (DYNAMIC)
Resolver FeeResolver operator (DYNAMIC)
Amount for ActionYour action executes with this

Dynamic Fee Model

Fees work like Ethereum gas:

  1. Users set their own fees - like setting gas price
  2. Operators compete - they choose which transactions to process
  3. Higher fees = priority - operators process profitable transactions first
  4. Market equilibrium - supply/demand determines fair prices

Speed Tiers

SpeedIndexer FeeResolver FeeEst. TimeUse Case
FastHigherHigherFasterTime-sensitive
StandardMediumMediumNormalBalanced
EconomyLowerLowerSlowerCost-sensitive

Fees are paid in your chosen token. Set fees based on market conditions and desired speed.


Fee Components

1. Network Fee (~0.01%)

Purpose: Cross-chain message relay
Rate: ~0.01% of send amount
When: During cross-chain transfer

2. Protocol Fee (~0.1%)

Purpose: Pons Network protocol treasury
Rate: ~0.1% of expected amount
When: Before action executes

3. Indexer Fee (DYNAMIC)

Purpose: Reward for the indexer who relays assets
Amount: Dynamic - YOU choose!
Recipient: Indexer operator (decentralized)

4. Resolver Fee (DYNAMIC)

Purpose: Reward for the resolver who executes your action
Amount: Dynamic - YOU choose!
Recipient: Resolver operator (decentralized)


Fee Calculation Functions

calculateFeesSync(sendAmount, options?)

Calculate fees with custom fee rates.

import { calculateFeesSync } from '@pons-network/pons.js';
import { parseUnits, formatUnits } from 'viem';

// Standard fees
const standard = calculateFeesSync(parseUnits('15', 6));

// Fast fees (2x operator fees)
const fast = calculateFeesSync(parseUnits('15', 6), {
indexerFee: parseUnits('0.2', 6),
resolverFee: parseUnits('0.3', 6),
});

// Economy fees (0.5x operator fees)
const economy = calculateFeesSync(parseUnits('15', 6), {
indexerFee: parseUnits('0.05', 6),
resolverFee: parseUnits('0.08', 6),
});

console.log('Standard:', formatUnits(standard.amountForAction, 6), 'USDC');
console.log('Fast:', formatUnits(fast.amountForAction, 6), 'USDC');
console.log('Economy:', formatUnits(economy.amountForAction, 6), 'USDC');

Returns:

{
burnAmount: bigint; // Input send amount
cctpFee: bigint; // Network fee
expectedAmount: bigint; // Amount arriving at Smart Account
protocolFee: bigint; // Protocol fee
indexerFee: bigint; // Indexer operator fee
resolverFee: bigint; // Resolver operator fee
totalFees: bigint; // Sum of all fees
amountForAction: bigint; // Available for your action
}

calculateBurnForAction(actionAmount, options?)

Reverse calculation: Given how much you need for an action, calculate send amount.

import { calculateBurnForAction } from '@pons-network/pons.js';

// NFT costs 10 USDC - how much to send?
const fees = calculateBurnForAction(parseUnits('10', 6));
console.log('Send:', formatUnits(fees.burnAmount, 6), 'USDC');

// Same, but with fast execution
const fastFees = calculateBurnForAction(parseUnits('10', 6), {
indexerFee: parseUnits('0.2', 6),
resolverFee: parseUnits('0.3', 6),
});
console.log('Send (fast):', formatUnits(fastFees.burnAmount, 6), 'USDC');

validateActionFeasibility(sendAmount, actionCost, options?)

Validate if send amount is sufficient.

import { validateActionFeasibility } from '@pons-network/pons.js';

const result = validateActionFeasibility(
parseUnits('15', 6), // User sends
parseUnits('14', 6) // Action needs
);

if (!result.feasible) {
console.log(`Need at least ${formatUnits(result.minimumBurn, 6)} USDC`);
}

Returns:

{
feasible: boolean; // Is it possible?
burnAmount: bigint; // Input send amount
amountForAction: bigint; // Available after fees
actionCost: bigint; // Input action cost
surplus: bigint; // Extra amount if feasible
shortfall: bigint; // Missing amount if not feasible
minimumBurn: bigint; // Minimum send needed
message: string; // Human-readable message
}

DEFAULT_FEES

Default fee constants (standard market rate).

import { DEFAULT_FEES } from '@pons-network/pons.js';

DEFAULT_FEES.CCTP_FEE_BPS // 1n (0.01%)
DEFAULT_FEES.PROTOCOL_FEE_BPS // 10n (0.1%)
DEFAULT_FEES.INDEXER_FEE // 100000n (default indexer fee)
DEFAULT_FEES.RESOLVER_FEE // 150000n (default resolver fee)

Implementation Example

const SPEED_OPTIONS = {
fast: {
indexerFee: parseUnits('0.2', 6),
resolverFee: parseUnits('0.3', 6),
label: 'Fast (~5-10 min)',
},
standard: {
indexerFee: parseUnits('0.1', 6),
resolverFee: parseUnits('0.15', 6),
label: 'Standard (~15-20 min)',
},
economy: {
indexerFee: parseUnits('0.05', 6),
resolverFee: parseUnits('0.08', 6),
label: 'Economy (~30+ min)',
},
};

function getFees(amount: bigint, speed: 'fast' | 'standard' | 'economy') {
return calculateFeesSync(amount, SPEED_OPTIONS[speed]);
}

// Let user choose
const userSpeed = 'fast';
const fees = getFees(parseUnits('15', 6), userSpeed);

Fee Payment Order

All fees are paid BEFORE the action executes:


Best Practices

Let Users Choose Speed

// Good - user has control
const fees = calculateFeesSync(amount, {
indexerFee: userSelectedIndexerFee,
resolverFee: userSelectedResolverFee,
});

Show Fee Breakdown

const fees = calculateFeesSync(parseUnits(userInput, 6), speedOptions);

// Show in UI:
// "You send: 15.00 USDC"
// "Operator fees: 0.25 USDC (fast)"
// "Available for action: 14.73 USDC"
// "Estimated time: ~5-10 minutes"

Validate Before Signing

const validation = validateActionFeasibility(sendAmount, actionCost, speedOptions);

if (!validation.feasible) {
throw new Error(`Need at least ${formatUnits(validation.minimumBurn, 6)} USDC`);
}

Troubleshooting

"Transaction taking too long"

Cause: Fees might be below market rate.
Solution: Use higher fees for faster execution, or wait longer.

"SmartAccount: insufficient amount for fees"

Cause: Fees not properly accounted for.
Solution: Use SDK's calculateFeesSync() which includes all fees.

"Operators not processing my transaction"

Cause: Fees too low for current market conditions.
Solution: Increase indexer and resolver fees.