F-2025-0001·reward-accounting-error

Incorrect reward distribution logic in GenesisLicenseStaking causes stakers to earn less than expected

Acknowledgednftstakingeip-712
TL;DR

Reward-per-GL is divided by a fixed constant NFT_AMOUNT_PER_STAKING_POOL = 20000, regardless of how many NFTs are actually staked. Stakers receive a small fraction of the reward they should.

Severity
CRITICAL
Impact
HIGH
Likelihood
HIGH
Method
MManual review
CAT.
Complexity
LOW
Exploitability
HIGH
02Section · Description

Description

In the GenesisLicenseStaking contract, users stake their NFTs and later call unstake() or requestClaim() to receive staking rewards based on how long they were staked.

The pending reward is calculated like this:

solidity
uint256 stakingRewardPerGL = $._stakingRewardPerGL[stakingPools_[i]];
uint256 pendingReward = stakingRewardPerGL - stakeInfo.rewardPaid;

Where rewardPaid is the checkpoint value saved at the time of staking, and stakingRewardPerGL increases only when the rewardDistributor calls rewardDistribution():

solidity
$._stakingRewardPerGL[stakingPool_] += amount_ / NFT_AMOUNT_PER_STAKING_POOL;

However, the issue lies in the use of the constant:

solidity
uint256 public constant NFT_AMOUNT_PER_STAKING_POOL = 20000;

This assumes that all 20,000 NFTs have been minted and are staked simultaneously. This is inaccurate and leads to an under-distribution of rewards for the following reasons:

  1. Minting may not be complete. The total minted NFTs might be significantly less than 20,000.
  2. Not all NFTs are staked. At any point in time, only a fraction of holders may have actively staked their NFTs.

This results in the actual reward per staker being diluted unfairly, as amount_ is divided across a fixed and inflated denominator regardless of actual participation.

03Section · Impact

Impact

Stakers receive substantially less than the rewards the protocol is distributing. The undistributed remainder either remains in the contract or is permanently lost depending on accounting elsewhere. The Foundry PoC supplied with the finding demonstrates the underdistribution by staking 2 NFTs and observing total claimed value far below the distributed amount.

04Section · Recommendation

Recommendation

Update the reward distribution logic to reflect the real number of staked NFTs, rather than assuming the full cap. Specifically:

  • Maintain a counter for the number of NFTs actively staked per pool.
  • Distribute rewards proportionally based on this live count.

This ensures fair and dynamic reward allocation based on actual staker participation and avoids reward underflows due to inactive or unminted supply.

F-2025-0001

oog
zealynx

Smart Contract Security Digest

Monthly exploit breakdowns, audit checklists, and DeFi security research — straight to your inbox

© 2026 Zealynx