Platform: Code4rena
Start Date: 28/09/2023
Pot Size: $36,500 USDC
Total HM: 5
Participants: 115
Period: 6 days
Judge: 0xDjango
Total Solo HM: 1
Id: 290
League: ETH
Rank: 35/115
Findings: 2
Award: $157.23
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: deth
Also found by: 0xDetermination, 0xpiken, 3agle, Brenzee, Flora, HChang26, KrisApostolov, Satyam_Sharma, Testerbot, aycozynfada, berlin-101, gkrastenov, mahdirostami, merlin, rokinot, rvierdiiev, said, santipu_, sl1, tapir, twicek
124.9633 USDC - $124.96
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L331-L359
user can still claim revocable
token even after upgraded to irrevocable
token
Prime.issue, issue prime token to user by checking if the token is irrevocable or revocable, https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L331C5-L359C6
if (isIrrevocable) { for (uint256 i = 0; i < users.length; ) { Token storage userToken = tokens[users[i]]; if (userToken.exists && !userToken.isIrrevocable) { _upgrade(users[i]); } else { _mint(true, users[i]); _initializeMarkets(users[i]); } unchecked { i++; }
if token issued is irrevocable it runs a for loop which saves user prime token's metadata to userToken
after that it checks for the user token metdata that if the token exists and if the user token is revocable, if (userToken.exists && !userToken.isIrrevocable)
than it calls to _upgrade
which upgrade the user token to irrevocable by incrementing totalIrrevocable
and decrementing totalRevocable
and if this condition fails the issue function calls to _mint
and _initializeMarkets
for irrevocable tokens,
further if the issued token is not irrevocable it calls _mint
and _initializeMarkets
after that it deletes the stakedAt mapping which tracks the claiming of tokens,
else { for (uint256 i = 0; i < users.length; ) { _mint(false, users[i]); _initializeMarkets(users[i]); delete stakedAt[users[i]]; unchecked { i++; } } }
The issue arises when the token is upgraded to irrevocable, but the stakedAt mapping, which tracks when users can claim tokens, is not deleted. This means that even though the token has been upgraded to irrevocable, users can still claim revocable tokens if they were eligible before the upgrade.
if (userToken.exists && !userToken.isIrrevocable) { _upgrade(users[i]);
manual
delete the claiming period for revocable token after the token get upgraded to irrevocable token,
delete stakedAt[users[i]];
Other
#0 - c4-pre-sort
2023-10-06T01:19:29Z
0xRobocop marked the issue as duplicate of #633
#1 - c4-judge
2023-11-01T19:32:01Z
fatherGoose1 marked the issue as satisfactory
#2 - c4-judge
2023-11-05T00:50:32Z
fatherGoose1 changed the severity to 3 (High Risk)
🌟 Selected for report: 0xDetermination
Also found by: 0xblackskull, 0xweb3boy, ADM, Breeje, Pessimistic, PwnStars, SBSecurity, Satyam_Sharma, ThreeSigma, al88nsk, blutorque, debo, dethera, maanas, neumo, oakcobalt, pina, said, sces60107, tapir, tsvetanovv, xAriextz
32.2731 USDC - $32.27
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L208-L226
Prime.updateScores the for loop will never get incremented if isScoreUpdated
is true, due to the continue statement that will lead to run for loop infinite number of times.
Prime.updateScores updates the score for every user, who has registered prime token in the contract under this function it checks if the user score updated for not as if (isScoreUpdated[nextScoreUpdateRoundId][user]) continue;
and if isScoreUpdated = true
for any user conditional "continue" statement will triggered and the code continues to next iteration without incrementing "i" hence the next loop is executed for the same index resulting in an infinite loop which reverts due to txn gas limit.
Prime.sol#L208-L226
if (isScoreUpdated[nextScoreUpdateRoundId][user]) continue; address[] storage _allMarkets = allMarkets; for (uint256 j = 0; j < _allMarkets.length; ) { address market = _allMarkets[j]; _executeBoost(user, market); _updateScore(user, market); unchecked { j++; } } pendingScoreUpdates--; isScoreUpdated[nextScoreUpdateRoundId][user] = true; unchecked { i++; }
manual
The solution for this issue would be to either manually increment the "i" when we "continue" or to simply use the default "for" loop syntax without the gas opt
Loop
#0 - c4-pre-sort
2023-10-06T01:16:50Z
0xRobocop marked the issue as duplicate of #556
#1 - c4-judge
2023-11-01T03:06:29Z
fatherGoose1 marked the issue as satisfactory