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

Lack of `L1->L2` Address Mapping Validation in `depositTokens()` Function May Lead to Locked Tokens on L1

Summary

The depositTokens() function in L1 bridge does not explicitly check if a valid mapping exists in the _l1ToL2Addresses mapping for the provided collectionL1 address.
This means that if the contract owner has not set up the mapping properly using the setL1L2CollectionMapping() function or the tokens are deposited before setting up of the mapping, the depositTokens() function will still attempt to use the default (likely zero) address for req.collectionL2.

Vulnerability Details

The depositTokens function is called with an L1 collection address (collectionL1):

function depositTokens(uint256 salt, address collectionL1, snaddress ownerL2, uint256[] calldata ids, bool useAutoBurn) external payable {
// ...
Request memory req;
// ...
req.collectionL2 = l1ToL2Addresses[collectionL1];
// ...
_depositIntoEscrow(ctype, collectionL1, ids);
req.tokenIds = ids;
uint256[] memory payload = Protocol.requestSerialize(req);
if (payload.length >= MAX_PAYLOAD_LENGTH) {
revert TooManyTokensError();
}
IStarknetMessaging(_starknetCoreAddress).sendMessageToL2{value: msg.value}(
snaddress.unwrap(_starklaneL2Address),
felt252.unwrap(_starklaneL2Selector),
payload
);
}

The function attempts to retrieve the corresponding L2 address (collectionL2) from the l1ToL2Addresses mapping without checking if the mapping exists. It directly assigns the retreived address to the request object without validating req.collectionL2.:

req.collectionL2 = *l1ToL2Addresses[collectionL1];

If the user calls this function and the mapping doesn't exist (i.e., if the owner hasn't set it up using setL1L2CollectionMapping), this will default to the zero address (0x0) for req.collectionL2.

The function proceeds to call sendMessageToL2 with this potentially invalid L2 address:

IStarknetMessaging(_starknetCoreAddress).sendMessageToL2{value: msg.value}(
snaddress.unwrap(_starklaneL2Address),
felt252.unwrap(_starklaneL2Selector),
payload
);

If the req.collectionL2 is set to an invalid address (e.g., the zero address), the sendMessageToL2() function will still accept this value and proceed to process the message and emit an event:

emit LogMessageToL2(msg.sender, toAddress, selector, payload, nonce, msg.value);

When this message is processed on the L2 (Starknet) side, it will likely fail due to the invalid collection address.

This could result in the user's tokens being locked in the escrow on L1, as the bridge transfer to Starknet will not complete successfully.

Impact

Users' tokens gets locked in the L1 escrow, as the L2 side won't be able to complete the transfer process with an invalid collection address.

Tools Used

Manual Review

Recommendations

Add a validation check in the depositTokens() function to ensure that a valid mapping exists for the provided collectionL1 address before proceeding with the token deposit and transfer.

+ if (req.collectionL2 == snaddress.unwrap(0x0)) {
+ revert InvalidCollectionMappingError();
+ }
Updates

Lead Judging Commences

n0kto Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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