Inmutable Variable Error in ERC2771Context

Hello Community. I’m trying to introduce meta-transactions to a ERC20 Token. However when Im trying to compile the contract I getting the next error:

TypeError: Immutable variables cannot be read during contract creation time, which means they cannot be read in the constructor or any function or modifier called from it.
  --> @openzeppelin/contracts/metatx/ERC2771Context.sol:18:29:
   |
18 |         return forwarder == _trustedForwarder;
   | 

Here is the code of the ERC20 contract.

:1234: Code to reproduce

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {
    ERC2771Context
} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";

contract Love is ERC20, ERC20Burnable, Pausable, AccessControl, ERC2771Context {
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

    constructor(address trustedForwarder) 
        ERC20("Test", "TST")
        ERC2771Context(trustedForwarder)
        {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
        _setupRole(PAUSER_ROLE, _msgSender());
        _mint(_msgSender(), 5000 * 10 ** decimals());
        _setupRole(MINTER_ROLE, _msgSender());
    }

        function _msgSender()
        internal
        view
        override(Context, ERC2771Context)
        returns (address sender)
    {
        sender = ERC2771Context._msgSender();
    }

    /// @inheritdoc	ERC2771Context
    function _msgData()
        internal
        view
        override(Context, ERC2771Context)
        returns (bytes calldata)
    {
        return ERC2771Context._msgData();
    }

    function pause() public {
        require(hasRole(PAUSER_ROLE, _msgSender()));
        _pause();
    }
  
    function unpause() public {
        require(hasRole(PAUSER_ROLE, _msgSender()));
        _unpause();
    }

    function mint(address to, uint256 amount) public {
        require(hasRole(MINTER_ROLE, _msgSender()));
        _mint(to, amount);
    }

    function _beforeTokenTransfer(address from, address to, uint256 amount)
        internal
        whenNotPaused
        override
    {
        super._beforeTokenTransfer(from, to, amount);
    }
}

:computer: Environment

I am using Truffle with @openzeppelin/contracts@4.1.0 version.

You’re getting this error because you’re using _msgSender() in the constructor.

I think you can safely use msg.sender (in the constructor only) and it will fix the error.

Thanks for answering! I tried changing _msgSender() to msg.sender only in the constructor. However, I got the same error :c

Hm, that’s true. It seems we access _msgSender in _setupRole. You will need to work around this by adding an external function that can set up the initial roles. You need to be careful and make sure this function can be called only once.

This is the Solidity issue about the limitation that makes this fail to compile.

I tried to remove everything from the constructor (_mint and rolesSetup). Unfortunately I still have the same result, I have compiled the ERC2771 mock without problems, but when I add the ERC20 constructor it is when the error appears.