Part 2

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

Incorrect weight calculation causes breaking of protocol functionality

Summary

Incorrect weight calculation, due to not summing up weights when calculating total weight leads to incorrect share values being outputted causing significant impacts in many parts of the protocol.

Vulnerability Details

function updateVaultAndCreditDelegationWeight(
Data storage self,
uint128[] memory connectedMarketsIdsCache
)
internal
{
// cache the connected markets length
uint256 connectedMarketsConfigLength = self.connectedMarkets.length;
// loads the connected markets storage pointer by taking the last configured market ids uint set
EnumerableSet.UintSet storage connectedMarkets = self.connectedMarkets[connectedMarketsConfigLength - 1];
// get the total of shares
uint128 newWeight = uint128(IERC4626(self.indexToken).totalAssets());
for (uint256 i; i < connectedMarketsIdsCache.length; i++) {
// load the credit delegation to the given market id
CreditDelegation.Data storage creditDelegation =
CreditDelegation.load(self.id, connectedMarkets.at(i).toUint128());
// update the credit delegation weight
creditDelegation.weight = newWeight;
}
// update the vault weight
self.totalCreditDelegationWeight = newWeight;
}

Here is the Vault::updateVaultAndCreditDelegationWeight function. The problem with this is that each weight is set to newWeight and the totalCreditDelegationWeight is also set to newWeight. As a result, in Vault::_updateCreditDelegations, each market will have a credit delegation share of 1:

UD60x18 creditDelegationShareX18 = ud60x18(creditDelegation.weight).div(ud60x18(totalCreditDelegationWeightCache));

since 2 of the same numbers divided by each other equal 1.
As a result, the new credit capacity each vault receives will be higher than it should be:

UD60x18 newCreditDelegationUsdX18 = vaultCreditCapacityUsdX18.gt(SD59x18_ZERO)
? vaultCreditCapacityUsdX18.intoUD60x18().mul(creditDelegationShareX18)
: UD60x18_ZERO;

This now incorrect value is set to be creditDelegation.valueUsd, therefore this value is also too high.

creditDelegation.valueUsd = newCreditDelegationUsdX18.intoUint128();

Then, when Vault::_recalculateConnectedMarketsState is called, incorrect values are used therefore, potentially leading to protocol insolvency since all the values for ctx.realizedDebtChangeUsdX18 / ctx.unrealizedDebtChangeUsdX18 / ctx.usdcCreditChangeX18 will be higher than they should be.

(
ctx.realizedDebtChangeUsdX18,
ctx.unrealizedDebtChangeUsdX18,
ctx.usdcCreditChangeX18,
ctx.wethRewardChangeX18
) = market.getVaultAccumulatedValues(
ud60x18(creditDelegation.valueUsd),
sd59x18(creditDelegation.lastVaultDistributedRealizedDebtUsdPerShare),
sd59x18(creditDelegation.lastVaultDistributedUnrealizedDebtUsdPerShare),
ud60x18(creditDelegation.lastVaultDistributedUsdcCreditPerShare),
ud60x18(creditDelegation.lastVaultDistributedWethRewardPerShare)
);

This incorrect values could lead to many issues, one for example being deleveraging taking place prematurely as the realised debt is too high for example so users lose profit they shouldn't use.

Impact

Auto deleveraging occurs too early causing unjustified extraction of profits from legitimate users.

Tools Used

Manual review

Recommendations

Set weight values correctly by summing them up when calculating th etotal.

Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Market Credit Delegation Weights Are Incorrectly Distributed

Support

FAQs

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