Burn redeemed inventory (warehouse NOT refreshed): admin clawback + DECREMENT minted so the freed cap can be re-minted when new barrels arrive — keeping tokens 1:1 with physical barrels.
fn burn(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
from: soroban_sdk::Address,
barrels: i128,
) -> Result<(), soroban_sdk::Error>
Cap-enforced mint of whole barrels of sac (authorize → mint → de-authorize).
fn mint(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
to: soroban_sdk::Address,
barrels: i128,
) -> Result<(), soroban_sdk::Error>
fn admin(env: soroban_sdk::Env) -> Option
fn pause(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
fn price(env: soroban_sdk::Env, sac: soroban_sdk::Address) -> Option
fn kyc_ok(env: soroban_sdk::Env, account: soroban_sdk::Address) -> bool
fn minted(env: soroban_sdk::Env, sac: soroban_sdk::Address) -> i128
fn resume(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
fn fee_bps(env: soroban_sdk::Env, sac: soroban_sdk::Address) -> u32
Admin sets an account's GLOBAL KYC/whitelist flag (valid for every commodity).
fn kyc_set(
env: soroban_sdk::Env,
account: soroban_sdk::Address,
allowed: bool,
) -> Result<(), soroban_sdk::Error>
Dual-controlled per-asset fee change (admin = multisig). In-contract so callers can't pass 0.
fn set_fee(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
fee_bps: u32,
) -> Result<(), soroban_sdk::Error>
Remediation clawback via the SAC (requires AUTH_CLAWBACK_ENABLED). Does NOT touch minted —
use burn for redemption burns that should free the cap.
fn clawback(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
from: soroban_sdk::Address,
barrels: i128,
) -> Result<(), soroban_sdk::Error>
fn is_paused(env: soroban_sdk::Env, sac: soroban_sdk::Address) -> bool
The asset's price-oracle hot key pushes its current USD price (USDC stroops per 1 barrel).
fn set_price(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
value: i128,
) -> Result<(), soroban_sdk::Error>
Platform/custodian DISTRIBUTION of existing inventory to a KYC'd buyer (the buy settlement).
from must be an allow-listed distributor for sac; NO fee (the buy fee is in the price).
fn distribute(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
from: soroban_sdk::Address,
to: soroban_sdk::Address,
barrels: i128,
) -> Result
fn is_settled(env: soroban_sdk::Env, settlement_id: soroban_sdk::BytesN<32>) -> bool
fn max_supply(env: soroban_sdk::Env, sac: soroban_sdk::Address) -> i128
Explicit freeze/unfreeze of a single account for sac (de-authorize / authorize its trustline).
fn set_frozen(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
account: soroban_sdk::Address,
frozen: bool,
) -> Result<(), soroban_sdk::Error>
fn kyc_manager(env: soroban_sdk::Env) -> Option
fn accept_admin(env: soroban_sdk::Env) -> Result<(), soroban_sdk::Error>
Constructor — sets the GLOBAL admin (issuer cold multisig). Commodities are onboarded
afterwards via register_asset. Runs once, atomically, at deploy.
fn __constructor(env: soroban_sdk::Env, admin: soroban_sdk::Address)
fn is_registered(env: soroban_sdk::Env, sac: soroban_sdk::Address) -> bool
fn propose_admin(
env: soroban_sdk::Env,
new_admin: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
Redeem escrow — a KYC'd holder moves inventory INTO a platform holding/escrow wallet (an
allow-listed distributor to) to start a physical redemption. User-signed, NO fee.
fn redeem_escrow(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
from: soroban_sdk::Address,
to: soroban_sdk::Address,
barrels: i128,
) -> Result
fn cancel_upgrade(env: soroban_sdk::Env) -> Result<(), soroban_sdk::Error>
The doorman — the only path a regulated asset moves peer-to-peer. Atomic authorize → transfer → de-authorize, then the USDC fee (priced off this asset's fresh pushed oracle; fail-closed).
fn gated_transfer(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
from: soroban_sdk::Address,
to: soroban_sdk::Address,
barrels: i128,
) -> Result
fn is_distributor(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
account: soroban_sdk::Address,
) -> bool
Onboard a commodity: register its asset config. Admin-only. The contract must ALSO be made
the SAC admin of sac (issuer/old-controller calls set_admin/transfer_sac_admin → this
contract). initial_minted seeds the cap counter with supply already in circulation (0 for a
fresh asset; the current minted total when migrating behind an existing SAC).
fn register_asset(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
usdc: soroban_sdk::Address,
treasury: soroban_sdk::Address,
price_oracle: soroban_sdk::Address,
max_supply: i128,
fee_bps: u32,
initial_minted: i128,
) -> Result<(), soroban_sdk::Error>
Admin: repoint an asset's transfer-fee USDC SAC. Used to migrate the fee
currency to the canonical USDC when an asset was registered against a
legacy USDC issuer (so gated_transfer pulls the fee in a USDC holders
actually trust). Only cfg.usdc changes — supply, cap, treasury, oracle
and fee_bps are untouched.
fn set_asset_usdc(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
usdc: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
Admin: adjust the asset's max-supply cap. Set at registration, then this governed setter lets the admin RAISE the ceiling (e.g. more warehouse stock now backs the token) or lower it — but NEVER below what is already minted, which would strand outstanding supply. Same require_admin gate as mint/set_fee, so it is M-of-N once the admin account is multisig.
fn set_max_supply(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
new_max: i128,
) -> Result<(), soroban_sdk::Error>
fn execute_upgrade(
env: soroban_sdk::Env,
expected_hash: soroban_sdk::BytesN<32>,
) -> Result<(), soroban_sdk::Error>
fn propose_upgrade(
env: soroban_sdk::Env,
new_wasm_hash: soroban_sdk::BytesN<32>,
) -> Result<(), soroban_sdk::Error>
Admin registers/de-registers an inventory wallet allowed to distribute/receive redeem_escrow
for sac (platform distribution wallet, or a 3rd-party-custodian wallet later).
fn set_distributor(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
distributor: soroban_sdk::Address,
allowed: bool,
) -> Result<(), soroban_sdk::Error>
Set the dedicated KYC-manager address (admin-only). Splits HOT kyc_set from the COLD M-of-N admin: pointed at a hot single-key, kyc_set stays a fast single-sig settlement op while mint/clawback/pause/upgrade require M-of-N. Defaults to the admin until set (so behaviour is unchanged pre-split and on upgraded contracts).
fn set_kyc_manager(
env: soroban_sdk::Env,
manager: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
Batched distribution: settle MANY buys in ONE transaction (one sequence number) — the
throughput primitive for the adaptive settlement worker. from (an allow-listed distributor)
is authorized ONCE for the whole batch. Each leg is idempotent (skips an already-Settled
settlement_id, so a retried batch can't double-send) and skip-and-continue (a leg whose
recipient is not KYC'd / amount is invalid is SKIPPED, not reverted — one bad leg can't sink
the batch). NO fee. Returns the number actually settled this call.
fn distribute_batch(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
from: soroban_sdk::Address,
items: soroban_sdk::Vec,
) -> Result
Escape hatch: hand one asset's SAC admin to a new address (A→B opening / future migration).
fn transfer_sac_admin(
env: soroban_sdk::Env,
sac: soroban_sdk::Address,
new_admin: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
fn get_pending_upgrade(env: soroban_sdk::Env) -> Option<(soroban_sdk::BytesN<32>, u64)>