Description
In function MoneyVault::withdrawUSDC
, it requires to burn crimeMoney token in account
address. If there is no enough crimeMoney in account
address the transaction will fail, and nobody can withdraw the USDC within.
Impact
The gang member with crimeMoney can transfer his crimeMoney to some other wallet address, and to prevent GodFather from withdrawing this part of USDC.
Proof of Concept
function test_migrateAndWithdraw3() public {
address alice = makeAddr("alice");
address bob = makeAddr("bob");
joinGangGodFather();
joinGang(alice);
vm.prank(godFather);
usdc.transfer(alice, 100e6);
vm.startPrank(alice);
usdc.approve(address(moneyShelf), 100e6);
laundrette.depositTheCrimeMoneyInATM(alice, alice, 100e6);
vm.stopPrank();
EmergencyMigration migration = new EmergencyMigration();
MoneyVault moneyVault = migration.migrate(kernel, usdc, crimeMoney, moneyShelf, laundrette);
vm.prank(alice);
crimeMoney.transfer(bob, 100e6);
vm.prank(godFather);
vm.expectRevert();
laundrette.withdrawMoney(alice, godFather, 100e6);
}
Recommendations
remove the bank
mapping in moneyVault
, and only rely on crimeMoney balance to withdrawUSDC
function withdrawUSDC(address account, address to, uint256 amount) external permissioned {
require(to == kernel.executor(), "MoneyVault: only GodFather can receive USDC");
-- withdraw(account, amount);
crimeMoney.burn(account, amount);
usdc.transfer(to, amount);
}