Summary
The purrgeBadPawsition
function has been identified with a potential bug related to the handling of zero collateral. The lack of validation for cases where userMeowllateralInEuros
is zero can lead to unintended behavior and may affect the accuracy of collateral redemption and reward distribution.
Vulnerability Details
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;
}
}
The function retrieves userMeowllateralInEuros
but does not validate if it is zero. If userMeowllateralInEuros
is zero, the calculation redeemPercent = totalDebt.mulDiv(PRECISION, userMeowllateralInEuros)
will result in zero. This prevents any collateral from being redeemed, potentially allowing users to avoid settlement or exploit the system.
Impact
Incorrect calculation of redeemPercent
and improper handling of collateral redemption and reward distribution. This could lead to financial losses or exploitation of the contract.
Tools Used
Manual Review
Recommendations
The following code addresses the issue by adding validation to handle cases where userMeowllateralInEuros
is zero:
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);
if (userMeowllateralInEuros == 0) {
revert("No collateral available");
}
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;
}
}
}