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

Unauthorized Deposit and Withdrawal of USDC and CrimeMoney

Summary

The Laundrette::depositTheCrimeMoneyInATM function allows users to deposit USDC tokens and receive CrimeMoney on behalf of any address, even if the user does not have permission to access the funds of that address.

Vulnerability Details

The Laundrette::depositTheCrimeMoneyInATM function calls the depositUSDC function of the MoneyShelf contract, which performs the following operations:

Calls the deposit function of the Shelf contract to update the account balance.
Transfers USDC tokens from the specified account to the MoneyShelf contract using usdc.transferFrom(account, address(this), amount).
Mints CrimeMoney tokens for the specified to address.
The vulnerability lies in the fact that the usdc.transferFrom function does not check if the caller (Laundrette contract) has permission to transfer USDC tokens from the specified account. As long as the account has approved the MoneyShelf contract to spend its USDC tokens, any user can call depositTheCrimeMoneyInATM with that account and receive CrimeMoney tokens on behalf of any other address.

POC

function testDepositFromAnotherAccount() public {
vm.prank(godFather);
usdc.transfer(address(this), 200e6);
//user approve more usdc than deposited
usdc.approve(address(moneyShelf), 200e6);
laundrette.depositTheCrimeMoneyInATM(address(this), address(this), 100e6);
address alice = makeAddr("alice");
//alice will take adventage and transfer usdc in her account
laundrette.depositTheCrimeMoneyInATM(address(this), alice, 100e6);
assertEq(moneyShelf.getAccountAmount(address(this)), 100000000);
assertEq(moneyShelf.getAccountAmount(alice), 100000000);
assertEq(usdc.balanceOf(address(moneyShelf)), 200000000);
assertEq(usdc.balanceOf(alice), 0);
assertEq(usdc.balanceOf(address(this)), 0);
assertEq(crimeMoney.balanceOf(address(this)), 100000000);
assertEq(crimeMoney.balanceOf(alice), 100000000);
joinGang(alice);
vm.prank(alice);
//If alice has gangmember role, she can withraw usdc
laundrette.withdrawMoney(alice, alice, 100e6);
assertEq(usdc.balanceOf(alice), 100000000);
assertEq(usdc.balanceOf(address(this)), 0);
}

Impact

The impact is that it allows any user to deposit USDC tokens and receive CrimeMoney on behalf of any address, even if the user does not have permission to access the funds of that address. This lead to unauthorized transfers of funds and theft of USDC tokens and CrimeMoney.

Additionally, if the user receiving the CrimeMoney has the "gangmember" role, they can withdraw the USDC tokens deposited by the unauthorized user, effectively stealing the funds.

Tools Used

Aderyn, foundry

Recommendations

Use transfer unstead of transferFrom in MoneyShelf::depositUSDC function

function depositUSDC(address account, address to, uint256 amount) external {
deposit(to, amount);
- usdc.transferFrom(account, address(this), amount);
+ usdc.transfer(address(this), amount);
crimeMoney.mint(to, 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.