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
Dynamic Fee Model
Fees work like Ethereum gas:
- Users set their own fees - like setting gas price
- Operators compete - they choose which transactions to process
- Higher fees = priority - operators process profitable transactions first
- Market equilibrium - supply/demand determines fair prices
Speed Tiers
| Speed | Indexer Fee | Resolver Fee | Est. Time | Use Case |
|---|---|---|---|---|
| Fast | Higher | Higher | Faster | Time-sensitive |
| Standard | Medium | Medium | Normal | Balanced |
| Economy | Lower | Lower | Slower | Cost-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.