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

Token Push Strategy Susceptible To OOG

Summary

Withdrawing atomic batches from escrow may exceed call gas limits.

Vulnerability Details

Due to data processing limits, the Ethereum Bridge contract enforces a MAX_PAYLOAD_LENGTH:

if (payload.length >= MAX_PAYLOAD_LENGTH) {
revert TooManyTokensError();
}

However, no such limit is enforced on the Starknet Bridge counterpart.

This makes it is possible to successfully generate payloads greatly in excess of the MAX_PAYLOAD_LENGTH from the L2 and request these to be handled back on Mainnet.

Furthermore, when we withdrawTokens, all bridged tokens must be redeemed simultaneously:

for (uint256 i = 0; i < req.tokenIds.length; i++) { /// @audit all_or_nothing
uint256 id = req.tokenIds[i];
bool wasEscrowed = _withdrawFromEscrow(ctype, collectionL1, req.ownerL1, id);
if (!wasEscrowed) {
// TODO: perhaps, implement the same interface for ERC721 and ERC1155
// As we only want to deal with ERC1155 token with value = 1.
// Also, check what to do with URIs. If the URI storage is supported
// or not for ERC721. If supported, we may need to mint with an URI.
IERC721Bridgeable(collectionL1).mintFromBridge(req.ownerL1, id);
}
}

Notice that each token in the batch must be successfully processed else the entire batch will fail.

If we consider the case of an IERC721Receiver which executes nontrivial business logic via onERC721Received callback, attempting to transfer all tokens at once to the receiver may exceed intended call gas limits and force the entire batch to fail. Likewise, if a single transaction were to fail (e.g. failed receiver validation), then the entire would also result in revert.

Impact

Susceptibility to OOG when withdrawing batches of bridged tokens from the L1 Bridge contract.

Tools Used

Manual Review

Recommendations

Firstly, it is imperative to enforce the invariant maximum payload size on Starknet when creating a payload.

Furthermore, we advise against the "push-payment" strategy when handling L2 payloads, and instead argue in favour of the "pull-payment" technique - receiving the payload at the Bridge L1 destination should merely approvereq.ownerL1 to withdraw the unlocked tokens in one-or-many subsequent transactions. This provides the flexibility to control which subset of tokens should be withdrawn from escrow.

This approach ensures that failures associated with transacting individual tokens, or failures associated with attempting to transact all tokens en masse, can be safely circumvented.

Updates

Lead Judging Commences

n0kto Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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