← Blog
17 de agosto, 2026 · 14 min

El tercer registro de ERC-8004 está vivo y vacío

ERC-8004 despliega tres registros: identidad, reputación y validación. En Ethereum mainnet, uno tiene 50.082 registros, otro tiene 3.215 y el tercero nunca fue llamado.

Toda discusión sobre confianza para agentes autónomos termina apuntando a ERC-8004. Es el estándar que le da a un agente un handle on-chain portable, un lugar donde acumular feedback y un hook para que terceros atestigüen que el trabajo se hizo bien. Cubrimos la propuesta cuando era nueva en EIP-8004: trustless agents, y leímos el primer estudio empírico en Auditando ERC-8004, que midió registration files y comportamiento de reviewers hasta mayo de 2026.

Este post hace algo distinto. En vez de leer el paper, leímos los contratos y después consultamos las cadenas. Clonamos erc-8004/erc-8004-contracts el 17 de agosto de 2026 (HEAD b9e466c, commiteado el 15 de agosto; repo creado el 8 de octubre de 2025; 231 stars, 107 forks, 54 issues abiertas) y leímos cada línea de Solidity. Después le preguntamos a Ethereum y a Base qué contienen realmente esos contratos.

La brecha entre ambas respuestas es la historia.

Qué está desplegado en realidad

La propuesta canónica en eips.ethereum.org/EIPS/eip-8004 sigue en estado Draft, creada el 13 de agosto de 2025, con autoría de Marco De Rossi, Davide Crapis, Jordan Ellis y Erik Reppel, y requiere EIP-155, EIP-712, EIP-721 y ERC-1271. El estado Draft no frenó el despliegue. El README del repo documenta 25 secciones de mainnet y 25 de testnet, desde Ethereum y Base hasta Injective, 0G, Robinhood Chain y SKALE.

Los tres registros son proxies UUPS en direcciones vanity minadas con CREATE2 a través del singleton factory de Safe, así que la misma dirección aparece en todas las cadenas. En mainnets:

// proxies de mainnet, idénticos en 25 cadenas
IdentityRegistry     0x8004A169FB4a3325136EB29fA0ceB6D2e539a432
ReputationRegistry   0x8004BAa17C55a88189AE136b182e5fdA19dE9b63
ValidationRegistry   0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58

La primera observación es documental. El README publica las direcciones de Identity y Reputation para las 50 redes, y nunca publica la de Validation para ninguna. El Validation Registry aparece en el README solo como prosa, bajo una advertencia de que esa parte de la spec está "still under active update and discussion with the TEE community". Su dirección vive en scripts/addresses.ts, no en la documentación.

Pero está desplegado. Consultamos Ethereum mainnet directamente: el proxy en 0x8004Cc84… devuelve código, getVersion() devuelve 2.0.0, owner() devuelve la misma dirección que los otros dos registros y getIdentityRegistry() resuelve correctamente a 0x8004A169…. Está cableado, inicializado y alcanzable. Igual en Base.

También confirmamos la ventana de despliegue haciendo búsqueda binaria del primer bloque con código en cada dirección. En Ethereum, el proxy del Identity Registry apareció en el bloque 24.339.871 y el del Validation Registry en 24.339.874 — 36 segundos de diferencia, el 29 de enero de 2026. En Base, bloques 41.663.783 y 41.663.785, el 3 de febrero de 2026. Los tres registros salieron a producción juntos, en una sola sesión, en ambas cadenas.

Qué contiene cada registro

El Identity Registry guarda su contador en storage namespaced ERC-7201, así que la cantidad de registros se puede leer directamente del slot sin confiar en un indexer. Leyendo el slot 0xa040f782…4e00 el 17 de agosto de 2026:

// Identity Registry _lastId — total de registros
Ethereum mainnet   0xc3a2  =  50.082 agentes
Base mainnet       0xf94f  =  63.823 agentes

Para reputación y validación contamos eventos desde el bloque de despliegue hasta la cabeza de la cadena, con dos formas de consulta independientes — una petición de rango completo y un escaneo por chunks con división recursiva — y tomamos solo los números donde ambas coincidían. En Ethereum mainnet, del bloque 24.339.871 al 25.773.811:

// ReputationRegistry 0x8004BAa1… en Ethereum
NewFeedback         3.215
ResponseAppended       37
FeedbackRevoked         0
Upgraded                2

// ValidationRegistry 0x8004Cc84… en Ethereum
ValidationRequest       0
ValidationResponse      0

Cero. No un número bajo — la ausencia literal de una sola validation request en los seis meses y medio desde que el registro salió a producción en Ethereum, en la cadena donde se registraron 50.082 agentes. Base es donde existe la única actividad, y es pequeña: 13 eventos ValidationRequest y 8 ValidationResponse desde el 3 de febrero.

Los números de reputación también merecen una segunda mirada. Decodificando los topics indexados de esos 3.215 eventos NewFeedback en Ethereum se obtienen 1.668 valores distintos de agentId y 653 direcciones de cliente distintas. O sea: el 3,3% de los agentes registrados en Ethereum recibió alguna vez una sola pieza de feedback on-chain, y todo el grafo de reputación del despliegue insignia lo construyeron menos de setecientas direcciones. Nadie revocó feedback nunca en Ethereum.

Es una versión más filosa del hallazgo de la auditoría empírica que cubrimos en julio. Ese estudio encontró que la mayoría de los registration files eran placeholders. La vista a nivel contrato agrega que dos de los tres primitivos de confianza están, tal como están desplegados, estadísticamente sin uso: la capa de identidad tiene volumen, la de reputación tiene un goteo y la de validación no tiene nada.

Quién puede reescribir la capa de confianza

Los tres registros son upgradeables, y la puerta del upgrade es una línea en cada implementación:

function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}

Entonces la pregunta es quién es el owner. Llamamos owner() en los tres proxies en Ethereum y en Base. Todos devuelven 0x547289319C3e6aedB179C0b8e8aF0B5ACd062603. Esa dirección no tiene código en Ethereum mainnet, lo que la vuelve una EOA simple — no un multisig, no un timelock, no un contrato de governance.

La dirección no es incidental. Está hardcodeada en la implementación placeholder que se usa para el despliegue vanity:

function initialize(address identityRegistry_) public initializer {
    __Ownable_init(address(0x547289319C3e6aedB179C0b8e8aF0B5ACd062603));
    __UUPSUpgradeable_init();
    _identityRegistry = identityRegistry_;
}

El flujo de despliegue del repo espera OWNER_PRIVATE_KEY en un archivo .env, genera transacciones de upgrade prefirmadas para los tres proxies y las emite. La guía para operadores del propio repo dice "use multi-sig or timelock for production" y "consider transferring ownership to governance". En las dos cadenas que revisamos, eso no pasó.

No es una capacidad hipotética. El Reputation Registry en Ethereum emitió dos eventos Upgraded, que es exactamente lo que predice la estrategia vanity de dos fases: el proxy primero apunta al placeholder mínimo y después se actualiza a la implementación real. La llave de upgrade ya se ejerció en producción. El slot de implementación ERC-1967 del Identity Registry en mainnet contiene hoy 0x7274e874…, la misma dirección de implementación que aparece en el artefacto de upgrade prefirmado del repo, lo que confirma que mainnet corre el código que leímos.

La forma práctica del riesgo — la semántica de 50.082 identidades y 3.215 registros de feedback en Ethereum, más sus equivalentes en otras 24 mainnets, vive detrás de proxies cuya lógica una sola llave puede reemplazar, en la misma dirección, sin demora. Cualquier cosa que construyas sobre ERC-8004 debería pinnear la dirección de implementación en la que confía y alertar sobre Upgraded, no solo sobre el proxy.

Qué obliga el Solidity en realidad

Leídos como código y no como estándar, los registros obligan menos de lo que sugiere su vocabulario — con una excepción genuinamente cuidada.

Esa excepción es la clave agentWallet, y es la que más importa para pagos. Es una clave de metadata reservada: setMetadata() y el overload con metadata de register() revierten con "reserved key" si intentas escribirla. Se inicializa con la dirección de quien registra, en el mint. Cambiarla exige que la nueva wallet pruebe control, vía una firma typed EIP-712 o una firma de contrato ERC-1271 sobre un struct que liga agentId, newWallet, owner y deadline, donde el deadline debe caer dentro de cinco minutos:

bytes32 private constant AGENT_WALLET_SET_TYPEHASH = keccak256(
  "AgentWalletSet(uint256 agentId,address newWallet,address owner,uint256 deadline)");

uint256 private constant MAX_DEADLINE_DELAY = 5 minutes;

Y se limpia en la transferencia — el override de _update borra agentWallet cada vez que el NFT cambia de manos, así que el nuevo owner debe volver a probar la dirección de cobro. Para un gateway de pagos este es el campo más útil del estándar: la dirección donde un agente cobra no la puede fijar un tercero y no sobrevive a un cambio de propiedad.

El lado de reputación es más delgado. giveFeedback() bloquea solo el autoservicio, preguntándole al Identity Registry si quien llama es el owner o un operator aprobado del agente:

require(!IIdentityRegistry(_identityRegistry).isAuthorizedOrOwner(msg.sender, agentId),
        "Self-feedback not allowed");

Una dirección nueva por review derrota eso, y por eso el diseño anti-Sybil vive en el camino de lectura y no en el de escritura: getSummary() del Reputation Registry revierte con "clientAddresses required" si pasas una lista vacía. No puedes preguntarle a la cadena "cuál es el score de este agente", solo "cuál es su score según estos clientes específicos". Es la decisión correcta, y es la línea de código más honesta del estándar.

La misma disciplina falta al lado. El getSummary() del Validation Registry acepta un array validatorAddresses vacío y lo trata como "sin filtro", iterando toda validación registrada para ese agente y devolviendo un promedio sin ponderar de respuestas uint8. Un solo validator puede mover el promedio global de un agente. Mientras tanto, appendResponse() del Reputation Registry no tiene ningún control de autorización: cualquier dirección puede adjuntar un response URI al feedback de cualquiera, y cada responder nuevo se empuja a un array sin límite. Tanto getSummary() como readAllFeedback() iteran estructuras anidadas sin cota, así que la agregación on-chain se degrada hacia el techo de gas de la llamada a medida que un agente acumula historia.

Un detalle más con consecuencias semánticas: el feedback se guarda como int128 value más uint8 valueDecimals, y getSummary() normaliza cada entrada a 18 decimales, promedia y luego reescala el resultado al valueDecimals más frecuente del conjunto. El significado del número lo cargan solo dos tags de texto libre. Filtra con laxitud y el contrato promediará felizmente una medición de latencia con un monto en dólares y te devolverá un score de aspecto impecable.

El juzgado elige al juez

El punto estructural más profundo no es un bug, es la dirección de la llamada. En el Validation Registry, validationRequest() debe ser llamada por el owner u operator del agente que se valida. El agente elige su validator, inicia el request y apunta al payload off-chain que el validator examinará. Los validators responden con un uint8 entre 0 y 100, y la spec permite explícitamente llamar a validationResponse() repetidas veces para el mismo requestHash para modelar finalidad progresiva.

Es el modelo issuer-pays de las agencias de rating, on-chain. Los incentivos y el slashing son, en palabras de la propia spec, "managed by the specific validation protocol and are outside the scope of this registry". El registro anota afirmaciones; no las vuelve caras de falsificar. Las issues abiertas del proyecto lo dicen en lenguaje más llano: la issue #28, "Rogue validators can manipulate validation response values" (27 de enero de 2026), la issue #16, "[Proposal] Support Refreshing/Expiring/Revoking a Validation" (3 de enero de 2026), y la issue #12, "Inconsistency between Validation and Registration implementations" (20 de noviembre de 2025). Una validación, una vez registrada, no expira nunca.

Con eso a la vista, el cero en Ethereum se lee menos como descuido y más como un precio de mercado exacto para un primitivo inconcluso.

La costura de los pagos

ERC-8004 deliberadamente no es un estándar de pagos. La spec dice que los pagos "are orthogonal to this protocol and not covered here", y el README lo repite. Lo interesante es dónde se filtran los pagos igual, y qué tan finos son esos hooks.

El agent registration file — el JSON al que resuelve agentURI — carga un único booleano:

{
  "services": [ { "name": "A2A", ... }, { "name": "MCP", ... } ],
  "x402Support": false,
  "supportedTrust": ["reputation", "crypto-economic", "tee-attestation"]
}

Un booleano no es un requerimiento de pago. Compáralo con lo que devuelve realmente un servidor x402 en su array accepts — scheme, network, asset, maxAmountRequired, payTo, expiración — que recorrimos en el post del protocolo x402. x402Support: true le dice a un agente que descubre que probablemente hay un paywall en algún lugar detrás del endpoint. No le dice qué cadena, qué stablecoin, qué scheme ni cuánto. Discovery y pricing siguen siendo lookups separados.

El otro hook está del lado del feedback. El archivo de feedback off-chain opcional incluye un objeto proofOfPayment con fromAddress, toAddress, chainId y txHash, anotado en la spec como "this can be used for x402 proof of payment". Ese es el primitivo interesante: entradas de reputación atadas a una transacción liquidada, mucho más difíciles de fabricar a escala que una dirección nueva dejando cinco estrellas. Ojo: aquí chainId es un string pelado, no un identificador CAIP-2, y el objeto no referencia el scheme de pago.

Ambos hooks viven bajo una disputa editorial sin resolver. El fuente de la spec en el repo todavía carga el comentario inline del editor de EIPs sobre la frase de x402: "This is a coinbase thing, right? If it isn't necessary to your standard, can you omit it?". La capa de confianza y la de pagos no se pusieron de acuerdo sobre cuán fuerte acoplarse.

Qué significa para LLM4Agents

LLM4Agents es un gateway: los agentes se autentican, llaman modelos y pagan por uso en stablecoins vía x402 y EIP-3009. ERC-8004 toca eso en tres puntos, y la auditoría cambia el orden de prioridad de los tres.

Primero, getAgentWallet() es usable hoy, y es la parte del estándar con contenido criptográfico real. Una identidad de agente cuya dirección de cobro fue probada con EIP-712 o ERC-1271, y que se invalida automáticamente al transferir, es una mejor fuente de payTo que una dirección autodeclarada en un archivo de configuración. Es un primitivo chico y verificable que podemos leer en cualquiera de 25 mainnets, en la misma dirección.

Segundo, la reputación todavía no es un input con el que podamos pricear riesgo. Con 653 clientes distintos produciendo todo el feedback de Ethereum y sin forma de pedir un score global, cualquier uso del Reputation Registry tiene que tener forma de allowlist explícita: elegimos de quién cuenta el feedback, pasamos esas direcciones a getSummary() y tratamos el resultado como una señal entre varias. Ese es el diseño al que empuja el contrato, y es el correcto.

Tercero, la validación es un ítem de roadmap, no una dependencia. Un registro con cero uso en Ethereum, sin semántica de expiración, con promedio sin filtrar y una issue abierta sobre manipulación de validators no puede controlar el acceso a un endpoint pagado. La versión honesta de "soportamos validación ERC-8004" hoy sería una integración que nadie ejercita.

El lado de amenaza conviene decirlo claro. Si un gateway trata un agentId de ERC-8004 como primitivo de autorización, hereda la llave de upgrade. La identidad es barata — 50.082 registros en Ethereum, la mayoría, según la auditoría previa, sin endpoint vivo — así que un agentId prueba que alguien pagó gas, nada más. La identidad sirve para resolución y atribución; la autorización se queda en el bearer token o en el pago firmado, como argumentamos en Bearer vs x402.

Cómo mantenerse en la frontera

Pasos concretos, en el orden en que los tomaríamos.

1. Resolver, no confiar. Agregar un campo opcional agentId al registro de agentes en el gateway y resolverlo contra el Identity Registry: leer ownerOf, tokenURI y getAgentWallet, traer el registration file y verificar que su array registrations apunte de vuelta al mismo agentRegistry y agentId. Guardar el resultado como metadata pegada a la cuenta, nunca como permiso.

2. Pinnear la implementación. Registrar la dirección de implementación ERC-1967 detrás de cada proxy de registro que leemos, por cadena, y alertar cuando cambie. Un evento Upgraded en un registro del que dependemos es un incidente operativo, no una entrada de changelog. Es barato de construir y es la mitigación específica para una llave de upgrade en una sola EOA.

3. Publicar feedback anclado a pagos. Cuando un agente liquida una factura x402 en el gateway, tenemos exactamente los campos que quiere el objeto proofOfPayment de la spec. Emitir feedback cuyo archivo off-chain cargue el hash de settlement — y cuyo value codifique algo objetivo, como completar llamadas pagadas con éxito — es una forma de sembrar el único tipo de entrada de reputación que cuesta dinero falsificar. Mantener los tags estables para que el promedio on-chain siga siendo semánticamente coherente.

4. Preferir resolución de payTo sobre trust scores. Cablear getAgentWallet() en los caminos de refund y revenue-share antes de cablear cualquier score en control de acceso. El campo de wallet es verificable ahora; el score no.

5. Mirar la revisión de validación, no integrar antes. El propio README del registro dice que la parte de la spec orientada a TEE va a ser revisada. Las señales a vigilar son semántica de expiración para validaciones, cualquier requisito de ponderación o stake para validators, y si los requests pueden iniciarlos el cliente en vez del agente juzgado. Si eso último cambia, la validación se vuelve usable como puerta de admisión. Hasta entonces, el enfoque de observabilidad que describimos en evaluación y observabilidad de agentes produce mejores señales de confianza que la cadena, porque controlamos la medición.

ERC-8004 está haciendo bien la mitad útil de su trabajo. Resolución de identidad en 25 mainnets en una sola dirección, con un campo de cobro probado criptográficamente, es infraestructura real. La mitad de confianza sigue siendo un schema esperando una economía — y los números dicen que la economía todavía no apareció.

La identidad del agente es resolución, no autorización

Registra un agente, carga saldo en USDC y paga por llamada sobre un gateway compatible con OpenAI.

Registrar agente