DittoETH

Ditto
DeFiFoundryOracle
55,000 USDC
View results
Submission Details
Severity: high
Invalid

ERC721 Reentrancy

Summary

ERC721 Reentrancy

Vulnerability Details

The ERC721 Reentrancy vulnerability refers to the potential for a reentrancy attack in the mintNFT function. This function is marked as nonReentrant, which is intended to prevent reentrancy attacks. However, the function calls an external contract onlyValidShortRecord before it updates the state s.nftMapping[s.tokenIdCounter] and short.tokenId.

Impact

In a reentrancy attack, a malicious contract could be called as the onlyValidShortRecord, and it could in turn call mintNFT again before the first call to mintNFT has finished. This could result in the same token being minted multiple times, potentially leading to unexpected behavior or a breach of the contract's intended logic.

Tools Used

Manual

Recommendations

To resolve the ERC721 Reentrancy issue, you should follow the Checks-Effects-Interactions pattern in your smart contract. This pattern recommends that you should make any state changes in your contract before calling external contracts.

Here's how you can modify the mintNFT function:

function mintNFT(address asset, uint8 shortRecordId)
external
isNotFrozen(asset)
nonReentrant
onlyValidShortRecord(asset, msg.sender, shortRecordId)
{
if (shortRecordId == Constants.SHORT_MAX_ID) {
revert Errors.CannotMintLastShortRecord();
}
STypes.ShortRecord storage short =
s.shortRecords[asset][msg.sender][shortRecordId];
if (short.tokenId != 0) revert Errors.AlreadyMinted();
// State changes before external call
uint256 newTokenId = s.tokenIdCounter;
s.nftMapping[newTokenId] = STypes.NFT({
owner: msg.sender,
assetId: s.asset[asset].assetId,
shortRecordId: shortRecordId
});
short.tokenId = newTokenId;
s.tokenIdCounter += 1;
// External call after state changes
// ... (if any)
}

This way, even if a reentrancy attack is attempted, the state changes have already been made, and the attack will not result in any unexpected behavior.

Additionally, you should also consider using the OpenZeppelin's ReentrancyGuard contract, which provides a modifier to protect against reentrancy attacks.

Updates

Lead Judging Commences

0xnevi Lead Judge
over 1 year ago
0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Vague generalities

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.