← Blog
5 de septiembre, 2026 · 16 min

ERC-7683 fue reescrito alrededor de resolvers

Casi todo lo que se ha escrito sobre ERC-7683 describe un estandar que el ERC ya no especifica. El 2026-05-13 el documento fue reescrito alrededor de una interfaz de resolver, y los structs de orden que todos citan quedaron relegados a una seccion titulada "Previous Draft".

ERC-7683 es el estandar de intents cross-chain. La version que circulo durante dos anios definia dos structs de orden, una forma resuelta canonica, y dos interfaces de settlement llamadas IOriginSettler e IDestinationSettler. Esa es la version que aparece en los explainers, los tutoriales y las guias de integracion.

No es la version que esta en el ERC. Bajamos el texto actual del repositorio ethereum/ERCs y lo leimos contra su propio historial. Lo que sigue es una auditoria de que cambio, las cuatro fallas que los autores ahora admiten, y por que el reemplazo importa para cualquier sistema que pague por trabajo entre cadenas.

El commit

El archivo ERCS/erc-7683.md tiene un historial corto. Se agrego el 2024-04-12. Entre esa fecha y el 2025-01-08 recibio seis ediciones, todas correcciones de tipeo, aclaraciones de comentarios y extensiones menores. Despues quedo intacto durante dieciseis meses.

El 2026-05-13 entro un solo commit con el mensaje Update ERC-7683: Redesign around resolvers, con autoria de Francisco Giordano. Agrego 350 lineas y elimino 264. Eso no es una enmienda. Es un reemplazo del cuerpo de la especificacion.

El frontmatter cuenta el resto de la historia:

eip: 7683
title: Cross Chain Intents
description: Programmable solvers for intent protocols.
status: Draft
type: Standards Track
category: ERC
created: 2024-04-11
requires: 7930

Tres cosas para notar. El status sigue siendo Draft — este estandar nunca fue Final, a pesar de que la cobertura secundaria lo describe como ratificado. La descripcion ya no menciona cadenas: ahora dice "programmable solvers for intent protocols", un alcance mas amplio que la transferencia de valor cross-chain. Y hay una dependencia nueva: ERC-7930, interoperable addresses, que decodificamos mas abajo porque cambia todas las firmas de tipos del documento.

La lista de autores tambien crecio a siete: Francisco Giordano, Mark Toda, Matt Rice, Nick Pai, Alexander Lindgren, Mark Gretzke y Chris Cashwell.

Que estandarizaba el draft anterior

Vale la pena repetir el diseno viejo con precision, porque es el modelo mental que todavia carga la mayoria de los integradores.

El usuario firmaba un GaslessCrossChainOrder con originSettler, user, nonce, originChainId, openDeadline, fillDeadline, orderDataType y un blob opaco orderData. Un OnchainCrossChainOrder era la misma idea con solo fillDeadline, orderDataType y orderData.

Cualquiera de las dos formas se resolvia en un ResolvedCrossChainOrder que llevaba orderId, arrays de Output llamados maxSpent y minReceived, y un array de FillInstruction. Un IOriginSettler exponia open, openFor, resolve y resolveFor; emitia un evento Open que cargaba la orden resuelta completa. Un IDestinationSettler exponia un unico fill(bytes32 orderId, bytes originData, bytes fillerData).

Esa descripcion es correcta — y es lo que erc7683.org, el sitio de documentacion del propio estandar, todavia publica como la spec. El ERC canonico y su sitio companero ahora describen sistemas distintos.

Consecuencia practica — si estas integrando hoy, "compatible con ERC-7683" es ambiguo. Pregunta cual draft. El diseno basado en structs y el diseno basado en resolver comparten un numero y casi nada mas.

Las cuatro fallas que el ERC ahora admite

El nuevo Rationale contiene una seccion llamada "Previous Draft" que es inusualmente franca para un documento de estandares. Lista cuatro razones por las que el diseno anterior no logro su objetivo.

La estandarizacion era superficial. Los structs de orden estaban parametrizados por orderDataType y un payload orderData especifico de cada implementacion. En palabras del propio ERC, las ordenes estaban "only superficially standardized" — un solver todavia tenia que implementar soporte para los subtipos de cada protocolo, "which is not meaningfully different from a situation where each protocol implements an entirely custom interface". El struct era compartido. El trabajo no.

La rentabilidad no tenia cota. maxSpent y minReceived existian para que un solver decidiera si valia la pena llenar una orden. Pero solo daban una cota inferior de ganancia. Si la cota era floja, ordenes rentables parecian no rentables y quedaban sin llenar. El ERC nombra el caso degenerado directamente: a veces los protocolos no podian dar otro maxSpent que UINT256_MAX. Eso pasa cuando la firma del usuario solo fija el peor precio que acepta, o cuando el costo real del solver depende de un valor elegido durante la ejecucion, como las priority fees en una subasta de gas.

Se asumia escrow. El flujo viejo era escrow-first: los fondos del usuario se bloquean en la cadena de origen, y recien entonces la orden puede llenarse. Los protocolos de resource lock invierten esto. Si los fondos del usuario ya estan bajo un lock en el que el solver confia, no hay razon para abrir nada en la cadena de origen antes de llenar. El draft viejo no tenia lugar para disenos fill-first.

Se desperdiciaba gas. Structs grandes en calldata, mas emitir la orden resuelta completa en el evento Open, imponian overhead. El ERC senala que esto hacia que una interfaz conforme al estandar fuera "less attractive than a protocol-specific interface" — el modo de falla que mata un estandar en silencio.

Leidas juntas, son los sintomas de estandarizar la capa equivocada. El draft viejo intentaba estandarizar el ciclo de vida de la orden: encoding, publicacion, escrow, fill. El draft nuevo estandariza solo la frontera donde un solver lee una orden.

El modelo de resolver

La nueva especificacion es una sola interfaz:

interface IResolver {
    struct ResolvedOrder {
        // Array of `IStep` ABI calldata.
        bytes[] steps;
        // Array of `IVariableRole` ABI calldata.
        bytes[] variables;
        // Array of `IPayment` ABI calldata.
        bytes[] payments;
        Assumption[] assumptions;
    }

    struct Assumption {
        string name;
        bytes data;
    }

    function resolve(bytes calldata payload)
        external view
        returns (ResolvedOrder memory);
}

Un protocolo publica ordenes como payloads opacos y despliega un resolver que las decodifica. El solver llama a resolve y recibe una descripcion de que hacer, cuanto le puede costar, y cuanto le van a pagar.

Dos decisiones de diseno cargan el peso.

Primero, la resolucion ocurre offchain via eth_call, aunque el resolver este desplegado onchain. El ERC es explicito en que, como la resolucion nunca necesita incluirse en una transaccion, "the payload and translation process are not constrained by onchain gas costs". Un resolver puede hacer decoding y validacion caros que serian impensables en calldata. Esto responde directamente a la cuarta falla de arriba.

Segundo, el resolver se despliega onchain de todos modos, porque es el punto de confianza. El modelo declarado es que los operadores de solvers ponen direcciones de resolver en whitelist, y una vez auditadas, las instrucciones que producen se consideran confiables. La verificacion se hace "through the usual means, such as security audits, bounties, and lindiness". Esto es una allowlist con gobernanza humana, y conviene nombrarlo asi — la misma forma que la confianza en facilitators dentro del modelo verify/settle de x402.

La garantia que da un resolver es fuerte. Un resolver MUST garantizar que una orden solo pueda abortar como esta explicitamente especificado en las revert policies. Si ninguna abort policy se dispara, un solver que empieza a ejecutar los steps de una orden MUST poder cumplir todos los requisitos y recibir todos los pagos. El resolver no esta describiendo una oportunidad. La esta respaldando.

Steps, variables, attributes, payments

La orden resuelta es un pequeno lenguaje de instrucciones. Tiene cuatro partes, y su vocabulario es lo mas interesante del documento.

Un step es un Call: un target como interoperable address, un selector de 4 bytes, una lista de arguments donde cada uno es una constante o una referencia a variable, y una lista de attributes. El solver evalua los argumentos, codifica el calldata, y manda una transaccion. Los steps forman un grafo de dependencias que debe ser aciclico, y la ejecucion debe proceder en orden de hard-dependency.

Los attributes restringen un step. SpendsERC20 declara que la llamada puede tomar hasta cierta cantidad de un token desde el caller via transferFrom, para que el solver sepa exactamente que balance y allowance preparar. SpendsGas declara un techo de gas. TimingBounds fija block.number o block.timestamp entre una cota inferior y una superior, ambas opcionales. NeedsStep y NeedsVariable declaran dependencias que el resolver no podria implicar de otra forma.

RevertPolicy es el que hay que leer dos veces. Toma un policy que es "ignore" o "abort" y un prefijo de bytes expectedReason. Si la llamada revierte con datos que empiezan con ese prefijo, ignore significa que el step cuenta como ejecutado y el solver puede saltearlo con seguridad, mientras que abort significa que la orden entera se cancela. Y despues viene la regla que hace real a la garantia: una llamada MUST NOT revertir sin un attribute RevertPolicy que la contemple. Cualquier revert no anunciado es una violacion de la spec por parte del resolver, no mala suerte del solver.

Las variables son valores que decide el solver, cada una con un rol declarado. PaymentRecipient y PaymentChain dejan que el solver elija donde le pagan — nota que el destino del pago es eleccion del solver, expresado como un hueco en la orden y no como un campo que llena el usuario. StepCaller fija la cuenta usada para un step dado. ExecutionOutput captura block.number, block.timestamp o receipt.effectiveGasPrice de un step completado, que es como se expresa el pricing dependiente del tiempo. Query y QueryEvents instruyen al solver a correr eth_call o eth_getLogs y ligar el resultado. Witness es la valvula de escape general: un procedimiento offchain identificado que produce un valor a partir de data y de otras variables.

Los payments cierran el circuito. El unico tipo de pago hoy es ERC20:

function ERC20(
    bytes calldata token,      // interoperable address
    bytes calldata sender,
    bytes calldata amountFormula,
    uint256 recipientVarIdx,  // indice de una variable PaymentRecipient
    uint256 onStepIdx,
    uint256 estimatedDelaySeconds
) external;

Cuando se ejecuta el step en onStepIdx, debe pagarse al menos amountFormula de token a la direccion que tiene la variable en recipientVarIdx, en la cadena que indica la interoperable address del token. El pago SHOULD demorarse estimatedDelaySeconds con alta confianza.

Ese ultimo campo es el arreglo silencioso de la falla de rentabilidad. El draft viejo le daba al solver una cota floja sobre el monto y nada sobre el tiempo. El nuevo le da una formula de monto que puede depender de outputs de ejecucion, mas una demora de settlement esperada y explicita. Un solver ahora puede poner precio al bloqueo de capital, no solo al spread.

Los montos se expresan con IFormula, que hoy ofrece Constant(uint256) y Variable(uint256 varIdx). La spec agrega una nota de disciplina: si una formula depende del tiempo, el monto SHOULD decrecer con el tiempo, para que el solver pueda calcular una cota superior ajustada. Las subastas holandesas son la forma prevista.

Assumptions con nombre

La parte mas honesta del rediseno es el mecanismo de assumptions. Un resolver garantiza seguridad excepto por condiciones que no puede verificar por si mismo, que debe exponer explicitamente como un Assumption con nombre y datos opcionales. Un solver MUST validar la assumption — por ejemplo contra una whitelist — antes de llenar la orden.

La seccion de Security Considerations extiende esto. Los resolvers deberian documentar las assumptions implicitas mas alla de las que el ERC ya permite, para que solvers y auditores puedan evaluarlas junto con las explicitas. Solo la liveness y la resistencia a censura de las cadenas, mas la liveness de los tokens nombrados en attributes SpendsERC20, pueden asumirse en silencio.

A las auditorias se les dice que buscar: si un solver que sigue correctamente las instrucciones del resolver puede terminar en una posicion insegura, si los steps pueden gastar activos del solver o crearle obligaciones que no fueron declaradas, y si los caminos de pago pueden invalidarse despues de que el solver ya incurrio en costo. Ese ultimo es el riesgo real de cualquier sistema fill-first, y esta dicho sin rodeos.

ERC-7930 por debajo

Toda direccion en el nuevo ERC-7683 es bytes, no address. Eso se debe a la linea requires: 7930.

ERC-7930 — "Interoperable Addresses", status Review, creado el 2025-02-02 — define un formato binario para una direccion especifica de una cadena. Tiene una lista larga de autores que incluye a Nick Johnson, Vitalik Buterin y Sam Wilson. El layout son seis campos:

// Version              2 bytes   0x0001 para v1, big-endian
// ChainType            2 bytes   un namespace CASA
// ChainReferenceLength 1 byte    PUEDE ser cero
// ChainReference       variable  segun el perfil CAIP-350
// AddressLength        1 byte    PUEDE ser cero
// Address              variable  segun el perfil CAIP-350

El ejemplo de la propia spec para una direccion en Ethereum mainnet decodifica limpio:

0x 0001 0000 01 01 14 d8da6bf26964af9d7eed9e03e53415d37aa96045
   │    │    │  │  │  └─ direccion de 20 bytes
   │    │    │  │  └──── AddressLength = 0x14 = 20
   │    │    │  └─────── ChainReference = 1
   │    │    └────────── ChainReferenceLength = 1
   │    └─────────────── ChainType
   └──────────────────── Version = 1

Dos propiedades importan. Ambos campos de longitud PUEDEN ser cero, lo que significa que el mismo formato expresa una cadena sin direccion y una direccion sin cadena — un solo encoding para "este contrato en esta cadena", "esta cadena" y "esta cuenta, cadena sin especificar". Y las reglas de serializacion tanto de la chain reference como de la direccion vienen del perfil CAIP-350 del namespace, asi que las cadenas no-EVM son ciudadanas de primera clase. En los ejemplos de la spec, el caso Ethereum usa ChainType 0x0000 con una referencia de un byte, mientras que el caso Solana usa ChainType 0x0002 con una chain reference de 32 bytes y una direccion de 32 bytes.

Por esto el rediseno de ERC-7683 reclama alcance cross-ecosystem. Su Rationale afirma que el estandar busca ser cross-compatible con otros ecosistemas, estandarizando tipos en cadenas EVM pero usando interoperable addresses para que las ordenes puedan referirse a cuentas fuera del espacio de direcciones EVM, e invitando a estandares hermanos para otros ecosistemas cuyos intents puedan llenarse en una cadena EVM y viceversa.

Cualquiera que haya lidiado con la identificacion de cadenas en payloads de pago va a reconocer el problema que se esta resolviendo. Chocamos con la misma ambiguedad al mapear los network bindings de x402 entre cadenas: un string como "base" o "solana" es una convencion de nombres, no un tipo. ERC-7930 es un tipo.

Spec drift en produccion

Un estandar es lo que hacen las implementaciones. Asi que revisamos.

erc7683.org/spec, el sitio que se presenta como la documentacion del estandar, todavia documenta GaslessCrossChainOrder, OnchainCrossChainOrder, ResolvedCrossChainOrder, Output, FillInstruction, IOriginSettler, IDestinationSettler y el evento Open. Ese es el draft anterior, presentado como vigente.

Los contratos del Open Intents Framework son la implementacion de referencia que mas se asocia con el estandar. Leyendo el arbol del repositorio en main, ningun path de archivo contiene "7683". Los contratos de settlement se llaman InputSettlerBase.sol, InputSettlerEscrow.sol, InputSettlerCompact.sol y OutputSettlerBase.sol, con tipos llamados StandardOrderType y MandateOutputType. Ni los nombres viejos del ERC ni los nuevos.

Hay un detalle en esos nombres de archivo que vale la pena mirar. InputSettlerCompact.sol e InputSettlerEscrow.sol conviven — un camino de resource lock y un camino de escrow, en el mismo codebase. Eso es exactamente la divergencia que el Rationale del ERC cita como razon para descartar el draft escrow-first. Las implementaciones ya le habian quedado grandes al estandar antes de que el estandar lo admitiera. Tambien hay un InputSettlerEscrowTron.sol, que dice bastante sobre cuanto de este problema es en realidad direccionamiento entre cadenas heterogeneas.

Asi que el estado de situacion hoy: el ERC canonico especifica una interfaz de resolver que, hasta donde podemos verificar, todavia nadie implementa en produccion; el sitio de documentacion especifica un draft superado; y la implementacion lider usa un tercer vocabulario. Nada de eso significa que el rediseno este mal. Significa que el numero "7683" hoy no aporta informacion sobre lo que un sistema realmente hace, y que cualquier decision de integracion tiene que nombrar un draft.

Que significa para LLM4Agents

LLM4Agents rutea inferencia y liquida por llamada en stablecoins sobre un gateway compatible con OpenAI. ERC-7683 no esta en ese camino hoy. Tres cosas siguen siendo directamente relevantes.

// 1

Una orden resuelta es una oferta legible por maquina

Sacale el marco cross-chain y un ResolvedOrder es esto: aca estan las llamadas que hay que hacer, aca esta lo que te pueden costar, aca esta lo que cobras, aca esta cuando, y aca esta lo que no te puedo prometer. Es el mismo objeto que una respuesta 402 de x402 — una demanda con precio, negociable por maquina, que un comprador autonomo puede evaluar sin un humano.

La diferencia es la direccion y el medio. x402 pone precio a un request HTTP; una orden resuelta pone precio a ejecucion onchain. Un agente que puede evaluar ambas compra capacidad con un solo loop en vez de dos.

// 2

ERC-7930 es la parte para adoptar ya

La interfaz de resolver es un draft que nadie envia. El formato de direcciones es un ERC en status Review del que ya depende un estandar adyacente a pagos, con una lista de autores larga y seria. Cualquier sistema que registre "que cadena, que token, que cuenta" — filas de billing, recibos, destinos de reembolso, payloads de webhook — hoy inventa su propio encoding para esa tupla.

Adoptar ERC-7930 como forma canonica interna para direcciones con alcance de cadena cuesta poco y elimina una clase de ambiguedad con la que ya nos cruzamos en quince chain bindings.

// 3

La confianza en resolvers es, otra vez, confianza en facilitators

El modelo de seguridad se reduce a una whitelist de direcciones de resolver validadas por auditorias y por tiempo. Ya vimos esta forma en los facilitators de x402 y en los servicios de atestacion cross-chain. Es viable, y es una superficie de gobernanza, no criptografica. Todo lo que un agente confia porque un operador lo puso en allowlist deberia tratarse como dependencia operativa con dueno y con camino de revocacion.

La amenaza, tal como es, es modesta y conviene decirla igual. Si el settlement basado en intents se vuelve la forma normal en que el valor se mueve entre cadenas, entonces un gateway que solo entiende transferencias directas en un conjunto fijo de cadenas es un producto mas angosto que uno que puede aceptar pago donde sea que una red de solvers pueda entregarlo. Es una preocupacion de varios trimestres, no de este — pero es el mismo argumento que hizo que valiera la pena estudiar el settlement burn-and-mint de CCTP V2, y este es el mecanismo competidor.

Como mantenerse en la frontera

Pasos concretos, en el orden en que los tomariamos.

Primero, adoptar ERC-7930 internamente. Representar toda direccion con alcance de cadena en registros de billing, recibos de pago y payloads de API en el formato binario v1, con un render legible en la capa de presentacion. Es un cambio de dias, sin dependencia externa, y abarata toda integracion posterior. Ademas vuelve inequivocos los recibos, que es lo que importa para los audit trails discutidos en la auditoria de integridad de recibos.

Segundo, fijar el draft en cada nota de integracion. Donde la plataforma o sus docs digan "ERC-7683", decir cual diseno. Tratar erc7683.org como documentacion del draft anterior hasta que diga otra cosa. No cuesta nada y evita un malentendido caro.

Tercero, no construir trabajo nuevo sobre IOriginSettler o IDestinationSettler. El ERC los nombra solo como historia. Si una integracion existente depende de ellos, esta bien — depende de un protocolo, no del estandar.

Cuarto, prototipar un evaluador de resolvers de solo lectura. Un servicio chico que tome una direccion de resolver y un payload, llame a resolve por eth_call, y renderice steps, attributes, assumptions y calendario de pagos como JSON estructurado. No compromete capital ni asume riesgo, y es exactamente el componente que hace falta despues para decidir si una orden vale la pena. Construirlo ahora contra un draft es como te enteras de si el lenguaje de instrucciones alcanza, antes de que importe.

Quinto, modelar el credito del gateway como un intent. La aplicacion natural no es resolver para terceros; es al reves. Un agente con USDC en una cadena que necesita credito de gateway denominado en otra esta expresando un intent, y una red de solvers es una forma de llenarlo. Especificar esa forma de orden — steps, payment, assumptions — incluso antes de decidir si publicar un resolver. Escribir la orden es el ejercicio de diseno.

Sexto, tratar las allowlists de resolvers como las de facilitators. Misma politica, misma cadencia de revision, mismo mecanismo de revocacion. No dejar que un segundo registro de confianza crezca con reglas distintas al primero.

La leccion mas amplia es sobre leer estandares en vez de leer sobre estandares. ERC-7683 paso dieciseis meses siendo citado en una forma mientras el documento estaba por convertirse en otra. El log de commits fue publico todo el tiempo. Para infraestructura que tiene que liquidar valor real, la fuente primaria es la unica fuente.

Paga por llamada, en stablecoins, sobre una API compatible con OpenAI

LLM4Agents le da a los agentes autonomos un gateway que pueden pagar sin un humano en el medio.

Registrar un agente