You want an AI agent to execute trades on your behalf -- picking venues, routes, and parameters autonomously. But you need guarantees that the agent can't drain your wallet, pick a malicious venue, or cause unbounded losses.
Traditional approaches require whitelisting every program, instruction format, and parameter. This is brittle, high-maintenance, and breaks whenever a new DEX or aggregator launches.
Swig is a role-based smart wallet protocol on Solana. Its key architectural property is that permissions are enforced post-execution by comparing account snapshots taken before and after CPI execution.
This means you can give an agent broad execution authority while confining the outcomes rather than the inputs.
A Swig wallet owner creates a role with:
| Permission | Purpose |
|---|---|
ProgramAll or ProgramCurated |
Agent can CPI to any (or curated) DEX programs |
TokenLimit / TokenRecurringLimit |
Caps total token outflow (absolute or per time window) |
TokenDestinationLimit |
Caps token outflow to specific destinations |
SolLimit / SolRecurringLimit |
Caps SOL outflow |
AllButManageAuthority |
Prevents the agent from modifying its own permissions |
The role is bound to a session key (Ed25519Session, Secp256r1Session, or ProgramExecSession) so the agent's access is time-limited.
The agent constructs a SignV2 transaction with whatever CPI instructions it chooses -- any DEX, any route, any parameters. Swig executes the CPIs with its wallet PDA as the signer.
After all CPIs complete, Swig enforces the confinement:
Pre-execution:
SHA256 hash all classified accounts (excluding mutable balance fields)
Post-execution:
1. Verify all hashes match (no unauthorized state mutations)
2. Measure balance deltas on all token/SOL/stake accounts
3. Check deltas against the role's spending limits
4. Reject the entire transaction if any limit is exceeded
If a malicious venue tries to drain tokens, the spending limit catches it. If a program tries to mutate account data it shouldn't, the hash integrity check catches it.
- Stack height check:
SignV2must be top-level -- other programs can't CPI into Swig to bypass checks - Monotonic role IDs: Prevent role ID reuse attacks
- Token account validation: Authority must be the Swig wallet PDA, delegates are rejected
- Session expiration: Slot-based expiry bounds temporal exposure
Venue-agnostic confinement. The agent can discover new aggregators, use novel routes, or compose multiple CPIs. The limits hold because enforcement is on outcomes, not instructions. No allowlist maintenance required.
Defense against malicious programs. If the agent is tricked into CPI-ing to a program that steals tokens, the spending limit caps the loss. The hash integrity check prevents unauthorized state changes beyond tracked balance fields.
No privilege escalation. The agent can't grant itself more permissions, create sub-accounts, or modify the wallet's authority structure.
Composable with external validation. For stronger guarantees (e.g., ratio-based slippage), combine with ProgramExec authority -- see below.
Swig's spending limits are one-sided bounds -- they cap how much the agent can lose, but don't enforce execution quality:
- Agent sends 100 USDC to a DEX, receives 0 SOL back -- passes Swig if 100 USDC is within
TokenLimit - Agent picks a venue with 20% slippage vs. 0.1% elsewhere -- passes Swig either way
The limits prevent catastrophic loss but don't optimize for good execution.
Configure ProgramScope actions that track the output token account's balance field. Set limits on how much that field can decrease. This provides an absolute floor on the output side -- not a ratio, but a hard minimum.
Build a small on-chain program that:
- Takes expected input/output amounts and a minimum ratio as instruction data
- Validates the ratio meets a threshold
- Passes the Swig config + wallet accounts as its first two accounts
The agent's role uses ProgramExec authority bound to this oracle program. The agent must call the oracle first (which validates the trade parameters), and that successful call authenticates the subsequent Swig SignV2. Spending limits remain as a backstop.
Transaction layout:
IX 0: SlippageOracle::validate(min_ratio=0.99, input=100 USDC, expected_output=X SOL)
accounts[0] = swig_config
accounts[1] = swig_wallet_address
IX 1: Swig::SignV2(role_id=N, authority_payload=[sysvar_ix_index])
CPI -> DEX swap instruction
Most DEX instructions have a minimum_amount_out parameter. The AI agent sets this. Swig's limits then serve as defense-in-depth if the agent sets a bad minimum or the DEX has a bug.
This maps to a clean ocap confinement pattern:
- Session key = the capability (time-limited, unforgeable token of authority)
- Permission set = the confinement membrane (attenuates the capability to bounded asset transfers)
- Post-execution hash check = integrity guarantee (membrane can't be bypassed by creative CPI composition)
- ProgramExec = powerbox-style delegation (agent can only act if a trusted program vouches for the operation)
The agent holds a confined capability: it can do anything within the membrane, and the membrane is defined by outcomes, not by enumerating allowed actions.
| Property | Mechanism |
|---|---|
| Bounded loss per transaction | TokenLimit, SolLimit |
| Bounded loss per time window | TokenRecurringLimit, SolRecurringLimit |
| Destination restrictions | TokenDestinationLimit, SolDestinationLimit |
| Venue flexibility | ProgramAll or ProgramCurated |
| No privilege escalation | AllButManageAuthority (excludes ManageAuthority + SubAccount) |
| Time-bounded access | Session keys with slot-based expiration |
| State integrity | Post-execution SHA256 hash verification |
| Execution quality (optional) | ProgramExec + custom oracle program |
Swig provides a practical confinement model for AI agents: let the agent be creative about how it executes, while bounding what it can cost you.