question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

GovernorPreventLateQuorum extends the proposalDeadline() as expected, but the proposal is not active past the original voteEnd deadline

See original GitHub issue

Hello, I believe I have found a bug with the GovernorPreventLateQuorum contract. In my Mocha/Chai tests I first created a proposal and saved the default proposalDeadline() block number. Just before the default voting period was over, I cast a vote that exceeded the quorum set, and when I called proposalDeadline() again after this it showed the expected extension of lateQuorumVoteExtension() being added to the default deadline block number. When I mined blocks past the original proposalDeadline() block number and tried to castVote() in the extension period, I kept getting the error: “Governor: vote not currently active”.

💻 Environment Hardhat & Waffle

📝 Details OpenZeppelin npm contracts version 4.4.1 (I copied GovernorPreventLateQuorum to the node_modules directory manually)

🔢 Code to reproduce bug “Governor: vote not currently active”. This error was due to GovernorPreventLateQuorum’s overridden _castVotes() function calling that of Governor.sol via this line: uint256 result = super._castVote(proposalId, account, support, reason); This then triggers the following line in super._castVote(): require(state(proposalId) == ProposalState.Active, "Governor: vote not currently active"); When looking at what causes the failure, state() makes comparisons with the deadline from proposalDeadline(), uint256 deadline = proposalDeadline(proposalId); Where proposalDeadline() gets the deadline value from the ProposalCore struct from the mapping _proposals: return _proposals[proposalId].voteEnd.getDeadline(); This appears to use the default deadline value to end the proposal on, not the updated value set in GovernorPreventLateQuorum as follows: Timers.BlockNumber storage extendedDeadline = _extendedDeadlines[proposalId];

I am still learning your contracts so I may be missing something here, in which case sorry! But if not, I have found a potential fix for this that now works as expected in my own testing. I copied state() from Governor into GovernorPreventLateQuorum, adding the following check to see if an extension has been created. If so, then use that and if not use the default deadline:

    uint256 deadline;
        if (_extendedDeadlines[proposalId].getDeadline() > 0) {
            deadline = _extendedDeadlines[proposalId].getDeadline();
        } else {
            deadline = proposalDeadline(proposalId);
        }

I combined the two _castVote() functions into one function in GovernorPreventLateQuorum:

    function _castVote(
        uint256 proposalId,
        address account,
        uint8 support,
        string memory reason
    ) internal virtual override returns (uint256) {
        ProposalCore storage proposal = _proposals[proposalId];                                                                                                             
        require(state(proposalId) == ProposalState.Active, "Governor: vote not currently active");

        uint256 weight = getVotes(account, proposal.voteStart.getDeadline());
        _countVote(proposalId, account, support, weight);

        emit VoteCast(account, proposalId, support, weight, reason);

        Timers.BlockNumber storage extendedDeadline = _extendedDeadlines[proposalId];

        if (extendedDeadline.isUnset() && _quorumReached(proposalId)) {
            uint64 extendedDeadlineValue = block.number.toUint64() + lateQuorumVoteExtension();

            if (extendedDeadlineValue > proposalDeadline(proposalId)) {
                emit ProposalExtended(proposalId, extendedDeadlineValue);
            }

            extendedDeadline.setDeadline(extendedDeadlineValue);
        }

        return weight;
    }

To access _proposals from Governor I then converted the mapping to public: mapping(uint256 => ProposalCore) public _proposals; Lastly, I overrode state() in my own governor file, as _castVote() was already overridden by GovernorPreventLateQuorum. These changes allow my tests to pass as expected. I would like to create a pull request with these changes , if you would like me to do so?

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
frangiocommented, Feb 11, 2022

OpenZeppelin npm contracts version 4.4.1 (I copied GovernorPreventLateQuorum to the node_modules directory manually)

I’m pretty sure this is the source of the issue. You can’t mix different versions of the contract. Please install the latest version from npm and run your tests again.

1reaction
Amxxcommented, Feb 13, 2022

Just wanted to say that it’s ok, and that you don’t have to apologize.

It’s actually valuable for us to know what the process (good or wrong) or our users are, so we can improve documentation.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Governance - OpenZeppelin Docs
→ uint256 proposalId public. Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the deadline...
Read more >
Part 15 - Contracting by Negotiation | Acquisition.GOV
(e) RFIs may be used when the Government does not presently intend to award a contract, but wants to obtain price, delivery, other...
Read more >
2022 Voter Outreach Partnership - Department of Elections |
REQUEST FOR PROPOSALS. 2022 Voter Outreach Partnership. September 5, 2022 – November 7, 2022. GRANT TERM. DATE OF ISSUANCE: FRIDAY, JULY 22, ...
Read more >
Formal Verification Report for OpenZeppelin Governance ...
The formal specifications are focused on validating the integrity of the governance system — valid states of proposals, correct transitions between proposal ......
Read more >
DHS extends proposal deadline for $10B FirstSource III ...
The solicitation for IT value-added resellers and software producers received far more interest than anticipated and eight preemptive ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found