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

L1-L2 Collection Remapping Leading to NFT Inaccessibility

Overview

This vulnerability arise on both ways L1 -> L2 and L2 -> L1, but for simplicity this report will only be on the L1 -> L2 way.

The Ark Project bridge contains a critical vulnerability that can lead to users losing access to their bridged NFTs. This issue arises when the mapping between L1 (Ethereum) and L2 (Starknet) collections is changed after initial bridging operations have occurred.

Initially, when users bridge their NFTs, the system automatically creates a corresponding collection on L2. However, if the original collection owner later deploys their own official L2 collection and ask the ark project team to updates the bridge mapping, previously bridged NFTs become orphaned in the old L2 collection.

These orphaned NFTs can no longer be bridged back to L1 or transferred to the new official L2 collection. As a result, users are left with inaccessible and potentially worthless NFTs on L2, trapped in a collection that's no longer recognized by the bridge.

Vulnerability Details

Scenario

  1. Users bridge NFTs from L1 to L2, triggering the deployment of an initial ERC721 contract on L2.

  2. The L1 collection owner later deploys their own NFT collection on L2.

  3. The Ark Project admin updates the L1-L2 mapping to point to the new L2 collection.

  4. Users with NFTs in the original L2 collection lose the ability to bridge back to L1.

Code Snippets

Initial bridging (simplified):

function bridgeNFTToL2(uint256 tokenId) external {
// Transfer NFT to bridge contract
l1Collection.transferFrom(msg.sender, address(this), tokenId);
// If L2 collection doesn't exist, deploy it
if (l2CollectionAddress == address(0)) {
l2CollectionAddress = deployNewL2Collection();
l1ToL2Mapping[address(l1Collection)] = l2CollectionAddress;
}
// Mint NFT on L2
IL2Bridge(l2BridgeAddress).mintNFT(l2CollectionAddress, msg.sender, tokenId);
}

Remapping function (vulnerable):

function updateL1L2Mapping(address l1Collection, address newL2Collection) external onlyOwner {
l1ToL2Mapping[l1Collection] = newL2Collection;
// No consideration for existing NFTs in the old L2 collection
}

Mermaid Diagram

sequenceDiagram
participant User
participant L1Bridge
participant L2Bridge
participant OldL2Collection
participant NewL2Collection
participant L1Collection
User->>L1Bridge: Bridge NFT to L2
L1Bridge->>OldL2Collection: Deploy & Mint NFT
Note over L1Bridge,OldL2Collection: Initial mapping created
L1Collection->>NewL2Collection: Deploy own L2 collection
L1Bridge->>L1Bridge: Update mapping to new L2 collection
L2Bridge->>L2Bridge: Update mapping to new L2 collection
Note over L1Bridge,NewL2Collection: Mapping updated, old L2 collection orphaned
User->>L2Bridge: Attempt to bridge NFT back to L1
L2Bridge-->>L1Bridge: Create a new collection uncorrelated to the original (NFT not in mapped collection)
Note over User,L2Bridge: User's NFT trapped in OldL2Collection or new useless NewL1Collection

Impact

  1. Loss of Asset Access: Users cannot bridge their NFTs back to original L1 collection from the original L2 collection.

  2. Asset Value Depreciation: Orphaned NFTs on L2 may lose value due to lack of bridging capability.

  3. Ecosystem Fragmentation: Creates inconsistencies between L1 and L2 token ownership and metadata.

Mitigation

Recommended Solution

Implement a migration system for NFTs when L1-L2 mappings change:

function migrateNFTsToNewL2Collection(address oldL2Collection, address newL2Collection) external {
require(isAuthorizedMigrator(msg.sender), "Not authorized");
uint256[] memory tokenIds = getTokensInCollection(oldL2Collection);
for (uint256 i = 0; i < tokenIds.length; i++) {
address owner = IERC721(oldL2Collection).ownerOf(tokenIds[i]);
IERC721(oldL2Collection).burn(tokenIds[i]);
IERC721(newL2Collection).mint(owner, tokenIds[i]);
}
emit CollectionMigrated(oldL2Collection, newL2Collection);
}
Updates

Lead Judging Commences

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

Informational / Gas

Please, do not suppose impacts, think about the real impact of the bug and check the CodeHawks documentation to confirm: https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity A PoC always helps to understand the real impact possible.

Appeal created

m4k2xmk Submitter
10 months ago
m4k2xmk Submitter
10 months ago
n0kto Lead Judge
9 months ago
n0kto Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational / Gas

Please, do not suppose impacts, think about the real impact of the bug and check the CodeHawks documentation to confirm: https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity A PoC always helps to understand the real impact possible.

Support

FAQs

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