The withdrawTokens function in the bridge.sol contract is vulnerable to re-entrancy attacks. This vulnerability arises from the order of operations in the _withdrawFromEscrow function, where the token transfer occurs before the escrow state is updated.
When a user calls withdrawTokens on bridge contract to withdraw tokens received from L2, it verifies for each token ID in the request payload whether it is escrowed or not by calling the _withdrawFromEscrow function:
Inside _withdrawFromEscrow, if the token is found in the escrow (checked by _isEscrowed(collection, id)), the token is transferred using safeTransferFrom:
The critical issue is that the escrow state is updated after the token transfer.
The safeTransferFrom calls invoke the onERC721Received function in the to address (i.e., the recipient contract). If the recipient contract is malicious, it could recursively call withdrawTokens before the escrow state (_escrow[collection][id] = address(0x0);) is updated.
Bridge contract on L1 can be drained of its escrowed tokens.
Manual Review
Update the _escrow state before calling safeTransferFrom:
Impact: - NFT already bridged won’t be bridgeable anymore without being stuck. Likelyhood: Low. - Attackers will corrupt their own tokens, deploying a risky contract interacting with an upgradable proxy. They have to buy and sell them without real benefits, except being mean. Some really specific and rare scenario can also trigger that bug.
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.