Settlement
All settlement happens on-chain via USDC on Base. Per-request, immediate, non-custodial.
How It Works
1. Response completes → server extracts token usage
2. Cost calculated at seller's listed price (sellerAmount)
3. Fee calculated: buyerAmount = sellerAmount × feeMultiplier / 10000 + flatFee
4. settle() called on Settlement contract (via UUPS proxy):
- Pulls sellerAmount from buyer's wallet → sends to seller (or payout address)
- Pulls fee from buyer's wallet → sends to feeRecipient
- All in one Base transaction (~$0.001 gas)
Fee Structure
Two components, both configurable on-chain by addresses with ADMIN_ROLE:
- feeMultiplier — basis points (10000 = 0% fee, 10300 = 3% fee)
- flatFee — fixed USDC amount per settlement (covers gas costs)
Current settings: feeMultiplier=10000 (0%), flatFee=0
Minimum feeMultiplier: 10000 (1.0x). Sub-1x subsidy mode is not supported.
Anyone can verify on-chain via calculateFee(sellerAmount) (free view call).
Buyer Setup
Buyers call usdc.approve(proxyAddress, amount) once. Funds stay in their wallet — nothing is locked. They can revoke approval at any time.
The proxy address is permanent — contract upgrades don't require re-approval.
Example
Input: 1,847 tokens Output: 3,201 tokens
Seller: $12/M input, $48/M output
Fee: 0% + $0.001038 flat
Input cost: $0.02216
Output cost: $0.15365
sellerAmount: $0.17581
buyerAmount: $0.17581 × 10000/10000 + $0.001038 = $0.176848
Sent to seller: $0.17581
Sent to fee recipient: $0.001038
Gas: ~$0.001
Payout Address
Sellers can set an optional payout_address to direct settlement to a different wallet. Use cases:
- Route to a Bankr wallet for automatic LLM credit top-up
- Send to a treasury or multisig
- Separate selling identity from payment destination
Failed Settlements
If a settlement fails after inference has already run, the usage row is marked failed and queued in pending_settlements. A cron job retries with exponential backoff for up to 5 attempts.
If all retries fail, the row is marked permanently_failed and removed from the retry queue. There is no automatic insurance pool or automatic seller reimbursement today. The seller is not paid on-chain until a settlement succeeds or the operator manually reconciles it. For API-key settlement, this means the seller can eat the upstream provider cost if the buyer's balance/allowance disappears and retries never settle. For x402/MPP/operator-mediated settlement, the buyer may already have paid the operator; seller payment still depends on the operator settlement succeeding or being manually remediated.
Contract
SettlementV2 deployed behind a UUPS proxy on Base. Source at contracts/SettlementV2.sol.
- UUPS proxy (permanent address, buyers approve once)
- Role-based access control via
OPERATOR_ROLE,ADMIN_ROLE,UPGRADER_ROLE, andDEFAULT_ADMIN_ROLE - Implementation upgradeable by
UPGRADER_ROLEwithout buyer re-approval - No contract-level timelock today
settle(buyer, seller, sellerAmount)— execute settlementcalculateFee(sellerAmount)→ (buyerAmount, fee) — free view callfeeMultiplier()→ current multiplier in basis pointsflatFee()→ current flat fee in USDC unitsfeeRecipient()→ where fees go
ADMIN_ROLE:setFeeMultiplier(uint256),setFlatFee(uint256),setFeeRecipient(address)DEFAULT_ADMIN_ROLE: grant/revoke rolesUPGRADER_ROLE:upgradeToAndCall(address, bytes)
Current limitation: there is no on-chain timelock or multisig requirement enforced by the contract. A role holder can change fee parameters or upgrade in a single transaction. The current feeMultiplier is 10000, and buyers can limit exposure by approving only the amount they are willing to spend.
For x402/MPP, the buyer pays/authorizes payment to the SI operator path first, then SI pays the selected seller via operator-mediated settlement. This avoids route-locking issues where a 402 challenge might name one seller but failover chooses another. Seller payout is still visible as a Base USDC transfer when settlement succeeds.