Summary
x402's upto scheme lets a client authorize a maximum spend and the server settle only actual usage. It's the scheme for metered APIs where cost isn't known until after execution — LLM inference, search, per-byte transfer. Stellar cannot express it today. @x402/stellar currently supports exact which sends the exact amount via SAC's transfer(from, to, amount).
Proposed mechanism
Stellar has the equivalent primitive natively in the SEP-41 token interface:
fn approve(env: Env, from: Address, spender: Address, amount: i128, live_until_ledger: u32);
fn transfer_from(env: Env, spender: Address, from: Address, to: Address, amount: i128);
approve(max) → transfer_from(actual). live_until_ledger gives native authorization expiry. EVM's Permit2 encodes deadlines manually.
scheme_upto.md requires each network binding to define four things; proposed Stellar answers:
| Requirement |
Proposed Stellar mechanism |
| Replay protection (Permit2-nonce equivalent) |
Soroban auth entry nonce |
Time-bound (validAfter / deadline) |
live_until_ledger + auth entry signatureExpirationLedger |
| Recipient binding |
to bound in the authorized invocation args |
| Settlement ≤ authorized max |
Enforced by allowance semantics; belt-and-braces check in a settle proxy |
Open design questions
- Who submits
approve, and does it cost an extra transaction? This is the crux. If approve needs its own submitted tx, upto costs 2 on-chain ops vs exact's 1, which may erase the benefit for small payments. Options: (a) facilitator submits both in sequence, (b) a Soroban settle-proxy the client authorizes once that internally does transfer_from with an enforced ceiling, (c) batch both into one transaction with multiple auth entries.
- Does fee sponsorship still hold?
exact on Stellar advertises areFeesSponsored: true. Need to confirm the allowance flow preserves zero-XLM-for-payer.
- Allowance hygiene. Does a partial
transfer_from leave a dangling allowance? live_until_ledger bounds it, but zeroing on settle may be cleaner.
- Proxy or no proxy? Raw SAC
approve/transfer_from may suffice, avoiding a deployed contract entirely — a meaningful simplification over EVM if it holds.
Acceptance criteria (this repo)
Written with Claude
Summary
x402's
uptoscheme lets a client authorize a maximum spend and the server settle only actual usage. It's the scheme for metered APIs where cost isn't known until after execution — LLM inference, search, per-byte transfer. Stellar cannot express it today.@x402/stellarcurrently supportsexactwhich sends the exact amount via SAC'stransfer(from, to, amount).Proposed mechanism
Stellar has the equivalent primitive natively in the SEP-41 token interface:
approve(max)→transfer_from(actual).live_until_ledgergives native authorization expiry. EVM's Permit2 encodes deadlines manually.scheme_upto.mdrequires each network binding to define four things; proposed Stellar answers:validAfter/deadline)live_until_ledger+ auth entrysignatureExpirationLedgertobound in the authorized invocation argsOpen design questions
approve, and does it cost an extra transaction? This is the crux. Ifapproveneeds its own submitted tx,uptocosts 2 on-chain ops vsexact's 1, which may erase the benefit for small payments. Options: (a) facilitator submits both in sequence, (b) a Soroban settle-proxy the client authorizes once that internally doestransfer_fromwith an enforced ceiling, (c) batch both into one transaction with multiple auth entries.exacton Stellar advertisesareFeesSponsored: true. Need to confirm the allowance flow preserves zero-XLM-for-payer.transfer_fromleave a dangling allowance?live_until_ledgerbounds it, but zeroing on settle may be cleaner.approve/transfer_frommay suffice, avoiding a deployed contract entirely — a meaningful simplification over EVM if it holds.Acceptance criteria (this repo)
examples/facilitatorverifies anuptopayload and settlesactualAmount ≤ authorizedMax/supportedadvertises{scheme: "upto", network: "stellar:testnet"}amountwith the actual settled valueactualAmount > authorizedMaxwith a spec-conformant errorWritten with Claude