First Flight #21: KittyFi

First Flight #21
Beginner FriendlyDeFiFoundry
100 EXP
View results
Submission Details
Severity: low
Invalid

The `KittyPool::purrgeBadPawsition` wont work with Revert on Zero transfer tokens

[L-01] the KittyPool::purrgeBadPawsition wont work with revert on zero transfer tokens

Summary

the purrgeBadPawsition will loop through vaults in order to liquidate user based on how much he owns in each vault. if a user has no collateral in one of the vaults it wont cause any problems, but if one of the collateral tokens is a wierd erc20 which reverts on zero transfer amount, it will revert the whole liqudation call, as a result users can just leave that specific collateral empty to never get liquidated.

Vulnerability Details

Note that if the vaultCollateral is zero, there is no check and it will try to call the executeWhiskdrawal nevertheless. causing reverts if there is a revert on zero transfer token in collaterals.

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);
uint256 userMeowllateralInEuros = getUserMeowllateralInEuros(_user);
uint256 redeemPercent;
if (totalDebt >= userMeowllateralInEuros) {
redeemPercent = PRECISION;
} else {
redeemPercent = totalDebt.mulDiv(
PRECISION,
userMeowllateralInEuros
);
}
uint256 vaults_length = vaults.length;
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;
}
}
}

Impact

Users can manipulate this to stop themselves from getting liquidated.

Tools Used

Manual Review

Recommendations

add a check before executeWhiskdrawal call to check if the amount being transfered is zero or not, if its zero dont transfer.

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);
uint256 userMeowllateralInEuros = getUserMeowllateralInEuros(_user);
uint256 redeemPercent;
if (totalDebt >= userMeowllateralInEuros) {
redeemPercent = PRECISION;
} else {
redeemPercent = totalDebt.mulDiv(
PRECISION,
userMeowllateralInEuros
);
}
uint256 vaults_length = vaults.length;
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);
+ if ((toDistribute + extraReward) != 0){
+ _vault.executeWhiskdrawal(msg.sender, toDistribute + extraReward);
+ }
- _vault.executeWhiskdrawal(msg.sender, toDistribute + extraReward);
unchecked {
++i;
}
}
}
Updates

Lead Judging Commences

shikhar229169 Lead Judge
10 months ago
shikhar229169 Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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