Skip to main content

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

ContractDescriptionPurpose
StakingFactoryDeploys basic staking contractsStandardized deployment with fee management
UnbondingStakingFactoryDeploys unbonding staking contractsAPY-based rewards with withdrawal delays

Staking Contracts

ContractDescriptionReward ModelWithdrawal
StakingBasic staking implementationTime-based flexible ratiosImmediate
StakingWithUnbondingUnbonding staking implementationFixed APY calculationTwo-phase with delays

Utility Libraries

LibraryDescriptionFunctionality
StakingBaseAbstract base contractCore staking functionality
FactoryFeeManagerFee management systemCustom and default fee handling
CurrencyTransferLibToken transfer utilitiesSafe ERC20 and ETH transfers
FeeFunctionsFee bitmask utilitiesFunction-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:

  1. Factory Level: Default fees and per-creator custom fees
  2. Contract Level: Function-specific fee application using bitmasks

Fee Types:

  • Gas: Fixed ETH amount per transaction
  • DistributionToken: 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 when Disabled.
  • stake(amount, receiver): requires caller to be trusted distributor in distributor modes; not allowed in Merkle.
  • stake(amount, receiver, proof): when Merkle is active; verifies leaf keccak256(abi.encodePacked(receiver)) against merkleRoot.

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 stakeable
  • tierUpperBound: Maximum tokens per individual staker
  • tierLowerBound: Minimum tokens per individual staker
  • startStakingDate: Staking operations start timestamp
  • endStakingDate: 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 address
  • StakingErrors.InsufficientFee(): Insufficient fee provided
  • StakingErrors.StakingNotStarted(): Staking period not active
  • StakingErrors.StakingEnded(): Staking period has ended
  • StakingErrors.PoolMaxCapExceeded(): Pool capacity exceeded
  • StakingErrors.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;