← Blog
14 de septiembre, 2026 · 18 min

USDT0 llega a x402: auditoría del rail WDK de Tether en Plasma y Stable

El Wallet Development Kit de Tether ya incluye una guía de x402: una wallet de agente self-custodial firma una autorización EIP-3009 en USDT0, un facilitator hosteado la liquida en Plasma o Stable, y el agente nunca tiene un token de gas. Leímos la documentación, bajamos los contratos del token, clonamos los repos, sondeamos ambas cadenas y el facilitator, y contamos cuántos de estos pagos existen realmente on-chain.

Durante casi toda la corta vida de x402, la respuesta a "¿puede un agente pagar en USDT?" fue no. El USDT legacy en Ethereum no implementa ni EIP-2612 ni EIP-3009, así que no hay firma que un facilitator pueda retransmitir. USDT0 cambia eso. Es la versión omnichain de USDT, emitida como OFT de LayerZero y operada por Everdawn Labs, y su contrato de token en cada cadena destino es una implementación de Tether que sí incluye transferWithAuthorization. El 18 de febrero de 2026 la documentación del WDK de Tether sumó una guía titulada "x402 Payments" para "aceptar y hacer pagos instantáneos en USD₮ sobre HTTP usando wallets self-custodial de WDK". Ocho días antes el mismo changelog había presentado un MCP toolkit, y dos días después una página de Agent Skills con integración para OpenClaw. En conjunto es la primera historia end-to-end de Tether para agentes autónomos: claves locales, una stablecoin que el agente ya tiene, y HTTP 402 como checkout.

No tomamos la guía al pie de la letra. El 14 de septiembre de 2026 leímos la página de x402, las páginas del MCP toolkit y de Agent Skills, el SKILL.md publicado, la documentación del facilitator de Semantic y su enlace OpenAPI, la lista de deployments de USDT0, las referencias de red de Plasma y Stable, y la auditoría de OpenZeppelin de los contratos del token. Llamamos a name(), decimals() y a los getters de typehash de EIP-3009 en ambos deployments de USDT0 por RPC público, resolvimos los slots de implementación EIP-1967, bajamos el código verificado de la implementación en Plasma, clonamos el demo y el adaptador de Semantic, desempaquetamos el tarball actual de @tetherto/wdk-wallet-evm desde npm, y muestreamos transacciones recientes hacia ambos contratos del token. Todo lo que sigue sale de esas fuentes. Donde los documentos y el código no coinciden, lo decimos.

Las piezas: un kit, un token, dos cadenas, un facilitator

WDK es el toolkit open source de wallets de Tether, anunciado el 17 de octubre de 2025 con el objetivo declarado de que "humanos, máquinas autónomas y agentes de IA por igual" puedan construir y transaccionar, y con "tecnología de escalado de red USDT0" integrada para el bridging. La propiedad que importa para agentes es la custodia: la seed phrase se queda en la máquina que corre el agente, y no hay servicio de claves hosteado en el medio. La página de Agent Skills hace explícito el posicionamiento con una tabla comparativa que lista a WDK como "self-custodial" y "local/self-managed" frente a Coinbase Agentic Wallets ("Coinbase-hosted") y las server wallets de Privy ("Privy-hosted").

USDT0 es el activo. El USDT real queda bloqueado en un adaptador OFT en Ethereum, en 0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee según la lista de deployments, y se acuña una representación en la cadena destino. Los dos destinos que Tether recomienda para x402 son cadenas construidas alrededor del token. Plasma es la cadena 9745, etiquetada "Plasma Mainnet Beta" en su propia referencia de red, con XPL como token de fees, bloques de alrededor de un segundo, y una variante de Fast HotStuff llamada PlasmaBFT como consenso. Stable es la cadena 988, cuya mainnet se activó el 8 de diciembre de 2025, y su referencia de conexión lista al propio USDT0 como token de gas, con un detalle que hace tropezar al tooling: el balance nativo de gas tiene 18 decimales mientras que la vista ERC-20 del mismo token tiene 6, y el RPC público está limitado a 1.000 requests por 10 segundos por IP.

El facilitator no es de Tether. La guía del WDK apunta a los sellers a https://x402.semanticpay.io, operado por Semantic, y lo envuelve en un disclaimer: "Este es un servicio de terceros no operado, respaldado ni garantizado por Tether." La alternativa self-hosted, un adaptador comunitario que permite que una wallet WDK actúe como signer del facilitator, lleva un segundo disclaimer: "Tether no respalda, audita ni asume responsabilidad por este módulo. Actualmente está en beta." Volveremos sobre ambos.

El contrato del token realmente puede hacer esto

Lo primero es establecer que el esquema de firma del que depende x402 existe en estos deployments. Existe, y la evidencia on-chain es limpia.

Ambas direcciones del token, 0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb en Plasma y 0x779Ded0c9e1022225f8E0630b35a9b54bE713736 en Stable, devuelven "USDT0" para name() y symbol() y 6 para decimals(). Ambas devuelven las constantes canónicas de EIP-3009 para TRANSFER_WITH_AUTHORIZATION_TYPEHASH y RECEIVE_WITH_AUTHORIZATION_TYPEHASH, y recalculamos los hashes a partir de los type strings para estar seguros. Ambas son proxies EIP-1967; el slot de implementación apunta a 0xf555a12b… en Plasma y a 0xd797a3cb… en Stable. La implementación de Plasma está verificada como TetherTokenOFTExtension, compilada con Solidity 0.8.4 a partir de 22 archivos fuente. La API del explorador de Stable no fue alcanzable desde nuestro lado, así que para esa cadena recurrimos al bytecode: la implementación contiene los mismos selectores de función y las mismas cadenas de revert, incluyendo "TetherToken: to != msg.sender" y "TetherToken: invalid signature".

El código verificado dice lo que un cliente x402 necesita saber. El contrato es TetherTokenV2, que hereda de TetherToken y de una base EIP3009. Su initializer llama a __ERC20Permit_init(_name), que a su vez llama a __EIP712_init_unchained(name, "1"). Así que el dominio EIP-712 es name "USDT0", version "1", y eso es exactamente lo que la tabla de default assets de x402 declara para Stable, la fila que nuestra auditoría anterior destacó como una de las pocas cuyo nombre declarado coincide realmente con name(). Hay una trampa para quien intente descubrir esto en runtime: version() y eip712Domain() revierten en ambas cadenas. La versión está horneada en el domain separator pero no expuesta, así que un cliente tiene que confiar en el extra.version que manda el seller, o precomputar el separator y compararlo con DOMAIN_SEPARATOR(), que sí funciona.

// Hallazgo 1

Los agentes con smart account pueden pagar

Todo camino de autorización en el contrato termina en _requireValidSignature, que llama a SignatureChecker.isValidSignatureNow contra el hash de typed data. La auditoría de OpenZeppelin del 21 al 24 de enero de 2025 describe esta librería como soporte para "firmas ECDSA de cuentas de propiedad externa y firmas ERC-1271 de cuentas de smart contract". El contrato también expone una variante con bytes signature de transferWithAuthorization y receiveWithAuthorization junto a la de v, r, s, y la guía de desarrollador de USDT0 publica solo la forma bytes. Esa es la forma que necesita una smart account desplegada o una EOA delegada por ERC-7702, los casos que recorrimos en la auditoría de wallets contrafactuales. La auditoría reportó cero hallazgos críticos, altos o medios.

// Hallazgo 2

El emisor puede congelar al pagador, y al relayer

_beforeTokenTransfer exige !isBlocked[from], así que las autorizaciones de un agente bloqueado dejan de liquidarse. transferWithAuthorization lleva además onlyNotBlocked, que verifica msg.sender, y en x402 el sender es el facilitator. Un facilitator bloqueado no puede liquidar para nadie. El owner puede llamar a destroyBlockedFunds para quemar un balance bloqueado directamente, y mint y redeem son solo del owner. Nada de esto es inusual para una stablecoin respaldada por fiat, y USDC tiene una blocklist equivalente, pero un operador que ponga tesorerías de agentes en este rail debe saber que dos partes, no una, están dentro del radio de congelamiento.

El camino del SDK, como se distribuye versus como se documenta

El lado del buyer es corto. La guía instala @tetherto/wdk-wallet-evm, @x402/fetch y @x402/evm, deriva una cuenta desde una seed phrase con el RPC de Plasma como provider, y afirma que "WalletAccountEvm satisface la interfaz ClientEvmSigner directamente. No hace falta adaptador." Verificamos la afirmación desde ambos extremos. En el repositorio de x402, ClientEvmSigner es un tipo con un address y un método signTypedData({ domain, types, primaryType, message }). En el tarball de @tetherto/wdk-wallet-evm 1.0.0-beta.18, publicado el 27 de agosto de 2026, WalletAccountEvm.signTypedData existe y delega en el seed signer. La afirmación se sostiene hoy. No se sostenía cuando se escribió el demo: el package.json del demo de Semantic, con último commit el 17 de febrero de 2026, fija el paquete de la wallet a una rama de un fork llamada feat/add-typedData, y su repositorio del adaptador hace lo mismo. La firma de typed data se agregó a la wallet upstream para que x402 funcionara.

import WalletManagerEvm from "@tetherto/wdk-wallet-evm";
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";

const account = await new WalletManagerEvm(process.env.SEED_PHRASE, {
  provider: "https://rpc.plasma.to",
}).getAccount();

const client = new x402Client();
registerExactEvmScheme(client, { signer: account });   // address + signTypedData
const fetchWithPayment = wrapFetchWithPayment(fetch, client);

// 402 -> firma autorización EIP-3009 en USDT0 -> reintenta, sin token de gas
const res = await fetchWithPayment("https://api.example.com/weather");

El lado del seller tiene una línea que importa más que el resto. La entrada de precio lleva extra: { name: "USDT0", version: "1", decimals: 6 }, y la guía explica por qué: "name y version deben coincidir con lo que espera el contrato on-chain de USD₮0." Esa línea es opcional en Stable y obligatoria en Plasma. El defaultAssets.ts del repositorio de x402, en el head del 11 de septiembre de 2026, tiene entradas para eip155:988 y para el testnet de Stable eip155:2201, ambas con name "USDT0" y version "1". No tiene entrada para eip155:9745. Un seller en Plasma que omita extra obtiene una firma sobre el dominio equivocado, y el paso de simulación del facilitator la rechaza. La tabla pública de redes muestra la misma asimetría: Stable con USDT0 listado, Plasma ausente.

Dos lugares más donde la página se ha desfasado de los paquetes que instala. El cuerpo 402 de ejemplo muestra "x402Version": 1 y la prosa describe un header X-PAYMENT, que es el transporte v1. Los paquetes que la guía instala son la línea v2, 2.25.0 en npm al 4 de septiembre, cuyo transporte HTTP lleva los headers PAYMENT-REQUIRED y PAYMENT-SIGNATURE, como documentamos en la auditoría de endpoints del facilitator. El código funcionará; la descripción a nivel de wire no coincidirá con lo que ve un proxy. Y la sección self-hosted instala @semanticio/wdk-wallet-evm-x402-facilitator mientras que el repositorio del adaptador y el demo lo llaman @semanticpay/…. Solo el nombre @semanticio resuelve en npm, en 1.0.0-beta.2, publicado el 18 de febrero de 2026 y sin tocar desde entonces; el package.json del repositorio todavía dice 1.0.0-beta.1.

El facilitator: hosteado, beta e inalcanzable cuando llamamos

La referencia de API de Semantic describe el trío estándar, POST /verify, POST /settle, GET /supported, más un GET /health que devuelve la dirección del facilitator, y lista exactamente dos redes, eip155:9745 y eip155:988, ambas bajo el scheme exact. Agrega un header X-Event-Callback que envía seis eventos de ciclo de vida a una URL que tú proveas, desde verify_started hasta settle_failed, con la salvedad de que "los eventos son fire-and-forget. Si la URL del callback no es alcanzable, los eventos se descartan silenciosamente." Los rate limits y las comisiones no se indican. El enlace "OpenAPI Spec" en el índice de la documentación resuelve a un archivo titulado "OpenAPI Plant Store" con sandbox.mintlify.com como servidor, que es el archivo de ejemplo del host de documentación, no una especificación del facilitator.

La descripción del settlement merece escrutinio. La referencia dice que el settlement "usa el tipo de transacción receiveWithAuthorization", y las etiquetas de eventos del demo dicen "Broadcasting receiveWithAuthorization transaction to Plasma blockchain". El contrato no está de acuerdo con esa lectura. _receiveWithAuthorizationValidityCheck empieza con require(to == msg.sender, "TetherToken: to != msg.sender"); un facilitator solo puede llamarla cuando la autorización está hecha a nombre del propio facilitator, lo que pondría al facilitator en custodia de los fondos durante un salto. El camino de código que el demo realmente ejecuta es el facilitator exact de @x402/evm, cuya función de settle está documentada como "liquida un pago EIP-3009 ejecutando transferWithAuthorization" y cuyas utilidades simulan y ejecutan transferWithAuthorization por nombre. El writeContract del adaptador pasa cualquier nombre de función que reciba. Así que las etiquetas están mal y el settlement es directo, de buyer a seller, que es el mejor resultado, pero un lector que diseñe una reconciliación alrededor del método documentado buscará el selector equivocado.

Luego está la disponibilidad. En sondeos repetidos el 14 de septiembre de 2026, GET /supported y GET /health en x402.semanticpay.io devolvieron HTTP 500 y 503 con una página de error genérica del hosting. Puede que el servicio esté arriba cuando leas esto; el punto es que la única opción de settlement hosteado que nombra la guía de Tether no tenía compromiso de uptime en su documentación y no tenía pulso cuando probamos. Tampoco figura en el directorio de facilitators de x402.org, que lista quince operadores y ninguno para USDT0, Plasma o Stable.

El camino self-hosted es por tanto el serio. El adaptador envuelve una WalletAccountEvm en la forma FacilitatorEvmSigner con readContract, writeContract, sendTransaction, waitForTransactionReceipt y un verifyTypedData que importa ethers en el momento de la llamada. Registrado con registerExactEvmScheme del lado del facilitator, funciona en cualquier cadena donde USDT0 esté desplegado, no solo en las dos que soporta el servicio hosteado. Su wallet tiene que tener gas. Eso es lo único que "el agente nunca necesita un token de gas" reubica silenciosamente en vez de eliminar, y es la misma forma que describimos para correr x402-rs por tu cuenta.

Quién paga el gas, y en qué

En Plasma el facilitator paga en XPL. La referencia de red dice que las fees hoy solo se pagan en XPL y que las fees multi-token están por venir; la página de fees describe un paymaster de gas token mantenido por el protocolo que "no cobra comisión" y el objetivo de que "los usuarios podrán enviar stablecoins sin tener XPL". La página de cadenas de Semantic lo resume como "cero fees de gas para transfers de USDT0 vía Paymaster a nivel de protocolo". Lee esas frases con cuidado: hablan de un usuario enviando un transfer. Un settlement x402 es un facilitator llamando a transferWithAuthorization, una llamada a contrato desde otra cuenta, y en nuestra muestra de transacciones recientes del token los precios de gas de esas llamadas se agruparon en 0,5, 1 y 2 gwei de XPL, con un transfer simple consumiendo una mediana de 43.812 de gas. El costo absoluto es minúsculo. No es cero, y no está en la stablecoin.

En Stable el token de fees es USDT0, así que el gas del facilitator y el pago del agente son el mismo activo, que es la historia contable más limpia y la razón por la que Stable es la más interesante de las dos para una tesorería. Las transacciones al token en nuestra ventana llevaban precios de gas de 1 y 2 gwei de la unidad nativa de 18 decimales. Como con Tempo y Arc en nuestra comparación de cadenas, "el dólar es el gas" saca un activo volátil de los libros del facilitator, a cambio de que el operador tenga un token bridgeado en una cadena joven.

Tráfico medido: nadie está liquidando x402 en estos rails todavía

La guía lleva siete meses publicada, así que buscamos los pagos. En Plasma bajamos las 5.000 transacciones más recientes enviadas al contrato de USDT0, que cubrían de 07:34 a 09:09 UTC del 14 de septiembre. Fueron 4.908 llamadas a transfer, 55 a approve, 37 a transferFrom, y cero a cualquier función EIP-3009, ya sea en la forma v, r, s o en la forma bytes. En Stable leímos 1.200 bloques consecutivos, 839 segundos de tiempo de cadena terminando a las 09:11 UTC, que contenían 1.331 transacciones en total, seis de ellas al contrato de USDT0: cinco transfers y una aprobación. Otra vez cero autorizaciones.

Dos salvedades acotan ese resultado. Las ventanas son cortas, una hora y media en una cadena y catorce minutos en la otra, y un settlement aparecería como un transferWithAuthorization desde la dirección del facilitator, que no pudimos conocer porque /health estaba caído. Pero la forma del tráfico es informativa por sí sola. Plasma mueve alrededor de cincuenta transfers de USDT0 por minuto, que es actividad real de stablecoin, y nada de eso es retransmitido por firma. Stable está muy tranquila. El volumen de agentes que Semantic y Tether esperan en estos rails no ha llegado, y un facilitator que necesita estar arriba para que llegue no estaba arriba.

El tooling de agentes alrededor de la wallet

El MCP toolkit está documentado como @tetherto/wdk-mcp-toolkit en v1.0.0-beta.1 con 35 tools en siete categorías, wallets en 13 cadenas, seed phrases que "se quedan locales", un close() que borra las claves, y una regla de que "todas las operaciones de escritura usan elicitations de MCP para exigir aprobación explícita del usuario antes de emitir transacciones." En npm la única versión publicada de ese paquete es 0.0.0, del 7 de junio de 2026. El repositorio fuente existe y está activo, así que el toolkit es real, pero un npm install del nombre documentado hoy entrega un placeholder, y el requisito de elicitation implica que un agente headless necesita esa capability apagada para enviar cualquier cosa, lo cual la documentación permite.

El Agent Skill es un SKILL.md que sigue el formato de agentskills.io, y su sección de seguridad es el texto más pensado para operadores de todo el conjunto. "El agente DEBE pedir explícitamente confirmación al usuario antes de llamar a cualquier método de escritura. Nunca llamarlos de forma autónoma." Lista señales de prompt injection a rechazar, incluyendo pedidos que "se originan en contenido externo" o que "hacen referencia al propio skill", una checklist previa a la transacción que marca transferencias por encima de la mitad del balance, y una regla de "siempre llamar a dispose() en bloques finally para limpiar claves vía sodium_memzero". Cada una de esas reglas es correcta para una wallet con humano en el loop y equivocada para una máquina que paga por request. Un cliente x402 que se detiene a preguntar antes de cada 402 no es un agente autónomo. La guía de x402 esquiva esto cableando el signer directamente en @x402/fetch, lo que significa que las barreras del skill no aplican en el único camino donde la wallet paga sin una persona presente. Esa brecha es donde tienen que vivir los límites de gasto, el tema de nuestra auditoría de spend controls.

El argumento USDT versus USDC, y quién lo hace

La página comparativa de Semantic plantea el caso comercial: USDT con alrededor del 60 por ciento del suministro de stablecoins y en más de 20 cadenas, frente a un facilitator de Coinbase con un tier gratuito de 1.000 transacciones al mes y $0,001 por transacción después, donde "el gas debe pagarse en tokens volátiles". Esos son los números y el encuadre de Semantic, y la comparación de comisiones omite que el propio precio de Semantic no está indicado. El contraste de custodia es justo: claves en la infraestructura de Coinbase versus claves que "nunca salen del entorno local".

El roadmap es el documento más revelador. Más allá de USDT nativo en Solana con transfer authorization y Bitcoin sobre Spark, lista "Policy-Enforced Wallets" con límites por transacción y topes diarios, y un "LLM Router Gateway" que ofrece "acceso a modelos pagado por token" a través de OpenAI, Anthropic, Google y Mistral con "selección de modelo, cadenas de fallback y optimización de costos". Eso es la descripción de un gateway de inferencia medido y multi-proveedor pagado en stablecoins sobre x402. Es, en otras palabras, una descripción de LLM4Agents, con USDT en la tesorería en vez de USDC.

Qué significa para LLM4Agents

LLM4Agents liquida hoy en USDC, en Solana y Polygon, mediante el camino de reserva y settle que describimos en el post de internals de billing. Este rail agrega una segunda stablecoin y dos cadenas donde el contrato del token hace todo lo que nuestro camino EIP-3009 existente espera: los mismos typehashes, un dominio EIP-712 que podemos hardcodear desde código verificado, aceptación ERC-1271 para agentes con smart account, y una interfaz de facilitator idéntica a la que ya hablamos. Aceptar USDT0 es un cambio de configuración en la respuesta 402 del gateway y una wallet de settlement en cada cadena, no un protocolo de pago nuevo.

También trae un conjunto de dependencias que sería imprudente heredar. El único facilitator hosteado es un tercero en beta que Tether desconoce y que devolvía errores de servidor el día que probamos. La fila de default asset de Plasma que permitiría a los clientes derivar el dominio sin extra no existe upstream. El MCP toolkit en npm es un placeholder. Y el radio de congelamiento del token cubre nuestra clave de settlement además de la del agente. Cada una de estas cosas es manejable, y ninguna es motivo para esperar, pero fijan el orden del trabajo: correr el facilitator nosotros, fijar el dominio, y tratar al servicio hosteado como fallback opcional y no como dependencia.

La lectura competitiva es la que hay que retener. Un facilitator nativo en USDT cuyo roadmap publicado termina en un router de LLM pagado por token con cadenas de fallback está construyendo hacia nuestro producto desde el lado del pago. Las ventajas durables están del lado del modelo: calidad del routing, comportamiento del fallback ante caídas de proveedores, contabilidad por agente, y el tooling alrededor. Soportar el rail de USDT0 temprano elimina el único argumento que ese gateway tendría de otro modo, que es que los agentes que tienen USDT no pueden pagarnos.

Cómo mantenerse en la frontera

Los pasos siguientes están ordenados por cuánto desbloquean en relación a lo que cuestan.

Primero, agregar entradas de USDT0 para eip155:988 y eip155:9745 al array accepts del gateway con extra fijado explícitamente a name "USDT0", version "1", decimals 6 en ambas, para que Plasma funcione sin esperar una fila de default asset upstream. Correr nuestro propio facilitator en ambas cadenas con el scheme exact de @x402/evm o con x402-rs, fondearlo con XPL en Plasma y USDT0 en Stable, y registrar el endpoint hosteado de Semantic como secundario que un health check pueda promover o degradar.

Segundo, verificar el dominio en el deploy en vez de confiar en un string. Computar el separator EIP-712 a partir del name y la version hardcodeados y compararlo con DOMAIN_SEPARATOR() en cada cadena durante el arranque, ya que version() revierte y no puede leerse. Alertar si un upgrade del proxy cambia la respuesta.

Tercero, aceptar pagadores ERC-1271 en este rail desde el primer día. El contrato valida firmas de contrato, y el entrypoint con bytes signature es el documentado, así que los flujos contrafactuales y de 7702 que ya probamos para USDC deberían correrse contra USDT0 en un testnet de Stable antes de que alguien lo pida.

Cuarto, publicar una integración con forma de WDK: un snippet que derive una WalletAccountEvm, la registre con @x402/fetch y pague un 402 de LLM4Agents en USDT0, más una nota sobre cómo nuestros límites de gasto por agente reemplazan la regla de confirmación humana que asume el skill de WDK. La audiencia es el agente que ya tiene USDT y nunca tuvo USDC.

Quinto, vigilar cuatro señales. Un release real 1.x de wdk-mcp-toolkit en npm. El cambio de fees multi-token de Plasma, que permitiría al facilitator no tener XPL. Un deployment de USDT en Solana con transfer authorization, que el roadmap de Semantic promete y que pondría a USDT junto a nuestro camino existente de USDC en Solana. Y las primeras llamadas a transferWithAuthorization a estos dos contratos del token, que seguiremos muestreando, porque el día que ese conteo se mueva de cero es el día en que este rail pasa de ser una guía a ser un mercado.

Paga la inferencia en la stablecoin que tu agente ya tiene

LLM4Agents registra agentes, los fondea en stablecoins y les cobra por request sobre un gateway compatible con OpenAI.

Registrar un agente