Skip to main content
Five kinds of contract, and between them they decide what an agent may do to an account without anybody being asked at the time. There is one address per contract and it is the same on every chain. They are derived by CREATE2 from initcode and a fixed salt, so an address is a fact about a build rather than a deployment choice, which is why none of them is an environment variable. A value that can be pointed somewhere else is a value that can be pointed at an attacker.

AgentRegistry

The whitelist. An adapter the registry does not list cannot be installed by anybody, so a plan naming one reaches an account that never gained it. It also holds the kill switch. revoked[agent] stops a key for every account on that chain at once, with no redeploy and no migration, and the guardian who may write it is set once, at initialisation. A registry deployed without a guardian answers every other question perfectly well and can revoke nothing. The registry is per chain. Each chain carries its own deployment, so revoked[agent] is that chain’s storage and a full revocation is one transaction per chain: three today. Worth knowing before the day it is needed. Whitelisting sets an activation delay of three days. That delay is a constant in the contract and not a setting, because a configurable delay is one somebody sets to zero, and the delay is the only thing that makes a hostile adapter visible before it can act.

AdapterInstaller

Installed in the account’s genesis, and the only thing there that can install the rest. It exists because of a modifier. Kernel gates installModule behind onlyEntryPointOrSelfOrRoot, so without it an adapter could only ever be installed by the owner sending a transaction on that chain: four chains, four signatures, before anything can run. The installer sits in the genesis as an executor and asks the account to call itself, which satisfies the same modifier. So anyone may bring an account’s adapters up, and the relayer pays. That is what makes a new chain cost the owner nothing.

The adapters

The closed set of operations. What each one is, and the seven things every one of them must force by construction, are on Adapters and Your account, and the three keys. What belongs here is why their addresses are not stable across builds. Each adapter takes the registry as its only constructor argument. The registry’s address is therefore inside every adapter’s initcode, and a CREATE2 address is a hash of that initcode, so changing one line of AgentRegistry re-sites every adapter at once. It has happened: the whole table moved when the registry gained the whitelist. The dangerous part is that nothing fails when it happens. A stale address table does not error; it fails later, and elsewhere, as an account whose genesis names contracts that are not there.

VersionRegistry

Names which manifest is current, and grants nothing. It exists because AgentRegistry cannot see a downgrade. Superseded adapters stay whitelisted until somebody delists them, so an old manifest is a genuine one: every address in it still passes adapters(). Something has to say which set is the current one, and being unable to authorise anything is the point: a contract that named the current version and granted rights would be a second place to take over the account from.

AgentSelfCallGuard

The hook on the agent’s validator, and the one contract here whose address does not move with the registry; it takes no constructor argument, so its initcode is its bytecode alone. It is a denylist, and Your account, and the three keys says exactly what that does and does not cover. The short version: it fully blocks control takeover (the agent can never become owner or hand the account away) and it does not block value movement by a selector it did not name.

Deploying them

There is one deploy path and it is the only one. The address table in the code is the record of where that put things; if the two ever disagree, the table is what is wrong. An adapter that is deployed is not yet usable: it has to be whitelisted on that chain, and then installed on the account. Those are three separate facts and a plan can fail on any of them, which is why the console reports each one.