Saltar al contenido principal

On-Chain Key-Value Metadata Storage for Compact Descriptors

Status: Draft

On-Chain Key-Value Metadata Storage for Compact Descriptors

Abstract

Smart contracts often rely on off-chain JSON documents (e.g. for NFTs) or fixed functions (e.g. name(), symbol()) for metadata. This standard introduces a flexible on-chain key-value structure for metadata that must be durable, auditable, and optionally updateable. Use cases include document fingerprints, compliance references, and structured legal proofs. The KV structure works in parallel with existing standards to enhance trust, transparency, and auditability in tokenized systems.

Motivation

This CIP defines a standardized smart contract interface for storing compact key-value (KV) metadata on-chain. It supports sealed (immutable) and unsealed (updatable) entries. It is particularly useful for Real World Asset (RWA) tokenization and complements existing practices like CBC-20 metadata and off-chain NFT metadata URLs.

Specification

Interface

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IOnChainKV {
function getValue(string calldata key) external view returns (string memory value);
function hasKey(string calldata key) external view returns (bool exists);
function isSealed(string calldata key) external view returns (bool sealed);
function listKeys() external view returns (string[] memory keys);
function getByIndex(uint256 index) external view returns (string memory key, string memory value);
function count() external view returns (uint256 total);
function setValue(string calldata key, string calldata value) external;
function sealKey(string calldata key) external;
}

Reference Implementation

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract OnChainKV is IOnChainKV {
struct Entry {
string value;
bool sealed;
bool exists;
}

mapping(string => Entry) private _entries;
string[] private _keys;

function setValue(string calldata key, string calldata value) external override {
Entry storage entry = _entries[key];
require(!entry.sealed, "Key is sealed and cannot be updated");

if (!entry.exists) {
_keys.push(key);
entry.exists = true;
}

entry.value = value;
}

function sealKey(string calldata key) external override {
require(_entries[key].exists, "Key not found");
_entries[key].sealed = true;
}

function getValue(string calldata key) external view override returns (string memory) {
require(_entries[key].exists, "Key not found");
return _entries[key].value;
}

function hasKey(string calldata key) external view override returns (bool) {
return _entries[key].exists;
}

function isSealed(string calldata key) external view override returns (bool) {
require(_entries[key].exists, "Key not found");
return _entries[key].sealed;
}

function listKeys() external view override returns (string[] memory) {
return _keys;
}

function getByIndex(uint256 index) external view override returns (string memory, string memory) {
require(index < _keys.length, "Index out of bounds");
string memory key = _keys[index];
return (key, _entries[key].value);
}

function count() external view override returns (uint256) {
return _keys.length;
}
}

Real World Asset Use Case

RWA tokens frequently require referencing off-chain legal and regulatory artifacts, such as:

  • Investment prospectuses
  • Legal disclaimers
  • KYC provider certifications
  • Title deed hashes
  • Security identifiers (ISIN, CUSIP)

By using on-chain KV:

  • Developers can store compact fingerprints or signed digests.
  • Legal auditors can verify presence and integrity on-chain.
  • Updates can be allowed when needed—but sealed when finalized.

RWA Ticker

The RWA Ticker should be chosen regards to the commodities that will be tokenized:

  • RWAZCH5 - where RWA is the ticker prefix, ZC is the commodity (Corn), H is month (March), 5 is year (2025).
  • RWASWSG5 - where RWA is the ticker prefix, SWS is the commodity (Type of Sugar), G is the month (February), 5 is year (2025).

Avoid using the tickers too long and keep brief and descriptive.

Month Code Table

The following table lists each month and its corresponding month code as referenced in CIP-150:

MonthMonth Code
JanuaryF
FebruaryG
MarchH
AprilJ
MayK
JuneM
JulyN
AugustQ
SeptemberU
OctoberV
NovemberX
DecemberZ

Comparison Summary

MethodScopeLocationMutableStandard Use
name() / symbol()GlobalOn-chainNoIdentification (ERC-20/4626)
tokenURI()Per-tokenOff-chainYesNFT metadata (ERC-721/1155)
KV (this CIP)Key-definedOn-chainOptionalContextual metadata, docs, hashes

Rationale

The on-chain key-value metadata storage approach addresses the need for flexible, auditable, and optionally updateable metadata in smart contracts. This standard provides a middle ground between immutable on-chain data and mutable off-chain references, particularly valuable for real-world asset tokenization where legal and regulatory compliance requires both transparency and the ability to update information when necessary.

Backward Compatibility

This standard is designed to work alongside existing metadata approaches like ERC-20 name/symbol functions and ERC-721 tokenURI, providing additional flexibility without breaking existing implementations.

Security Considerations

  • Mutable entries must be explicitly managed and sealed once final.
  • Gas efficiency must be considered for large-scale use.
  • Contracts should restrict setValue() and sealKey() to authorized parties.
  • Consider using versioned keys (e.g. PROSPECTUS_V1, PROSPECTUS_V2) to retain history.

Conclusion

The On-Chain Key-Value Metadata Storage standard provides a flexible and secure approach to managing metadata in smart contracts. Its adoption can enhance transparency, auditability, and compliance in tokenized systems, particularly for real-world assets.

References

  • Deployment Script: DeployOnChainKV.s.sol Solidity script for deploying the OnChainKV contract using the Foxar deployment framework. Automates and documents the deployment process.
  • Test Suite: OnChainKV.t.sol Solidity test file containing unit tests for OnChainKV, verifying correct behavior for setting, sealing, and retrieving key-value pairs.
  • Contract ABI: IOnChainKV.abi.json Application Binary Interface (ABI) for the IOnChainKV interface, defining contract methods and events for integration with external tools.

Copyright and related rights waived via CC0.

Tags:CBC