First Flight #21: KittyFi

First Flight #21
Beginner FriendlyDeFiFoundry
100 EXP
View results
Submission Details
Severity: high
Valid

`KittyPool::purrgeBadPawsion` Should Not Call `KittyVault::executeWhiskdrawal` But Directly Transfer Collaterals

[H-03] KittyPool::purrgeBadPawsion Should Not Call KittyVault::executeWhiskdrawal But Directly Transfer Collaterals

Summary

The purrgeBadPawsion function in the KittyPool contract is designed to incentivize liquidators by calling the executeWhiskdrawal function on each vault involved in the liquidation process. However, this approach inadvertently reduces the liquidator's own collateral instead of incentivizing them, as executeWhiskdrawal operates on the assumption that the liquidator is withdrawing their own funds. This misalignment leads to two primary issues:

  1. In the best-case scenario, the function will always revert due to the liquidator not having deposited any collateral with the protocol.

  2. In the worst-case scenario, the liquidator loses money instead of gaining a reward, as they pay the kitty coins for liquidating and receive their own deposited collateral instead of a reward.

Vulnerability Details

The core issue arises from the purrgeBadPawsion function calling _vault.executeWhiskdrawal(msg.sender, toDistribute + extraReward); with msg.sender as the user input, which incorrectly treats the liquidator as withdrawing their own collateral, thereby reducing their share instead of increasing it as a reward.

function purrgeBadPawsition(
address _user
) external returns (uint256 _totalAmountReceived) {
require(!(_hasEnoughMeowllateral(_user)), KittyPool__UserIsPurrfect());
uint256 totalDebt = kittyCoinMeownted[_user];
kittyCoinMeownted[_user] = 0;
@> i_kittyCoin.burn(msg.sender, totalDebt);
.
.
.
for (uint256 i; i < vaults_length; ) {
IKittyVault _vault = IKittyVault(vaults[i]);
uint256 vaultCollateral = _vault.getUserVaultMeowllateralInEuros(
_user
);
uint256 toDistribute = vaultCollateral.mulDiv(
redeemPercent,
PRECISION
);
uint256 extraCollateral = vaultCollateral - toDistribute;
uint256 extraReward = toDistribute.mulDiv(
REWARD_PERCENT,
PRECISION
);
extraReward = Math.min(extraReward, extraCollateral);
_totalAmountReceived += (toDistribute + extraReward);
@> _vault.executeWhiskdrawal(msg.sender, toDistribute + extraReward);
unchecked {
++i;
}
}
}

The executeWhiskdrawal function is designed to allow users to withdraw their collateral, but when called with the intention of rewarding a liquidator, it fails to serve its intended purpose.

function executeWhiskdrawal(
address _user,
uint256 _cattyNipToWithdraw
) external onlyPool {
//@audit-written high user cannot withdrawl if all collateral is supplied to aave atm
uint256 _ameownt = _cattyNipToWithdraw.mulDiv(
getTotalMeowllateral(),
totalCattyNip
);
@> userToCattyNip[_user] -= _cattyNipToWithdraw;
@> totalCattyNip -= _cattyNipToWithdraw;
@> totalMeowllateralInVault -= _ameownt;
IERC20(i_token).safeTransfer(_user, _ameownt);
}

Impact

This flaw directly impacts the financial outcome for liquidators, who are supposed to be rewarded for their actions but end up losing money instead.

Tools Used

Manual Review

Recommendations

To address this issue, a separate function specifically designed for liquidation rewards should be created. This new function would correctly increase the liquidator's share in the vaults, ensuring that they are genuinely incentivized for their role in the liquidation process.

Updates

Lead Judging Commences

shikhar229169 Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

`purrgeBadPawsition` doesn't reward the liquidator instead perform withdrawal of their own collateral or lead to a DoS

Support

FAQs

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