Skip to main content

FactoryFeeManager

Overview

FactoryFeeManager is an abstract contract that provides sophisticated fee management functionality for factory contracts. It enables factory owners to configure different fee structures for different campaign creators, offering flexibility for partnerships, tiered pricing, and custom fee arrangements.

Contract Specification

abstract contract FactoryFeeManager is Ownable

Inheritance:

  • Ownable: Access control functionality

Used by:

  • StakingFactory
  • UnbondingStakingFactory

Data Structures

CustomFee

struct CustomFee {
bool enabled; // Whether custom fee is active
ITypes.FeeType preferredFeeType; // Gas or DistributionToken
uint256 gasFee; // Gas fee amount in wei
uint256 tokenFee; // Token fee in basis points
uint8 feeFunctions; // Bitmask for fee-enabled functions
}

State Variables

Constants

uint256 public constant BASIS_POINTS = 10_000;  // 100% = 10,000 basis points

Configuration Variables

address public feeCollector;                    // Address receiving fees
uint256 public defaultGasFee; // Default gas fee (wei)
uint256 public defaultTokenFee; // Default token fee (basis points)
ITypes.FeeType public defaultFeeType; // Default fee type
uint8 public defaultFeeFunctions; // Default fee function bitmask

Custom Fee Storage

mapping(address campaignCreator => CustomFee customFee) private _customFees;

Constructor

constructor(
address feeCollector_,
uint256 defaultGasFee_,
uint256 defaultTokenFee_,
uint8 defaultFeeFunctions_
)

Parameters:

  • feeCollector_: Address that will receive collected fees
  • defaultGasFee_: Default gas fee in wei
  • defaultTokenFee_: Default token fee in basis points (max 10,000)
  • defaultFeeFunctions_: Bitmask defining which functions have fees

Validation:

  • Fee collector cannot be zero address
  • Default fee functions must be ≤ 7 (valid bitmask)

Core Functions

Default Fee Management

setFeeCollector

function setFeeCollector(address newFeeCollector) external onlyOwner

Updates the fee collector address.

Parameters:

  • newFeeCollector: New fee collector address

Requirements:

  • Only contract owner
  • Address cannot be zero

Events: FeeCollectorSet(address admin, address indexed newFeeCollector)

setDefaultGasFee

function setDefaultGasFee(uint256 newGasFee) external onlyOwner

Sets the default gas fee for all users.

Parameters:

  • newGasFee: New default gas fee in wei

Requirements:

  • Only contract owner

Events: SetDefaultGasFee(address admin, uint256 oldGasFee, uint256 newGasFee)

setDefaultTokenFee

function setDefaultTokenFee(uint256 newTokenFee) external onlyOwner

Sets the default token fee percentage.

Parameters:

  • newTokenFee: New default token fee in basis points

Requirements:

  • Only contract owner

Events: SetDefaultTokenFee(address admin, uint256 oldTokenFee, uint256 newTokenFee)

setDefaultFeeType

function setDefaultFeeType(ITypes.FeeType feeType) external onlyOwner

Sets the default fee type for all users.

Parameters:

  • feeType: ITypes.FeeType.Gas or ITypes.FeeType.DistributionToken

Requirements:

  • Only contract owner

Events: ChangeDefaultFeeType(address admin, ITypes.FeeType newFeeType)

setDefaultFeeFunctions

function setDefaultFeeFunctions(uint8 newFeeFunctions) external onlyOwner

Sets the default fee functions bitmask.

Parameters:

  • newFeeFunctions: Bitmask (0-7) defining which functions have fees

Requirements:

  • Only contract owner
  • Must be ≤ 7 (valid bitmask)

Events: SetDefaultFeeFunctions(address indexed admin, uint8 oldFeeFunctions, uint8 newFeeFunctions)

Custom Fee Management

setCustomFee

function setCustomFee(
address campaignCreator,
ITypes.FeeType feeType,
uint256 gasFee,
uint256 tokenFee,
uint8 feeFunctions
) external onlyOwner

Configures custom fees for a specific campaign creator.

Parameters:

  • campaignCreator: Address of the campaign creator
  • feeType: Preferred fee type for this creator
  • gasFee: Gas fee amount in wei
  • tokenFee: Token fee in basis points (max 10,000)
  • feeFunctions: Bitmask for fee-enabled functions

Requirements:

  • Only contract owner
  • Campaign creator cannot be zero address
  • Token fee must be ≤ 10,000 (100%)

Events: SetCustomFee(address admin, bool enabled, address indexed campaignCreator, ITypes.FeeType feeType, uint256 gasFee, uint256 tokenFee, uint8 feeFunctions)

disableCustomFee

function disableCustomFee(address campaignCreator) external onlyOwner

Removes custom fee configuration for a campaign creator.

Parameters:

  • campaignCreator: Address to remove custom fees for

Requirements:

  • Only contract owner
  • Address cannot be zero

Events: SetCustomFee(address admin, bool enabled, address indexed campaignCreator, ITypes.FeeType feeType, uint256 gasFee, uint256 tokenFee, uint8 feeFunctions) with enabled = false

Utility Functions

resetGasFee

function resetGasFee() external onlyOwner

Resets the default gas fee to zero.

Requirements:

  • Only contract owner

Events: SetDefaultGasFee(address admin, uint256 oldGasFee, uint256 newGasFee)

resetTokenFee

function resetTokenFee() external onlyOwner

Resets the default token fee to zero.

Requirements:

  • Only contract owner

Events: SetDefaultTokenFee(address admin, uint256 oldTokenFee, uint256 newTokenFee)

View Functions

getCustomFee

function getCustomFee(address campaignCreator) external view returns (CustomFee memory)

Returns the custom fee configuration for a campaign creator.

Parameters:

  • campaignCreator: Address to query

Returns:

  • CustomFee struct containing fee configuration

getFeeConfig

function getFeeConfig(address campaignCreator) external view returns (
ITypes.FeeType feeType,
uint256 fee,
uint8 feeFunctions
)

Returns the effective fee configuration for a campaign creator.

Parameters:

  • campaignCreator: Address to query

Returns:

  • feeType: Effective fee type (custom or default)
  • fee: Effective fee amount (custom or default)
  • feeFunctions: Effective fee functions bitmask

Logic:

  • If custom fee is enabled, returns custom configuration
  • Otherwise returns default configuration

hasCustomFee

function hasCustomFee(address campaignCreator) external view returns (bool)

Checks if a campaign creator has custom fee configuration.

Parameters:

  • campaignCreator: Address to check

Returns:

  • Boolean indicating if custom fees are enabled

Internal Functions

Fee Resolution

_getFeeType

function _getFeeType(address campaignCreator) internal view returns (ITypes.FeeType)

Returns the effective fee type for a campaign creator.

_getFee

function _getFee(address campaignCreator) internal view returns (uint256)

Returns the effective fee amount for a campaign creator.

_getFeeFunctions

function _getFeeFunctions(address campaignCreator) internal view returns (uint8)

Returns the effective fee functions bitmask for a campaign creator.

Fee Types

Gas Fees

  • Type: ITypes.FeeType.Gas
  • Payment: Fixed ETH amount per transaction
  • Collection: Immediate transfer to fee collector
  • Configuration: Amount in wei

Token Fees

  • Type: ITypes.FeeType.DistributionToken
  • Payment: Percentage of tokens being operated on
  • Collection: Deducted from token operations
  • Configuration: Percentage in basis points (1-10000)

Fee Functions Bitmask

The fee functions bitmask determines which contract functions have fees applied:

uint8 constant FEE_ON_STAKE = 1;     // Bit 0: Fee on staking functions
uint8 constant FEE_ON_WITHDRAW = 2; // Bit 1: Fee on withdrawal functions
uint8 constant FEE_ON_CLAIM = 4; // Bit 2: Fee on claim functions

Bitmask Values:

  • 0: No fees
  • 1: Fee on stake only
  • 2: Fee on withdraw only
  • 3: Fee on stake and withdraw
  • 4: Fee on claim only
  • 5: Fee on stake and claim
  • 6: Fee on withdraw and claim
  • 7: Fee on all functions

Fee Configuration Logic

Default Configuration

All campaign creators use default fees unless they have custom configuration:

if (!_customFees[campaignCreator].enabled) {
return defaultFeeType;
}

Custom Configuration

When custom fees are enabled, they override all default settings:

if (_customFees[campaignCreator].enabled) {
return _customFees[campaignCreator].preferredFeeType;
}

Fee Amount Resolution

The fee amount depends on the fee type:

Gas Fee Type:

  • Uses gasFee field from custom config or defaultGasFee
  • Amount is in wei

Token Fee Type:

  • Uses tokenFee field from custom config or defaultTokenFee
  • Amount is in basis points

Error Conditions

Access Control Errors:

  • OwnableUnauthorizedAccount(): Unauthorized access to owner function
  • OwnableInvalidOwner(): Invalid owner address

Validation Errors:

  • InvalidAddress(): Zero address provided
  • InvalidFeeFunctionsMask(): Invalid fee functions bitmask (> 7)
  • FeeTooHigh(): Token fee exceeds BASIS_POINTS (10,000)

Configuration Errors:

  • CustomFeeNotSet(): Attempting to use non-existent custom fee
  • FeeCollectorCannotBeZero(): Zero address for fee collector

Events

Default Fee Events

event FeeCollectorSet(address admin, address indexed newFeeCollector);
event SetDefaultGasFee(address admin, uint256 oldGasFee, uint256 newGasFee);
event SetDefaultTokenFee(address admin, uint256 oldTokenFee, uint256 newTokenFee);
event ChangeDefaultFeeType(address admin, ITypes.FeeType newFeeType);
event SetDefaultFeeFunctions(address indexed admin, uint8 oldFeeFunctions, uint8 newFeeFunctions);

Custom Fee Events

event SetCustomFee(
address admin,
bool enabled,
address indexed campaignCreator,
ITypes.FeeType feeType,
uint256 gasFee,
uint256 tokenFee,
uint8 feeFunctions
);

Usage Patterns

Default Configuration

Factory deploys with default fees that apply to all users:

- defaultGasFee: 0.001 ETH
- defaultTokenFee: 250 basis points (2.5%)
- defaultFeeType: DistributionToken
- defaultFeeFunctions: 1 (FEE_ON_STAKE)

Custom Configuration

Factory owner can set custom fees for specific campaign creators:

- Premium Partners: 0% fees (partnership incentive)
- Regular Users: Default fees
- High-Volume Users: Reduced fees

Fee Type Selection

Different fee types serve different purposes:

Gas Fees:

  • Predictable cost per transaction
  • Immediate payment required
  • Good for fixed-cost operations

Token Fees:

  • Percentage-based pricing
  • Scales with transaction size
  • Good for value-based operations

Configuration Examples

Partnership Fee Structure

// Zero fees for strategic partners
setCustomFee(
partnerAddress,
ITypes.FeeType.Gas,
0, // No gas fee
0, // No token fee
0 // No functions have fees
);

Tiered Fee Structure

// High-volume user with reduced fees
setCustomFee(
highVolumeUser,
ITypes.FeeType.DistributionToken,
0, // No gas fee
100, // 1% token fee (reduced from default)
7 // All functions have fees
);

Mixed Fee Structure

// Custom mixed fee configuration
setCustomFee(
campaignCreator,
ITypes.FeeType.Gas,
0.0005 ether, // 0.0005 ETH gas fee
200, // 2% token fee
3 // Fees on stake and withdraw
);

Security Considerations

Access Control

  • Only factory owner can modify fee configurations
  • Fee collector role is separate from owner role
  • Custom fees can only be set by owner

Validation

  • All fee percentages validated against maximum (BASIS_POINTS)
  • Address validation prevents zero address assignments
  • Bitmask validation prevents invalid fee function configurations

Immutability

  • Custom fees are mutable (owner can change them)
  • Default fees are mutable (owner can change them)
  • Fee structure can be completely reconfigured if needed

Inherited Functionality

FactoryFeeManager provides the following functionality to factory contracts:

Fee Configuration:

  • Default fee management for all users
  • Custom fee configuration for specific users
  • Fee type and amount resolution

Administrative Functions:

  • Fee collector management
  • Fee structure updates
  • Custom fee enablement/disablement

Query Functions:

  • Fee configuration retrieval
  • Custom fee status checking
  • Effective fee calculation