SUP · Docs

Delegation policy

A Sup Wallet is a smart-contract vault. Delegation lets someone other than the owner spend from it — but only under rules the owner sets. A delegate isn't just an address: it is whoever or whatever can satisfy the rules attached to the wallet — an address, a transferable capability object, another contract, a ZK proof, a machine, or an AI agent.

This is the Sui TransferPolicy model applied to spending: a delegated spend produces a SpendRequest hot potato that confirm_spend only cashes out once the owner's rules approve it.

#Two kinds of rule

  • Auth rules (OR) — prove who the principal is. At least one must pass. Built-in: CapAuth (holds a DelegateCap), ScopedAuth (holds a budgeted ScopedCap).
  • Caveat rules (AND) — prove the spend is allowed. Every one must pass. Built-in: ScopedBudget (per-cap budget), RecipientAllowlist (reference third-party rule).

A spend is released iff: policy version current ∧ ≥1 auth rule stamped ∧ every caveat rule stamped. A rule can only read the request and stamp (or abort) — it can never change the amount or recipient, so a buggy or malicious rule can only block the people who opted into it.

#The principal ladder — "a delegate can be anything"

Delegate is…Rule
an addressAddressAuth
a key / agent / zkSend linkCapAuth (holds a DelegateCap)
a contractCapAuth (the cap lives in the contract's field)
a sub-delegate (attenuated)ScopedAuth (budget ≤ parent)
a ZK proof / 8183 assessora custom rule

#Quickstart (SDK)

Owner turns on the policy and issues a cap-based delegate:

const sup = createSupWalletClient({ network: "testnet", runtime });

await sign(sup.initializePolicy({ walletId }));
await sign(sup.addAuthRule({ walletId, ruleType: sup.capAuthRuleType() }));

// mint a bearer cap to the delegate (an address, an agent, a contract that stores it…)
await sign(sup.mintDelegateCap({ walletId, recipient: agentAddress }));

The delegate spends by holding the cap:

await sign(sup.capSpend({ walletId, capId, coinType: SUI, amount: 30n, recipient }));

Add a condition (a third-party caveat rule):

await sign(sup.addCaveatRule({ walletId, ruleType: sup.recipientAllowlistRuleType() }));
await sign(sup.createAllowlist({ walletId }));
await sign(sup.allowlistAllow({ allowlistId, recipient }));
// spends must now satisfy CapAuth AND the allowlist:
await sign(sup.capSpendWithAllowlist({ walletId, capId, allowlistId, coinType: SUI, amount: 30n, recipient }));

#Sub-delegation (attenuation)

A ScopedCap carries a per-coin budget. Its holder can subdelegate part of it to a child cap (budget moved from parent, depth + 1), so a child can never outspend its grant and no chain exceeds the root.

await sign(sup.mintScopedRoot({ walletId, coinType: SUI, budget: 100n, maxDepth: 2, recipient: agent }));
await sign(sup.subdelegate({ capId, amount: 40n, recipient: subAgent }));
await sign(sup.scopedSpend({ walletId, capId: childCapId, coinType: SUI, amount: 25n, recipient }));

#Revocation

await sign(sup.revokeAllPolicies({ walletId })); // bumps version — kills every outstanding cap at once

#Recipes — policies worth building

Auth (OR) and caveat (AND) rules compose, so a handful of small rules cover a surprising range of real arrangements. Each row is a policy you can ship today:

You want…Compose
An AI trading deskScopedCap (daily budget) + recipient allowlist (only approved DEX contracts) + a time window
Payroll / treasury opsa bearer/scoped cap per payee + recipient allowlist + a monthly velocity limit
A subscription keeperscoped budget + recipient = the service + a per-period cadence caveat
A family allowancea scoped cap per member + a kid's daily cap + spend-category envelopes
A DAO sub-treasurysub-delegated scoped caps down a hierarchy + a quorum (co-sign) caveat over a threshold
Inheritance / dead-man switcha cap-gated unmetered payout + an inactivity gate (releases after N silent days)
Milestone escrowa caveat that only stamps once an oracle/attestation marks delivery
In-app / gaming spenda small bearer cap to the game contract + a recipient allowlist

The pattern to internalize: start from the tightest cap that still works (a scoped budget, not a bare bearer cap), then add caveats to express the "but only if…". A bearer cap with no caveats is unlimited — treat it like a hot wallet, not a policy.

#Open by design

Auth and caveat rules are separately deployed packages anyone can write and list in the rule marketplace. See Build a policy rule. Historical address + allowance data remains preserved while the TEE policy path is completed.

#Design it with an agent

Composing a safe policy (which auth/caveat rules, recipes, the foot-guns) is packaged as an installable skill so your coding agent designs it with you.

📥 View / download the skill → /llms/delegation-design.md  ·  on GitHub: view · raw

Save it for your agent: curl -sL $SUP/llms/delegation-design.md -o SKILL.md. For your wallet's actual policy, the 🛡 Delegation policy panel has an in-app "✨ Ask AI" assistant grounded in its live state.