# 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

1. **Initialization**: The contract is initialized with admin address, stablecoin, fee percentages, and receiver addresses.
2. **Fee Calculation**: When an order is created, the vault calls `collectFromVault()` to calculate the complete fee breakdown based on order size and destination chain.
3. **Fee Collection**: The vault transfers the calculated fees to the FeeCollector, which distributes them into the appropriate fee buckets (protocol, LP, operator).
4. **Fee Distribution**: Authorized roles can claim their respective fees by calling the appropriate claim functions:
   * `claimProtocolFees()` for admins
   * `claimLPFees()` for distributors
   * `claimOperatorFees()` for workers
5. **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**

{% code title="FeeCollector.sol" %}

```solidity
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;
}
```

{% endcode %}

#### **Fee Breakdown Calculation**

{% code title="FeeCollector.sol" %}

```solidity
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
    });
}
```

{% endcode %}

#### **Fee Claiming**

{% code title="FeeCollector.sol" %}

```solidity
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;
}
```

{% endcode %}

#### **Tiered Fee Calculation**

{% code title="FeeCollector.sol" %}

```solidity
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;
}
```

{% endcode %}

### Fee structure and calculation

#### **Fee Components**

The total fee for an order consists of three components:

1. **Base Fee**: A fixed minimum fee per destination chain, accounting for gas costs and operational expenses
2. **BPS Fee**: A percentage-based fee calculated on the order amount, split between protocol and LP fees
3. **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 payments
* `vault`: The authorized vault contract that can collect fees
* `protocolFee`: Percentage of BPS fees allocated to protocol
* `feeTiers`: Array of fee tiers based on order size
* `insuranceFeeTiers`: Array of insurance fee tiers
* `targetChainMinFee`: Mapping of chain ID to minimum fees
* `protocolFeesCollected` / `protocolFeesClaimed`: Protocol fee accounting
* `lpFeesCollected` / `lpFeesClaimed`: LP fee accounting
* `operatorFeesCollected` / `operatorFeesClaimed`: Operator fee accounting

### Events

The contract emits various events to track fee operations:

* `FeesCollectedFromVault`: When fees are collected from the vault
* `ProtocolFeesClaimed`: When protocol fees are claimed
* `LPFeesClaimed`: When LP fees are claimed
* `OperatorFeesClaimed`: When operator fees are claimed
* `ProtocolFeeReceiverSet`: When protocol fee receiver is updated
* `LPFeeReceiverSet`: When LP fee receiver is updated
* `OperatorFeeReceiverSet`: When operator fee receiver is updated
* `FeeTiersUpdated`: When fee tiers are updated
* `InsuranceFeeTiersUpdated`: When insurance fee tiers are updated
* `TargetChainMinFeeChanged`: When minimum fees for chains are updated

### Fee management functions

#### **Configuration Functions**

* `setProtocolFeeReceiver()`: Set the protocol fee receiver address
* `setLPFeeReceiver()`: Set the LP fee receiver address
* `setOperatorFeeReceiver()`: Set the operator fee receiver address
* `setProtocolFee()`: Set the protocol fee percentage
* `setTargetChainMinFee()`: Set minimum fees for specific chains
* `setFeeTiers()`: Configure fee tiers based on order size
* `setInsuranceFeeTiers()`: Configure insurance fee tiers

#### **Query Functions**

* `claimableProtocolFees()`: Get claimable protocol fees
* `claimableLPFees()`: Get claimable LP fees
* `claimableOperatorFees()`: Get claimable operator fees
* `getOrderFees()`: 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.
