Skip to content

Fee Collector

Overview

The FeeCollector is the central contract for managing protocol fee collection and distribution across the RAAC ecosystem. It handles fee collection from various protocol activities and distributes them according to configurable splits to different stakeholders including treasury, repair fund, veRAAC holders, and other designated recipients.

Purpose

  • Centralized Fee Management: Collect fees from all protocol activities in a unified manner
  • Configurable Distribution: Split collected fees across multiple stakeholders based on predefined percentages
  • Multi-Token Support: Handle fee collection in different supported tokens (scrvUSD, crvUSD, iRAAC)
  • Role-Based Access Control: Secure management through distinct roles for different operations
  • Emergency Controls: Pause functionality and emergency withdrawal capabilities

Architecture

flowchart TD
    A[Protocol Activities] -->|collectFee| B[FeeCollector]
    B -->|Fee Split| C[Treasury]
    B -->|Fee Split| D[Repair Fund]
    B -->|Fee Split| E[Burn Address]
    B -->|Fee Split| F[veRAAC Holders]
    B -->|Fee Split| G[RAAC Corp]
    B -->|Fee Split| H[Other Targets]

    I[Fee Types] -->|Configure| B
    J[Supported Tokens] -->|Whitelist| B
    K[Distribution Targets] -->|Whitelist| B

Supported Tokens

The FeeCollector accepts fees in the following whitelisted tokens:

Token Description
scrvUSD Curve SCRVUSD vault shares
crvUSD Curve USD stablecoin
iRAAC RAAC index token from RWA Vault

Approval Security

We strongly advise against giving type(uint256).max approval to the FeeCollector.
Instead, approve only the specific amount needed for fee collection to minimize security risks.

CRITICAL: Pull-Based System - Direct Transfers Result in Permanent Loss

The FeeCollector is a pull-based system that does NOT track direct token transfers.
Any direct transfer of tokens to the FeeCollector address will result in PERMANENT LOSS of funds.
The contract only tracks and accounts for fees collected through the collectFee() function.
NEVER send tokens directly to the FeeCollector address.

Fee Types & Distribution

Fees are collected by fee type and distributed according to configurable percentages across six target categories:

Target Description Configurable
Treasury Protocol treasury for general operations YES
Repair Fund Safety fund for protocol maintenance YES
Burn Token burn mechanism YES
veRAAC Rewards for veRAAC token holders YES
RAAC Corp Corporate allocation YES
Other Additional designated recipients YES

Fee Type Configuration

Each fee type must have percentages that sum to exactly 100% (10,000 basis points).
For detailed parameter configuration, refer to the Parameters page.

Dust and Rounding Handling

If the total distribution for a fee type is not exactly 100% due to rounding or configuration errors, any remaining amount (including dust) is automatically sent to the treasury. This ensures that all collected fees are properly distributed and no funds are left unallocated.

Key Functions

collectFee

collectFee(address token, address target, uint256 amount, bytes32 feeType) → bool

Summary
Collects fees of a specific type from a target contract. This is the primary public method for fee collection across the protocol.

Guarded Method
- Callable by any address (typically protocol contracts) - Protected by nonReentrant, whenNotPaused, and validation checks

Parameters

Name Type Description
token address Token address to collect fees in (must be whitelisted)
target address Address to collect fees from (must approve FeeCollector)
amount uint256 Amount of tokens to collect
feeType bytes32 Type of fee being collected (must be configured)

Returns
booltrue if collection successful

Emits
- FeeCollected(address indexed token, address indexed target, bytes32 indexed feeType, uint256 amount, uint256 actualAmount)

Reverts

  • InvalidFeeAmount() — if amount == 0
  • FeeTypeDoesNotExist() — if fee type not configured
  • TokenNotSupported() — if token not whitelisted
  • ERC20 transfer failures

Requirements

  • Target must have approved FeeCollector to spend tokens
  • Token must be in supported tokens list
  • Fee type must be configured with valid percentages
  • Handles fee-on-transfer tokens by measuring actual received amount
Example (TypeScript / ethers)
// Approve FeeCollector to spend tokens
await token.approve(feeCollector.target, amount);

// Collect fee from protocol contract
const tx = await feeCollector.collectFee(
    tokenAddress,
    protocolContract,
    amount,
    keccak256("LENDING_FEE")
);
await tx.wait();
Source code
function collectFee(address token, address target, uint256 amount, bytes32 feeType) 
    external 
    nonReentrant 
    whenNotPaused 
    returns (bool) 
{
    if (amount == 0) revert InvalidFeeAmount();
    if (feeTypes[feeType].feeType == bytes32(0)) revert FeeTypeDoesNotExist();
    if (!isTokenSupported[token]) revert TokenNotSupported();

    // Transfer tokens from target to this contract
    uint256 balanceBefore = IERC20(token).balanceOf(address(this));
    IERC20(token).safeTransferFrom(target, address(this), amount);
    uint256 balanceAfter = IERC20(token).balanceOf(address(this));

    // Handle fee-on-transfer tokens
    uint256 actualAmount = balanceAfter - balanceBefore;

    // Update collected fees for this token
    _updateCollectedFees(token, feeType, actualAmount);

    emit FeeCollected(token, target, feeType, amount, actualAmount);
    return true;
}

Private Methods (Role-Protected)

Fee Management

Function Role Description
addFeeType FEE_MANAGER_ROLE Add new fee type with distribution percentages
updateFeeType FEE_MANAGER_ROLE Update existing fee type configuration
removeFeeType FEE_MANAGER_ROLE Remove fee type (after distribution)
setTargetFeeType FEE_MANAGER_ROLE Assign fee type to specific target
removeTargetFeeType FEE_MANAGER_ROLE Remove fee type assignment from target

Token & Target Management

Function Role Description
addClaimableToken FEE_MANAGER_ROLE Add token to supported tokens list
removeClaimableToken FEE_MANAGER_ROLE Remove token from supported tokens list
addWhitelistedTarget FEE_MANAGER_ROLE Add target to whitelist for fee collection
removeWhitelistedTarget FEE_MANAGER_ROLE Remove target from whitelist
setTargetAddress FEE_MANAGER_ROLE Set address for distribution targets

Distribution & Collection

Function Role Description
distributeFees DISTRIBUTOR_ROLE Distribute collected fees to specific target
claimCollectorRewards FEE_MANAGER_ROLE Claim rewards from whitelisted targets
claimNFTUnderlying FEE_MANAGER_ROLE Claim underlying assets from wrapped tokens

Emergency Controls

Function Role Description
pause EMERGENCY_ROLE Pause all contract operations
unpause EMERGENCY_ROLE Resume contract operations
emergencyWithdraw EMERGENCY_ROLE Emergency withdrawal of all tokens

Public Read Methods

Target Information

Function Returns Description
getTargetAddress(bytes32 target) address Get address for specific target type
getTargetAmount(bytes32 feeType, bytes32 target, address token) uint256 Get collected amount for target

Fee Type Information

Function Returns Description
getFeeType(bytes32 feeType) FeeType Get fee type configuration
getFeeTypes() FeeType[] Get all fee type configurations

Collected Fees

Function Returns Description
getCollectedFees(address token, bytes32 feeType) CollectedFeeForType Get collected fees for token/fee type

Configuration Status

Function Returns Description
isTokenSupported(address token) bool Check if token is whitelisted
isTargetWhitelisted(address target) bool Check if target is whitelisted
isValidDistributionTarget(address target) bool Check if target supports distribution interface

Fee Distribution Flow

  1. Collection: Protocol contracts call collectFee() with appropriate fee type
  2. Splitting: Fees are automatically split according to fee type percentages
  3. Storage: Split amounts are stored in collectedFeesByToken mapping
  4. Distribution: Authorized distributors call distributeFees() to send funds to targets
  5. Tracking: All distributions are tracked and amounts are reduced accordingly

Access Control Roles

Role Permissions
DEFAULT_ADMIN_ROLE Full administrative control, can grant/revoke all roles
FEE_MANAGER_ROLE Configure fee types, manage tokens/targets, claim rewards
DISTRIBUTOR_ROLE Execute fee distributions to targets
EMERGENCY_ROLE Pause/unpause contract, emergency withdrawals

Integration Notes

  • Protocol Contracts: Should call collectFee() after collecting fees from users
  • Target Contracts: Must implement IDistributionTarget interface for automated distribution
  • Fee Types: Must be pre-configured before collection can begin
  • Token Support: Only whitelisted tokens can be used for fee collection

For detailed parameter configuration and current fee type settings, refer to the Parameters page.