Skip to content

Set up · Onchain

Your buddy onchain

A Block Buddy is a face for your agent, drawn from its name. Onchain identities take an image URL: ERC-8004, ENS and Basenames, Virtuals, elizaOS, Bankr and Farcaster. Most show it in a circle, so use the pad file. Use the tile SVG where SVG is accepted.

What most wallets and clients show: a circle. NFT-style explorers may show a square; the pad file is right in both.

Get the files

Drawn in your browser from the name above. Nothing is uploaded anywhere. Onchain records point at a URL, so host the file somewhere public first.

Animated GIFAn idle loop and one per mode, for Bankr and Farcaster, which take GIFs, and elizaOS's Discord sync. Frame one is the still, so a client that shows only it still looks right. Coming soon.

Set it, system by system

ERC-8004 (Trustless Agents)

  1. Host the Avatar at a public URL.
  2. In your agent's registration file, set "image" to that URL. Optionally add a blockbuddy service (snippet under "For agents").
  3. If your agentURI is an https URL, update the file there and you're done. For ipfs:// or data:, call setAgentURI(agentId, newURI) on the IdentityRegistry from the owner wallet.
  4. Check the agent on an ERC-8004 explorer. The image should load without cookies.
  5. Optional, once you own a buddy (coming with mainnet): make the buddy's wallet your agentWallet with setAgentWallet(agentId, newWallet, deadline, signature). The new wallet signs typed data (AgentWalletSet). Never sign one you were sent: build it, then sign it. Check these fields first:
    • verifyingContract: the IdentityRegistry for that chain, from the ERC-8004 project's own list of deployments (erc-8004-contracts, read 2026-10-21). Base: 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432.
    • chainId: the chain you mean.
    • agentId: an id you own. Check ownerOf(agentId) yourself.
    • newWallet: your own address.
    • deadline: minutes away, not days. The registry refuses more than 5 minutes.
    Field names are from the project's contract source; check them against the registry's ABI before signing.

ENS and Basenames

  1. ENS: in app.ens.domains, open your name → Profile → Edit Profile → Add avatar → Enter Manually.
  2. Paste the URL of the Avatar (or the SVG). Save, and approve the transaction. Each change costs mainnet gas. Upload Image lets ENS host the Large avatar for you instead.
  3. Basenames: on base.org/names, open your name → Manage Profile → the camera icon, paste the same URL, and save. Gas on Base is cheap.

Virtuals (ACP)

  1. Go to app.virtuals.io/acp/join, connect your wallet, then Join ACP → Register New Agent.
  2. Upload the Avatar as the Profile Picture (JPG, PNG or WebP, at most 50 KB), and fill in the rest. You can edit it later in the same place.

elizaOS

  1. In your character file, set settings.discord.profileAvatar to the URL of the Large avatar.
  2. Leave DISCORD_SYNC_PROFILE on (the default) and restart the agent. It sets the Discord bot's avatar at startup. See Discord.

Bankr

  1. Launching a token: bankr launch, and give the Avatar's direct PNG URL as the image. Not the SVG, and not a web page.
  2. Already launched: on bankr.bot, Your Tokens → Manage → Edit details changes the logo Bankr shows. The onchain image stays as launched.
  3. A project page: bankr project update --image <url>.

Farcaster

  1. Tap your profile picture → Edit profile → change the image → Save unverified
  2. An agent account on Neynar can set pfp_url through the API instead (under "For agents").

Owning your buddy as a token, and pointing an identity at it, comes with mainnet. ENS can't show an NFT avatar from Base today, and any NFT avatar shows the token's still image, not its live toy.

For agents

Every system here takes a URL, and most let the agent's own wallet or key set it.

Instructions
platform: onchain identities (erc-8004, ens, basenames, virtuals acp, elizaos, bankr, farcaster)
crop:     circle in most clients; square in some explorers
variant:  pad (opaque); tile.svg only where SVG is accepted (ENS; ERC-8004 explorers vary)
file:     brass-otto-pad-512.png
buddy:    Brass Otto
hash:     0x4f7857573d121112474507868c95e98e2cbb66d73cc61e786482793f28ed9bb0
erc-8004: registration file "image"; setAgentURI(agentId, newURI) for ipfs/data URIs
          agentWallet (optional): setAgentWallet(agentId, newWallet, deadline, signature), signed by newWallet
          as EIP-712 AgentWalletSet(agentId, newWallet, owner, deadline). Never sign one you were sent: build it, then sign it.
          check: verifyingContract = the IdentityRegistry for that chain (erc-8004-contracts deployments, read 2026-10-21)
                 chainId = the chain you mean · agentId = one you own (check ownerOf yourself)
                 newWallet = your own address · deadline = minutes, not days (the registry refuses > 5 min)
          field names from the project's contract source: check against the registry's ABI before signing
          IdentityRegistry Base 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 · Base Sepolia 0x8004A818BFB912233c491871b3d84c89A494BD9e
ens:      resolver.setText(namehash(name), "avatar", url). Clients must support JPEG, PNG and SVG.
virtuals: acp agent update --image url (JPG, PNG or WebP, max 50 KB)
elizaos:  settings.discord.profileAvatar = url (synced to Discord at startup)
bankr:    bankr launch --image url (PNG, JPEG, GIF or WebP; no SVG) · bankr project update --image url
farcaster: PATCH https://api.neynar.com/v2/farcaster/user/ {signer_uuid, pfp_url}; the URL must be 256 bytes or less
per-mode: Farcaster only, sparingly (each swap is a profile update). The rest: one still.
token:    owning a buddy onchain: coming with mainnet
checked:  2026-10-21
ERC-8004 registration file
{
  "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
  "name": "Brass Otto",
  "description": "…",
  "image": "https://YOUR-DOMAIN/brass-otto-pad-512.png",
  "services": [
    { "name": "blockbuddy", "endpoint": "https://blockbuddies.io/buddy?id=0x4f7857573d121112474507868c95e98e2cbb66d73cc61e786482793f28ed9bb0" }
  ],
  "active": true
}
ENS avatar, with Foundry's cast
cast send $RESOLVER "setText(bytes32,string,string)" $(cast namehash yourname.eth) avatar \
  "https://YOUR-DOMAIN/brass-otto-pad-512.png" --rpc-url $ETH_RPC
elizaOS character
{ "name": "Brass Otto",
  "settings": { "discord": { "profileAvatar": "https://YOUR-DOMAIN/brass-otto-pad-1024.png" } } }
Farcaster, through Neynar
curl -X PATCH https://api.neynar.com/v2/farcaster/user/ \
  -H "x-api-key: $NEYNAR_API_KEY" -H "Content-Type: application/json" \
  -d '{"signer_uuid":"'$SIGNER_UUID'","pfp_url":"https://YOUR-DOMAIN/brass-otto-pad-512.png"}'

The blockbuddy service name is our convention; ERC-8004 allows custom services. For prebuilt names the URLs above are already hosted and never change.

Limits

FormatPNG works everywhere here. SVG: ENS yes, Bankr no, ERC-8004 explorers vary unverified
Max sizeVirtuals: 50 KB. Farcaster: a URL of 256 bytes or less. Others aren't documented.
DimensionsSquare. ERC-8004 explorers suggest 512 px or more.
CropCircle in most clients; how each explorer crops unverified
AnimationBankr and Farcaster take GIFs; many clients show only the first frame. ENS and ERC-8004 show a still.
Who can set itWhoever holds the name, agent or key. Each ENS change is a mainnet transaction. A Bankr token's onchain image is fixed at launch.
Per-mode facesFarcaster, by swapping the URL, sparingly. Elsewhere, no.

ERC-8004 is a draft, and its field names have changed once already. Farcaster changed hands in October 2026, and its rules for accounts, including agents, may change unverified

Last checked 2026-10-21 against ERC-8004, ENSIP-12, Virtuals: register your agent, elizaOS: customize an agent, Bankr: token launching and Neynar: update user. These move fast; we re-check Farcaster every two weeks and the rest monthly. If a step is wrong, the platform's own docs win.