账户
0xee...fddf
Indexed COMP Meta Governor

Indexed COMP Meta Governor

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.6.12+commit.27d51765
语言
Solidity
合同源代码
文件 1 的 1:MetaGovernorCOMP.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.6.12;
pragma experimental ABIEncoderV2;


/**
 * @title MetaGovernorCOMP
 * @dev Meta-governance contract for Compound's GovernorAlpha.
 *
 * This contract enables NDX holders to vote, by simple majority, on how to cast
 * votes for Compound governance proposals.
 *
 * Each Compound proposal is wrapped as a meta proposal, which has an endBlock which
 * ends some number of blocks prior to the end of the real proposal in order to give
 * NDX holders time to cast meta votes prior to casting votes for the entire dao.
 *
 * This contract counts voting power from users the same way as the typical GovernorAlpha,
 * which is to call getPriorVotes to check the delegation a voting account held at the time
 * the external proposal began.
 *
 * Once a meta proposal has ended, it may be executed to cast votes on Compound. If the proposal
 * has more votes in favor than against, it will cast votes supporting the proposal. Otherwise,
 * it will cast votes against the proposal.
 *
 * This contract may not be used to submit proposals to Compound, only to vote on them.
 */
contract MetaGovernorCOMP {
  /** @dev The name of this contract */
  string public constant name = "Indexed COMP Meta Governor";

  /**
   * @dev The number of blocks subtracted from the endBlock of an external
   * proposal to set the end block of a meta proposal.
   */
  uint32 public immutable votingGracePeriod;

  /** @dev The address of the Indexed governance token */
  NdxInterface public immutable ndx;


  /** @dev The address of the COMP GovernorAlpha */
  IGovernorAlpha public immutable compGovernor;

  /**
   * @param startBlock The block at which voting begins: holders must delegate their votes prior to this block
   * @param endBlock The block at which voting ends: votes must be cast prior to this block
   * @param forVotes Current number of votes in favor of this proposal
   * @param againstVotes Current number of votes in opposition to this proposal
   * @param voteSubmitted Flag marking whether the vote has been cast on the external governor
   * @param receipts Receipts of ballots for the entire set of voters
   */
  struct MetaProposal {
    uint32 startBlock;
    uint32 endBlock;
    uint96 forVotes;
    uint96 againstVotes;
    bool voteSubmitted;
    mapping(address => Receipt) receipts;
  }

  /**
   * @dev Possible states that a meta proposal may be in
   */
  enum MetaProposalState {
    Active,
    Defeated,
    Succeeded,
    Executed
  }

  mapping(uint256 => MetaProposal) public proposals;

  /**
   * @dev Ballot receipt record for a voter
   * @param hasVoted Whether or not a vote has been cast
   * @param support Whether or not the voter supports the proposal
   * @param votes The number of votes the voter had, which were cast
   */
  struct Receipt {
    bool hasVoted;
    bool support;
    uint96 votes;
  }

  /**
   * @dev An event emitted when a vote has been cast on a proposal
   */
  event MetaVoteCast(
    address voter,
    uint256 proposalId,
    bool support,
    uint256 votes
  );

  event ExternalVoteSubmitted(
    uint256 proposalId,
    bool support
  );

  constructor(address ndx_, address compGovernor_, uint32 votingGracePeriod_) public {
    ndx = NdxInterface(ndx_);
    compGovernor = IGovernorAlpha(compGovernor_);
    votingGracePeriod = votingGracePeriod_;
  }

  function getReceipt(uint256 proposalId, address voter)
    external
    view
    returns (Receipt memory)
  {
    return proposals[proposalId].receipts[voter];
  }

  function submitExternalVote(uint256 proposalId) external {
    MetaProposal storage proposal = proposals[proposalId];
    MetaProposalState state = _state(proposal);
    require(
      state == MetaProposalState.Succeeded || state == MetaProposalState.Defeated,
      "MetaGovernorCOMP::submitExternalVote: proposal must be in Succeeded or Defeated state to execute"
    );
    proposal.voteSubmitted = true;
    bool support = state == MetaProposalState.Succeeded;
    compGovernor.castVote(proposalId, support);
    emit ExternalVoteSubmitted(proposalId, support);
  }

  function _getMetaProposal(uint256 proposalId) internal returns (MetaProposal storage) {
    // Get the meta proposal if it exists, else initialize the block fields using the external proposal.
    MetaProposal storage proposal = proposals[proposalId];
    if (proposal.startBlock == 0) {
      IGovernorAlpha.Proposal memory externalProposal = compGovernor.proposals(proposalId);
      proposal.startBlock = safe32(externalProposal.startBlock);
      proposal.endBlock = sub32(safe32(externalProposal.endBlock), votingGracePeriod);
    }
    return proposal;
  }

  function castVote(uint256 proposalId, bool support) external {
    MetaProposal storage proposal = _getMetaProposal(proposalId);
    require(
      _state(proposal) == MetaProposalState.Active,
      "MetaGovernorCOMP::_castVote: meta proposal not active"
    );
    Receipt storage receipt = proposal.receipts[msg.sender];
    require(
      receipt.hasVoted == false,
      "MetaGovernorCOMP::_castVote: voter already voted"
    );
    uint96 votes = ndx.getPriorVotes(msg.sender, proposal.startBlock);
    require(
      votes > 0,
      "MetaGovernorCOMP::_castVote: caller has no delegated NDX"
    );

    if (support) {
      proposal.forVotes = add96(proposal.forVotes, votes);
    } else {
      proposal.againstVotes = add96(proposal.againstVotes, votes);
    }

    receipt.hasVoted = true;
    receipt.support = support;
    receipt.votes = votes;

    emit MetaVoteCast(msg.sender, proposalId, support, votes);
  }

  function state(uint256 proposalId) external view returns (MetaProposalState) {
    MetaProposal storage proposal = proposals[proposalId];
    return _state(proposal);
  }

  function _state(MetaProposal storage proposal) internal view returns (MetaProposalState) {
    require(
      proposal.startBlock != 0 && block.number > proposal.startBlock,
      "MetaGovernorCOMP::_state: meta proposal does not exist or is not ready"
    );
    if (block.number <= proposal.endBlock) {
      return MetaProposalState.Active;
    } else if (proposal.voteSubmitted) {
      return MetaProposalState.Executed;
    } else if (proposal.forVotes > proposal.againstVotes) {
      return MetaProposalState.Succeeded;
    }
    return MetaProposalState.Defeated;
  }

  function add96(uint96 a, uint96 b) internal pure returns (uint96) {
    uint96 c = a + b;
    require(c >= a, "addition overflow");
    return c;
  }

  function safe32(uint256 a) internal pure returns (uint32) {
    require(a <= uint32(-1), "uint32 overflow");
    return uint32(a);
  }

  function sub32(uint32 a, uint32 b) internal pure returns (uint32) {
    require(b <= a, "subtraction underflow");
    return a - b;
  }
}


interface IGovernorAlpha {
  struct Proposal {
    uint256 id;
    address proposer;
    uint256 eta;
    uint256 startBlock;
    uint256 endBlock;
    uint256 forVotes;
    uint256 againstVotes;
    bool canceled;
    bool executed;
  }

  function proposals(uint256 proposalId) external view returns (Proposal memory);

  function castVote(uint256 proposalId, bool support) external;
}


interface NdxInterface {
  function getPriorVotes(address account, uint256 blockNumber)
    external
    view
    returns (uint96);
}
设置
{
  "compilationTarget": {
    "temp-contracts/meta/MetaGovernorCOMP.sol": "MetaGovernorCOMP"
  },
  "evmVersion": "istanbul",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"address","name":"ndx_","type":"address"},{"internalType":"address","name":"compGovernor_","type":"address"},{"internalType":"uint32","name":"votingGracePeriod_","type":"uint32"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"support","type":"bool"}],"name":"ExternalVoteSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"support","type":"bool"},{"indexed":false,"internalType":"uint256","name":"votes","type":"uint256"}],"name":"MetaVoteCast","type":"event"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"bool","name":"support","type":"bool"}],"name":"castVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"compGovernor","outputs":[{"internalType":"contract IGovernorAlpha","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"address","name":"voter","type":"address"}],"name":"getReceipt","outputs":[{"components":[{"internalType":"bool","name":"hasVoted","type":"bool"},{"internalType":"bool","name":"support","type":"bool"},{"internalType":"uint96","name":"votes","type":"uint96"}],"internalType":"struct MetaGovernorCOMP.Receipt","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ndx","outputs":[{"internalType":"contract NdxInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposals","outputs":[{"internalType":"uint32","name":"startBlock","type":"uint32"},{"internalType":"uint32","name":"endBlock","type":"uint32"},{"internalType":"uint96","name":"forVotes","type":"uint96"},{"internalType":"uint96","name":"againstVotes","type":"uint96"},{"internalType":"bool","name":"voteSubmitted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"state","outputs":[{"internalType":"enum MetaGovernorCOMP.MetaProposalState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"submitExternalVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"votingGracePeriod","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"}]