From c7bc73ff27fb197f94d1fcc577bc262b9dd5e0f5 Mon Sep 17 00:00:00 2001 From: aguilar1x Date: Mon, 22 Jun 2026 19:31:00 -0600 Subject: [PATCH 1/3] chore: release vc-vault v0.4.0, vc-vault-factory v0.1.0, did-stellar-registry v0.2.0 to testnet Bumps vc-vault 0.3.0->0.4.0 (single-tenant rearchitecture + open issuance + fees in factory), did-stellar-registry 0.1.0->0.2.0 (key reuse across relationships, duplicate service id_suffix rejection, admin-role spec), first release of vc-vault-factory 0.1.0. Adds factory build/deploy support to scripts and the new template-install deploy model (vaults are instantiated by the factory). Testnet deploys: did-stellar-registry CBUNQ3GX3ZQ4MF64H7JCYZMXLGOS47VPIQQS7NCR6V3KX6YP7O72L5QF; vc-vault-factory CBTNMBRD3TSGLPEZRD226U5LR7G3RWOYHCILAUEMRZAP7AHUZJ7CP4AB; vc-vault v0.4.0 template hash 576b4c7b3d5aeafb9610bc569f45e1a007d2eff92855938a0bf933e657558ef9. --- README.md | 2 +- contracts/did-stellar-registry/Cargo.toml | 2 +- contracts/vc-vault/Cargo.toml | 2 +- docs/deployments/testnet.md | 17 +++- scripts/build.sh | 18 +++- scripts/deploy.sh | 109 +++++++++++++--------- 6 files changed, 99 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 26e6586..20a67cb 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Soroban smart contracts for the ACTA identity and Verifiable Credential infrastructure on Stellar. -**Latest release:** [vc-vault v0.3.0](https://github.com/ACTA-Team/contracts-acta/releases/tag/vc-vault-v0.3.0) +**Latest release:** [vc-vault v0.4.0](https://github.com/ACTA-Team/contracts-acta/releases/tag/vc-vault-v0.4.0) --- diff --git a/contracts/did-stellar-registry/Cargo.toml b/contracts/did-stellar-registry/Cargo.toml index 476970d..d44856a 100644 --- a/contracts/did-stellar-registry/Cargo.toml +++ b/contracts/did-stellar-registry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "did-stellar-registry" -version = "0.1.0" +version = "0.2.0" edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/contracts/vc-vault/Cargo.toml b/contracts/vc-vault/Cargo.toml index f9cc6ce..7e61a66 100644 --- a/contracts/vc-vault/Cargo.toml +++ b/contracts/vc-vault/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vc-vault-contract" -version = "0.3.0" +version = "0.4.0" edition = { workspace = true } license = { workspace = true } repository = { workspace = true } diff --git a/docs/deployments/testnet.md b/docs/deployments/testnet.md index 3229eea..f1ac9d2 100644 --- a/docs/deployments/testnet.md +++ b/docs/deployments/testnet.md @@ -10,11 +10,24 @@ RPC: `https://soroban-testnet.stellar.org:443` | Version | Contract ID | Date | Notes | |---|---|---|---| | 0.1.0 | `CB7ATU7SF5QUKJMSULJDJVWJZVDXC23HTZX6NFUDTSFPVT6MA575NNZJ` | 2026-05-06 | Tranche 1 initial deploy | +| 0.2.0 | `CBUNQ3GX3ZQ4MF64H7JCYZMXLGOS47VPIQQS7NCR6V3KX6YP7O72L5QF` | 2026-06-22 | Allow key reuse across verification relationships; reject duplicate service `id_suffix`; admin-role spec; clippy. WASM hash `6835c23806075288284c89e133b271a3ac9c61977fbe49121f92c5431f29a0e7`. | -## vc-vault +## vc-vault-factory | Version | Contract ID | Date | Notes | |---|---|---|---| -| 0.1.0 | `CC3SQ7UTAQQDQF6PUQMQIGK3BMPB22OKMHE5Y5XELEX3JFAKC72SQOAM` | 2026-05-06 | Tranche 1 initial deploy | +| 0.1.0 | `CBTNMBRD3TSGLPEZRD226U5LR7G3RWOYHCILAUEMRZAP7AHUZJ7CP4AB` | 2026-06-22 | First release. Deploys single-tenant vaults (deterministic address from `keccak(salt‖XDR(owner))`), centralizes fee config, `is_vault` registry. Constructed with vault template WASM hash `576b4c7b3d5aeafb9610bc569f45e1a007d2eff92855938a0bf933e657558ef9`. WASM hash `f94a77905d87f9a195ea837414b4995c7d3d66bed0e287481710246bc1d5bdcd`. | + +## vc-vault + +Since v0.4.0 the vault is **single-tenant** and is no longer deployed standalone — +individual vaults are instantiated by `vc-vault-factory.deploy(...)`. The release +publishes the vault as an installed WASM **template**; the factory is constructed +with its hash. + +| Version | Contract ID / WASM hash | Date | Notes | +|---|---|---|---| +| 0.1.0 | `CC3SQ7UTAQQDQF6PUQMQIGK3BMPB22OKMHE5Y5XELEX3JFAKC72SQOAM` | 2026-05-06 | Tranche 1 initial deploy (multi-tenant). | | 0.2.0 | `CBXC6LXBY5FGEG46VZ4AJ2AH2EJBINBA7BMILIEO4EJYI6ZTY7K7J5D5` | 2026-05-07 | SOW D2: O(1) index + pagination + migrate + batch_issue. WASM hash `c8da61dd3dd46b2810a743d50a388c09a00f0b7e8e2df7ceb5a71c8ce5dc4dd8`. | | 0.3.0 | `CATL4IDH7XXPDC2UHSEX2GP45PPBVDFSKUDTKCSQICDOJVDLYNKISXFH` | 2026-05-14 | Refactoring: constructor, types rename, push_vc extraction, input caps, event emissions, O(1) issuer storage, tombstone TTL fix. WASM hash `775a141520de56fb4b1ebeb55d63e49fadf03f467ea8444cddb2caed2756ca8c`. | +| 0.4.0 | WASM hash `576b4c7b3d5aeafb9610bc569f45e1a007d2eff92855938a0bf933e657558ef9` (template; deployed via factory) | 2026-06-22 | Single-tenant rearchitecture + open issuance (deny-by-exception) + fees moved to factory. Installed as a template; instances created by `vc-vault-factory` `CBTNMBRD3TSGLPEZRD226U5LR7G3RWOYHCILAUEMRZAP7AHUZJ7CP4AB`. | diff --git a/scripts/build.sh b/scripts/build.sh index 27fd399..13b4f72 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -35,16 +35,30 @@ build_did_registry() { echo "Built: target/wasm32v1-none/release/did_stellar_registry.optimized.wasm" } +# vc-vault-factory already declares cdylib so a standard cargo build suffices. +build_factory() { + cargo build \ + -p vc-vault-factory-contract \ + --target wasm32v1-none \ + --release + stellar contract optimize \ + --wasm target/wasm32v1-none/release/vc_vault_factory_contract.wasm + echo "Built: target/wasm32v1-none/release/vc_vault_factory_contract.optimized.wasm" +} + case "$PACKAGE" in vc-vault) build_vc_vault ;; did-stellar-registry) build_did_registry ;; + vc-vault-factory) + build_factory ;; all) build_vc_vault - build_did_registry ;; + build_did_registry + build_factory ;; *) echo "Unknown package: $PACKAGE" >&2 - echo "Usage: $0 [vc-vault|did-stellar-registry|all]" >&2 + echo "Usage: $0 [vc-vault|did-stellar-registry|vc-vault-factory|all]" >&2 exit 1 ;; esac diff --git a/scripts/deploy.sh b/scripts/deploy.sh index ce8b683..835b148 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -6,24 +6,28 @@ set -eu # Usage: # ./scripts/deploy.sh # -# package: vc-vault | did-stellar-registry +# package: did-stellar-registry | vc-vault | vc-vault-factory # network: testnet | mainnet # source-account: stellar keys alias (e.g. acta_deployer) # +# Deployment model (since vc-vault v0.4.0): +# - did-stellar-registry: deployed standalone (constructor: --admin). +# - vc-vault: single-tenant TEMPLATE — not deployed standalone. Its WASM is +# installed (uploaded) and the resulting hash is handed to the factory. +# Individual vaults are created by calling vc-vault-factory.deploy(...). +# - vc-vault-factory: deployed with the vault template hash + a contract admin. +# # Examples: # ./scripts/deploy.sh did-stellar-registry testnet acta_deployer -# ./scripts/deploy.sh vc-vault testnet acta_deployer +# ./scripts/deploy.sh vc-vault testnet acta_deployer # install template +# ./scripts/deploy.sh vc-vault-factory testnet acta_deployer # installs vault + deploys factory +# +# Env overrides: +# DID_ADMIN / FACTORY_ADMIN — admin address (defaults to the source address) +# VAULT_HASH — reuse a pre-installed vc-vault template hash # -# Prerequisites: -# - stellar-cli installed and configured -# - Network already added: -# stellar config network add testnet \ -# --rpc-url https://soroban-testnet.stellar.org:443 \ -# --network-passphrase "Test SDF Network ; September 2015" -# - Source account key generated: -# stellar keys generate acta_deployer --network -# - WASM built: -# ./scripts/build.sh +# Prerequisites: stellar-cli configured, network added, source key funded, and +# ./scripts/build.sh run first. PACKAGE=${1:-} NETWORK=${2:-} @@ -31,49 +35,66 @@ SOURCE=${3:-} if [ -z "$PACKAGE" ] || [ -z "$NETWORK" ] || [ -z "$SOURCE" ]; then echo "Usage: $0 " >&2 - echo " package: vc-vault | did-stellar-registry" >&2 + echo " package: did-stellar-registry | vc-vault | vc-vault-factory" >&2 echo " network: testnet | mainnet" >&2 exit 1 fi +REL="target/wasm32v1-none/release" +VAULT_WASM="$REL/vc_vault_contract.optimized.wasm" +FACTORY_WASM="$REL/vc_vault_factory_contract.optimized.wasm" +DID_WASM="$REL/did_stellar_registry.optimized.wasm" + +require_wasm() { + if [ ! -f "$1" ]; then + echo "WASM not found: $1" >&2 + echo "Run: ./scripts/build.sh $2" >&2 + exit 1 + fi +} + case "$PACKAGE" in - vc-vault) - WASM="target/wasm32v1-none/release/vc_vault_contract.optimized.wasm" - ADMIN=${VC_ADMIN:-$(stellar keys address "$SOURCE")} - CONSTRUCTOR_ARGS="-- --contract_admin $ADMIN" - ;; did-stellar-registry) - WASM="target/wasm32v1-none/release/did_stellar_registry.optimized.wasm" - # Requires an admin address at construction. - # Defaults to the deployer address; override by setting DID_ADMIN env var. + require_wasm "$DID_WASM" did-stellar-registry ADMIN=${DID_ADMIN:-$(stellar keys address "$SOURCE")} - CONSTRUCTOR_ARGS="-- --admin $ADMIN" + echo "Deploying did-stellar-registry to $NETWORK (admin $ADMIN)..." + CONTRACT_ID=$(stellar contract deploy \ + --wasm "$DID_WASM" --source "$SOURCE" --network "$NETWORK" \ + -- --admin "$ADMIN") + echo "" + echo "Contract ID: $CONTRACT_ID" ;; + + vc-vault) + require_wasm "$VAULT_WASM" vc-vault + echo "Installing vc-vault template WASM on $NETWORK..." + HASH=$(stellar contract upload \ + --wasm "$VAULT_WASM" --source "$SOURCE" --network "$NETWORK") + echo "" + echo "vc-vault template WASM hash: $HASH" + echo "Pass this to the factory (VAULT_HASH=$HASH ./scripts/deploy.sh vc-vault-factory ...)." + ;; + + vc-vault-factory) + require_wasm "$VAULT_WASM" vc-vault + require_wasm "$FACTORY_WASM" vc-vault-factory + ADMIN=${FACTORY_ADMIN:-$(stellar keys address "$SOURCE")} + VAULT_HASH=${VAULT_HASH:-$(stellar contract upload \ + --wasm "$VAULT_WASM" --source "$SOURCE" --network "$NETWORK")} + echo "Deploying vc-vault-factory to $NETWORK (admin $ADMIN, vault_hash $VAULT_HASH)..." + CONTRACT_ID=$(stellar contract deploy \ + --wasm "$FACTORY_WASM" --source "$SOURCE" --network "$NETWORK" \ + -- --vault_init_meta "{\"vault_hash\":\"$VAULT_HASH\",\"contract_admin\":\"$ADMIN\"}") + echo "" + echo "Factory Contract ID: $CONTRACT_ID" + echo "Vault template hash: $VAULT_HASH" + ;; + *) echo "Unknown package: $PACKAGE" >&2 - echo " package: vc-vault | did-stellar-registry" >&2 + echo " package: did-stellar-registry | vc-vault | vc-vault-factory" >&2 exit 1 ;; esac -if [ ! -f "$WASM" ]; then - echo "WASM not found: $WASM" >&2 - echo "Run: ./scripts/build.sh $PACKAGE" >&2 - exit 1 -fi - -echo "Deploying $PACKAGE to $NETWORK..." -echo " WASM: $WASM" -echo " Source: $SOURCE" - -CONTRACT_ID=$(stellar contract deploy \ - --wasm "$WASM" \ - --source "$SOURCE" \ - --network "$NETWORK" \ - $CONSTRUCTOR_ARGS) - -echo "" -echo "Contract ID: $CONTRACT_ID" -echo "" -echo "Add this entry to docs/deployments/$NETWORK.md:" echo "" -echo "| $PACKAGE | $(date +%Y-%m-%d) | \`$CONTRACT_ID\` | $NETWORK |" +echo "Record the result in docs/deployments/$NETWORK.md" From c36648eed5b4a0c654154ee44473e0d8235b9de6 Mon Sep 17 00:00:00 2001 From: aguilar1x Date: Mon, 22 Jun 2026 19:47:24 -0600 Subject: [PATCH 2/3] feat: remove vault upgrade entrypoint for immutable code Removes the contract-admin-gated upgrade() from vc-vault (and its ContractUpgraded event). The vault is now immutable: no single-key authority can replace its WASM. Redeployed the v0.4.0 testnet template + factory accordingly. --- README.md | 2 +- contracts/vc-vault/README.md | 1 - contracts/vc-vault/src/contract.rs | 9 +-------- contracts/vc-vault/src/events.rs | 14 +------------- contracts/vc-vault/src/interface.rs | 3 +-- docs/deployments/testnet.md | 4 ++-- 6 files changed, 6 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 20a67cb..cb5e5df 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Per-holder vault for Verifiable Credentials on Stellar. Manages VC storage, issu | Category | Functions | |---|---| -| Admin | `nominate_admin`, `accept_contract_admin`, `upgrade`, `version`, `fee_*` | +| Admin | `nominate_admin`, `accept_contract_admin`, `version` | | Vault | `create_vault`, `create_sponsored_vault`, `set_vault_admin`, `authorize_issuer`, `authorize_issuers`, `revoke_issuer`, `revoke_vault`, `list_authorized_issuers`, `list_denied_issuers`, `authorized_issuer_count`, `denied_issuer_count` | | Credentials | `issue`, `batch_issue`, `issue_linked`, `revoke`, `verify_vc`, `get_vc`, `list_vc_ids`, `vc_count`, `push` | diff --git a/contracts/vc-vault/README.md b/contracts/vc-vault/README.md index cbdf244..0bb0311 100644 --- a/contracts/vc-vault/README.md +++ b/contracts/vc-vault/README.md @@ -20,7 +20,6 @@ The contract admin is set atomically at deploy time via Soroban's `__constructor |---|---|---| | `nominate_admin(new_admin)` | `contract_admin` | Propose a new contract admin. Must be accepted by the nominee. | | `accept_contract_admin()` | pending nominee | Complete the two-step admin transfer. Fails with `NoPendingAdmin` if no nomination exists. | -| `upgrade(new_wasm_hash)` | `contract_admin` | Replace the contract WASM. Irreversible per-invocation. | | `version()` | none | Returns the crate version string (from `CARGO_PKG_VERSION`). | ### Fee configuration diff --git a/contracts/vc-vault/src/contract.rs b/contracts/vc-vault/src/contract.rs index 03c9fda..fa16c89 100644 --- a/contracts/vc-vault/src/contract.rs +++ b/contracts/vc-vault/src/contract.rs @@ -8,7 +8,7 @@ use crate::storage; use crate::validator::*; use crate::vault; use soroban_sdk::{ - contract, contractimpl, contractmeta, panic_with_error, symbol_short, Address, BytesN, Env, + contract, contractimpl, contractmeta, panic_with_error, symbol_short, Address, Env, IntoVal, String, Vec, }; @@ -63,13 +63,6 @@ impl VcVaultTrait for VcVaultContract { events::admin_transferred(&e, &old_admin, &pending); } - fn upgrade(e: Env, new_wasm_hash: BytesN<32>) { - require_contract_admin(&e); - storage::extend_instance_ttl(&e); - events::contract_upgraded(&e, &new_wasm_hash); - e.deployer().update_current_contract_wasm(new_wasm_hash); - } - fn version(e: Env) -> String { String::from_str(&e, VERSION) } diff --git a/contracts/vc-vault/src/events.rs b/contracts/vc-vault/src/events.rs index 16100dd..d211d93 100644 --- a/contracts/vc-vault/src/events.rs +++ b/contracts/vc-vault/src/events.rs @@ -1,6 +1,6 @@ //! Contract events. Published on key state transitions for on-chain observability. -use soroban_sdk::{contractevent, Address, BytesN, Env, String}; +use soroban_sdk::{contractevent, Address, Env, String}; // --- Vault lifecycle --- @@ -75,11 +75,6 @@ pub struct AdminTransferred { pub new_admin: Address, } -#[contractevent] -pub struct ContractUpgraded { - pub new_wasm_hash: BytesN<32>, -} - // --- Publishers --- pub fn vault_created(e: &Env, owner: &Address, did_uri: &String) { @@ -169,10 +164,3 @@ pub fn admin_transferred(e: &Env, old_admin: &Address, new_admin: &Address) { } .publish(e); } - -pub fn contract_upgraded(e: &Env, new_wasm_hash: &BytesN<32>) { - ContractUpgraded { - new_wasm_hash: new_wasm_hash.clone(), - } - .publish(e); -} diff --git a/contracts/vc-vault/src/interface.rs b/contracts/vc-vault/src/interface.rs index 669fced..34a760d 100644 --- a/contracts/vc-vault/src/interface.rs +++ b/contracts/vc-vault/src/interface.rs @@ -1,6 +1,6 @@ //! Public contract interface. All exported functions are defined here. -use soroban_sdk::{Address, BytesN, Env, String, Vec}; +use soroban_sdk::{Address, Env, String, Vec}; use crate::types::{VCStatus, VerifiableCredential}; @@ -9,7 +9,6 @@ pub trait VcVaultTrait { // --- Admin --- fn nominate_admin(e: Env, new_admin: Address); fn accept_contract_admin(e: Env); - fn upgrade(e: Env, new_wasm_hash: BytesN<32>); fn version(e: Env) -> String; // --- Vault management --- diff --git a/docs/deployments/testnet.md b/docs/deployments/testnet.md index f1ac9d2..131b9af 100644 --- a/docs/deployments/testnet.md +++ b/docs/deployments/testnet.md @@ -16,7 +16,7 @@ RPC: `https://soroban-testnet.stellar.org:443` | Version | Contract ID | Date | Notes | |---|---|---|---| -| 0.1.0 | `CBTNMBRD3TSGLPEZRD226U5LR7G3RWOYHCILAUEMRZAP7AHUZJ7CP4AB` | 2026-06-22 | First release. Deploys single-tenant vaults (deterministic address from `keccak(salt‖XDR(owner))`), centralizes fee config, `is_vault` registry. Constructed with vault template WASM hash `576b4c7b3d5aeafb9610bc569f45e1a007d2eff92855938a0bf933e657558ef9`. WASM hash `f94a77905d87f9a195ea837414b4995c7d3d66bed0e287481710246bc1d5bdcd`. | +| 0.1.0 | `CDRFQRIP4FA3WMPWCSAM3XEY6EM6EGKRYZRSCSVZ5NHCF6AGEVR2XEPQ` | 2026-06-22 | First release. Deploys single-tenant vaults (deterministic address from `keccak(salt‖XDR(owner))`), centralizes fee config, `is_vault` registry. Constructed with vault template WASM hash `2bd0323a98acb8469606808368da6c79824f2dd8391494b94ddbeb3d22c1a957`. WASM hash `f94a77905d87f9a195ea837414b4995c7d3d66bed0e287481710246bc1d5bdcd`. | ## vc-vault @@ -30,4 +30,4 @@ with its hash. | 0.1.0 | `CC3SQ7UTAQQDQF6PUQMQIGK3BMPB22OKMHE5Y5XELEX3JFAKC72SQOAM` | 2026-05-06 | Tranche 1 initial deploy (multi-tenant). | | 0.2.0 | `CBXC6LXBY5FGEG46VZ4AJ2AH2EJBINBA7BMILIEO4EJYI6ZTY7K7J5D5` | 2026-05-07 | SOW D2: O(1) index + pagination + migrate + batch_issue. WASM hash `c8da61dd3dd46b2810a743d50a388c09a00f0b7e8e2df7ceb5a71c8ce5dc4dd8`. | | 0.3.0 | `CATL4IDH7XXPDC2UHSEX2GP45PPBVDFSKUDTKCSQICDOJVDLYNKISXFH` | 2026-05-14 | Refactoring: constructor, types rename, push_vc extraction, input caps, event emissions, O(1) issuer storage, tombstone TTL fix. WASM hash `775a141520de56fb4b1ebeb55d63e49fadf03f467ea8444cddb2caed2756ca8c`. | -| 0.4.0 | WASM hash `576b4c7b3d5aeafb9610bc569f45e1a007d2eff92855938a0bf933e657558ef9` (template; deployed via factory) | 2026-06-22 | Single-tenant rearchitecture + open issuance (deny-by-exception) + fees moved to factory. Installed as a template; instances created by `vc-vault-factory` `CBTNMBRD3TSGLPEZRD226U5LR7G3RWOYHCILAUEMRZAP7AHUZJ7CP4AB`. | +| 0.4.0 | WASM hash `2bd0323a98acb8469606808368da6c79824f2dd8391494b94ddbeb3d22c1a957` (template; deployed via factory) | 2026-06-22 | Single-tenant rearchitecture + open issuance (deny-by-exception) + fees moved to factory; `upgrade` entrypoint removed (immutable). Installed as a template; instances created by `vc-vault-factory` `CDRFQRIP4FA3WMPWCSAM3XEY6EM6EGKRYZRSCSVZ5NHCF6AGEVR2XEPQ`. | From b709b4a20e6c62c75e6ad6ae2eb8d2671c74fe5b Mon Sep 17 00:00:00 2001 From: aguilar1x Date: Mon, 22 Jun 2026 20:00:14 -0600 Subject: [PATCH 3/3] docs: record testnet factory fee config (5 XLM ~ 1 USD) --- docs/deployments/testnet.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/deployments/testnet.md b/docs/deployments/testnet.md index 131b9af..cf26c91 100644 --- a/docs/deployments/testnet.md +++ b/docs/deployments/testnet.md @@ -18,6 +18,19 @@ RPC: `https://soroban-testnet.stellar.org:443` |---|---|---|---| | 0.1.0 | `CDRFQRIP4FA3WMPWCSAM3XEY6EM6EGKRYZRSCSVZ5NHCF6AGEVR2XEPQ` | 2026-06-22 | First release. Deploys single-tenant vaults (deterministic address from `keccak(salt‖XDR(owner))`), centralizes fee config, `is_vault` registry. Constructed with vault template WASM hash `2bd0323a98acb8469606808368da6c79824f2dd8391494b94ddbeb3d22c1a957`. WASM hash `f94a77905d87f9a195ea837414b4995c7d3d66bed0e287481710246bc1d5bdcd`. | +### Fee configuration (factory `CDRFQRIP…`, set 2026-06-22) + +| Field | Value | +|---|---| +| enabled | `true` | +| token | `CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC` (native XLM SAC) | +| dest | `GAP7AUGY2Q2NKIHJ2XMZAGVHD7KDF2UAUEPXE5HRXL7BOXRWDHXHG6IY` | +| standard | `50000000` stroops = **5 XLM ≈ 1 USD** @ ~$0.20/XLM | + +Charged per credential issued; the issuer pays. The amount is fixed on-chain (does +not track the USD price). Adjust with `set_fee_standard` / `set_fee_custom`, or +`set_fee_enabled false` to disable. + ## vc-vault Since v0.4.0 the vault is **single-tenant** and is no longer deployed standalone —