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 feesdefaultGasFee_
: Default gas fee in weidefaultTokenFee_
: 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
orITypes.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 creatorfeeType
: Preferred fee type for this creatorgasFee
: Gas fee amount in weitokenFee
: 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 fees1
: Fee on stake only2
: Fee on withdraw only3
: Fee on stake and withdraw4
: Fee on claim only5
: Fee on stake and claim6
: Fee on withdraw and claim7
: 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 ordefaultGasFee
- Amount is in wei
Token Fee Type:
- Uses
tokenFee
field from custom config ordefaultTokenFee
- Amount is in basis points
Error Conditions
Access Control Errors:
OwnableUnauthorizedAccount()
: Unauthorized access to owner functionOwnableInvalidOwner()
: Invalid owner address
Validation Errors:
InvalidAddress()
: Zero address providedInvalidFeeFunctionsMask()
: Invalid fee functions bitmask (> 7)FeeTooHigh()
: Token fee exceeds BASIS_POINTS (10,000)
Configuration Errors:
CustomFeeNotSet()
: Attempting to use non-existent custom feeFeeCollectorCannotBeZero()
: 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