Skip to main content

HCS-7: Smart Hashinals - A Micro-DSL for Deterministic Topic Selection

Status: Draft

Table of Contents


Authors


Abstract

HCS-7 is a sub-standard of HCS-6 that introduces a powerful mechanism for creating dynamic NFTs (Hashinals) whose metadata automatically updates based on smart contract state. By combining on-chain data with WebAssembly (WASM) processing, HCS-7 enables trustless, programmatic, and verifiable metadata selection without requiring additional transactions for each update.

The standard defines a micro domain-specific language (DSL) for deterministic topic selection, allowing smart contracts to drive the appearance and behavior of NFTs. This enables rich, interactive experiences such as evolving artwork, price-reactive visuals, and state-dependent functionality.


Motivation

HCS-6 introduced dynamic metadata updates for Hashinals through sequence number registration. However, many use cases require switching metadata based on complex on-chain conditions:

  • Number of minted NFTs in a collection
  • Uniswap V3 pool price thresholds
  • Token balance requirements
  • Time-weighted average prices
  • Complex mathematical calculations

These scenarios would traditionally require submitting many messages and maintaining off-chain state. HCS-7 solves this through trustless, programmatic, verifiable execution by combining on-chain state with WASM processing.


Architecture Overview

HCS-7 creates a framework where NFT metadata is automatically selected based on smart contract state, without requiring additional transactions for updates. The architecture leverages HCS topics, smart contracts, and WASM for deterministic processing.

Key Components

ComponentDescriptionRole in HCS-7
HCS-7 Registry TopicCentral topic storing configuration and registrationsContains EVM configs, WASM configs, and metadata registrations
WASM ModuleWebAssembly code for processing state dataEvaluates contract state and returns appropriate Topic ID
Smart ContractOn-chain source of state dataProvides real-time data that determines metadata selection
HCS-1 Metadata TopicsTopics containing actual metadata contentStores the variant content that will be displayed
HCS-7 ClientSoftware implementing the standardOrchestrates the flow between components

Processing Flow

The HCS-7 system follows a deterministic processing flow:

This architecture allows for deterministic, trustless selection of metadata based on on-chain conditions, without requiring additional transactions for metadata updates.


Common Use Cases

HCS-7 enables a variety of dynamic NFT experiences through its flexible architecture.

Price-Reactive NFTs

NFTs that change appearance based on asset prices from oracles:

Mint Progress NFTs

NFTs that evolve as collection minting progresses:

Time-Based NFTs

NFTs that update based on time of day or other temporal factors:

Other popular use cases include:

  • Balance-Dependent NFTs: Artwork that changes based on user's token balance
  • Game State NFTs: NFTs that reflect in-game achievements or status

Specification

Topic System

Topic Types

HCS-7 uses the following topic types to manage dynamic metadata selection:

Topic TypeDescriptionKey Configuration
HCS-7 Registry TopicCentral configuration and routing topicNo admin key (as per HCS-2)
HCS-1 Metadata TopicsTopics containing variant metadataHCS-1 standard for content storage
WASM Module TopicTopic containing the WASM codeHCS-1 format for binary storage

Topic Memo Formats

Each topic type uses a specific memo format in its HCS topic creation transaction to indicate its purpose and configuration. For a comprehensive overview of topic memos across all HCS standards, see the Topic Memos definition.

HCS-7 Registry Topic Memo Format

The HCS-7 Registry Topic serves as the central configuration hub for dynamic metadata selection:

hcs-7:indexed:{ttl}
FieldDescriptionExample Value
hcs-7Standard identifierhcs-7
indexedLiteral "indexed" indicating all messages should be read and indexedindexed
ttlTime-to-live in seconds for caching3600

Metadata Format

HCS-7 metadata follows the HCS-5 standard with protocol number 7:

Format TypeFormat StructureExample
HRL Formathcs://7/{topicId}hcs://7/0.0.1234567
RequirementsValid HCS-7 Registry Topic IDMust exist on network

Message Types and Fields

HCS-7 defines three primary message types:

1. EVM Configuration

EVM Configuration messages define smart contract interactions to retrieve state:

{
"p": "hcs-7",
"op": "register-config",
"t": "evm",
"c": {
"contractAddress": "0x1d67aaf7f7e8d806bbeba24c4dea24808e1158b8",
"abi": {
"inputs": [],
"name": "minted",
"outputs": [
{
"name": "",
"type": "uint64"
}
],
"stateMutability": "view",
"type": "function"
}
},
"m": "LaunchPage Test Mint"
}
FieldTypeDescriptionRequired
pstringProtocol identifier (must be "hcs-7")Yes
opstringOperation type (must be "register-config")Yes
tstringConfiguration type (must be "evm")Yes
c.contractAddressstringEthereum contract addressYes
c.abiobjectContract ABI with function detailsYes
c.abi.namestringMethod name to callYes
c.abi.inputsarrayArray of input parametersYes
c.abi.outputsarrayArray of return typesYes
c.abi.stateMutabilitystringMust be "view" or "pure"Yes
c.abi.typestringMust be "function"Yes
mstringMessage descriptionNo

2. WASM Configuration

WASM Configuration messages define the processing logic:

{
"p": "hcs-7",
"op": "register-config",
"t": "wasm",
"c": {
"wasmTopicId": "0.0.5263817",
"inputType": {
"stateData": {
"minted": "number",
"tokensRemaining": "number"
}
},
"outputType": {
"type": "string",
"format": "topic-id"
}
},
"m": "minted-even-odd-router"
}
FieldTypeDescriptionRequired
pstringProtocol identifier (must be "hcs-7")Yes
opstringOperation type (must be "register-config")Yes
tstringConfiguration type (must be "wasm")Yes
c.wasmTopicIdstringTopic ID containing WASM moduleYes
c.inputTypeobjectJSON Schema for input dataYes
c.inputType.stateDataobjectContract return value typesYes
c.outputTypeobjectOutput specificationYes
c.outputType.typestringOutput data type (must be "string")Yes
c.outputType.formatstringOutput format (must be "topic-id")Yes
mstringMessage descriptionNo

Required WASM Functions:

The WASM module must implement two functions:

  1. process_state(state_json: &str, messages_json: &str) -> String

    • Processes the state data and messages to determine the output topic ID
    • state_json: JSON string containing the state data from EVM calls
    • messages_json: JSON string containing the array of registered messages
    • Returns: A valid topic ID as a string
  2. get_params() -> String

    • Returns a JSON string describing the required parameters and their types
    • Example return value:
      {
      "minted": "number",
      "tokensRemaining": "number"
      }

Example WASM Implementation:

#[wasm_bindgen]
pub fn process_state(state_json: &str, messages_json: &str) -> String {
// Parse JSON inputs
let state: Value = match serde_json::from_str(state_json) {
Ok(data) => data,
Err(_) => return String::new(),
};

let messages: Vec<Value> = match serde_json::from_str(messages_json) {
Ok(data) => data,
Err(_) => return String::new(),
};

// Get minted from state, return empty if invalid
let minted = match parse_minted(&state) {
Some(p) => p,
None => return String::new()
};

// Process data - check if minted is even/odd
let is_even = minted % 2u32 == BigUint::from(0u32);

let topic_id = if is_even {
// Find first matching even registration
messages.iter()
.find(|msg| {
msg.get("t_id").is_some() &&
msg.get("d")
.and_then(|d| d.get("tags"))
.and_then(|tags| tags.as_array())
.map(|tags| tags.iter().any(|t| t.as_str() == Some("even")))
.unwrap_or(false)
})
.and_then(|msg| msg.get("t_id").and_then(|id| id.as_str()))
.map(|s| s.to_string())
} else {
// Find first matching odd registration
messages.iter()
.find(|msg| {
msg.get("t_id").is_some() &&
msg.get("d")
.and_then(|d| d.get("tags"))
.and_then(|tags| tags.as_array())
.map(|tags| tags.iter().any(|t| t.as_str() == Some("odd")))
.unwrap_or(false)
})
.and_then(|msg| msg.get("t_id").and_then(|id| id.as_str()))
.map(|s| s.to_string())
};

// Return topic ID or empty string if none found
topic_id.unwrap_or_default()
}

3. Metadata Registration

Metadata Registration messages link HCS-1 topics to selection tags:

{
"p": "hcs-7",
"op": "register",
"t_id": "0.0.3717738",
"m": "blue",
"d": {
"weight": 1,
"tags": ["odd"]
}
}
FieldTypeDescriptionRequired
pstringProtocol identifier (must be "hcs-7")Yes
opstringOperation type (must be "register")Yes
t_idstringHCS-1 topic ID containing metadataYes
mstringMessage descriptionNo
dobjectAdditional routing dataYes
d.weightnumberPriority if multiple matchesYes
d.tagsarrayRouting identifiersYes

Error Handling

HCS-7 defines a robust error handling strategy to manage failures at different stages:

Error TypeHandling StrategyFallback
Smart Contract ErrorsSkip state updateUse cached state
Network IssuesRetry with backoffUse cached state
Contract Not FoundFail validationReturn error
WASM Invalid InputReturn emptyDefault topic
WASM TimeoutFail gracefullyDefault topic
No Matching TagReturn defaultEmpty string
Topic Not FoundFail validationReturn error
Invalid FormatSkip registrationContinue with valid data
Network IssuesUse cacheRetry with backoff

Implementation Bridge Classes

HCS-7 defines a set of classes to implement the standard:


Implementation Workflow

Step 1: Setup Phase

StepActionDescription
1Create HCS-7 TopicCreate an indexed topic with memo format hcs-7:indexed:{ttl}
2Deploy WASM ModuleDeploy WASM module to a separate topic for processing state data
3Configure EVM & WASMSubmit EVM and WASM configuration messages
4Create Metadata TopicsCreate HCS-1 topics for each metadata variant (e.g., odd/even)
5Register TopicsRegister each HCS-1 topic with appropriate tags and weights
6Validate ConfigurationEnsure all configurations are properly submitted and indexed

Step 2: Processing Requirements

The HCS-7 processing model has specific requirements to ensure proper operation:

RequirementDescriptionNotes
Smart Contract CallsMust be view/pure functionsNo state mutations allowed
WASM ExecutionLimited to 50msPrevents excessive resource usage
Topic ID ValidationMust return valid IDEmpty for no match
Error HandlingMust implement fallbacksSee Error Handling section

Step 3: Extended WASM Capabilities

WASM modules can implement complex processing logic:

// Combining multiple state values
let minted = parse_number(&state, "minted").unwrap_or_default();
let tokens_remaining = parse_number(&state, "tokensRemaining").unwrap_or_default();

// Calculate combined value for decision making
let combined_value = minted.clone() * tokens_remaining;
let is_even = combined_value % 2u32 == BigUint::from(0u32);

WASM processing allows for:

  • Mathematical operations on state data
  • Complex conditional logic
  • Multi-factor decision making
  • State variable combination

HCS-7 supports integration with Chainlink oracles using this configuration:

{
"p": "hcs-7",
"op": "register-config",
"t": "evm",
"c": {
"contractAddress": "0x59bC155EB6c6C415fE43255aF66EcF0523c92B4a",
"abi": {
"inputs": [],
"name": "latestRoundData",
"outputs": [
{
"name": "roundId",
"type": "uint80"
},
{
"name": "answer",
"type": "int256"
},
{
"name": "startedAt",
"type": "uint256"
},
{
"name": "updatedAt",
"type": "uint256"
},
{
"name": "answeredInRound",
"type": "uint80"
}
],
"stateMutability": "view",
"type": "function"
}
},
"m": "Chainlink HBAR Price Feed"
}

This enables price-reactive NFTs that can change based on real-world asset prices.


Limitations

Smart Contract Limitations

LimitationDescriptionMitigation
View/Pure OnlyMust be public view/pure functionsUse read-only methods for state
No State MutationCannot change stateDesign for read-only operations
VerificationMust be verified and accessibleDeploy contracts through verified channels
Gas CostsGas costs affect performanceOptimize contracts for minimal gas usage

WASM Limitations

LimitationDescriptionMitigation
Processing Time50ms processing limitOptimize WASM code for performance
Error HandlingMust handle all error casesImplement comprehensive error checks
Topic SelectionLimited to topic ID selectionDesign within the constraints
MemoryMemory constraintsOptimize memory usage

Infrastructure Requirements

RequirementDescriptionImplementation
Cache ManagementCache state and resultsImplement TTL-based caching
Network ReliabilityMaintain network connectivityUse retry logic and fallbacks
State ConsistencyEnsure state consistencyImplement validation checks
Error RecoveryPlan for failuresDesign failure recovery paths

Reference Implementation

A reference implementation toolkit is available at Standards SDK with the following components:

ComponentDescriptionPurpose
EVMBridgeClass for reading smart contract stateRetrieves on-chain data
WasmBridgeClass for loading and executing WASM modulesProcesses state data
CreateTopicUtility for creating HCS-7 topicsSets up required topics
Example WASM ModulesSample implementations for various use casesProvides reference code

Conclusion

HCS-7 extends HCS-6 by enabling smart contract driven metadata selection through WASM processing. This creates a powerful system for dynamic NFTs while maintaining decentralization and trustlessness. The standard enables a wide range of reactive NFT applications from price-reactive visuals to complex state-dependent metadata.