ERC-5521: Referable NFT
ERC-5521 lets NFTs reference each other in a directed graph. A new NFT's mint can declare which NFTs it "refers to" (citations, remixes, parent works); each NFT exposes both its forward references (what it cites) and its backward references (what cites it). Used for:
- Citation graphs — academic NFTs citing other research NFTs.
- Remix attribution — derivative NFTs pointing back to originals (eligible for royalty splits).
- Influencer / referral economies — NFTs minted via a referral link record the referrer.
- Wikipedia-style NFT-as-encyclopedia — articles citing other articles via NFT references.
Required Interface
solidity
interface IERC5521 {
event UpdateNode(uint256 indexed tokenId, address indexed owner,
uint256[] referring, uint256[] referred);
function safeMint(uint256 tokenId, uint256[] calldata referrers) external;
function setNode(uint256 tokenId, uint256[] calldata referrers) external;
function referringOf(address contract_, uint256 tokenId)
external view returns (uint256[] memory);
function referredOf(address contract_, uint256 tokenId)
external view returns (uint256[] memory);
function createdTimestampOf(address contract_, uint256 tokenId) external view returns (uint256);
}When a new NFT is minted with referrers, the contract automatically updates each referrer's "referred" list to include the new NFT. Forms a citation graph queryable from either direction.
Neo Equivalent: NEP-11 + Referring/Referred Edge Storage
csharp
public static void SafeMintWithReferrers(UInt160 to, ByteString tokenId, ByteString[] referrers)
{
if (!Runtime.CheckWitness(GetIssuer())) throw new Exception("NEP11:NotIssuer");
Mint(tokenId, new TokenState { Owner = to }); // NEP-11 base: Mint(tokenId, TokenState)
// Store outgoing edges (this token → referrers).
Storage.Put(Storage.CurrentContext, ReferringKey(tokenId), StdLib.Serialize(referrers));
Storage.Put(Storage.CurrentContext, CreatedKey(tokenId), Runtime.Time);
// Update reverse edges (referrers → this token).
for (var i = 0; i < referrers.Length; i++)
{
var existing = ReferredOf(referrers[i]);
var updated = new ByteString[existing.Length + 1];
for (var j = 0; j < existing.Length; j++) updated[j] = existing[j];
updated[existing.Length] = tokenId;
Storage.Put(Storage.CurrentContext, ReferredKey(referrers[i]), StdLib.Serialize(updated));
}
OnUpdateNode(tokenId, to, referrers, new ByteString[0]);
}| ERC-5521 (Ethereum) | Neo Equivalent | Notes |
|---|---|---|
safeMint(tokenId, referrers[]) | SafeMintWithReferrers(...) | Atomic mint + edge updates |
referringOf(contract, tokenId) | ReferringOf(tokenId) (single-contract) | Outgoing edges |
referredOf(contract, tokenId) | ReferredOf(tokenId) (single-contract) | Incoming edges |
createdTimestampOf(contract, tokenId) | CreatedTimestampOf(tokenId) | Timestamp at mint |
UpdateNode event | OnUpdateNode notification |
The contract parameter in the Solidity interface lets you reference NFTs across contracts; the simplest Neo port is single-contract (cross-contract referrals require a separate graph contract).
Composition
- ERC-2981 — royalty. Royalty splits propagate back through the citation graph (a remix pays royalty to its referenced originals).
- ERC-5375 — author + consent. Citations preserve attribution to the cited NFTs' authors.
- ERC-7007 — AI-generated content. AI-generated NFTs cite their prompt source NFTs.
- ERC-6150 — hierarchical NFTs. Hierarchies are parent-child trees; citations are arbitrary directed graphs.
Migration Notes
For citation/remix-economy NFT collections:
- The reverse-edge update at mint is the expensive part — for N referrers, that's N storage writes. Cap the referrer list size at mint to bound cost.
- Cross-contract references need a separate graph contract that maintains
(contractA, tokenA, contractB, tokenB)edges; the Neo port supports this via a registry pattern similar to ERC-6551. - Citation graphs can be queried off-chain for analytics; the on-chain storage is the source of truth.
