Beginner FriendlyDeFiFoundry
100 EXP
View results
Submission Details
Severity: low
Invalid

Panic: arithmetic underflow flaws in `Laundrette::withdrawMoney`.

Summary

Panic: arithmetic underflow flaws in Laundrette::withdrawMoney.

Vulnerability Details

  1. Function Call Sequence:

    • The withdrawMoney function calls withdrawUSDC.

    • withdrawUSDC calls withdraw, crimeMoney.burn, and usdc.transfer.

    • The withdraw function performs the arithmetic operation bank[account] -= amount.

  2. Potential Underflow in withdraw Function:

    • The withdraw function directly subtracts the amount from bank[account].

    • If amount is greater than bank[account], an underflow occurs, causing the resulting balance to wrap around to a very large number (2^256 - (amount - bank[account])).

Impact

The impact in your specific case, given the protections provided by Solidity 0.8.0 and later, is minimal. The built-in checks effectively prevent the underflow from causing unauthorized actions or corrupting the contract state. While the concern for underflows is valid in general.

PoC

Stateless fuzzing test

function test_WithdrawUSDCWithoutCrimeMoney(uint256 depositAmount, uint256 withdrawAmount) public payable {
uint256 initialUserBalance = 100e6;
console.log("depositAmount:", depositAmount);
console.log("withdrawAmount:", withdrawAmount);
// Ensure depositAmount starts at 2 and withdrawAmount starts at 1
vm.assume(depositAmount >= 100);
vm.assume(withdrawAmount >= 100);
joinGang(gangMemberOne);
vm.prank(godFather);
usdc.transfer(gangMemberOne, 100e6);
vm.startPrank(gangMemberOne);
// Only attempt deposit if the user has enough balance
if (depositAmount <= initialUserBalance) {
usdc.approve(address(moneyShelf), depositAmount);
laundrette.depositTheCrimeMoneyInATM(gangMemberOne, gangMemberOne, depositAmount);
if (withdrawAmount <= depositAmount) {
laundrette.withdrawMoney(gangMemberOne, gangMemberOne, withdrawAmount);
assertEq(
crimeMoney.balanceOf(gangMemberOne),
depositAmount - withdrawAmount,
"Balance after withdrawal should match expected value"
);
} else {
// Expect a revert due to insufficient balance
vm.expectRevert("Insufficient balance");
laundrette.withdrawMoney(gangMemberOne, gangMemberOne, withdrawAmount);
}
}
vm.stopPrank();
}

Traces output

vesper3023@LAPTOP-7INTR2BC:~/First_Flight/2024-05-mafia-take-down$ forge test --match-test test_WithdrawUSDCWithoutCrimeMoney -vv
[⠊] Compiling...
No files changed, compilation skipped
Ran 1 test for test/Laundrette.t.sol:LaundretteTest
[FAIL. Reason: Error != expected error: != Insufficient balance; counterexample: calldata=0x788f9c95000000000000000000000000000000000000000000000000000000000000080c00000000000000000000000000000000000000000000000000000000000018ab args=[2060, 6315]] test_WithdrawUSDCWithoutCrimeMoney(uint256,uint256) (runs: 4, μ: 152390, ~: 152390)
Logs:
⚠️ You have deployed a mock conract!
Make sure this was intentional
depositAmount: 2060
withdrawAmount: 6315
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 10.94ms (6.21ms CPU time)
Ran 1 test suite in 13.58ms (10.94ms CPU time): 0 tests passed, 1 failed, 0 skipped (1 total tests)
Failing tests:
Encountered 1 failing test in test/Laundrette.t.sol:LaundretteTest
[FAIL. Reason: Error != expected error: != Insufficient balance; counterexample: calldata=0x788f9c95000000000000000000000000000000000000000000000000000000000000080c00000000000000000000000000000000000000000000000000000000000018ab args=[2060, 6315]] test_WithdrawUSDCWithoutCrimeMoney(uint256,uint256) (runs: 4, μ: 152390, ~: 152390)
Encountered a total of 1 failing tests, 0 tests succeeded

Tools Used

Manual review

Stateless fuzz testing

Recommendations

Even though the immediate risk is mitigated, it’s good practice to include explicit checks in your smart contracts to handle these conditions gracefully and provide clear error messages. This can enhance the robustness and user experience of your smart contracts:

function withdraw(address account, uint256 amount) public {
+ require(bank[account] >= amount, "Insufficient balance");
bank[account] -= amount;
}
Updates

Lead Judging Commences

n0kto Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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