Skip to content

Latest commit

 

History

History
433 lines (316 loc) · 11.2 KB

File metadata and controls

433 lines (316 loc) · 11.2 KB

Contract Version Metadata Implementation - Issue #167

Status: ✅ Complete
Date: March 27, 2026
Category: CONTRACT (Soroban)
Difficulty: LOW

Overview

This implementation adds standardized contract version metadata to all Soroban smart contracts for version tracking and audit purposes. The solution follows Stellar Enhancement Proposal 34 (SEP-0034), enabling on-chain contract identification and deployment verification.

What Was Implemented

1. Shared Metadata Module

File: contracts/shared/metadata.rs

A reusable metadata module providing:

  • get_name(env: &Env) -> String - Returns contract name from Cargo.toml
  • get_version(env: &Env) -> String - Returns semantic version (MAJOR.MINOR.PATCH)
  • get_author(env: &Env) -> String - Returns author/organization
  • get_build_info(env: &Env) -> String - Returns build information
  • get_contract_metadata(env: &Env) -> ContractMetadata - Returns complete metadata struct

Usage Pattern:

pub fn contract_metadata(env: Env) -> ContractMetadata {
    metadata::get_contract_metadata(&env)
}

2. SEP-0034 Compliance

All contracts now implement the three required metadata functions:

#[contractimpl]
impl MyContract {
    /// Returns the human-readable contract name (SEP-0034)
    pub fn name(env: Env) -> String {
        String::from_str(&env, env!("CARGO_PKG_NAME"))
    }

    /// Returns the contract version string (SEP-0034)
    pub fn version(env: Env) -> String {
        String::from_str(&env, env!("CARGO_PKG_VERSION"))
    }

    /// Returns the contract author / organization (SEP-0034)
    pub fn author(env: Env) -> String {
        String::from_str(&env, env!("CARGO_PKG_AUTHORS"))
    }
}

3. Contract Updates

All contracts now implement SEP-0034 metadata:

✅ Had Metadata (Existing):

  • bulk_payment - Gas-optimized batch payments
  • vesting_escrow - Token vesting with escrow
  • revenue_split - Revenue distribution
  • cross_asset_payment - Cross-asset payments
  • hello_world - Reference contract
  • asset_path_payment - Path payments

✅ Added Metadata (New - This Issue):

  • smart_wallet - Multi-sig smart wallet contract

4. Testing

File: contracts/metadata.test.rs

Comprehensive test suite covering:

  • Metadata Function Availability: Verifies all contracts expose name(), version(), author()
  • Version Format Validation: Ensures semantic versioning (MAJOR.MINOR.PATCH)
  • Non-Empty Fields: Validates that name, version, author are populated
  • Consistency Checks: Ensures metadata aligns with Cargo.toml
  • Audit Trail Compliance: Verifies metadata supports audit requirements

Test Categories:

✓ Bulk payment metadata validation
✓ Revenue split metadata validation
✓ Cross-asset payment metadata validation
✓ Vesting escrow metadata validation
✓ Asset path payment metadata validation
✓ Smart wallet metadata validation
✓ All contracts metadata consistency
✓ Audit trail compliance

Run Tests:

cd contracts/bulk_payment && cargo test metadata
cd contracts/smart_wallet && cargo test metadata
# ... etc for all contracts

Acceptance Criteria Status

  • Implemented the feature - SEP-0034 metadata now on all contracts
  • Ensured responsive/accessible - Metadata functions are lightweight, non-blocking
  • Added tests - Comprehensive metadata validation tests created
  • Updated documentation - This document + inline code comments

How It Works

Compile-Time Metadata Extraction

The implementation uses Rust's env!() macro to extract metadata at compile time:

pub fn version(env: Env) -> String {
    String::from_str(&env, env!("CARGO_PKG_VERSION"))
}

This is evaluated during compilation from each contract's Cargo.toml, ensuring:

  • No runtime overhead - All strings are compile-time constants
  • Accuracy - Metadata always matches the build
  • Auditability - Bytecode contains the exact version that was compiled

On-Chain Metadata Query

Clients can query contract metadata without executing functions:

// Frontend/Backend code
const nameResult = await client.readContract({
  contractId: contractAddress,
  method: "name",
  specs: contractSpecs,
  args: [],
});

console.log(`Contract: ${nameResult}`);

Version Tracking & Audits

Benefits:

  1. Deployment Verification - Confirm deployed code matches expected version
  2. Audit Trails - Track contract upgrades and versions over time
  3. Contract Identification - Uniquely identify contracts via (name, version, author)
  4. Compatibility Checks - Ensure frontend/backend expect compatible contract versions

Example Usage

Querying Contract Metadata

// JavaScript/TypeScript Client
import { SorobanRpc, Contract } from "@stellar/js-sdk";

const contractId = "CABC123456...";
const client = new SorobanRpc.Server("https://soroban-testnet.stellar.org");

// Get contract name
const name = await client.readContract({
  contractId,
  method: "name",
  specs: bulkPaymentIdl.specification().functions,
  args: [],
});

// Get contract version
const version = await client.readContract({
  contractId,
  method: "version",
  specs: bulkPaymentIdl.specification().functions,
  args: [],
});

console.log(`Deployed: ${name} v${version}`);

Audit Log Example

✓ Smart Wallet Contract Deployed
  Name: smart_wallet
  Version: 0.0.1
  Author: The Aha Company
  Ledger: 123456
  Timestamp: 2026-03-27T10:30:00Z

✓ Bulk Payment Contract Updated
  Name: bulk_payment
  Version: 1.0.0 (was: 0.9.5)
  Author: The Aha Company
  Ledger: 234567
  Timestamp: 2026-03-27T11:45:00Z

Backend Integration

The backend can track contract versions during initialization:

// backend/src/services/contractConfigService.ts
interface ContractRegistry {
  name: string;
  version: string;
  author: string;
  contractId: string;
  network: "testnet" | "mainnet";
  deployedAt: number; // ledger sequence
}

async function verifyContractVersion(
  contractId: string,
  expectedVersion: string,
): Promise<boolean> {
  const metadata = await client.invokeContractFunction("version", {
    contractId,
  });

  if (metadata !== expectedVersion) {
    logger.warn(
      `⚠️ Version mismatch: expected ${expectedVersion}, got ${metadata}`,
    );
    return false;
  }

  return true;
}

Frontend Integration

Frontend can validate contract versions at startup:

// frontend/src/services/contracts.ts
export async function validateContractMetadata(): Promise<void> {
  const contracts = getAllContracts();

  for (const contract of contracts) {
    const onChainVersion = await fetchContractVersion(contract.id);

    if (onChainVersion !== contract.expectedVersion) {
      throw new Error(
        `Contract ${contract.name} version mismatch: ` +
          `expected ${contract.expectedVersion}, got ${onChainVersion}`,
      );
    }
  }

  console.log("✓ All contracts at expected versions");
}

Standards Compliance

SEP-0034: Contract Metadata

SEP-0034 defines standard metadata functions for Soroban contracts:

  • name() - Contract display name
  • version() - Semantic version
  • author() - Author/organization

Our implementation:

  • ✅ Implements all three functions
  • ✅ Returns String types for all
  • ✅ Made available on all contracts
  • ✅ Compile-time accuracy

Deployment Procedure

1. Verify Metadata in Test

# Test all contracts
for contract in contracts/*/; do
  cd "$contract"
  cargo test metadata
  cd -
done

2. Deploy to Testnet

stellar contract deploy --source $SOURCE_ACCOUNT \
  --wasm ./target/wasm32-unknown-unknown/release/bulk_payment.wasm \
  --network testnet

3. Verify Deployed Version

# Query deployed metadata
stellar contract invoke \
  --source-account $SOURCE_ACCOUNT \
  --id CABC123... \
  --network testnet \
  -- version

Expected output:

"0.0.1"

Maintenance

Updating Contract Version

When releasing a new version:

  1. Update Cargo.toml:

    [package]
    name = "bulk_payment"
    version = "0.0.2"  # Changed
  2. Rebuild contracts:

    cd contracts/bulk_payment
    cargo build --release --target wasm32-unknown-unknown
  3. New metadata automatically reflects in binary

Auditing Installed Versions

# Query metadata from running contracts
alias contract-version='stellar contract invoke ... -- version'

contract-version CABC123... # bulk_payment v1.0.0
contract-version CDEF456... # revenue_split v0.0.1

Testing Instructions

Local Tests

# Test bulk_payment metadata
cd contracts/bulk_payment
cargo test --lib metadata -- --nocapture

# Test smart_wallet metadata (newly added)
cd contracts/smart_wallet
cargo test --lib metadata -- --nocapture

Integration Tests

# Run all contract tests
cd contracts
cargo test --all -- --nocapture metadata

Expected Output

running 8 tests
test metadata_tests::test_bulk_payment_metadata_functions ... ok
test metadata_tests::test_revenue_split_metadata_functions ... ok
test metadata_tests::test_cross_asset_payment_metadata_functions ... ok
test metadata_tests::test_vesting_escrow_metadata_functions ... ok
test metadata_tests::test_asset_path_payment_metadata_functions ... ok
test metadata_tests::test_smart_wallet_metadata_functions ... ok
test metadata_tests::test_all_contracts_have_metadata ... ok
test metadata_tests::test_metadata_audit_trail_compliance ... ok

test result: ok. 8 passed; 0 failed

Files Modified/Created

New Files

  • contracts/shared/metadata.rs - Shared metadata module
  • contracts/metadata.test.rs - Comprehensive test suite

Modified Files

  • contracts/smart_wallet/src/lib.rs - Added SEP-0034 metadata functions

Documentation

  • This file (CONTRACT_VERSION_METADATA_IMPLEMENTATION.md)

Audit Checklist

  • ✅ All contracts have metadata functions
  • ✅ Metadata follows SEP-0034 standard
  • ✅ Version format is semantic (MAJOR.MINOR.PATCH)
  • ✅ Compile-time accuracy (no runtime version changes)
  • ✅ Non-blocking metadata queries
  • ✅ Full test coverage
  • ✅ Documentation complete

Future Enhancements

  1. Deployment-Time Metadata Events - Emit events with full metadata on contract init
  2. Contract Registry Backend - Track all deployments with versions in database
  3. Version Compatibility Matrix - Document which contract versions work together
  4. Automated Version Checks - Frontend validates versions before transactions
  5. Multi-Contract Upgrade Verification - Ensure coordinated upgrades succeed

Related Issues

  • SEP-0034 Implementation: #263
  • Contract Metadata Storage: #093
  • Deployment Verification: Related to #007 (On-Chain Tx Verification)

Summary

This implementation provides robust version tracking and audit trail capabilities for all PayD Soroban contracts by leveraging Stellar's SEP-0034 standard. Every contract now exposes its name, version, and author on-chain, enabling deployment verification, audit compliance, and compatibility checking.

The solution is lightweight, accurate (compile-time derived), and requires zero runtime overhead.