For each reSDL NFT, there is an approval which can be set by calling approve(address _to, uint256 _lockId)
to allow another user _to
to transfer _lockId
on behalf of its owner. However, the logic in the RESDLTokenBridge
contract does not clear this approval when the lockId is transferred to another chain. This means that irrespective of who the owner of that lockId is in the future (let's say it was transferred to a new user), if it is ever transferred back to the originating chain, the approved address will be able to perform a transferFrom
call to transfer that lockId to themselves, effectively stealing it.
Consider the following attack (here we are assuming that we are starting on the primary chain):
User A owns a reSDL NFT and calls SDLPoolPrimary:approve
to approve an address which they also control for this reSDL's lockId.
User A calls RESDLTokenBridge:transferRESDL
to transfer their reSDL NFT from chain A to chain B. This triggers SDLPoolCCIPControllerPrimary:handleOutgoingRESDL
-> SDLPoolPrimary:handleOutgoingRESDL
. Consider what happens in the SDLPoolPrimary:handleOutgoingRESDL
call:
Although the ownership data for the _lockId
is deleted, the tokenApprovals[_lockId]
is never touched, meaning the existing approval will remain for this _lockId
.
We assume that User A's CCIP message is successful, and on chain B, user A will now have ownership of the reSDL NFT. On chain B we then assume that user A transfers this reSDL NFT to user B in exchange for funds.
User B decides to transfer this reSDL NFT back to chain A from chain B. This process is very similar to what I described earlier, and ultimately this will trigger SDLPoolPrimary:handleIncomingRESDL
on chain A which sets user B as the owner of this reSDL's _lockId
on chain A. This function is defined as follows:
Again, there is no logic which clears the existing tokenApprovals[_lockId]
.
Finally, user A, through their secondary address is able to call transferFrom
to transfer the _lockId
from user B to an address of their choosing, effectively stealing the reSDL.
A reSDL NFT can be stolen when transferred to another chain & back.
Manual review
The tokenApprovals
mapping for a given _lockId
should be deleted prior to the reSDL NFT being transferred to another chain in the RESDLTokenBridge
contract.
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.