diff --git a/Makefile b/Makefile index 786e701..66977be 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Configurable variables -WASM ?= target/wasm32v1-none/release/my_token.wasm +WASM ?= target/wasm32-unknown-unknown/release/my_contract.wasm SOURCE ?= alice NETWORK ?= testnet HOST_TARGET ?= x86_64-unknown-linux-gnu @@ -13,8 +13,8 @@ test: build cargo test --workspace --target $(HOST_TARGET) build: - SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2=1 stellar contract build - @ls -l target/wasm32v1-none/release/*.wasm + stellar contract build + @ls -l target/wasm32-unknown-unknown/release/*.wasm # Deploy the built wasm to Stellar (uses `stellar` CLI) # Usage: make deploy WASM=path/to/wasm SOURCE=alice NETWORK=testnet @@ -25,25 +25,6 @@ deploy: build deploy-show: deploy @echo "Deployed. Check output above for CONTRACT_ID" -# Mainnet deployment for AgentVerse (MyToken + PromptMarketplace) -# Requires MAINNET_DEPLOYER_SOURCE, MAINNET_ADMIN_SOURCE, MAINNET_ADMIN_ADDR -# Usage: -# MAINNET_DEPLOYER_SOURCE=deployer \ -# MAINNET_ADMIN_SOURCE=admin \ -# MAINNET_ADMIN_ADDR=G... \ -# make deploy-mainnet -deploy-mainnet: - bash scripts/deploy-mainnet.sh - -# Mainnet verification of deployed contracts -# Usage: -# MAINNET_TOKEN_ID=C... \ -# MAINNET_MARKETPLACE_ID=C... \ -# MAINNET_ADMIN_ADDR=G... \ -# make verify-mainnet -verify-mainnet: - bash scripts/verify-mainnet.sh - fmt: cargo fmt --all diff --git a/README.md b/README.md index fd24b52..1c5d9b2 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2=1 stellar contract build --pac SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2=1 stellar contract build --package prompt-marketplace ``` -Requiere el target `wasm32v1-none` y la env var `SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2=1` para Spec Shaking v2. Alternativamente, para mainnet se usa `cargo build --target wasm32v1-none --release` (ver sección Deploy en Mainnet). +Requiere el target `wasm32v1-none` y la env var para Spec SHAKING v2. --- @@ -136,114 +136,6 @@ stellar contract deploy \ --token "CCHAUOEVX6TQD56VFZY2GI3N3HNF5W6QSRRKAGKDXV6S53T4BKD5PYQD" ``` -## Deploy en Mainnet - -> ⚠️ **ADVERTENCIA DE SEGURIDAD — LEER ANTES DE EJECUTAR** -> -> Mainnet implica valor real y transacciones irreversibles. Antes de deployar: -> -> 1. **No hardcodees ni hagas `source` de claves privadas.** Usa un secrets manager (1Password CLI, AWS Secrets Manager, HashiCorp Vault, GitHub encrypted secrets, etc.) para inyectar `MAINNET_DEPLOYER_SOURCE` y `MAINNET_ADMIN_SOURCE` en runtime. -> 2. **Verifica el código y el WASM antes de deployar.** Recompila desde una fuente confiable, calcula el hash SHA-256 y comparalo con el artefacto que vas a subir. -> 3. **Preferí cuentas multisig o hardware wallets** para la cuenta admin (`MAINNET_ADMIN_ADDR`). El deployer y el admin pueden ser distintas cuentas. -> 4. **Revisa los parámetros de constructor.** Un error en `owner`/`admin` o en el `token` del marketplace puede dejar los contratos incontrolables. -> 5. **Tené XLM suficiente** en la cuenta deployer para cubrir el rent/storage de ambos contratos en mainnet. - -### Prerrequisitos - -- Stellar CLI configurado para mainnet (`stellar network add mainnet ...` o variables de entorno equivalentes). -- Acceso a un RPC endpoint de mainnet (Stellar public RPC, Blockdaemon, etc.). -- Cuenta con XLM real para pagar fees y rent. -- Cuenta admin separada (recomendado) con su par de claves seguras. -- Target de compilación instalado: `rustup target add wasm32v1-none`. -- Variable de entorno para Spec Shaking V2: - ```bash - export SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2=1 - ``` - -### Scripts de mainnet - -#### `scripts/deploy-mainnet.sh` - -Build release, calcula hashes, deploya, inicializa y valida ambos contratos. Emite un resumen JSON en `deploy-artifacts/`. - -```bash -MAINNET_DEPLOYER_SOURCE="deployer" \ -MAINNET_ADMIN_SOURCE="admin" \ -MAINNET_ADMIN_ADDR="G..." \ -bash scripts/deploy-mainnet.sh -``` - -También podés usar el target de Makefile: - -```bash -MAINNET_DEPLOYER_SOURCE="deployer" \ -MAINNET_ADMIN_SOURCE="admin" \ -MAINNET_ADMIN_ADDR="G..." \ -make deploy-mainnet -``` - -Variables opcionales: - -| Variable | Descripción | Default | -|---|---|---| -| `MAINNET_TOKEN_NAME` | Nombre del token | `AgentVerse Token` | -| `MAINNET_TOKEN_SYMBOL` | Símbolo del token | `AVT` | -| `MAINNET_TOKEN_DECIMALS` | Decimales | `7` | -| `MAINNET_DEPLOY_OUT_DIR` | Carpeta de artefactos | `./deploy-artifacts` | - -El script: - -1. Construye ambos contratos con `cargo build --target wasm32v1-none --release`. -2. Calcula el hash SHA-256 de cada WASM. -3. Deploya `MyToken` y `PromptMarketplace` desde `MAINNET_DEPLOYER_SOURCE`. -4. Inicializa el token con el admin, nombre, símbolo y decimales configurados. -5. Inicializa el marketplace con el admin y el `contract_id` del token recién deployado. -6. Valida post-deploy: - - Metadata del token (`name`, `symbol`, `decimals`). - - Supply inicial igual a `0`. - - Owner del token igual a `MAINNET_ADMIN_ADDR`. - - Admin del marketplace igual a `MAINNET_ADMIN_ADDR`. - - Token del marketplace igual al `contract_id` del token deployado. - - Hash WASM on-chain (fetcheado) coincide con el artefacto local. -7. Escribe `deploy-artifacts/mainnet-deploy-summary-.json`. - -#### `scripts/verify-mainnet.sh` - -Verifica un par de contratos ya deployados sin re-deployar. Útil para CI o validaciones periódicas. - -```bash -MAINNET_TOKEN_ID="C..." \ -MAINNET_MARKETPLACE_ID="C..." \ -MAINNET_ADMIN_ADDR="G..." \ -bash scripts/verify-mainnet.sh -``` - -O vía Makefile: - -```bash -MAINNET_TOKEN_ID="C..." \ -MAINNET_MARKETPLACE_ID="C..." \ -MAINNET_ADMIN_ADDR="G..." \ -make verify-mainnet -``` - -Verifica: - -- Hash WASM on-chain vs. artefacto local. -- Admin/owner de ambos contratos. -- Link token ↔ marketplace. -- Supply inicial (`0`). -- Metadata del token. - -Escribe `deploy-artifacts/mainnet-verify-report-.json`. - -### Multisig / DAuthorization (roadmap v2) - -La v1 actual soporta cuentas multisig configuradas en Stellar CLI (el CLI pedirá/co-firmará las transacciones). Para una v2 se documentará como mejora: - -- Flujo de firmas separadas: el deployer crea la transacción, múltiples signers la firman off-line, y alguien la publica. -- DAuthorization: delegar privilegios admin a un módulo de gobernanza on-chain. - ### Invocar ```bash diff --git a/scripts/deploy-mainnet.sh b/scripts/deploy-mainnet.sh deleted file mode 100644 index b24ec64..0000000 --- a/scripts/deploy-mainnet.sh +++ /dev/null @@ -1,365 +0,0 @@ -#!/usr/bin/env bash -# ============================================================================= -# AgentVerse — Mainnet Deployment Script -# ============================================================================= -# This script builds both Soroban contracts in release mode, computes and -# verifies WASM hashes, deploys them to Stellar mainnet, initializes them, -# runs post-deploy validation, and emits a machine-readable JSON summary. -# -# SECURITY NOTICE: -# - NEVER source this script with secret keys inline. -# - ALWAYS provide keys via environment variables injected at runtime by a -# secrets manager (e.g. 1Password CLI, AWS Secrets Manager, HashiCorp Vault, -# GitHub encrypted secrets, etc.). -# - Prefer a hardware wallet / multisig account for mainnet admin operations. -# - This script does NOT write private keys to disk. -# -# Required environment variables (inject securely): -# MAINNET_DEPLOYER_SOURCE Stellar CLI source alias/name for deployer account -# MAINNET_ADMIN_SOURCE Stellar CLI source alias/name for admin account -# MAINNET_ADMIN_ADDR Mainnet public address that will own the contracts -# -# Optional environment variables: -# MAINNET_TOKEN_NAME Token name (default: "AgentVerse Token") -# MAINNET_TOKEN_SYMBOL Token symbol (default: "AVT") -# MAINNET_TOKEN_DECIMALS Token decimals (default: 7) -# MAINNET_DEPLOY_OUT_DIR Directory for deploy artifacts (default: ./deploy-artifacts) -# -# Example invocation: -# MAINNET_DEPLOYER_SOURCE="deployer" \ -# MAINNET_ADMIN_SOURCE="admin" \ -# MAINNET_ADMIN_ADDR="G..." \ -# bash scripts/deploy-mainnet.sh -# -# Multisig / DAuthorization (v1 roadmap): -# This initial version deploys from a single Stellar CLI source. If your -# deployer account is a multisig account configured in the Stellar CLI, -# the CLI will prompt/co-sign as usual. Future versions can integrate -# explicit multi-signature workflows (e.g. signed transactions submitted -# via separate signers) and DAuthorization (decentralized authorization) -# modules. -# ============================================================================= - -set -euo pipefail - -# ── Configuration ─────────────────────────────────────────────────────────── -NETWORK="mainnet" -TARGET="wasm32v1-none" -RELEASE_DIR="target/${TARGET}/release" -TOKEN_WASM_NAME="my_token.wasm" -MKT_WASM_NAME="prompt_marketplace.wasm" - -TOKEN_NAME="${MAINNET_TOKEN_NAME:-AgentVerse Token}" -TOKEN_SYMBOL="${MAINNET_TOKEN_SYMBOL:-AVT}" -TOKEN_DECIMALS="${MAINNET_TOKEN_DECIMALS:-7}" -OUT_DIR="${MAINNET_DEPLOY_OUT_DIR:-./deploy-artifacts}" -TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ) - -TOKEN_WASM="${RELEASE_DIR}/${TOKEN_WASM_NAME}" -MKT_WASM="${RELEASE_DIR}/${MKT_WASM_NAME}" - -# ── Helpers ───────────────────────────────────────────────────────────────── - -log_section() { - echo "" - echo "=== $1 ===" -} - -log_info() { - echo " ℹ️ $*" -} - -log_ok() { - echo " ✅ $*" -} - -log_error() { - echo " ❌ $*" >&2 -} - -fail() { - log_error "$*" - exit 1 -} - -# Portable SHA-256 file hashing (Linux sha256sum or macOS shasum) -sha256_file() { - local file="$1" - if command -v sha256sum >/dev/null 2>&1; then - sha256sum "$file" | awk '{print $1}' - elif command -v shasum >/dev/null 2>&1; then - shasum -a 256 "$file" | awk '{print $1}' - else - fail "No SHA-256 tool found. Install sha256sum (Linux) or shasum (macOS)." - fi -} - -# Verify that a required environment variable is set and non-empty -require_env() { - local var_name="$1" - local var_value="${!var_name:-}" - if [[ -z "$var_value" ]]; then - fail "Missing required environment variable: ${var_name}" - fi -} - -# Verify that a binary is available in PATH -require_cmd() { - if ! command -v "$1" >/dev/null 2>&1; then - fail "Missing required command: $1. Please install it and add it to PATH." - fi -} - -# Invoke stellar contract with a small wrapper for readability -stellar_invoke() { - local contract_id="$1" - local source="$2" - shift 2 - stellar contract invoke \ - --id "$contract_id" \ - --source "$source" \ - --network "$NETWORK" \ - -- "$@" -} - -# ── Pre-flight checks ─────────────────────────────────────────────────────── - -log_section "AgentVerse Mainnet Deploy" -log_info "Network: ${NETWORK}" -log_info "Timestamp: ${TIMESTAMP}" - -require_cmd cargo -require_cmd stellar - -require_env MAINNET_DEPLOYER_SOURCE -require_env MAINNET_ADMIN_SOURCE -require_env MAINNET_ADMIN_ADDR - -# Basic address format sanity check (Stellar public keys start with G and are 56 chars) -if [[ ! "${MAINNET_ADMIN_ADDR}" =~ ^G[A-Z0-9]{55}$ ]]; then - fail "MAINNET_ADMIN_ADDR does not look like a valid Stellar public key: ${MAINNET_ADMIN_ADDR}" -fi - -log_ok "Prerequisites satisfied" - -# ── Build release ─────────────────────────────────────────────────────────── - -log_section "Build Release" -log_info "Target: ${TARGET}" -log_info "Profile: release (LTO, strip, overflow-checks)" - -# The workspace profile.release already configures: -# opt-level = "z", lto = true, strip = "symbols", overflow-checks = true -SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2=1 \ - cargo build --target "${TARGET}" --release - -if [[ ! -f "$TOKEN_WASM" ]]; then - fail "Token WASM not found after build: ${TOKEN_WASM}" -fi -if [[ ! -f "$MKT_WASM" ]]; then - fail "Marketplace WASM not found after build: ${MKT_WASM}" -fi - -log_ok "Release build completed" - -# ── Compute and store WASM hashes ─────────────────────────────────────────── - -log_section "Wasm Hashes" - -TOKEN_WASM_HASH=$(sha256_file "$TOKEN_WASM") -MKT_WASM_HASH=$(sha256_file "$MKT_WASM") - -log_info "MyToken (${TOKEN_WASM_NAME}): ${TOKEN_WASM_HASH}" -log_info "Marketplace (${MKT_WASM_NAME}): ${MKT_WASM_HASH}" - -log_ok "WASM hashes computed" - -# ── Deploy MyToken ────────────────────────────────────────────────────────── - -log_section "Deploy MyToken" - -MY_TOKEN_ID=$(stellar contract deploy \ - --wasm "$TOKEN_WASM" \ - --source "$MAINNET_DEPLOYER_SOURCE" \ - --network "$NETWORK") - -if [[ -z "$MY_TOKEN_ID" ]]; then - fail "MyToken deployment returned an empty contract ID" -fi - -log_ok "MyToken deployed: ${MY_TOKEN_ID}" - -# ── Initialize MyToken ────────────────────────────────────────────────────── - -log_section "Initialize MyToken" - -stellar_invoke "$MY_TOKEN_ID" "$MAINNET_ADMIN_SOURCE" \ - __constructor \ - --owner "$MAINNET_ADMIN_ADDR" \ - --name "$TOKEN_NAME" \ - --symbol "$TOKEN_SYMBOL" \ - --decimals "$TOKEN_DECIMALS" - -log_ok "MyToken initialized" - -# ── Deploy PromptMarketplace ──────────────────────────────────────────────── - -log_section "Deploy PromptMarketplace" - -MARKETPLACE_ID=$(stellar contract deploy \ - --wasm "$MKT_WASM" \ - --source "$MAINNET_DEPLOYER_SOURCE" \ - --network "$NETWORK") - -if [[ -z "$MARKETPLACE_ID" ]]; then - fail "Marketplace deployment returned an empty contract ID" -fi - -log_ok "PromptMarketplace deployed: ${MARKETPLACE_ID}" - -# ── Initialize PromptMarketplace ──────────────────────────────────────────── - -log_section "Initialize PromptMarketplace" - -stellar_invoke "$MARKETPLACE_ID" "$MAINNET_ADMIN_SOURCE" \ - __constructor \ - --admin "$MAINNET_ADMIN_ADDR" \ - --token "$MY_TOKEN_ID" - -log_ok "PromptMarketplace initialized" - -# ── Post-deploy validation ────────────────────────────────────────────────── - -log_section "Post-Deploy Validation" - -# 1. Verify MyToken metadata matches the requested values -TOKEN_NAME_ON_CHAIN=$(stellar_invoke "$MY_TOKEN_ID" "$MAINNET_ADMIN_SOURCE" name | tr -d '"') -TOKEN_SYMBOL_ON_CHAIN=$(stellar_invoke "$MY_TOKEN_ID" "$MAINNET_ADMIN_SOURCE" symbol | tr -d '"') -TOKEN_DECIMALS_ON_CHAIN=$(stellar_invoke "$MY_TOKEN_ID" "$MAINNET_ADMIN_SOURCE" decimals) -TOKEN_SUPPLY_ON_CHAIN=$(stellar_invoke "$MY_TOKEN_ID" "$MAINNET_ADMIN_SOURCE" total_supply) -TOKEN_OWNER_ON_CHAIN=$(stellar_invoke "$MY_TOKEN_ID" "$MAINNET_ADMIN_SOURCE" owner | tr -d '"') - -if [[ "$TOKEN_NAME_ON_CHAIN" != "$TOKEN_NAME" ]]; then - fail "Token name mismatch: expected '${TOKEN_NAME}', got '${TOKEN_NAME_ON_CHAIN}'" -fi -if [[ "$TOKEN_SYMBOL_ON_CHAIN" != "$TOKEN_SYMBOL" ]]; then - fail "Token symbol mismatch: expected '${TOKEN_SYMBOL}', got '${TOKEN_SYMBOL_ON_CHAIN}'" -fi -if [[ "$TOKEN_DECIMALS_ON_CHAIN" != "$TOKEN_DECIMALS" ]]; then - fail "Token decimals mismatch: expected '${TOKEN_DECIMALS}', got '${TOKEN_DECIMALS_ON_CHAIN}'" -fi -if [[ "$TOKEN_SUPPLY_ON_CHAIN" != "0" ]]; then - fail "Initial token supply must be 0 at mainnet genesis, got '${TOKEN_SUPPLY_ON_CHAIN}'" -fi -if [[ "$TOKEN_OWNER_ON_CHAIN" != "$MAINNET_ADMIN_ADDR" ]]; then - fail "Token owner mismatch: expected '${MAINNET_ADMIN_ADDR}', got '${TOKEN_OWNER_ON_CHAIN}'" -fi - -log_ok "MyToken validation passed (name, symbol, decimals, supply=0, owner)" - -# 2. Verify marketplace admin and token linkage -MKT_ADMIN_ON_CHAIN=$(stellar_invoke "$MARKETPLACE_ID" "$MAINNET_ADMIN_SOURCE" get_admin | tr -d '"') -MKT_TOKEN_ON_CHAIN=$(stellar_invoke "$MARKETPLACE_ID" "$MAINNET_ADMIN_SOURCE" get_token | tr -d '"') - -if [[ "$MKT_ADMIN_ON_CHAIN" != "$MAINNET_ADMIN_ADDR" ]]; then - fail "Marketplace admin mismatch: expected '${MAINNET_ADMIN_ADDR}', got '${MKT_ADMIN_ON_CHAIN}'" -fi -if [[ "$MKT_TOKEN_ON_CHAIN" != "$MY_TOKEN_ID" ]]; then - fail "Marketplace token mismatch: expected '${MY_TOKEN_ID}', got '${MKT_TOKEN_ON_CHAIN}'" -fi - -log_ok "PromptMarketplace validation passed (admin, token)" - -# 3. Verify on-chain WASM hash matches the locally built artifact -verify_on_chain_hash() { - local contract_id="$1" - local expected_hash="$2" - local label="$3" - local fetched_wasm - fetched_wasm="${OUT_DIR}/${label}_fetched.wasm" - - mkdir -p "$OUT_DIR" - stellar contract fetch \ - --id "$contract_id" \ - --out-file "$fetched_wasm" \ - --network "$NETWORK" - - local fetched_hash - fetched_hash=$(sha256_file "$fetched_wasm") - - if [[ "$fetched_hash" != "$expected_hash" ]]; then - fail "${label} on-chain WASM hash mismatch. Expected: ${expected_hash}, got: ${fetched_hash}" - fi - - log_ok "${label} on-chain WASM hash verified (${fetched_hash})" -} - -verify_on_chain_hash "$MY_TOKEN_ID" "$TOKEN_WASM_HASH" "my_token" -verify_on_chain_hash "$MARKETPLACE_ID" "$MKT_WASM_HASH" "prompt_marketplace" - -# ── Persist deploy artifacts ──────────────────────────────────────────────── - -log_section "Persisting Deploy Artifacts" - -mkdir -p "$OUT_DIR" - -SUMMARY_FILE="${OUT_DIR}/mainnet-deploy-summary-${TIMESTAMP}.json" -# Sanitize filename for Windows/Unix compatibility -SUMMARY_FILE="${SUMMARY_FILE//:/-}" - -cat > "$SUMMARY_FILE" <&2 -} - -fail() { - log_error "$*" - exit 1 -} - -sha256_file() { - local file="$1" - if command -v sha256sum >/dev/null 2>&1; then - sha256sum "$file" | awk '{print $1}' - elif command -v shasum >/dev/null 2>&1; then - shasum -a 256 "$file" | awk '{print $1}' - else - fail "No SHA-256 tool found. Install sha256sum (Linux) or shasum (macOS)." - fi -} - -require_env() { - local var_name="$1" - local var_value="${!var_name:-}" - if [[ -z "$var_value" ]]; then - fail "Missing required environment variable: ${var_name}" - fi -} - -require_cmd() { - if ! command -v "$1" >/dev/null 2>&1; then - fail "Missing required command: $1. Please install it and add it to PATH." - fi -} - -stellar_invoke() { - local contract_id="$1" - shift 1 - stellar contract invoke \ - --id "$contract_id" \ - --source "$VERIFY_SOURCE" \ - --network "$NETWORK" \ - -- "$@" -} - -# ── Pre-flight checks ─────────────────────────────────────────────────────── - -log_section "AgentVerse Mainnet Verification" -log_info "Network: ${NETWORK}" -log_info "Timestamp: ${TIMESTAMP}" - -require_cmd stellar - -require_env MAINNET_TOKEN_ID -require_env MAINNET_MARKETPLACE_ID -require_env MAINNET_ADMIN_ADDR - -if [[ ! -f "$TOKEN_WASM" ]]; then - fail "Local MyToken WASM not found: ${TOKEN_WASM}. Build with: cargo build --target ${TARGET} --release" -fi -if [[ ! -f "$MKT_WASM" ]]; then - fail "Local Marketplace WASM not found: ${MKT_WASM}. Build with: cargo build --target ${TARGET} --release" -fi - -log_ok "Inputs validated" - -# ── Compute local WASM hashes ─────────────────────────────────────────────── - -log_section "Local WASM Hashes" - -LOCAL_TOKEN_HASH=$(sha256_file "$TOKEN_WASM") -LOCAL_MKT_HASH=$(sha256_file "$MKT_WASM") - -log_info "MyToken local hash: ${LOCAL_TOKEN_HASH}" -log_info "Marketplace local hash: ${LOCAL_MKT_HASH}" - -# ── Verify on-chain WASM hashes ───────────────────────────────────────────── - -log_section "On-Chain WASM Hash Verification" - -mkdir -p "$OUT_DIR" - -verify_fetched_hash() { - local contract_id="$1" - local expected_hash="$2" - local label="$3" - local fetched_wasm="${OUT_DIR}/${label}_fetched.wasm" - - log_info "Fetching ${label} WASM from mainnet..." - stellar contract fetch \ - --id "$contract_id" \ - --out-file "$fetched_wasm" \ - --network "$NETWORK" - - local fetched_hash - fetched_hash=$(sha256_file "$fetched_wasm") - - if [[ "$fetched_hash" != "$expected_hash" ]]; then - fail "${label} WASM hash mismatch. Local: ${expected_hash}, On-chain: ${fetched_hash}" - fi - - log_ok "${label} on-chain WASM hash matches local artifact" -} - -verify_fetched_hash "$TOKEN_ID" "$LOCAL_TOKEN_HASH" "my_token" -verify_fetched_hash "$MKT_ID" "$LOCAL_MKT_HASH" "prompt_marketplace" - -# ── Verify MyToken state ──────────────────────────────────────────────────── - -log_section "MyToken State Verification" - -TOKEN_NAME_CHAIN=$(stellar_invoke "$TOKEN_ID" name | tr -d '"') -TOKEN_SYMBOL_CHAIN=$(stellar_invoke "$TOKEN_ID" symbol | tr -d '"') -TOKEN_DECIMALS_CHAIN=$(stellar_invoke "$TOKEN_ID" decimals) -TOKEN_SUPPLY_CHAIN=$(stellar_invoke "$TOKEN_ID" total_supply) -TOKEN_OWNER_CHAIN=$(stellar_invoke "$TOKEN_ID" owner | tr -d '"') - -if [[ "$TOKEN_NAME_CHAIN" != "$TOKEN_NAME" ]]; then - fail "Token name mismatch. Expected: ${TOKEN_NAME}, Got: ${TOKEN_NAME_CHAIN}" -fi -log_ok "Token name: ${TOKEN_NAME_CHAIN}" - -if [[ "$TOKEN_SYMBOL_CHAIN" != "$TOKEN_SYMBOL" ]]; then - fail "Token symbol mismatch. Expected: ${TOKEN_SYMBOL}, Got: ${TOKEN_SYMBOL_CHAIN}" -fi -log_ok "Token symbol: ${TOKEN_SYMBOL_CHAIN}" - -if [[ "$TOKEN_DECIMALS_CHAIN" != "$TOKEN_DECIMALS" ]]; then - fail "Token decimals mismatch. Expected: ${TOKEN_DECIMALS}, Got: ${TOKEN_DECIMALS_CHAIN}" -fi -log_ok "Token decimals: ${TOKEN_DECIMALS_CHAIN}" - -if [[ "$TOKEN_SUPPLY_CHAIN" != "0" ]]; then - fail "Token initial supply mismatch. Expected: 0, Got: ${TOKEN_SUPPLY_CHAIN}" -fi -log_ok "Token initial supply: ${TOKEN_SUPPLY_CHAIN}" - -if [[ "$TOKEN_OWNER_CHAIN" != "$ADMIN_ADDR" ]]; then - fail "Token owner mismatch. Expected: ${ADMIN_ADDR}, Got: ${TOKEN_OWNER_CHAIN}" -fi -log_ok "Token owner: ${TOKEN_OWNER_CHAIN}" - -# ── Verify Marketplace state ──────────────────────────────────────────────── - -log_section "PromptMarketplace State Verification" - -MKT_ADMIN_CHAIN=$(stellar_invoke "$MKT_ID" get_admin | tr -d '"') -MKT_TOKEN_CHAIN=$(stellar_invoke "$MKT_ID" get_token | tr -d '"') - -if [[ "$MKT_ADMIN_CHAIN" != "$ADMIN_ADDR" ]]; then - fail "Marketplace admin mismatch. Expected: ${ADMIN_ADDR}, Got: ${MKT_ADMIN_CHAIN}" -fi -log_ok "Marketplace admin: ${MKT_ADMIN_CHAIN}" - -if [[ "$MKT_TOKEN_CHAIN" != "$TOKEN_ID" ]]; then - fail "Marketplace token mismatch. Expected: ${TOKEN_ID}, Got: ${MKT_TOKEN_CHAIN}" -fi -log_ok "Marketplace token: ${MKT_TOKEN_CHAIN}" - -# ── Persist verification report ───────────────────────────────────────────── - -log_section "Verification Report" - -REPORT_FILE="${OUT_DIR}/mainnet-verify-report-${TIMESTAMP}.json" -REPORT_FILE="${REPORT_FILE//:/-}" - -cat > "$REPORT_FILE" <