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.