Submitted by 0xDetermination, also found by hals, Testerbot, bin2chen, Pessimistic, rokinot, ThreeSigma (1, 2), ether_sky, PwnStars, neumo, DeFiHackLabs, turvy_fuzz, Norah, dirk_y, deadrxsezzz, blutorque, SpicyMeatball, seerether, and said
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L397-L405 
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L704-L756 
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L623-L639 
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L827-L833 
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L200-L219 
https://github.com/code-423n4/2023-09-venus/blob/main/tests/hardhat/Prime/Prime.ts#L294-L301
Please note: All functions/properties referred to are in the Prime.sol contract.
A malicious user can accrue outsized rewards at the expense of other users after updateAlpha() or updateMultipliers() is called.
An attacker can prevent their score from being updated and decreased after the protocols alpha or multipliers change. This is done by manipulatively decreasing the value of pendingScoreUpdates, then ensuring that only other user scores are updated until pendingScoreUpdates reaches zero, at which point calls to updateScores() will revert with the error NoScoreUpdatesRequired(). This can be done via the attacker calling updateScores() to update other users scores first and/or DoSing calls to updateScores() that would update the attackers score (see the issue titled DoS and gas griefing of Prime.updateScores()).
The core of this vulnerability is the attackers ability to manipulate pendingScoreUpdates. Notice below that claim(), which is called to mint a users Prime token, doesnt change the value of pendingScoreUpdates:
However, burning a token decrements pendingScoreUpdates. (Burning a token is done by withdrawing XVS from XVSVault.sol so that the resulting amount staked is below the minimum amount required to possess a Prime token.) Notice below:
To inappropriately decrement the value of pendingScoreUpdates, the attacker can backrun the transaction updating the alpha/multiplier, minting and burning a Prime token (this requires the attacker to have staked the minimum amount of XVS 90 days in advance). If the number of Prime tokens minted is often at the max number of Prime tokens minted, the attacker could burn an existing token and then mint and burn a new one. Since the value of !isScoreUpdated[nextScoreUpdateRoundId][user] is default false, pendingScoreUpdates will be inappropriately decremented if the burned token was minted after the call to updateMultipliers()/updateAlpha().
As aforementioned, the attacker can ensure that only other users scores are updated until pendingScoreUpdates reaches zero, at which point further calls to updateScores will revert with the custom error NoScoreUpdatesRequired().
Relevant code from updateScores() for reference:
As seen, the attackers score can avoid being updated. This is signficant if a change in multiplier or alpha would decrease the attackers score. Because rewards are distributed according to the users score divided by the total score, the attacker can freeze their score at a higher than appropriate value and accrue increased rewards at the cost of the other users in the market.
The attacker can also prevent score updates for other users. The attacker can freeze a users score that would otherwise increase after the alpha/multiplier changes, resulting in even greater rewards accrued for the attacker and denied from other users. This is because it is possible to decrease the value of pendingScoreUpdates by more than one if the attacker mints and burns more than one token after the alpha/multiplier is updated.
Let $a$ represent the attackers score if it is properly updated after a change in alpha/multiplier, $b$ represent the properly updated total score, and $c$ represent the difference between the attackers larger unupdated score and the attackers smaller updated score. Clearly $a$, $b$, and $c$ are positive with $a < b$. Consider the following inequality, which holds true since $a \< b$ :
$`\frac{a+c}{b+c} > \frac{a}{b} \iff a+c > \frac{a(b+c)}{b} \iff a+c > a+\frac{ac}{b}$
Paste and run the below test in the mint and burn scenario in Prime.ts (line 302)
Hardhat
Check if pendingScoreUpdates is nonzero when a token is minted, and increment it if so. This removes the attackers ability to manipulate pendingScoreUpdates.
The call to updateMultipliers() can be frontrun by the attacker with staking XVS and/or lending/borrowing transactions in order to increase the attackers score before freezing it.
If the attacker wants to keep the inflated score, no actions that update the attackers score can be taken. However, the attacker can claim the outsized rewards earned at any time and as often as desired since claimInterest() does not update user scores.
If anyone has knowledge that the exploit has occurred, it is possible for any users score in a market to be updated with a call to accrueInterestAndUpdateScore(), which can neutralize the attack.
The required amount of XVS staked for this exploit can be reduced by 1000 if this exploit is combined with the exploit titled Irrevocable token holders can instantly mint a revocable token after burning and bypass the minimum XVS stake for revocable tokens.
chechu (Venus) confirmed and commented:
