ENSFirewall

Decentralized firewall for AI agents. Security policies live in ENS. Wallets enforce them onchain.

ENSFirewall

Created At

Open Agents

Project Description

ENSFirewall is a TypeScript monorepo (pnpm + Turborepo) with packages for the contracts (Solidity, Foundry), the SDK, a CLI agent, a Next.js demo, and shared types.

ENS does five distinct, load-bearing jobs in our stack:

  1. Identity — each agent IS an ENS name (e.g. demo-agent.ensfirewall.eth).
  2. Configuration — security teams publish policy lists as text records under their own subnames (scamlist.ensfirewall.eth).
  3. Distribution — a single ENS text-record update propagates to every subscribed smart account worldwide instantly, no redeploy.
  4. Reputation — subscriber counts and authority graphs are queryable onchain at any time.
  5. Enforcement — our ERC-4337 contract (extending eth-infinitism's SimpleAccount) reads the authority's policy:rules-encoded text record on every execute() call and reverts onchain if the destination is on the blocklist.

The cleverest move is treating ENS text records as an enforced ACL for smart accounts. Each policy is stored as two paired records: policy:rules (human-readable JSON, the canonical source for tooling) and policy:rules-encoded (ABI-encoded bytes for cheap onchain reading). The smart account reads the encoded blob via the Public Resolver's text(), parses the hex string into bytes, and abi.decodes into an address[] before allowing any transfer.

Architectural note: validation lives in execute() rather than _validateUserOp(). ERC-4337's validation phase forbids external storage reads — putting an ENS resolver call in _validateUserOp would risk bundler bans. Validating in execute() keeps the trust path clean and supports both direct owner calls and standard userOp flows. Tech stack: Solidity 0.8.28 with Foundry, eth-infinitism account-abstraction reference (EntryPoint v0.8 at 0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108 on Sepolia), OpenZeppelin contracts. Frontend: Next.js 16, Tailwind v4, viem + wagmi + RainbowKit. Agent: Anthropic Claude Sonnet 4.6 via @anthropic-ai/sdk (CLI) and via the Vercel AI SDK (web demo). ENS infra: Registry at 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e, Public Resolver at 0xE99638b40E4Fff0129D56f03b55b6bbC4BBE49b5.

Defense in depth: the SDK validates offchain before constructing the call (fast feedback to the LLM), and the smart account re-validates onchain (catches the case where a compromised agent bypasses the SDK). The full E2E test runs on Sepolia — change a text record, the smart account's behavior changes without redeploy. Four verifiable transaction hashes prove the thesis.

Hacky parts worth mentioning: Solidity has no native hex-string-to-bytes converter, so the smart account ships with an inline parser that strips the 0x prefix and converts hex chars to bytes before abi.decode. Also, ENS text records can point to non-default resolvers — most off-the-shelf helpers hardcode the Public Resolver, which silently returns empty for our authority. We resolve the resolver from the registry first.

How it's Made

ENSFirewall is a TypeScript monorepo with five packages: contracts (Solidity), lib (the SDK, published to npm as ens-agent-firewall), agent (Anthropic SDK with tool calling), web (Next.js + viem + wagmi), and shared (types).

ENS does five distinct jobs in this protocol:

  1. Identity. Every agent has its own ENS name as onchain identity.
  2. Configuration. Agent owners declare trusted policies via the policy:subscriptions text record. No backend, no database.
  3. Distribution. Security teams publish policies as text records on their own subnames (like scamlist.ensfirewall.eth). Updates propagate to every subscribed agent worldwide instantly.
  4. Reputation. Verifiable by counting subscribers onchain via ENS reverse iteration.
  5. Enforcement. A custom ERC-4337 SimpleAccount overrides _validateUserOp to read the agent's ENS text records and revert any userOp that violates a subscribed policy.

The clever part is using text records as ACL for smart accounts. The wallet enforces what the ENS record says. We store policies in two paired records, policy:rules (human-readable JSON) and policy:rules-encoded (ABI-encoded compact bytes for cheap onchain reading). The encoded version is what _validateUserOp parses, the JSON is the canonical source for tooling.

The other clever piece is bidirectional signals. When the smart account blocks a transaction, the owner can opt-in publish the malicious address to a community ENS list. The graph of subscriptions becomes the trust graph of the entire agent ecosystem, fully onchain, queryable, and composable.

Tech stack: Solidity 0.8.26 with Foundry, ERC-4337 with Pimlico bundler on Sepolia, viem and wagmi for ENS reads and writes, Next.js 16 with Tailwind for the dashboard and the live demo, Framer Motion for the three-panel attack visualization, Anthropic SDK for the live agent. ENS Sepolia contracts used: Registry (0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e), NameWrapper, and Public Resolver for text record reads and writes.

Defense in depth: the npm SDK validates locally before submitting userOps (fast feedback for honest agents), and the smart account re-validates onchain (catches compromised agents that bypass the lib).

background image mobile

Join the mailing list

Get the latest news and updates