In L1Bridge
when we are withdrawing NFTs, and these NFTs are held by the Bridge, we transfer them from the Bridge to the receiver, then we burn that NFT by setting escrow address to zero
.
But in L2Bridge
escrowed NFT token is not burned when transferring, we are just transferring the NFT without resetting the escrow mapping to address_zero
.
So this will result in an NFT being escrowed by the L2Bridge
(which is like being owned by him), But it is actually owned by another owner, which is the ownerL2
that received the tokens when Bridging tokens from L1
to L2
.
UserA Bridged an NFT token from L2
to L1
via L2Bridge::deposit_tokens()
.
This NFT token is now escrowed by the L2Bridge
and it holds it.
UserA received the NFT on L1
by his L1Address
.
Time passed, and this NFT is traded between addresses.
This NFT is now getting Bridged from L1
to L2
via L1Bridge::depositTokens()
This NFT token is now escrowed by the L1Bridge
and it holds it.
This token is getting withdrawn from L2Bridge
.
Token was transferred to the ownerL2
but did not burn on L2Bridge
(it is still escrowed).
NFT token is escrowed by L2Bridge
, but it doesn't hold it.
NFT tokens is escrowed in both L1Bridge
and L2Bridge
.
Incorrect State modification, where the NFT tokens will still be escrowed by L2Bridge
but it doesn't hold them.
The NFTs will be escrowed in both L1Bridge
and L2Bridge
which breaks NFTs bridging invariant, where the NFT will exist in both Bridged in the time it should only be on only one Bridge (should be escrowed one chain).
Manual Review
Burn the NFT by setting its escrow to address_zero
in L2Bridge
.
Impact: Incorrect state without any other impact, which deserves a Low according to CodeHawks documentation.
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.