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: 56/115
Findings: 2
Award: $36.64
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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
Judge has assessed an item in Issue #203 as 2 risk. The relevant finding follows:
L-1 Function updateScores spends all gas and reverts if a user has score updated Summary Function updateScores incorrectly handles case when a user’s score is already updated.
Vulnerability Details There is a for loop in the function updateScores that updates score for every user in users. If a user’s score is already updated, the user should be skipped and the next user should be updated. For this case there is an if statement (https://github.com/code-423n4/2023-09-venus/blob/b11d9ef9db8237678567e66759003138f2368d23/contracts/Tokens/Prime/Prime.sol#L208C1-L208C1):
if (isScoreUpdated[nextScoreUpdateRoundId][user]) continue; However, here is an issue. The variable i that is responsible for the current user in the loop is incremented in the end of the loop, but due to the continue statement, this code is not reached, the value of i remains and the current user is processed again and again until all the gas is spent, and then the function reverts.
Recommended Mitigation Steps When user’s score is updated, the i value must be incremented.
#0 - c4-judge
2023-11-03T16:43:47Z
fatherGoose1 marked the issue as satisfactory
#1 - c4-judge
2023-11-03T20:41:45Z
fatherGoose1 marked the issue as duplicate of #556
🌟 Selected for report: Bauchibred
Also found by: 0x3b, 0xDetermination, 0xMosh, 0xScourgedev, 0xTheC0der, 0xTiwa, 0xWaitress, 0xdice91, 0xfusion, 0xpiken, 0xprinc, 0xweb3boy, ArmedGoose, Aymen0909, Breeje, Brenzee, Daniel526, DavidGiladi, DeFiHackLabs, Flora, Fulum, HChang26, Hama, IceBear, J4X, Krace, KrisApostolov, Maroutis, Mirror, MohammedRizwan, Norah, PwnStars, SPYBOY, TangYuanShen, Testerbot, ThreeSigma, Tricko, al88nsk, alexweb3, ast3ros, berlin-101, bin2chen, blutorque, btk, d3e4, deth, e0d1n, ether_sky, ge6a, gkrastenov, glcanvas, hals, imare, inzinko, jkoppel, jnforja, joaovwfreire, josephdara, kutugu, lotux, lsaudit, mahdirostami, merlin, n1punp, nadin, neumo, nisedo, nobody2018, oakcobalt, orion, peanuts, pep7siup, pina, ptsanev, rokinot, rvierdiiev, said, santipu_, sashik_eth, seerether, squeaky_cactus, terrancrypt, tonisives, twicek, vagrant, xAriextz, y4y
4.3669 USDC - $4.37
Function updateScores
incorrectly handles case when a user's score is already updated.
There is a for
loop in the function updateScores
that updates score for every user in users
. If a user's score is already updated, the user should be skipped and the next user should be updated. For this case there is an if
statement (https://github.com/code-423n4/2023-09-venus/blob/b11d9ef9db8237678567e66759003138f2368d23/contracts/Tokens/Prime/Prime.sol#L208C1-L208C1):
if (isScoreUpdated[nextScoreUpdateRoundId][user]) continue;
However, here is an issue. The variable i
that is responsible for the current user in the loop is incremented in the end of the loop, but due to the continue
statement, this code is not reached, the value of i
remains and the current user is processed again and again until all the gas is spent, and then the function reverts.
When user's score is updated, the i
value must be incremented.
Function getPendingInterests
returns incorrect underlying token for VBNB market.
VBNB
market is specifically handled in function _getUnderlying
(https://github.com/code-423n4/2023-09-venus/blob/b11d9ef9db8237678567e66759003138f2368d23/contracts/Tokens/Prime/Prime.sol#L930-L936):
function _getUnderlying(address vToken) internal view returns (address) { if (vToken == VBNB) { return WBNB; } else { return IVToken(vToken).underlying(); } }
So, when market is VBNB
, the underlying token must be WBNB
, otherwise the underlying()
function result must be used. However, the function getPendingInterests
uses IVToken(vToken).underlying()
directly for all markets and has not special handling for VBNB
market (https://github.com/code-423n4/2023-09-venus/blob/b11d9ef9db8237678567e66759003138f2368d23/contracts/Tokens/Prime/Prime.sol#L183-L186):
pendingInterests[i] = PendingInterest({ market: IVToken(market).underlying(), amount: interestAccrued + accrued });
So, the VBNB market is not handled correctly, _getUnderlying
must be used instead.
Use function _getUnderlying
to get underlying token in function getPendingInterests
.
#0 - 0xRobocop
2023-10-07T02:17:15Z
L-01 dup of #556 L-02 dup of #101
#1 - c4-pre-sort
2023-10-07T15:22:47Z
0xRobocop marked the issue as sufficient quality report
#2 - c4-judge
2023-11-03T16:43:53Z
fatherGoose1 marked the issue as grade-b