User Proxy Security
The User Proxy has one owner per clone and no factory administrator. Its security boundary is the owner, the owner-configured agent policy, the selected router, the selected pull target, the token contracts, canonical Permit2 where used, and EVM transaction atomicity.
This page describes the V6 proxy deployment and its swap and intent boundaries. The intent settlement rules are described in the Intents trust model.
Trust model
Section titled “Trust model”The factory and implementation have no owner, administrator, pause switch, allowlist, or upgrade
path. Each clone is initialized once for its user. Swap entry points, agent policy, and sweeps are
onlyOwner, and swap entry points use the shared non-reentrant guard.
The non-owner-gated entry points are deliberate. executeAsAgent is callable by anyone holding a
valid agent signature, pullForIntent is callable only by the factory-named settler, and
init(address) is external with no modifier. Three things make initialization safe, and it is
worth being precise about which one does the work:
- It is single-use — it reverts
AlreadyInitializedonceowneris non-zero. - The canonical address can only be produced by the factory. It is CREATE2 with the factory as
deployer and
keccak256(abi.encode("AgentSwap.UserProxy.v6", user))as the salt, and the factory callsinit(user)in the same transaction that deploys the clone. A user’s proxy is therefore never left deployed-but-uninitialised for someone else to claim; there is no window to race. - The shared implementation sets its own
ownerto0xdeadin its constructor, so it can never be initialised or driven directly.
Anyone can of course deploy their own clone of the implementation and initialise it to themselves,
but that clone lives at a different address and is nobody’s canonical proxy. Which is the practical
rule: resolve a user’s proxy through proxyOf or predictProxy, and never trust a proxy address
someone hands you.
The owner must still trust:
| Trust anchor | Boundary |
|---|---|
| Owner wallet | The owner can execute direct swaps, grant or revoke agents, change caps, and sweep the proxy. |
| Agent keys | An active agent can sign orders within the policy and its remaining input-token caps. |
| Router and token behavior | The route and ERC-20 contracts are external code selected by the owner or authorized agent. |
| Canonical Permit2 | Permit2 verifies and executes the plain transfer used by executePermit2In, and supplies the Permit2 allowance path. |
| EVM and chain | Atomic transaction execution and the deployed chain’s support for the implementation’s opcodes are assumed. |
The proxy has no external price reference. minOut is the value floor chosen by the direct caller
or signed by the agent. A transaction that receives less than the floor, or delivers less than the
floor to the owner, reverts atomically.
Structural controls
Section titled “Structural controls”amountIn == 0andminOut == 0are rejected by the shared settlement path.- For an ERC-20 input, the router receives the supplied route data only after the input amount is pulled and the temporary approval is set; native input is passed as call value.
- The proxy measures the output balance delta and requires it to meet
minOut. - Output is always settled to
owner; there is no recipient parameter. - Temporary input approvals are revoked after the route, and leftover input is returned to the owner.
- A shared reentrancy guard covers
execute,executePermit2In, andexecuteAsAgent. - Owner-only sweeps provide recovery for native ETH and ERC-20 balances held by the proxy.
These controls enforce the signed or directly supplied floor. They do not determine whether the floor represents fair market value.
The relayer boundary
Section titled “The relayer boundary”Anyone may relay a valid executeAsAgent call. The agent signature covers:
agent, generation, router, tokenIn, amountIn, tokenOut, minOut, nonce, deadlinegeneration is the policy generation current when the agent signed. An order signed under a
revoked generation cannot execute under a later grant. The signature does not cover spender or
routerData. A relayer can therefore choose the pull target and route calldata at execution time.
The relayer can choose a route down to the agent’s minOut; this is real discretion in the design,
not an authority-free relay.
The agent path limits that discretion in three ways:
spender == address(0)resolves to the signed router.- A non-zero pull target must be the signed router or canonical Permit2, or the call reverts with
SpenderNotAllowed. - The input amount is charged against the agent’s current per-token, per-epoch cap.
The relayer cannot change the signed agent, generation, router, tokens, input amount, minimum output, nonce, or deadline. It can censor or delay its own transaction. A successful route still settles its output to the owner, not to the relayer.
For intents, the proxy has a separate pullForIntent entry point. Only the IntentSettlerV3 named
by the factory can call it; the proxy verifies the owner’s flat order authorization and sends the
input to that caller. It does not change the direct swap paths or their Permit2 option.
Agent and owner compromise
Section titled “Agent and owner compromise”A compromised agent key can authorize orders until the policy expires or is revoked, subject to
the action mask, allowed input tokens, non-zero caps, nonces, minOut, and the remaining epoch
budget. Revocation increments the generation and orphans the old generation’s permissions and
caps.
A compromised owner key has the owner’s authority: it can execute direct swaps, grant policies, change caps, revoke agents, and sweep balances. The proxy does not reduce the authority of the owner key.
Accepted residuals
Section titled “Accepted residuals”- A weak
minOutpermits economically poor routing down to that floor. - A relayer may choose poor or expensive route data, or may not submit an otherwise valid order.
- Non-standard token behavior may be unsupported or behave unexpectedly.
- A compromised agent may spend up to its remaining on-chain cap before a revocation transaction is effective.
- The owner must choose appropriate tokens, route data, and minimum outputs.
Clients should derive proxies from the canonical factory, pin the factory and implementation addresses, and simulate unfamiliar router calldata before submitting it. For deployment and ABI values, see the proxy reference. For deterministic address derivation, see the factory.