Saltar al contenido
0%

¿Qué son las meta transacciones (ERC-2771)?

Harpalsinh Jadeja headshot

Escrito por Harpalsinh Jadeja

Publicado el 9 de agosto de 20234 min de lectura

Todas las transacciones de Ethereum usan gas, y el emisor de cada transacción debe tener suficiente Ether para pagar el gas gastado. Esto obliga a los nuevos usuarios a comprar Ether (lo cual puede ser una tarea intimidante) antes de poder empezar a usar una dapp. Esto es un obstáculo importante en la incorporación de usuarios.

Las llamadas "Meta transactions" hicieron posible pagar las tarifas de gas en nombre de los usuarios.

Sin embargo, muchas de estas soluciones están transicionando hacia infraestructura de Account Abstraction (ERC-4337), ya que es una forma más prometedora y sofisticada de abstracción de gas, ¡con muchas más funciones!

¿Qué son las meta transactions?

La idea de las Meta Transactions es simple: un tercero, llamado Relayer, envía la transacción en nombre del usuario y paga las tarifas de gas.

Los usuarios firman mensajes (preferentemente compatibles con EIP-712) que contienen información sobre la transacción a ejecutar.

El mensaje firmado se pasa al Relayer, quien es entonces responsable de validar si el Relayer recibirá pago o no (esto podría ser opcional, más sobre esto después), tener fondos suficientes para pagar las tarifas de gas, firmar una transacción nativa y enviarla para su ejecución.

Entendamos las Meta Transactions tomando como ejemplo el Relayer de OpenZepplin:

Diagrama animado de una meta transacción: el usuario firma un mensaje y un relayer lo envía, pagando el gas
Una guía paso a paso sobre meta transacciones

¿Cómo se ve una solicitud de meta transaction?

Así se ve un mensaje de ejemplo de Meta Transaction...

Ejemplo de mensaje de meta transacción para acuñar un NFT, mostrando la dirección from y el call data
Ejemplo de meta transacción

El mensaje anterior acuña un NFT y debe ser firmado por la dirección from 0x7099797...

Una vez que se firma el mensaje, el cliente (o usuario) puede crear una solicitud de Meta Transaction (que se ve abajo). Esto se envía como una solicitud POST al Autotask, un webhook que, al ser invocado, usa internamente la clave privada del Relayer para firmar transacciones nativas.

Payload de la solicitud POST de meta transacción enviada al webhook del relayer de Autotask
Solicitud POST de meta transacción

¿Qué es el relayer de meta transaction?

Un Relayer es una Ethereum Account que contiene los fondos para patrocinar las tarifas de gas del usuario. La clave privada de la Account se almacena en una bóveda segura en el servidor del proveedor.

El desarrollador puede entonces enviar fondos al Relayer, que cubrirá las tarifas de transacción de su usuario.

Los desarrolladores pueden crear tantos Relayers como quieran, cada uno de los cuales necesita ser financiado por separado con ETH.

OZ Relay permite pausar el Relayer, aceptar solicitudes de direcciones en lista blanca (Whitelisted Addresses) y limitar el precio del gas (Gas Price Capping). Se puede programar más lógica condicional en el Autotask si se desea.

Ten en cuenta que la transacción definida por el usuario ahora vive dentro del campo data de la transacción nativa del Relayer. ¡Una Meta Transaction es esta transacción dentro de otra transacción!

¿Qué es el MinimalForwarder en las meta transactions?

Hasta ahora, no se ha realizado ninguna validación on-chain. Aquí es donde entra el MinimalForwarder.

MinimalForwarder es un smart contract on-chain que valida el mensaje firmado por el usuario para asegurar su validez y protección contra reenvíos (replay-protection).

text
Copied
struct ForwardRequest { address from; address to; uint256 value; uint256 gas; uint256 nonce; bytes data; } function verify(ForwardRequest calldata req, bytes calldata signature) public view returns (bool) { address signer = _hashTypedDataV4( keccak256( abi.encode( _TYPEHASH, req.from, req.to, req.value, req.gas, req.nonce, keccak256(req.data) ) ) ).recover(signature); return _nonces[req.from] == req.nonce && signer == req.from; }

Tras una validación exitosa, MinimalForwarder ejecuta la transacción haciendo la llamada al contrato solicitado con el calldata apropiado

text
Copied
function execute(ForwardRequest calldata req, bytes calldata signature) public payable returns (bool, bytes memory) { require(verify(req, signature), "MinimalForwarder: signature does not match request"); _nonces[req.from] = req.nonce + 1; (bool success, bytes memory returndata) = req.to.call{gas: req.gas, value: req.value}(abi.encodePacked(req.data, req.from)); // Validate that the relayer has sent enough gas for the call. // See if (gasleft() <= req.gas / 63) { // We explicitly trigger invalid opcode to consume all gas and bubble-up the effects, since // neither revert or assert consume all gas since Solidity 0.8.0 // /// @solidity memory-safe-assembly assembly { invalid() } } return (success, returndata); }

Aquí es también donde entran en juego las desventajas de las Meta Transactions, porque el contrato que llama el MinimalForwarder necesita permitir que el MinimalForwarder lo llame en nombre de los usuarios.

¿Qué es ERC-2771?

Finalmente, cuando la llamada llega al contrato objetivo previsto, este necesita poder determinar el usuario original (msg.sender) y el calldata (msg.data), que están anidados dentro de la transacción del Relayer. Para estandarizar este proceso se propuso ERC2771.

OpenZepplin ofrece un contrato de utilidad llamado ERC2771Context para facilitar que el desarrollador del smart contract extraiga el msg.sender y msg.data previstos a partir de los datos enviados por el MinimalForwarder.

text
Copied
contract YourContract is ERC2771Context { constructor(MinimalForwarder forwarder, string memory uri_) ERC2771Context(address(forwarder)) {} // Depending on whether the call is made by the `MinimalForwarder` or not the `msg.sender` and `msg.data` will be inferred accordingly }

Debido a que cada smart contract debe saber cómo leer las Meta Transactions, implementarlas en contratos ya desplegados es difícil y puede llevar a la introducción de bugs.

Aunque existen muchos otros servicios de infraestructura de Meta Transactions, todos requieren que el contrato objetivo herede de un contrato basado en EIP-712 o EIP-2771 para deducir msg.sender y msg.data.

Si bien este estándar es muy bueno, no funciona de forma retroactiva. Por esto se creó ERC-4337, que está reemplazando a la mayoría de las soluciones basadas en ERC-2771 que existen.

Preguntas frecuentes

¿Qué son las meta transactions?

Las meta transactions permiten que un tercero llamado Relayer envíe transacciones en nombre de los usuarios y pague las tarifas de gas, eliminando la barrera de que los usuarios deban tener Ether antes de interactuar con apps.

¿Cómo funcionan las meta transactions?

Los usuarios firman mensajes que contienen información de la transacción, los cuales se pasan a un Relayer que valida la solicitud, paga las tarifas de gas, firma una transacción nativa y la envía para su ejecución en la blockchain.

¿Qué es ERC-2771?

ERC-2771 es un estándar que permite a los smart contracts identificar al usuario original y el calldata al recibir meta transactions a través de un forwarder confiable, asegurando la correcta extracción de msg.sender y msg.data.

¿Qué es el MinimalForwarder en las meta transactions?

El MinimalForwarder es un smart contract on-chain que valida los mensajes firmados por los usuarios para verificar su autenticidad y protección contra reenvíos, antes de ejecutar la transacción llamando al contrato objetivo.

¿Qué es ERC2771Context?

ERC2771Context es un contrato de utilidad de OpenZeppelin que facilita que los desarrolladores de smart contracts extraigan el msg.sender y msg.data previstos a partir de las meta transactions enviadas por el MinimalForwarder.

¿Cuáles son las limitaciones de las meta transactions basadas en ERC-2771?

ERC-2771 requiere que los contratos objetivo admitan explícitamente el estándar heredando contratos basados en EIP-712 o EIP-2771, lo que dificulta su implementación en contratos ya desplegados y puede introducir bugs.

¿Cómo se compara ERC-2771 con ERC-4337?

Mientras que ERC-2771 permite transacciones sin gas mediante relayers y forwarders, ERC-4337 (Account Abstraction) está reemplazando a la mayoría de las soluciones ERC-2771 porque funciona de forma retroactiva y no requiere modificar los contratos existentes.

¿Qué papel cumple el relayer en las meta transactions?

Un Relayer es una cuenta de Ethereum que patrocina las tarifas de gas de los usuarios, con su clave privada almacenada de forma segura en el servidor del proveedor, y puede configurarse con funciones como listas blancas, límites de precio de gas y lógica condicional.

Background gradient

Construye magia blockchain

Alchemy combina los productos y herramientas de desarrollo Web3 más potentes con recursos, comunidad y un soporte legendario.