Incorrect reward distribution logic in GenesisLicenseStaking causes stakers to earn less than expected
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.
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:
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():
$._stakingRewardPerGL[stakingPool_] += amount_ / NFT_AMOUNT_PER_STAKING_POOL;
However, the issue lies in the use of the constant:
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:
- Minting may not be complete. The total minted NFTs might be significantly less than 20,000.
- 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.
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.
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.

