Closed c4-submissions closed 11 months ago
bytes032 marked the issue as duplicate of #827
GalloDaSballo changed the severity to QA (Quality Assurance)
This previously downgraded issue has been upgraded by GalloDaSballo
GalloDaSballo marked the issue as not a duplicate
GalloDaSballo marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/contracts/ethereum/contracts/bridge/L1ERC20Bridge.sol#L195-L197 https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/contracts/ethereum/contracts/bridge/L1WethBridge.sol#L182-L184 https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/contracts/ethereum/contracts/zksync/facets/Mailbox.sol#L262-L272 https://github.com/code-423n4/2023-10-zksync/blob/1fb4649b612fac7b4ee613df6f6b7d921ddd6b0d/code/contracts/ethereum/contracts/zksync/facets/Mailbox.sol#L312-L314
Vulnerability details
Impact
L1ERC20Bridge
contract is designed to allow users to deposit ERC20 tokens from Ethereum chain to zkSync Era chain by by locking funds in the contract and sending the request of processing an L2 transaction where tokens would be minted to.If a user wants to bridge his ERC20 tokens from L1 to L2:
He invokes the
L1ERC20Bridge.deposit
function with the following parameters:where the
_refundRecipient
is the address on L2 that will receive the refund for the transaction.Then a check is made on the
_refundRecipient
argument if it's a zero address; then it will be set to the L2 aliased address of themsg.sender
if the transaction is sent by a contract (when msg.sender != tx.origin):Then a call to the
zkSync.requestL2Transaction
is sent with the updated/aliasedrefundRecipient
address:This call is sent to the
DiamondProxy
contract where it will invoke theMailbox.requestL2Transaction
function in L1:In
Mailbox.requestL2Transaction
function: acanonicalTxHash
will be created by the_requestL2Transaction
function.But it was noticed in the
_requestL2Transaction
function that therefundRecipient
will be aliased again ifrefundRecipient.code.length > 0
:This will result in wrong address of the
refundRecipient
due to aliasing the L1 address to L2 address twice, so the added operation will not send the refund of the transaction to the correct address and the transaction initiator will lose this asset/refund.The same issue is spotted in
L1WethBridge.deposit
function.Proof of Concept
Code Instances:
The first aliasing in L1ERC20Bridge:
L1ERC20Bridge.deposit function/L195-L197
The first aliasing in L1WethBridge:
L1WethBridge.deposit function/L182-L184
The second aliasing in Mailbox:
Mailbox.requestL2Transaction function/L262-L272
Mailbox._requestL2Transaction function/L312-L314
Foundry PoC:
Add the following test file (
AddressAliasHelperTest
) in thecode/contracts/ethereum/test/foundry/unit/concrete/Bridge/L1WethBridge/AddressAliasHelperTest.t.sol
directory, where a test is set to check that aliasing the address twice will result in different L2 addresses :Test result:
Tools Used
Manual Testing & Foundry.
Recommended Mitigation Steps
Remove
refundRecipient
address aliasing fromL1ERC20Bridge.deposit
&L1WethBridge.deposit
functions so that it will be only aliased to L2 address format once in theMailbox.requestL2Transaction
.Assessed type
Context