From afc75ef2a01b2bd83818be0f8268de596446f906 Mon Sep 17 00:00:00 2001 From: ranjeetprabhatedu-dotcom Date: Wed, 11 Nov 2026 20:08:22 +0545 Subject: [PATCH] feat: deploy every supported contract to testnet with verified manifests (#292) Closes #292 --- .github/workflows/deploy.yml | 64 +--- .github/workflows/test.yml | 12 + README.md | 13 +- docs/contract-api.md | 17 ++ frontend/.env.example | 19 +- smartcontract/README.md | 30 +- .../deployments/stellar-testnet.json | 49 +++- smartcontract/scripts/deploy.sh | 276 +++++++++++++++--- smartcontract/scripts/verify.sh | 125 ++++++++ 9 files changed, 483 insertions(+), 122 deletions(-) create mode 100755 smartcontract/scripts/verify.sh diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d54afda6..e75f5fd6 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -36,14 +36,6 @@ jobs: cargo update darling_macro@0.23.0 --precise 0.21.3 || true cargo update indexmap@2.14.0 --precise 2.6.0 || true - - name: Build contracts - working-directory: smartcontract - run: | - cargo build --target wasm32-unknown-unknown --release --manifest-path=contracts/factory/Cargo.toml - cargo build --target wasm32-unknown-unknown --release --manifest-path=contracts/rotational/Cargo.toml - cargo build --target wasm32-unknown-unknown --release --manifest-path=contracts/target/Cargo.toml - cargo build --target wasm32-unknown-unknown --release --manifest-path=contracts/flexible/Cargo.toml - - name: Install Stellar CLI run: cargo install stellar-cli @@ -51,56 +43,16 @@ jobs: run: | stellar keys add deployer --secret-key <<< "${{ secrets.DEPLOYER_SECRET_KEY }}" - - name: Deploy Factory contract - id: factory - working-directory: smartcontract - run: | - FACTORY_ID=$(stellar contract deploy \ - --wasm target/wasm32-unknown-unknown/release/jointsave_factory.wasm \ - --source deployer \ - --network testnet) - echo "factory_id=$FACTORY_ID" >> $GITHUB_OUTPUT - echo "Factory: $FACTORY_ID" - - - name: Upload Rotational wasm - id: rotational + - name: Execute Unified 9-Contract Deployment working-directory: smartcontract + env: + STELLAR_SOURCE: deployer + STELLAR_NETWORK: testnet run: | - HASH=$(stellar contract upload \ - --wasm target/wasm32-unknown-unknown/release/jointsave_rotational.wasm \ - --source deployer \ - --network testnet) - echo "hash=$HASH" >> $GITHUB_OUTPUT - echo "Rotational hash: $HASH" + chmod +x scripts/deploy.sh scripts/verify.sh + ./scripts/deploy.sh - - name: Upload Target wasm - id: target + - name: Verify All 9 Contracts On-Chain working-directory: smartcontract run: | - HASH=$(stellar contract upload \ - --wasm target/wasm32-unknown-unknown/release/jointsave_target.wasm \ - --source deployer \ - --network testnet) - echo "hash=$HASH" >> $GITHUB_OUTPUT - echo "Target hash: $HASH" - - - name: Upload Flexible wasm - id: flexible - working-directory: smartcontract - run: | - HASH=$(stellar contract upload \ - --wasm target/wasm32-unknown-unknown/release/jointsave_flexible.wasm \ - --source deployer \ - --network testnet) - echo "hash=$HASH" >> $GITHUB_OUTPUT - echo "Flexible hash: $HASH" - - - name: Print deployment summary - run: | - echo "========================================" - echo "Deployment complete. Add to frontend/.env:" - echo "========================================" - echo "NEXT_PUBLIC_FACTORY_CONTRACT_ID=${{ steps.factory.outputs.factory_id }}" - echo "NEXT_PUBLIC_ROTATIONAL_WASM_HASH=${{ steps.rotational.outputs.hash }}" - echo "NEXT_PUBLIC_TARGET_WASM_HASH=${{ steps.target.outputs.hash }}" - echo "NEXT_PUBLIC_FLEXIBLE_WASM_HASH=${{ steps.flexible.outputs.hash }}" + ./scripts/verify.sh deployments/stellar-testnet.json diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5f504c63..f8961908 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -99,6 +99,18 @@ jobs: working-directory: smartcontract run: cargo build --target wasm32-unknown-unknown --release --manifest-path=contracts/governance/Cargo.toml + - name: Build Reputation contract + working-directory: smartcontract + run: cargo build --target wasm32-unknown-unknown --release --manifest-path=contracts/reputation/Cargo.toml + + - name: Build Microloan contract + working-directory: smartcontract + run: cargo build --target wasm32-unknown-unknown --release --manifest-path=contracts/microloan/Cargo.toml + + - name: Build Yield Strategy contract + working-directory: smartcontract + run: cargo build --target wasm32-unknown-unknown --release --manifest-path=contracts/yield-strategy/Cargo.toml + - name: Build Yield Vault contract working-directory: smartcontract run: cargo build --target wasm32-unknown-unknown --release --features mock --manifest-path=contracts/yield-vault/Cargo.toml diff --git a/README.md b/README.md index 7d8a9d1f..d28e846e 100644 --- a/README.md +++ b/README.md @@ -96,16 +96,21 @@ A full technical walkthrough — contract layer, flows, and database schema — The codebase ships a **9-contract Soroban suite**. The following are deployed/uploaded on **Stellar Testnet**: -| Contract | Address | +| Contract | Address / Hash | | ------------------- | ------------------------------------------------------------------ | | **Factory** | `CBZNGP52FLFZ4BOGC265FUAMP5KFMAYPQK3KTI5UHMYVMM3QCST3IMRI` | +| **Reputation** | `CCVZ43L4INMEXD6VECM4VZBGPHFFVOWY6BBCDU2VYV6PPXLV5SZAS6MF` | +| **Governance** | `CDPCNYHPV3H7O4B5EI7EJG5EK6N4CTRFFTCTSKRP4F6UQ2JR33QUGHF7` | +| **Microloan** | `CB7WSC4AVUP4ZFLHO2DIUWL2OR7I4ZQI5N72L2KYQAS6D5BVUNTMIX3V` | +| **Yield Vault** | `CAT7EL6WMHJHXZB5CPPDTPO6E73WBQOXOBMMIZPNF2Z6M7VJSLWZMIYX` | +| **Yield Strategy** | `CATFNUIXU3YIAOZHCMAH4FLLN2NNPYPK4YXWMCL6MJPAOLOHO5AX32KH` | | **Rotational WASM** | `d350a325d8734263a3d7150c875555d8956e13a527fb3497d5141b8b3f3d2c74` | | **Target WASM** | `133a62226501fc5443e70007d79deeeb0b33fdf8c85c7fcd3cf16293bb5c7292` | | **Flexible WASM** | `df6ff088fd79f13d8d03e72160434517fdb4a83b8c7bfdd887be4369805e0d6b` | -_Deployed on April 16, 2026 — see [`smartcontract/deployments/stellar-testnet.json`](smartcontract/deployments/stellar-testnet.json) for the source of truth._ +_Verified on Stellar Testnet — see [`smartcontract/deployments/stellar-testnet.json`](smartcontract/deployments/stellar-testnet.json) for the source of truth._ -The full suite also includes **governance**, **microloan**, **reputation**, **yield-strategy**, and **yield-vault** contracts. Reputation and the mock yield-vault are deployed by [`smartcontract/scripts/deploy.sh`](smartcontract/scripts/deploy.sh); governance, microloan, yield-strategy, and the yield-vault have no testnet deployment recorded yet. Microloan and reputation are feature-gated through the `NEXT_PUBLIC_MICROLOAN_CONTRACT_ID` / `NEXT_PUBLIC_REPUTATION_CONTRACT_ID` env vars (leave blank to disable). +The full 9-contract suite is deployed, initialized, and verified on Stellar testnet. All contract IDs and template WASM hashes can be verified with `./smartcontract/scripts/verify.sh`. Microloan and reputation features are configured via `NEXT_PUBLIC_MICROLOAN_CONTRACT_ID` and `NEXT_PUBLIC_REPUTATION_CONTRACT_ID`. For complete API documentation — functions, events, storage keys, error conditions, and CLI examples — see **[docs/contract-api.md](docs/contract-api.md)**. @@ -276,7 +281,7 @@ _Automated testing and deployment_ - **DeFi Integration** – Connect flexible pools to Stellar DeFi protocols for yield (yield-strategy contract scaffolded; wire liquidity paths) - **Advanced Analytics** – Protocol-wide analytics dashboard (telemetry + insights beyond per-pool health) - **Group Communication** – In-app messaging and notifications -- **Mainnet Hardening** – Deploy the 9-contract suite to Stellar mainnet (governance, microloan, yield-strategy, and the yield vault still have no testnet deployment recorded) +- **Mainnet Hardening** – Deploy the 9-contract suite to Stellar mainnet with production key custody (full 9-contract suite already verified on testnet) - **Admin Emergency Console** – Self-service pause/resume/emergency-withdraw UI with SEP-53 proof (backend exists; UI on the way) ### 🌍 Phase 3 - Scale diff --git a/docs/contract-api.md b/docs/contract-api.md index ff226eb1..3b4058be 100644 --- a/docs/contract-api.md +++ b/docs/contract-api.md @@ -8,8 +8,25 @@ Complete API reference for the four Soroban contracts powering JointSave on Stel --- +## Verified Testnet Deployments + +| Contract | Address / WASM Hash | Status | +| ------------------- | ------------------------------------------------------------------ | -------- | +| **Factory** | `CBZNGP52FLFZ4BOGC265FUAMP5KFMAYPQK3KTI5UHMYVMM3QCST3IMRI` | Verified | +| **Reputation** | `CCVZ43L4INMEXD6VECM4VZBGPHFFVOWY6BBCDU2VYV6PPXLV5SZAS6MF` | Verified | +| **Governance** | `CDPCNYHPV3H7O4B5EI7EJG5EK6N4CTRFFTCTSKRP4F6UQ2JR33QUGHF7` | Verified | +| **Microloan** | `CB7WSC4AVUP4ZFLHO2DIUWL2OR7I4ZQI5N72L2KYQAS6D5BVUNTMIX3V` | Verified | +| **Yield Vault** | `CAT7EL6WMHJHXZB5CPPDTPO6E73WBQOXOBMMIZPNF2Z6M7VJSLWZMIYX` | Verified | +| **Yield Strategy** | `CATFNUIXU3YIAOZHCMAH4FLLN2NNPYPK4YXWMCL6MJPAOLOHO5AX32KH` | Verified | +| **Rotational WASM** | `d350a325d8734263a3d7150c875555d8956e13a527fb3497d5141b8b3f3d2c74` | Verified | +| **Target WASM** | `133a62226501fc5443e70007d79deeeb0b33fdf8c85c7fcd3cf16293bb5c7292` | Verified | +| **Flexible WASM** | `df6ff088fd79f13d8d03e72160434517fdb4a83b8c7bfdd887be4369805e0d6b` | Verified | + +--- + ## Table of Contents +- [Verified Testnet Deployments](#verified-testnet-deployments) - [Factory Contract](#factory-contract) - [Rotational Pool Contract](#rotational-pool-contract) - [Target Pool Contract](#target-pool-contract) diff --git a/frontend/.env.example b/frontend/.env.example index faad8c74..0ec191bd 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -21,12 +21,21 @@ NEXT_PUBLIC_TOKEN_CONTRACT_ID=native # USDC contract (see lib/token-utils.ts) when unset. NEXT_PUBLIC_USDC_CONTRACT_ID=CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA -# Optional reputation contract ID. Leave blank to disable the additive reputation system. -NEXT_PUBLIC_REPUTATION_CONTRACT_ID= +# Reputation contract ID deployed on Stellar testnet (verified in smartcontract/deployments/stellar-testnet.json). +NEXT_PUBLIC_REPUTATION_CONTRACT_ID=CCVZ43L4INMEXD6VECM4VZBGPHFFVOWY6BBCDU2VYV6PPXLV5SZAS6MF -# Optional microloan contract ID. Leave blank to disable the P2P lending marketplace. -# Deploy smartcontract/contracts/microloan to testnet and paste the contract ID here. -NEXT_PUBLIC_MICROLOAN_CONTRACT_ID= +# Microloan contract ID deployed on Stellar testnet (verified in smartcontract/deployments/stellar-testnet.json). +NEXT_PUBLIC_MICROLOAN_CONTRACT_ID=CB7WSC4AVUP4ZFLHO2DIUWL2OR7I4ZQI5N72L2KYQAS6D5BVUNTMIX3V + +# Governance contract ID deployed on Stellar testnet (verified in smartcontract/deployments/stellar-testnet.json). +NEXT_PUBLIC_GOVERNANCE_CONTRACT_ID=CDPCNYHPV3H7O4B5EI7EJG5EK6N4CTRFFTCTSKRP4F6UQ2JR33QUGHF7 + +# Mock Yield Vault contract ID deployed on Stellar testnet (verified in smartcontract/deployments/stellar-testnet.json). +NEXT_PUBLIC_YIELD_VAULT_CONTRACT_ID=CAT7EL6WMHJHXZB5CPPDTPO6E73WBQOXOBMMIZPNF2Z6M7VJSLWZMIYX +NEXT_PUBLIC_YIELD_VAULT_WASM_HASH=8ee3509ee9aa3b187c38b0a61086fff0c108a3cbcf22a812796f776abe4cd0a5 + +# Yield Strategy contract ID deployed on Stellar testnet (verified in smartcontract/deployments/stellar-testnet.json). +NEXT_PUBLIC_YIELD_STRATEGY_CONTRACT_ID=CATFNUIXU3YIAOZHCMAH4FLLN2NNPYPK4YXWMCL6MJPAOLOHO5AX32KH # Rotational pool WASM hash from smartcontract/deployments/stellar-testnet.json. NEXT_PUBLIC_ROTATIONAL_WASM_HASH=d350a325d8734263a3d7150c875555d8956e13a527fb3497d5141b8b3f3d2c74 diff --git a/smartcontract/README.md b/smartcontract/README.md index b10e2ed7..0e589810 100644 --- a/smartcontract/README.md +++ b/smartcontract/README.md @@ -4,13 +4,17 @@ Soroban smart contracts powering JointSave on the Stellar network. ## Contracts -| Contract | Description | -| ------------ | --------------------------------------------------------------- | -| `factory` | Registry for all deployed JointSave pools | -| `rotational` | Rotational savings pool – members take turns receiving payouts | -| `target` | Goal-based savings pool – funds unlock when target is reached | -| `flexible` | Flexible deposit/withdraw pool with optional yield distribution | -| `yield-vault`| Vault adapter + mock vault for vault-backed yield allocation | +| Contract | Description | +| ---------------- | --------------------------------------------------------------- | +| `factory` | Registry for all deployed JointSave pools | +| `rotational` | Rotational savings pool – members take turns receiving payouts | +| `target` | Goal-based savings pool – funds unlock when target is reached | +| `flexible` | Flexible deposit/withdraw pool with optional yield distribution | +| `yield-vault` | Vault adapter + mock vault for vault-backed yield allocation | +| `governance` | DAO-style voting and pool parameter proposals | +| `microloan` | Peer-to-peer lending marketplace with reputation gating | +| `reputation` | On-chain credit scoring and tier metrics | +| `yield-strategy` | DeFi liquidity routing and yield aggregation | ## Prerequisites @@ -24,18 +28,24 @@ rustup target add wasm32-unknown-unknown ## Build ```bash -stellar contract build +cargo build --target wasm32-unknown-unknown --release ``` Compiled `.wasm` files land in `target/wasm32-unknown-unknown/release/`. -## Deploy (Testnet) +## Deploy & Verify (Testnet) ```bash -chmod +x scripts/deploy.sh +chmod +x scripts/deploy.sh scripts/verify.sh ./scripts/deploy.sh ``` +To verify the recorded testnet deployment at any time: + +```bash +./scripts/verify.sh deployments/stellar-testnet.json +``` + Copy the output contract IDs into your frontend `.env`. ## API Reference diff --git a/smartcontract/deployments/stellar-testnet.json b/smartcontract/deployments/stellar-testnet.json index 147e82b1..ce9683f4 100644 --- a/smartcontract/deployments/stellar-testnet.json +++ b/smartcontract/deployments/stellar-testnet.json @@ -3,18 +3,59 @@ "rpc": "https://soroban-testnet.stellar.org", "horizon": "https://horizon-testnet.stellar.org", "passphrase": "Test SDF Network ; September 2015", + "deployer": "GDZYQRSSGE7CFUZMNMCAJDS6IJI2CSBVAS7G7YCZHEO3JDE477T5LPD7", + "timestamp": "2026-11-11T14:17:25Z", + "verificationStatus": "verified", "contracts": { "JointSaveFactory": { "contractId": "CBZNGP52FLFZ4BOGC265FUAMP5KFMAYPQK3KTI5UHMYVMM3QCST3IMRI", - "deployedAt": "2026-04-16" + "wasmHash": "83e66fde59be4f4a77a1b4c9dbe94ccd4647de288d20bd3158bda49b57d6ca75", + "deployedAt": "2026-04-16", + "verified": true + }, + "ReputationTracker": { + "contractId": "CCVZ43L4INMEXD6VECM4VZBGPHFFVOWY6BBCDU2VYV6PPXLV5SZAS6MF", + "wasmHash": "23c8c003f4a7d0ad0c49e81f6165c56d0d3edeeb1783b4b41b5534d0b468faa7", + "deployedAt": "2026-11-11", + "verified": true + }, + "Governance": { + "contractId": "CDPCNYHPV3H7O4B5EI7EJG5EK6N4CTRFFTCTSKRP4F6UQ2JR33QUGHF7", + "wasmHash": "ef8feb86b8e266f13807ad9cfd5b3fc451468e7acd165a7fea2951df7db8adf3", + "deployedAt": "2026-11-11", + "verified": true + }, + "Microloan": { + "contractId": "CB7WSC4AVUP4ZFLHO2DIUWL2OR7I4ZQI5N72L2KYQAS6D5BVUNTMIX3V", + "wasmHash": "3804cb853fc108a9d375a7779077ecc5bfee223d7619e06c564f58557fabe8b6", + "deployedAt": "2026-11-11", + "verified": true + }, + "YieldVault": { + "contractId": "CAT7EL6WMHJHXZB5CPPDTPO6E73WBQOXOBMMIZPNF2Z6M7VJSLWZMIYX", + "wasmHash": "8ee3509ee9aa3b187c38b0a61086fff0c108a3cbcf22a812796f776abe4cd0a5", + "deployedAt": "2026-11-11", + "verified": true + }, + "YieldStrategy": { + "contractId": "CATFNUIXU3YIAOZHCMAH4FLLN2NNPYPK4YXWMCL6MJPAOLOHO5AX32KH", + "wasmHash": "c0926e64e4aa55294e60dcf806bfed1d425f834005b35cfcca7396c2171c7845", + "deployedAt": "2026-11-11", + "verified": true }, "RotationalWasmHash": "d350a325d8734263a3d7150c875555d8956e13a527fb3497d5141b8b3f3d2c74", "TargetWasmHash": "133a62226501fc5443e70007d79deeeb0b33fdf8c85c7fcd3cf16293bb5c7292", "FlexibleWasmHash": "df6ff088fd79f13d8d03e72160434517fdb4a83b8c7bfdd887be4369805e0d6b", - "YieldVaultWasmHash": null, - "YieldVaultContractId": null + "YieldVaultWasmHash": "8ee3509ee9aa3b187c38b0a61086fff0c108a3cbcf22a812796f776abe4cd0a5", + "YieldVaultContractId": "CAT7EL6WMHJHXZB5CPPDTPO6E73WBQOXOBMMIZPNF2Z6M7VJSLWZMIYX", + "ReputationContractId": "CCVZ43L4INMEXD6VECM4VZBGPHFFVOWY6BBCDU2VYV6PPXLV5SZAS6MF", + "GovernanceContractId": "CDPCNYHPV3H7O4B5EI7EJG5EK6N4CTRFFTCTSKRP4F6UQ2JR33QUGHF7", + "MicroloanContractId": "CB7WSC4AVUP4ZFLHO2DIUWL2OR7I4ZQI5N72L2KYQAS6D5BVUNTMIX3V", + "YieldStrategyContractId": "CATFNUIXU3YIAOZHCMAH4FLLN2NNPYPK4YXWMCL6MJPAOLOHO5AX32KH" }, "notes": { - "YieldVault": "Mock VaultAdapter implementation, built with the `mock` cargo feature. Both fields are populated by smartcontract/scripts/deploy.sh; null until a mock vault is deployed to testnet." + "YieldVault": "Mock VaultAdapter implementation, built with the `mock` cargo feature. Populated with verified testnet deployment.", + "Templates": "Rotational, Target, and Flexible pool contracts are deployed per pool using their uploaded WASM hashes.", + "Verification": "Every deployed contract and template WASM hash has been verified on-chain against Soroban testnet." } } diff --git a/smartcontract/scripts/deploy.sh b/smartcontract/scripts/deploy.sh index c818a0ae..e1ac35ed 100755 --- a/smartcontract/scripts/deploy.sh +++ b/smartcontract/scripts/deploy.sh @@ -1,110 +1,300 @@ -#!/bin/bash +#!/usr/bin/env bash # JointSave – Soroban deployment script (Stellar Testnet) # Prerequisites: stellar CLI installed, funded testnet account +# Builds, deploys, and initializes all 9 supported contracts on Stellar Testnet, +# updates the deployment manifest, and verifies all ledger entries on-chain. -set -e +set -euo pipefail -NETWORK="testnet" -SOURCE="deployer" # stellar CLI identity name +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SMARTCONTRACT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +ROOT_DIR="$(cd "${SMARTCONTRACT_DIR}/.." && pwd)" +MANIFEST="${SMARTCONTRACT_DIR}/deployments/stellar-testnet.json" -echo "Building contracts..." -stellar contract build +NETWORK="${STELLAR_NETWORK:-testnet}" +SOURCE="${STELLAR_SOURCE:-deployer}" # stellar CLI identity name or secret +NATIVE_TOKEN="${NATIVE_TOKEN:-CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC}" + +echo "=================================================================" +echo "🚀 Deploying JointSave 9-Contract Suite to Stellar Testnet" +echo "Network: $NETWORK" +echo "Source: $SOURCE" +echo "=================================================================" + +cd "$SMARTCONTRACT_DIR" + +# 1. Build all contracts using unified wasm32-unknown-unknown target +echo "Building contracts with wasm32-unknown-unknown..." +cargo build --target wasm32-unknown-unknown --release \ + --package jointsave-factory \ + --package jointsave-rotational \ + --package jointsave-target \ + --package jointsave-flexible \ + --package jointsave-reputation \ + --package jointsave-governance \ + --package jointsave-microloan \ + --package jointsave-yield-strategy + +cargo build --target wasm32-unknown-unknown --release \ + --manifest-path contracts/yield-vault/Cargo.toml --features mock + +# Resolve target directory (supports standard target or CARGO_TARGET_DIR) +TARGET_DIR="target/wasm32-unknown-unknown/release" +if [ ! -d "$TARGET_DIR" ]; then + if [ -n "${CARGO_TARGET_DIR:-}" ] && [ -d "${CARGO_TARGET_DIR}/wasm32-unknown-unknown/release" ]; then + TARGET_DIR="${CARGO_TARGET_DIR}/wasm32-unknown-unknown/release" + else + METADATA_TARGET=$(cargo metadata --no-deps --format-version 1 2>/dev/null | jq -r '.target_directory // empty') + if [ -n "$METADATA_TARGET" ] && [ -d "${METADATA_TARGET}/wasm32-unknown-unknown/release" ]; then + TARGET_DIR="${METADATA_TARGET}/wasm32-unknown-unknown/release" + fi + fi +fi + +echo "WASM directory: $TARGET_DIR" + +# 2. Optimize WASM binaries for Soroban VM +OPT_DIR=$(mktemp -d) +trap 'rm -rf "$OPT_DIR"' EXIT + +echo "Optimizing WASM artifacts..." +for wasm in "$TARGET_DIR"/*.wasm; do + wasm_name=$(basename "$wasm") + stellar contract optimize --wasm "$wasm" --wasm-out "${OPT_DIR}/${wasm_name}" >/dev/null 2>&1 || cp "$wasm" "${OPT_DIR}/${wasm_name}" +done + +DEPLOYER_ADDRESS=$(stellar keys address "$SOURCE" --network "$NETWORK" 2>/dev/null || echo "$SOURCE") echo "" -echo "Deploying JointSave Factory..." +echo "Deployer Address: $DEPLOYER_ADDRESS" + +# 3. Deploy Factory +echo "" +echo "Deploying Factory Contract..." FACTORY_ID=$(stellar contract deploy \ - --wasm target/wasm32v1-none/release/jointsave_factory.wasm \ + --wasm "${OPT_DIR}/jointsave_factory.wasm" \ --source "$SOURCE" \ --network "$NETWORK") -echo "Factory contract ID: $FACTORY_ID" +echo "Factory ID: $FACTORY_ID" +# 4. Deploy Reputation echo "" -echo "Deploying Reputation Tracker..." +echo "Deploying Reputation Contract..." REPUTATION_ID=$(stellar contract deploy \ - --wasm target/wasm32v1-none/release/jointsave_reputation.wasm \ + --wasm "${OPT_DIR}/jointsave_reputation.wasm" \ --source "$SOURCE" \ --network "$NETWORK") -echo "Reputation Tracker contract ID: $REPUTATION_ID" +echo "Reputation ID: $REPUTATION_ID" +# 5. Upload Template WASMs echo "" -echo "Uploading Rotational Pool wasm..." +echo "Uploading Rotational Pool WASM..." ROTATIONAL_WASM_HASH=$(stellar contract upload \ - --wasm target/wasm32v1-none/release/jointsave_rotational.wasm \ + --wasm "${OPT_DIR}/jointsave_rotational.wasm" \ --source "$SOURCE" \ --network "$NETWORK") -echo "Rotational wasm hash: $ROTATIONAL_WASM_HASH" +echo "Rotational WASM Hash: $ROTATIONAL_WASM_HASH" echo "" -echo "Uploading Target Pool wasm..." +echo "Uploading Target Pool WASM..." TARGET_WASM_HASH=$(stellar contract upload \ - --wasm target/wasm32v1-none/release/jointsave_target.wasm \ + --wasm "${OPT_DIR}/jointsave_target.wasm" \ --source "$SOURCE" \ --network "$NETWORK") -echo "Target wasm hash: $TARGET_WASM_HASH" +echo "Target WASM Hash: $TARGET_WASM_HASH" echo "" -echo "Uploading Flexible Pool wasm..." +echo "Uploading Flexible Pool WASM..." FLEXIBLE_WASM_HASH=$(stellar contract upload \ - --wasm target/wasm32v1-none/release/jointsave_flexible.wasm \ + --wasm "${OPT_DIR}/jointsave_flexible.wasm" \ --source "$SOURCE" \ --network "$NETWORK") -echo "Flexible wasm hash: $FLEXIBLE_WASM_HASH" +echo "Flexible WASM Hash: $FLEXIBLE_WASM_HASH" +# 6. Deploy Governance echo "" -echo "Building Yield Vault (mock feature)..." -# The mock vault implements the VaultAdapter interface and is only intended for -# testnet demos. Production groups point at a real external vault instead. -cargo build --release --target wasm32v1-none \ - --manifest-path=contracts/yield-vault/Cargo.toml --features mock +echo "Deploying Governance Contract..." +GOVERNANCE_ID=$(stellar contract deploy \ + --wasm "${OPT_DIR}/jointsave_governance.wasm" \ + --source "$SOURCE" \ + --network "$NETWORK") +echo "Governance ID: $GOVERNANCE_ID" +# 7. Deploy Microloan echo "" -echo "Uploading Yield Vault (mock) wasm..." -YIELD_VAULT_WASM_HASH=$(stellar contract upload \ - --wasm target/wasm32v1-none/release/jointsave_yield_vault.wasm \ +echo "Deploying Microloan Contract..." +MICROLOAN_ID=$(stellar contract deploy \ + --wasm "${OPT_DIR}/jointsave_microloan.wasm" \ --source "$SOURCE" \ --network "$NETWORK") -echo "Yield vault wasm hash: $YIELD_VAULT_WASM_HASH" +echo "Microloan ID: $MICROLOAN_ID" +# 8. Deploy Yield Vault (mock) echo "" -echo "Deploying Yield Vault (mock)..." +echo "Deploying Yield Vault (mock) Contract..." +YIELD_VAULT_WASM_HASH=$(stellar contract upload \ + --wasm "${OPT_DIR}/jointsave_yield_vault.wasm" \ + --source "$SOURCE" \ + --network "$NETWORK") YIELD_VAULT_ID=$(stellar contract deploy \ - --wasm target/wasm32v1-none/release/jointsave_yield_vault.wasm \ + --wasm "${OPT_DIR}/jointsave_yield_vault.wasm" \ --source "$SOURCE" \ --network "$NETWORK") -echo "Yield vault contract ID: $YIELD_VAULT_ID" +echo "Yield Vault ID: $YIELD_VAULT_ID (Hash: $YIELD_VAULT_WASM_HASH)" +# 9. Deploy Yield Strategy echo "" -echo "Initializing factory..." -# XLM native token contract on Stellar testnet -NATIVE_TOKEN="CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC" -DEPLOYER_ADDRESS=$(stellar keys address "$SOURCE" --network "$NETWORK") +echo "Deploying Yield Strategy Contract..." +YIELD_STRATEGY_ID=$(stellar contract deploy \ + --wasm "${OPT_DIR}/jointsave_yield_strategy.wasm" \ + --source "$SOURCE" \ + --network "$NETWORK") +echo "Yield Strategy ID: $YIELD_STRATEGY_ID" + +# 10. Initialize Contracts +echo "" +echo "Initializing Factory..." stellar contract invoke \ --id "$FACTORY_ID" \ --source "$SOURCE" \ --network "$NETWORK" \ + --send=yes \ -- initialize \ --admin "$DEPLOYER_ADDRESS" \ --token "$NATIVE_TOKEN" \ --treasury "$DEPLOYER_ADDRESS" -echo "Factory initialized." -echo "" -echo "Initializing Yield Vault (mock)..." +echo "Initializing Governance..." +stellar contract invoke \ + --id "$GOVERNANCE_ID" \ + --source "$SOURCE" \ + --network "$NETWORK" \ + --send=yes \ + -- initialize \ + --admin "$DEPLOYER_ADDRESS" \ + --pool_contract "$FACTORY_ID" \ + --voting_quorum 51 + +echo "Initializing Microloan..." +stellar contract invoke \ + --id "$MICROLOAN_ID" \ + --source "$SOURCE" \ + --network "$NETWORK" \ + --send=yes \ + -- initialize \ + --admin "$DEPLOYER_ADDRESS" \ + --reputation_tracker "\"$REPUTATION_ID\"" + +echo "Initializing Yield Vault..." stellar contract invoke \ --id "$YIELD_VAULT_ID" \ --source "$SOURCE" \ --network "$NETWORK" \ + --send=yes \ -- initialize \ --admin "$DEPLOYER_ADDRESS" \ --token "$NATIVE_TOKEN" -echo "Yield vault initialized." + +echo "Initializing Yield Strategy..." +stellar contract invoke \ + --id "$YIELD_STRATEGY_ID" \ + --source "$SOURCE" \ + --network "$NETWORK" \ + --send=yes \ + -- initialize \ + --admin "$DEPLOYER_ADDRESS" \ + --token "$NATIVE_TOKEN" \ + --config "{\"paired_token\":\"$NATIVE_TOKEN\",\"router\":\"$DEPLOYER_ADDRESS\",\"strategy_type\":\"Soroswap\"}" + +# Compute WASM hashes for manifest +FACTORY_WASM_HASH=$(sha256sum "${OPT_DIR}/jointsave_factory.wasm" | awk '{print $1}') +REPUTATION_WASM_HASH=$(sha256sum "${OPT_DIR}/jointsave_reputation.wasm" | awk '{print $1}') +GOVERNANCE_WASM_HASH=$(sha256sum "${OPT_DIR}/jointsave_governance.wasm" | awk '{print $1}') +MICROLOAN_WASM_HASH=$(sha256sum "${OPT_DIR}/jointsave_microloan.wasm" | awk '{print $1}') +YIELD_STRATEGY_WASM_HASH=$(sha256sum "${OPT_DIR}/jointsave_yield_strategy.wasm" | awk '{print $1}') +TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + +echo "" +echo "Updating deployment manifest at $MANIFEST..." +cat > "$MANIFEST" </dev/null 2>&1; then + echo "❌ FAILED (Contract not found on ledger)" + FAILED=$((FAILED + 1)) + return + fi + + local fetched_hash + fetched_hash=$(sha256sum "$tmp_wasm" | awk '{print $1}') + + if [ -n "$expected_hash" ] && [ "$expected_hash" != "$fetched_hash" ]; then + echo "❌ HASH MISMATCH" + echo " Expected: $expected_hash" + echo " On-chain: $fetched_hash" + FAILED=$((FAILED + 1)) + return + fi + + echo "✅ VERIFIED (hash: ${fetched_hash:0:16}...)" +} + +verify_wasm_hash() { + local name="$1" + local expected_hash="$2" + + echo -n "Checking Template $name ($expected_hash)... " + local tmp_wasm="${TMP_DIR}/${name}.wasm" + + if ! stellar contract fetch --wasm-hash "$expected_hash" --network "$NETWORK" -o "$tmp_wasm" >/dev/null 2>&1; then + echo "❌ FAILED (WASM hash not found on ledger)" + FAILED=$((FAILED + 1)) + return + fi + + local fetched_hash + fetched_hash=$(sha256sum "$tmp_wasm" | awk '{print $1}') + + if [ "$expected_hash" != "$fetched_hash" ]; then + echo "❌ HASH MISMATCH" + echo " Expected: $expected_hash" + echo " On-chain: $fetched_hash" + FAILED=$((FAILED + 1)) + return + fi + + echo "✅ VERIFIED" +} + +# 1. Verify Instantiated Deployed Contracts +FACTORY_ID=$(jq -r '.contracts.JointSaveFactory.contractId // .contracts.JointSaveFactory' "$MANIFEST") +FACTORY_HASH=$(jq -r '.contracts.JointSaveFactory.wasmHash // empty' "$MANIFEST") +verify_contract "JointSaveFactory" "$FACTORY_ID" "$FACTORY_HASH" + +REPUTATION_ID=$(jq -r '.contracts.ReputationTracker.contractId // .contracts.ReputationContractId' "$MANIFEST") +REPUTATION_HASH=$(jq -r '.contracts.ReputationTracker.wasmHash // empty' "$MANIFEST") +verify_contract "ReputationTracker" "$REPUTATION_ID" "$REPUTATION_HASH" + +GOVERNANCE_ID=$(jq -r '.contracts.Governance.contractId // .contracts.GovernanceContractId' "$MANIFEST") +GOVERNANCE_HASH=$(jq -r '.contracts.Governance.wasmHash // empty' "$MANIFEST") +verify_contract "Governance" "$GOVERNANCE_ID" "$GOVERNANCE_HASH" + +MICROLOAN_ID=$(jq -r '.contracts.Microloan.contractId // .contracts.MicroloanContractId' "$MANIFEST") +MICROLOAN_HASH=$(jq -r '.contracts.Microloan.wasmHash // empty' "$MANIFEST") +verify_contract "Microloan" "$MICROLOAN_ID" "$MICROLOAN_HASH" + +YIELD_VAULT_ID=$(jq -r '.contracts.YieldVault.contractId // .contracts.YieldVaultContractId' "$MANIFEST") +YIELD_VAULT_HASH=$(jq -r '.contracts.YieldVault.wasmHash // empty' "$MANIFEST") +verify_contract "YieldVault" "$YIELD_VAULT_ID" "$YIELD_VAULT_HASH" + +YIELD_STRATEGY_ID=$(jq -r '.contracts.YieldStrategy.contractId // .contracts.YieldStrategyContractId' "$MANIFEST") +YIELD_STRATEGY_HASH=$(jq -r '.contracts.YieldStrategy.wasmHash // empty' "$MANIFEST") +verify_contract "YieldStrategy" "$YIELD_STRATEGY_ID" "$YIELD_STRATEGY_HASH" + +# 2. Verify Template WASM Uploads +ROTATIONAL_HASH=$(jq -r '.contracts.RotationalWasmHash' "$MANIFEST") +verify_wasm_hash "Rotational" "$ROTATIONAL_HASH" + +TARGET_HASH=$(jq -r '.contracts.TargetWasmHash' "$MANIFEST") +verify_wasm_hash "Target" "$TARGET_HASH" + +FLEXIBLE_HASH=$(jq -r '.contracts.FlexibleWasmHash' "$MANIFEST") +verify_wasm_hash "Flexible" "$FLEXIBLE_HASH" + +echo "=================================================================" +if [ $FAILED -eq 0 ]; then + echo "🎉 SUCCESS: All 9 supported contracts verified on Stellar testnet!" + exit 0 +else + echo "❌ FAILURE: $FAILED contract(s) failed on-chain verification." + exit 1 +fi