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);
}
}
Submitted on: 2025-10-07 09:28:05
Comments
Log in to comment.
No comments yet.