NFT Security Testing
Specialized techniques for assessing the security of Non-Fungible Token (NFT) systems
NFT Security Testing
Token Implementation
Assess the security of the NFT smart contract implementation.
- ERC-721/ERC-1155 compliance
- Minting and burning mechanisms
- Transfer and approval security
Metadata Security
Evaluate the security and integrity of NFT metadata.
- Storage mechanisms (IPFS, Arweave)
- Metadata immutability
- URI manipulation resistance
Marketplace Integration
Assess the security of NFT interactions with marketplaces.
- Royalty enforcement
- Listing and auction security
- Cross-platform vulnerabilities
Common NFT Vulnerabilities
Vulnerable Code
// Vulnerable NFT contract with centralized metadata
contract VulnerableNFT is ERC721 {
// Base URI points to a centralized server
string private _baseTokenURI = "https://api.example.com/metadata/";
constructor() ERC721("VulnerableNFT", "VNFT") {}
function mint(address to, uint256 tokenId) public {
_mint(to, tokenId);
}
function _baseURI() internal view override returns (string memory) {
return _baseTokenURI;
}
// Owner can change the base URI at any time
function setBaseURI(string memory newBaseURI) public onlyOwner {
_baseTokenURI = newBaseURI;
}
}Secure Implementation
// Improved NFT contract with decentralized metadata
contract SecureNFT is ERC721 {
// IPFS URI for decentralized storage
string private _baseTokenURI = "ipfs://QmXyZ...";
// Mapping to store if metadata is frozen for a token
mapping(uint256 => bool) private _frozenMetadata;
// Event for metadata changes
event MetadataUpdate(uint256 indexed tokenId);
event BatchMetadataUpdate(uint256 indexed fromTokenId, uint256 indexed toTokenId);
constructor() ERC721("SecureNFT", "SNFT") {}
function mint(address to, uint256 tokenId) public {
_mint(to, tokenId);
}
function _baseURI() internal view override returns (string memory) {
return _baseTokenURI;
}
// Owner can change the base URI, but emits events for transparency
function setBaseURI(string memory newBaseURI) public onlyOwner {
_baseTokenURI = newBaseURI;
emit BatchMetadataUpdate(1, totalSupply());
}
// Allow freezing metadata permanently
function freezeMetadata(uint256 tokenId) public onlyOwner {
require(_exists(tokenId), "Token does not exist");
require(!_frozenMetadata[tokenId], "Metadata already frozen");
_frozenMetadata[tokenId] = true;
}
// Check if metadata is frozen before allowing changes
function updateTokenMetadata(uint256 tokenId) public onlyOwner {
require(_exists(tokenId), "Token does not exist");
require(!_frozenMetadata[tokenId], "Metadata is frozen");
// Update logic here
emit MetadataUpdate(tokenId);
}
}NFT Testing Approaches
Key Steps
- Review token implementation for ERC-721/ERC-1155 compliance
- Analyze minting mechanisms and access controls
- Evaluate metadata storage and immutability
- Check royalty implementation (EIP-2981)
- Test approval and transfer mechanisms
- Assess batch operations for vulnerabilities
Recommended Tools
- Static analyzers (Slither, MythX)
- Symbolic execution tools (Mythril)
- Fuzzing frameworks (Echidna)
- NFT-specific linters
- Contract verification tools
Key Steps
- Analyze metadata storage mechanisms (centralized vs. decentralized)
- Test metadata retrieval and rendering
- Verify metadata immutability guarantees
- Check for metadata manipulation vulnerabilities
- Assess content addressing and integrity verification
- Test metadata update mechanisms if present
Recommended Tools
- IPFS pinning services
- Metadata validation tools
- Content addressing verifiers
- URI resolvers and validators
- Metadata monitoring services
Key Steps
- Analyze listing and sale mechanisms
- Test royalty enforcement across platforms
- Evaluate approval handling in marketplaces
- Check for front-running vulnerabilities in auctions
- Test escrow mechanisms and security
- Assess cross-platform compatibility
Recommended Tools
- Transaction simulation frameworks
- Marketplace API testing tools
- Front-running detection tools
- Cross-chain bridge monitors
- Gas optimization analyzers
NFT Security Checklist
Token Implementation
- Verify ERC-721/ERC-1155 standard compliance
- Check access controls for minting and administrative functions
- Verify proper handling of approvals and transfers
- Test batch operations for reentrancy and other vulnerabilities
Metadata Security
- Verify metadata is stored on decentralized storage (IPFS, Arweave)
- Check if metadata can be frozen or made immutable
- Verify content addressing and integrity verification
- Test metadata update mechanisms for security
Royalty Implementation
- Verify EIP-2981 royalty standard implementation
- Check for royalty bypass vulnerabilities in marketplace integrations
- Verify royalty recipient addresses are properly secured
- Test cross-platform royalty enforcement
Marketplace Integration
- Check for front-running vulnerabilities in auctions and listings
- Verify escrow mechanisms and security
- Test approval handling in marketplace interactions
- Assess cross-platform compatibility and security
NFT Security Case Study
Project Overview
The assessment targeted a high-value NFT collection with 10,000 unique tokens and a custom marketplace. The project used ERC-721 for the tokens, IPFS for metadata storage, and implemented a custom royalty mechanism for secondary sales across multiple platforms.
Testing Approach
The assessment combined smart contract auditing, metadata integrity verification, and marketplace integration testing. It included both automated and manual testing, with a focus on royalty enforcement and metadata immutability.
Key Findings
Metadata Centralization Risk
While the project used IPFS for storage, the IPFS hashes were not directly stored on-chain. Instead, a base URI pointing to a centralized API was used, which could be changed by the contract owner at any time, potentially allowing for metadata manipulation.
Royalty Bypass Vulnerability
The custom royalty implementation did not follow EIP-2981, making it incompatible with some marketplaces. Additionally, the marketplace contract had a vulnerability that allowed bypassing royalty payments through a specific sequence of transactions.
Approval Handling Issue
The marketplace contract did not properly clear approvals after transfers in certain scenarios, potentially allowing previously approved operators to transfer tokens after they were sold to new owners.
Remediation Outcomes
- Implemented on-chain storage of IPFS content identifiers (CIDs) with a metadata freezing mechanism
- Added EIP-2981 support while maintaining backward compatibility with the custom royalty system
- Fixed approval handling in the marketplace contract and added explicit approval clearing
- Implemented a royalty registry for cross-platform enforcement and verification