FeeManagerV2
Central fee management contract for protocol fee collection, burning, staker rewards, and treasury distribution.
FeeManagerV2
The FeeManagerV2 contract is the central hub for processing protocol fees from all PRIV marketplace contracts. It handles the three-way split between burning tokens (deflationary), distributing rewards to stakers, and funding the protocol treasury.
Overview
Fee Sources
The FeeManagerV2 receives fees from:
| Source | Fee Rate | Description |
|---|---|---|
| DataXchange | 3% | Data marketplace sales |
| DataWalletMarketplace | 3% | Data wallet media purchases |
| AdNetwork | 3% | Advertising spend |
Note: All marketplaces use a unified 3% fee to prevent arbitrage and simplify the economic model.
Fee Processing (40/35/25 Split)
When fees are processed:
Fee Amount (100 PRIV)
├── 40% Burned (40 PRIV) → Supply decreases (deflationary)
├── 35% Stakers (35 PRIV) → PRIVStaking rewards pool
└── 25% Treasury (25 PRIV) → Protocol reservesThe burn/staking/treasury ratios are configurable via governance with a 2-day timelock.
Contract Details
Constants
| Constant | Value | Description |
|---|---|---|
MAX_RATIO | 10000 | Maximum ratio (100%) |
BPS_DENOMINATOR | 10000 | Basis points denominator |
RATIO_UPDATE_DELAY | 2 days | Timelock for ratio changes |
MIN_PROCESS_AMOUNT | 0.01 PRIV | Minimum to process (prevents dust) |
State Variables
// The PRIV token contract (burnable)
IPRIVToken public immutable privToken;
// The PRIVStaking contract for rewards distribution
IPRIVStaking public stakingContract;
// Treasury address for protocol reserves
address public treasury;
// Current burn ratio in basis points (4000 = 40%)
uint256 public burnRatio;
// Current staking ratio in basis points (3500 = 35%)
uint256 public stakingRatio;
// Current treasury ratio in basis points (2500 = 25%)
uint256 public treasuryRatio;
// Accumulated fees pending processing
uint256 public pendingFees;
// Total fees ever received
uint256 public totalFeesReceived;
// Total PRIV burned
uint256 public totalBurned;
// Total PRIV distributed to stakers
uint256 public totalDistributedToStakers;
// Total PRIV sent to treasury
uint256 public totalSentToTreasury;
// Mapping of authorized fee sources
mapping(address => bool) public authorizedFeeSources;Functions
Fee Collection
receiveFees
Receives fees from authorized marketplace contracts.
function receiveFees(uint256 amount) external whenNotPausedParameters:
amount- The amount of PRIV tokens to receive as fees
Requirements:
- Caller must be an authorized fee source
- Amount must be greater than 0
- Caller must have approved the FeeManagerV2 to transfer PRIV
Events:
event FeesReceived(address indexed source, uint256 amount);Fee Processing
processFees
Processes all accumulated pending fees with the 40/35/25 split.
function processFees() external nonReentrant whenNotPausedDescription:
- Anyone can call this function to process pending fees
- Burns 40% of fees (deflationary)
- Distributes 35% to the staking rewards pool
- Sends 25% to protocol treasury
Requirements:
- Pending fees must be at least
MIN_PROCESS_AMOUNT(0.01 PRIV) - Staking contract must be set
- Treasury address must be set
Events:
event FeesProcessed(
uint256 totalAmount,
uint256 burnedAmount,
uint256 stakingAmount,
uint256 treasuryAmount
);processFeesPartial
Processes a specific amount of pending fees.
function processFeesPartial(uint256 amount) external nonReentrant whenNotPausedParameters:
amount- The specific amount to process
Use Case: Useful for gas optimization or partial processing during high-fee periods.
Ratio Management
proposeRatioUpdate
Proposes new fee distribution ratios (governance with timelock).
function proposeRatioUpdate(
uint256 newBurnRatio,
uint256 newStakingRatio,
uint256 newTreasuryRatio
) external onlyOwnerParameters:
newBurnRatio- New burn ratio in basis points (4000 = 40%)newStakingRatio- New staking ratio in basis points (3500 = 35%)newTreasuryRatio- New treasury ratio in basis points (2500 = 25%)
Requirements:
- All ratios must sum to exactly 10000 (100%)
- Cannot propose same ratios as current
- No pending update can exist
Events:
event RatioUpdateProposed(
uint256 burnRatio,
uint256 stakingRatio,
uint256 treasuryRatio,
uint256 effectiveTime
);executeRatioUpdate
Executes a pending ratio update after the 2-day timelock.
function executeRatioUpdate() external onlyOwnerRequirements:
- A pending update must exist
- Timelock must have elapsed (2 days)
cancelRatioUpdate
Cancels a pending ratio update.
function cancelRatioUpdate() external onlyOwnerAdmin Functions
setStakingContract
Updates the staking contract address.
function setStakingContract(address newStakingContract) external onlyOwnersetTreasury
Updates the treasury address.
function setTreasury(address newTreasury) external onlyOwnerauthorizeFeeSource
Authorizes a marketplace contract to send fees.
function authorizeFeeSource(address source) external onlyOwnerrevokeFeeSource
Revokes authorization from a fee source.
function revokeFeeSource(address source) external onlyOwnerpause / unpause
Emergency pause controls.
function pause() external onlyOwner
function unpause() external onlyOwneremergencyRecoverTokens
Recovers accidentally sent tokens.
function emergencyRecoverTokens(
address token,
address to,
uint256 amount
) external onlyOwnerCannot recover pending PRIV fees - only excess tokens.
View Functions
getStats
Returns comprehensive fee manager statistics.
function getStats() external view returns (
uint256 _pendingFees,
uint256 _totalReceived,
uint256 _totalBurned,
uint256 _totalDistributedToStakers,
uint256 _totalSentToTreasury,
uint256 _burnRatio,
uint256 _stakingRatio,
uint256 _treasuryRatio
)calculateFeeSplit
Preview how fees would be split at current ratios.
function calculateFeeSplit(uint256 amount) external view returns (
uint256 burnAmount,
uint256 stakingAmount,
uint256 treasuryAmount
)ratioUpdateTimeRemaining
Returns seconds until pending update can be executed.
function ratioUpdateTimeRemaining() external view returns (uint256)Security Features
| Feature | Description |
|---|---|
| ReentrancyGuard | Protection against reentrancy attacks |
| Pausable | Emergency pause functionality |
| Ownable | Access control for admin functions |
| Timelock | 2-day delay for ratio changes |
| Authorization | Only approved contracts can send fees |
| SafeERC20 | Safe token transfer handling |
| Ratio Validation | Ensures ratios always sum to 100% |
Integration Example
import { ethers } from 'ethers';
const feeManagerABI = [...]; // ABI
const feeManagerAddress = '0x...';
const feeManager = new ethers.Contract(
feeManagerAddress,
feeManagerABI,
signer
);
// Check current stats
const stats = await feeManager.getStats();
console.log('Pending fees:', ethers.formatEther(stats._pendingFees));
console.log('Total burned:', ethers.formatEther(stats._totalBurned));
console.log('Total to stakers:', ethers.formatEther(stats._totalDistributedToStakers));
console.log('Total to treasury:', ethers.formatEther(stats._totalSentToTreasury));
// Current ratios (40/35/25)
console.log('Burn ratio:', stats._burnRatio / 100, '%'); // 40%
console.log('Staking ratio:', stats._stakingRatio / 100, '%'); // 35%
console.log('Treasury ratio:', stats._treasuryRatio / 100, '%'); // 25%
// Process fees (anyone can call)
if (stats._pendingFees >= ethers.parseEther('0.01')) {
const tx = await feeManager.processFees();
await tx.wait();
}
// Preview fee split for 100 PRIV
const [burnAmount, stakingAmount, treasuryAmount] = await feeManager.calculateFeeSplit(
ethers.parseEther('100')
);
console.log('Would burn:', ethers.formatEther(burnAmount)); // 40 PRIV
console.log('Would stake:', ethers.formatEther(stakingAmount)); // 35 PRIV
console.log('Would treasury:', ethers.formatEther(treasuryAmount)); // 25 PRIVEvents Reference
| Event | Description |
|---|---|
FeesReceived | Fees received from a marketplace |
FeesProcessed | Fees burned, distributed to stakers, and sent to treasury |
RatioUpdateProposed | New ratios proposed |
RatiosUpdated | Ratio change executed |
RatioUpdateCancelled | Pending update cancelled |
StakingContractUpdated | Staking contract changed |
TreasuryUpdated | Treasury address changed |
FeeSourceAuthorized | New fee source authorized |
FeeSourceRevoked | Fee source revoked |
Migration from FeeManager (V1)
FeeManagerV2 replaces the original FeeManager with the following changes:
| Aspect | FeeManager (V1) | FeeManagerV2 |
|---|---|---|
| Split | 50% burn / 50% stakers | 40% burn / 35% stakers / 25% treasury |
| Treasury | None | Protocol treasury receives 25% |
| Ratios | Single burn ratio | Three configurable ratios |
| Stats | 5 return values | 8 return values |
Existing marketplace contracts can be migrated by updating the FeeManager address they point to.