Unable to get relay hub address of recipient using OpenZeppelin GSN tutorial

:computer: Environment

Truffle v5.1.41 (core: 5.1.41)
Node v14.9.0
Web3.js v1.2.1

:memo:Details
I’m learning about GNS using Openzeppelin gns tutorial and i keepgetting this error.


:1234: Code to reproduce

// "SPDX-License-Identifier: UNLICENSED"
pragma solidity >0.6.0 <=0.8.0;

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

contract Counter is GSNRecipientUpgradeSafe {
    using SafeMath for uint;
    uint public value;

    function increment() public {
        value = value.add(1);
    }

    function decrement() public {
        value = value.sub(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 override 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 override returns (bytes32) {
    }

    function _postRelayedCall(bytes memory context, bool, uint256 actualCharge, bytes32) internal override {
    }
}
import React, { useState, useEffect, useCallback } from "react";
import { useWeb3Network } from "@openzeppelin/network/react";
// load Counter json artifact
import counterJSON from './build/contracts/Counter.json';

const PROVIDER_URL = "http://localhost:8545";

function App() {
  // get GSN web3
  const context = useWeb3Network(PROVIDER_URL, {
    gsn: { dev: true }
  });

  const { accounts, lib } = context;

  // load Counter Instance
  const [counterInstance, setCounterInstance] = useState(undefined);

  if (
    !counterInstance &&
    context &&
    context.networkId
  ) {
    const deployedNetwork = counterJSON.networks[context.networkId.toString()];
    const instance = new context.lib.eth.Contract(counterJSON.abi, deployedNetwork.address);
    setCounterInstance(instance);
  }

  const [count, setCount] = useState(0);

  const getCount = useCallback(async () => {
    if (counterInstance) {
      // Get the value from the contract to prove it worked.
      const response = await counterInstance.methods.value().call();
      // Update state with the result.
      setCount(response);
    }
  }, [counterInstance]);

  useEffect(() => {
    getCount();
  }, [counterInstance, getCount]);

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

  return (
    <div>
      <h3> Counter counterInstance </h3>
      {lib && !counterInstance && (
        <React.Fragment>
          <div>Contract Instance or network not loaded.</div>
        </React.Fragment>
      )}
      {lib && counterInstance && (
        <React.Fragment>
          <div>
            <div>Counter Value:</div>
            <div>{count}</div>
          </div>
          <div>Counter Actions</div>
            <button onClick={() => increase()} size="small">
              Increase Counter by 1
            </button>
        </React.Fragment>
      )}
    </div>
  );
}
export default App;
1 Like

Hi @DragonLord,

All development on the GSN has been moved to the OpenGSN organization. They are developing GSNv2.

If you have questions on GSNv2 you can asking in the GSN support telegram: https://t.me/joinchat/F_BETUjG0Crb2s6mFx1LWA


:warning: You can still use this GSNv1 tutorial but for many of the dependencies we are no longer developing new features nor addressing issues. Read here for more info.


The issue was that with upgradeable contracts we need to initialize to set the relay hub address.

We also have to do the following (though using the UpgradeSafe versions):

From: https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v3.0.0

if you’re inheriting from GSNRecipient or one of the other GSN contracts, you’ll need to add the following snippet to your contracts:

function _msgSender() internal view override(Context, GSNRecipient) returns (address payable) {
   return GSNRecipient._msgSender();
}

function _msgData() internal view override(Context, GSNRecipient) returns (bytes memory) {
   return GSNRecipient._msgData();
}

Your Counter contract should then be as follows:

Counter.sol

// "SPDX-License-Identifier: UNLICENSED"
pragma solidity >0.6.0 <=0.8.0;

import "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/GSN/GSNRecipient.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/GSN/Context.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/Initializable.sol";

contract Counter is Initializable, ContextUpgradeSafe, GSNRecipientUpgradeSafe {
    using SafeMath for uint;
    uint public value;

    function initialize() public {
        __GSNRecipient_init();
    }

    function increment() public {
        value = value.add(1);
    }

    function decrement() public {
        value = value.sub(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 override 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 override returns (bytes32) {
    }

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

    function _msgSender() internal view override(ContextUpgradeSafe, GSNRecipientUpgradeSafe) returns (address payable) {
        return GSNRecipientUpgradeSafe._msgSender();
    }

    function _msgData() internal view override(ContextUpgradeSafe, GSNRecipientUpgradeSafe) returns (bytes memory) {
        return GSNRecipientUpgradeSafe._msgData();
    }
}

Deploy

We can deploy, making sure that we call initialize

$ npx oz deploy
✓ Compiled contracts with solc 0.6.12 (commit.27d51765)
Compilation warnings:
...

? Choose the kind of deployment upgradeable
? Pick a network development
? Pick a contract to deploy Counter
✓ Contract Counter deployed
All implementations have been deployed
? Call a function to initialize the instance after creating it? Yes
? Select which function initialize()
✓ Setting everything up to create contract instances
✓ Instance created at 0xCfEB869F69431e42cdB54A4F4f105C19C080A601
To upgrade this instance run 'oz upgrade'
0xCfEB869F69431e42cdB54A4F4f105C19C080A601

We can then run the dapp and use the Counter.

Hi @DragonLord,

I wanted to check if you were able to use the above?