Reward-per-share or accrual math is wrong (updated in the wrong order, not scaled, or recomputed on stale state), letting users claim more rewards than earned or claim repeatedly.
function claim() external updateReward(msg.sender) {
uint r = rewards[msg.sender]; rewards[msg.sender]=0;
reward.safeTransfer(msg.sender, r);
}
modifier updateReward(address a){
rewardPerTokenStored = rewardPerToken();
rewards[a] += earned(a);
userPaid[a] = rewardPerTokenStored; _;
}
Largest recorded losses in the same failure class — related, not the same bug:
The SaferICO scanner runs 201 detectors over your Solidity source, SAFE-0067 among them. Paste an address or the source itself — a small per-scan fee, shown before you sign, or unlimited on any plan.