From 189cced143f8cd62d3f3e97619eaa5df32217cf2 Mon Sep 17 00:00:00 2001 From: SunDrive Auto Date: Sat, 25 Jul 2026 13:51:35 +0000 Subject: [PATCH 1/5] docs: add compliance contract to mainnet deployment checklist Add compliance-contract deployment and initialization steps to the ceremony checklist in docs/MAINNET_DEPLOYMENT.md, including admin address handling, initial allowlist state, and compliance-specific admin key handling guidance. --- docs/MAINNET_DEPLOYMENT.md | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/docs/MAINNET_DEPLOYMENT.md b/docs/MAINNET_DEPLOYMENT.md index e75d95a..42c3748 100644 --- a/docs/MAINNET_DEPLOYMENT.md +++ b/docs/MAINNET_DEPLOYMENT.md @@ -31,15 +31,36 @@ Set these via environment variables or in a `.env.mainnet` file. Scripts will fa 4. Verify WASM hashes match the deployment issue. 5. Submit deployment transactions through the approved signer. 6. Record transaction hashes and deployed contract IDs. -7. Update backend production secrets with: - - `INVOICE_CONTRACT_ID` - - `TREASURY_CONTRACT_ID` - - `COMPLIANCE_CONTRACT_ID` -8. Run backend `GET /health/rpc` and a low-value end-to-end invoice payment smoke test. +7. Deploy and initialize the compliance contract: + - Deploy the compliance WASM to Soroban mainnet. + - Call `initialize` with the protocol admin address. + - Populate the initial allowlist with the admin, treasury signers, and any pre-approved merchants by calling `allow_address` for each. + - Record the `COMPLIANCE_CONTRACT_ID` in the ceremony log. +8. Deploy and initialize the invoice contract: + - Deploy the invoice WASM to Soroban mainnet. + - Call `initialize` with the protocol admin address and the deployed compliance contract address. + - Configure the grace window via `set_grace_window` if the default is not appropriate. + - Record the `INVOICE_CONTRACT_ID` in the ceremony log. +9. Deploy and initialize the treasury contract: + - Deploy the treasury WASM to Soroban mainnet. + - Call `initialize` with the protocol admin address, the list of initial signers and their weights, and the required approval threshold. + - Record the `TREASURY_CONTRACT_ID` in the ceremony log. +10. Update backend production secrets with: + - `INVOICE_CONTRACT_ID` + - `TREASURY_CONTRACT_ID` + - `COMPLIANCE_CONTRACT_ID` +11. Run backend `GET /health/rpc` and a low-value end-to-end invoice payment smoke test. + +## Compliance-Specific Admin Key Handling + +- The compliance contract's admin keypair **must** be distinct from the invoice and treasury admin keypairs where possible to limit blast radius in the event of key compromise. +- The compliance admin key must be stored in a separate KMS key or hardware wallet from other contract admin keys. +- During signing ceremony, the compliance `initialize` and `allow_address` transactions should be signed and submitted **before** the invoice contract is initialized, because the invoice contract references the compliance contract at initialization time. ## Abort Conditions - Any signer mismatch - Any WASM hash mismatch - Soroban RPC health degraded across all configured endpoints +- Compliance contract initialization fails or `is_allowed` returns unexpected results for the initial allowlist - Any failed low-value payment smoke test From 1ebadb632640599c9d34f0d83cbc685806b58685 Mon Sep 17 00:00:00 2001 From: SunDrive Auto Date: Sat, 25 Jul 2026 13:51:35 +0000 Subject: [PATCH 2/5] docs: document compliance contract usage examples Add a compliance contract section to docs/contract-interaction-guide.md with realistic example transactions for allow_address, block_address, allow_address_until, transfer_admin/accept_admin, and clear_address alongside existing invoice and treasury examples. --- docs/contract-interaction-guide.md | 306 +++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100644 docs/contract-interaction-guide.md diff --git a/docs/contract-interaction-guide.md b/docs/contract-interaction-guide.md new file mode 100644 index 0000000..4a114c0 --- /dev/null +++ b/docs/contract-interaction-guide.md @@ -0,0 +1,306 @@ +# Contract Interaction Guide + +This guide provides realistic `soroban` CLI examples for interacting with the three COMEBACKHERE contracts — **invoice**, **treasury**, and **compliance** — deployed on Stellar testnet or mainnet. + +> **Prerequisites** +> +> - [Soroban CLI](https://developers.stellar.org/docs/soroban/soroban-cli) installed +> - Contract IDs for each deployed contract +> - A funded Stellar account with its secret key configured locally: +> +> ```sh +> soroban config identity generate alice +> soroban config identity fund alice +> ``` + +--- + +## Common Flags + +All examples assume the following aliased flags. Adjust values for your network. + +```sh +# Testnet +NETWORK="--network testnet" +RPC="--rpc-url https://soroban-testnet.stellar.org" +PASSPHRASE="--network-passphrase 'Test SDF Network ; September 2025'" + +# Mainnet +# NETWORK="--network mainnet" +# RPC="--rpc-url https://soroban-mainnet.stellar.org" +# PASSPHRASE="--network-passphrase 'Public Global Stellar Network ; September 2025'" + +# Shortcut alias +SOROBAN="soroban contract invoke $NETWORK $RPC $PASSPHRASE" +``` + +--- + +## Invoice Contract + +### Create an Invoice + +```sh +$SOROBAN \ + --id \ + --source alice \ + -- \ + create_invoice \ + --merchant "$(soroban config identity address alice)" \ + --amount_usdc 10000000 \ + --gross_usdc 10500000 \ + --expires_in_seconds 3600 \ + --metadata_hash "0xabcd...1234" \ + --payment_link_hash "0xef56...7890" +``` + +### Mark an Invoice as Paid + +```sh +$SOROBAN \ + --id \ + --source admin \ + -- \ + mark_paid \ + --invoice_id 1 \ + --payer "$(soroban config identity address bob)" +``` + +### Request a Refund + +```sh +$SOROBAN \ + --id \ + --source bob \ + -- \ + request_refund \ + --invoice_id 1 +``` + +### Release Escrow + +```sh +$SOROBAN \ + --id \ + --source admin \ + -- \ + release_escrow \ + --invoice_id 1 +``` + +--- + +## Treasury Contract + +### Propose a Settlement + +```sh +$SOROBAN \ + --id \ + --source signer_a \ + -- \ + propose_settlement \ + --merchant_address "$(soroban config identity address merchant)" \ + --token_contract "$(soroban config identity address usdc)" \ + --amount 10000000 \ + --memo "Invoice #1 settlement" +``` + +### Approve a Settlement + +```sh +$SOROBAN \ + --id \ + --source signer_b \ + -- \ + approve_settlement \ + --settlement_id 1 +``` + +### Execute a Settlement + +```sh +$SOROBAN \ + --id \ + --source signer_a \ + -- \ + execute_settlement \ + --settlement_id 1 +``` + +### Raise a Dispute + +```sh +$SOROBAN \ + --id \ + --source bob \ + -- \ + raise_dispute \ + --settlement_id 1 \ + --reason "Goods not received" +``` + +--- + +## Compliance Contract + +The **compliance** contract maintains an allowlist of Stellar addresses permitted to participate in the protocol. It supports temporary grants, full blocking, and secure admin delegation. + +### Check if an Address Is Allowed + +```sh +$SOROBAN \ + --id \ + --source alice \ + -- \ + is_allowed \ + --address "$(soroban config identity address alice)" +``` + +Returns `true` if the address is currently allowlisted. + +### Add an Address to the Allowlist (`allow_address`) + +Permanently adds a Stellar address to the allowlist. Only the contract admin may call this. + +```sh +$SOROBAN \ + --id \ + --source admin \ + -- \ + allow_address \ + --address "$(soroban config identity address merchant)" +``` + +After execution, `is_allowed` returns `true` for the merchant address. + +### Block an Address (`block_address`) + +Removes a Stellar address from the allowlist entirely, revoking all participation rights. + +```sh +$SOROBAN \ + --id \ + --source admin \ + -- \ + block_address \ + --address "$(soroban config identity address malicious_actor)" +``` + +The blocked address can be re-added later with another `allow_address` call. + +### Allow an Address Until a Specific Time (`allow_address_until`) + +Grants temporary access until a specified Unix timestamp (in seconds). After the timestamp passes, `is_allowed` returns `false` for that address. + +```sh +# Allow merchant until January 1, 2027 00:00:00 UTC +$SOROBAN \ + --id \ + --source admin \ + -- \ + allow_address_until \ + --address "$(soroban config identity address merchant)" \ + --until 1798761600 +``` + +### Clear an Address (`clear_address`) + +Resets an address's compliance state to its default (neither explicitly allowed nor blocked). This is useful for cleaning up after a temporary grant expires or resetting a test address. + +```sh +$SOROBAN \ + --id \ + --source admin \ + -- \ + clear_address \ + --address "$(soroban config identity address merchant)" +``` + +### Admin Transfer Flow (`transfer_admin` / `accept_admin`) + +Admin ownership of the compliance contract is transferred in two steps to prevent accidental lockout. + +**Step 1 — Current admin nominates a new admin:** + +```sh +$SOROBAN \ + --id \ + --source admin \ + -- \ + transfer_admin \ + --new_admin "$(soroban config identity address new_admin)" +``` + +**Step 2 — The nominated admin accepts the role:** + +```sh +$SOROBAN \ + --id \ + --source new_admin \ + -- \ + accept_admin +``` + +After step 2 completes, `new_admin` becomes the contract admin and the previous admin loses admin privileges. + +> **Note:** If `accept_admin` is never called, the original admin remains in control. There is no timeout on the pending transfer. + +--- + +## Cross-Contract Workflow + +A typical end-to-end flow touches all three contracts: + +1. **Compliance**: Admin adds the merchant to the allowlist (`allow_address`). +2. **Invoice**: Merchant creates an invoice (`create_invoice`). +3. **Invoice**: Admin marks the invoice as paid (`mark_paid`). +4. **Invoice**: Admin releases escrow (`release_escrow`). +5. **Treasury**: A signer proposes settlement (`propose_settlement`). +6. **Treasury**: Additional signers approve (`approve_settlement`). +7. **Treasury**: A signer executes the settlement (`execute_settlement`). + +```sh +# 1. Allowlist the merchant +$SOROBAN --id --source admin -- \ + allow_address --address "$(soroban config identity address merchant)" + +# 2. Create and process the invoice +$SOROBAN --id --source merchant -- \ + create_invoice --merchant "$(soroban config identity address merchant)" \ + --amount_usdc 10000000 --gross_usdc 10500000 --expires_in_seconds 86400 + +$SOROBAN --id --source admin -- \ + mark_paid --invoice_id 1 --payer "$(soroban config identity address payer)" + +# 3. Settle through the treasury +$SOROBAN --id --source signer_a -- \ + propose_settlement --merchant_address "$(soroban config identity address merchant)" \ + --token_contract --amount 10000000 --memo "Invoice #1" + +$SOROBAN --id --source signer_b -- \ + approve_settlement --settlement_id 1 + +$SOROBAN --id --source signer_a -- \ + execute_settlement --settlement_id 1 +``` + +## Reference: Function Signatures + +| Contract | Function | Key Parameters | +|--------------|------------------------|-------------------------------------------------------------------------------------------------------------------------------------| +| Invoice | `create_invoice` | `merchant`, `amount_usdc`, `gross_usdc`, `expires_in_seconds`, `metadata_hash?`, `payment_link_hash?` | +| Invoice | `mark_paid` | `invoice_id`, `payer` | +| Invoice | `request_refund` | `invoice_id` | +| Invoice | `release_escrow` | `invoice_id` | +| Treasury | `propose_settlement` | `merchant_address`, `token_contract`, `amount`, `memo?` | +| Treasury | `approve_settlement` | `settlement_id` | +| Treasury | `execute_settlement` | `settlement_id` | +| Treasury | `raise_dispute` | `settlement_id`, `reason?` | +| Compliance | `is_allowed` | `address` — returns `true` if the address is allowlisted | +| Compliance | `allow_address` | `address` | +| Compliance | `block_address` | `address` | +| Compliance | `allow_address_until` | `address`, `until: u64` | +| Compliance | `transfer_admin` | `new_admin` | +| Compliance | `accept_admin` | _(no params)_ | +| Compliance | `clear_address` | `address` | From eb4ed354de9bbfb6685ca21c8d4511c102e96cfe Mon Sep 17 00:00:00 2001 From: SunDrive Auto Date: Sat, 25 Jul 2026 13:51:44 +0000 Subject: [PATCH 3/5] docs: document payer frontend wallet setup for testnet Add a comebackhere-frontend-specific walkthrough section to docs/TESTNET_ONBOARDING.md covering browser wallet setup (Freighter/xBull), testnet funding via Friendbot, USDC acquisition, network configuration (soroban.ts env vars), wallet connection steps, and troubleshooting. --- docs/TESTNET_ONBOARDING.md | 136 +++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 docs/TESTNET_ONBOARDING.md diff --git a/docs/TESTNET_ONBOARDING.md b/docs/TESTNET_ONBOARDING.md new file mode 100644 index 0000000..b9a5c0b --- /dev/null +++ b/docs/TESTNET_ONBOARDING.md @@ -0,0 +1,136 @@ +# Testnet Onboarding Guide + +This guide walks through setting up a browser wallet on Stellar testnet for use with **comebackhere-frontend** — the payer-facing application where users pay invoices and request refunds. + +> **Note:** For the merchant dashboard (admin/signer UI), see `comebackhere-frontend`'s own setup docs in that repository. This guide focuses on the **payer** experience. + +--- + +## Prerequisites + +- A browser-based Stellar wallet (e.g., [Freighter](https://www.freighter.app/) or [xBull](https://xbull.app/)) +- Chrome, Firefox, or Brave browser + +--- + +## Step 1: Install and Configure a Wallet + +### Freighter (Recommended) + +1. Install the [Freighter](https://www.freighter.app/) browser extension. +2. Open Freighter and click **"Create a new wallet"** (or import an existing one). +3. Save your seed phrase in a secure location. +4. Once the wallet is created, click the network dropdown in the top-left corner and select **"Testnet"**. + +### xBull Wallet + +1. Install the [xBull](https://xbull.app/) browser extension. +2. Create a new wallet or import an existing one. +3. Open settings and switch the network to **"Testnet"**. + +--- + +## Step 2: Fund Your Wallet on Testnet + +Stellar provides a **Friendbot** service that sends free testnet XLM to any new account. + +### Via Freighter (Built-in) + +1. Open Freighter and navigate to your account. +2. Click the **"Fund with Friendbot"** button (only visible when the wallet is set to Testnet). + +### Via Stellar Laboratory + +1. Copy your Stellar public address (G...) from your wallet. +2. Open the [Stellar Laboratory Friendbot](https://laboratory.stellar.org/#create-account?network=testnet). +3. Paste your address into the **"Fund an account using Friendbot"** field. +4. Click **"Get testnet funds"**. + +### Via Stellar Quest + +1. Visit [Stellar Quest](https://quest.stellar.org/) and connect your wallet. +2. Complete any quest to earn testnet funds and USDC. + +### Verify the Funding + +After funding, check your balance in the wallet extension. You should see at least 10,000 testnet XLM. + +--- + +## Step 3: Obtain Testnet USDC + +Most invoices require USDC. You can obtain testnet USDC from the Stellar Testnet USDC issuer. + +### Via Laboratory Swap + +1. Go to the [Stellar Laboratory Payments page](https://laboratory.stellar.org/#xdr-viewer?network=testnet). +2. Use the **"Build Transaction"** tool to create a `ManageSellOffer` or trustline operation. +3. Alternatively, use the **Stellar Expert** or contact the protocol team for testnet USDC faucet access. + +### Via the COMEBACKHERE Testnet Faucet + +If a testnet faucet endpoint is available: + +```sh +curl -X POST https://faucet.testnet.comebackhere.dev/fund \ + -H "Content-Type: application/json" \ + -d '{"address": "G...YOUR_ADDRESS...", "amount_usdc": "10000000"}' +``` + +--- + +## Step 4: Connect Your Wallet to comebackhere-frontend + +### Network Configuration + +The frontend application (`comebackhere-frontend`) expects the following configuration. These values are already set in the testnet deployment, but you can verify them in the app's settings or `.env`: + +| Variable | Testnet Value | +|---------------------------|------------------------------------------------------------| +| `VITE_SOROBAN_RPC` | `https://soroban-testnet.stellar.org` | +| `VITE_HORIZON_URL` | `https://horizon-testnet.stellar.org` | +| `VITE_NETWORK_PASSPHRASE` | `Test SDF Network ; September 2025` | +| `VITE_API_URL` | Backend URL (e.g., `https://api.testnet.comebackhere.dev`) | + +> These variables are defined in `comebackhere-frontend/src/utils/soroban.ts`. If you are running the frontend locally, verify your `.env` values match the table above. + +### Connecting in the Browser + +1. Navigate to the **comebackhere-frontend** URL (e.g., `https://pay.testnet.comebackhere.dev`). +2. Click **"Connect Wallet"**. +3. Your browser wallet (Freighter/xBull) will prompt you to connect — approve the connection. +4. The app will verify that your wallet is on the **Testnet** network. If it detects `Public Global Stellar Network ; September 2025`, it will prompt you to switch to testnet. +5. Once connected, you will see your Stellar public address and balance in the top-right corner. + +--- + +## Step 5: Make a Test Payment + +1. Open a payment link or navigate to an invoice in the app. +2. Review the invoice details (merchant, amount, description). +3. Click **"Pay Invoice"**. +4. Your wallet will display the transaction for approval — verify the details and confirm. +5. Wait for the transaction to be confirmed (typically 3–5 seconds on testnet). +6. You will see a success confirmation. The invoice now shows as **Paid**. + +--- + +## Troubleshooting + +| Problem | Likely Cause | Solution | +|--------------------------------------|-------------------------------------------|------------------------------------------------| +| Wallet shows "Mainnet" | Network not switched to Testnet | Change wallet network to Testnet | +| "Insufficient balance" | No XLM or no USDC | Fund with Friendbot and obtain testnet USDC | +| "Network passphrase mismatch" | Wallet on wrong network | Reconnect wallet or switch to Testnet | +| Transaction fails with "Not allowed" | Payer address not on compliance allowlist | Contact the protocol admin to add your address | +| App shows "Connecting..." forever | Browser wallet extension not installed | Install Freighter or xBull and refresh | + +--- + +## Network Details + +- **Soroban RPC**: `https://soroban-testnet.stellar.org` +- **Horizon**: `https://horizon-testnet.stellar.org` +- **Network Passphrase**: `Test SDF Network ; September 2025` +- **Friendbot URL**: `https://friendbot.stellar.org` +- **Faucet (Stellar Lab)**: From 3f0751143fcbeb9eaa608203280e6b24e34595f2 Mon Sep 17 00:00:00 2001 From: SunDrive Auto Date: Sat, 25 Jul 2026 13:51:44 +0000 Subject: [PATCH 4/5] docs: add missing terms to glossary Add definitions for grace window, on-hold settlement, dispute quorum, and allowlist (compliance) to docs/glossary.md, keeping tone consistent with existing entries and cross-referencing the relevant contracts. --- docs/glossary.md | 99 +++++++++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 40 deletions(-) diff --git a/docs/glossary.md b/docs/glossary.md index 65c4906..d48b551 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -30,33 +30,36 @@ An optional SHA-256 (or equivalent) hash of off-chain invoice metadata (e.g. lin **payment_link_hash** An optional hash of a payment-link URI, enabling deterministic linking between on-chain state and an off-chain checkout page. +**Grace Window** +The duration (in seconds) after an invoice's `expires_at` during which payment is still accepted. Set by the contract admin via `set_grace_window`. A grace window allows for ledger drift and network congestion without forcing merchants to reissue invoices. Configurable per deployment; default matches the invoice contract's `DEFAULT_GRACE_WINDOW` constant. + ### InvoiceStatus -| Status | Meaning | -|-------------------|-------------------------------------------------------------------------| -| `Pending` | Created and awaiting payment. Can be paid, cancelled, or expired. | -| `Paid` | Marked paid by the admin. Payer and `paid_at` timestamp are recorded. | -| `Expired` | The ledger passed `expires_at` before payment. Set by `batch_expire`. | -| `Cancelled` | Cancelled by the merchant or admin before payment. | -| `RefundRequested` | The payer requested a refund on a paid invoice (initiates escrow dispute). | +| Status | Meaning | +|-------------------|-----------------------------------------------------------------------------| +| `Pending` | Created and awaiting payment. Can be paid, cancelled, or expired. | +| `Paid` | Marked paid by the admin. Payer and `paid_at` timestamp are recorded. | +| `Expired` | The ledger passed `expires_at` before payment. Set by `batch_expire`. | +| `Cancelled` | Cancelled by the merchant or admin before payment. | +| `RefundRequested` | The payer requested a refund on a paid invoice (initiates escrow dispute). | | `Released` | Escrow funds have been released to the merchant after payment confirmation. | ### InvoiceError -| Code | Name | Trigger | -|------|-----------------------|------------------------------------------------------------------| -| 1 | `Unauthorized` | Caller is not the merchant, admin, or payer. | -| 2 | `ContractPaused` | A state-changing call was made while the contract is paused. | -| 3 | `InvalidAmount` | `amount_usdc` ≤ 0 or `gross_usdc` < `amount_usdc`. | -| 4 | `NotPending` | Operation requires `Pending` status but invoice is in another state. | -| 5 | `Expired` | Payment attempted after `expires_at`. | -| 6 | `NotFound` | No invoice exists for the given ID. | -| 7 | `AlreadyInitialized` | `initialize` called when the contract is already set up. | -| 8 | `ZeroDuration` | `expires_in_seconds` was 0 on invoice creation. | -| 9 | `ExpiryOverflow` | `ledger_timestamp + expires_in_seconds` overflows `u64`. | -| 10 | `NotPaid` | `request_refund` or `release_escrow` called on a non-`Paid` invoice. | -| 12 | `AmountPrecision` | Amount is below 1 USDC (10,000,000 stroops). | -| 13 | `DuplicateNonce` | Merchant nonce has already been used for a previous invoice. | +| Code | Name | Trigger | +|------|----------------------|----------------------------------------------------------------------| +| 1 | `Unauthorized` | Caller is not the merchant, admin, or payer. | +| 2 | `ContractPaused` | A state-changing call was made while the contract is paused. | +| 3 | `InvalidAmount` | `amount_usdc` ≤ 0 or `gross_usdc` < `amount_usdc`. | +| 4 | `NotPending` | Operation requires `Pending` status but invoice is in another state. | +| 5 | `Expired` | Payment attempted after `expires_at`. | +| 6 | `NotFound` | No invoice exists for the given ID. | +| 7 | `AlreadyInitialized` | `initialize` called when the contract is already set up. | +| 8 | `ZeroDuration` | `expires_in_seconds` was 0 on invoice creation. | +| 9 | `ExpiryOverflow` | `ledger_timestamp + expires_in_seconds` overflows `u64`. | +| 10 | `NotPaid` | `request_refund` or `release_escrow` called on a non-`Paid` invoice. | +| 12 | `AmountPrecision` | Amount is below 1 USDC (10,000,000 stroops). | +| 13 | `DuplicateNonce` | Merchant nonce has already been used for a previous invoice. | --- @@ -77,25 +80,28 @@ The minimum cumulative signer weight required to execute a settlement. Set at in **Token Allowlist** An optional list of token contract addresses accepted for settlement. If non-empty, any unlisted token is rejected with `TokenNotAllowed`. +**On-Hold Settlement** +A settlement whose status is `OnHold`, meaning execution is blocked pending review. A settlement enters the on-hold state automatically when a dispute is raised against it. It can also be placed on hold by an admin for compliance, fraud, or KYC reasons (see `SettlementHoldReason`). An on-hold settlement cannot be executed until the hold is lifted. + ### SettlementStatus -| Status | Meaning | -|----------------------|-------------------------------------------------------------------------| -| `Pending` | Proposed and awaiting sufficient approvals. | -| `Executed` | Full amount transferred to the merchant. | -| `PartiallyExecuted` | A partial amount was transferred. | -| `OnHold` | Blocked from execution (compliance review or open dispute). | -| `Cancelled` | Cancelled by an authorised signer before execution. | +| Status | Meaning | +|---------------------|-------------------------------------------------------------| +| `Pending` | Proposed and awaiting sufficient approvals. | +| `Executed` | Full amount transferred to the merchant. | +| `PartiallyExecuted` | A partial amount was transferred. | +| `OnHold` | Blocked from execution (compliance review or open dispute). | +| `Cancelled` | Cancelled by an authorised signer before execution. | ### SettlementHoldReason -| Variant | Meaning | -|---------------------|-------------------------------------------------| -| `None` | Not on hold (default state). | -| `ComplianceReview` | Held pending a compliance review. | -| `FraudCheck` | Held for fraud investigation. | -| `KycPending` | Held until KYC verification is complete. | -| `AdminHold` | Held by an admin for an unspecified reason. | +| Variant | Meaning | +|--------------------|---------------------------------------------| +| `None` | Not on hold (default state). | +| `ComplianceReview` | Held pending a compliance review. | +| `FraudCheck` | Held for fraud investigation. | +| `KycPending` | Held until KYC verification is complete. | +| `AdminHold` | Held by an admin for an unspecified reason. | --- @@ -107,13 +113,16 @@ An on-chain record raised by a claimant against a counterparty over a specific s **resolution_weight** Cumulative weight of signers who have voted on the dispute resolution. When it reaches the treasury threshold the dispute transitions to `ResolvedClaimant` or `ResolvedCounterparty`. +**Dispute Quorum** +The minimum cumulative signer weight required to finalise a dispute resolution. This is the same value as the treasury's `threshold` — when the `resolution_weight` of signers who have voted reaches this threshold, the dispute transitions from `Raised` to `ResolvedClaimant` or `ResolvedCounterparty`. + ### DisputeStatus -| Status | Meaning | -|-------------------------|-----------------------------------------------------------------| -| `Raised` | Dispute created and awaiting resolution votes. | -| `ResolvedClaimant` | Resolved in favour of the claimant. | -| `ResolvedCounterparty` | Resolved in favour of the counterparty (merchant). | +| Status | Meaning | +|------------------------|----------------------------------------------------| +| `Raised` | Dispute created and awaiting resolution votes. | +| `ResolvedClaimant` | Resolved in favour of the claimant. | +| `ResolvedCounterparty` | Resolved in favour of the counterparty (merchant). | --- @@ -133,6 +142,16 @@ A governance process for replacing one authorised signer with another. The old s --- +## Compliance Terms + +**Allowlist (Compliance)** +The set of Stellar addresses permitted to interact with protocol contracts. Maintained by the compliance contract's admin via `allow_address`, `block_address`, `allow_address_until`, and `clear_address`. The contract exposes `is_allowed` to query whether a given address is currently on the allowlist. The invoice contract checks the compliance allowlist before marking invoices as paid. An address not on the allowlist (or explicitly blocked) is rejected with an `Unauthorized` error. + +**Allowlist (Token)** +See _Token Allowlist_ under Settlement Terms. + +--- + ## Cross-Contract Workflow Summary ``` From 1ccdd2c42b99f6e5974838d4159515b98a0741dc Mon Sep 17 00:00:00 2001 From: SunDrive Auto Date: Sat, 25 Jul 2026 13:51:53 +0000 Subject: [PATCH 5/5] style: fix markdownlint formatting in README Add blank lines around lists and code blocks in README.md to satisfy markdownlint rules (MD031, MD032). --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 83f4de3..fd7bfd6 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,12 @@ docker-compose up -d ``` This starts: + - **Soroban Node**: Stellar quickstart (Horizon at `http://localhost:8000`) - **Redis**: Event consumer backing service (port 6379) Check service health: + ```sh docker-compose ps curl http://localhost:8000/health