Modify Respective Function

Make a method which supports native meta transactions

Now using all the information from previous sections, let's make a new method that sets the quote from the user but this time we do it with native meta transaction support.

Create a new function to include the following params

  • userAddress

  • newQuote

  • sigR

  • sigS

  • sigV

function setQuoteMeta(address userAddress,string memory newQuote, bytes32 sigR, bytes32 sigS, uint8 sigV) public {
 }

Add an instance of the struct

  // Make an instance of the predefined struct
  MetaTransaction memory metaTx = MetaTransaction({
    nonce: nonces[userAddress],
    from: userAddress
   });

Hash message in EIP712 compatible form

   // Hash the mandatory fields of EIP712
   bytes32 digest = keccak256(
    abi.encodePacked(
            "\x19\x01",
            DOMAIN_SEPARATOR,
            keccak256(abi.encode(META_TRANSACTION_TYPEHASH, metaTx.nonce, metaTx.from))
        )
    );

"\x19" makes the encoding deterministic

"\x01" is the version byte to make it compatible to EIP-191

Verify the Signatures On Chain

// Verify the userAddress is not address zero 
require(userAddress != address(0), "invalid-address-0");

// Verify the userAddress with the address recovered from the signatures
require(userAddress == ecrecover(digest, v, r, s), "invalid-signatures");

ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address) recover the address associated with the public key from elliptic curve signature

Add the Necessary Logic

quote = newQuote;
owner = userAddress;

Increment Nonce for Replay Protection

nonces[userAddress]++;

Complete Code Snippet

function setQuoteMeta(address userAddress,string memory newQuote, bytes32 r, bytes32 s, uint8 v) public {
    
 MetaTransaction memory metaTx = MetaTransaction({
    nonce: nonces[userAddress],
    from: userAddress
   });
    
 bytes32 digest = keccak256(
    abi.encodePacked(
            "\x19\x01",
            DOMAIN_SEPARATOR,
            keccak256(abi.encode(META_TRANSACTION_TYPEHASH, metaTx.nonce, metaTx.from))
        )
    );

   require(userAddress != address(0), "invalid-address-0");
   require(userAddress == ecrecover(digest, v, r, s), "invalid-signatures");
	
   quote = newQuote;
   owner = userAddress;
   nonces[userAddress]++;
 } 

Checkout the full working code here https://github.com/bcnmy/dapp-demo

Congratulations! You have successfully integrated meta transactions in your Smart Contracts

In the next section, Let's see what changes we need to do on the Client side.

Last updated