Fee Collector
The FeeCollector is a fee management contract that handles the calculation, collection, and distribution of fees in the Genius bridge protocol. It implements a multi-tier fee structure with separate fee types for protocol maintenance, liquidity providers, and operators, ensuring sustainable protocol economics while incentivizing all participants.
The contract serves as the central hub for all fee-related operations, providing transparent fee calculation, secure fee collection, and automated distribution to various stakeholders. It supports dynamic fee tiers based on order size and maintains separate accounting for different fee types.
The FeeCollector contract - overview
The FeeCollector contract is an upgradeable contract that implements a comprehensive fee management system. It calculates fees based on order size using tiered structures, collects fees from the vault during order creation, and distributes them to designated receivers based on role-based access control.
The contract maintains separate accounting for protocol fees, liquidity provider (LP) fees, and operator fees, ensuring transparent tracking and secure distribution to the appropriate stakeholders.
The FeeCollector contract - key features
Multi-tier fee structure
The contract implements sophisticated fee tiers based on order size, allowing for dynamic fee calculation that scales with transaction volume. This ensures that larger orders contribute proportionally more to protocol sustainability while keeping fees reasonable for smaller transactions.
Separate fee types
The contract manages three distinct fee types:
Protocol fees: Allocated to protocol maintenance and development
LP fees: Distributed to liquidity providers as incentives
Operator fees: Compensates operators for cross-chain execution work
Role-based fee distribution
Different fee types are distributed to different roles:
Admin: Can claim protocol fees for the designated receiver
Distributor: Can claim LP fees for liquidity providers
Worker: Can claim operator fees for operators
Chain-specific minimum fees
Each destination chain has its own minimum fee requirement, accounting for different gas costs and operational expenses across different blockchain networks.
Insurance fee calculation
The contract calculates insurance fees separately from other fees, which are retained in the vault as additional liquidity protection against reorgs and rebalancing fees.
Comprehensive fee tracking
All fees are tracked with separate accounting for collected and claimed amounts, providing full transparency and preventing double-spending.
Upgradeable architecture
The contract uses the UUPS upgradeable pattern, allowing for future improvements to the fee structure without disrupting existing operations.
Understanding the workflow of FeeCollector
Initialization: The contract is initialized with admin address, stablecoin, fee percentages, and receiver addresses.
Fee Calculation: When an order is created, the vault calls
collectFromVault()
to calculate the complete fee breakdown based on order size and destination chain.Fee Collection: The vault transfers the calculated fees to the FeeCollector, which distributes them into the appropriate fee buckets (protocol, LP, operator).
Fee Distribution: Authorized roles can claim their respective fees by calling the appropriate claim functions:
claimProtocolFees()
for adminsclaimLPFees()
for distributorsclaimOperatorFees()
for workers
Fee Tracking: All fee movements are tracked and emitted as events for transparency and auditing purposes.
Core functions and their purposes
Fee Collection and Calculation
function collectFromVault(
bytes32 _orderHash,
uint256 _amountIn,
uint256 _destChainId,
uint256 _orderFee
) external returns (uint256 amountToTransfer) {
if (msg.sender != vault) revert GeniusErrors.NotAuthorized();
if (_amountIn == 0) revert GeniusErrors.InvalidAmount();
// Calculate fee breakdown
FeeBreakdown memory feeBreakdown = _calculateFeeBreakdown(
_amountIn,
_destChainId
);
// Check if the provided fee is sufficient
if (_orderFee < feeBreakdown.totalFee)
revert GeniusErrors.InsufficientFees(
_orderFee,
feeBreakdown.totalFee
);
// Calculate fee distribution based on percentages
uint256 protocolFeeAmount = (feeBreakdown.bpsFee * protocolFee) /
BASE_PERCENTAGE;
uint256 lpFee = feeBreakdown.bpsFee - protocolFeeAmount;
// Add fees to their respective buckets
protocolFeesCollected += protocolFeeAmount;
lpFeesCollected += lpFee;
operatorFeesCollected += feeBreakdown.baseFee + feeSurplus;
// The vault should transfer the total fee minus insurance fee to the fee collector
amountToTransfer = _orderFee - feeBreakdown.insuranceFee;
emit FeesCollectedFromVault(
_orderHash,
protocolFeeAmount,
lpFee,
feeBreakdown.baseFee + feeSurplus
);
return amountToTransfer;
}
Fee Breakdown Calculation
function _calculateFeeBreakdown(
uint256 _amount,
uint256 _destChainId
) internal view returns (FeeBreakdown memory) {
uint256 baseFee = targetChainMinFee[_destChainId];
if (baseFee == 0) {
revert GeniusErrors.InvalidDestChainId(_destChainId);
}
// Calculate BPS fee
uint256 bpsFeePercentage = _getBpsFeeForAmount(_amount);
uint256 bpsFee = (_amount * bpsFeePercentage) / BASE_PERCENTAGE;
// Calculate insurance fee
uint256 insuranceFeePercentage = _getInsuranceFeeBpsForAmount(_amount);
uint256 insuranceFee = (_amount * insuranceFeePercentage) /
BASE_PERCENTAGE;
// Calculate total fee
uint256 totalFee = baseFee + bpsFee + insuranceFee;
return FeeBreakdown({
baseFee: baseFee,
bpsFee: bpsFee,
insuranceFee: insuranceFee,
totalFee: totalFee
});
}
Fee Claiming
function claimProtocolFees()
external
nonReentrant
onlyAdmin
returns (uint256 amount)
{
amount = protocolFeesCollected - protocolFeesClaimed;
if (amount == 0) revert GeniusErrors.InvalidAmount();
if (protocolFeeReceiver == address(0))
revert GeniusErrors.NonAddress0();
protocolFeesClaimed += amount;
stablecoin.safeTransfer(protocolFeeReceiver, amount);
emit ProtocolFeesClaimed(msg.sender, protocolFeeReceiver, amount);
return amount;
}
Tiered Fee Calculation
function _getBpsFeeForAmount(
uint256 _amount
) internal view returns (uint256 bpsFee) {
if (feeTiers.length == 0) return 0;
// Default to the lowest tier fee
bpsFee = feeTiers[0].bpsFee;
// Find the highest tier that the amount qualifies for
for (uint256 i = 0; i < feeTiers.length; i++) {
if (_amount >= feeTiers[i].thresholdAmount) {
bpsFee = feeTiers[i].bpsFee;
} else {
// Found a tier with threshold higher than amount, so break
break;
}
}
return bpsFee;
}
Fee structure and calculation
Fee Components
The total fee for an order consists of three components:
Base Fee: A fixed minimum fee per destination chain, accounting for gas costs and operational expenses
BPS Fee: A percentage-based fee calculated on the order amount, split between protocol and LP fees
Insurance Fee: A percentage-based fee retained in the vault for additional liquidity protection
Fee Tiers
The contract supports dynamic fee tiers based on order size:
Threshold-based: Each tier has a minimum order size threshold
Ascending order: Tiers are ordered from smallest to largest threshold
Highest applicable: The highest tier that the order qualifies for is applied
Fee Distribution
Protocol fees: Calculated as
(bpsFee * protocolFee) / BASE_PERCENTAGE
LP fees: Remaining BPS fees after protocol allocation
Operator fees: Base fee plus any surplus fees
Security features
Access Control
The contract implements comprehensive role-based access control:
Admin: Can manage all fee settings and claim protocol fees
Distributor: Can claim LP fees for liquidity providers
Worker: Can claim operator fees for operators
Reentrancy Protection
All fee claiming functions are protected against reentrancy attacks using OpenZeppelin's ReentrancyGuard.
Input Validation
Extensive validation ensures:
Valid addresses for all receivers
Proper fee percentages within acceptable bounds
Correct tier ordering and validation
Sufficient fees provided for orders
Vault Authorization
Only the authorized vault contract can call fee collection functions, preventing unauthorized fee manipulation.
Integration with other contracts
The FeeCollector interacts with several other contracts in the Genius ecosystem:
GeniusVault: Calls fee collection functions during order creation
Stablecoin Contracts: The underlying stablecoin used for fee payments
Fee Receivers: Various addresses that receive different fee types
Key state variables
stablecoin
: The stablecoin token used for fee paymentsvault
: The authorized vault contract that can collect feesprotocolFee
: Percentage of BPS fees allocated to protocolfeeTiers
: Array of fee tiers based on order sizeinsuranceFeeTiers
: Array of insurance fee tierstargetChainMinFee
: Mapping of chain ID to minimum feesprotocolFeesCollected
/protocolFeesClaimed
: Protocol fee accountinglpFeesCollected
/lpFeesClaimed
: LP fee accountingoperatorFeesCollected
/operatorFeesClaimed
: Operator fee accounting
Events
The contract emits various events to track fee operations:
FeesCollectedFromVault
: When fees are collected from the vaultProtocolFeesClaimed
: When protocol fees are claimedLPFeesClaimed
: When LP fees are claimedOperatorFeesClaimed
: When operator fees are claimedProtocolFeeReceiverSet
: When protocol fee receiver is updatedLPFeeReceiverSet
: When LP fee receiver is updatedOperatorFeeReceiverSet
: When operator fee receiver is updatedFeeTiersUpdated
: When fee tiers are updatedInsuranceFeeTiersUpdated
: When insurance fee tiers are updatedTargetChainMinFeeChanged
: When minimum fees for chains are updated
Fee management functions
Configuration Functions
setProtocolFeeReceiver()
: Set the protocol fee receiver addresssetLPFeeReceiver()
: Set the LP fee receiver addresssetOperatorFeeReceiver()
: Set the operator fee receiver addresssetProtocolFee()
: Set the protocol fee percentagesetTargetChainMinFee()
: Set minimum fees for specific chainssetFeeTiers()
: Configure fee tiers based on order sizesetInsuranceFeeTiers()
: Configure insurance fee tiers
Query Functions
claimableProtocolFees()
: Get claimable protocol feesclaimableLPFees()
: Get claimable LP feesclaimableOperatorFees()
: Get claimable operator feesgetOrderFees()
: Calculate complete fee breakdown for an order
The FeeCollector is a critical component of the Genius protocol's economic model, ensuring sustainable revenue generation while maintaining transparency and fair distribution among all stakeholders. Its sophisticated fee structure and secure distribution mechanisms provide the foundation for long-term protocol viability.
Last updated