Platform: Code4rena
Start Date: 02/10/2023
Pot Size: $1,100,000 USDC
Total HM: 28
Participants: 64
Period: 21 days
Judge: GalloDaSballo
Total Solo HM: 13
Id: 292
League: ETH
Rank: 48/64
Findings: 1
Award: $273.57
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: HE1M
Also found by: 0xsomeone, AkshaySrivastav, Aymen0909, J4de, Koolex, Mohandes, bin2chen, brgltd, cccz, hals, ladboy233, max10afternoon, peanuts, rvierdiiev, shealtielanz, tsvetanovv, zzzitron
273.5673 USDC - $273.57
https://github.com/code-423n4/2023-10-zksync/blob/615333f3c5ef3e1249879b56524214d4710c9fd7/code/contracts/ethereum/contracts/bridge/L1ERC20Bridge.sol#L188 https://github.com/code-423n4/2023-10-zksync/blob/615333f3c5ef3e1249879b56524214d4710c9fd7/code/contracts/ethereum/contracts/bridge/L1ERC20Bridge.sol#L278 https://github.com/code-423n4/2023-10-zksync/blob/615333f3c5ef3e1249879b56524214d4710c9fd7/code/contracts/ethereum/contracts/bridge/L1ERC20Bridge.sol#L340 https://github.com/code-423n4/2023-10-zksync/blob/615333f3c5ef3e1249879b56524214d4710c9fd7/code/contracts/ethereum/contracts/bridge/L1ERC20Bridge.sol#L342
HIGH - Assets can be locked
If the deposit limit is updated, users might not be able to claim their failed deposits.
For example, a user deposits while there is no deposit limit. Then the owner sets the deposit limit for that token. Then the issue may occur that the user may not be able to claim their failed deposit due to an underflow on line 345 in L1ERC20Bridge.sol.
Below is a snippet of the proof of concept demonstrating the issue.
The full code can be found in this gist.
The poc is written based on the code/contracts/ethereum/test/foundry/unit/concrete/Bridge/L1WethBridge/_L1WethBridge_Shared.t.sol
function test_claimFailedDeposit_poc() public { uint256 amount = 10000; l1Weth.deposit{value: amount}(); l1Weth.approve(address(bridgeProxy), amount); // user (address(this)) deposit bytes32 l2TxHash = bridgeProxy.deposit(randomSigner, address(l1Weth), amount, 1000000, REQUIRED_L2_GAS_PRICE_PER_PUBDATA, randomSigner); // owner setDepositLimit vm.prank(owner); allowList.setDepositLimit(address(l1Weth), true, type(uint256).max); // user (address(this)) claimFailedDeposit vm.expectRevert(stdError.arithmeticError); bridgeProxy.claimFailedDeposit(address(this), address(l1Weth), l2TxHash, 1, 2, 3, new bytes32[](0)); }
L1ERC20Bridge.deposit
AllowList.setDepositLimit
L1ERC20Bridge.claimFailedDeposit
,
however fails with "Arithmetic over/underflow"If the owner would have not updated the deposit limit, the user could have claimed the failed deposit.
Note: A simple mock zkSync contract is used for the ease of the test, which will return true for all proveL1ToL2TransactionStatus
call.
In the functions L1ERC20Bridge.deposit
and L1ERC20Bridge.claimFailedDeposit
, L1ERC20Bridge._verifyDepositLimit
is called to update totalDepositedAmountPerUser
.
https://github.com/code-423n4/2023-10-zksync/blob/615333f3c5ef3e1249879b56524214d4710c9fd7/code/contracts/ethereum/contracts/bridge/L1ERC20Bridge.sol#L188 https://github.com/code-423n4/2023-10-zksync/blob/615333f3c5ef3e1249879b56524214d4710c9fd7/code/contracts/ethereum/contracts/bridge/L1ERC20Bridge.sol#L278 https://github.com/code-423n4/2023-10-zksync/blob/615333f3c5ef3e1249879b56524214d4710c9fd7/code/contracts/ethereum/contracts/bridge/L1ERC20Bridge.sol#L340
However, the totalDepositedAmountPerUser
is only updated if the depositLimitation is set to be true.
So, if the user deposits while the depositLimitation is not set (false), the user's totalDepositedAmountPerUser
will be remain zero.
After the owner set the depositLimitation to be true, if the user should call the L1ERC20Bridge.claimFailedDeposit
, it will attempt to reduce the totalDepositedAmountPerUser
, which may result in Arithmetic over/underflow.
Manual
Consider updating totalDepositedAmountPerUser
even when depositLimitation is not set.
Under/Overflow
#0 - c4-pre-sort
2023-10-31T14:56:10Z
bytes032 marked the issue as duplicate of #425
#1 - c4-pre-sort
2023-10-31T14:56:43Z
bytes032 marked the issue as sufficient quality report
#2 - c4-judge
2023-11-24T19:55:35Z
GalloDaSballo changed the severity to 2 (Med Risk)
#3 - c4-judge
2023-11-24T20:01:02Z
GalloDaSballo marked the issue as satisfactory