Skip to main content

FeeCollector

The FeeCollector contract aggregates protocol fees from QsnDEX trading pairs and distributes them to the QsnStakeVault as WETH rewards for QSN stakers.

Overview

Protocol fees accumulate in each trading pair as excess token reserves beyond what the pair's internal accounting tracks. The FeeCollector skims these excess reserves, converts them to WETH, and forwards them to the StakeVault for distribution to stakers.

Fee Collection Flow

Trading Pairs --> FeeCollector (skim) --> Wrap ETH to WETH --> StakeVault (distribute)
  1. Skim -- The FeeCollector calls skim() on each pair contract to extract excess token balances that represent accumulated protocol fees.
  2. Wrap -- Any native ETH received (e.g., from pairs involving WETH that unwrap during skim) is wrapped to WETH.
  3. Distribute -- The collected WETH is sent to the StakeVault, which incorporates it into the current or next reward period.

Batch Collection

The FeeCollector supports batch operations, allowing fees to be collected from multiple pairs in a single transaction. This reduces operational overhead and gas costs for the fee collection process.

function collectFromPairs(address[] calldata pairs) external;

The caller provides an array of pair addresses, and the contract iterates through them, skimming excess reserves from each.

ETH Wrapping

The contract automatically wraps any received ETH to WETH. This ensures a uniform reward token (WETH) is distributed to the StakeVault regardless of whether the underlying pairs contain native ETH or WETH.

The contract includes a receive() function to accept ETH transfers and a dedicated wrapETH() function to convert the contract's ETH balance to WETH on demand.

Ownership

The FeeCollector uses a two-step ownership transfer pattern for safety:

  1. The current owner calls transferOwnership(newOwner) to nominate a new owner.
  2. The nominated address calls acceptOwnership() to complete the transfer.

This prevents accidental ownership transfers to incorrect or inaccessible addresses, as the new owner must actively accept the role.

Key Functions

FunctionDescription
collectFromPairs(address[])Skim fees from multiple pairs in one transaction.
distribute()Send accumulated WETH to the StakeVault.
wrapETH()Convert the contract's ETH balance to WETH.
transferOwnership(address)Nominate a new owner (step 1 of 2).
acceptOwnership()Accept ownership nomination (step 2 of 2).