During a battle, both the defender's and challenger's rapper NFTs are transferred to the module address (@battle_addr
) using object::transfer
. However, after determining the winner, only the stats are updated via one_shot::transfer_record_only
—there are no corresponding object::transfer
calls to send the NFTs back to the winner. The tokens remain owned by the module address indefinitely.
Likelihood:
This bug triggers on every battle completion, making it inevitable in normal usage. No special conditions or attacker intervention are required beyond participating in gameplay.
Impact:
Players lose permanent control of their NFTs after any battle or staging action. The winner receives the CRED coin prize pool but not the rapper tokens, rendering the NFTs unusable and "bricked."
In the go_on_stage_or_battle
function, add transfer_raw(owner: &signer, object: address, to: address)
calls post-battle to send both NFTs to the winner. This allows transfer of NFT object using address only.
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.
The contest is complete and the rewards are being distributed.