diff --git a/Architecture.md b/Architecture.md index 904f491da..f2a9a2a2c 100644 --- a/Architecture.md +++ b/Architecture.md @@ -12,18 +12,26 @@ The OpenZeppelin Stellar Contracts library follows a modular, trait-based archit stellar-contracts/ ├── packages/ # Core library packages │ ├── access/ # Role-based access controls and ownable patterns -│ ├── contract-utils/ # Utilities (pausable, upgradeable, cryptography) -│ ├── macros/ # Procedural and derive macros -│ └── tokens/ # Token implementations (fungible, non-fungible) -│ ├── src/ -│ │ ├── fungible/ # Fungible token implementation -│ │ │ ├── extensions/ # Optional token extensions -│ │ │ ├── utils/ # Utility functions and helpers -│ │ │ ├── mod.rs # Core trait definitions, constants, errors, and events -│ │ │ ├── storage.rs # Storage management and state operations -│ │ │ └── test.rs # Comprehensive test suite -│ │ └── non_fungible/ # Non-fungible token implementation -│ └── lib.rs +│ ├── accounts/ # Smart accounts (context rules, signers, verifiers, policies) +│ ├── confidential/ # Confidential token (encrypted balances, ZK proofs, Noir circuits) +│ ├── contract-utils/ # Utilities (pausable, upgradeable, cryptography, math, merkle distributor) +│ ├── fee-abstraction/ # Fee forwarding (pay transaction fees in fungible tokens) +│ ├── governance/ # Governor, votes, timelock +│ ├── macros/ # Procedural macros +│ ├── tokens/ # Token implementations (fungible, non-fungible, RWA, vault) +│ │ └── src/ +│ │ ├── fungible/ # Fungible token implementation +│ │ │ ├── extensions/ # Optional token extensions +│ │ │ ├── utils/ # Utility functions and helpers +│ │ │ ├── mod.rs # Core trait definitions, constants, errors, and events +│ │ │ ├── overrides.rs # Base contract type and override traits +│ │ │ ├── storage.rs # Storage management and state operations +│ │ │ └── test.rs # Comprehensive test suite +│ │ ├── non_fungible/ # Non-fungible token implementation +│ │ ├── rwa/ # Real-world asset token (T-REX) and its periphery +│ │ ├── vault/ # Tokenized vault (ERC-4626) +│ │ └── lib.rs +│ └── zk-email/ # DKIM registry for zkEmail verification ├── examples/ # Example contract implementations └── audits/ # Security audit reports ``` @@ -60,19 +68,19 @@ pub struct Consecutive; // For batch minting optimization Extensions are constrained to specific contract types using associated type bounds: ```rust -// Enumerable can only be used with Enumerable contract type -trait NonFungibleEnumerable: NonFungibleToken { +// Enumerable requires a contract type that keeps the enumeration bookkeeping +trait NonFungibleEnumerable: NonFungibleToken { fn total_supply(e: &Env) -> u32; fn get_owner_token_id(e: &Env, owner: Address, index: u32) -> u32; // ... } -// Consecutive can only be used with Consecutive contract type -trait NonFungibleConsecutive: NonFungibleToken { - // Batch minting functionality -} +// Consecutive requires a contract type that follows the consecutive accounting model +trait NonFungibleConsecutive: NonFungibleToken {} ``` +`EnumerableContractType` and `ConsecutiveContractType` are marker traits implemented by `Enumerable` and `Consecutive` and by the curated combinations that include them (`EnumerableVotes`, `ConsecutiveVotes`). + #### Mutual Exclusivity Enforcement This design makes it **impossible** to implement conflicting extensions: @@ -87,9 +95,13 @@ impl NonFungibleEnumerable for MyContract { // ... enumerable methods } -// ❌ This CANNOT compile - Consecutive requires different ContractType -// impl NonFungibleConsecutive for MyContract { ... } -// ^^^ Error: expected `Consecutive`, found `Enumerable` +// ❌ This CANNOT compile - Consecutive requires a consecutive ContractType +// impl NonFungibleConsecutive for MyContract {} +// ^^^ error[E0277]: the trait bound `Enumerable: ConsecutiveContractType` is not satisfied + +// ❌ Neither can listing both in `Compose` +// type ContractType = Compose<(Enumerable, Consecutive)>; +// ^^^ error[E0277]: `Enumerable` cannot be combined with `Consecutive` in a `Compose` list ``` #### Override Mechanism Through ContractOverrides @@ -208,10 +220,11 @@ The library provides two levels of abstraction: The architecture supports optional extensions that can be mixed and matched. Below is the list of the extensions for the Fungible Token: - **Burnable**: Token destruction capabilities +- **TotalSupply**: Total supply tracking - **Capped**: Maximum supply limits - **Allowlist**: Whitelist-based access control - **Blocklist**: Blacklist-based access control -- **Metadata**: Enhanced token information (name, symbol, decimals) +- **Votes**: Voting power tracking for governance - **Vault**: Asset deposit/withdrawal with share tokenization ## Storage Architecture @@ -222,8 +235,8 @@ The library uses a structured approach to storage keys: ```rust #[contracttype] -pub enum StorageKey { - TotalSupply, +pub enum FungibleStorageKey { + Meta, Balance(Address), Allowance(AllowanceKey), } @@ -387,7 +400,6 @@ The non-fungible token implementation is designed to be compatible with existing - **Unit Tests**: Individual function testing - **Integration Tests**: Cross-module interaction testing - **Property-Based Testing**: Invariant verification -- **Fuzzing**: Edge case discovery ## Deployment Architecture @@ -415,19 +427,22 @@ Noir artifacts for a package live under `packages//circuits/`: ```text packages//circuits/ ├── Nargo.toml # Nargo workspace manifest +├── constraints.baseline # normalized `nargo info` output ├── lib/ # Shared primitives (type = "lib", no `main`) │ ├── src/lib.nr │ └── testdata/*.json # cross-language test vectors ├── gadgets// # one tiny `bin` crate per primitive │ └── src/main.nr # measurement-only: wraps one lib call -└── / # full circuits (planned -- one per proof type, - └── src/main.nr # e.g. register / withdraw / transfer) +├── / # full circuits, one per proof type +│ └── src/main.nr # (e.g. register / withdraw / transfer) +├── scripts/ # VK extraction and CI checks +└── vks/ # pinned verification keys ``` The `main.nr` files in `gadgets/` and `/` are both Noir circuit entry points, but they serve very different purposes: - **Gadget `main`s** are measurement-only. Each one wraps a single lib primitive in the smallest circuit that exercises it, so `nargo info` can report per-primitive constraint costs. A Noir `bin` package has exactly one `fn main`, and `nargo info` only measures `main`. Per-primitive constraint counts therefore require one `bin` package per primitive. The alternative (one gadget that calls every primitive in sequence) collapses everything into a single combined number and loses the per-primitive breakdown the constraint baseline depends on. -- **Operation `main`s** *are* the production circuits — one per proof type listed in the design doc's §7. They consume on-chain state as public inputs and enforce the constraint set that the wrapper contract relies on. +- **Operation `main`s** *are* the production circuits — one per proof type (in `confidential/`: register, withdraw, transfer, set_spender, spender_transfer, clawback). They consume on-chain state as public inputs and enforce the constraint set that the wrapper contract relies on. ### Commands @@ -436,9 +451,9 @@ The `main.nr` files in `gadgets/` and `/` are both Noir circuit entry | Type-check the workspace | `nargo check` | | Run all tests | `nargo test` | | Per-primitive constraint counts | `nargo info` | -| Compile a single circuit | `nargo compile --package ` | +| Compile a single circuit | `nargo compile --package circuit_` | -Compiled ACIR and proving artifacts are gitignored; `testdata/*.json` is the only Noir-side artifact committed to the repo. +Build output (`target/`) and `Prover.toml` are gitignored. Four kinds of generated file are committed: `constraints.baseline`, `vks/*.vk.json`, `vks/*.vk.bin`, and `lib/testdata/*.json`. CI regenerates the baseline and the verification keys and fails when they differ from the committed ones; `nargo test` checks the test vectors against the primitives. ## Code Conventions diff --git a/Cargo.lock b/Cargo.lock index cbc62153a..b52cb3130 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -458,124 +458,124 @@ dependencies = [ [[package]] name = "compliance-country-allow" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "compliance-country-restrict" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "compliance-initial-lockup-period" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "compliance-max-balance" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "compliance-supply-limit" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "compliance-time-transfers-limits" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "compliance-transfer-allow" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "confidential-allowlist-policy-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", + "stellar-access 0.8.0", "stellar-confidential", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "confidential-auditor-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", + "stellar-access 0.8.0", "stellar-confidential", - "stellar-contract-utils 0.7.1", - "stellar-macros 0.7.1", + "stellar-contract-utils 0.8.0", + "stellar-macros 0.8.0", ] [[package]] name = "confidential-compliant-token-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", + "stellar-access 0.8.0", "stellar-confidential", - "stellar-contract-utils 0.7.1", - "stellar-macros 0.7.1", + "stellar-contract-utils 0.8.0", + "stellar-macros 0.8.0", ] [[package]] name = "confidential-factory-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", "stellar-confidential", - "stellar-contract-utils 0.7.1", + "stellar-contract-utils 0.8.0", ] [[package]] name = "confidential-verifier-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", + "stellar-access 0.8.0", "stellar-confidential", - "stellar-macros 0.7.1", + "stellar-macros 0.8.0", ] [[package]] @@ -965,23 +965,23 @@ checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fee-forwarder-permissioned-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", + "stellar-access 0.8.0", "stellar-fee-abstraction", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "fee-forwarder-permissionless-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", "stellar-fee-abstraction", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] @@ -1020,93 +1020,93 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "fungible-allowlist-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "fungible-blocklist-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "fungible-capped-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-tokens 0.7.1", + "stellar-tokens 0.8.0", ] [[package]] name = "fungible-governor-contract" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-governance 0.7.1", + "stellar-governance 0.8.0", ] [[package]] name = "fungible-governor-token" -version = "0.7.1" +version = "0.8.0" dependencies = [ "fungible-governor-contract", "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-governance 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-governance 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "fungible-merkle-airdrop-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "hex-literal 1.1.0", "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-contract-utils 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-contract-utils 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "fungible-pausable-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-contract-utils 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-contract-utils 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "fungible-vault-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "fungible-votes-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-governance 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-governance 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] @@ -1184,22 +1184,22 @@ dependencies = [ [[package]] name = "governor-timelock-contract" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-governance 0.7.1", + "stellar-governance 0.8.0", ] [[package]] name = "governor-timelock-token" -version = "0.7.1" +version = "0.8.0" dependencies = [ "governor-timelock-contract", "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-governance 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-governance 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", "timelock-controller-example", ] @@ -1467,24 +1467,24 @@ checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" [[package]] name = "merkle-voting-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-contract-utils 0.7.1", + "stellar-contract-utils 0.8.0", ] [[package]] name = "multisig-account-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", "stellar-accounts", - "stellar-contract-utils 0.7.1", + "stellar-contract-utils 0.8.0", ] [[package]] name = "multisig-account-factory-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", "stellar-accounts", @@ -1492,7 +1492,7 @@ dependencies = [ [[package]] name = "multisig-ed25519-verifier-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", "stellar-accounts", @@ -1500,7 +1500,7 @@ dependencies = [ [[package]] name = "multisig-spending-limit-policy-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", "stellar-accounts", @@ -1508,7 +1508,7 @@ dependencies = [ [[package]] name = "multisig-threshold-policy-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", "stellar-accounts", @@ -1516,7 +1516,7 @@ dependencies = [ [[package]] name = "multisig-webauthn-verifier-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "hex-literal 1.1.0", "p256", @@ -1526,7 +1526,7 @@ dependencies = [ [[package]] name = "multisig-weighted-threshold-policy-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", "stellar-accounts", @@ -1534,48 +1534,48 @@ dependencies = [ [[package]] name = "nft-access-control-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "nft-consecutive-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-tokens 0.7.1", + "stellar-tokens 0.8.0", ] [[package]] name = "nft-enumerable-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "nft-royalties-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "nft-sequential-minting-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] @@ -1631,11 +1631,11 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "ownable-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", ] [[package]] @@ -1658,11 +1658,11 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pausable-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-contract-utils 0.7.1", - "stellar-macros 0.7.1", + "stellar-contract-utils 0.8.0", + "stellar-macros 0.8.0", ] [[package]] @@ -1925,74 +1925,74 @@ dependencies = [ [[package]] name = "rwa-claim-issuer-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "ed25519-dalek", "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "rwa-claim-topics-and-issuers-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "rwa-compliance-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "rwa-identity-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "rwa-identity-registry-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "rwa-identity-verifier-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "rwa-token-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-contract-utils 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-contract-utils 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] @@ -2003,21 +2003,21 @@ checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "sac-admin-generic-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "ed25519-dalek", "soroban-sdk 28.0.0", - "stellar-tokens 0.7.1", + "stellar-tokens 0.8.0", ] [[package]] name = "sac-admin-wrapper-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] @@ -2633,23 +2633,23 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stellar-access" -version = "0.7.1" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aae4c50000565b08e97241a06cfb2cff4c3dfde12bdafa0b5303aca22139f38" dependencies = [ - "soroban-sdk 28.0.0", + "soroban-sdk 26.1.0", ] [[package]] name = "stellar-access" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aae4c50000565b08e97241a06cfb2cff4c3dfde12bdafa0b5303aca22139f38" +version = "0.8.0" dependencies = [ - "soroban-sdk 26.1.0", + "soroban-sdk 28.0.0", ] [[package]] name = "stellar-accounts" -version = "0.7.1" +version = "0.8.0" dependencies = [ "ed25519-dalek", "hex-literal 1.1.0", @@ -2662,27 +2662,14 @@ dependencies = [ [[package]] name = "stellar-confidential" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-poseidon", "soroban-sdk 28.0.0", - "stellar-contract-utils 0.7.1", + "stellar-contract-utils 0.8.0", "ultrahonk_soroban_verifier", ] -[[package]] -name = "stellar-contract-utils" -version = "0.7.1" -dependencies = [ - "ark-ec 0.6.0", - "ark-ff 0.6.0", - "ark-grumpkin", - "ark-serialize 0.6.0", - "hex-literal 1.1.0", - "proptest", - "soroban-sdk 28.0.0", -] - [[package]] name = "stellar-contract-utils" version = "0.7.2" @@ -2693,19 +2680,25 @@ dependencies = [ ] [[package]] -name = "stellar-fee-abstraction" -version = "0.7.1" +name = "stellar-contract-utils" +version = "0.8.0" dependencies = [ + "ark-ec 0.6.0", + "ark-ff 0.6.0", + "ark-grumpkin", + "ark-serialize 0.6.0", + "hex-literal 1.1.0", + "proptest", "soroban-sdk 28.0.0", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", ] [[package]] -name = "stellar-governance" -version = "0.7.1" +name = "stellar-fee-abstraction" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] @@ -2717,9 +2710,18 @@ dependencies = [ "soroban-sdk 26.1.0", ] +[[package]] +name = "stellar-governance" +version = "0.8.0" +dependencies = [ + "soroban-sdk 28.0.0", +] + [[package]] name = "stellar-macros" -version = "0.7.1" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a512f2975f47ab532537c7b3cc845bd5a39cab8f8c52c16388a26482f201883" dependencies = [ "proc-macro2", "quote", @@ -2728,9 +2730,7 @@ dependencies = [ [[package]] name = "stellar-macros" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a512f2975f47ab532537c7b3cc845bd5a39cab8f8c52c16388a26482f201883" +version = "0.8.0" dependencies = [ "proc-macro2", "quote", @@ -2758,19 +2758,6 @@ dependencies = [ "heapless", ] -[[package]] -name = "stellar-tokens" -version = "0.7.1" -dependencies = [ - "ed25519-dalek", - "k256", - "p256", - "soroban-sdk 28.0.0", - "soroban-test-helpers", - "stellar-contract-utils 0.7.1", - "stellar-governance 0.7.1", -] - [[package]] name = "stellar-tokens" version = "0.7.2" @@ -2782,6 +2769,19 @@ dependencies = [ "stellar-governance 0.7.2", ] +[[package]] +name = "stellar-tokens" +version = "0.8.0" +dependencies = [ + "ed25519-dalek", + "k256", + "p256", + "soroban-sdk 28.0.0", + "soroban-test-helpers", + "stellar-contract-utils 0.8.0", + "stellar-governance 0.8.0", +] + [[package]] name = "stellar-xdr" version = "26.0.1" @@ -2822,7 +2822,7 @@ dependencies = [ [[package]] name = "stellar-zk-email" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", ] @@ -2916,12 +2916,12 @@ dependencies = [ [[package]] name = "timelock-controller-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-governance 0.7.1", - "stellar-macros 0.7.1", + "stellar-access 0.8.0", + "stellar-governance 0.8.0", + "stellar-macros 0.8.0", ] [[package]] @@ -2977,9 +2977,9 @@ name = "upgradeable-lazy-v1-example" version = "1.0.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-contract-utils 0.7.1", - "stellar-macros 0.7.1", + "stellar-access 0.8.0", + "stellar-contract-utils 0.8.0", + "stellar-macros 0.8.0", ] [[package]] @@ -2987,9 +2987,9 @@ name = "upgradeable-lazy-v2-example" version = "2.0.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-contract-utils 0.7.1", - "stellar-macros 0.7.1", + "stellar-access 0.8.0", + "stellar-contract-utils 0.8.0", + "stellar-macros 0.8.0", ] [[package]] @@ -3008,20 +3008,20 @@ name = "upgradeable-v2-example" version = "2.0.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-contract-utils 0.7.1", - "stellar-macros 0.7.1", - "stellar-tokens 0.7.1", + "stellar-access 0.8.0", + "stellar-contract-utils 0.8.0", + "stellar-macros 0.8.0", + "stellar-tokens 0.8.0", ] [[package]] name = "upgrader-example" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk 28.0.0", - "stellar-access 0.7.1", - "stellar-contract-utils 0.7.1", - "stellar-macros 0.7.1", + "stellar-access 0.8.0", + "stellar-contract-utils 0.8.0", + "stellar-macros 0.8.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 9d5ea9390..aff61f973 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,7 @@ repository = "https://github.com/OpenZeppelin/stellar-contracts" documentation = "https://docs.openzeppelin.com/stellar-contracts/" keywords = ["stellar", "soroban", "smart-contracts", "standards"] categories = ["no-std", "wasm"] -version = "0.7.1" +version = "0.8.0" [workspace.dependencies] soroban-sdk = "28.0.0" @@ -73,15 +73,15 @@ serde-json-core = { version = "0.6.0", default-features = false } ultrahonk-soroban-verifier = { version = "0.1.0", package = "ultrahonk_soroban_verifier" } # members -stellar-access = { path = "packages/access", version = "0.7.1" } -stellar-accounts = { path = "packages/accounts", version = "0.7.1" } -stellar-confidential = { path = "packages/confidential", version = "0.7.1" } -stellar-contract-utils = { path = "packages/contract-utils", version = "0.7.1" } -stellar-fee-abstraction = { path = "packages/fee-abstraction", version = "0.7.1" } -stellar-governance = { path = "packages/governance", version = "0.7.1" } -stellar-tokens = { path = "packages/tokens", version = "0.7.1" } -stellar-macros = { path = "packages/macros", version = "0.7.1" } -stellar-zk-email = { path = "packages/zk-email", version = "0.7.1" } +stellar-access = { path = "packages/access", version = "0.8.0" } +stellar-accounts = { path = "packages/accounts", version = "0.8.0" } +stellar-confidential = { path = "packages/confidential", version = "0.8.0" } +stellar-contract-utils = { path = "packages/contract-utils", version = "0.8.0" } +stellar-fee-abstraction = { path = "packages/fee-abstraction", version = "0.8.0" } +stellar-governance = { path = "packages/governance", version = "0.8.0" } +stellar-tokens = { path = "packages/tokens", version = "0.8.0" } +stellar-macros = { path = "packages/macros", version = "0.8.0" } +stellar-zk-email = { path = "packages/zk-email", version = "0.8.0" } [profile.release] opt-level = "z" diff --git a/README.md b/README.md index 9ebd3a3ea..34b99e07b 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ OpenZeppelin Stellar Contracts are published as separate crates on [crates.io](h - [stellar-access](https://crates.io/crates/stellar-access): Role-based access controls and ownable - [stellar-accounts](https://crates.io/crates/stellar-accounts): Smart accounts with custom authentication and authorization +- [stellar-confidential](https://crates.io/crates/stellar-confidential): Confidential token with encrypted balances and zero-knowledge proofs - [stellar-contract-utils](https://crates.io/crates/stellar-contract-utils): Utilities for contracts (pausable, upgradeable, cryptography, etc.) - [stellar-fee-abstraction](https://crates.io/crates/stellar-fee-abstraction): Fee abstraction utilities - [stellar-governance](https://crates.io/crates/stellar-governance): Governance utilities (governor, votes, timelock) @@ -74,13 +75,14 @@ We recommend pinning to a specific version, because rapid iterations are expecte ```toml [dependencies] -stellar-tokens = "=0.7.1" -stellar-access = "=0.7.1" -stellar-contract-utils = "=0.7.1" -stellar-governance = "=0.7.1" -stellar-accounts = "=0.7.1" -stellar-fee-abstraction = "=0.7.1" -stellar-macros = "=0.7.1" +stellar-tokens = "=0.8.0" +stellar-access = "=0.8.0" +stellar-contract-utils = "=0.8.0" +stellar-governance = "=0.8.0" +stellar-accounts = "=0.8.0" +stellar-fee-abstraction = "=0.8.0" +stellar-confidential = "=0.8.0" +stellar-macros = "=0.8.0" ``` ## Notes diff --git a/audits/Stellar Contracts Library v0.8.0 Audit.pdf b/audits/Stellar Contracts Library v0.8.0 Audit.pdf new file mode 100644 index 000000000..93a610575 Binary files /dev/null and b/audits/Stellar Contracts Library v0.8.0 Audit.pdf differ diff --git a/bench/rwa-batch/Cargo.lock b/bench/rwa-batch/Cargo.lock index fe349e04e..e10960f18 100644 --- a/bench/rwa-batch/Cargo.lock +++ b/bench/rwa-batch/Cargo.lock @@ -1333,7 +1333,7 @@ checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "rwa-batch-bench" -version = "0.7.1" +version = "0.8.0" dependencies = [ "ed25519-dalek", "soroban-sdk", @@ -1523,9 +1523,9 @@ checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "soroban-builtin-sdk-macros" -version = "27.0.1" +version = "28.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b77bc93d930032c487cb1506b6ed166b2af49db76d52678ec4887ac621ecce01" +checksum = "86ffd329211a50add3965a8f4a8f70e24fc5c8268c945566ab963029b12dce40" dependencies = [ "itertools", "proc-macro2", @@ -1535,12 +1535,12 @@ dependencies = [ [[package]] name = "soroban-env-common" -version = "27.0.1" +version = "28.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b22e9981cdd444f3aa6734bc58d76195bf7eca3ccf1dd432b875af5d02da068" +checksum = "610bb12ee937a56c2b629f8eb16efb7e47607cba4e79ab0c24132b9a53dd19a0" dependencies = [ "arbitrary", - "crate-git-revision 0.0.6", + "crate-git-revision 0.0.9", "ethnum", "num-derive", "num-traits", @@ -1554,9 +1554,9 @@ dependencies = [ [[package]] name = "soroban-env-guest" -version = "27.0.1" +version = "28.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b6072f99ca6bf8e8d5b04e05d083dac785e5357d9c0f36a6658f819c2fd7d67" +checksum = "7d383176b27bb286f718ab0ff5713bd9b01132089151266359bd9b20f38684cf" dependencies = [ "soroban-env-common", "static_assertions", @@ -1564,9 +1564,9 @@ dependencies = [ [[package]] name = "soroban-env-host" -version = "27.0.1" +version = "28.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c06afd7c75ce150ce53e4d77a77645b18e3fb61856a0ddc42bfcecdc39fa3b9" +checksum = "36d7e5920c200939164cc58038224e2d90d7e2fabbfa505d6e2129d648dce7e2" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -1601,9 +1601,9 @@ dependencies = [ [[package]] name = "soroban-env-macros" -version = "27.0.1" +version = "28.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "647811bdd28a3ec40296987f6635781e5e1141c8f5affbbd53ba12b6295b7bb6" +checksum = "077600bb175ea54592c1ac5983b8fb34ec9ab7a65f298af11d687b61e9d646a4" dependencies = [ "itertools", "proc-macro2", @@ -1616,9 +1616,9 @@ dependencies = [ [[package]] name = "soroban-ledger-snapshot" -version = "27.0.6" +version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b59883d8bd0d1aed8d57579a9974ab88eaf787dd0a1af104f6881b5707450558" +checksum = "b5caeb0a4c8af6d04dc1dfbf96199e0d50ae086c7d54c9001abe78bb891fc44f" dependencies = [ "serde", "serde_json", @@ -1628,20 +1628,11 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "soroban-poseidon" -version = "27.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b241822373adc51c23d5412e412b3b91b0d6b6bba146584946391aa32667820d" -dependencies = [ - "soroban-sdk", -] - [[package]] name = "soroban-sdk" -version = "27.0.2" +version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cfa78af0110f0830d3af9db0361b6cdb50507846cedb8725189318134218b80" +checksum = "e4946477e75667215a25b652b0febb446485686c944d364c117c903e3fb98bab" dependencies = [ "arbitrary", "bytes-lit", @@ -1663,9 +1654,9 @@ dependencies = [ [[package]] name = "soroban-sdk-macros" -version = "27.0.6" +version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bd4a847273d749807fe2eb52e2b9c1917ee482cd6a39465cad5c389548996ad" +checksum = "168f2d2c3fd4da57584c71e0a8315a8e656486495bc53e18c93b8ec4db085438" dependencies = [ "darling 0.20.11", "heck", @@ -1683,9 +1674,9 @@ dependencies = [ [[package]] name = "soroban-spec" -version = "27.0.6" +version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473404322827b285cbcd87517f365986bd63af7842c78b2a86ee061715fda61e" +checksum = "2f48c8e183fc140ccd89e1fe1663cc605fb18641967c0bb591f64887599fde59" dependencies = [ "base64", "sha2", @@ -1696,9 +1687,9 @@ dependencies = [ [[package]] name = "soroban-spec-rust" -version = "27.0.6" +version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f25698b6ce2125850a9ef075cf9ba1e8d25b4cfa0c46aca42dadd80cc29d881" +checksum = "40cd0021887fd047e9f63cea36da35b202881bc0e0dbcc067a146137ca46f192" dependencies = [ "prettyplease", "proc-macro2", @@ -1753,14 +1744,14 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stellar-contract-utils" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk", ] [[package]] name = "stellar-governance" -version = "0.7.1" +version = "0.8.0" dependencies = [ "soroban-sdk", ] @@ -1788,9 +1779,8 @@ dependencies = [ [[package]] name = "stellar-tokens" -version = "0.7.1" +version = "0.8.0" dependencies = [ - "soroban-poseidon", "soroban-sdk", "stellar-contract-utils", "stellar-governance", @@ -1798,14 +1788,14 @@ dependencies = [ [[package]] name = "stellar-xdr" -version = "27.0.0" +version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ff843326969bdf1ef673dcdba94c08f4a3c8f1e58d6e6ef39b1bd4f749179a" +checksum = "f93d09ff8b9f919b084f664003c4c546ac66a76affd5429460dbe29f4b326f8e" dependencies = [ "arbitrary", "base64", "cfg_eval", - "crate-git-revision 0.0.6", + "crate-git-revision 0.0.9", "escape-bytes", "ethnum", "hex", diff --git a/bench/rwa-batch/Cargo.toml b/bench/rwa-batch/Cargo.toml index 9c9c17408..8e618c5d6 100644 --- a/bench/rwa-batch/Cargo.toml +++ b/bench/rwa-batch/Cargo.toml @@ -5,7 +5,7 @@ license = "MIT" repository = "https://github.com/OpenZeppelin/stellar-contracts" publish = false authors = ["OpenZeppelin"] -version = "0.7.1" +version = "0.8.0" # Deliberately excluded from the root workspace (see its `workspace.exclude`): # the harness measures cost curves rather than asserting behaviour, takes ~2 @@ -13,10 +13,7 @@ version = "0.7.1" # and counted by `cargo llvm-cov --workspace --fail-under-lines 90`. [dependencies] -soroban-sdk = { version = "27.0.2", features = [ - "testutils", - "experimental_spec_shaking_v2", -] } -stellar-contract-utils = { path = "../../packages/contract-utils", version = "0.7.1" } -stellar-tokens = { path = "../../packages/tokens", version = "0.7.1" } +soroban-sdk = { version = "28.0.0", features = ["testutils"] } +stellar-contract-utils = { path = "../../packages/contract-utils", version = "0.8.0" } +stellar-tokens = { path = "../../packages/tokens", version = "0.8.0" } ed25519-dalek = "2.1.1" diff --git a/examples/rwa/README.md b/examples/rwa/README.md index 6340de552..a681229ae 100644 --- a/examples/rwa/README.md +++ b/examples/rwa/README.md @@ -224,19 +224,19 @@ stellar contract invoke --id identity-registry --source admin \ -- add_identity \ --account alice \ --identity $ALICE_IDENTITY \ - --initial_profiles '[{"country": {"Individual": {"Residence": 840}}, "metadata": null}]' \ + --initial_profiles '[{"map": [{"key": {"symbol": "country"}, "val": {"vec": [{"symbol": "Individual"}, {"vec": [{"symbol": "Residence"}, {"u32": 840}]}]}}, {"key": {"symbol": "metadata"}, "val": "void"}]}]' \ --operator admin ``` -`CountryData` uses a nested enum structure. The outer `CountryRelation` variant is either `Individual` or `Organization`, and the inner variant is the relationship type (e.g., `Residence`, `Citizenship`, `Incorporation`) wrapping an ISO 3166-1 numeric country code (e.g., 840 = United States). +`initial_profiles` is a `Vec`, so the CLI cannot infer the `CountryData` type and each profile is passed as a raw `ScVal` JSON value. `CountryData` is a struct, encoded as a `map` with the symbol keys `country` and `metadata` in that order; a `metadata` of `None` is `"void"`. `country` is a nested enum: the outer `CountryRelation` variant is either `Individual` or `Organization`, and the inner variant is the relationship type (e.g., `Residence`, `Citizenship`, `Incorporation`) wrapping an ISO 3166-1 numeric country code (e.g., 840 = United States). Each enum variant is encoded as a `vec` holding its name as a `symbol` followed by its value. -Examples of valid `CountryData` JSON values: +Examples of valid `CountryData` values: ```json -{"country": {"Individual": {"Residence": 840}}, "metadata": null} -{"country": {"Individual": {"Citizenship": 276}}, "metadata": null} -{"country": {"Organization": {"Incorporation": 840}}, "metadata": null} -{"country": {"Organization": {"OperatingJurisdiction": 276}}, "metadata": null} +{"map": [{"key": {"symbol": "country"}, "val": {"vec": [{"symbol": "Individual"}, {"vec": [{"symbol": "Residence"}, {"u32": 840}]}]}}, {"key": {"symbol": "metadata"}, "val": "void"}]} +{"map": [{"key": {"symbol": "country"}, "val": {"vec": [{"symbol": "Individual"}, {"vec": [{"symbol": "Citizenship"}, {"u32": 276}]}]}}, {"key": {"symbol": "metadata"}, "val": "void"}]} +{"map": [{"key": {"symbol": "country"}, "val": {"vec": [{"symbol": "Organization"}, {"vec": [{"symbol": "Incorporation"}, {"u32": 840}]}]}}, {"key": {"symbol": "metadata"}, "val": "void"}]} +{"map": [{"key": {"symbol": "country"}, "val": {"vec": [{"symbol": "Organization"}, {"vec": [{"symbol": "OperatingJurisdiction"}, {"u32": 276}]}]}}, {"key": {"symbol": "metadata"}, "val": "void"}]} ``` ### 6. Deploy Identity Verifier Contract @@ -259,7 +259,7 @@ export VERIFIER_ADDRESS=$(stellar contract alias show identity-verifier 2>&1 | t ### 7. Deploy Compliance Contract -The compliance contract enforces business rules through pluggable modules registered on specific hooks. +The compliance contract enforces business rules through pluggable modules registered on specific hooks. Modules are configured in step 9, once the token exists. ```bash stellar contract deploy --alias compliance \ @@ -273,22 +273,6 @@ stellar contract deploy --alias compliance \ export COMPLIANCE_ADDRESS=$(stellar contract alias show compliance 2>&1 | tail -n 1) ``` -#### Register Compliance Modules (Optional) - -If you have custom compliance module contracts (e.g., transfer limits, country restrictions), register them on the appropriate hooks: - -```bash -stellar contract invoke --id compliance --source admin \ - -- add_module_to \ - --hook CanTransfer \ - --module \ - --operator admin -``` - -Available hooks: `CanTransfer`, `CanCreate`, `Transferred`, `Created`, `Destroyed`. - -> **Note:** Without any registered modules, the compliance contract allows all operations by default. - ### 8. Deploy RWA Token Contract Finally, deploy the token itself: @@ -325,7 +309,157 @@ stellar contract invoke --id compliance --source admin \ --operator admin ``` -### 9. Mint Tokens +### 9. Configure Compliance Modules (Optional) + +Compliance modules are separate contracts registered on the hooks they act on. Available hooks: `Transferred`, `Created`, `Destroyed`. Each hook runs after the token operation in the same transaction, and a module rejects the operation by panicking. + +The following ready-made module examples are ports of the T-REX modular compliance modules. Each takes `--admin` and `--manager` in its constructor: + +| Directory | Contract | Description | Hooks | +| ----------------------------------- | ----------------------------- | ------------------------------------------------------------------- | ------------------------------------- | +| `compliance-country-allow/` | `CountryAllowContract` | Only recipients with an allowed country code may receive tokens | `Transferred`, `Created` | +| `compliance-country-restrict/` | `CountryRestrictContract` | Recipients with a restricted country code may not receive tokens | `Transferred`, `Created` | +| `compliance-initial-lockup-period/` | `InitialLockupPeriodContract` | Locks minted tokens for a configured period | `Transferred`, `Created`, `Destroyed` | +| `compliance-max-balance/` | `MaxBalanceContract` | Caps the aggregate balance per identity | `Transferred`, `Created`, `Destroyed` | +| `compliance-supply-limit/` | `SupplyLimitContract` | Caps the total supply | `Created`, `Destroyed` | +| `compliance-time-transfers-limits/` | `TimeTransfersLimitsContract` | Caps cumulative outgoing transfers per identity within time windows | `Transferred` | +| `compliance-transfer-allow/` | `TransferAllowContract` | Allows a transfer only when the sender or recipient is allowlisted | `Transferred` | + +Module settings are keyed by token address, so they are set after the token is deployed in step 8. Configure a module fully before registering it on its hooks: a registered module enforces its policy from the next token operation. + +> **Note:** Without any registered modules, the compliance contract allows all operations by default. + +#### Deploy and Bind a Module + +The commands below alias each module after its directory name without the `compliance-` prefix. Deploy the supply limit module; the other modules follow the same pattern with their own alias and WASM file (e.g. `max-balance` and `compliance_max_balance.wasm`): + +```bash +stellar contract deploy --alias supply-limit \ + --wasm target/wasm32v1-none/release/compliance_supply_limit.wasm \ + -- \ + --admin admin \ + --manager admin +``` + +```bash +export SUPPLY_LIMIT_ADDRESS=$(stellar contract alias show supply-limit 2>&1 | tail -n 1) +``` + +Bind the module to the compliance contract for the token with `set_compliance_address`: + +```bash +stellar contract invoke --id supply-limit --source admin \ + -- set_compliance_address \ + --token $TOKEN_ADDRESS \ + --compliance $COMPLIANCE_ADDRESS \ + --operator admin +``` + +The country, max-balance, and time-transfers-limits modules also resolve identities, so they need the Identity Registry address set with `set_identity_registry_storage`: + +```bash +stellar contract invoke --id max-balance --source admin \ + -- set_identity_registry_storage \ + --token $TOKEN_ADDRESS \ + --irs $REGISTRY_ADDRESS \ + --operator admin +``` + +#### Set the Module Policy + +Each module starts with an empty policy for the token. The example values below let the mint in step 10 and the transfer under Key Operations go through, unless noted otherwise. Amounts use the token's 7 decimals, and durations are in ledgers (17280 ledgers ≈ 1 day). + +**Supply limit:** the cap defaults to `0`, which rejects every mint. Cap the supply at 1,000,000 tokens: + +```bash +stellar contract invoke --id supply-limit --source admin \ + -- set_supply_limit \ + --token $TOKEN_ADDRESS \ + --limit 10000000000000 \ + --operator admin +``` + +**Max balance:** the cap defaults to `0`, which rejects every mint and regular transfer. Cap the aggregate balance of each identity at 500 tokens: + +```bash +stellar contract invoke --id max-balance --source admin \ + -- set_max_balance \ + --token $TOKEN_ADDRESS \ + --max 5000000000 \ + --operator admin +``` + +**Initial lockup period:** the period defaults to `0`, so mints create no locks. Lock minted tokens for about 1 day: + +```bash +stellar contract invoke --id initial-lockup-period --source admin \ + -- set_lockup_period \ + --token $TOKEN_ADDRESS \ + --period 17280 \ + --operator admin +``` + +With this module registered, the tokens minted in step 10 stay locked for the period, so the transfer under Key Operations reverts until it elapses. + +**Time transfers limits:** no time windows are configured by default, so transfers are not limited. Cap the outgoing transfers of each identity at 100 tokens per day: + +```bash +stellar contract invoke --id time-transfers-limits --source admin \ + -- set_time_transfer_limit \ + --token $TOKEN_ADDRESS \ + --limit '{"limit_duration": 17280, "limit_value": "1000000000"}' \ + --operator admin +``` + +**Country allow:** the allowlist starts empty, which rejects every mint and regular transfer. Allow the United States (840), the country registered for the investors in step 5.1: + +```bash +stellar contract invoke --id country-allow --source admin \ + -- add_allowed_country \ + --token $TOKEN_ADDRESS \ + --country 840 \ + --operator admin +``` + +**Country restrict:** the restriction list starts empty, so no country is blocked. Restrict North Korea (408): + +```bash +stellar contract invoke --id country-restrict --source admin \ + -- add_country_restriction \ + --token $TOKEN_ADDRESS \ + --country 408 \ + --operator admin +``` + +**Transfer allow:** the allowlist starts empty, which rejects every regular transfer. A transfer passes when the sender or the recipient is allowlisted, so allowlist `alice`: + +```bash +stellar contract invoke --id transfer-allow --source admin \ + -- allow_user \ + --token $TOKEN_ADDRESS \ + --user alice \ + --operator admin +``` + +#### Register the Module on Its Hooks + +Register the module on each of its hooks listed in the table, e.g. `Created` and `Destroyed` for the supply limit module: + +```bash +stellar contract invoke --id compliance --source admin \ + -- add_module_to \ + --hook Created \ + --module $SUPPLY_LIMIT_ADDRESS \ + --operator admin + +stellar contract invoke --id compliance --source admin \ + -- add_module_to \ + --hook Destroyed \ + --module $SUPPLY_LIMIT_ADDRESS \ + --operator admin +``` + +### 10. Mint Tokens With everything configured, mint tokens to verified investors: @@ -348,9 +482,10 @@ Use this checklist to verify your deployment is complete: - [ ] Identity contracts deployed for each investor, claims added - [ ] Identity Registry Storage deployed, identities registered - [ ] Identity Verifier deployed, linked to Claim Topics and Issuers + Identity Registry Storage -- [ ] Compliance deployed, modules registered (if any) +- [ ] Compliance deployed - [ ] RWA Token deployed, linked to Compliance + Identity Verifier - [ ] Token bound to Identity Registry and Compliance contracts +- [ ] Compliance modules (if any) deployed, bound, configured, and registered on their hooks - [ ] Initial token supply minted to verified addresses ## Key Operations diff --git a/examples/rwa/identity-registry/src/contract.rs b/examples/rwa/identity-registry/src/contract.rs index b54fe1773..af25033ca 100644 --- a/examples/rwa/identity-registry/src/contract.rs +++ b/examples/rwa/identity-registry/src/contract.rs @@ -40,7 +40,7 @@ impl TokenBinder for IdentityRegistryContract { } } -#[contractimpl] +#[contractimpl(contracttrait)] impl IdentityRegistryStorage for IdentityRegistryContract { #[only_role(operator, "manager")] fn add_identity( @@ -102,7 +102,7 @@ impl IdentityRegistryStorage for IdentityRegistryContract { } } -#[contractimpl] +#[contractimpl(contracttrait)] impl CountryDataManager for IdentityRegistryContract { #[only_role(operator, "manager")] fn add_country_data_entries(e: &Env, account: Address, profiles: Vec, operator: Address) { diff --git a/examples/rwa/sign-claim/Cargo.toml b/examples/rwa/sign-claim/Cargo.toml index 8f40624e9..df8fced7b 100644 --- a/examples/rwa/sign-claim/Cargo.toml +++ b/examples/rwa/sign-claim/Cargo.toml @@ -5,7 +5,7 @@ license = "MIT" repository = "https://github.com/OpenZeppelin/stellar-contracts" publish = false authors.workspace = true -version = "0.7.1" +version = "0.8.0" [[bin]] name = "rwa-sign-claim" diff --git a/packages/access/README.md b/packages/access/README.md index 9c10420bf..c892742a6 100644 --- a/packages/access/README.md +++ b/packages/access/README.md @@ -6,6 +6,7 @@ This crate is part of the [OpenZeppelin Stellar Contracts](https://github.com/Op - **[stellar-access](https://crates.io/crates/stellar-access)**: Role-based access controls and ownable - [stellar-accounts](https://crates.io/crates/stellar-accounts): Smart accounts with custom authentication and authorization +- [stellar-confidential](https://crates.io/crates/stellar-confidential): Confidential token with encrypted balances and zero-knowledge proofs - [stellar-contract-utils](https://crates.io/crates/stellar-contract-utils): Utilities for contracts (pausable, upgradeable, cryptography, etc.) - [stellar-fee-abstraction](https://crates.io/crates/stellar-fee-abstraction): Fee abstraction utilities - [stellar-governance](https://crates.io/crates/stellar-governance): Governance utilities (governor, votes, timelock) @@ -157,9 +158,9 @@ Add this to your `Cargo.toml`: ```toml [dependencies] # We recommend pinning to a specific version, because rapid iterations are expected as the library is in an active development phase. -stellar-access = "=0.7.1" +stellar-access = "=0.8.0" # Add this if you want to use macros -stellar-macros = "=0.7.1" +stellar-macros = "=0.8.0" ``` ## Examples diff --git a/packages/accounts/README.md b/packages/accounts/README.md index 944f520a0..2b688bcf2 100644 --- a/packages/accounts/README.md +++ b/packages/accounts/README.md @@ -6,6 +6,7 @@ This crate is part of the [OpenZeppelin Stellar Contracts](https://github.com/Op - [stellar-access](https://crates.io/crates/stellar-access): Role-based access controls and ownable - **[stellar-accounts](https://crates.io/crates/stellar-accounts)**: Smart accounts with custom authentication and authorization +- [stellar-confidential](https://crates.io/crates/stellar-confidential): Confidential token with encrypted balances and zero-knowledge proofs - [stellar-contract-utils](https://crates.io/crates/stellar-contract-utils): Utilities for contracts (pausable, upgradeable, cryptography, etc.) - [stellar-fee-abstraction](https://crates.io/crates/stellar-fee-abstraction): Fee abstraction utilities - [stellar-governance](https://crates.io/crates/stellar-governance): Governance utilities (governor, votes, timelock) @@ -349,7 +350,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] # We recommend pinning to a specific version, because rapid iterations are expected as the library is in an active development phase. -stellar-accounts = "=0.7.1" +stellar-accounts = "=0.8.0" ``` ### 2. Implement the Smart Account Trait diff --git a/packages/confidential/CLAUDE.md b/packages/confidential/CLAUDE.md index 7172e6467..adebe4324 100644 --- a/packages/confidential/CLAUDE.md +++ b/packages/confidential/CLAUDE.md @@ -1,6 +1,6 @@ # Confidential Token — Agent Guide -Scoped to `packages/confidential/`. The root `CLAUDE.md` still applies in full; this file only covers what is specific to this subtree. The Noir workspace has its own guide at `circuits/CLAUDE.md`. +Scoped to `packages/confidential/`. The root `CLAUDE.md` still applies in full; this file only covers what is specific to this subtree. ## Orientation @@ -39,6 +39,27 @@ Beyond the root guide's conventions: - Use `fixture_point` / `fixture_field`, not arbitrary bytes. The fixtures are canonical and on-curve; random values fail the canonicality guards before reaching any logic under test. - Two mocks model proof semantics on purpose: the register mock in `src/test.rs` binds the first `acct_f` it sees, and `ClawbackReplayGuardVerifier` in `src/compliance/test.rs` binds the first whole blob, both standing in for UltraHonk's absorption of public inputs, so replay tests are meaningful. Keep that behaviour if either flow changes. +## Noir circuits + +Run from `circuits/`; CI is `.github/workflows/noir.yml`. There is no `nargo fmt` step and no formatter config. + +```bash +nargo check && nargo test +nargo info # per-package constraint counts +./scripts/extract_vks.sh # regenerate vks/*.vk.json +./scripts/build_vk_bins.sh # regenerate vks/*.vk.bin +./scripts/check_witness_lookups.sh # no witness reaches a lookup table +``` + +Each change below spans several files and lands in one PR with all of its sites: + +- **Adding a circuit.** The package, the `members` list in `circuits/Nargo.toml`, and the hardcoded `CIRCUITS` arrays in both `circuits/scripts/extract_vks.sh` and `circuits/scripts/build_vk_bins.sh`; then regenerate `constraints.baseline` and both VK formats. +- **Renaming a package.** Directory `transfer/` is package `circuit_transfer`. Both VK scripts derive `circuit_${name}` and `target/${pkg}.json` from the directory name, and every row of `constraints.baseline` is keyed on the package name. +- **Bumping the toolchain.** `NARGO_VERSION` and `BB_VERSION` in `noir.yml` are the source of truth and move together; the VKs are byte-sensitive to bb. Both versions are restated in the comment above `compiler_version` in every package `Nargo.toml` and in `circuits/vks/README.md`; the nargo version in the `constraints.baseline` header; the bb version in `circuits/scripts/check_witness_lookups.sh`, whose blackbox allowlist must be re-confirmed against the new bb, and in `README.md`, which names the bb version the on-chain verifier accepts. The CI installers are pinned by commit with SHA256 verification; bump URL and hash together, then regenerate the baseline and both VK formats. +- **`address_to_field` vectors.** The derivation has no Noir implementation (circuits take `addr_f` as an opaque public input), so `circuits/lib/testdata/address_to_field.json` is guarded only by `address_to_field_matches_testdata_vectors` in `src/test.rs`, which transcribes the hex values as literals rather than reading the JSON. Update both together. + +Regenerating `constraints.baseline` with the command in its header overwrites that header, and CI strips comments before diffing, so nothing flags the loss. Restore the header by hand. + ## The documentation set `docs/` is a specification, not commentary, and it is the single largest maintenance hazard in this module — doc-consistency fixes outnumber code commits on this branch. @@ -54,7 +75,7 @@ Most facts now have exactly one owning section and are linked from everywhere el | Content | Owner | Copies live in | |:---|:---|:---| | `Clawback` is a `T₀` anchor alongside `Merge` | `docs/protocol/wallet-state.md#recovery` | `docs/compliance.md#wallet-and-auditor-consequences`, the role column of `docs/indexer.md#events-in-scope` | -| Per-circuit public-input counts | the `Public inputs` heading of each `docs/protocol/operations/*.md` and `docs/compliance.md#circuit` | header comments of `circuits/*/src/main.nr`, `circuits/CLAUDE.md` | +| Per-circuit public-input counts | the `Public inputs` heading of each `docs/protocol/operations/*.md` and `docs/compliance.md#circuit` | header comments of `circuits/*/src/main.nr` | | Domain-separation tag values | `docs/protocol/domain-separators.md` | `circuits/lib/src/lib.nr`, `circuits/lib/testdata/*.json` | The tags are a cross-language wire contract. `docs/protocol/domain-separators.md` is their only authoritative source: it assigns every value, states which layer absorbs each, and states which subset `circuits/lib/src/lib.nr` implements. Changing any assigned value is a new deployment, not an upgrade. diff --git a/packages/confidential/README.md b/packages/confidential/README.md index d52fa0005..ab1ec6936 100644 --- a/packages/confidential/README.md +++ b/packages/confidential/README.md @@ -4,6 +4,19 @@ A Soroban contract suite that provides SEP-41 tokens with **private balances and The protocol provides **confidentiality, not anonymity** — sender and recipient addresses remain visible on-chain; amounts and balances do not. +This crate is part of the [OpenZeppelin Stellar Contracts](https://github.com/OpenZeppelin/stellar-contracts) library, which is published as separate crates on [crates.io](https://crates.io): + +- [stellar-access](https://crates.io/crates/stellar-access): Role-based access controls and ownable +- [stellar-accounts](https://crates.io/crates/stellar-accounts): Smart accounts with custom authentication and authorization +- **[stellar-confidential](https://crates.io/crates/stellar-confidential)**: Confidential token with encrypted balances and zero-knowledge proofs +- [stellar-contract-utils](https://crates.io/crates/stellar-contract-utils): Utilities for contracts (pausable, upgradeable, cryptography, etc.) +- [stellar-fee-abstraction](https://crates.io/crates/stellar-fee-abstraction): Fee abstraction utilities +- [stellar-governance](https://crates.io/crates/stellar-governance): Governance utilities (governor, votes, timelock) +- [stellar-macros](https://crates.io/crates/stellar-macros): Proc macros (`#[only_owner]`, `#[when_not_paused]`, etc.) +- [stellar-tokens](https://crates.io/crates/stellar-tokens): Token types (fungible, non-fungible, real-world assets, vaults) + +Refer to the [OpenZeppelin for Stellar Contracts](https://docs.openzeppelin.com/stellar-contracts) page for additional information. + ## Layout ```text @@ -67,6 +80,16 @@ A turnkey [`Hooks`] implementation layering deployer-configurable controls on to Noir sources, build scripts, and the pinned UltraHonk VKs that the verifier registry serves. Regeneration is gated on a CI diff against the committed `circuits/vks/*.vk.json` files; see [`circuits/vks/README.md`](./circuits/vks/README.md) for the toolchain pin and re-extraction procedure. +## Installation + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +# We recommend pinning to a specific version, because rapid iterations are expected as the library is in an active development phase. +stellar-confidential = "=0.8.0" +``` + ## Documentation Start with [`docs/overview.md`](./docs/overview.md) for the design without mathematics, then read the protocol specification from [`docs/protocol/README.md`](./docs/protocol/README.md) onward; each file links to the next. [`docs/README.md`](./docs/README.md) maps the whole set: reading paths per role, the compliance, selective-disclosure, indexer, and SDK companions, and the citation rules that CI enforces with lychee. diff --git a/packages/confidential/circuits/CLAUDE.md b/packages/confidential/circuits/CLAUDE.md deleted file mode 100644 index e5e46e52c..000000000 --- a/packages/confidential/circuits/CLAUDE.md +++ /dev/null @@ -1,96 +0,0 @@ -# Confidential Circuits — Agent Guide - -Scoped to `packages/confidential/circuits/`. Read alongside the root `CLAUDE.md` and `../CLAUDE.md`. - -This tree is Noir, built by `nargo` — **not** part of the Cargo workspace. Nothing in `Cargo.toml` references it and nothing here references `Cargo.toml`. `Architecture.md` §"Noir Circuits" explains the package model (`lib` vs measurement-only `bin` gadgets vs operation circuits); it is not repeated here. - -## Commands - -Run from this directory. CI is `.github/workflows/noir.yml`. - -| Task | Command | -|:---|:---| -| Type-check | `nargo check` | -| Test | `nargo test` | -| Per-primitive constraint counts | `nargo info` | -| Compile one circuit | `nargo compile --package circuit_` | -| Regenerate verification keys | `./scripts/extract_vks.sh` | -| Check no witness reaches a lookup table | `./scripts/check_witness_lookups.sh` | - -There is no `nargo fmt` step in CI and no formatter config — Noir formatting is unenforced. The workflow triggers only on `circuits/**`, so a change to the Rust-side parity test in `../test.rs` does **not** run this job. - -## Traps - -### `compiler_version = "=1.0.0"` is deliberate - -It appears in all fourteen package `Nargo.toml` files — the workspace manifest `circuits/Nargo.toml` carries only `[workspace]` — and looks like a mistake. Nargo requirements cannot name prereleases, so the real toolchain — **nargo 1.0.0-beta.11 + bb 0.87.0**, pinned in `.github/workflows/noir.yml` — is documented in the comment above it instead. Do not "correct" this to `=1.0.0-beta.11`. - -### Do not prune unused public inputs - -`_acct_f` in `register/src/main.nr` is referenced by no gate and looks like dead code. It is the replay binding: UltraHonk absorbs every public input into the transcript, so a proof produced for one account fails when the contract assembles the blob for another. Removing it lets anyone replay a legitimate registration's published proof and payload to mint duplicate-key accounts. `clawback/src/main.nr` carries four such bindings — `addr_f`, `_acct_f`, `_dest_f`, `_nonce` — removing `_dest_f` lets a compromised clawback signer settle a witness to a destination of its own choosing, and removing `_nonce` lets an approved proof execute again once the commitments are restored. Each operation circuit declares its exact public-input count in a header comment — clawback 11, withdraw 16, transfer / spender_transfer 25, set_spender 26 — and the count is part of the contract with the on-chain assembler. - -### `as_witness` in `commit` and `scalar_mul` is not dead code - -`as_witness(G, value)` looks like an identity wrapper around a constant. It keeps bb off its fixed-base lookup tables: proofs are non-zk, so the read-count commitments would publish which table rows each secret scalar's windows hit. The doc comment on `as_witness` lists what keeps the generator a witness. `scripts/check_witness_lookups.sh` fails CI on any `multi_scalar_mul` with a constant base point and on any blackbox outside its plookup-free allowlist; extend the allowlist only after confirming bb lowers the new blackbox without lookups. - -### Package names are load-bearing - -Directory `transfer/` is package `circuit_transfer`; `gadgets/commit/` is `gadget_commit`; the library is `stellar_confidential_lib`. `scripts/extract_vks.sh` derives `circuit_${name}` and `target/${pkg}.json` from a bare name, and every row of `constraints.baseline` is keyed on the package name. Renaming a directory without matching the package name breaks both. Gadgets depend on the lib via `../../lib`, operations via `../lib`. - -### Never hash raw - -`poseidon_with_domain` is the only Poseidon entry point in `lib/src/lib.nr`; calling the underlying hash directly is a violation of the library contract. The domain tag is always the first absorbed element. The numeric tag values are the cross-language contract with the SDK — see `../CLAUDE.md` and `../docs/protocol/domain-separators.md`, which is their only authoritative source. - -Sponge parameters, the canonical lane assignment, and the mode-exclusivity rule that follows from a single-block absorb are normative in `../docs/protocol/primitives.md#poseidon2-hash`; the Noir sponge must match it exactly. The obligations that section places on this code: `sponge_squeeze_2(d,s,σ)[0]` must stay equal to `poseidon_with_domain(d,[s,σ])`, and `sponge_squeeze_3(d,s,σ)[0..2]` must stay equal to `sponge_squeeze_2(d,s,σ)` — which is why `sponge_squeeze_2` is defined as the prefix of `sponge_squeeze_3`. A divergence in either silently changes every existing mask. - -`AUDITOR_SENDER` is always squeezed three-wide; `AUDITOR_RECIPIENT` is always two-wide; every other tag goes through `poseidon_with_domain`. Widening or narrowing a channel is a spec change. - -`lane[2]` carries the blinding of a commitment the operation writes — `r'` on W_a5 / T_a9 / S_a6, `r_a'` on O_a9. Tag 17 (`ESCROWED_ALLOWANCE_BLINDING_AUDITOR`) escrows `r_a` off-sponge at S14; the construction is specified in `../docs/protocol/auditing.md#auditor-side-allowance-blinding-escrow`. - -ECDH must absorb both `S.x` and `S.y`; x-only extraction collapses `P` and `-P`. - -The `G` and `H` generators are hardcoded but provenance-checked at runtime by the `print_generators` test; re-extract with `nargo test print_generators --show-output` rather than editing the constants by hand. - -## Committed artifacts - -Four kinds of generated file are committed: `constraints.baseline`, `vks/*.vk.json`, `vks/*.vk.bin`, and `lib/testdata/*.json`. CI regenerates and diffs all four. (`Architecture.md` claims `testdata/*.json` is the only one — that statement is stale.) `target/` and `Prover.toml` are gitignored. - -### `constraints.baseline` - -Normalized `nargo info` output. Regenerate with the command in its own header: - -```bash -LC_ALL=C nargo info | grep '^|' | LC_ALL=C sort > constraints.baseline -``` - -`LC_ALL=C` is mandatory on **both** sides of the pipe — byte order is the only ordering stable between macOS and the Ubuntu runner. The redirect overwrites the file's header comments; re-paste them, because CI's failure message asks for them. - -One non-obvious consequence: adding or removing a **gadget** changes the baseline even when no circuit logic changed. The baseline is the only place the ACIR opcode counts are recorded; the docs cite it rather than quoting the numbers. - -### `vks/` - -`./scripts/extract_vks.sh` compiles each circuit and runs `bb write_vk -s ultra_honk --output_format fields`. The `fields` format is required, not a preference: bb's `bytes` format carries platform-dependent header bytes that break macOS↔Linux diffs. - -Adding a circuit means **four** edits — the package itself, the `members` list in `Nargo.toml`, and the hardcoded `CIRCUITS` arrays in `scripts/extract_vks.sh` and `scripts/build_vk_bins.sh` — then regenerating the baseline and both VK formats. - -Proving uses non-default flags: `bb prove -s ultra_honk --oracle_hash keccak`. Keccak is required because the on-chain verifier reproduces the Fiat-Shamir transcript with Keccak while bb defaults to `poseidon2`. Do **not** pass `--zk`; the verifier implements only the non-zk `ultra_flavor`. This recipe is provisional until the verifier settles the zero-knowledge setting. - -Drift policy: if the circuit changed, regenerate in the same PR. If the **toolchain** drifted, do not regenerate — investigate first. - -### `lib/testdata/` - -Fixtures are not auto-generated. Changing a primitive is a three-step lockstep: - -1. `nargo test print_fixtures --package stellar_confidential_lib --show-output` -2. Update the matching `testdata/*.json` -3. Update the hardcoded expected values in the `fixtures_match_testdata` test in `lib/src/tests.nr` - -`fixtures_match_testdata` is the in-Noir guard that fails CI. The sponge vectors are additionally hoisted into `global SPONGE_SQUEEZE_2_*` / `SPONGE_SQUEEZE_3_*` constants in the same file — a fourth site. - -`address_to_field.json` is the exception. That derivation has no Noir implementation at all (circuits take `addr_f` as an opaque public input), so it is the one primitive with two independent implementations. Its guard is the Rust test `address_to_field_matches_testdata_vectors` in `../test.rs`, which **transcribes the hex values as string literals** rather than reading the JSON — update both together or neither. Its inputs are 56-character SEP-23 strkeys, and the lo/hi 28-byte limbs are little-endian. - -Note the standing obligation on the future TS SDK (`../docs/sdk/conformance.md#primitive-fixtures`): its tests must *read* these JSON files rather than transcribe them, so that a change to `print_fixtures` output becomes a test failure instead of a silent divergence. Do not copy the Rust test's transcription pattern into new consumers. - -## Version bumps - -`.github/workflows/noir.yml` is the source of truth for `NARGO_VERSION` and `BB_VERSION`, and the two must be bumped together — the VK pipeline is byte-sensitive to bb. The string `1.0.0-beta.11` is duplicated across all fourteen package `Nargo.toml` files, `constraints.baseline`, `vks/README.md` (which also restates the bb version), and this file. A bump touches all of them and requires regenerating both the baseline and the VKs. The installer scripts in CI are pinned to git commits with SHA256 verification; bump URL and hash together. diff --git a/packages/contract-utils/README.md b/packages/contract-utils/README.md index 27eff3aaf..a64dedd1d 100644 --- a/packages/contract-utils/README.md +++ b/packages/contract-utils/README.md @@ -6,6 +6,7 @@ This crate is part of the [OpenZeppelin Stellar Contracts](https://github.com/Op - [stellar-access](https://crates.io/crates/stellar-access): Role-based access controls and ownable - [stellar-accounts](https://crates.io/crates/stellar-accounts): Smart accounts with custom authentication and authorization +- [stellar-confidential](https://crates.io/crates/stellar-confidential): Confidential token with encrypted balances and zero-knowledge proofs - **[stellar-contract-utils](https://crates.io/crates/stellar-contract-utils)**: Utilities for contracts (pausable, upgradeable, cryptography, etc.) - [stellar-fee-abstraction](https://crates.io/crates/stellar-fee-abstraction): Fee abstraction utilities - [stellar-governance](https://crates.io/crates/stellar-governance): Governance utilities (governor, votes, timelock) @@ -115,7 +116,7 @@ impl Ownable for ExampleContract {} ### Crypto -The `crypto` module provides cryptographic utilities including hash functions and Merkle tree verification. +The `crypto` module provides cryptographic utilities including hash functions, Merkle tree verification, and Grumpkin curve arithmetic. #### Usage Examples @@ -135,6 +136,7 @@ pub fn hash_data(e: &Env, data: Bytes) -> BytesN<32> { - **Hash Functions**: SHA-256 and Keccak-256 implementations - **Merkle Verification**: Verify Merkle proofs for data integrity - **Utility Functions**: Hash pairs and commutative hashing +- **Grumpkin**: Affine point arithmetic (add, sub, neg, scalar mul) and point validation on the Grumpkin curve, built on the BN254 scalar-field host functions ### Merkle Distributor @@ -150,6 +152,8 @@ The `merkle_distributor` module implements a Merkle-based claim distribution sys The `math` module provides fixed-point arithmetic: a `Wad` decimal type with 18 decimal places, and free functions for `x * y / denominator` on both `i128` and `I256` with an explicit rounding direction. +`Wad` also provides the natural logarithm (`ln`), the natural exponential (`exp`), and powers with an integer (`powi`) or a `Wad` (`powf`) exponent. + Each operation comes in a panicking and a checked variant. The panicking variants raise `SorobanFixedPointError::Overflow` (1500) when the result overflows; the checked variants return `None`. `Wad`'s operators (`+`, `-`, `*`, `/`) work directly on `i128` and panic with a native arithmetic error instead (see the `# Overflow` section on `Wad`). #### Usage Examples @@ -196,9 +200,9 @@ Add this to your `Cargo.toml`: ```toml [dependencies] # We recommend pinning to a specific version, because rapid iterations are expected as the library is in an active development phase. -stellar-contract-utils = "=0.7.1" +stellar-contract-utils = "=0.8.0" # Add this if you want to use macros -stellar-macros = "=0.7.1" +stellar-macros = "=0.8.0" ``` ## Examples diff --git a/packages/fee-abstraction/README.md b/packages/fee-abstraction/README.md index f4fcd35d0..33e6e3260 100644 --- a/packages/fee-abstraction/README.md +++ b/packages/fee-abstraction/README.md @@ -6,6 +6,7 @@ This crate is part of the [OpenZeppelin Stellar Contracts](https://github.com/Op - [stellar-access](https://crates.io/crates/stellar-access): Role-based access controls and ownable - [stellar-accounts](https://crates.io/crates/stellar-accounts): Smart accounts with custom authentication and authorization +- [stellar-confidential](https://crates.io/crates/stellar-confidential): Confidential token with encrypted balances and zero-knowledge proofs - [stellar-contract-utils](https://crates.io/crates/stellar-contract-utils): Utilities for contracts (pausable, upgradeable, cryptography, etc.) - **[stellar-fee-abstraction](https://crates.io/crates/stellar-fee-abstraction)**: Fee abstraction utilities - [stellar-governance](https://crates.io/crates/stellar-governance): Governance utilities (governor, votes, timelock) @@ -63,7 +64,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] # We recommend pinning to a specific version, because rapid iterations are expected as the library is in an active development phase. -stellar-fee-abstraction = "=0.7.1" +stellar-fee-abstraction = "=0.8.0" ``` ### Examples diff --git a/packages/governance/README.md b/packages/governance/README.md index 204296947..ff72b29da 100644 --- a/packages/governance/README.md +++ b/packages/governance/README.md @@ -6,6 +6,7 @@ This crate is part of the [OpenZeppelin Stellar Contracts](https://github.com/Op - [stellar-access](https://crates.io/crates/stellar-access): Role-based access controls and ownable - [stellar-accounts](https://crates.io/crates/stellar-accounts): Smart accounts with custom authentication and authorization +- [stellar-confidential](https://crates.io/crates/stellar-confidential): Confidential token with encrypted balances and zero-knowledge proofs - [stellar-contract-utils](https://crates.io/crates/stellar-contract-utils): Utilities for contracts (pausable, upgradeable, cryptography, etc.) - [stellar-fee-abstraction](https://crates.io/crates/stellar-fee-abstraction): Fee abstraction utilities - **[stellar-governance](https://crates.io/crates/stellar-governance)**: Governance utilities (governor, votes, timelock) @@ -146,7 +147,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] # We recommend pinning to a specific version, because rapid iterations are expected as the library is in an active development phase. -stellar-governance = "=0.7.1" +stellar-governance = "=0.8.0" ``` ## Examples diff --git a/packages/macros/README.md b/packages/macros/README.md index 78f7a614a..90c4c44a2 100644 --- a/packages/macros/README.md +++ b/packages/macros/README.md @@ -6,6 +6,7 @@ This crate is part of the [OpenZeppelin Stellar Contracts](https://github.com/Op - [stellar-access](https://crates.io/crates/stellar-access): Role-based access controls and ownable - [stellar-accounts](https://crates.io/crates/stellar-accounts): Smart accounts with custom authentication and authorization +- [stellar-confidential](https://crates.io/crates/stellar-confidential): Confidential token with encrypted balances and zero-knowledge proofs - [stellar-contract-utils](https://crates.io/crates/stellar-contract-utils): Utilities for contracts (pausable, upgradeable, cryptography, etc.) - [stellar-fee-abstraction](https://crates.io/crates/stellar-fee-abstraction): Fee abstraction utilities - [stellar-governance](https://crates.io/crates/stellar-governance): Governance utilities (governor, votes, timelock) @@ -108,7 +109,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] # We recommend pinning to a specific version, because rapid iterations are expected as the library is in an active development phase. -stellar-macros = "=0.7.1" +stellar-macros = "=0.8.0" ``` ## Examples diff --git a/packages/tokens/README.md b/packages/tokens/README.md index 96593ef67..de0858174 100644 --- a/packages/tokens/README.md +++ b/packages/tokens/README.md @@ -6,6 +6,7 @@ This crate is part of the [OpenZeppelin Stellar Contracts](https://github.com/Op - [stellar-access](https://crates.io/crates/stellar-access): Role-based access controls and ownable - [stellar-accounts](https://crates.io/crates/stellar-accounts): Smart accounts with custom authentication and authorization +- [stellar-confidential](https://crates.io/crates/stellar-confidential): Confidential token with encrypted balances and zero-knowledge proofs - [stellar-contract-utils](https://crates.io/crates/stellar-contract-utils): Utilities for contracts (pausable, upgradeable, cryptography, etc.) - [stellar-fee-abstraction](https://crates.io/crates/stellar-fee-abstraction): Fee abstraction utilities - [stellar-governance](https://crates.io/crates/stellar-governance): Governance utilities (governor, votes, timelock) @@ -163,9 +164,9 @@ Add this to your `Cargo.toml`: ```toml [dependencies] # We recommend pinning to a specific version, because rapid iterations are expected as the library is in an active development phase. -stellar-tokens = "=0.7.1" +stellar-tokens = "=0.8.0" # Add this if you want to use macros -stellar-macros = "=0.7.1" +stellar-macros = "=0.8.0" ``` ## Examples @@ -174,7 +175,7 @@ See the following examples in the repository: - [`examples/fungible-pausable/`](https://github.com/OpenZeppelin/stellar-contracts/tree/main/examples/fungible-pausable) - Pausable fungible token - [`examples/nft-sequential-minting/`](https://github.com/OpenZeppelin/stellar-contracts/tree/main/examples/nft-sequential-minting) - Basic non-fungible token - [`examples/fungible-merkle-airdrop/`](https://github.com/OpenZeppelin/stellar-contracts/tree/main/examples/fungible-merkle-airdrop) - Airdrop with merkle proofs -- [`examples/rwa/`](https://github.com/OpenZeppelin/stellar-contracts/tree/main/examples/rwa) - A complete RWA contract suite and a step-by-step deployment guide. +- [`examples/rwa/`](https://github.com/OpenZeppelin/stellar-contracts/tree/main/examples/rwa) - A complete RWA contract suite, ready-made compliance modules, and a step-by-step deployment guide. ## License diff --git a/packages/zk-email/README.md b/packages/zk-email/README.md new file mode 100644 index 000000000..2ab68dee3 --- /dev/null +++ b/packages/zk-email/README.md @@ -0,0 +1,16 @@ +# Stellar zkEmail + +> [!Warning] +> This package is under development and not ready for use. Its API may change without notice, and it is not published on crates.io. + +zkEmail utilities for Stellar contracts: on-chain email verification using zero-knowledge proofs of DKIM signatures. + +## Modules + +### DKIM Registry + +The `dkim_registry` module is the on-chain trust anchor for a zkEmail system. It stores which DKIM public key hashes are valid for which domains, so that a proof verifier can confirm the key that signed an email is still trusted. + +## License + +This package is part of the Stellar Contracts library and follows the same licensing terms. diff --git a/packages/zk-email/src/lib.rs b/packages/zk-email/src/lib.rs index 08c70ab09..a8a97f52a 100644 --- a/packages/zk-email/src/lib.rs +++ b/packages/zk-email/src/lib.rs @@ -1,5 +1,8 @@ //! zkEmail utilities for Stellar contracts. //! +//! **This crate is under development and not ready for use.** Its API may +//! change without notice. +//! //! This crate provides modules for on-chain email verification using //! zero-knowledge proofs of DKIM signatures.