The RAACNFT contract allows for the multiple minting of the same tokenId that allows an attacker to mint the same NFT tokenId multiple times.
As a result, the LendingPool contract, which utilizes these NFTs as collateral, is susceptible to two attacks:
Collateral Exploitation: An attacker can deposit duplicate instances of an NFT as collateral to extract more funds.
DoS: If a legitimate user deposits a specific tokenId into the LendingPool, an attacker can re-mint the same tokenId, effectively causing a state conflict. This results in the LendingPool losing its legitimate ownership of the token, which will later cause withdrawals of that token collateral to fail.
The mint function in the RAACNFT contract does not check if a given _tokenId has already been minted. This allows an attacker to call the mint function multiple times with the same _tokenId, resulting in multiple NFTs with the same ID being minted to the same or different addresses.
The LendingPool contract accepts NFT deposits and verifies ownership by calling raacNFT.ownerOf(tokenId). Because an attacker can mint an NFT multiple times under different addresses, they can create multiple “legitimate” appearances of the same NFT. Each duplicate can be deposited as collateral. The LendingPool logic subsequently allows borrowing or depositing reserve assets (such as crvUSD) against each instance, even though they all represent the same underlying asset.
Step 1: The attacker calls the mint function for a specific tokenId (e.g., tokenId 42) with _amount equal to or greater than the price.
Step 2: Address A deposits the NFT (tokenId 42) into the LendingPool contract by calling depositNFT(42).
Step 3: The attacker then invokes the mint function again for the same tokenId 42 from a different controlled address (e.g., Address B), passing the required funds.
Step 4: Address B deposits the NFT (tokenId 42) into the LendingPool using depositNFT(42).
Step 5: Using the inflated collateral value, the attacker borrows or otherwise withdraws reserve assets (crvUSD) multiple times—once for each deposited duplicate NFT.
By re-minting the NFT tokenId multiple times and depositing each version into the LendingPool, the attacker is able to withdraw more assets than what would be collateralized by a single NFT in the LendingPool.
Step 1: A legitimate user deposits NFT tokenId 42 into the LendingPool, transferring it as collateral.
Step 2: An attacker re-mints tokenId 42 and transfers ownership away from the LendingPool (using the duplicate contract logic).
Subsequent withdrawal attempts by the legitimate user will fail, as the system's ownership tracking for tokenId 42 is compromised.
The LendingPool treats each instance of the re-minted NFT as a unique, valid collateral. This results in an artificially inflated total collateral value.
An attacker can repeatedly extract reserve assets (e.g., crvUSD) using the same NFT as collateral, leading to liquidation events or balance imbalances within the protocol.
If a legitimate user deposits an NFT (with a specific tokenId) to secure a loan or maintain collateral, an attacker can DOS that tokenId by re-minting it. By doing so, the LendingPool’s record of collateral ownership is invalidated. Consequently, when the legitimate user attempts to withdraw their collateral, the operation fails because the contract no longer holds the rightful NFT.
Manual review
Modify the mint function in the RAACNFT contract to check if the _tokenId already exists before minting a new NFT.
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.