2

I have a function in a base contract that could have the state mutability modifier "pure" because it always returns true:

    BaseContract {
        function x(bytes memory) 
            public
            view
            returns(bool) 
        {
            return true
        }
    }

However, this function is usually overridden in derived contracts, like so:

DerivedContract is Base {
    function x (bytes memory payload) 
        public 
        view 
        returns(bool) 
    {
        // do some non-pure stuff
        // return true OR false
    }
}

My question regarding how to silence this compiler warning is rooted in deeper questions:

  1. Does function overriding in Solidity still work, even if the to-be-overidden function has a non-identical state mutability modifier?
  2. Therefore, can I change the state-mutability modifier of the base function to pure, and still have this function overridden, or will the two dissimilar state mutabilities (view vs. pure), all else being identical, result in some sort of function overloading?
  3. If overriding a function with a dissimilar state mutability does not work, how can I silence the aforementioned compiler warning?

Thanks for your help!

2 Answers 2

2

I found that OpenZeppelin seems to silence such compiler warnings about state mutability in this way:

function _msgData() internal view returns (bytes memory) {
    this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
    return msg.data;
}

This snippet is from there Context.sol contract.

1

I believe that all of this can be solved with a single keyword - interface.

For example:

pragma solidity 0.4.26;

interface IBaseContract {
    function func(uint _x) external view returns (bool);
}

contract BaseContract is IBaseContract {
    function func(uint _x) external view returns (bool) {
        return _x == 1;
    }
}

contract DerivedContract is BaseContract {
    uint public x;
    function func(uint _x) external view returns (bool) {
        return _x == x;
    }
}

And the compilation warning is gone!

The only problem that I can think of here, is that you cannot declare public functions in an interface.

So for once, you cannot override your public variable getter functions, since those are... well, public.

But that can be solved by explicitly declaring an external getter function with a slightly different name (e.g., getVal instead of val).

Of course, you don't have to do this for every public variable in your contract, but just for those which are used by other contracts.

Second, if one of your functions must be public (because it is used both internally in the contract and externally by other contracts or from an off-chain script), then - again - you cannot delcare it in the interface.

The solution in this case is simply to split it into an external function and an internal or private function.

Note that with this approach, the only public function remaining in each contract would be the constructor itself, which can be either public or internal.

11
  • Hi, and thank you for helping @goodvibrtaion. I have decided just to ignore the compiler warning. The only other 'clean' way for me to go about this, without introducing more code from manually written getters and internal vs external functions, would be to write an interface, from which to inherit, just for this one function. This seems a little dirty. What do you think? Also, can you explain why the state mutability warning is bypassed, if you inherit the function from an interface, please? Commented Oct 6, 2019 at 8:38
  • also, I cannot upvote your answer, since I am a newbie here and dont have the reputation points to do so. Commented Oct 6, 2019 at 8:46
  • @LuisSchliesske: No worries about the vote. I cannot really explain why the compilation warning is resolved when changing from contract to interface and/or when changing the function from public to external. Perhaps the compiler implementation is such that a contract dictates tight restrictions (e.g., function should be view) and an interface dictates weaker restrictions (e.g., function can be view or "lower"). Perhaps this is even dictated by the Solidity language standard, in which case, you could find it in the official documentation. Commented Oct 6, 2019 at 9:11
  • But regardless of all of this, IMO, interfaces are useful not because they solve (or workaround) this specific compilation warning, but because they allow for a more clean and more transparent system design, which makes it easier for users to read your code and distinguish between API and internal functionality. Also, IMO, public variable getter functions, are more of a curse than a bless (again, because they are less transparent for the user). So the fact that they cannot be declared in your interface is not much of a downside. Commented Oct 6, 2019 at 9:11
  • Explaining the "make it easier to... distinguish between API and internal functionality" part: this is because the only thing that you are allowed to do in an interface is declaring external functions. No public functions (which can be called internally) are allowed, no variable declaration is allowed, and no function implementation is allowed. Just recalled - enum declaration is not yet supported (at least in Solc v0.4.x). That one definitely is a downside. Commented Oct 6, 2019 at 9:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.