Windows can't compile when using GSNReceipient

I’m trying to make my own ERC20 token with GSN enabled but when I try to compile I get the following error:

DeclarationError: Identifier not found or not unique. contract MyToken is ERC20, GSNRecipient {

here’s my code:

pragma solidity ^0.6.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/GSN/GSNRecipient.sol";


contract MyToken is ERC20, GSNRecipient {
    constructor() public ERC20("My Token", "TKN") {
        uint256 initialSupply = 1000 * (10**18);
        _mint(msg.sender, initialSupply);
    }

    function mint(address account, uint256 amount) public {
        _mint(account, amount);
    }

    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 {}
}

Any help would be apreciated

:computer: Environment
OpenZeppelin 3.0
Truffle v5.1.14-nodeLTS.0 (core: 5.1.13)
Node v10.0.0
I used Windows
I also tried WSL Ubuntu

1 Like

Hi @medma05,

Welcome to the community :wave:

I would recommend using WSL, I use WSL2.

I got the following errors when compiling (ignoring the SPDX warnings)

$ npx oz compile
✖ Compiling contracts with solc 0.6.8 (commit.0bbfe453)
Compilation warnings:
@openzeppelin/contracts/GSN/Context.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

@openzeppelin/contracts/GSN/GSNRecipient.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

@openzeppelin/contracts/GSN/IRelayHub.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

@openzeppelin/contracts/GSN/IRelayRecipient.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

@openzeppelin/contracts/math/SafeMath.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

@openzeppelin/contracts/token/ERC20/ERC20.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

@openzeppelin/contracts/token/ERC20/IERC20.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

@openzeppelin/contracts/utils/Address.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

contracts/MyToken.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

Compilation errors:
contracts/MyToken.sol:7:1: TypeError: Derived contract must override function "_msgData". Two or more base classes define function with same name and parameter types.
contract MyToken is ERC20, GSNRecipient {
^ (Relevant source part starts here and spans across multiple lines).
@openzeppelin/contracts/GSN/Context.sol:22:5: Definition in "Context":
    function _msgData() internal view virtual returns (bytes memory) {
    ^ (Relevant source part starts here and spans across multiple lines).
@openzeppelin/contracts/GSN/GSNRecipient.sol:102:5: Definition in "GSNRecipient":
    function _msgData() internal view virtual override returns (bytes memory) {
    ^ (Relevant source part starts here and spans across multiple lines).

contracts/MyToken.sol:7:1: TypeError: Derived contract must override function "_msgSender". Two or more base classes define function with same name and parameter types.
contract MyToken is ERC20, GSNRecipient {
^ (Relevant source part starts here and spans across multiple lines).
@openzeppelin/contracts/GSN/Context.sol:18:5: Definition in "Context":
    function _msgSender() internal view virtual returns (address payable) {
    ^ (Relevant source part starts here and spans across multiple lines).
@openzeppelin/contracts/GSN/GSNRecipient.sol:88:5: Definition in "GSNRecipient":
    function _msgSender() internal view virtual override returns (address payable) {
    ^ (Relevant source part starts here and spans across multiple lines).

The OpenZeppelin Contracts v3.0 release notes has the following note:

The other exception to this are 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();
} 

Updating the contract to include these overrides and add the override keyword where necessary and I was able to compile:

pragma solidity ^0.6.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/GSN/GSNRecipient.sol";


contract MyToken is ERC20, GSNRecipient {
    constructor() public ERC20("My Token", "TKN") {
        uint256 initialSupply = 1000 * (10**18);
        _mint(msg.sender, initialSupply);
    }

    function mint(address account, uint256 amount) public {
        _mint(account, amount);
    }

    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(Context, GSNRecipient) returns (address payable) {
        return GSNRecipient._msgSender();
    }

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

One other point, depending on your development roadmap, GSNv2 is under development at https://www.opengsn.org/. You may want to look at the upcoming improvements. You can still use GSNv1, though you may want to run your own relayer. See Doubling down on security for more details.

thank you so much for the support

1 Like

A post was split to a new topic: How can I test ERC20 token?