Emissions can be claimed multiple times
Description
The function claimEmissions
can be used by users to claim Y2K emissions. This function uses the correct vault balance of users to calculate the accumulated emissions and then subtracts the emission debt to find out the amount of emission tokens to be transferred to the users.
function claimEmissions(address receiver) external returns (uint256 emissions)
{
int256 accEmissions = int256(
(balanceOf[msg.sender] * accEmissionPerShare) / PRECISION
);
emissions = uint256(accEmissions - userEmissionDebt[msg.sender]);
userEmissionDebt[msg.sender] = accEmissions;
if (emissions > 0) emissionToken.safeTransfer(receiver, emissions);
emit EmissionsClaimed(msg.sender, receiver, emissions);
}
A user can also transfer their vault tokens to another account after calling claimEmissions
. As the emission debt is not transferred along with the vault balance, they can call claimEmissions
again using their other account and claim these emissions again.
This process can be repeated multiple times, effectively draining all the emission tokens from the StrategyVault contract.
Impact
All the emission tokens can be drained out of the contract.
Recommendations
While transferring tokens using the functions transfer
and transferFrom
, it is important to update the userEmissionDebt
mapping using the function _updateUserEmissions
.
To do this, override the _transfer
function, which is called in both transfer
and transferFrom
functions, to add the following additional logic.
function _transfer(address sender, address recipient, uint256 amount) internal virtual override {
+ _updateUserEmissions(sender,amount,false);
+ _updateUserEmissions(recipient,amount,true);
super._transfer(sender, recipient, amount);
}