Part 2

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

Potential deadlock in credit delegation system (CreditDelegation.sol)

Summary

The clear() function in CreditDelegation.sol is responsible for resetting delegation-related state variables. However, it does not validate whether the market state has been fully synchronized before clearing. This could lead to a deadlock scenario, preventing new credit delegations or undelegations from being processed correctly.

Finding Description

The clear() function deletes multiple key delegation-related state variables, including:

54: function clear(Data storage self) internal {
delete self.vaultId;
delete self.marketId;
delete self.weight;
delete self.valueUsd;
delete self.lastVaultDistributedRealizedDebtUsdPerShare;
delete self.lastVaultDistributedUnrealizedDebtUsdPerShare;
delete self.lastVaultDistributedUsdcCreditPerShare;
delete self.lastVaultDistributedWethRewardPerShare;
}

The issue arises when clear() is executed before ensuring all pending market debt distributions are fully settled. Since it deletes the last distributed debt values, any ongoing or future operations that rely on these values could end up in an inconsistent state.

Impact

  • The system may not recognize existing credit or debt obligations after clearing, causing it to be stuck in an undefined state where new delegations cannot be processed.

  • Removing critical debt-related values (lastVaultDistributedRealizedDebtUsdPerShare, lastVaultDistributedUnrealizedDebtUsdPerShare) without proper reconciliation may cause miscalculations and prevent accurate tracking of outstanding debts.

  • If an undelegation process requires these deleted values, the function calls could fail or lead to unexpected behavior.

Likelihood

  • If clear() is only triggered after all debt obligations are settled, the risk is minimized.

  • However, if it can be called while outstanding debt values are still being processed, a deadlock becomes highly probable.

  • Since there are no built-in checks to prevent premature execution, this is an exploitable flaw in the current design.

Recommendation

To mitigate this risk, consider the following improvements:

  • Before executing clear(), ensure that all debts and credits are fully settled:

    require(self.valueUsd == 0, "Cannot clear delegation with outstanding credit.");
    require(self.lastVaultDistributedRealizedDebtUsdPerShare == 0, "Outstanding realized debt must be settled.");
    require(self.lastVaultDistributedUnrealizedDebtUsdPerShare == 0, "Outstanding unrealized debt must be settled.");
  • Instead of immediately deleting all values, introduce a soft reset:

    function softClear(Data storage self) internal {
    self.valueUsd = 0;
    self.weight = 0;
    self.marketId = bytes32(0); // Mark as inactive without losing reference
    }

    This allows pending operations to complete before permanently removing data.

  • Emit an event before and after clearing state:

    event DelegationCleared(bytes32 indexed vaultId, bytes32 indexed marketId);
Updates

Lead Judging Commences

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

Support

FAQs

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

Give us feedback!