Staking

Technical documentation for StakeChain — the Zentachain staking smart contract system.

Verified Contracts

All contracts are deployed on Ethereum mainnet and verified on Etherscan.

Contract
Address
Etherscan

Zentachain

0x6B58cfBEdCfe7C59d456c864c92257910A61D8FC

StakeChain

0xC00D35881e66E9eCC116De9696Ae12A18104B106

Zentanode

0x5a427e6aA609509C6EE089502a048f17B4895a9b


Overview

StakeChain is the staking smart contract that allows CHAIN token holders to stake their tokens in configurable pools and earn rewards. Rewards are minted directly to stakers — there is no pre-funded reward pool.

The contract is built on Solidity ^0.8.28 with OpenZeppelin v5.2.0 libraries and includes reentrancy protection, timestamp manipulation safeguards, and owner-controlled administration.


Live Staking Pools

Three staking pools are currently active on mainnet:

Pool
APR
Min Stake
Max Stake
Pool Size
Claim Lock
Unstake Lock

0

12%

1,000 CHAIN

10,000 CHAIN

100,000 CHAIN

1 day

7 days

1

16%

2,000 CHAIN

20,000 CHAIN

200,000 CHAIN

1 day

14 days

2

20%

5,000 CHAIN

50,000 CHAIN

500,000 CHAIN

1 day

28 days

Higher APR pools require larger minimum stakes and longer lock-up periods.


Pool System

Each staking pool is an independent configuration with its own parameters:

Parameter
Description

APR

Annual Percentage Rate in basis points (1600 = 16%)

Minimum Stake Amount

Lowest amount a user can stake

Maximum Stake Per User

Cap on individual stakes

Pool Size Limit

Maximum total tokens in the pool

Claim Time Lock

Minimum time between reward claims (1 day)

Unstake Time Lock

Minimum time before withdrawal allowed


Staking

Standard Staking

Two-transaction process:

  1. Approve — User approves the StakeChain contract to spend their CHAIN tokens

  2. Stake — Call stake(poolId, amount) to deposit tokens into a pool

Permit-Based Staking

Single-transaction process using ERC-2612 permit signatures:

  • Call stakeWithPermit(poolId, amount, deadline, v, r, s)

  • Combines approval and staking in one transaction

  • Saves gas and improves UX

Compound Staking

Users can add more tokens to an existing stake at any time:

  • Previous rewards are preserved and continue accruing

  • The unstake timer resets for the entire staked amount

  • New rewards begin accruing on the combined amount


Rewards

Calculation

Rewards are calculated based on time elapsed and the pool's APR:

Key details:

  • APR is stored in basis points (1200 = 12%, 1600 = 16%, 2000 = 20%)

  • A 15-minute timestamp buffer is applied to prevent manipulation

  • Rewards are minted to the user (inflationary), not drawn from a pool

Claiming

  • User calls claimRewards(poolId)

  • Claim time lock (1 day) must have elapsed since last claim

  • Pool must not be paused

  • Rewards are minted directly to the user's wallet


Unstaking

Standard Unstake

  • Unstake time lock must have elapsed since staking (7/14/28 days depending on pool)

  • Returns full staked amount plus any unclaimed rewards

  • Removes user from the pool

Emergency Unstake

  • Only available when emergency mode is enabled for the pool

  • Bypasses time lock restrictions

  • Returns staked amount plus accumulated rewards

  • Emergency mode has a 24-hour toggle cooldown to prevent abuse


Security

Feature
Implementation

Reentrancy Protection

nonReentrant modifier on all external calls

No Contract Interaction

noContracts modifier blocks smart contract callers

APR Change Delay

48-hour delay prevents front-running

Timestamp Buffer

15-minute buffer reduces manipulation window

Emergency Cooldown

24-hour cooldown on emergency toggle

Pause Mechanism

Pools can be paused individually

Max Stake Limits

Per-user cap enforcement per pool


Testing & Audit

Metric
Value

Test Cases

152 passing (100% coverage)

Test Files

18 dedicated test files

Security Rating

9.2 / 10

Code Quality

9.0 / 10

Gas Efficiency

8.5 / 10

Solidity Version

^0.8.28

OpenZeppelin Version

5.2.0

Framework

Hardhat + Chai

Security Tests Include

  • Access control enforcement

  • Staking limits and pool size enforcement

  • Timelock mechanism validation

  • Emergency function testing

  • Reward calculation precision and edge cases

  • APR change protection (48-hour delay, front-running prevention)

  • Timestamp manipulation protection

  • Pool deletion safety (only when empty)

  • Emergency toggle rate limiting

  • Permit-based staking validation

  • Deployment integrity verification

Security Verification Matrix

Check
Zentachain
StakeChain
Zentanode

Reentrancy Protection

Passed

Passed

Passed

Access Control

Passed

Passed

Passed

Input Validation

Passed

Passed

Passed

Integer Overflow

Passed

Passed

Passed

Emergency Pause

Passed

Passed

Passed

Time Manipulation

Passed

Passed

Passed

Front-running Protection

Passed

Passed

Passed

Rate Limiting

Passed

Passed

Passed


APR Changes

To prevent front-running:

  1. Owner schedules an APR change via scheduleAPRChange(poolId, newAPR)

  2. A 48-hour delay period begins

  3. After the delay, anyone can call applyPendingAPRChange(poolId) to activate it

  4. All changes are publicly visible on-chain


View Functions

Function
Returns

getPoolInfo(id)

Complete pool configuration

getUserStakeInfo(address, id)

User's staked amount, rewards, timestamps

getUserRewards(address, poolId)

Accumulated unclaimed rewards

getUnstakeUnlockTimestamp(address, poolId)

When unstake becomes available

getClaimUnlockTimestamp(address, poolId)

When next claim is available

getPoolStatus(poolId)

Whether pool is paused

getPoolEmergencyStatus(poolId)

Whether emergency mode is active

getMaximumStakeStatus(poolId)

Whether max stake is enforced

getPendingAPRChange(poolId)

Scheduled APR change details


Token Contract

Property
Value

Name

Zentachain

Symbol

CHAIN

Standard

ERC-20

Decimals

12

Total Supply

5,000,000

Features

Burnable, Pausable, Permit (EIP-2612)

Address

0x6B58cfBEdCfe7C59d456c864c92257910A61D8FC

StakeChain and Zentanode are both whitelisted as minters on the CHAIN token contract, allowing them to mint reward tokens directly.


Zentanode Rewards Contract

A separate contract (Zentanode.sol) handles node operator rewards independently from StakeChain:

Parameter
Value

Address

0x5a427e6aA609509C6EE089502a048f17B4895a9b

Rewards Per Claim

25 CHAIN (configurable, max 1,000)

Claim Duration

31 days

Slash Duration

15 days

Daily Mint Limit

100,000 CHAIN

Access

Allowlist-based

Node operators are added to the allowlist and can claim rewards at regular intervals. The contract includes a slashing mechanism for misbehaving nodes and pro-rated partial rewards for operator removal.

Last updated

Was this helpful?