Reentrancy in mintNft() allows unexpected double execution before mint state is updated
IMPACT: LOW
LIKELIHOOD: MEDIUM
The mintNft() function performs an external call to usdc.transferFrom(msg.sender, address(this), lockAmount) before updating critical internal state such as tokenIdCounter and collateralForMinting[tokenIdCounter].
A malicious payment token can reenter mintNft() and trigger multiple executions before the original call updates internal accounting.
This may lead to:
unexpected multiple mints in a single transaction
inconsistent state transitions around tokenIdCounter
unsafe reliance on external token behavior
broader cross-function reentrancy risk if other protocol logic depends on partially updated mint state
Although the demonstrated PoC required paying the locked amount twice, the protocol still exposes a real reentrancy surface and relies on unsafe ordering of external interactions.
A malicious ERC20 was used in place of USDC. During transferFrom(), it called back into the whitelisted attacker contract, which reentered mintNft() before tokenIdCounter was incremented in the original execution.
Observed result from the test:
the initial call to mintNft() invoked transferFrom()
transferFrom() triggered a reentrant call to mintNft()
mintNft() executed twice in the same transaction
totalMinted() became 2
PoC results:
This confirms that mintNft() is reentrable through the external token call.
Follow the Checks-Effects-Interactions pattern by updating internal mint state before performing external calls.
Also consider adding nonReentrant protection and using SafeERC20.
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.