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

Hi,

I’m trying to follow the example about GNS, here https://docs.openzeppelin.com/learn/sending-gasless-transactions

But when I try to compile the contracts, I have the error

contracts/Counter.sol:5:21: DeclarationError: Identifier not found or not unique.
contract Counter is GSNRecipient {

I saw similar issues but did not resolve mine with this solutions. I installed the latest truffle and I’m on ubuntu.

Any Idea?

:computer: Environment
Ubuntu 18.04
@openzeppelin/network”: “^0.4.2”
@openzeppelin/cli”: “^2.8.2”,
@openzeppelin/contracts-ethereum-package”: “^3.0.0”,
@openzeppelin/gsn-helpers”: “^0.2.3”,
@openzeppelin/upgrades”: “^2.8.0”,
“ganache-cli”: “^6.9.1”
Truffle v5.1.34 (core: 5.1.34)

:memo:Details
Source “@openzeppelin/contracts-ethereum-package/contracts/GSN/GSNRecipient.sol” not found: File import callback not supported

:1234: Code to reproduce

    pragma solidity >=0.6.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 {
        }
    }
1 Like

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();
    }
}

Thanks @abcoathup! I changed the contracts version and the code that you provided and it is working now

1 Like

Hi @abcoathup,

I’m just trying to understand this better. Is the use of acceptRelayedCall , preRelayedCall and postRelayedCall required here, is this just making this contract the paymaster too? (https://docs.opengsn.org/contracts/index.html#paymaster)

(eg. in this example is the Paymaster and the RelayRecipient the same contract?)

Thakns :slight_smile:

1 Like

Hi @JasoonS,

The above is for GSNv1.

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