Tokens withdrawn from the bridge are not cleared from the escrow map in Bridge::withdraw_auto_from_l1
.
An escrow map is defined as a map between collection's token_id
and its depositor:
Bridge::escrow_deposit_tokens(...)
is called to deposit tokens into the escrow, which updates the current owner of the token_id
in the escrow map:
Bridge::withdraw_auto_from_l1(...)
, decorated with [L1_handler]
which are special functions that can only be executed by a L1HandlerTransaction
, processes message from L1 to withdraw tokens. It read the escrow map to check if a token_id
is in escrow and if so, it transfers the token from the contract to its owner, otherwise it mints the token for that owner:
The problem is that the function never clear the escrow map after withdrawal, which means that even after a token has been withdrawn, the escrow map will still show the token_id
as being in escrow. Take the following scenario:
Alice initially bridges token_x
from L1 to L2. Since is_escrowed
is initially false
, token_x
is minted from the bridge to Alice.
Alice bridges token_x
back to L1 by calling Bridge::deposit_tokens(...)
, which transfers token_x
from Alice to escrow. is_escrowed
is now true
on L2. Alice doesn't own the token now on L2.
Alice bridges the token back to L2 and since is_escrowed
is true
on L2, this piece of code will be triggered:
As we see, token_id
is transferred from the escrow to Alice but is_escrowed
remains true
. Aside from this state inconsistency, this problem is worse if token_id
was burned from the escrow (in use_deposit_burn_auto
mode) because the function will try to transfer the non-existing token from the escrow instead of minting it which will always revert because well, token_id
does not exist, permanently removing that token_id
from circulation.
State inconsistency: is_escrowed
is true
when the token is not in the escrow.
Permanent removing oftoken_id
from circulation in use_deposit_burn_auto
mode.
Manual review.
Impact: Incorrect state without any other impact, which deserves a Low according to CodeHawks documentation.
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.