First Flight #21: KittyFi

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

Front-running attack

Summary

The Kitty-Fi contract is potentially vulnerable to front-running attacks, where malicious actors can exploit the timing of transactions to gain an unfair advantage.

Vulnerability Details

A front-running attack occurs when a malicious actor observes a pending transaction in the mempool and submits a similar transaction with a higher gas fee to be processed before the original transaction. This can be particularly problematic in DeFi contracts where timing and order of transactions are critical.
The executeDepawsit executeWhiskdrawal amd purrgeBadPawsition functions does not have mechanism to prevent front-running attack.

function executeDepawsit(address _user, uint256 _ameownt) external onlyPool {
uint256 _totalMeowllateral = getTotalMeowllateral();
uint256 _cattyNipGenerated;
if (_totalMeowllateral == 0) {
_cattyNipGenerated = _ameownt;
}
else {
>> _cattyNipGenerated = _ameownt.mulDiv(totalCattyNip, _totalMeowllateral);
}
userToCattyNip[_user] += _cattyNipGenerated;
totalCattyNip += _cattyNipGenerated;
totalMeowllateralInVault += _ameownt;
IERC20(i_token).safeTransferFrom(_user, address(this), _ameownt);
}

A malicious actor could front-run a deposit transaction to manipulate the user's collateral status.

function executeWhiskdrawal(address _user, uint256 _cattyNipToWithdraw) external onlyPool {
>> uint256 _ameownt = _cattyNipToWithdraw.mulDiv(getTotalMeowllateral(), totalCattyNip);
userToCattyNip[_user] -= _cattyNipToWithdraw;
totalCattyNip -= _cattyNipToWithdraw;
totalMeowllateralInVault -= _ameownt;
IERC20(i_token).safeTransfer(_user, _ameownt);
}

A malicious actor could front-run a withdrawal transaction to manipulate the user's collateral status or liquidate their position.

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;
}
}
}

A malicious actor could front-run the liquidation transaction to manipulate the user's debt position or collateral status, potentially profiting from the liquidation process.

Impact

Users could suffer financial losses if their transactions are front-run by malicious actors. For example, a user attempting to deposit or withdraw collateral might find their transaction executed at a less favorable rate or even reverted.
In the case of purrgeBadPawsition, a malicious actor could front-run the liquidation process to profit from the user's collateral.

Tools used

Manual Review

Recommendations

Implement a commit-reveal scheme for sensitive operations to prevent front-running. Users first commit to a transaction by submitting a hash, and later reveal the details to execute it.

Updates

Lead Judging Commences

shikhar229169 Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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