Skip to content

Document Vault Module

The vault module provides a secure, immutable, and auditable system for linking RWA tokens with their legal documents stored on Walrus. It maintains complete version history and supports auditor endorsements.

Overview

The document vault stores metadata about documents (not the documents themselves). Documents are stored encrypted on Walrus, while the vault stores:

  • Walrus blob IDs
  • Document hashes for integrity verification
  • Version history
  • Auditor endorsements
  • Access key commitments

Key Structures

DocumentRegistry

Central shared registry for all documents:

public struct DocumentRegistry has key {
    id: UID,
    records: Table<address, DocumentRecord>,  // Maps token address to record
    total_documents: u64,
}

DocumentRecord

Complete record for a single RWA token's documentation:

public struct DocumentRecord has store {
    token_address: address,
    issuer: address,                          // Original issuer (only can append versions)
    versions: vector<DocumentVersion>,        // Immutable version history
    auditors: vector<address>,                // List of endorsing auditors
    created_at: u64,
    updated_at: u64,
}

DocumentVersion

Individual document version:

public struct DocumentVersion has store {
    version_index: u64,                       // 0-indexed version number
    blob_id: String,                         // Walrus blob ID
    blob_object_id: ID,                      // Walrus object ID
    file_hash: vector<u8>,                   // SHA-256 hash of file
    description: String,                     // Human-readable description
    access_key: vector<u8>,                  // Encrypted access key
    metadata: vector<u8>,                    // JSON metadata
    created_at: u64,                         // Version creation timestamp
    created_by: address,                     // Address that created this version
}

Main Functions

register_document()

Register initial document for an RWA token:

public entry fun register_document(
    registry: &mut DocumentRegistry,
    token_address: address,
    blob_id: String,
    blob_object_id: ID,
    file_hash: vector<u8>,
    description: String,
    access_key: vector<u8>,
    metadata: vector<u8>,
    ctx: &mut TxContext
)

Parameters:

  • registry: Mutable reference to DocumentRegistry
  • token_address: Address of RWA token
  • blob_id: Walrus blob ID
  • blob_object_id: Walrus object ID
  • file_hash: SHA-256 hash of file (32 bytes)
  • description: Human-readable description
  • access_key: Encrypted access key
  • metadata: JSON metadata
  • ctx: Transaction context

Requirements:

  • Document must not already exist for this token
  • Caller should be token owner

Effects:

  • Creates new DocumentRecord
  • Adds initial version
  • Increments total_documents
  • Emits DocumentRegistered event

append_version()

Add new version to existing document (issuer-only):

public entry fun append_version(
    registry: &mut DocumentRegistry,
    token_address: address,
    blob_id: String,
    blob_object_id: ID,
    file_hash: vector<u8>,
    description: String,
    access_key: vector<u8>,
    metadata: vector<u8>,
    ctx: &mut TxContext
)

Requirements:

  • Document must already exist
  • Caller must be the original issuer
  • Previous versions are preserved (immutable history)

Effects:

  • Appends new version to versions vector
  • Updates updated_at timestamp
  • Emits VersionUpdated event

endorse_document()

Allow auditors to verify document validity:

public entry fun endorse_document(
    registry: &mut DocumentRegistry,
    token_address: address,
    ctx: &TxContext
)

Requirements:

  • Document must exist
  • Auditor must not have already endorsed

Effects:

  • Adds auditor to auditors list
  • Emits DocumentEndorsed event

get_latest_blob()

Get current Walrus blob ID:

public fun get_latest_blob(
    registry: &DocumentRegistry,
    token_address: address
): (String, ID)

Returns: Tuple of (blob_id, blob_object_id)

get_access_key()

Get encrypted access key (requires token ownership):

public fun get_access_key(
    registry: &DocumentRegistry,
    token: &RwaToken,
    token_address: address
): (vector<u8>, u64)

Requirements:

  • Caller must own the RWA token
  • Document must exist

Returns: Tuple of (access_key, version_index)

Events

DocumentRegistered

public struct DocumentRegistered has copy, drop {
    token_address: address,
    issuer: address,
    blob_id: String,
    version_index: u64,
    timestamp: u64,
}

VersionUpdated

public struct VersionUpdated has copy, drop {
    token_address: address,
    version_index: u64,
    blob_id: String,
    timestamp: u64,
}

DocumentEndorsed

public struct DocumentEndorsed has copy, drop {
    token_address: address,
    auditor: address,
    timestamp: u64,
}

Version History

Document versions are immutable and append-only:

  • Version 0: Initial document registration
  • Version 1+: Updated versions (amendments, corrections)
  • All versions preserved for audit trail
  • Cannot delete or modify existing versions

Access Control

Issuer Restrictions

Only the original issuer (token creator) can:

  • Append new document versions
  • Maintain version history

This ensures:

  • Document integrity
  • Clear provenance
  • Audit trail completeness

Ownership-Based Access

Token owners can:

  • Retrieve access keys
  • Access encrypted documents
  • Verify document integrity

When token transfers:

  • New owner gains access
  • Previous owner loses access

Walrus Integration

Documents are stored on Walrus decentralized storage:

  1. Upload: Client encrypts document and uploads to Walrus
  2. Blob ID: Walrus returns content-addressed blob ID
  3. Registration: Blob ID stored on-chain in vault
  4. Download: Token owner retrieves blob ID and downloads from Walrus
  5. Decryption: Access key used to decrypt document

Usage Examples

Register Document

sui client call \
  --package <PACKAGE_ID> \
  --module vault \
  --function register_document \
  --args <REGISTRY_ID> <TOKEN_ADDRESS> "<WALRUS_BLOB_ID>" "<WALRUS_OBJECT_ID>" "[<FILE_HASH_BYTES>]" "Initial Property Deed" '{"encrypted":"key"}' \
  --gas-budget 10000000

Append Version

sui client call \
  --package <PACKAGE_ID> \
  --module vault \
  --function append_version \
  --args <REGISTRY_ID> <TOKEN_ADDRESS> "<NEW_BLOB_ID>" "<NEW_OBJECT_ID>" "[<NEW_HASH>]" "Updated deed with correction" '{"encrypted":"key"}' \
  --gas-budget 10000000

Endorse Document

sui client call \
  --package <PACKAGE_ID> \
  --module vault \
  --function endorse_document \
  --args <REGISTRY_ID> <TOKEN_ADDRESS> \
  --gas-budget 10000000

Security Considerations

Immutability

  • Versions can never be deleted
  • History is permanent
  • Provides complete audit trail

Integrity Verification

  • SHA-256 hashes verify document integrity
  • Download and compare hash
  • Detects tampering or corruption

Access Key Security

  • Access keys are encrypted
  • Only token owners can retrieve
  • Keys not stored in plaintext on-chain

Auditor System

  • Third-party verification
  • Immutable endorsements
  • Legal compliance support

Best Practices

  1. Version Descriptions: Use clear, descriptive version descriptions
  2. Hash Verification: Always verify document hashes after download
  3. Auditor Verification: Get professional endorsements for legal documents
  4. Metadata: Store structured metadata in JSON format
  5. Version Tracking: Document why each version was created

Integration Points

Marketplace

When tokens are traded:

  • Access keys transfer to new owner
  • Document access follows ownership
  • No action needed from seller/buyer

Frontend

Frontend services:

  • Upload documents to Walrus
  • Register on-chain
  • Retrieve and decrypt documents
  • Verify integrity

Next Steps