Security model
What you sign, what the contract can and cannot do, and the risks that remain.
No custody, ever
Sama never holds your tokens. The API cannot move them, and the settlement contract only moves what an exact, fully signed plan says, straight from one wallet to another. Its token balance is zero before and after every settlement, and the verifier checks that on every round.
What you sign
| Signature | It authorizes | It cannot |
|---|---|---|
| Intent (EIP-712) | Your limits for one round: per asset, the most you send and receive | Move any token |
| Plan approval (EIP-712) | One exact plan: every leg, amount, round, price snapshot and deadline | Be reused for a different plan, or after it settles |
| Token allowance | The contract may move the exact amount of one token you send in the plan | Exceed that amount |
What the contract enforces
- Time window: a plan settles only between its
validAfterandvalidUntil. - Everyone signed: one valid approval per participant, EOA or ERC-1271 smart wallet.
- No replay: each plan settles at most once; each (owner, nonce) is consumed once.
- Canonical plans: participants and legs must be sorted, non-zero, and every party must be a participant. No participant can be idle.
- All or nothing: one failed
transferFromreverts the whole plan. - Nothing else: no owner, no upgrade, no fee, no oracle, no stored funds. It is
nonReentrant.
What the server checks
- Your balances are read from the chain, never taken from the browser.
- A reported settlement hash is accepted only if the transaction calls this round's contract, on the right chain, with exactly this round's plan. A member cannot post an unrelated transaction to fail a round.
- State-changing requests from an origin outside the allowlist are refused before any handler runs.
- Sign-in tokens are verified with Privy on the server; the session is an HTTP-only cookie.
- Round state changes are compare-and-set, so a retried request never doubles a signature or a step.
Risks that remain
| Risk | Mitigation |
|---|---|
| The contract is not externally audited | Plans are capped at $500 crossed until an audit; Foundry unit, fuzz and mainnet-fork tests cover custody, replay, tampering and reverts |
| An issuer pauses or blocks a token | Status is read before a plan; a blocked wallet is left out. If it happens mid-round the settlement reverts and nothing moves |
| A price source is wrong or stale | Tier A prices are cross-checked on-chain; any asset that fails is left out of the round |
| A participant never approves | The plan expires after 30 minutes; nothing moves |
| You change your mind after approving | Call cancelNonce on the contract before settlement |
Reporting an issue
Found a vulnerability? Please report it privately to the team before disclosing it publicly, with steps to reproduce. Do not test against other people's funds.