NFT Infrastructure
Tenzro Ledger provides native NFT support through the NFT Factory precompile at address 0x1006. NFTs on Tenzro follow the same cross-VM pointer model used for fungible tokens — a single NFT record exists in the unified registry, and each VM (EVM, SVM, DAML) exposes a thin pointer contract that reads and writes against the same underlying ownership data. This means an NFT minted on EVM is immediately visible and transferable from SVM or DAML without bridging.
Architecture Overview
The NftRegistry stores all NFT state in a DashMap backed by the CF_NFTS RocksDB column family. Each collection is identified by a deterministic CollectionId computed as SHA-256(creator_address || nonce). Individual tokens within a collection are keyed by (collection_id, token_id).
NFT Factory Precompile
The NFT Factory is a Tenzro-specific EVM precompile deployed at address 0x1006. It provides gas-efficient native operations without requiring Solidity contract deployment.
| Function Selector | Function | Description | Gas Cost |
|---|---|---|---|
0x01 | createCollection | Create a new NFT collection with name, symbol, max supply, and standard (721 or 1155) | 50,000 |
0x02 | mint | Mint a new token in a collection to a recipient address with metadata URI | 30,000 |
0x03 | mintBatch | Batch mint multiple tokens in a single transaction (ERC-1155) | 30,000 + 5,000/token |
0x04 | transfer | Transfer an NFT between addresses (same or cross-VM) | 25,000 |
0x05 | burn | Burn a token (only by owner or approved operator) | 20,000 |
0x06 | approve | Approve an operator for a specific token or entire collection | 15,000 |
0x07 | ownerOf | Query the owner of a specific token (read-only, no gas in static call) | 2,600 |
0x08 | tokenURI | Get the metadata URI for a token | 2,600 |
0x09 | collectionInfo | Get collection metadata (name, symbol, total supply, max supply, standard) | 2,600 |
Supported Standards
ERC-721 (Non-Fungible)
Each token is unique with a distinct token ID and single owner. Used for unique digital assets like art, identity credentials, domain names, and real-world asset certificates.
ERC-1155 (Multi-Token)
A single contract manages multiple token types, where each token ID can have a supply greater than one. Used for gaming items, event tickets, membership passes, and semi-fungible assets.
Cross-VM NFT Pointer Model
NFTs use the same Sei V2 pointer architecture as fungible tokens. When a collection is created through the NFT Factory, three pointer representations are automatically registered:
| VM | Interface | Behavior |
|---|---|---|
| EVM | ERC-721 / ERC-1155 pointer contract | Reads/writes directly to NftRegistry. Full Solidity compatibility. |
| SVM | Metaplex-compatible program | Maps Metaplex metadata account structure to NftRegistry entries. PDAs derived from collection mint + token ID. |
| DAML | CIP-NFT DAML template | Two-step transfer flow (create-offer, accept/reject) with party-to-address mapping. |
No bridge risk — Cross-VM NFT transfers do not lock and mint. When you transfer an NFT from EVM to SVM, the NftRegistry updates the owner address in place. The EVM pointer reflects the new owner, and the SVM pointer sees the same owner. There is never a wrapped or synthetic NFT.
Code Example
use tenzro_vm::nft::{NftRegistry, NftStandard, CollectionConfig, MintParams};
// Initialize the NFT registry with storage
let registry = NftRegistry::with_storage(storage.clone())?;
// Create a new ERC-721 collection
let collection = registry.create_collection(CollectionConfig {
name: "Tenzro Agents".to_string(),
symbol: "TAGENT".to_string(),
standard: NftStandard::Erc721,
max_supply: Some(10_000),
base_uri: "https://metadata.tenzro.network/agents/".to_string(),
royalty_bps: Some(250), // 2.5% royalties
creator: creator_address,
})?;
println!("Collection ID: {}", collection.id);
// Mint a token
let token = registry.mint(MintParams {
collection_id: collection.id,
token_id: 1,
recipient: recipient_address,
metadata_uri: Some("https://metadata.tenzro.network/agents/1.json".to_string()),
amount: 1, // Always 1 for ERC-721
})?;
// Transfer (works across VMs — same operation regardless of source VM)
registry.transfer(
collection.id,
1, // token_id
recipient_address, // from
new_owner_address, // to (can be EVM, SVM, or DAML address)
)?;
// Query ownership
let owner = registry.owner_of(collection.id, 1)?;
assert_eq!(owner, new_owner_address);
// ERC-1155 batch mint example
let collection_1155 = registry.create_collection(CollectionConfig {
name: "Tenzro Items".to_string(),
symbol: "TITEM".to_string(),
standard: NftStandard::Erc1155,
max_supply: None, // No global cap
base_uri: "https://metadata.tenzro.network/items/".to_string(),
royalty_bps: Some(500), // 5% royalties
creator: creator_address,
})?;
// Batch mint: 100 copies each of token IDs 1, 2, and 3
registry.mint_batch(
collection_1155.id,
vec![
MintParams { token_id: 1, amount: 100, ..Default::default() },
MintParams { token_id: 2, amount: 100, ..Default::default() },
MintParams { token_id: 3, amount: 100, ..Default::default() },
],
recipient_address,
)?;CLI Usage
# Create a new ERC-721 collection
tenzro nft create-collection --name "Tenzro Agents" --symbol TAGENT \
--standard erc721 --max-supply 10000 \
--base-uri "https://metadata.tenzro.network/agents/"
# Mint a token
tenzro nft mint --collection <collection-id> --token-id 1 \
--recipient 0xrecipient...abc \
--metadata-uri "https://metadata.tenzro.network/agents/1.json"
# Batch mint (ERC-1155)
tenzro nft mint-batch --collection <collection-id> \
--tokens "1:100,2:100,3:50" --recipient 0xrecipient...abc
# Transfer an NFT
tenzro nft transfer --collection <collection-id> --token-id 1 \
--to 0xnewowner...def
# Cross-VM transfer (EVM -> SVM)
tenzro nft transfer --collection <collection-id> --token-id 1 \
--to <solana-pubkey> --target-vm svm
# Query token info
tenzro nft info --collection <collection-id> --token-id 1
# List collections by creator
tenzro nft collections --creator 0xcreator...abc
# Get collection stats
tenzro nft collection-info --collection <collection-id>Comparison with Other Chains
| Feature | Tenzro | Sei V2 | Solana (Metaplex) | Unique Network |
|---|---|---|---|---|
| NFT storage | Native precompile + registry | CosmWasm + pointer | On-chain accounts | Native pallet |
| Cross-VM | EVM + SVM + DAML (pointer model) | EVM + CosmWasm (pointer) | SVM only | Substrate only |
| Standards | ERC-721, ERC-1155 | CW-721 | Metaplex Token Standard | Native NFT pallet |
| Batch operations | Native batch mint (ERC-1155) | Multi-message tx | Compressed NFTs (Bubblegum) | Bulk mint extrinsic |
| Mint cost | 30,000 gas (~0.00003 TNZO) | ~100,000 gas | ~0.01 SOL (compressed: ~0.00005 SOL) | ~0.1 UNQ |
| Enterprise support | DAML template (Canton) | No | No | Limited |
| Identity binding | TDIP DID linked to collections | No native identity | No native identity | No native identity |
Metadata Standard
Tenzro NFTs follow the standard JSON metadata schema used across the ecosystem. Metadata is stored off-chain at the URI specified during minting and can point to IPFS, Arweave, or any HTTP endpoint.
{
"name": "Tenzro Agent #1",
"description": "A verified AI agent on the Tenzro Network",
"image": "ipfs://Qm.../agent-1.png",
"external_url": "https://tenzro.network/agents/1",
"attributes": [
{ "trait_type": "Agent Type", "value": "Validator" },
{ "trait_type": "TEE Verified", "value": "true" },
{ "trait_type": "Reputation Score", "value": 95 },
{ "trait_type": "Capabilities", "value": "inference,settlement,verification" }
]
}