function poolCheckpoint() public virtual override returns (bool) {
if (killed) {
return false;
}
uint256 timeElapsed = block.timestamp - uint256(ammLastUpdated);
uint256 currentRate = IController(controller).inflationManager().getAmmRateForToken(
ammToken
);
uint256 crvEarned = IERC20(crv).balanceOf(address(this)) -
_preClaimRewardsCrvEarned +
crvRewardsContract.earned(address(this));
uint256 cvxEarned = getCvxMintAmount(crvEarned);
// Update the integral of total token supply for the pool
if (totalStaked > 0) {
if (inflationRecipient == address(0)) {
ammStakedIntegral += (currentRate * timeElapsed).scaledDiv(totalStaked);
} else {
perUserShare[inflationRecipient] += currentRate * timeElapsed;
}
crvStakedIntegral += (crvEarned - _crvLastEarned).scaledDiv(totalStaked);
cvxStakedIntegral += (cvxEarned - _cvxLastEarned).scaledDiv(totalStaked);
}
_crvLastEarned = crvEarned;
_cvxLastEarned = cvxEarned;
ammLastUpdated = uint48(block.timestamp);
return true;
}
In the current implementation, crvEarned is the new crv reward earned since the last claim.
However, anyone can send crv tokens to the contract to increase crvEarned.
Since cvxEarned is based on crvEarned, by increasing crvEarned, cvxStakedIntegral can be increased artificially.
When the increased cvx is worth more than the crv tokens sent, the attacker can net a profit from it.
Given:
Consider updating the cvxStakedIntegral after crvRewardsContract.getReward(); with the actual amount of CVX tokens received.
The text was updated successfully, but these errors were encountered:
All reactions