Upgradeable GSN enabled Counter.sol has DeclarationError: Identifier not found or not unique

Hi @ialberquilla,

Welcome to the community forum :wave:

There are two versions of the GSN:

GSNv1: Use in production now (though you may want to run your own relayer on mainnet to ensure availability).

We are no longer actively developing new features for this project, and will only be releasing fixes for high severity issues until July 2020.

GSNv2: In development at OpenGSN.org.

See Doubling down on security for more details.

Assuming you are just getting started and depending on your development roadmap, you could look at the upcoming improvements in GSNv2.

I suggest joining the OpenGSN telegram to get the latest news on GSNv2 development and timescales.


The Building a GSN-powered DApp was written with an upgradeable contract using OpenZeppelin Contracts Ethereum Package 2.x.

You can either use OpenZeppelin Contracts Ethereum Package 2.x, or OpenZeppelin Contracts Ethereum Package 3.x (contract below) or change to a regular contract. It is up to you.

To upgrade from 2.5 to 3.x:

https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v3.0.0
contracts that use the Gas Station Network (GSN) : 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();
}

Counter.sol

Upgradeable contract inheriting from OpenZeppelin Contracts Ethereum Package

// contracts/Counter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

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

contract Counter is ContextUpgradeSafe, GSNRecipientUpgradeSafe {
    uint256 public value;

    function initialize() public {
        __GSNRecipient_init();
    }

    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 override 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
        override
        returns (bytes32)
    {}

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

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

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