OZ Error: ‘Governor: proposer votes below proposal threshold’

   constructor(
        IVotes _token,
        TimelockController _timelock
    )
        Governor("Governor")
        GovernorSettings(0,300,7000e18)
        GovernorVotes(_token)
        GovernorVotesQuorumFraction(4) 
        GovernorTimelockControl(_timelock)
    {
        s_proposalCount = 0;
    }

I'm testing the deployment of a simple voting system. The voting system works, queueing and execution works. The voting power is delegated appropriately during voting.

However, I am having problems with implementing a minimum vote threshold for proposal creation. My token has 18 decimals and a 100m+ supply. I want the minimum vote threshold to be 7000 votes. I have tried passing both 7000e18 and just 7000 but only accounts with very large voting power (e.g. owning the majority of the supply) can create a proposal in both cases. It only works properly when setting the value to 0.

I believe that your problem stems from function proposalThreshold, which is implemented in both contract Governor and contract GovernorSettings, both of which your contract inherits from.

So I'm not quite sure how come you do not get a compilation error on that.

In any case, the one implemented in contract GovernorSettings seems to be the one that you want:

function proposalThreshold() public view virtual override returns (uint256) {
    return _proposalThreshold;
}

While the one implemented in contract Governor seems to be the one that you don't want:

function proposalThreshold() public view virtual override returns (uint256) {
    return 0;
}

And since contract GovernorSettings already inherits from contract Governor, it seems that all you really need is to inherit your contract from GovernorSettings, but NOT from Governor.

   function proposalThreshold()
        public
        view
        override(Governor, GovernorSettings)
        returns (uint256)
    {
        return super.proposalThreshold();
    }

Thank you for the quick response. This was my implementation. I assumed it would have worked because it's overriding both contract functions.

You're just calling the proposalThreshold function of ONE of these two base contracts.
And since you don't know which one you're actually calling, this solution is technically useless.

In fact, since you're only doing return super.proposalThreshold(), it is the same as NOT overriding that function to begin with.

It might work with return GovernorSettings.proposalThreshold(), I'm not sure whether or not this syntax is supported.

But as I wrote in my original answer, since contract GovernorSettings already inherits from contract Governor, you should inherit your contract from GovernorSettings, but NOT from Governor.

1 Like

@barakman's answers are unfortunately not accurate. (I nevertheless really appreciate that you take the time to answer!)

   function proposalThreshold()
        public
        view
        override(Governor, GovernorSettings)
        returns (uint256)
    {
        return super.proposalThreshold();
    }

:point_up: This is correct and it should work fine.

We know that the code above will call the function GovernorSettings.proposalThreshold. The reason is that GovernorSettings extends Governor, and the compiler will refer to the derived contracts before the base contracts when using super.


Setting the proposalThreshold to 7000e18 should work.

Most likely the problem is in your test. Are you delegating first and immediately trying to propose? You should mint votingDelay blocks before proposing.

If this is not the issue, can you share the rest of the contract so we can see if the problem is elsewhere?