NounsFailQuorumResolver873

Description:

Governance contract for decentralized decision-making.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

/// @notice Minimal interface to your PredictionMarket.
interface IPredictionMarketMinimal {
    function closeMarket(uint256 marketId) external;
    function resolve(uint256 marketId, bool outcome) external;
    function tradingOpen(uint256 marketId) external view returns (bool);
    function getMarket(uint256 marketId)
        external
        view
        returns (
            uint256 yesSupply,
            uint256 noSupply,
            address resolver,
            bool resolved,
            bool outcome,
            uint256 pot,
            uint256 payoutPerShare,
            string memory desc
        );
}

/// @notice Nouns Governor V4 interface.
interface INounsGovernorV4 {
    function state(uint256 proposalId) external view returns (uint8);
    function proposalVotes(uint256 proposalId)
        external
        view
        returns (uint256 forVotes, uint256 againstVotes, uint256 abstainVotes);
    function quorumVotes(uint256 proposalId) external view returns (uint256);
}

/**
 * @title NounsFailQuorumResolver873
 * @notice YES if Nouns DAO proposal 873 fails quorum after voting (incl. objection period) is over.
 * - Hardcoded targets:
 *     PM:       0x0000000000337f99F242D11AF1908469B0424C8D
 *     Governor: 0x6f3E6272A167e8AcCb32072d08E0957F9c79223d
 *     Proposal: 873
 * - Flow: snapshot forVotes/quorum once voting is not Pending/Active/ObjectionPeriod/Updatable,
 *         close market if open, resolve YES if forVotes < quorum, else NO.
 */
contract NounsFailQuorumResolver873 {
    // ---- Hardcoded addresses/ids ----
    address public constant PM_ADDR = 0x0000000000337f99F242D11AF1908469B0424C8D;
    address public constant GOVERNOR_ADDR = 0x6f3E6272A167e8AcCb32072d08E0957F9c79223d;
    uint256 public constant PROPOSAL_ID = 873;

    IPredictionMarketMinimal private constant PM = IPredictionMarketMinimal(PM_ADDR);
    INounsGovernorV4 private constant GOV = INounsGovernorV4(GOVERNOR_ADDR);

    // ---- State ----
    uint256 public marketId; // set once via link()
    bool public observed; // sticky snapshot taken
    uint256 public forVotesAtEnd; // snapshot of forVotes
    uint256 public quorumAtEnd; // snapshot of required quorum

    // ---- Events ----
    event Linked(uint256 indexed marketId);
    event Observed(uint256 forVotes, uint256 quorum);
    event Closed(uint256 indexed marketId, uint256 atTs);
    event Resolved(uint256 indexed marketId, bool failedQuorum);

    // ---- Errors ----
    error AlreadyLinked();
    error NotLinked();
    error WrongResolver();
    error VotingNotOver();

    /// @notice One-time link; verifies this contract is the market's resolver.
    function link(uint256 _marketId) external {
        if (marketId != 0) revert AlreadyLinked();
        (,, address resolver,,,,,) = PM.getMarket(_marketId);
        if (resolver != address(this)) revert WrongResolver();
        marketId = _marketId;
        emit Linked(_marketId);
    }

    /// @notice Resolve after voting truly ends. YES iff forVotes < quorumVotes(proposalId).
    function poke() external {
        uint256 id = marketId;
        if (id == 0) revert NotLinked();

        // Ensure voting is *not* in any pre-final state.
        // Governor Bravo baseline: 0=Pending, 1=Active.
        // Nouns V3/V4 adds 9=ObjectionPeriod and 10=Updatable.
        uint8 s = GOV.state(PROPOSAL_ID);
        if (s == 0 || s == 1 || s == 9 || s == 10) revert VotingNotOver();

        // Take a sticky observation exactly at/after end.
        if (!observed) {
            (uint256 forVotes,,) = GOV.proposalVotes(PROPOSAL_ID);
            uint256 quorumReq = GOV.quorumVotes(PROPOSAL_ID);
            forVotesAtEnd = forVotes;
            quorumAtEnd = quorumReq;
            observed = true;
            emit Observed(forVotes, quorumReq);
        }

        // Close market before resolve if still open (PM enforces close <= now).
        if (PM.tradingOpen(id)) {
            PM.closeMarket(id); // requires market was created with canClose = true
            emit Closed(id, block.timestamp);
        }

        bool failedQuorum = (forVotesAtEnd < quorumAtEnd);
        PM.resolve(id, failedQuorum);
        emit Resolved(id, failedQuorum);
    }

    /// @notice View helper to preview outcome (uses snapshot if already taken).
    function preview()
        external
        view
        returns (uint8 govState, uint256 forVotes, uint256 quorumReq, bool wouldFailQuorum)
    {
        govState = GOV.state(PROPOSAL_ID);
        if (observed) {
            forVotes = forVotesAtEnd;
            quorumReq = quorumAtEnd;
        } else {
            (forVotes,,) = GOV.proposalVotes(PROPOSAL_ID);
            quorumReq = GOV.quorumVotes(PROPOSAL_ID);
        }
        wouldFailQuorum = (forVotes < quorumReq);
    }
}

Tags:
Governance, Voting|addr:0x776c2135545cf891e4051e9633a718a57522266d|verified:true|block:23521187|tx:0x495053749bb34cdb62aea1485c377771cf5b7f0f8fd4f8d86a882e7dbc772dfe|first_check:1759822085

Submitted on: 2025-10-07 09:28:05

Comments

Log in to comment.

No comments yet.