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: 114/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
setPrimeToken
Function:Link
The setPrimeToken
function allows the owner of the contract to update the address of the prime token contract and emits an event to notify observers of this change. However, the problem lies in the ordering of operations within the function:
_emit PrimeTokenUpdated(prime, prime_); prime = prime_;
Here, the event PrimeTokenUpdated
is emitted before updating the prime
state variable with the new address prime_
. This sequence means that external contracts or observers listening to this event will receive the old value of prime, not the updated one. It can lead to external code relying on outdated information, potentially causing unexpected behavior.
The impact of this issue is that external code relying on the emitted event may make decisions or take actions based on outdated information about the address of the prime token contract. This could result in errors, inconsistencies, or vulnerabilities in the behavior of the contract or interacting contracts.
To address this issue, the order of operations in the setPrimeToken
function should be corrected. The state variable prime
should be updated before emitting the event, as follows:
function setPrimeToken(address prime_) external onlyOwner { _ensureZeroAddress(prime_); prime = prime_; // Update the state variable first emit PrimeTokenUpdated(prime, prime_); // Then emit the event }
Link
The vulnerability arises in the provided Solidity function getPendingInterests
, which is designed to calculate pending interest accrued for a user across all markets. The vulnerability details are as follows:
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({ market: IVToken(market).underlying(), amount: interestAccrued + accrued }); unchecked { i++; } } return pendingInterests; }
The function loops through the _allMarkets
array to calculate pending interest for a user across all markets. The gas limit challenge arises if _allMarkets
contains a large number of elements. In such cases, the gas cost of processing the loop may exceed the gas limit set for Ethereum transactions.
The impact of this gas limit challenge is that transactions invoking the getPendingInterests function may fail when processing a large number of markets. Users will not receive the expected results, and the contract's functionality may be limited when dealing with extensive data sets.
To mitigate the gas limit challenge when processing large arrays, consider implementing batch processing.
Link
LinkB
The vulnerable code section is within the _calculateScore
function, specifically when updating the asset price of xvsToken
using the oracle.updateAssetPrice(xvsToken)
function. Here's the relevant code snippet:
address xvsToken = IXVSVault(xvsVault).xvsAddress(); oracle.updateAssetPrice(xvsToken);
The purpose of this code is to obtain the current asset price of xvsToken
from an external oracle. However, the vulnerability lies in the fact that the obtained price may not be up-to-date, leading to inaccurate calculations of the user's score. This issue could occur due to delays in the oracle's data source or infrequent updates.
The impact of using stale prices in asset valuation is that the user's score, which relies on these prices, may not accurately reflect the current market conditions. This could lead to incorrect risk assessments and financial decisions within the decentralized application.
Instead of relying on a single price update, implement price averaging by considering the average of the last N price updates over a specific time period. This approach helps smooth out price fluctuations and reduces the impact of a single stale price on calculations.
#0 - c4-pre-sort
2023-10-06T01:22:58Z
0xRobocop marked the issue as low quality report
#1 - c4-judge
2023-11-03T02:09:55Z
fatherGoose1 marked the issue as grade-b