transferFrom operation in depositTokens()
safeTransferFrom execution in _cancelRequest()
The depositTokens() function on the L1 side does not perform checks to verify if the sender is a contract account. This oversight can lead to complications during the cancelRequest() process, potentially resulting in NFTs being locked within the contract.
In depositTokens():
The function does not perform any checks to verify if the sender (msg.sender) is a contract account.
It does not require the implementation of onERC721Received() for contract accounts.
In cancelRequest():
The function uses safeTransferFrom() to return NFTs.
safeTransferFrom() requires contract recipients to implement onERC721Received().
This inconsistency can lead to a situation where NFTs are accepted from contract accounts during deposit but cannot be returned to them during cancellation.
NFT Lock-up: If a contract account that doesn't implement onERC721Received() deposits an NFT and then attempts to cancel the request, the NFT will become locked in the escrow contract.
Create a file JustContract.t.sol in the test/mock folder:
And add the following to test/Bridge.t.sol:
Run the test: forge test --mt test\_cancelRequest\_forContract -vvvv
You will get the following output:
Evidently, the contract fails to retrieve the NFT after depositing it to the bridge.
Manual Review
Implement Consistent Checks: Add a check in depositTokens() to verify if the sender is a contract account. If so, require it to implement onERC721Received():
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.
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.