EIP-3009: la transferencia gasless bajo cada pago de agente
x402 se lleva los titulares. Pero cuando un agente paga por una llamada a una API, el dinero no se mueve por HTTP. Se mueve por una función en un contrato de token: transferWithAuthorization. Esa función la define EIP-3009, y vale la pena leerla con cuidado.
Ya escribimos sobre x402 como el rail de pago nativo de HTTP y sobre cuándo usarlo frente a una bearer key. Esos posts se quedan en la capa de protocolo. Este baja un nivel, al primitivo criptográfico que hace que todo lo demás funcione. Si operas agentes que pagan por llamada, este es el mecanismo por el que pasa tu dinero, así que conviene saber cómo se comporta y dónde se rompe.
El problema: approve, transferFrom y la trampa del gas token
Antes de EIP-3009, pagar con un token ERC-20 era un baile de dos transacciones. Primero el pagador enviaba un approve para permitir que un contrato gastara sus tokens. Después alguien enviaba un transferFrom para moverlos de verdad. Dos transacciones on-chain, dos comisiones de gas, para un solo pago.
El problema más profundo era el gas token en sí. Para gastar USDC en Ethereum, tenías que tener ETH para pagar el gas. Una wallet con cien dólares de USDC y cero ETH no podía mover un centavo. Para un humano es una molestia de onboarding. Para un agente autónomo es una falla estructural: el agente tendría que gestionar un balance de token nativo en cada cadena que toca, recargarlo antes de que se agote, y meter la volatilidad del gas en cada decisión. Eso es una segunda tesorería que cuidar, y arruina el sentido de un agente que solo quiere pagar por una llamada al modelo.
EIP-3009 elimina ambos problemas convirtiendo una transferencia en un mensaje firmado.
Cómo funciona transferWithAuthorization
En vez de enviar un approve on-chain, el pagador firma una autorización off-chain: un mensaje estructurado que dice "mueve esta cantidad de mi balance, a esta dirección, válido dentro de esta ventana de tiempo, identificado por este nonce". La firma se produce con la llave del pagador pero no transmite nada. Un tercero — un relayer, o en términos de x402 un facilitator — toma ese mensaje firmado y lo envía al contrato del token, pagando el gas.
El contrato hace la verificación por sí mismo. Reconstruye el hash EIP-712 de datos tipados, ejecuta ecrecover para confirmar que la firma pertenece a la dirección from, verifica que el nonce nunca se haya usado, y confirma que el tiempo del bloque actual cae dentro de la ventana de validez. Si cada check pasa, mueve los tokens. El pagador nunca tocó gas; el relayer sí.
Aquí está la función, directo de la especificación EIP-3009:
function transferWithAuthorization(
address from, address to, uint256 value,
uint256 validAfter, uint256 validBefore,
bytes32 nonce, uint8 v, bytes32 r, bytes32 s
) external;
Dos decisiones de diseño importan para los agentes. El nonce es un valor aleatorio de 32 bytes, no un contador secuencial. Eso significa que una wallet puede firmar muchas autorizaciones en paralelo sin preocuparse de que fallen por orden — crítico para un agente que dispara requests pagados concurrentes. Y el par de timestamps validAfter / validBefore permite agendar una autorización: firma ahora, pagable en dos semanas, expirada en tres. Suscripciones, escrow y pagos por hito salen de esa ventana gratis.
El mensaje que el pagador firma es un struct tipado. Su type hash está fijo en el spec:
// keccak256 del type string de TransferWithAuthorization
// TransferWithAuthorization(address from,address to,uint256 value,
// uint256 validAfter,uint256 validBefore,bytes32 nonce)
bytes32 TYPEHASH =
0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267;
EIP-3009 salió como Draft ERC en 2020, escrito por Peter Jihoon Kim, Kevin Britz y David Knott. Circle lo implementó en el contrato USDC v2 junto con EIP-2612 (permit). Los dos estándares se solapan pero difieren: permit autoriza un allowance que aún necesita una transferencia posterior, y usa nonces secuenciales. EIP-3009 autoriza la transferencia entera de forma atómica y usa nonces aleatorios. Para un rail de pago, atómico-y-paralelo gana.
La trampa de front-running: transfer vs receive
Hay una segunda función con los mismos parámetros, receiveWithAuthorization, y la diferencia entre las dos es una frontera de seguridad, no de conveniencia.
transferWithAuthorization lo puede enviar cualquiera. Si un contrato lo envuelve — por ejemplo, "llama transferWithAuthorization, luego acredita el depósito" — un atacante que observa el mempool puede extraer la autorización firmada y llamar directo al transferWithAuthorization pelado, haciendo front-running al wrapper. La transferencia se ejecuta, pero la lógica posterior del wrapper nunca corre. El depósito llega y nunca se acredita.
La respuesta del spec es receiveWithAuthorization, que agrega un check: msg.sender debe ser igual al payee. Eso vuelve la autorización inútil para cualquier front-runner, porque solo el destinatario previsto puede enviarla. La regla del spec es tajante: usa la variante receive cuando llames desde otro contrato. Si tu lógica de settlement vive en un contrato wrapper, y para facturación de agentes tarde o temprano vivirá ahí, esto no es opcional.
Cómo x402 se apoya en EIP-3009
x402 es la capa HTTP; EIP-3009 es la capa de settlement. Cuando un resource server responde a un request con 402 Payment Required, el cliente construye una autorización EIP-3009, la firma, y reintenta el request con el payload firmado en un header X-PAYMENT. El server entrega ese payload a un facilitator, y el facilitator hace dos trabajos distintos.
Verify es de solo lectura. Según el spec EVM del exact-scheme, el facilitator confirma que la firma recupera a authorization.from, verifica que el pagador tiene balance suficiente, valida que el monto y el destinatario de la autorización coinciden con lo que el server exigió, confirma que el token y la red cuadran, y simula la llamada transferWithAuthorization para asegurar que tendría éxito. Todavía no se ha movido dinero.
Settle es la escritura. El facilitator envía la transacción real de transferWithAuthorization y paga el gas. El payload que lleva es la misma autorización que el cliente firmó:
// payload.authorization dentro del header X-PAYMENT
{
"from": "0xAgentWallet...",
"to": "0xResourceServer...",
"value": "10000", // 0.01 USDC, 6 decimales
"validAfter": "0",
"validBefore": "1752345600",
"nonce": "0x9f2c...random32bytes"
}
La división importa. Verify deja que el server decida si servir la respuesta antes de pagar por settle. Settle es donde se gasta gas y la transferencia se vuelve final. Como el facilitator solo puede transmitir la autorización firmada — no alterar su monto ni su destino — el riesgo del pagador está acotado a lo que firmó. Ese es todo el argumento de seguridad del modelo: al facilitator se le confía liveness, no fondos.
El método de asset por defecto de x402 es EIP-3009 para los tokens que lo soportan, con fallback a Permit2 para los que no. El facilitator alojado de Coinbase liquida pagos EIP-3009 en USDC y EURC en Base, Polygon, Arbitrum, World y Solana, con un free tier de 1,000 transacciones al mes y $0.001 por transacción más allá. Son números pequeños, y así deben ser — un primitivo de pago que cuesta una décima de centavo liquidar es lo que hace plausible la facturación por llamada. Cubrimos cómo un gateway convierte eso en balances usables en los internals de facturación reserve-proxy-settle.
Dónde el modelo se queda sin margen
EIP-3009 es elegante, pero es estrecho, y un operador debería conocer los bordes antes de apostar una flota a él.
El primer borde es el soporte de tokens. EIP-3009 es una feature de contrato, no de red, así que solo funciona si el token específico lo implementa. USDC y EURC lo hacen. USDT de Tether, la stablecoin más grande por supply, no lo implementa en Ethereum — que es exactamente por qué x402 hace fallback a Permit2 para tokens no-3009 y por qué USDC domina los pagos de agentes hoy. También hay huecos de implementación dentro de la misma marca: algunos despliegues bridged, notablemente el USDC bridged de Polygon, no exponen la superficie completa de EIP-3009. Siempre verifica que tu token objetivo en tu cadena objetivo realmente soporte el método, y prefiere receiveWithAuthorization donde exista.
El segundo borde es más profundo: EIP-3009 es solo una transferencia. Mueve valor de A a B y para. No puede expresar "paga, luego ejecuta lógica de negocio, luego acuña acceso, luego reparte revenue" como una operación atómica. Para una sola llamada a una API está bien. Para suscripciones medidas, créditos, escrow o revenue splits, necesitas lógica de settlement en un contrato, y esa lógica debe usar la variante receive para quedar a salvo de front-running. Esta es la frontera que el ecosistema está empujando ahora — pasar de transferencias peladas a settlement programable sin renunciar al modelo gasless y firma-primero que hizo posible que los agentes pagaran en primer lugar.
Qué significa para LLM4Agents
LLM4Agents cobra a los agentes por uso en stablecoins sobre un gateway compatible con OpenAI. EIP-3009 es el primitivo debajo de ese cobro. Cada decisión de diseño del spec mapea a algo que nos importa.
Los nonces aleatorios significan que un agente puede firmar muchos requests pagados en paralelo sin orden serial — exactamente el perfil de concurrencia de una flota golpeando el gateway. El settlement gasless significa que un agente se fondea una vez en USDC y nunca tiene que tener ETH, MATIC o SOL para pagar inferencia; el modelo de una-sola-tesorería que defendimos solo es posible porque la transferencia lleva su propio relay de gas. La ventana de validez nos da un handle nativo para expiración de autorización y facturación agendada sin inventar el nuestro. Y la división verify/settle es la costura donde el gateway decide servir una completion antes de que la transferencia finalice — la misma costura sobre la que está construido nuestro flujo reserve-and-settle.
La regla de front-running es la lección más filosa. Cualquier contrato de settlement que nosotros o nuestros facilitators corramos debe usar receiveWithAuthorization, no la transferencia pelada. Un gateway que acredita balance a partir de una llamada transferWithAuthorization en un wrapper está a un observador de mempool de acreditar nada. Esto no es una preocupación teórica; es un ítem del checklist de code review.
Cómo mantenerse en la frontera
Pasos concretos, en orden.
Primero, trata el soporte de EIP-3009 como un chequeo de capacidad por-token y por-cadena, no como un supuesto. Mantén una matriz de qué stablecoins en qué cadenas exponen transferWithAuthorization y, críticamente, receiveWithAuthorization — y enruta el settlement en consecuencia, con fallback a Permit2 solo cuando estás obligado. No dejes que un caso borde de USDC bridged de Polygon aparezca como un pago de agente fallido.
Segundo, audita cada ruta de settlement contra la trampa de front-running. Donde sea que un contrato envuelva una autorización, exige la variante receive y verifica el check del payee on-chain. Hazlo una puerta en el pipeline de deploy, no un comentario en un doc de diseño.
Tercero, construye hacia settlement programable sin abandonar el modelo firma-primero. La próxima fase es "paga más ejecuta" como un solo paso atómico — medición, créditos, revenue splits — expresado en un contrato que consume receive-authorizations. Empieza por el lado de lectura: expón chequeos estilo verify para que los agentes puedan confirmar que un pago pasaría antes de comprometerse.
Cuarto, mantente token-agnóstico en la interfaz y opinado por debajo. Los agentes deberían firmar una sola forma de autorización; el gateway debería decidir si eso se vuelve una transferencia EIP-3009, un flujo Permit2, o algo más nuevo, y absorber la diferencia. El primitivo seguirá evolucionando. La experiencia del agente no debería.
Paga por llamada en stablecoins, sin gas token
LLM4Agents liquida la inferencia de agentes sobre el mismo primitivo gasless en el que se apoya x402. Un balance en USDC, un endpoint compatible con OpenAI, sin ETH que cuidar.
Registra tu agente