One-time constructor, run atomically at deploy
(stellar contract deploy … -- --admin … --usdc_token …). There is no
separate initialize call and thus no uninitialized window; the config
is guaranteed present the instant the contract exists.
quote_signer is the raw ed25519 public key of the off-chain quote
signer. network_id binds quotes to this deployment's network
(testnet = 1, mainnet = 2).
fn __constructor(
env: soroban_sdk::Env,
admin: soroban_sdk::Address,
usdc_token: soroban_sdk::Address,
attester: soroban_sdk::Address,
quote_signer: soroban_sdk::BytesN<32>,
default_ttl_ledgers: u32,
network_id: u32,
) -> Result<(), soroban_sdk::Error>
Sole entry point for user payments. Validates the backend-signed
quote, pulls amount USDC from the payer into escrow, and creates the
order in Paid status.
Validation runs in a fixed order, so the first failing condition determines the error surfaced: paused -> denylist -> treasury/enabled -> amount -> quote expiry -> signature -> duplicate intent -> balance/allowance.
Token movement uses SEP-41 transfer_from with the router as spender,
which is why the payer must have approved the router beforehand.
fn pay_order(
env: soroban_sdk::Env,
intent_id: soroban_sdk::BytesN<32>,
payer: soroban_sdk::Address,
amount: i128,
service_type: ServiceType,
quote_expires_at_ledger: u32,
signature: soroban_sdk::BytesN<64>,
) -> Result<(), soroban_sdk::Error>
Attester confirms off-chain fulfillment. Releases escrowed USDC to the
service treasury and stores the opaque fulfillment_ref_hash.
Remains callable while paused, after the refund TTL (as long as the
order is still Paid), and for disabled
services (disabling only blocks new payments).
fn attest_fulfillment(
env: soroban_sdk::Env,
intent_id: soroban_sdk::BytesN<32>,
fulfillment_ref_hash: soroban_sdk::BytesN<32>,
) -> Result<(), soroban_sdk::Error>
Returns escrowed USDC to the payer.
Until expires_at_ledger + REFUND_GRACE_LEDGERS, only the attester may
refund (AttesterInitiated). On or after that point the call is
permissionless (TtlExpired) — no auth is required from anyone. The
grace window past the nominal TTL gives the attester an exclusive
settlement buffer so a slightly-late attest_fulfillment cannot be
front-run by a permissionless refund. Remains callable while paused.
fn refund(
env: soroban_sdk::Env,
intent_id: soroban_sdk::BytesN<32>,
) -> Result<(), soroban_sdk::Error>
Full order record. Errors with OrderNotFound if unknown.
fn get_order(
env: soroban_sdk::Env,
intent_id: soroban_sdk::BytesN<32>,
) -> Result
Order lifecycle status. Errors with OrderNotFound if unknown.
fn get_order_status(
env: soroban_sdk::Env,
intent_id: soroban_sdk::BytesN<32>,
) -> Result
Global configuration.
fn get_config(env: soroban_sdk::Env) -> Result
Treasury configuration for a service type.
fn get_treasury(
env: soroban_sdk::Env,
service_type: ServiceType,
) -> Result
Whether an address is denylisted.
fn is_denied(env: soroban_sdk::Env, address: soroban_sdk::Address) -> bool
Transfer the admin role. Emits config_updated attributed to the
acting (outgoing) admin.
fn set_admin(
env: soroban_sdk::Env,
new_admin: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
Rotate the attester.
fn set_attester(
env: soroban_sdk::Env,
new_attester: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
Rotate the quote signer (raw ed25519 public key).
fn set_quote_signer(
env: soroban_sdk::Env,
new_signer: soroban_sdk::BytesN<32>,
) -> Result<(), soroban_sdk::Error>
Configure a service treasury. Must be called for a ServiceType
before that service accepts payments.
Routing is by service_type, resolved at settlement time: an Order
stores only its service, not a treasury snapshot. Changing a service's
treasury_address therefore redirects settlement of already-Paid
orders for that service to the new address (see the
set_treasury_rotation_redirects_settlement test). Rotate with that in
mind, or drain in-flight orders first.
fn set_treasury(
env: soroban_sdk::Env,
service_type: ServiceType,
treasury_address: soroban_sdk::Address,
enabled: bool,
ttl_ledgers: Option,
) -> Result<(), soroban_sdk::Error>
Emergency pause. Blocks pay_order only; attest_fulfillment and
refund remain callable for existing Paid orders.
fn set_paused(env: soroban_sdk::Env, paused: bool) -> Result<(), soroban_sdk::Error>
Update the default refund window. Affects only orders paid after the
change; existing orders keep their recorded expires_at_ledger.
fn set_default_ttl(
env: soroban_sdk::Env,
ledgers: u32,
) -> Result<(), soroban_sdk::Error>
Block an address from calling pay_order. Does not affect refunds of
existing escrow (the payer must always be refundable).
fn add_to_denylist(
env: soroban_sdk::Env,
address: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
Unblock an address.
fn remove_from_denylist(
env: soroban_sdk::Env,
address: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>