Contract Reference
Every external function on the ERC-8004 Identity Adapter, organized by section.
All functions live on Adapter8004 (src/Adapter8004.sol). Exact parameter
types track the contract source. Check the repo if a signature changes.
The adapter implements IERC8004IdentityRecord and IERC8004AdapterRegistration,
so an ERC-8004 client can talk to the adapter using the same interfaces it
uses to talk to a vanilla registry.
Initialization#
initialize#
function initialize(address identityRegistry_, address initialOwner) external
What it does
UUPS initializer. Wires the proxy to the ERC-8004 registry it forwards into, and assigns the admin role.
Parameters
identityRegistry_— ERC-8004 IdentityRegistry the adapter forwards into.initialOwner— admin address. ReceivesOwnableUpgradeableownership.
Reverts
InvalidTokenContract()ifidentityRegistry_is zero.OwnableInvalidOwner(address)ifinitialOwneris zero.InvalidInitialization()on a second call.
Caller
Whoever deploys the proxy. The implementation's constructor calls
_disableInitializers(), so the bare implementation cannot be initialized
directly.
Registration#
register (with metadata)#
function register(
TokenStandard standard,
address tokenContract,
uint256 tokenId,
string memory agentURI,
MetadataEntry[] memory metadata
) public returns (uint256 agentId)
What it does
Mints a new ERC-8004 identity through the registry and binds it to
(standard, tokenContract, tokenId). Writes the supplied metadata
entries, the canonical 20-byte agent-binding row, and clears the
default agentWallet slot the registry initialized to the adapter
address.
Parameters
standard—ERC721,ERC1155, orERC6909.tokenContract— external token contract address.tokenId— id withintokenContract.agentURI— initial off-chain URI.metadata— array ofMetadataEntry { string metadataKey; bytes metadataValue; }.
Returns
agentId— the newly minted ERC-8004 id.
Reverts
InvalidTokenContract()iftokenContractis zero.NotController(account, agentId)if the caller does not currently control the external token. (agentId == type(uint256).maxsince the agent does not exist yet.)ReservedMetadataKey("agent-binding")if a caller tries to overwrite the canonical binding row through the metadata array.
Events
AgentBound(agentId, standard, tokenContract, tokenId, registeredBy).
Caller
Whoever currently controls the external token: literal ownerOf for
ERC-721, or any holder with balanceOf > 0 for ERC-1155 / ERC-6909.
register (no metadata)#
function register(
TokenStandard standard,
address tokenContract,
uint256 tokenId,
string calldata agentURI
) external returns (uint256 agentId)
What it does
Convenience overload equivalent to the metadata-array form above with an
empty MetadataEntry[]. Same revert behavior, same AgentBound event.
Returns
agentId— the newly minted ERC-8004 id.
Caller
Same as the metadata-array overload.
Controller-gated writes#
Every function in this section calls _requireController(agentId, msg.sender),
which reverts with UnknownAgent(agentId) if the id was never bound and
NotController(account, agentId) if the caller does not currently control
the bound token. Each function below assumes those two reverts; only
function-specific reverts and events are listed.
setAgentURI#
function setAgentURI(uint256 agentId, string calldata newURI) external
What it does
Updates the agent's off-chain URI in the registry.
Behavior
Forwards to identityRegistry.setAgentURI(agentId, newURI).
Events
AgentURISet(agentId, newURI, updatedBy)after the registry call succeeds.
Caller
Current controller of the bound token.
setMetadata#
function setMetadata(uint256 agentId, string memory metadataKey, bytes memory metadataValue) external
What it does
Writes one metadata key on the agent.
Reverts
ReservedMetadataKey("agent-binding")— the canonical binding row cannot be overwritten through this path.
Behavior
Forwards to identityRegistry.setMetadata(agentId, metadataKey, metadataValue).
Events
MetadataSet(agentId, metadataKey, metadataValue, updatedBy)after the registry call succeeds.
Caller
Current controller of the bound token.
setMetadataBatch#
function setMetadataBatch(uint256 agentId, MetadataEntry[] calldata metadata) external
What it does
Writes multiple metadata keys in one transaction.
Reverts
ReservedMetadataKey("agent-binding")if any entry tries to overwrite the canonical binding row.
Behavior
Loops over metadata and forwards each entry to
identityRegistry.setMetadata. The count can be zero; the event still
fires.
Events
MetadataBatchSet(agentId, count, updatedBy)after the loop.
Caller
Current controller of the bound token.
setAgentWallet#
function setAgentWallet(uint256 agentId, address newWallet, uint256 deadline, bytes calldata signature) external
What it does
Binds an agent wallet (newWallet) to the ERC-8004 record. The registry
verifies that newWallet itself signed the EIP-712 typed data.
Behavior
Forwards to identityRegistry.setAgentWallet(agentId, newWallet, deadline, signature).
The registry enforces the signature rule. The signed payload uses
owner = adapter address because the adapter is ownerOf(agentId) from
the registry's view. See Concepts
for the full caller-vs-signer breakdown.
Events
AgentWalletSet(agentId, newWallet, updatedBy)after the registry call succeeds.
Caller
Current controller of the bound token. Note: the signer of the
signature is newWallet, not the caller.
unsetAgentWallet#
function unsetAgentWallet(uint256 agentId) external
What it does
Clears the agent's wallet binding.
Behavior
Forwards to identityRegistry.unsetAgentWallet(agentId). Idempotent.
Events
AgentWalletUnset(agentId, updatedBy)after the registry call succeeds.
Caller
Current controller of the bound token.
Counterfactual#
Counterfactual functions and events have a dedicated reference page. See
Counterfactual for the emit-only registration surface,
registrationHash, event ABI, and indexer guidance.
Views#
getMetadata#
function getMetadata(uint256 agentId, string memory metadataKey) external view returns (bytes memory)
What it does
Reads a metadata value from the registry. Lets ERC-8004 clients read directly from the adapter address without bouncing to the underlying registry.
Behavior
Forwards to identityRegistry.getMetadata(agentId, metadataKey).
getAgentWallet#
function getAgentWallet(uint256 agentId) external view returns (address)
What it does
Returns the bound agent wallet, or the zero address if none is set.
Behavior
Forwards to identityRegistry.getAgentWallet(agentId).
ownerOf#
function ownerOf(uint256 agentId) external view returns (address)
What it does
Returns the registry's owner of the ERC-8004 token. For any agent registered through this adapter, the owner is the adapter contract itself.
Behavior
Forwards to identityRegistry.ownerOf(agentId).
tokenURI#
function tokenURI(uint256 agentId) external view returns (string memory)
What it does
Returns the agent's URI as known to the registry.
Behavior
Forwards to identityRegistry.tokenURI(agentId).
bindingOf#
function bindingOf(uint256 agentId) external view returns (Binding memory)
What it does
Returns the Binding { TokenStandard standard; address tokenContract; uint256 tokenId; }
stored at registration time.
Reverts
UnknownAgent(agentId)if no binding exists.
agentIdForBinding#
function agentIdForBinding(TokenStandard standard, address tokenContract, uint256 tokenId)
external view returns (uint256 agentId, bool exists)
What it does
Reverse lookup. Resolves an external (standard, tokenContract, tokenId)
back to the bound agent id.
Returns
agentId— bound id, or0if no binding exists.exists— source of truth. The adapter stores bindings asagentId + 1internally, soagentId == 0is correctly distinguished from "unset" via this boolean.
isController#
function isController(uint256 agentId, address account) external view returns (bool)
What it does
Returns true iff account currently controls the bound external token
under that token's standard. Returns false (no revert) if agentId is
unknown.
Behavior
Calls into the bound token contract:
- ERC-721 —
ownerOf(tokenId) == account. - ERC-1155 / ERC-6909 —
balanceOf(account, tokenId) > 0.
Use this as a safe pre-flight before attempting a controller-gated write.
Admin#
setIdentityRegistry#
function setIdentityRegistry(address newRegistry) external
What it does
Swaps the registry the adapter forwards into.
Reverts
InvalidTokenContract()ifnewRegistryis zero.OwnableUnauthorizedAccount(address)if the caller is not the owner.
Events
IdentityRegistryUpdated(previousRegistry, newRegistry, updatedBy).
Behavior
Previously-registered bindings remain in the adapter's storage, but writes targeted at their agentIds will now route into the new registry, which has no record of those ids. The new registry will revert controller-gated writes against those agentIds because they are unknown to it.
Caller
Owner only.
upgradeToAndCall#
function upgradeToAndCall(address newImplementation, bytes memory data) external payable
What it does
UUPS upgrade. Replaces the implementation behind the proxy.
Behavior
Gated by _authorizeUpgrade(onlyOwner). Renouncing ownership via
renounceOwnership() permanently disables upgrades and registry swaps.
Caller
Owner only.
ERC-721 receiver#
onERC721Received#
function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4)
What it does
Returns IERC721Receiver.onERC721Received.selector. The adapter never
calls safeTransferFrom against the external bound token, but it
implements the interface so it can receive the ERC-8004 token from the
registry on register.
Errors#
| Error | When |
|---|---|
InvalidTokenContract() | Zero address passed as registry or tokenContract |
NotController(address account, uint256 agentId) | Caller isn't the current controller of the bound token |
UnknownAgent(uint256 agentId) | agentId was never bound |
ReservedMetadataKey(string metadataKey) | Caller tried to write the canonical agent-binding key |
OwnableUnauthorizedAccount(address) | Non-owner hitting an admin function |
OwnableInvalidOwner(address) | Zero address passed as initialOwner |
InvalidInitialization() | Re-initialization attempt |
Events#
On-chain#
| Event | Fired by |
|---|---|
AgentBound(agentId, standard, tokenContract, tokenId, registeredBy) | register |
AgentURISet(agentId, newURI, updatedBy) | setAgentURI |
MetadataSet(agentId, metadataKey, metadataValue, updatedBy) | setMetadata |
MetadataBatchSet(agentId, count, updatedBy) | setMetadataBatch |
AgentWalletSet(agentId, newWallet, updatedBy) | setAgentWallet |
AgentWalletUnset(agentId, updatedBy) | unsetAgentWallet |
BindingMetadataRewritten(agentId, updatedBy) | rewriteBindingMetadata (owner-only migration helper) |
IdentityRegistryUpdated(previousRegistry, newRegistry, updatedBy) | setIdentityRegistry |
OwnershipTransferred(previousOwner, newOwner) | Inherited from OwnableUpgradeable |
Upgraded(newImplementation) | Inherited from UUPS |
Counterfactual#
Declared on IERC8004AdapterCounterfactual. See
Counterfactual for full signatures,
indexed topics, and payload semantics.