DocsOverview

AI trading agents are a hot narrative · but handing an AI your private key is reckless: prompt injection, hallucination, or a bug can drain everything. Most "AI agent wallets" today rely on off-chain promises.

Emet's answer: a smart account (the Clay) where the AI holds only a session key (the Mark). Every action is checked onchain against rules the user sets (the Inscription) · allowed assets, max position size, max daily loss, trade caps, allowed venues, max slippage, and expiry. The Maker keeps the master key. The AI can be anything · Claude, GPT, a custom model, a copy-trading bot · because the guardrails never depend on trusting it.

Brand & voice

The product is about control, not hype. Tone: calm, precise, confident.

"One letter from stillness." "Strength without trust." "Your rules, written in clay."

Sensitivity

Emet is a meaningful word in Jewish tradition, and the Golem legend is widely used in culture · the name is fine, but treat it with respect. Use it as the myth of a bounded servant. Never pair Hebrew letters with joke copy, and never use divine names.

Lore glossary

Use the Emet name in the UI, docs, and marketing. Use the code name in contracts and the SDK · a new developer should be able to read the code without learning the mythology.

ConceptEmet nameCode name
User / master keyMakermaker
AI agentGolemagent
Smart accountClayEmetAccount
Policy moduleInscriptionInscriptionModule
Individual rulesLettersRule
Session keyMarksessionKey
Kill switchEraseerase()
Active stateEmetState.EMET
Frozen stateMetState.MET
GuardianKeeperkeeper
Audit trailChronicleChronicle* events
Blocked breach attemptsRefusalsRefused event
Agent marketplace (v2)The Workshopregistry

Architecture

Checks are split by execution phase, because ERC-4337 validation limits which external storage can be read · a Chainlink read inside validateUserOp would get the bundle rejected.

Flow
Maker · writes Inscription
Golem · signs UserOp with Mark
VALIDATION (validateUserOp) · Mark valid & unexpired? · account state == EMET? · target a whitelisted adapter? · selector known? default-deny
EXECUTION · Adapter → Uniswap / opening auction
POST-EXECUTION HOOK (ERC-7579) · recipient == EmetAccount? · fill ≥ oracle quote × (1 − maxSlippage)? · position limits still ok? · NAV ≥ high-water mark × (1 − maxDrawdown)? · oracle feeds fresh?
pass → Chronicle event  fail → revert

Key design decisions

01
Split checks by phase

Cheap, storage-local checks go in validation. Oracle-based checks (NAV, drawdown, slippage) go in an ERC-7579 post-execution hook that reverts on breach.

02
Whitelist thin adapters, not routers

We never decode Uniswap's Universal Router · its command-byte format is a large bypass surface. A small SwapAdapter exposes only swapExactIn(tokenIn, tokenOut, amountIn, minOut) and always sends output to the calling account.

03
Default-deny

Any unknown target or selector is rejected · including the account's own functions. The Mark can never call execute for transfers, module changes, or approvals to arbitrary spenders.

04
Recipient enforcement

Every trade's output recipient must be the EmetAccount itself. This is what makes "no withdrawals" hold.

05
Oracle-anchored slippage

Require minOut ≥ oracleQuote × (1 − maxSlippage). Without this, an agent can bleed value inside every other limit through bad fills or sandwich attacks.

06
Stale-oracle policy

If any held asset's feed is older than maxOracleAge, trading is blocked. The account is never valued on stale prices.

Contracts reference

The moving parts of the protocol layer, named in both worlds.

EmetAccount · ERC-4337 smart account

The Clay. Holds funds, validates every UserOp against the account's State, and delegates policy checks to the InscriptionModule. Never exposes a direct transfer path to the Mark.

InscriptionModule · ERC-7579 policy module

Holds the Letters (Rule set) for an EmetAccount. Runs pre-execution checks during validation and post-execution checks via the ERC-7579 hook.

Rule · a single Letter

One enforceable constraint: asset allowlist, max position size, max daily loss, trade size/frequency cap, venue whitelist, max slippage, or expiry.

SwapAdapter.swapExactIn(tokenIn, tokenOut, amountIn, minOut)

The only whitelisted execution target for trading. A thin wrapper around a DEX (Uniswap for MVP) that always returns output to the calling EmetAccount · never to an arbitrary address.

State.EMET · State.MET

The account's two states. EMET: Golem can trade within its Letters. MET: frozen · all Marks revoked, no execution possible until the Maker re-inscribes.

erase() · callable by Maker or Keeper

Moves the account to State.MET instantly and revokes every Mark. Auto-triggered after N consecutive Refused events (configurable) or a hard drawdown breach. Only the Maker can return the account to EMET.

sessionKey (the Mark)

The Golem's signing key. Scoped to trade-only actions, dies after N days, and is revoked instantly on erase().

Chronicle* events · Refused event

Every successful action emits a Chronicle* event, feeding the public performance page. Reverted UserOps emit nothing onchain · the bundler/SDK layer simulates each one and logs Refused off-chain, tagged with the rule that failed.

Base Sepolia Testnet Deployments (Chain ID 84532)

ContractAddressExplorer
InscriptionModule0x7E758484ECd3321B628Ba021017FdfB95e22c208Basescan
EmetFactory0xC875a21d24d8c3C8cB774EF9645FE66B5E6ee8F3Basescan
SwapAdapter0xb269c0F4E1ACeB606DC5Cfc9826db256D5111a55Basescan
MockDexRouter0xcF09199bf919B99c1eAf60E441688ffbD335A4f6Basescan
Clay (Demo Account)0x5b46e423fb13d1f3ba69fc685ba9b7633f7f4089Basescan
USDG (Faucet Token)0x5659Eb1eF33d4B94D74594b60391f7FA94196a90Basescan
NVDA (Stock Token)0xf3DC1C78044d3D286F3654bf18801936Dc66D4A1Basescan
TSLA (Stock Token)0x18CD5a3a248f21b16872F4CD47F3252673b4B82eBasescan

The Letters

Rules live onchain, enforced across two phases: cheap checks during validateUserOp, oracle-dependent checks in the ERC-7579 post-execution hook.

LetterEnforcesPhaseExample
Allowed assetsOnly listed tokens may be tradedValidationNVDA, TSLA, USDG
Max position sizeCap on any single asset's share of NAVPost-hook≤ 20% of portfolio
Max daily lossDrawdown vs. high-water mark over a 24h UTC windowPost-hook−5% → auto-freeze
Trade size & frequencyPer-trade size and a per-hour trade count capValidation≤ 6 trades / hour
Allowed venuesOnly whitelisted adapters as call targetsValidationSwapAdapter (Uniswap)
Max slippageFill must clear the oracle-anchored boundPost-hookfill ≥ oracle × (1 − 0.5%)
ExpiryThe Mark dies after N days · no silent renewalValidation30 days
No withdrawalsOutput recipient must always be the EmetAccountPost-hookenforced, not optional

Agent SDK

@emet/sdk · a TypeScript SDK that builds, simulates, and submits UserOps, and mirrors Refusals back with the exact rule that would block them.

typescript · build & submit a trade
import { EmetClient } from "@emet/sdk";

const emet = new EmetClient({
  clay: "0x5b4...089",
  mark: process.env.SESSION_KEY,
  chain: "base-sepolia",
});

const plan = await emet.simulate({
  action: "swap", tokenIn: "USDG", tokenOut: "NVDA", amountIn: "250",
});

if (plan.refused) {
  console.log(`Refused by ${plan.rule}`);
} else {
  await emet.submit(plan);
}

// listen for the Chronicle in real time
emet.on("chronicle", (evt) => console.log(evt));
emet.on("refused", (evt) => console.log(evt.rule));
cli · inscribe a Clay and mint a Mark
# install & point at a chain
npx @emet/sdk init --chain base-sepolia

# write the Inscription
emet inscribe --clay 0x5b4...089 \
  --assets NVDA,TSLA,USDG \
  --max-position 20% \
  --max-daily-loss 5% \
  --expiry 30d

# mint a Mark for your Golem
emet mark:create --clay 0x5b4...089 --ttl 30d

Method reference

MethodDescription
simulate(action)Simulates a UserOp against the live Inscription; returns a plan or a refused flag with the failing rule.
submit(plan)Builds, signs with the Mark, and submits the UserOp through the bundler.
on("chronicle", fn)Subscribes to successful, onchain-confirmed actions.
on("refused", fn)Subscribes to blocked attempts, tagged with the Letter that stopped them.
erase()Maker/Keeper-only. Freezes the Clay immediately.

Tech stack

ContractsSolidity, ERC-4337 + ERC-7579 modules on the Safe or Kernel account stack; Foundry for tests
InfraBundler and paymaster on Base Sepolia Testnet (Chain ID 84532)
OraclesChainlink feeds for valuation and slippage checks
SDKTypeScript agent SDK (@emet/sdk) that builds, simulates, and submits UserOps
Demo GolemAn LLM plus a simple strategy (rebalancer or momentum)

Milestones

#DeliverableEst.
M1InscriptionModule + SwapAdapter + unit/fuzz tests (breach attempts)3 wk
M24337 integration (bundler, paymaster), Marks (session keys)2 wk
M3Agent SDK + demo Golem + Refusal logging2 wk
M4Website, dashboard + testnet launch2–3 wk

M1 test requirements

Fuzz every Letter with breach attempts, including: wrong recipient, unknown selector, direct token transfer/approve, expired Mark, stale oracle, slippage beyond bound, trades after erase(), and a drawdown crossed mid-window.

Risks

Bypass surface

Any decodable path left open is a potential drain. Default-deny and adapter-only targets keep this small.

Oracle risk

Loss checks inherit oracle risk; the stale-oracle policy mitigates it.

Regulatory

If Emet provides the strategy, that may count as investment advice or management. Being the infrastructure is safer · the demo Golem is clearly labeled as a demo.

Success metrics

Funded Clay accounts
AUM under Inscription
Refusals blocked
Third-party Golems onboarded

Refusals · breach attempts blocked onchain · double as a marketing stat: proof the guardrails hold, not a promise that they do.