🥩Staking

Learn about the 2.0 version of Staking CHAIN token currency instructions.

StakeChain Staking Documentation

Overview

StakeChain is a comprehensive staking platform that allows users to earn rewards by staking CHAIN tokens in multiple pools. Each pool has its own unique parameters including APR (Annual Percentage Rate), minimum and maximum stake amounts, and time locks for unstaking and claiming rewards. The system provides flexible staking options with robust security measures to protect user funds.

Pool System

The StakeChain contract manages multiple independent pools through the PoolInfo structure. Each pool operates with distinct parameters that determine how users can interact with it:

struct PoolInfo {
    bool created;
    uint256 APR;
    uint256 maximumStakedByUser;
    uint256 minimumStakeAmount;
    uint256 lastClaimedRewards;
    uint256 maxSize;
    uint256 unstakeTimeLock;
    uint256 claimTimeLock;
    uint256 totalStakers;
    uint256 totalStakedAmount;
    uint256 totalRewardsEarned;
}

Pool Parameters

APR (Annual Percentage Rate): Determines the yearly reward rate for staked tokens. For example, a 16% APR means users earn 16% of their staked amount annually

Minimum Stake Amount: The lowest amount of CHAIN tokens required to participate in a pool, ensuring meaningful participation and preventing spam transactions

Maximum Stake Per User: Optional limit on how much a single user can stake in a pool, promoting fair distribution of staking opportunities

Pool Size Limit: Maximum total tokens that can be staked across all users in a pool, preventing unlimited growth

Claim Time Lock: Minimum waiting period between reward claims, preventing frequent micro-transactions

Unstake Time Lock: Required waiting period after staking before tokens can be withdrawn, ensuring pool stability

User Staking Process

Standard Staking

Users can stake CHAIN tokens in any active pool using the standard staking function:

function stake(uint256 poolId, uint256 amount) external nonReentrant noContracts whenNotPaused(poolId)

Security Checks:

  • Pool must exist and be active

  • Amount must meet minimum stake requirement

  • Pool size limit cannot be exceeded

  • User must have sufficient token balance

  • Maximum stake per user limit enforced (if enabled)

  • Only externally owned accounts can stake (no contracts)

  • Pool must not be paused

Permit-Based Staking

For enhanced user experience, users can stake without separate approval transactions:

function stakeWithPermit(
    uint256 poolId,
    uint256 amount,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external nonReentrant whenNotPaused(poolId) noContracts returns (bool)

This function uses ERC20Permit to combine token approval and staking in a single transaction, reducing gas costs and improving user experience.

Reward System

Reward Calculation

Rewards are calculated using precise mathematics with timestamp buffering to prevent manipulation:

function calculateRewards(
    uint256 APR,
    uint256 amount,
    uint256 lastStakeOrClaimTimestamp
) private view returns (uint256) {
    uint256 rewardsEarnedRange = block.timestamp - lastStakeOrClaimTimestamp;
    
    if (rewardsEarnedRange > TIMESTAMP_BUFFER) {
        rewardsEarnedRange -= TIMESTAMP_BUFFER;
    }
    
    uint256 annualRewards = (amount * APR) / 10000;
    uint256 rewardsPerSecond = annualRewards / ONE_YEAR;
    
    return rewardsPerSecond * rewardsEarnedRange;
}

Security Features:

  • 15-minute timestamp buffer prevents manipulation

  • High precision calculations prevent rounding errors

  • APR stored in basis points (1600 = 16.00%)

Claiming Rewards

Users can claim accumulated rewards while keeping their tokens staked:

function claimRewards(uint256 poolId) external nonReentrant noContracts whenNotPaused(poolId)

Requirements:

  • Pool must exist and be active

  • User must have staked tokens

  • Claim time lock must have passed

  • Pool must not be paused

Unstaking Process

Standard Unstaking

Users can withdraw their staked tokens along with accumulated rewards:

function unstake(uint256 poolId) external nonReentrant noContracts whenNotPaused(poolId)

Security Checks:

  • Pool must exist

  • User must have staked tokens

  • Unstake time lock must have passed

  • Pool must not be paused

Emergency Unstaking

During emergency situations, users can immediately withdraw their funds:

function emergencyUnstake(uint256 poolId) external nonReentrant noContracts onEmergency(poolId)

Emergency unstaking bypasses normal time locks but requires the pool to be in emergency mode, which can only be activated by the contract owner.

Compound Staking

Users can add more tokens to their existing stake at any time. When additional tokens are staked:

  • The unstake timer resets for the entire staked amount

  • Previously earned rewards are preserved and continue accruing

  • New stake amount is added to the existing balance

  • Reward calculations continue based on the new total

This compound staking mechanism allows users to grow their stake while maintaining their reward history.

Security Measures

Access Control

No Contract Interaction: The noContracts modifier prevents smart contracts from interacting with staking functions, reducing attack vectors

Reentrancy Protection: All state-changing functions use nonReentrant modifier to prevent reentrancy attacks

Owner-Only Functions: Critical administrative functions are restricted to the contract owner

Time-Based Security

APR Change Delays: Changes to APR rates require a 48-hour delay to prevent front-running attacks

Emergency Toggle Cooldown: Emergency status can only be toggled once per day to prevent abuse

Timestamp Buffering: Reward calculations include a 15-minute buffer to prevent timestamp manipulation

Pool Security

Pause Mechanism: Pools can be paused to prevent new interactions during maintenance or emergencies

Maximum Stake Limits: Optional per-user and total pool limits prevent concentration of stakes

Pool Deletion: Empty pools can be deleted to clean up the contract state

View Functions for Users

Pool Information

function getPoolInfo(uint256 id) public view returns (PoolInfo memory)

Returns complete pool information including APR, limits, and current statistics.

User Stake Information

function getUserStakeInfo(address user, uint256 id) public view returns (StakeInfo memory)

Returns user's staking details including staked amount, rewards, and timestamps.

Reward Calculations

function getUserRewards(address user, uint256 poolId) public view returns (uint256)

Calculates total rewards available for claiming including both stored rewards and newly earned rewards.

Time Lock Information

function getUnstakeUnlockTimestamp(address user, uint256 poolId) public view returns (uint256)
function getClaimUnlockTimestamp(address user, uint256 poolId) public view returns (uint256)

Returns remaining time before users can unstake or claim rewards.

Pool Status Monitoring

Status Checks

function getPoolStatus(uint256 poolId) public view returns (bool)
function getPoolEmergencyStatus(uint256 poolId) public view returns (bool)
function getMaximumStakeStatus(uint256 poolId) public view returns (bool)

These functions allow users to check if pools are paused, in emergency mode, or have maximum stake limits enabled.

Best Practices for Users

Check Pool Status: Always verify pool status before attempting transactions

Monitor Time Locks: Track remaining time before unstaking or claiming becomes available

Understand APR Changes: Be aware that APR changes have a 48-hour delay for security

Emergency Procedures: Familiarize yourself with emergency unstaking procedures

Gas Optimization: Use permit-based staking to reduce transaction costs

Reward Timing: Plan reward claims considering time locks and gas costs

Error Handling

The contract provides clear error messages for common issues:

  • "Pool has not been created yet" - Invalid pool ID

  • "The staked amount is lower than the minimum stake amount required" - Insufficient stake

  • "The minimum lockup period has not passed" - Time lock not expired

  • "Pool operations are currently paused" - Pool is paused

  • "Not in Emergency" - Emergency function called on non-emergency pool

This comprehensive staking system provides users with flexible options for earning rewards while maintaining strong security measures to protect their investments.

Last updated

Was this helpful?