Skip to content

Latest commit

 

History

History
123 lines (89 loc) · 6.62 KB

README.md

File metadata and controls

123 lines (89 loc) · 6.62 KB

Soroban Contracts — Backend Integration Reference

This directory contains the Soroban smart contract workspace for ManageHub.

Backend ↔ Contract Interface

The NestJS backend interacts with the payment_escrow contract via a hand-written client at backend/src/payments/soroban/escrow-contract.client.ts.

Required Entrypoints

The backend expects exactly these four public functions on the deployed contract:

fn create(escrow_id: BytesN<32>, payer: Address, beneficiary: Address, amount: i128)
fn release(escrow_id: BytesN<32>)
fn refund(escrow_id: BytesN<32>)
fn get_status(escrow_id: BytesN<32>) -> u32
Method Backend caller Purpose
create buildCreateTx() Lock funds in a new escrow
release buildReleaseTx() Release escrowed funds to the beneficiary
refund buildRefundTx() Refund escrowed funds to the payer
get_status getEscrowStatus() (simulate) Read-only status check, never submitted

Status Code Mapping

The get_status return value maps to the backend's EscrowStatus enum (escrow-status.enum.ts):

Raw u32 Contract State Backend EscrowStatus
1 Locked LOCKED
2 Released RELEASED
3 Refunded REFUNDED
4 Completed (fully released in instalments) -

A missing escrow is not a status code: get_status returns Err(Error::NotFound), which surfaces to clients as Error(Contract, #1). The backend maps that error to NOT_FOUND.

Error Codes

Code Error Meaning
1 NotFound No escrow exists for the id
2 AlreadyResolved The escrow is no longer Locked
3 InvalidAmount Amount must be positive
4 AlreadyExists An escrow with this id already exists
5 ArithmeticOverflow Checked arithmetic failed
20 AmountExceedsEscrow A partial release would exceed the locked amount
21 NothingToRefund Nothing remains to refund

Amount Units and Token Decimals

amount is an i128 in the escrowed token's smallest unit, not fiat minor units. The backend stores fiat amounts in minor units (cents); it must convert to token units before building the transaction:

token_units = round_half_up(fiat_minor_units * 10^token_decimals / 10^fiat_decimals / rate)

Rounding is applied once, on the backend, to the token amount; the contract never rounds. Most Stellar assets use 7 decimals.

Worked example: 50.00 USD paid in a token pegged 1:1 to USD with 7 decimals. The payment record holds 5000 (cents); 5000 * 10^7 / 10^2 = 500_000_000 token units, which is the amount passed to create. Partial releases use the same unit and satisfy released <= amount.

Configuration Variables

These environment variables bind the backend to the on-chain contract (see soroban-config.ts):

Variable Description
SOROBAN_ENABLED "true" to activate the Stellar escrow rail; any other value disables it
STELLAR_ESCROW_CONTRACT_ID StrKey-encoded address of the deployed payment_escrow contract
STELLAR_NETWORK Stellar network passphrase (e.g. Test SDF Network ; September 2015)
STELLAR_RPC_URLS Comma-separated Soroban RPC endpoints
STELLAR_SECRET_KEY Treasury/operator secret key for signing releases and refunds
STELLAR_BENEFICIARY_ADDRESS Default beneficiary Stellar address

Escrow ID Derivation

The backend derives escrow IDs as the SHA-256 hash of the Payment entity UUID, passed to the contract as BytesN<32>. See escrow-submission.processor.ts for the exact derivation.

Arithmetic Safety (CT-73)

Amount-handling paths must use checked arithmetic (checked_add / checked_sub) rather than raw + / -. revenue_distribution already does this for its basis-point sum. payment_escrow stores a single amount per escrow and performs no arithmetic on it today; when partial releases or batch totals are added they must use the same checked pattern inline.

Workspace Crates

Crate Purpose
payment_escrow Escrow lifecycle (create → release / refund)

Additional crates (e.g. resource_credits, staking_rewards) should be added as workspace members in Cargo.toml as they are developed.

Tooling

Security

  • SECURITY.md — trust model and pre-deployment checklist (CT-68).
  • UPGRADE.md — contract upgrade/migration path (CT-69).

On-chain scope decisions

  • Settlement batches (execute / retry / abandon) are modelled off-chain only, in the backend settlement-batch.entity.ts. There is no on-chain batch contract, so the placeholder settlement_batch_lifecycle tests were removed.
  • Split allocation property tests and the escrow-to-distribution integration test were placeholders with no assertions. They are removed until the behaviour they describe exists on-chain; add them back with real assertions (a proptest dev-dependency and both contracts registered in one Env) together with that feature.
  • cargo test --workspace now runs natively in CI together with cargo fmt --check, cargo clippy -- -D warnings and a WASM build.