Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: medium
Invalid

connectedMarketsIdsCache is NOT Populated in Either Function

Summary

The memory array intialised with length but not populated empty array will be passed as an arguments which leads incorrect calculation and accounting in protocol.

Vulnerability Details

The function recalculateVaultsCreditCapacity() is used to calculate the vaults' credit capacity and update it based on the markets they are connected to. The connected markets are stored as an EnumerableSet, which can become corrupted when using the .remove() function, as it does not guarantee ordering. To address this, the developer attempts to cache the connected market IDs but declares them without initializing them.

// loads the connected markets storage pointer by taking the last configured market ids uint set
EnumerableSet.UintSet storage connectedMarkets = self.connectedMarkets[connectedMarketsConfigLength - 1];
// cache the connected markets ids to avoid multiple storage reads, as we're going to loop over them twice
// at `_recalculateConnectedMarketsState` and `_updateCreditDelegations`
uint128[] memory connectedMarketsIdsCache = new uint128[]());// @audit empty array here
...
// update vault and credit delegation weight
updateVaultAndCreditDelegationWeight(self, connectedMarketsIdsCache);// For loop
...
_recalculateConnectedMarketsState(self, connectedMarketsIdsCache, true);

In above code snippet we can see that connectedMarketsIdsCache passed without populate it. In function updateVaultAndCreditDelegationWeight() it used for-loop lenght condition

for (uint256 i; i < connectedMarketsIdsCache.length; i++) {

But in function it is used to copy markets Ids to rehydrated but with empty array default 0 will be copy this leads to incorrect calculation and accounting

for (uint256 i; i < connectedMarketsIdsCache.length; i++) {
if (shouldRehydrateCache) {
rehydratedConnectedMarketsIdsCache[i] = connectedMarkets.at(i).toUint128();// @audit check here
} else {
rehydratedConnectedMarketsIdsCache[i] = connectedMarketsIdsCache[i];// @audit check here
}

Impact

It will break the protocol accounting and calculations by passing empty array.

Tools Used

Foundry , Manual view

Recommendations

Populate before Passes as an Arguments

uint128[] memory connectedMarketsIdsCache = new uint128[]());;
for (uint256 i = 0; i < connectedMarketsIdsCache.length(); i++)
{
connectedMarketsIdsCache[i] = connectedMarkets.at(i).toUint128();
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
7 months ago
inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.