Skip to content

Back to the catalog

ERC-8427: Portable Spend Grants
ethereum-magicians.orgthread

ERC-8427: Portable Spend Grants

ERC-8427 'Portable Spend Grants' is a draft Ethereum standard defining a signed SpendGrant object that lets a principal authorize a delegate (e.g. an AI agent or session key) to spend up to specified per-call, trailing-24h, and lifetime caps of named assets, to a restricted set of recipients, within a validity window — solving problems that plain ERC-20 approve and midnight-resetting daily caps don't. A non-custodial registry tracks remaining usage and revocation while an immutable executor contract must call consume() in the same transaction as any transfer, so unauthorized value movement is provably blocked; the reference implementation is deployed on Arc testnet with formal verification (Halmos) of expiry, cap, revocation and executor-binding invariants plus fuzzing of the rolling-window logic. The thread also discusses interplay with ERC-7710/7715 delegation/permission RPCs, ERC-8226's regulated grants, and ERC-8312's usage-tracking pattern, and solicits feedback on EIP-7702 signer/delegation ordering and executor-vs-delegate binding in consume().

TL;DR Draft ERC defining a formally-verified, revocable spend-cap primitive (per-call/rolling-window/lifetime caps, non-custodial registry) for delegating limited fund access to AI agents or session keys.
Document

What it is

ERC-8427 "Portable Spend Grants" — a draft signed SpendGrant type letting a principal authorize a delegate (agent/session key) to spend named assets under per-call, trailing-window, and lifetime caps, to restricted recipients, within a validity range. The reference implementation is live on Arc testnet (chain 5042002) with verified source:

  • Registry: 0xE3591E35c6473FB2A9D2f7370d1FE3454864fb32
  • Executor: 0xd0F9e902b054fd8B329Ae8615F9C8247A199ecd2

The existing summary covers the design, registry/executor split, and ERC cross-references. This adds the concrete numbers, the deployment gotcha, and the exact roles the summary flattens.

How it works (mechanics the summary omits)

The digest is bound to one chain and one registry — you pick the executor by choosing which registry you sign against, since the executor is set immutably on the registry. Native currency is the ERC-7528 0xEeee…EEeE address; everything else is ERC-20. A cap of zero means zero, never unlimited. The trailing window looks back windowSeconds from now — it is not a calendar "today," which is the whole point over midnight-resetting daily caps.

Rolling-window cost: each asset's debits sit in a 1024-slot ring with a running sum, expired debits dropped from the front. Execution gas through the reference executor (excluding 21k base + calldata):

  • ~161k first spend on a grant
  • ~89k subsequent, regardless of live debit count
  • ~70k once the ring has wrapped

The assetCombine field exists in the signed type but only 0 is valid (per-asset budgets); it's reserved so a future shared-budget mode won't change the type hash.

Preconditions / Affected

Relevant if you build with agents or session keys and need revocable, time-windowed, multi-asset spend limits. Requires the executor contract to call consume in the same transaction as any transfer, or the spend doesn't count.

What to do

If testing on Arc: list USDC by its token address 0x3600…0000, not the native ERC-7528 address. On Arc they share one balance, so listing both creates two separate budgets over one pool of funds. An ERC-7730 descriptor exists for the registry (renders delegate, recipient, window, per-asset caps, validity dates; rejects any assetCombine ≠ 0) but it cannot show executor() — the wallet must look that up itself.

Caveats

The reference is unaudited — keep it on testnets. Formal coverage is partial by design: Halmos proves expiry, cap checks at full 256-bit width, two-spend sequences, revocation, and executor-only consume; the rolling window is fuzzed against a naive model including full-ring wraparound. The 1024 live-debit limit is a reference choice, not in the spec — a conformant registry may revert WINDOW_FULL at its own cap, so a delegate making many small payments has no guaranteed floor (open question in the thread).

Three unresolved design questions the author is soliciting on: EIP-7702 signer ordering (ECDSA checked before ERC-1271, so key-signed grants survive delegation changes until revoked in the registry); whether consume should also bind msg.sender to delegate rather than only to the registry's executor; and whether the spec should mandate a minimum live-debit bound.

Organisations named here

  • ERC-8427

Technologies named here

  • Solidity reference implementation
  • ERC-20
  • ERC-7730 display descriptor
  • Arc testnet
  • Halmos
  • Registry contract
  • Executor contract
  • Fuzzing
  • USDC on Arc
  • EIP-7702
  • ERC-7710
  • ERC-7715
  • ERC-8226
  • ERC-8312
  • ERC-7528
  • ERC-7730
  • Ethereum
  • Solidity

Techniques named here

  • Trailing rolling-window spend cap
  • Per-asset, per-call, trailing-window, and lifetime caps
  • Registry-bound revocation and usage tracking
  • Executor-only consume binding
  • Chain- and registry-bound signature digest
  • Exact rolling window via ring buffer
  • assetCombine field reservation
  • ECDSA-before-ERC-1271 signature check ordering