Staking Overview
This document provides technical API reference for the TokenOps Staking Contracts system. The system consists of factory contracts for deployment, core staking contracts, and utility libraries.
Table of Contents
System Architecture
The TokenOps Staking Contracts implement a factory pattern for deploying staking contracts with configurable parameters. The system supports multiple staking mechanisms with different reward calculation methods and withdrawal patterns.
Contract Hierarchy
StakingBase (Abstract)
├── Staking (Basic staking with flexible rewards)
└── StakingWithUnbonding (Unbonding staking with fixed APY)
FactoryFeeManager (Abstract)
├── StakingFactory
├── UnbondingStakingFactory
└── DualTokenStakingFactory
Contract Types
Factory Contracts
Contract | Description | Purpose |
---|---|---|
StakingFactory | Deploys basic staking contracts | Standardized deployment with fee management |
UnbondingStakingFactory | Deploys unbonding staking contracts | APY-based rewards with withdrawal delays |
Staking Contracts
Contract | Description | Reward Model | Withdrawal |
---|---|---|---|
Staking | Basic staking implementation | Time-based flexible ratios | Immediate |
StakingWithUnbonding | Unbonding staking implementation | Fixed APY calculation | Two-phase with delays |
Utility Libraries
Library | Description | Functionality |
---|---|---|
StakingBase | Abstract base contract | Core staking functionality |
FactoryFeeManager | Fee management system | Custom and default fee handling |
CurrencyTransferLib | Token transfer utilities | Safe ERC20 and ETH transfers |
FeeFunctions | Fee bitmask utilities | Function-specific fee control |
Audit Reports
You can find the audit reports for this project here.
Core Concepts
Fee Management
The system implements a two-tier fee structure:
- Factory Level: Default fees and per-creator custom fees
- Contract Level: Function-specific fee application using bitmasks
Fee Types:
Gas
: Fixed ETH amount per transactionDistributionToken
: Percentage of tokens being operated on
Fee Function Bitmasks:
FEE_ON_STAKE = 1
(0x01)FEE_ON_WITHDRAW = 2
(0x02)FEE_ON_CLAIM = 4
(0x04)FEE_ON_ALL = 7
(0x07)FEE_ON_NONE = 0
(0x00)
Whitelist System
Both Staking
and StakingWithUnbonding
share the same whitelist behavior via StakingBase
.
Modes:
Disabled
: anyone can self-stake.Merkle
: only addresses in a Merkle allowlist can receive stakes (requires proof).TrustedDistributors
: only approved distributors can stake for any receiver. Regular users cannot stake at all.MerkleAndTrustedDistributors
: either a valid Merkle proof for the receiver, or a trusted distributor without proof.
Use the right function:
stake(amount)
: only whenDisabled
.stake(amount, receiver)
: requires caller to be trusted distributor in distributor modes; not allowed inMerkle
.stake(amount, receiver, proof)
: when Merkle is active; verifies leafkeccak256(abi.encodePacked(receiver))
againstmerkleRoot
.
Key rules:
- If any whitelist mode is enabled,
stake(amount)
is disabled. - In
TrustedDistributors
mode, only distributors can stake - no direct user staking. - In combined mode, both distributor and Merkle paths are valid.
- The proof authorizes the
receiver
(anyone may relay the tx).
Common errors: WhitelistEnabled()
, OnlyTrustedDistributor()
, InvalidMerkleProof()
, InvalidAddress()
.
Pool Management
Configuration Parameters:
poolMaxCap
: Maximum total tokens stakeabletierUpperBound
: Maximum tokens per individual stakertierLowerBound
: Minimum tokens per individual stakerstartStakingDate
: Staking operations start timestampendStakingDate
: Staking operations end timestamp
Reward Calculation Systems
Basic Staking Formula:
reward = (stakedAmount × rewardRatioNumerator × timeStaked) / (rewardRatioDenominator × timeUnit)
Unbonding Staking Formula:
reward = (stakedAmount × timeStaked × apyPercentage) / (365 days × 10000)
Security Model
Access Control
Owner Role:
- Contract configuration updates
- Emergency token recovery
- Pool parameter modifications
- Whitelist management
Fee Collector Role:
- Fee withdrawal operations
- Fee collector address updates
Trusted Distributor Role:
- Staking on behalf of others (if whitelist enabled)
- Bypass certain whitelist restrictions
Protection Mechanisms
Reentrancy Protection:
- All state-changing functions use
ReentrancyGuardTransient
- Prevents recursive calls during execution
Input Validation:
- Parameter bounds checking
- Address validation (non-zero checks)
- Timestamp validation
- Amount validation
Balance Verification:
- Automatic balance checks post-transfer
- Prevents direct token transfers bypassing logic
- Excess token recovery mechanisms
Error Handling
The system uses custom error types for gas-efficient error reporting:
StakingErrors.InvalidAddress()
: Zero address or invalid addressStakingErrors.InsufficientFee()
: Insufficient fee providedStakingErrors.StakingNotStarted()
: Staking period not activeStakingErrors.StakingEnded()
: Staking period has endedStakingErrors.PoolMaxCapExceeded()
: Pool capacity exceededStakingErrors.InvalidMerkleProof()
: Invalid whitelist proof
Type Definitions
Enums
enum FeeType {
Gas,
DistributionToken
}
enum WhitelistStatus {
Disabled,
Merkle,
TrustedDistributors,
MerkleAndTrustedDistributors
}
Constants
uint256 public constant BASIS_POINTS = 10_000;
uint256 public constant MAX_STAKING_CONDITIONS_LIMIT = 512;
uint64 public constant MAX_UNBONDING_PERIOD = 365 days * 5;