In the L2 implementation of _ensureTokenRegisteredWithNTV,
the function fails to return a valid
assetId after attempting to register a token. This oversight leads the withdrawToken
function to receive an invalid assetId (bytes32(0))
, disrupting the withdrawal flow. As withdrawToken
calls withdrawSender
with this invalid assetId, the lack of a valid identifier results in misrouted or incomplete transactions, failed interactions within _withdrawSender
, and mismanaged token burns in the bridgeBurn and _bridgeBurnBridgedToken flows
.
The issue arises because the L2 version of _ensureTokenRegisteredWithNTV
does not return an assetId
,
contrary to the L1 function, which correctly retrieves and returns this value. This discrepancy means that
when withdrawToken calls _ensureTokenRegisteredWithNTV
, it receives bytes32(0)
as the assetId.
Consequently, downstream functions in the withdrawal process are fed an invalid assetId
, disrupting the withdrawal and
bridging functions.
Correct L1 Function (Benchmark)
The L1 implementation of _ensureTokenRegisteredWithNTV
ensures that a valid assetId is returned, as seen below:
L2 Function with the Vulnerability
In contrast, the L2 version of _ensureTokenRegisteredWithNTV
does not return any assetId,
causing withdrawToken
to receive an invalid identifier (bytes32(0)), which propagates through the withdrawal flow:
When _withdrawSender
is called with an invalid assetId (bytes32(0))
, it attempts to retrieve the asset handler
address using assetHandlerAddress[_assetId]
, which is likely uninitialized or incorrect due to the invalid
identifier. This results in potentially null interactions, failed transactions, or unintended contract actions,
as _withdrawSender
interacts with incorrect or undefined addresses.
The bridgeBurn function, which is called within _withdrawSender
, expects a valid assetId to differentiate
between native and bridged token burning. Since the originChainId[_assetId]
will not match the current chain ID
due to the invalid assetId, bridgeBurn
proceeds with _bridgeBurnBridgedToken
.
In _bridgeBurnBridgedToken
, the following issues arise:
The tokenAddress[_assetId]
mapping fetches an incorrect or null address for bridgedToken
due to the
invalid assetId
.
Consequently, when IBridgedStandardToken(bridgedToken).bridgeBurn(_originalCaller, _amount)
is called, it could
attempt to burn tokens at an incorrect address, leading to token mismanagement or reverts.
The function continues to rely on a valid assetId to set originChainId
and retrieve metadata, both of which would
fail or produce incorrect results, causing incomplete or incorrect token handling.
If the _assetId
used is invalid, _bridgeBurnBridgedToken
emits an originChainId[_assetId]
value of 0, leading to
a ZeroAddress revert, ultimately blocking the withdrawal process for users.
As _withdrawSender
continues with erroneous data, the entire withdrawal attempt can revert,
leaving users unable to access their funds on L1. This results in funds being effectively locked on L2,
preventing users from completing their withdrawal due to the invalid assetId
.
In summary, the lack of a valid assetId
in the L2 _ensureTokenRegisteredWithNTV
function leads to failed
contract interactions, mismanaged token burns, and incomplete withdrawals, directly impacting users
attempting to bridge tokens to L1.
Manual Review
To ensure withdrawToken and _withdrawSender
operate with the correct assetId, the L2 _ensureTokenRegisteredWithNTV
function should be updated to retrieve and return the assetId as in the L1 implementation.
With this correction, withdrawToken will consistently receive a valid assetId, ensuring reliable token
handling within _withdrawSender
and complete, accurate execution of user withdrawals.
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.