Titres Titres
Toutes les transactions Ethereum doivent payer des frais de gaz pour être exécutées, de sorte que les nouveaux utilisateurs sont obligés d’acheter Ether avant de pouvoir commencer à utiliser une dapp.
L’achat d’Ethers peut être une tâche ardue pour les utilisateurs novices qui doivent souvent passer par les processus Know Your Customer et Anti-Money-Laundering (KYC & AML) d’un échange.
Pour obtenir moins de friction de l’utilisateur, une approche possible est Meta Transaction.
Il n’y a pas d’astuce, l’idée est simple : un tiers (le Relayeur) envoie les transactions de l’utilisateur et paie le coût du gaz.

Les acteurs de ce dispositif sont :
- Utilisateur: signe une méta-transaction (c’est-à-dire un message contenant des informations sur la transaction qu’il souhaite exécuter).
- Relais: un serveur Web avec un portefeuille qui signe une transaction Ethereum valide (qui a la méta-transaction comme charge utile) et l’envoie à la blockchain.
- Transitaire: un contrat Ethereum chargé de vérifier la signature de la méta transaction qui, sans surprise, transmet la requête à un contrat destinataire.
- Destinataire: le contrat Ethereum que l’utilisateur avait l’intention d’appeler sans payer la redevance gaz, ce contrat doit pouvoir conserver l’identité de l’utilisateur qui a initialement demandé la transaction.
Sur Ethereum, les relais sont organisés en réseau, dans le soi-disant Open Gas Station Network (OGSN). Le mécanisme derrière l’OGSN est le même, mais le réseau de relais assure la décentralisation, la tolérance aux pannes et de nombreux autres avantages.
Mais, pour l’instant, nous voulons seulement répliquer le mécanisme simple des méta transactions sans compliquer la situation en introduisant dans le schéma tous les acteurs nécessaires à un réseau Relayer (Paymasters, Relayer Hub, etc.).
Le contrat de transitaire
Le point de départ pour comprendre le mécanisme de base est donné par l’implémentation MinimalForwarder d’OpenZeppelin, à utiliser avec un contrat compatible ERC2771 comme contrat Destinataire (ce point sera plus clair plus tard).
Inspectons le contrat MinimalForwarder.sol :
contract MinimalForwarder is EIP712
Le contrat suit la proposition d’amélioration EIP-712, une norme de hachage et de signature de données structurées typées, mettant en œuvre un schéma de séparation de domaine pour se protéger contre les attaques par relecture sur une éventuelle branche de la chaîne.
struct ForwardRequest {
address from;
address to;
uint256 value;
uint256 gas;
uint256 nonce;
bytes data;
}
Il a un type de structure définissant les champs Meta Transaction nécessaires.
mapping(address => uint256) private _nonces;
Un mapping entre adresses et nonces, ceci parce que les Meta Transactions ne sont pas enregistrées sur la blockchain, donc le contrat doit vérifier par lui-même le nombre de meta transactions envoyées depuis une adresse donnée, pour éviter les attaques par rejeu.
function verify(ForwardRequest calldata req, bytes calldata signature) public view returns (bool)
Cette fonction vérifie que la Meta Transaction (le ForwarderRequest) a une signature valide par l’Utilisateur et que son nonce est correct.
function execute(ForwardRequest calldata req, bytes calldata signature)
public
payable
returns (bool, bytes memory)
{
Après la méthode de vérification, cette fonction met à jour le nonce de l’utilisateur et transmet la méta-transaction au contrat destinataire.
Le contrat Destinataire
Maintenant, nous avons besoin d’un exemple de contrat de destinataire, heureusement nous en avons un.
Dans l’image suivante, le comportement de ce contrat.

Ce contrat a en mémoire un objet drapeau initialement blanc et sans propriétaire.
Tout utilisateur peut appeler le setFlagOwner méthode du contrat et réclamer la propriété du drapeau et peindre le drapeau avec la couleur qu’il préfère.
Le contrat destinataire doit être en mesure de traiter à la fois des transactions directes et transmises. La différence entre eux est la valeur msg.sender.
Dans les transactions transférées, le msg.sender est l’adresse du contrat de transitaire. Ainsi, dans cette situation, le contrat du destinataire doit récupérer le msg.sender réel à partir de la charge utile de la transaction.
Ceci est visé par la prolongation du contrat « @openzeppelin/contracts/metatx/ERC2771Context.sol ».
contract Recipient is ERC2771Context
De plus, le contrat doit être déployé en indiquant un transitaire de confiance (le seul autorisé à lui transmettre des transactions) :
constructor(address trustedForwarder) ERC2771Context(trustedForwarder) {}
et, dans le code du contrat, msg.sender doit être remplacé par la méthode _msgSender().
function setFlagOwner(string memory _color) external {
address previousHolder = currentHolder;
currentHolder = _msgSender();
color = _color;
emit FlagCaptured(previousHolder, currentHolder, color);
}
Dans le code ci-dessous, comment la méthode _msgSender() est capable de récupérer l’expéditeur du message prévu pour les transactions directes et transférées.
function _msgSender() internal view virtual override returns (address sender) {
if (isTrustedForwarder(msg.sender)) {
assembly {
sender := shr(96, calldataload(sub(calldatasize(), 20)))
}
} else {
return msg.sender;
}
}
Des approches similaires qui devraient être étudiées sont utilisées dans des protocoles d’échange tels que :
Source https://medium.com/coinmonks/gas-free-transactions-meta-transactions-explained-f829509a462d?source=rss—-721b17443fd5—4