NFTBridge
60,000 USDC
View results
Submission Details
Severity: low
Invalid

Permanent loss of user's tokens if a transaction fails on the L1 side

Summary

When a user wants to bridge a token from L2 to L1, tokens will be escrowed in L2. But if for some reason bridging procedure fails, user's tokens will be freezed at L2 side forever with no possibility to withdraw them.

Vulnerability Details

For bridging a token from L2 to L1, the user needs to call deposit_tokens() in bridge.cairo. deposit_tokens() calls escrow_deposit_tokens() to transfer token from user to the L2 contract.

escrow_deposit_tokens(ref self, collection_l2, from, token_ids);

Then, at L1 side, the user needs to call withdrawTokens() function to receive the bridged tokens. However, if for some reasons, the transaction fails at this function, user's tokens will be freezed at L2 side with no possibility to withdraw them. Additionally, if a situation like the issue that I submitted titled "Collection address generated for L2 native token in Bridge.sol is not synced with bridge.cairo" happens and causes panic at L2 side when we bridge back L2 native tokens, there would be no possibility to withdraw tokens at L2 anymore. However, in addition to this example, any other bug or issue that can fail bridging procedure with tokens escrowed at L2 will cause the loss of user's tokens permanently.

As a result, there must be a function at the L2 side for withdrawing user's tokens in case of these unexpected situations. This mechanism is already provided in L1 → L2 message cancellation mechanism for situations like a bug in the dApp’s Cairo contract. From https://docs.starknet.io/architecture-and-concepts/network-architecture/messaging-mechanism/#l2-l1_message_cancellation:

The flow described here should only be used in edge cases such as bugs on the Layer 2 contract preventing message consumption.

Consider that Alice sends an L1 asset to a Starknet bridge to transfer it to L2, which generates the corresponding L1→L2 message. Now, consider that the L2 message consumption doesn’t function, which might happen due to a bug in the dApp’s Cairo contract. This bug could result in Alice losing custody of their asset forever.

To mitigate this risk, the contract that initiated the L1→L2 message can cancel it by declaring the intent to cancel, waiting five days, and then completing the cancellation. This delay protects the sequencer from a DoS attack in the form of repeatedly sending and canceling a message before it is included in L1, rendering the L2 block which contains the activation of the corresponding L1 handler invalid.

However, this withdraw mechanism is not provided for messages from L2 to L1.

During the audit period, I discussed this issue with ArkProject team, and they confirmed this as a valid issue and mentioned that something like a mismatch between L2 and L1 contract can trigger this bug and at that point there would be a need for an update of contract to have a kind of admin only withdraw function.

Impact

User's tokens can be freezed at L2 contract forever.

Tools Used

Manual Review

Recommendations

Consider an admin only mechanism for withdrawing tokens at L2 side in case of a bridging failure.

Updates

Lead Judging Commences

n0kto Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Appeal created

pwnforce Submitter
12 months ago
n0kto Lead Judge
12 months ago
n0kto Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

invalid-no-L2-cancel-mecanism-without-any-root-cause

Lack of feature is not a bug. Moreover that’s more something that the Starknet Core should implement since there is no way for Ark to have trusted data, preventing double spending. Finally, there is no real root cause in those reports, only suppositions that something bad can happen.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.