Every time that we bridge an L1 native token to L2, a new collection address will be generated by calling function ensure_erc721_deployment()
at L2 side. A similar critical bug to this one is reported in the audit report provided during the contest titled "...a different collection address will be generated for every native l2 token bridged". However, this is a different bug with different root cause that cannot be fixed by the recomendations mentioned in that audit report.
For bridging an L1 native token to L2, we need to call function depositTokens()
in Bridge.sol. The req.collectionL2
will be zero since this is the first time that we are bridging this collection:
At L2 side, the function withdraw_auto_from_l1()
will be called. withdraw_auto_from_l1()
calls ensure_erc721_deployment()
and it calls verify_collection_address()
. since L1 address is present in the request and L2 address is not, the following code will be executed:
As a result, a new address will be generated for that collection at L2, and it will be mapped to L1 address:
However, bridge code at L1 side is not synced with this new generated address for the collection, and the next time that we bridge a token from that collection from L1 to L2, a new address will be generated for the collection because we receive a zero address in req.collection_l2
every time.
For every native L1 token from a same collection, we will have a different collection address at L2 side.
Manual Review
The root cause of this bug is that the bridge code at L1 side is not synced with the new generated address for the collection at L2 side. Thus, there is a need to implement a mechanism for notifying the L1 side about this update (e.g., with a message from L2 to L1).
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.