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: 109/115
Findings: 1
Award: $4.37
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L174-L194 https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L930-L936
The getPendingInterests
function is using IVToken(market).underlying()
to get the underlying token address returned but this will not handle the case of VBNB/WBNB
as it is done _getUnderlying
which will result in the wrong underlying token being returned when dealing with VBNB
market which will be misleading to users and parties relying on the returned values in their respective protocols
The issue occurs in the getPendingInterests
function below :
function getPendingInterests(address user) external returns (PendingInterest[] memory pendingInterests) { address[] storage _allMarkets = allMarkets; PendingInterest[] memory pendingInterests = new PendingInterest[](_allMarkets.length); for (uint256 i = 0; i < _allMarkets.length; ) { address market = _allMarkets[i]; uint256 interestAccrued = getInterestAccrued(market, user); uint256 accrued = interests[market][user].accrued; pendingInterests[i] = PendingInterest({ //@audit should use _getUnderlying(market) to handle VBNB/WBNB market: IVToken(market).underlying(), amount: interestAccrued + accrued }); unchecked { i++; } } return pendingInterests; }
As you can see the call directly IVToken(market).underlying()
to the market underlying token address but this will not work with the VBNB
market, as it's handled differently in the _getUnderlying
function below :
function _getUnderlying(address vToken) internal view returns (address) { //@audit `VBNB/WBNB` is a special market if (vToken == VBNB) { return WBNB; } else { return IVToken(vToken).underlying(); } }
Thus the getPendingInterests
function could return a wrong address (or zero address) when dealing with VBNB/WBNB
market, this can cause problems for users or other protocols relying on the returned data (token address & accrued rewards) in their logic.
Manual review
To avoid this issue you should use _getUnderlying
function to get underlying token address in getPendingInterests
.
Context
#0 - c4-pre-sort
2023-10-05T01:59:04Z
0xRobocop marked the issue as duplicate of #101
#1 - c4-judge
2023-11-01T20:21:41Z
fatherGoose1 marked the issue as satisfactory
#2 - c4-judge
2023-11-03T01:45:20Z
fatherGoose1 changed the severity to QA (Quality Assurance)