# Updating a pool's total points doesn't affect existing stake positions for rewards calculation

NeoTokyoStaker computes reward shares using current pool.totalPoints, so stake/unstake retroactively misprices existing positions' accrued rewards.

- Payout: Contest reward
- Severity: high
- Program: Neo Tokyo
- Credited: adriro
- Disclosed: 2023-04-11
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-03-neotokyo-findings/issues/423
- Library page: https://bugbountylibrary.com/r/c4%3A2023-03-neotokyo%3AH-01
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:accounting-error vuln:reward-distribution

**Target:** NeoTokyoStaker staking/rewards contract (getPoolReward)
**Root cause:** getPoolReward divides points by the live pool.totalPoints rather than a time-weighted reward-per-point accumulator, so past periods are recomputed at the current total.
**Steps:**
1. Alice stakes 100 points at t1; pool.totalPoints=100.
2. Bob stakes 100 points at t2; pool.totalPoints=200.
3. Alice calls getReward at t3; share = points*PRECISION/pool.totalPoints*totalReward uses 200, underpaying her for [t1,t2].
4. Inverse: Alice unstakes at t3 lowering totalPoints to 100; Bob claims at t4 and is overpaid for [t1,t3].
5. Griefer calls permissionless BYTES2.getReward(alice) while totalPoints is high to shrink Alice's payout.
**How found:** Code reading of getPoolReward: noticed pool.totalPoints is read live at claim time and is not tied to when positions were opened, so stake/unstake actions retroactively change the divisor for prior periods.
**Exploitation:** Any user or griefer triggers claim via permissionless BYTES2.getReward(victim) at a moment when pool.totalPoints is inflated by other stakes, forcing the victim's accrued rewards to be divided by the larger total and reducing their payout; conversely unstaking before a claim inflates the claimer's share.
**Escalation:** Griefer can time permissionless getReward calls against arbitrary victims to systematically reduce their rewards.
**Insight:** In staking/reward contracts, check whether the share divisor (totalPoints/totalSupply) is read live at claim time instead of via a rewardPerToken accumulator updated on every stake/unstake; live divisors let later deposits/withdrawals retroactively reprice earlier accrual.
