How to Simplify Transactions with ERC 2771

Posted By : Yogesh

May 01, 2024

Ever wished your users could interact with your Ethereum smart contract without worrying about gas fees? ERC-2771, a meta-transactions standard, offers a solution! This blog dives into ERC-2771, guiding developers through its implementation with an easy-to-understand code example. For more about Ethereum, visit our Ethereum blockchain development services

 

Implementing ERC-2771

 

Prerequisites

 

Before we delve into the code, ensure you have a basic understanding of:

 

  • Solidity: The programming language for Ethereum smart contracts.
  • Meta Transactions: Transactions where a third-party covers the gas fees on behalf of the user.

 

Implementation

 

Here's how to integrate ERC-2771 into your smart contract:

 

Embrace the Inheritance:

 

  • Utilize libraries like OpenZeppelin's ERC2771Context for a smoother experience.
  • In your contract, inherit from ERC2771Context.

 

Trusted Delivery Partner:

 

  • Deploy a separate "trusted forwarder" contract. This acts as the relayer, receiving signed messages from users and forwarding them to your main contract.
  • OpenZeppelin provides a "MinimalForwarder" contract for this purpose.

 

Constructor Configuration:

 

  • During your main contract's deployment, provide the address of the trusted forwarder contract. This establishes trust.
  •  

Overriding the Messenger:

 

  • Override the _msgSender()
  •  function within your contract.
  • This function retrieves the original user address from the meta transaction data using the parent contract's implementation in ERC2771Context.

 

Also, Explore |  Understanding ERC-404 | The Unofficial Token Standard

 

1. MyContract.sol (ERC-2771 enabled contract)

 

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/metatx/ERC2771Context.sol";

contract MyContract is ERC2771Context {
  address private __trustedForwarder;

  constructor(address _trustedForwarder) ERC2771Context(_trustedForwarder) {
    __trustedForwarder = _trustedForwarder;
  }

  function someFunction(uint256 data) public {
    // Access the real user address using _msgSender()
    address user = _msgSender();
    // Your function logic using user address and data
    msg.sender; // This will return the address of the trusted forwarder contract (for informational purposes)
    // Use user for further processing
  }

  function _msgSender() internal view override(ERC2771Context) returns (address sender) {
    return super._msgSender();
  }

}

 

Explanation:

 

  • We import ERC2771Context from OpenZeppelin.
  • The contract inherits from ERC2771Context.
  • The constructor takes the trusted forwarder address and sets it during deployment.
  • The someFunction demonstrates how to access the user's address retrieved by the overridden _msgSender() function.
  • We've also included the isTrustedForwarder function, which is required by ERC-2771 to identify the trusted forwarder contract
     

Also, Explore | ERC-721 Non-Fungible Token Standard Development
 

2. MinimalForwarder.sol (Trusted Forwarder Contract):

 

pragma solidity ^0.8.0;

contract MinimalForwarder {
    bytes32 private constant DOMAIN_SEPARATOR = keccak256(
        abi.encodePacked(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        )
    );

    mapping(address => uint256) private nonces;

    function getMessageHash(
        address from,
        address to,
        uint256 value,
        uint256 gas,
        uint256 nonce,
        bytes memory data
    ) public pure returns (bytes32) {
        bytes32 message = keccak256(
            abi.encodePacked(from, to, value, gas, nonce, data)
        );
        return keccak256(abi.encodePacked(message));

    }

    function verify(bytes memory sig, bytes32 messageHash, address from)
        public
        view
        returns (bool)
    {
        return recoverSigner(messageHash, sig) == from;
    }

    function recoverSigner(bytes32 messageHash, bytes memory sig)
    public
    pure
    returns (address)
{
    uint8 v = uint8(sig[64]);
    if (v < 27) {
        v += 27;
    }
    bytes32 r;
    bytes32 s;
    assembly {
        r := mload(add(sig, 32))
        s := mload(add(sig, 64))
    }
    return ecrecover(messageHash, v, r, s);
}


    function execute(
        address from,
        address to,
        uint256 value,
        uint256 gas,
        uint256 nonce,
        bytes memory data,
        bytes memory sig
    ) public {
        require(verify(sig, getMessageHash(from, to, value, gas, nonce, data), from), "Invalid signature");
        require(nonces[from] == nonce, "Invalid nonce");
        nonces[from] = nonce + 1;
        (bool success, bytes memory result) = to.call{value: value, gas: gas}(data);
        if (!success) {
            assembly {
                revert(result, mload(result))
            }
        }
    }
}

 

Explanation:

 

  • This contract is a simplified version of OpenZeppelin's MinimalForwarder.

 

You may also like | A Comprehensive Guide to ERC-6551 Token Standard

 

Conclusion


In conclusion, ERC-2771 offers a significant advancement in simplifying transactions within the Ethereum ecosystem. By providing a seamless method for smart contracts to cover gas costs, it reduces friction for users, fosters better adoption, and opens doors to new possibilities in decentralized applications. With its potential to enhance user experience and streamline interactions, ERC-2771 stands as a promising solution for the Ethereum community's ongoing development and growth.

 

If you are interested in developing your token on a popular ERC standard and wondering how to get started? Connect with Ethereum Developers for 

for more information.

 

References:

 

Leave a

Comment

Name is required

Invalid Name

Comment is required

Recaptcha is required.

blog-detail

October 15, 2024 at 06:10 pm

Your comment is awaiting moderation.

By using this site, you allow our use of cookies. For more information on the cookies we use and how to delete or block them, please read our cookie notice.

Chat with Us
Telegram Button
Youtube Button
Contact Us

Oodles | Blockchain Development Company

Name is required

Please enter a valid Name

Please enter a valid Phone Number

Please remove URL from text