ETH$3,420
Launchpad/staking

Staking pools

A per-token pool that pays two reward assets — the token side of LP fees and the creator WETH share.

If a launch picks the staking fee policy on either side, the module clones a TokenStakingPool dedicated to that token. Holders stake the token and earn from two independent reward streams: the token side of LP fees, and the creator’s WETH share. Pick staking on both sides and one pool pays both.

#The rules

Stake
Any amount, any time. deposit(amount) after an ERC-20 approve.
Lock
Every deposit (re)locks your entire stake for 24 hours.
Unstake
After the lock, whenever you like — partially or in full. No exit fee, no penalty.
Claim rewards
Any time, lock or no lock. claimRewards() pays both assets at once.
Rewards asset
The token itself and WETH — never a third token, never a receipt token.
Admin
None. No owner, no pause, no rescue, no upgrade.
Why deposits re-lock everything
A per-deposit lock would let someone stake a large amount just before a fee collection and withdraw immediately after, farming a reward stream they took no risk in. Re-locking the whole stake makes that cost you 24 hours of exposure on your entire position.

#How rewards accrue

Each asset has its own rewardPerShare accumulator, so the two streams are completely independent — a token that only picked staking on the WETH side simply never accrues the token stream. Rewards are distributed pro-rata across whoever is staked at the moment they arrive; there is no vesting, no boost curve, and no lock multiplier.

  • Rewards that arrive at an empty pool are queued, not lost. They sit in queued and are released into the accumulator on the first deposit — and that depositor shares in them, since debts are snapshotted before the release.
  • Anyone can top the pool up. donateRewards (the token), donateWethRewards (WETH) and donateEthRewards (native ETH, wrapped on arrival) are all open. A creator running a campaign, or a community pooling for one, needs no permission.
  • Only the fee module can call the notify hooks. Its sole power is distributing rewards that have already been transferred in — it cannot move stakes and cannot take anything out.

#Pool API

solidityTokenStakingPool
// staking
function deposit(uint256 amount) external;                  // re-locks your whole stake 24h
function withdraw(uint256 amount) external;                 // reverts StillLocked(lockedUntil)
function claimRewards() external returns (uint256 tokenAmount, uint256 wethAmount);
function exit() external;                                   // withdraw everything + claim

// top-ups — open to anyone
function donateRewards(uint256 amount) external;            // in the staked token
function donateWethRewards(uint256 amount) external;        // in WETH
function donateEthRewards() external payable;               // in native ETH, wrapped here

// reads
function earned(address user) external view returns (uint256 tokenAmount, uint256 wethAmount);
function getStake(address user) external view returns (StakeInfo memory);
function totalStaked() external view returns (uint256);
function tokenRewards() external view returns (uint256 accPerShare, uint256 queued,
                                               uint256 totalAdded, uint256 totalPaid);
function wethRewards() external view returns (uint256 accPerShare, uint256 queued,
                                              uint256 totalAdded, uint256 totalPaid);

uint64 public constant LOCK_DURATION = 1 days;

#Finding a token’s pool

Pools are EIP-1167 clones, one per token, created at launch. Resolve one with StakingFeeModule.poolOf(token). The indexed StakingPool entity carries the same pool plus the staked total and both reward counters (Data & indexing). A zero address means the token did not choose staking — pools cannot be added afterwards.

#Reading the numbers honestly

FieldMeans
totalAddedLifetime rewards this pool has received in that asset.
totalPaidLifetime rewards claimed out of it.
queuedReceived while nobody was staked; releases at the next deposit.
accPerShareThe accumulator, scaled by 1e18. Not a rate — do not read it as APR.
There is no fixed APR here
Rewards are trading fees. They arrive when there is volume and stop when there is not, and the rate depends on how much is staked at the time. Any yield figure — including one hood.dev shows you — is a backward-looking observation, never a promise.

#Upgrades

StakingFeeModule.setPoolImplementation swaps the master copy that future launches clone. Existing pools are standalone clones of whatever implementation was current when they were created and are never touched by that call — including their code. The master copy itself is bricked in its constructor, so nobody can initialise it.

chain 4663·on-chain values read 2026-07-29·Blockscout