How does a contract interact with the GSN?

I have been checking out the Sending Gasless Transactions tutorial.

As discussed in the tutorial, we have a Counter contract that implements the GSNRecipient.

I’m trying to see how the react-app that we made in the tutorial, is interacting with the Relayer that we deployed locally.

The App.js file contains an increase() function:

  const increase = async () => {
    console.log("test");
    await counterInstance.methods.increase().send({ from: accounts[0] });
    getCount();
  };

which sends a transaction to the deployed Counter contract.

Here is the Counter contract.

// contracts/Counter.sol
pragma solidity ^0.5.0;

import "@openzeppelin/contracts-ethereum-package/contracts/GSN/GSNRecipient.sol";

contract Counter is GSNRecipient {
    uint256 public value;

    function increase() public {
        value += 1;
    }

    function acceptRelayedCall(
        address relay,
        address from,
        bytes calldata encodedFunction,
        uint256 transactionFee,
        uint256 gasPrice,
        uint256 gasLimit,
        uint256 nonce,
        bytes calldata approvalData,
        uint256 maxPossibleCharge
    ) external view returns (uint256, bytes memory) {
        return _approveRelayedCall();
    }

    // We won't do any pre or post processing, so leave _preRelayedCall and _postRelayedCall empty
    function _preRelayedCall(bytes memory context) internal returns (bytes32) {}

    function _postRelayedCall(
        bytes memory context,
        bool,
        uint256 actualCharge,
        bytes32
    ) internal {}
}

Question: I can’t figure out, how calling the increase() function triggers the Relayer? I mean I can’t find anything interacting with the HTTP interface of the Relayer.

1 Like

Hi @vasa-develop,

In our App.js we use OpenZeppelin Network.js and specify that we want to use the GSN.

  const context = useWeb3Network(PROVIDER_URL, {
    gsn: { dev: true }
  });

OpenZeppelin Network.js uses OpenZeppelin GSN Provider where transactions sent to contracts will then be automatically routed through the GSN.

1 Like

Hey @abcoathup!

Just wanted to check if I understood the flow correctly:

  • There is a RelayHub Contract.
  • There are a number of Relays(or Relayers) with owners, all registered on the RelayHub Contract.
  • We have a GSN compatible Recipient Contract that has a function named increase() that we want to execute. This Recipient Contract is funded and is charged by the Relay for fueling the transactions.
  • We have a react app(to interact with the dapp) that uses OpenZeppelin Network.js which uses OpenZeppelin GSN Provider .
  • The OpenZeppelin GSN Provider selects the best Relay from the available relays.
  • It contacts the winner relayer via the relay’s HTTP interface to send the required data.
  • The relayer gets the required data via the HTTP interface and signs the transaction.
  • The Relay submits the transaction to the RelayHub contract.
  • The RelayHub publishes the transaction to the Network.
  • The Recipient Contract is charged a fee according to the Relayer’s fee structure.

Is this right?

P.S. I have omitted the details like stakes etc. and assumed that all the conditions of the Relay to filter an eligible transaction are met, and nothing messes up.

1 Like

Hi @vasa-develop

That flow is correct. Though it is the Relayer (not the RelayHub) that publishes the transaction to the Network.

In addition, a recipient contract will generally use a GSN Strategy to decide whether or not to accept a requested relayed call.

We can see the available relays using the following website with injected web3 (e.g. MetaMask) and setting the desired network in injected web3. https://gsn.openzeppelin.com/relay-hubs/0xd216153c06e857cd7f72665e0af1d7d82172f494?listRelays=true

Feel free to ask all the questions that you need.

1 Like