Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: high
Invalid

RAACNFT.sol Allows Unauthorized NFT Transfers

Summary

The RAACNFT.sol contract does not check approval status before allowing transfers. This allows attackers to transfer NFTs without owner permission if they can call the contract directly.

Risk: Attackers can steal RAACNFTs, bypass collateralization requirements, and manipulate governance.

Vulnerability Details

  1. The transferFrom Function Lacks Approval Checks

RAACNFT.sol (Vulnerable Code)

function transferFrom(address from, address to, uint256 tokenId) public override {
_transfer(from, to, tokenId);
}

What’s wrong?

  • No require(isApprovedOrOwner(msg.sender, tokenId)) check.

  • Any caller can force a transfer without being the owner or having approval.

  • This violates ERC-721 security principles.

2. Attack Scenario: Stealing RAACNFTs

  1. Attacker calls transferFrom() from a contract they control.

  2. The function doesn’t check ownership, so the NFT is transferred to the attacker.

  3. If the NFT was being used as collateral in LendingPool.sol, the borrower is liquidated unfairly.

  4. The attacker sells the stolen NFT on OpenSea or other marketplaces.

Impact

NFT Theft – Attackers can steal RAACNFTs from unsuspecting users.
Bypassing Lending Requirements – Users can move collateralized NFTs and avoid liquidation.
Manipulating Governance – If NFTs grant voting power, attackers can steal votes and control governance.

Tools Used

  • Manual Review – Identified missing approval checks.

  • Slither – Detected missing ERC721 security enforcement.

Recommendations

1. Enforce Approval Checks

function transferFrom(address from, address to, uint256 tokenId) public override {
require(_isApprovedOrOwner(msg.sender, tokenId), "Not authorized to transfer");
_transfer(from, to, tokenId);
}

2. Implement Reentrancy Guards on Transfers
3. Use OpenZeppelin’s Secure ERC721 Implementation

PoC Exploit Script

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../contracts/tokens/RAACNFT.sol";
contract NFTStealer {
RAACNFT public target;
address public attacker;
constructor(address _target) {
target = RAACNFT(_target);
attacker = msg.sender;
}
function stealNFT(uint256 tokenId) external {
target.transferFrom(address(this), attacker, tokenId); // No approval required
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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

Give us feedback!