NounsDAOLogicV1

Deploy on Alchemy

Contract Information

Explore the source code, ABI, and bytecode for the NounsDAOLogicV1 smart contract.
More Info

NounsDAOLogicV1 Source Code

// SPDX-License-Identifier: BSD-3-Clause /// @title The Nouns DAO logic version 1 /********************************* * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ * * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ * * β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ * * β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ * * β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ * * β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ * * β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ * * β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ * * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ * * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ * *********************************/ // LICENSE // NounsDAOLogicV1.sol is a modified version of Compound Lab's GovernorBravoDelegate.sol: // https://github.com/compound-finance/compound-protocol/blob/b9b14038612d846b83f8a009a82c38974ff2dcfe/contracts/Governance/GovernorBravoDelegate.sol // // GovernorBravoDelegate.sol source code Copyright 2020 Compound Labs, Inc. licensed under the BSD-3-Clause license. // With modifications by Nounders DAO. // // Additional conditions of BSD-3-Clause can be found here: https://opensource.org/licenses/BSD-3-Clause // // MODIFICATIONS // NounsDAOLogicV1 adds: // - Proposal Threshold basis points instead of fixed number // due to the Noun token's increasing supply // // - Quorum Votes basis points instead of fixed number // due to the Noun token's increasing supply // // - Per proposal storing of fixed `proposalThreshold` // and `quorumVotes` calculated using the Noun token's total supply // at the block the proposal was created and the basis point parameters // // - `ProposalCreatedWithRequirements` event that emits `ProposalCreated` parameters with // the addition of `proposalThreshold` and `quorumVotes` // // - Votes are counted from the block a proposal is created instead of // the proposal's voting start block to align with the parameters // stored with the proposal // // - Veto ability which allows `veteor` to halt any proposal at any stage unless // the proposal is executed. // The `veto(uint proposalId)` logic is a modified version of `cancel(uint proposalId)` // A `vetoed` flag was added to the `Proposal` struct to support this. // // NounsDAOLogicV1 removes: // - `initialProposalId` and `_initiate()` due to this being the // first instance of the governance contract unlike // GovernorBravo which upgrades GovernorAlpha // // - Value passed along using `timelock.executeTransaction{value: proposal.value}` // in `execute(uint proposalId)`. This contract should not hold funds and does not // implement `receive()` or `fallback()` functions. // pragma solidity ^0.8.6; import './NounsDAOInterfaces.sol'; contract NounsDAOLogicV1 is NounsDAOStorageV1, NounsDAOEvents { /// @notice The name of this contract string public constant name = 'Nouns DAO'; /// @notice The minimum setable proposal threshold uint256 public constant MIN_PROPOSAL_THRESHOLD_BPS = 1; // 1 basis point or 0.01% /// @notice The maximum setable proposal threshold uint256 public constant MAX_PROPOSAL_THRESHOLD_BPS = 1_000; // 1,000 basis points or 10% /// @notice The minimum setable voting period uint256 public constant MIN_VOTING_PERIOD = 5_760; // About 24 hours /// @notice The max setable voting period uint256 public constant MAX_VOTING_PERIOD = 80_640; // About 2 weeks /// @notice The min setable voting delay uint256 public constant MIN_VOTING_DELAY = 1; /// @notice The max setable voting delay uint256 public constant MAX_VOTING_DELAY = 40_320; // About 1 week /// @notice The minimum setable quorum votes basis points uint256 public constant MIN_QUORUM_VOTES_BPS = 200; // 200 basis points or 2% /// @notice The maximum setable quorum votes basis points uint256 public constant MAX_QUORUM_VOTES_BPS = 2_000; // 2,000 basis points or 20% /// @notice The maximum number of actions that can be included in a proposal uint256 public constant proposalMaxOperations = 10; // 10 actions /// @notice The EIP-712 typehash for the contract's domain bytes32 public constant DOMAIN_TYPEHASH = keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)'); /// @notice The EIP-712 typehash for the ballot struct used by the contract bytes32 public constant BALLOT_TYPEHASH = keccak256('Ballot(uint256 proposalId,uint8 support)'); /** * @notice Used to initialize the contract during delegator contructor * @param timelock_ The address of the NounsDAOExecutor * @param nouns_ The address of the NOUN tokens * @param vetoer_ The address allowed to unilaterally veto proposals * @param votingPeriod_ The initial voting period * @param votingDelay_ The initial voting delay * @param proposalThresholdBPS_ The initial proposal threshold in basis points * * @param quorumVotesBPS_ The initial quorum votes threshold in basis points */ function initialize( address timelock_, address nouns_, address vetoer_, uint256 votingPeriod_, uint256 votingDelay_, uint256 proposalThresholdBPS_, uint256 quorumVotesBPS_ ) public virtual { require(address(timelock) == address(0), 'NounsDAO::initialize: can only initialize once'); require(msg.sender == admin, 'NounsDAO::initialize: admin only'); require(timelock_ != address(0), 'NounsDAO::initialize: invalid timelock address'); require(nouns_ != address(0), 'NounsDAO::initialize: invalid nouns address'); require( votingPeriod_ >= MIN_VOTING_PERIOD && votingPeriod_ <= MAX_VOTING_PERIOD, 'NounsDAO::initialize: invalid voting period' ); require( votingDelay_ >= MIN_VOTING_DELAY && votingDelay_ <= MAX_VOTING_DELAY, 'NounsDAO::initialize: invalid voting delay' ); require( proposalThresholdBPS_ >= MIN_PROPOSAL_THRESHOLD_BPS && proposalThresholdBPS_ <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::initialize: invalid proposal threshold' ); require( quorumVotesBPS_ >= MIN_QUORUM_VOTES_BPS && quorumVotesBPS_ <= MAX_QUORUM_VOTES_BPS, 'NounsDAO::initialize: invalid proposal threshold' ); emit VotingPeriodSet(votingPeriod, votingPeriod_); emit VotingDelaySet(votingDelay, votingDelay_); emit ProposalThresholdBPSSet(proposalThresholdBPS, proposalThresholdBPS_); emit QuorumVotesBPSSet(quorumVotesBPS, quorumVotesBPS_); timelock = INounsDAOExecutor(timelock_); nouns = NounsTokenLike(nouns_); vetoer = vetoer_; votingPeriod = votingPeriod_; votingDelay = votingDelay_; proposalThresholdBPS = proposalThresholdBPS_; quorumVotesBPS = quorumVotesBPS_; } struct ProposalTemp { uint256 totalSupply; uint256 proposalThreshold; uint256 latestProposalId; uint256 startBlock; uint256 endBlock; } /** * @notice Function used to propose a new proposal. Sender must have delegates above the proposal threshold * @param targets Target addresses for proposal calls * @param values Eth values for proposal calls * @param signatures Function signatures for proposal calls * @param calldatas Calldatas for proposal calls * @param description String description of the proposal * @return Proposal id of new proposal */ function propose( address[] memory targets, uint256[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description ) public returns (uint256) { ProposalTemp memory temp; temp.totalSupply = nouns.totalSupply(); temp.proposalThreshold = bps2Uint(proposalThresholdBPS, temp.totalSupply); require( nouns.getPriorVotes(msg.sender, block.number - 1) > temp.proposalThreshold, 'NounsDAO::propose: proposer votes below proposal threshold' ); require( targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, 'NounsDAO::propose: proposal function information arity mismatch' ); require(targets.length != 0, 'NounsDAO::propose: must provide actions'); require(targets.length <= proposalMaxOperations, 'NounsDAO::propose: too many actions'); temp.latestProposalId = latestProposalIds[msg.sender]; if (temp.latestProposalId != 0) { ProposalState proposersLatestProposalState = state(temp.latestProposalId); require( proposersLatestProposalState != ProposalState.Active, 'NounsDAO::propose: one live proposal per proposer, found an already active proposal' ); require( proposersLatestProposalState != ProposalState.Pending, 'NounsDAO::propose: one live proposal per proposer, found an already pending proposal' ); } temp.startBlock = block.number + votingDelay; temp.endBlock = temp.startBlock + votingPeriod; proposalCount++; Proposal storage newProposal = proposals[proposalCount]; newProposal.id = proposalCount; newProposal.proposer = msg.sender; newProposal.proposalThreshold = temp.proposalThreshold; newProposal.quorumVotes = bps2Uint(quorumVotesBPS, temp.totalSupply); newProposal.eta = 0; newProposal.targets = targets; newProposal.values = values; newProposal.signatures = signatures; newProposal.calldatas = calldatas; newProposal.startBlock = temp.startBlock; newProposal.endBlock = temp.endBlock; newProposal.forVotes = 0; newProposal.againstVotes = 0; newProposal.abstainVotes = 0; newProposal.canceled = false; newProposal.executed = false; newProposal.vetoed = false; latestProposalIds[newProposal.proposer] = newProposal.id; /// @notice Maintains backwards compatibility with GovernorBravo events emit ProposalCreated( newProposal.id, msg.sender, targets, values, signatures, calldatas, newProposal.startBlock, newProposal.endBlock, description ); /// @notice Updated event with `proposalThreshold` and `quorumVotes` emit ProposalCreatedWithRequirements( newProposal.id, msg.sender, targets, values, signatures, calldatas, newProposal.startBlock, newProposal.endBlock, newProposal.proposalThreshold, newProposal.quorumVotes, description ); return newProposal.id; } /** * @notice Queues a proposal of state succeeded * @param proposalId The id of the proposal to queue */ function queue(uint256 proposalId) external { require( state(proposalId) == ProposalState.Succeeded, 'NounsDAO::queue: proposal can only be queued if it is succeeded' ); Proposal storage proposal = proposals[proposalId]; uint256 eta = block.timestamp + timelock.delay(); for (uint256 i = 0; i < proposal.targets.length; i++) { queueOrRevertInternal( proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], eta ); } proposal.eta = eta; emit ProposalQueued(proposalId, eta); } function queueOrRevertInternal( address target, uint256 value, string memory signature, bytes memory data, uint256 eta ) internal { require( !timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), 'NounsDAO::queueOrRevertInternal: identical proposal action already queued at eta' ); timelock.queueTransaction(target, value, signature, data, eta); } /** * @notice Executes a queued proposal if eta has passed * @param proposalId The id of the proposal to execute */ function execute(uint256 proposalId) external { require( state(proposalId) == ProposalState.Queued, 'NounsDAO::execute: proposal can only be executed if it is queued' ); Proposal storage proposal = proposals[proposalId]; proposal.executed = true; for (uint256 i = 0; i < proposal.targets.length; i++) { timelock.executeTransaction( proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta ); } emit ProposalExecuted(proposalId); } /** * @notice Cancels a proposal only if sender is the proposer, or proposer delegates dropped below proposal threshold * @param proposalId The id of the proposal to cancel */ function cancel(uint256 proposalId) external { require(state(proposalId) != ProposalState.Executed, 'NounsDAO::cancel: cannot cancel executed proposal'); Proposal storage proposal = proposals[proposalId]; require( msg.sender == proposal.proposer || nouns.getPriorVotes(proposal.proposer, block.number - 1) < proposal.proposalThreshold, 'NounsDAO::cancel: proposer above threshold' ); proposal.canceled = true; for (uint256 i = 0; i < proposal.targets.length; i++) { timelock.cancelTransaction( proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta ); } emit ProposalCanceled(proposalId); } /** * @notice Vetoes a proposal only if sender is the vetoer and the proposal has not been executed. * @param proposalId The id of the proposal to veto */ function veto(uint256 proposalId) external { require(vetoer != address(0), 'NounsDAO::veto: veto power burned'); require(msg.sender == vetoer, 'NounsDAO::veto: only vetoer'); require(state(proposalId) != ProposalState.Executed, 'NounsDAO::veto: cannot veto executed proposal'); Proposal storage proposal = proposals[proposalId]; proposal.vetoed = true; for (uint256 i = 0; i < proposal.targets.length; i++) { timelock.cancelTransaction( proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta ); } emit ProposalVetoed(proposalId); } /** * @notice Gets actions of a proposal * @param proposalId the id of the proposal * @return targets * @return values * @return signatures * @return calldatas */ function getActions(uint256 proposalId) external view returns ( address[] memory targets, uint256[] memory values, string[] memory signatures, bytes[] memory calldatas ) { Proposal storage p = proposals[proposalId]; return (p.targets, p.values, p.signatures, p.calldatas); } /** * @notice Gets the receipt for a voter on a given proposal * @param proposalId the id of proposal * @param voter The address of the voter * @return The voting receipt */ function getReceipt(uint256 proposalId, address voter) external view returns (Receipt memory) { return proposals[proposalId].receipts[voter]; } /** * @notice Gets the state of a proposal * @param proposalId The id of the proposal * @return Proposal state */ function state(uint256 proposalId) public view returns (ProposalState) { require(proposalCount >= proposalId, 'NounsDAO::state: invalid proposal id'); Proposal storage proposal = proposals[proposalId]; if (proposal.vetoed) { return ProposalState.Vetoed; } else if (proposal.canceled) { return ProposalState.Canceled; } else if (block.number <= proposal.startBlock) { return ProposalState.Pending; } else if (block.number <= proposal.endBlock) { return ProposalState.Active; } else if (proposal.forVotes <= proposal.againstVotes || proposal.forVotes < proposal.quorumVotes) { return ProposalState.Defeated; } else if (proposal.eta == 0) { return ProposalState.Succeeded; } else if (proposal.executed) { return ProposalState.Executed; } else if (block.timestamp >= proposal.eta + timelock.GRACE_PERIOD()) { return ProposalState.Expired; } else { return ProposalState.Queued; } } /** * @notice Cast a vote for a proposal * @param proposalId The id of the proposal to vote on * @param support The support value for the vote. 0=against, 1=for, 2=abstain */ function castVote(uint256 proposalId, uint8 support) external { emit VoteCast(msg.sender, proposalId, support, castVoteInternal(msg.sender, proposalId, support), ''); } /** * @notice Cast a vote for a proposal with a reason * @param proposalId The id of the proposal to vote on * @param support The support value for the vote. 0=against, 1=for, 2=abstain * @param reason The reason given for the vote by the voter */ function castVoteWithReason( uint256 proposalId, uint8 support, string calldata reason ) external { emit VoteCast(msg.sender, proposalId, support, castVoteInternal(msg.sender, proposalId, support), reason); } /** * @notice Cast a vote for a proposal by signature * @dev External function that accepts EIP-712 signatures for voting on proposals. */ function castVoteBySig( uint256 proposalId, uint8 support, uint8 v, bytes32 r, bytes32 s ) external { bytes32 domainSeparator = keccak256( abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainIdInternal(), address(this)) ); bytes32 structHash = keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support)); bytes32 digest = keccak256(abi.encodePacked('\x19\x01', domainSeparator, structHash)); address signatory = ecrecover(digest, v, r, s); require(signatory != address(0), 'NounsDAO::castVoteBySig: invalid signature'); emit VoteCast(signatory, proposalId, support, castVoteInternal(signatory, proposalId, support), ''); } /** * @notice Internal function that caries out voting logic * @param voter The voter that is casting their vote * @param proposalId The id of the proposal to vote on * @param support The support value for the vote. 0=against, 1=for, 2=abstain * @return The number of votes cast */ function castVoteInternal( address voter, uint256 proposalId, uint8 support ) internal returns (uint96) { require(state(proposalId) == ProposalState.Active, 'NounsDAO::castVoteInternal: voting is closed'); require(support <= 2, 'NounsDAO::castVoteInternal: invalid vote type'); Proposal storage proposal = proposals[proposalId]; Receipt storage receipt = proposal.receipts[voter]; require(receipt.hasVoted == false, 'NounsDAO::castVoteInternal: voter already voted'); /// @notice: Unlike GovernerBravo, votes are considered from the block the proposal was created in order to normalize quorumVotes and proposalThreshold metrics uint96 votes = nouns.getPriorVotes(voter, proposal.startBlock - votingDelay); if (support == 0) { proposal.againstVotes = proposal.againstVotes + votes; } else if (support == 1) { proposal.forVotes = proposal.forVotes + votes; } else if (support == 2) { proposal.abstainVotes = proposal.abstainVotes + votes; } receipt.hasVoted = true; receipt.support = support; receipt.votes = votes; return votes; } /** * @notice Admin function for setting the voting delay * @param newVotingDelay new voting delay, in blocks */ function _setVotingDelay(uint256 newVotingDelay) external { require(msg.sender == admin, 'NounsDAO::_setVotingDelay: admin only'); require( newVotingDelay >= MIN_VOTING_DELAY && newVotingDelay <= MAX_VOTING_DELAY, 'NounsDAO::_setVotingDelay: invalid voting delay' ); uint256 oldVotingDelay = votingDelay; votingDelay = newVotingDelay; emit VotingDelaySet(oldVotingDelay, votingDelay); } /** * @notice Admin function for setting the voting period * @param newVotingPeriod new voting period, in blocks */ function _setVotingPeriod(uint256 newVotingPeriod) external { require(msg.sender == admin, 'NounsDAO::_setVotingPeriod: admin only'); require( newVotingPeriod >= MIN_VOTING_PERIOD && newVotingPeriod <= MAX_VOTING_PERIOD, 'NounsDAO::_setVotingPeriod: invalid voting period' ); uint256 oldVotingPeriod = votingPeriod; votingPeriod = newVotingPeriod; emit VotingPeriodSet(oldVotingPeriod, votingPeriod); } /** * @notice Admin function for setting the proposal threshold basis points * @dev newProposalThresholdBPS must be greater than the hardcoded min * @param newProposalThresholdBPS new proposal threshold */ function _setProposalThresholdBPS(uint256 newProposalThresholdBPS) external { require(msg.sender == admin, 'NounsDAO::_setProposalThresholdBPS: admin only'); require( newProposalThresholdBPS >= MIN_PROPOSAL_THRESHOLD_BPS && newProposalThresholdBPS <= MAX_PROPOSAL_THRESHOLD_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold' ); uint256 oldProposalThresholdBPS = proposalThresholdBPS; proposalThresholdBPS = newProposalThresholdBPS; emit ProposalThresholdBPSSet(oldProposalThresholdBPS, proposalThresholdBPS); } /** * @notice Admin function for setting the quorum votes basis points * @dev newQuorumVotesBPS must be greater than the hardcoded min * @param newQuorumVotesBPS new proposal threshold */ function _setQuorumVotesBPS(uint256 newQuorumVotesBPS) external { require(msg.sender == admin, 'NounsDAO::_setQuorumVotesBPS: admin only'); require( newQuorumVotesBPS >= MIN_QUORUM_VOTES_BPS && newQuorumVotesBPS <= MAX_QUORUM_VOTES_BPS, 'NounsDAO::_setProposalThreshold: invalid proposal threshold' ); uint256 oldQuorumVotesBPS = quorumVotesBPS; quorumVotesBPS = newQuorumVotesBPS; emit QuorumVotesBPSSet(oldQuorumVotesBPS, quorumVotesBPS); } /** * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. * @param newPendingAdmin New pending admin. */ function _setPendingAdmin(address newPendingAdmin) external { // Check caller = admin require(msg.sender == admin, 'NounsDAO::_setPendingAdmin: admin only'); // Save current value, if any, for inclusion in log address oldPendingAdmin = pendingAdmin; // Store pendingAdmin with value newPendingAdmin pendingAdmin = newPendingAdmin; // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin) emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin); } /** * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin * @dev Admin function for pending admin to accept role and update admin */ function _acceptAdmin() external { // Check caller is pendingAdmin and pendingAdmin β‰  address(0) require(msg.sender == pendingAdmin && msg.sender != address(0), 'NounsDAO::_acceptAdmin: pending admin only'); // Save current values for inclusion in log address oldAdmin = admin; address oldPendingAdmin = pendingAdmin; // Store admin with value pendingAdmin admin = pendingAdmin; // Clear the pending value pendingAdmin = address(0); emit NewAdmin(oldAdmin, admin); emit NewPendingAdmin(oldPendingAdmin, pendingAdmin); } /** * @notice Changes vetoer address * @dev Vetoer function for updating vetoer address */ function _setVetoer(address newVetoer) public { require(msg.sender == vetoer, 'NounsDAO::_setVetoer: vetoer only'); emit NewVetoer(vetoer, newVetoer); vetoer = newVetoer; } /** * @notice Burns veto priviledges * @dev Vetoer function destroying veto power forever */ function _burnVetoPower() public { // Check caller is pendingAdmin and pendingAdmin β‰  address(0) require(msg.sender == vetoer, 'NounsDAO::_burnVetoPower: vetoer only'); _setVetoer(address(0)); } /** * @notice Current proposal threshold using Noun Total Supply * Differs from `GovernerBravo` which uses fixed amount */ function proposalThreshold() public view returns (uint256) { return bps2Uint(proposalThresholdBPS, nouns.totalSupply()); } /** * @notice Current quorum votes using Noun Total Supply * Differs from `GovernerBravo` which uses fixed amount */ function quorumVotes() public view returns (uint256) { return bps2Uint(quorumVotesBPS, nouns.totalSupply()); } function bps2Uint(uint256 bps, uint256 number) internal pure returns (uint256) { return (number * bps) / 10000; } function getChainIdInternal() internal view returns (uint256) { uint256 chainId; assembly { chainId := chainid() } return chainId; } } // SPDX-License-Identifier: BSD-3-Clause /// @title Nouns DAO Logic interfaces and events /********************************* * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ * * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ * * β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ * * β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ * * β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ * * β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ * * β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ * * β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ * * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ * * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ * *********************************/ // LICENSE // NounsDAOInterfaces.sol is a modified version of Compound Lab's GovernorBravoInterfaces.sol: // https://github.com/compound-finance/compound-protocol/blob/b9b14038612d846b83f8a009a82c38974ff2dcfe/contracts/Governance/GovernorBravoInterfaces.sol // // GovernorBravoInterfaces.sol source code Copyright 2020 Compound Labs, Inc. licensed under the BSD-3-Clause license. // With modifications by Nounders DAO. // // Additional conditions of BSD-3-Clause can be found here: https://opensource.org/licenses/BSD-3-Clause // // MODIFICATIONS // NounsDAOEvents, NounsDAOProxyStorage, NounsDAOStorageV1 adds support for changes made by Nouns DAO to GovernorBravo.sol // See NounsDAOLogicV1.sol for more details. pragma solidity ^0.8.6; contract NounsDAOEvents { /// @notice An event emitted when a new proposal is created event ProposalCreated( uint256 id, address proposer, address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, uint256 startBlock, uint256 endBlock, string description ); event ProposalCreatedWithRequirements( uint256 id, address proposer, address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, uint256 startBlock, uint256 endBlock, uint256 proposalThreshold, uint256 quorumVotes, string description ); /// @notice An event emitted when a vote has been cast on a proposal /// @param voter The address which casted a vote /// @param proposalId The proposal id which was voted on /// @param support Support value for the vote. 0=against, 1=for, 2=abstain /// @param votes Number of votes which were cast by the voter /// @param reason The reason given for the vote by the voter event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 votes, string reason); /// @notice An event emitted when a proposal has been canceled event ProposalCanceled(uint256 id); /// @notice An event emitted when a proposal has been queued in the NounsDAOExecutor event ProposalQueued(uint256 id, uint256 eta); /// @notice An event emitted when a proposal has been executed in the NounsDAOExecutor event ProposalExecuted(uint256 id); /// @notice An event emitted when a proposal has been vetoed by vetoAddress event ProposalVetoed(uint256 id); /// @notice An event emitted when the voting delay is set event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay); /// @notice An event emitted when the voting period is set event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod); /// @notice Emitted when implementation is changed event NewImplementation(address oldImplementation, address newImplementation); /// @notice Emitted when proposal threshold basis points is set event ProposalThresholdBPSSet(uint256 oldProposalThresholdBPS, uint256 newProposalThresholdBPS); /// @notice Emitted when quorum votes basis points is set event QuorumVotesBPSSet(uint256 oldQuorumVotesBPS, uint256 newQuorumVotesBPS); /// @notice Emitted when pendingAdmin is changed event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin); /// @notice Emitted when pendingAdmin is accepted, which means admin is updated event NewAdmin(address oldAdmin, address newAdmin); /// @notice Emitted when vetoer is changed event NewVetoer(address oldVetoer, address newVetoer); } contract NounsDAOProxyStorage { /// @notice Administrator for this contract address public admin; /// @notice Pending administrator for this contract address public pendingAdmin; /// @notice Active brains of Governor address public implementation; } /** * @title Storage for Governor Bravo Delegate * @notice For future upgrades, do not change NounsDAOStorageV1. Create a new * contract which implements NounsDAOStorageV1 and following the naming convention * NounsDAOStorageVX. */ contract NounsDAOStorageV1 is NounsDAOProxyStorage { /// @notice Vetoer who has the ability to veto any proposal address public vetoer; /// @notice The delay before voting on a proposal may take place, once proposed, in blocks uint256 public votingDelay; /// @notice The duration of voting on a proposal, in blocks uint256 public votingPeriod; /// @notice The basis point number of votes required in order for a voter to become a proposer. *DIFFERS from GovernerBravo uint256 public proposalThresholdBPS; /// @notice The basis point number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed. *DIFFERS from GovernerBravo uint256 public quorumVotesBPS; /// @notice The total number of proposals uint256 public proposalCount; /// @notice The address of the Nouns DAO Executor NounsDAOExecutor INounsDAOExecutor public timelock; /// @notice The address of the Nouns tokens NounsTokenLike public nouns; /// @notice The official record of all proposals ever proposed mapping(uint256 => Proposal) public proposals; /// @notice The latest proposal for each proposer mapping(address => uint256) public latestProposalIds; struct Proposal { /// @notice Unique id for looking up a proposal uint256 id; /// @notice Creator of the proposal address proposer; /// @notice The number of votes needed to create a proposal at the time of proposal creation. *DIFFERS from GovernerBravo uint256 proposalThreshold; /// @notice The number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed at the time of proposal creation. *DIFFERS from GovernerBravo uint256 quorumVotes; /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds uint256 eta; /// @notice the ordered list of target addresses for calls to be made address[] targets; /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made uint256[] values; /// @notice The ordered list of function signatures to be called string[] signatures; /// @notice The ordered list of calldata to be passed to each call bytes[] calldatas; /// @notice The block at which voting begins: holders must delegate their votes prior to this block uint256 startBlock; /// @notice The block at which voting ends: votes must be cast prior to this block uint256 endBlock; /// @notice Current number of votes in favor of this proposal uint256 forVotes; /// @notice Current number of votes in opposition to this proposal uint256 againstVotes; /// @notice Current number of votes for abstaining for this proposal uint256 abstainVotes; /// @notice Flag marking whether the proposal has been canceled bool canceled; /// @notice Flag marking whether the proposal has been vetoed bool vetoed; /// @notice Flag marking whether the proposal has been executed bool executed; /// @notice Receipts of ballots for the entire set of voters mapping(address => Receipt) receipts; } /// @notice Ballot receipt record for a voter struct Receipt { /// @notice Whether or not a vote has been cast bool hasVoted; /// @notice Whether or not the voter supports the proposal or abstains uint8 support; /// @notice The number of votes the voter had, which were cast uint96 votes; } /// @notice Possible states that a proposal may be in enum ProposalState { Pending, Active, Canceled, Defeated, Succeeded, Queued, Expired, Executed, Vetoed } } interface INounsDAOExecutor { function delay() external view returns (uint256); function GRACE_PERIOD() external view returns (uint256); function acceptAdmin() external; function queuedTransactions(bytes32 hash) external view returns (bool); function queueTransaction( address target, uint256 value, string calldata signature, bytes calldata data, uint256 eta ) external returns (bytes32); function cancelTransaction( address target, uint256 value, string calldata signature, bytes calldata data, uint256 eta ) external; function executeTransaction( address target, uint256 value, string calldata signature, bytes calldata data, uint256 eta ) external payable returns (bytes memory); } interface NounsTokenLike { function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96); function totalSupply() external view returns (uint96); }
< // SPDX-License-Identifier: BSD-3-Clause

/// @title The Nouns DAO logic version 1

/*********************************
 * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ *
 * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ *
 * β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ *
 * β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ *
 * β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ *
 * β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ *
 * β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ *
 * β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ *
 * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ *
 * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ *
 *********************************/

// LICENSE
// NounsDAOLogicV1.sol is a modified version of Compound Lab's GovernorBravoDelegate.sol:
// https://github.com/compound-finance/compound-protocol/blob/b9b14038612d846b83f8a009a82c38974ff2dcfe/contracts/Governance/GovernorBravoDelegate.sol
//
// GovernorBravoDelegate.sol source code Copyright 2020 Compound Labs, Inc. licensed under the BSD-3-Clause license.
// With modifications by Nounders DAO.
//
// Additional conditions of BSD-3-Clause can be found here: https://opensource.org/licenses/BSD-3-Clause
//
// MODIFICATIONS
// NounsDAOLogicV1 adds:
// - Proposal Threshold basis points instead of fixed number
//   due to the Noun token's increasing supply
//
// - Quorum Votes basis points instead of fixed number
//   due to the Noun token's increasing supply
//
// - Per proposal storing of fixed `proposalThreshold`
//   and `quorumVotes` calculated using the Noun token's total supply
//   at the block the proposal was created and the basis point parameters
//
// - `ProposalCreatedWithRequirements` event that emits `ProposalCreated` parameters with
//   the addition of `proposalThreshold` and `quorumVotes`
//
// - Votes are counted from the block a proposal is created instead of
//   the proposal's voting start block to align with the parameters
//   stored with the proposal
//
// - Veto ability which allows `veteor` to halt any proposal at any stage unless
//   the proposal is executed.
//   The `veto(uint proposalId)` logic is a modified version of `cancel(uint proposalId)`
//   A `vetoed` flag was added to the `Proposal` struct to support this.
//
// NounsDAOLogicV1 removes:
// - `initialProposalId` and `_initiate()` due to this being the
//   first instance of the governance contract unlike
//   GovernorBravo which upgrades GovernorAlpha
//
// - Value passed along using `timelock.executeTransaction{value: proposal.value}`
//   in `execute(uint proposalId)`. This contract should not hold funds and does not
//   implement `receive()` or `fallback()` functions.
//

pragma solidity ^0.8.6;

import './NounsDAOInterfaces.sol';

contract NounsDAOLogicV1 is NounsDAOStorageV1, NounsDAOEvents {
    /// @notice The name of this contract
    string public constant name = 'Nouns DAO';

    /// @notice The minimum setable proposal threshold
    uint256 public constant MIN_PROPOSAL_THRESHOLD_BPS = 1; // 1 basis point or 0.01%

    /// @notice The maximum setable proposal threshold
    uint256 public constant MAX_PROPOSAL_THRESHOLD_BPS = 1_000; // 1,000 basis points or 10%

    /// @notice The minimum setable voting period
    uint256 public constant MIN_VOTING_PERIOD = 5_760; // About 24 hours

    /// @notice The max setable voting period
    uint256 public constant MAX_VOTING_PERIOD = 80_640; // About 2 weeks

    /// @notice The min setable voting delay
    uint256 public constant MIN_VOTING_DELAY = 1;

    /// @notice The max setable voting delay
    uint256 public constant MAX_VOTING_DELAY = 40_320; // About 1 week

    /// @notice The minimum setable quorum votes basis points
    uint256 public constant MIN_QUORUM_VOTES_BPS = 200; // 200 basis points or 2%

    /// @notice The maximum setable quorum votes basis points
    uint256 public constant MAX_QUORUM_VOTES_BPS = 2_000; // 2,000 basis points or 20%

    /// @notice The maximum number of actions that can be included in a proposal
    uint256 public constant proposalMaxOperations = 10; // 10 actions

    /// @notice The EIP-712 typehash for the contract's domain
    bytes32 public constant DOMAIN_TYPEHASH =
        keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');

    /// @notice The EIP-712 typehash for the ballot struct used by the contract
    bytes32 public constant BALLOT_TYPEHASH = keccak256('Ballot(uint256 proposalId,uint8 support)');

    /**
     * @notice Used to initialize the contract during delegator contructor
     * @param timelock_ The address of the NounsDAOExecutor
     * @param nouns_ The address of the NOUN tokens
     * @param vetoer_ The address allowed to unilaterally veto proposals
     * @param votingPeriod_ The initial voting period
     * @param votingDelay_ The initial voting delay
     * @param proposalThresholdBPS_ The initial proposal threshold in basis points
     * * @param quorumVotesBPS_ The initial quorum votes threshold in basis points
     */
    function initialize(
        address timelock_,
        address nouns_,
        address vetoer_,
        uint256 votingPeriod_,
        uint256 votingDelay_,
        uint256 proposalThresholdBPS_,
        uint256 quorumVotesBPS_
    ) public virtual {
        require(address(timelock) == address(0), 'NounsDAO::initialize: can only initialize once');
        require(msg.sender == admin, 'NounsDAO::initialize: admin only');
        require(timelock_ != address(0), 'NounsDAO::initialize: invalid timelock address');
        require(nouns_ != address(0), 'NounsDAO::initialize: invalid nouns address');
        require(
            votingPeriod_ >= MIN_VOTING_PERIOD && votingPeriod_ <= MAX_VOTING_PERIOD,
            'NounsDAO::initialize: invalid voting period'
        );
        require(
            votingDelay_ >= MIN_VOTING_DELAY && votingDelay_ <= MAX_VOTING_DELAY,
            'NounsDAO::initialize: invalid voting delay'
        );
        require(
            proposalThresholdBPS_ >= MIN_PROPOSAL_THRESHOLD_BPS && proposalThresholdBPS_ <= MAX_PROPOSAL_THRESHOLD_BPS,
            'NounsDAO::initialize: invalid proposal threshold'
        );
        require(
            quorumVotesBPS_ >= MIN_QUORUM_VOTES_BPS && quorumVotesBPS_ <= MAX_QUORUM_VOTES_BPS,
            'NounsDAO::initialize: invalid proposal threshold'
        );

        emit VotingPeriodSet(votingPeriod, votingPeriod_);
        emit VotingDelaySet(votingDelay, votingDelay_);
        emit ProposalThresholdBPSSet(proposalThresholdBPS, proposalThresholdBPS_);
        emit QuorumVotesBPSSet(quorumVotesBPS, quorumVotesBPS_);

        timelock = INounsDAOExecutor(timelock_);
        nouns = NounsTokenLike(nouns_);
        vetoer = vetoer_;
        votingPeriod = votingPeriod_;
        votingDelay = votingDelay_;
        proposalThresholdBPS = proposalThresholdBPS_;
        quorumVotesBPS = quorumVotesBPS_;
    }

    struct ProposalTemp {
        uint256 totalSupply;
        uint256 proposalThreshold;
        uint256 latestProposalId;
        uint256 startBlock;
        uint256 endBlock;
    }

    /**
     * @notice Function used to propose a new proposal. Sender must have delegates above the proposal threshold
     * @param targets Target addresses for proposal calls
     * @param values Eth values for proposal calls
     * @param signatures Function signatures for proposal calls
     * @param calldatas Calldatas for proposal calls
     * @param description String description of the proposal
     * @return Proposal id of new proposal
     */
    function propose(
        address[] memory targets,
        uint256[] memory values,
        string[] memory signatures,
        bytes[] memory calldatas,
        string memory description
    ) public returns (uint256) {
        ProposalTemp memory temp;

        temp.totalSupply = nouns.totalSupply();

        temp.proposalThreshold = bps2Uint(proposalThresholdBPS, temp.totalSupply);

        require(
            nouns.getPriorVotes(msg.sender, block.number - 1) > temp.proposalThreshold,
            'NounsDAO::propose: proposer votes below proposal threshold'
        );
        require(
            targets.length == values.length &&
                targets.length == signatures.length &&
                targets.length == calldatas.length,
            'NounsDAO::propose: proposal function information arity mismatch'
        );
        require(targets.length != 0, 'NounsDAO::propose: must provide actions');
        require(targets.length <= proposalMaxOperations, 'NounsDAO::propose: too many actions');

        temp.latestProposalId = latestProposalIds[msg.sender];
        if (temp.latestProposalId != 0) {
            ProposalState proposersLatestProposalState = state(temp.latestProposalId);
            require(
                proposersLatestProposalState != ProposalState.Active,
                'NounsDAO::propose: one live proposal per proposer, found an already active proposal'
            );
            require(
                proposersLatestProposalState != ProposalState.Pending,
                'NounsDAO::propose: one live proposal per proposer, found an already pending proposal'
            );
        }

        temp.startBlock = block.number + votingDelay;
        temp.endBlock = temp.startBlock + votingPeriod;

        proposalCount++;
        Proposal storage newProposal = proposals[proposalCount];

        newProposal.id = proposalCount;
        newProposal.proposer = msg.sender;
        newProposal.proposalThreshold = temp.proposalThreshold;
        newProposal.quorumVotes = bps2Uint(quorumVotesBPS, temp.totalSupply);
        newProposal.eta = 0;
        newProposal.targets = targets;
        newProposal.values = values;
        newProposal.signatures = signatures;
        newProposal.calldatas = calldatas;
        newProposal.startBlock = temp.startBlock;
        newProposal.endBlock = temp.endBlock;
        newProposal.forVotes = 0;
        newProposal.againstVotes = 0;
        newProposal.abstainVotes = 0;
        newProposal.canceled = false;
        newProposal.executed = false;
        newProposal.vetoed = false;

        latestProposalIds[newProposal.proposer] = newProposal.id;

        /// @notice Maintains backwards compatibility with GovernorBravo events
        emit ProposalCreated(
            newProposal.id,
            msg.sender,
            targets,
            values,
            signatures,
            calldatas,
            newProposal.startBlock,
            newProposal.endBlock,
            description
        );

        /// @notice Updated event with `proposalThreshold` and `quorumVotes`
        emit ProposalCreatedWithRequirements(
            newProposal.id,
            msg.sender,
            targets,
            values,
            signatures,
            calldatas,
            newProposal.startBlock,
            newProposal.endBlock,
            newProposal.proposalThreshold,
            newProposal.quorumVotes,
            description
        );

        return newProposal.id;
    }

    /**
     * @notice Queues a proposal of state succeeded
     * @param proposalId The id of the proposal to queue
     */
    function queue(uint256 proposalId) external {
        require(
            state(proposalId) == ProposalState.Succeeded,
            'NounsDAO::queue: proposal can only be queued if it is succeeded'
        );
        Proposal storage proposal = proposals[proposalId];
        uint256 eta = block.timestamp + timelock.delay();
        for (uint256 i = 0; i < proposal.targets.length; i++) {
            queueOrRevertInternal(
                proposal.targets[i],
                proposal.values[i],
                proposal.signatures[i],
                proposal.calldatas[i],
                eta
            );
        }
        proposal.eta = eta;
        emit ProposalQueued(proposalId, eta);
    }

    function queueOrRevertInternal(
        address target,
        uint256 value,
        string memory signature,
        bytes memory data,
        uint256 eta
    ) internal {
        require(
            !timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))),
            'NounsDAO::queueOrRevertInternal: identical proposal action already queued at eta'
        );
        timelock.queueTransaction(target, value, signature, data, eta);
    }

    /**
     * @notice Executes a queued proposal if eta has passed
     * @param proposalId The id of the proposal to execute
     */
    function execute(uint256 proposalId) external {
        require(
            state(proposalId) == ProposalState.Queued,
            'NounsDAO::execute: proposal can only be executed if it is queued'
        );
        Proposal storage proposal = proposals[proposalId];
        proposal.executed = true;
        for (uint256 i = 0; i < proposal.targets.length; i++) {
            timelock.executeTransaction(
                proposal.targets[i],
                proposal.values[i],
                proposal.signatures[i],
                proposal.calldatas[i],
                proposal.eta
            );
        }
        emit ProposalExecuted(proposalId);
    }

    /**
     * @notice Cancels a proposal only if sender is the proposer, or proposer delegates dropped below proposal threshold
     * @param proposalId The id of the proposal to cancel
     */
    function cancel(uint256 proposalId) external {
        require(state(proposalId) != ProposalState.Executed, 'NounsDAO::cancel: cannot cancel executed proposal');

        Proposal storage proposal = proposals[proposalId];
        require(
            msg.sender == proposal.proposer ||
                nouns.getPriorVotes(proposal.proposer, block.number - 1) < proposal.proposalThreshold,
            'NounsDAO::cancel: proposer above threshold'
        );

        proposal.canceled = true;
        for (uint256 i = 0; i < proposal.targets.length; i++) {
            timelock.cancelTransaction(
                proposal.targets[i],
                proposal.values[i],
                proposal.signatures[i],
                proposal.calldatas[i],
                proposal.eta
            );
        }

        emit ProposalCanceled(proposalId);
    }

    /**
     * @notice Vetoes a proposal only if sender is the vetoer and the proposal has not been executed.
     * @param proposalId The id of the proposal to veto
     */
    function veto(uint256 proposalId) external {
        require(vetoer != address(0), 'NounsDAO::veto: veto power burned');
        require(msg.sender == vetoer, 'NounsDAO::veto: only vetoer');
        require(state(proposalId) != ProposalState.Executed, 'NounsDAO::veto: cannot veto executed proposal');

        Proposal storage proposal = proposals[proposalId];

        proposal.vetoed = true;
        for (uint256 i = 0; i < proposal.targets.length; i++) {
            timelock.cancelTransaction(
                proposal.targets[i],
                proposal.values[i],
                proposal.signatures[i],
                proposal.calldatas[i],
                proposal.eta
            );
        }

        emit ProposalVetoed(proposalId);
    }

    /**
     * @notice Gets actions of a proposal
     * @param proposalId the id of the proposal
     * @return targets
     * @return values
     * @return signatures
     * @return calldatas
     */
    function getActions(uint256 proposalId)
        external
        view
        returns (
            address[] memory targets,
            uint256[] memory values,
            string[] memory signatures,
            bytes[] memory calldatas
        )
    {
        Proposal storage p = proposals[proposalId];
        return (p.targets, p.values, p.signatures, p.calldatas);
    }

    /**
     * @notice Gets the receipt for a voter on a given proposal
     * @param proposalId the id of proposal
     * @param voter The address of the voter
     * @return The voting receipt
     */
    function getReceipt(uint256 proposalId, address voter) external view returns (Receipt memory) {
        return proposals[proposalId].receipts[voter];
    }

    /**
     * @notice Gets the state of a proposal
     * @param proposalId The id of the proposal
     * @return Proposal state
     */
    function state(uint256 proposalId) public view returns (ProposalState) {
        require(proposalCount >= proposalId, 'NounsDAO::state: invalid proposal id');
        Proposal storage proposal = proposals[proposalId];
        if (proposal.vetoed) {
            return ProposalState.Vetoed;
        } else if (proposal.canceled) {
            return ProposalState.Canceled;
        } else if (block.number <= proposal.startBlock) {
            return ProposalState.Pending;
        } else if (block.number <= proposal.endBlock) {
            return ProposalState.Active;
        } else if (proposal.forVotes <= proposal.againstVotes || proposal.forVotes < proposal.quorumVotes) {
            return ProposalState.Defeated;
        } else if (proposal.eta == 0) {
            return ProposalState.Succeeded;
        } else if (proposal.executed) {
            return ProposalState.Executed;
        } else if (block.timestamp >= proposal.eta + timelock.GRACE_PERIOD()) {
            return ProposalState.Expired;
        } else {
            return ProposalState.Queued;
        }
    }

    /**
     * @notice Cast a vote for a proposal
     * @param proposalId The id of the proposal to vote on
     * @param support The support value for the vote. 0=against, 1=for, 2=abstain
     */
    function castVote(uint256 proposalId, uint8 support) external {
        emit VoteCast(msg.sender, proposalId, support, castVoteInternal(msg.sender, proposalId, support), '');
    }

    /**
     * @notice Cast a vote for a proposal with a reason
     * @param proposalId The id of the proposal to vote on
     * @param support The support value for the vote. 0=against, 1=for, 2=abstain
     * @param reason The reason given for the vote by the voter
     */
    function castVoteWithReason(
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) external {
        emit VoteCast(msg.sender, proposalId, support, castVoteInternal(msg.sender, proposalId, support), reason);
    }

    /**
     * @notice Cast a vote for a proposal by signature
     * @dev External function that accepts EIP-712 signatures for voting on proposals.
     */
    function castVoteBySig(
        uint256 proposalId,
        uint8 support,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        bytes32 domainSeparator = keccak256(
            abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainIdInternal(), address(this))
        );
        bytes32 structHash = keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support));
        bytes32 digest = keccak256(abi.encodePacked('\x19\x01', domainSeparator, structHash));
        address signatory = ecrecover(digest, v, r, s);
        require(signatory != address(0), 'NounsDAO::castVoteBySig: invalid signature');
        emit VoteCast(signatory, proposalId, support, castVoteInternal(signatory, proposalId, support), '');
    }

    /**
     * @notice Internal function that caries out voting logic
     * @param voter The voter that is casting their vote
     * @param proposalId The id of the proposal to vote on
     * @param support The support value for the vote. 0=against, 1=for, 2=abstain
     * @return The number of votes cast
     */
    function castVoteInternal(
        address voter,
        uint256 proposalId,
        uint8 support
    ) internal returns (uint96) {
        require(state(proposalId) == ProposalState.Active, 'NounsDAO::castVoteInternal: voting is closed');
        require(support <= 2, 'NounsDAO::castVoteInternal: invalid vote type');
        Proposal storage proposal = proposals[proposalId];
        Receipt storage receipt = proposal.receipts[voter];
        require(receipt.hasVoted == false, 'NounsDAO::castVoteInternal: voter already voted');

        /// @notice: Unlike GovernerBravo, votes are considered from the block the proposal was created in order to normalize quorumVotes and proposalThreshold metrics
        uint96 votes = nouns.getPriorVotes(voter, proposal.startBlock - votingDelay);

        if (support == 0) {
            proposal.againstVotes = proposal.againstVotes + votes;
        } else if (support == 1) {
            proposal.forVotes = proposal.forVotes + votes;
        } else if (support == 2) {
            proposal.abstainVotes = proposal.abstainVotes + votes;
        }

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

        return votes;
    }

    /**
     * @notice Admin function for setting the voting delay
     * @param newVotingDelay new voting delay, in blocks
     */
    function _setVotingDelay(uint256 newVotingDelay) external {
        require(msg.sender == admin, 'NounsDAO::_setVotingDelay: admin only');
        require(
            newVotingDelay >= MIN_VOTING_DELAY && newVotingDelay <= MAX_VOTING_DELAY,
            'NounsDAO::_setVotingDelay: invalid voting delay'
        );
        uint256 oldVotingDelay = votingDelay;
        votingDelay = newVotingDelay;

        emit VotingDelaySet(oldVotingDelay, votingDelay);
    }

    /**
     * @notice Admin function for setting the voting period
     * @param newVotingPeriod new voting period, in blocks
     */
    function _setVotingPeriod(uint256 newVotingPeriod) external {
        require(msg.sender == admin, 'NounsDAO::_setVotingPeriod: admin only');
        require(
            newVotingPeriod >= MIN_VOTING_PERIOD && newVotingPeriod <= MAX_VOTING_PERIOD,
            'NounsDAO::_setVotingPeriod: invalid voting period'
        );
        uint256 oldVotingPeriod = votingPeriod;
        votingPeriod = newVotingPeriod;

        emit VotingPeriodSet(oldVotingPeriod, votingPeriod);
    }

    /**
     * @notice Admin function for setting the proposal threshold basis points
     * @dev newProposalThresholdBPS must be greater than the hardcoded min
     * @param newProposalThresholdBPS new proposal threshold
     */
    function _setProposalThresholdBPS(uint256 newProposalThresholdBPS) external {
        require(msg.sender == admin, 'NounsDAO::_setProposalThresholdBPS: admin only');
        require(
            newProposalThresholdBPS >= MIN_PROPOSAL_THRESHOLD_BPS &&
                newProposalThresholdBPS <= MAX_PROPOSAL_THRESHOLD_BPS,
            'NounsDAO::_setProposalThreshold: invalid proposal threshold'
        );
        uint256 oldProposalThresholdBPS = proposalThresholdBPS;
        proposalThresholdBPS = newProposalThresholdBPS;

        emit ProposalThresholdBPSSet(oldProposalThresholdBPS, proposalThresholdBPS);
    }

    /**
     * @notice Admin function for setting the quorum votes basis points
     * @dev newQuorumVotesBPS must be greater than the hardcoded min
     * @param newQuorumVotesBPS new proposal threshold
     */
    function _setQuorumVotesBPS(uint256 newQuorumVotesBPS) external {
        require(msg.sender == admin, 'NounsDAO::_setQuorumVotesBPS: admin only');
        require(
            newQuorumVotesBPS >= MIN_QUORUM_VOTES_BPS && newQuorumVotesBPS <= MAX_QUORUM_VOTES_BPS,
            'NounsDAO::_setProposalThreshold: invalid proposal threshold'
        );
        uint256 oldQuorumVotesBPS = quorumVotesBPS;
        quorumVotesBPS = newQuorumVotesBPS;

        emit QuorumVotesBPSSet(oldQuorumVotesBPS, quorumVotesBPS);
    }

    /**
     * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
     * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
     * @param newPendingAdmin New pending admin.
     */
    function _setPendingAdmin(address newPendingAdmin) external {
        // Check caller = admin
        require(msg.sender == admin, 'NounsDAO::_setPendingAdmin: admin only');

        // Save current value, if any, for inclusion in log
        address oldPendingAdmin = pendingAdmin;

        // Store pendingAdmin with value newPendingAdmin
        pendingAdmin = newPendingAdmin;

        // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)
        emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);
    }

    /**
     * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin
     * @dev Admin function for pending admin to accept role and update admin
     */
    function _acceptAdmin() external {
        // Check caller is pendingAdmin and pendingAdmin β‰  address(0)
        require(msg.sender == pendingAdmin && msg.sender != address(0), 'NounsDAO::_acceptAdmin: pending admin only');

        // Save current values for inclusion in log
        address oldAdmin = admin;
        address oldPendingAdmin = pendingAdmin;

        // Store admin with value pendingAdmin
        admin = pendingAdmin;

        // Clear the pending value
        pendingAdmin = address(0);

        emit NewAdmin(oldAdmin, admin);
        emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);
    }

    /**
     * @notice Changes vetoer address
     * @dev Vetoer function for updating vetoer address
     */
    function _setVetoer(address newVetoer) public {
        require(msg.sender == vetoer, 'NounsDAO::_setVetoer: vetoer only');

        emit NewVetoer(vetoer, newVetoer);

        vetoer = newVetoer;
    }

    /**
     * @notice Burns veto priviledges
     * @dev Vetoer function destroying veto power forever
     */
    function _burnVetoPower() public {
        // Check caller is pendingAdmin and pendingAdmin β‰  address(0)
        require(msg.sender == vetoer, 'NounsDAO::_burnVetoPower: vetoer only');

        _setVetoer(address(0));
    }

    /**
     * @notice Current proposal threshold using Noun Total Supply
     * Differs from `GovernerBravo` which uses fixed amount
     */
    function proposalThreshold() public view returns (uint256) {
        return bps2Uint(proposalThresholdBPS, nouns.totalSupply());
    }

    /**
     * @notice Current quorum votes using Noun Total Supply
     * Differs from `GovernerBravo` which uses fixed amount
     */
    function quorumVotes() public view returns (uint256) {
        return bps2Uint(quorumVotesBPS, nouns.totalSupply());
    }

    function bps2Uint(uint256 bps, uint256 number) internal pure returns (uint256) {
        return (number * bps) / 10000;
    }

    function getChainIdInternal() internal view returns (uint256) {
        uint256 chainId;
        assembly {
            chainId := chainid()
        }
        return chainId;
    }
}
// SPDX-License-Identifier: BSD-3-Clause

/// @title Nouns DAO Logic interfaces and events

/*********************************
 * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ *
 * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ *
 * β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ *
 * β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ *
 * β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ *
 * β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ *
 * β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ *
 * β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘ *
 * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ *
 * β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ *
 *********************************/

// LICENSE
// NounsDAOInterfaces.sol is a modified version of Compound Lab's GovernorBravoInterfaces.sol:
// https://github.com/compound-finance/compound-protocol/blob/b9b14038612d846b83f8a009a82c38974ff2dcfe/contracts/Governance/GovernorBravoInterfaces.sol
//
// GovernorBravoInterfaces.sol source code Copyright 2020 Compound Labs, Inc. licensed under the BSD-3-Clause license.
// With modifications by Nounders DAO.
//
// Additional conditions of BSD-3-Clause can be found here: https://opensource.org/licenses/BSD-3-Clause
//
// MODIFICATIONS
// NounsDAOEvents, NounsDAOProxyStorage, NounsDAOStorageV1 adds support for changes made by Nouns DAO to GovernorBravo.sol
// See NounsDAOLogicV1.sol for more details.

pragma solidity ^0.8.6;

contract NounsDAOEvents {
    /// @notice An event emitted when a new proposal is created
    event ProposalCreated(
        uint256 id,
        address proposer,
        address[] targets,
        uint256[] values,
        string[] signatures,
        bytes[] calldatas,
        uint256 startBlock,
        uint256 endBlock,
        string description
    );

    event ProposalCreatedWithRequirements(
        uint256 id,
        address proposer,
        address[] targets,
        uint256[] values,
        string[] signatures,
        bytes[] calldatas,
        uint256 startBlock,
        uint256 endBlock,
        uint256 proposalThreshold,
        uint256 quorumVotes,
        string description
    );

    /// @notice An event emitted when a vote has been cast on a proposal
    /// @param voter The address which casted a vote
    /// @param proposalId The proposal id which was voted on
    /// @param support Support value for the vote. 0=against, 1=for, 2=abstain
    /// @param votes Number of votes which were cast by the voter
    /// @param reason The reason given for the vote by the voter
    event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 votes, string reason);

    /// @notice An event emitted when a proposal has been canceled
    event ProposalCanceled(uint256 id);

    /// @notice An event emitted when a proposal has been queued in the NounsDAOExecutor
    event ProposalQueued(uint256 id, uint256 eta);

    /// @notice An event emitted when a proposal has been executed in the NounsDAOExecutor
    event ProposalExecuted(uint256 id);

    /// @notice An event emitted when a proposal has been vetoed by vetoAddress
    event ProposalVetoed(uint256 id);

    /// @notice An event emitted when the voting delay is set
    event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);

    /// @notice An event emitted when the voting period is set
    event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);

    /// @notice Emitted when implementation is changed
    event NewImplementation(address oldImplementation, address newImplementation);

    /// @notice Emitted when proposal threshold basis points is set
    event ProposalThresholdBPSSet(uint256 oldProposalThresholdBPS, uint256 newProposalThresholdBPS);

    /// @notice Emitted when quorum votes basis points is set
    event QuorumVotesBPSSet(uint256 oldQuorumVotesBPS, uint256 newQuorumVotesBPS);

    /// @notice Emitted when pendingAdmin is changed
    event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);

    /// @notice Emitted when pendingAdmin is accepted, which means admin is updated
    event NewAdmin(address oldAdmin, address newAdmin);

    /// @notice Emitted when vetoer is changed
    event NewVetoer(address oldVetoer, address newVetoer);
}

contract NounsDAOProxyStorage {
    /// @notice Administrator for this contract
    address public admin;

    /// @notice Pending administrator for this contract
    address public pendingAdmin;

    /// @notice Active brains of Governor
    address public implementation;
}

/**
 * @title Storage for Governor Bravo Delegate
 * @notice For future upgrades, do not change NounsDAOStorageV1. Create a new
 * contract which implements NounsDAOStorageV1 and following the naming convention
 * NounsDAOStorageVX.
 */
contract NounsDAOStorageV1 is NounsDAOProxyStorage {
    /// @notice Vetoer who has the ability to veto any proposal
    address public vetoer;

    /// @notice The delay before voting on a proposal may take place, once proposed, in blocks
    uint256 public votingDelay;

    /// @notice The duration of voting on a proposal, in blocks
    uint256 public votingPeriod;

    /// @notice The basis point number of votes required in order for a voter to become a proposer. *DIFFERS from GovernerBravo
    uint256 public proposalThresholdBPS;

    /// @notice The basis point number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed. *DIFFERS from GovernerBravo
    uint256 public quorumVotesBPS;

    /// @notice The total number of proposals
    uint256 public proposalCount;

    /// @notice The address of the Nouns DAO Executor NounsDAOExecutor
    INounsDAOExecutor public timelock;

    /// @notice The address of the Nouns tokens
    NounsTokenLike public nouns;

    /// @notice The official record of all proposals ever proposed
    mapping(uint256 => Proposal) public proposals;

    /// @notice The latest proposal for each proposer
    mapping(address => uint256) public latestProposalIds;

    struct Proposal {
        /// @notice Unique id for looking up a proposal
        uint256 id;
        /// @notice Creator of the proposal
        address proposer;
        /// @notice The number of votes needed to create a proposal at the time of proposal creation. *DIFFERS from GovernerBravo
        uint256 proposalThreshold;
        /// @notice The number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed at the time of proposal creation. *DIFFERS from GovernerBravo
        uint256 quorumVotes;
        /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds
        uint256 eta;
        /// @notice the ordered list of target addresses for calls to be made
        address[] targets;
        /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made
        uint256[] values;
        /// @notice The ordered list of function signatures to be called
        string[] signatures;
        /// @notice The ordered list of calldata to be passed to each call
        bytes[] calldatas;
        /// @notice The block at which voting begins: holders must delegate their votes prior to this block
        uint256 startBlock;
        /// @notice The block at which voting ends: votes must be cast prior to this block
        uint256 endBlock;
        /// @notice Current number of votes in favor of this proposal
        uint256 forVotes;
        /// @notice Current number of votes in opposition to this proposal
        uint256 againstVotes;
        /// @notice Current number of votes for abstaining for this proposal
        uint256 abstainVotes;
        /// @notice Flag marking whether the proposal has been canceled
        bool canceled;
        /// @notice Flag marking whether the proposal has been vetoed
        bool vetoed;
        /// @notice Flag marking whether the proposal has been executed
        bool executed;
        /// @notice Receipts of ballots for the entire set of voters
        mapping(address => Receipt) receipts;
    }

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

    /// @notice Possible states that a proposal may be in
    enum ProposalState {
        Pending,
        Active,
        Canceled,
        Defeated,
        Succeeded,
        Queued,
        Expired,
        Executed,
        Vetoed
    }
}

interface INounsDAOExecutor {
    function delay() external view returns (uint256);

    function GRACE_PERIOD() external view returns (uint256);

    function acceptAdmin() external;

    function queuedTransactions(bytes32 hash) external view returns (bool);

    function queueTransaction(
        address target,
        uint256 value,
        string calldata signature,
        bytes calldata data,
        uint256 eta
    ) external returns (bytes32);

    function cancelTransaction(
        address target,
        uint256 value,
        string calldata signature,
        bytes calldata data,
        uint256 eta
    ) external;

    function executeTransaction(
        address target,
        uint256 value,
        string calldata signature,
        bytes calldata data,
        uint256 eta
    ) external payable returns (bytes memory);
}

interface NounsTokenLike {
    function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96);

    function totalSupply() external view returns (uint96);
}
 < 

NounsDAOLogicV1 ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":false,"internalType":"address","name":"newImplementation","type":"address"}],"name":"NewImplementation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"NewPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldVetoer","type":"address"},{"indexed":false,"internalType":"address","name":"newVetoer","type":"address"}],"name":"NewVetoer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"ProposalCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"proposer","type":"address"},{"indexed":false,"internalType":"address[]","name":"targets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"},{"indexed":false,"internalType":"string[]","name":"signatures","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"indexed":false,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endBlock","type":"uint256"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"proposer","type":"address"},{"indexed":false,"internalType":"address[]","name":"targets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"},{"indexed":false,"internalType":"string[]","name":"signatures","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"indexed":false,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"proposalThreshold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quorumVotes","type":"uint256"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ProposalCreatedWithRequirements","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"eta","type":"uint256"}],"name":"ProposalQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldProposalThresholdBPS","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newProposalThresholdBPS","type":"uint256"}],"name":"ProposalThresholdBPSSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"ProposalVetoed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldQuorumVotesBPS","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorumVotesBPS","type":"uint256"}],"name":"QuorumVotesBPSSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"support","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"votes","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"VoteCast","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldVotingDelay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVotingDelay","type":"uint256"}],"name":"VotingDelaySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldVotingPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVotingPeriod","type":"uint256"}],"name":"VotingPeriodSet","type":"event"},{"inputs":[],"name":"BALLOT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PROPOSAL_THRESHOLD_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_QUORUM_VOTES_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VOTING_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VOTING_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_PROPOSAL_THRESHOLD_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_QUORUM_VOTES_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_VOTING_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_VOTING_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"_burnVetoPower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"_setPendingAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newProposalThresholdBPS","type":"uint256"}],"name":"_setProposalThresholdBPS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newQuorumVotesBPS","type":"uint256"}],"name":"_setQuorumVotesBPS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newVetoer","type":"address"}],"name":"_setVetoer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newVotingDelay","type":"uint256"}],"name":"_setVotingDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newVotingPeriod","type":"uint256"}],"name":"_setVotingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"}],"name":"castVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"castVoteBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"}],"name":"castVoteWithReason","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"getActions","outputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"string[]","name":"signatures","type":"string[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"}],"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":"uint8","name":"support","type":"uint8"},{"internalType":"uint96","name":"votes","type":"uint96"}],"internalType":"struct NounsDAOStorageV1.Receipt","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"timelock_","type":"address"},{"internalType":"address","name":"nouns_","type":"address"},{"internalType":"address","name":"vetoer_","type":"address"},{"internalType":"uint256","name":"votingPeriod_","type":"uint256"},{"internalType":"uint256","name":"votingDelay_","type":"uint256"},{"internalType":"uint256","name":"proposalThresholdBPS_","type":"uint256"},{"internalType":"uint256","name":"quorumVotesBPS_","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"latestProposalIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nouns","outputs":[{"internalType":"contract NounsTokenLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalMaxOperations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalThresholdBPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposals","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposer","type":"address"},{"internalType":"uint256","name":"proposalThreshold","type":"uint256"},{"internalType":"uint256","name":"quorumVotes","type":"uint256"},{"internalType":"uint256","name":"eta","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"uint256","name":"forVotes","type":"uint256"},{"internalType":"uint256","name":"againstVotes","type":"uint256"},{"internalType":"uint256","name":"abstainVotes","type":"uint256"},{"internalType":"bool","name":"canceled","type":"bool"},{"internalType":"bool","name":"vetoed","type":"bool"},{"internalType":"bool","name":"executed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"string[]","name":"signatures","type":"string[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"string","name":"description","type":"string"}],"name":"propose","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"queue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"quorumVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quorumVotesBPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"state","outputs":[{"internalType":"enum NounsDAOStorageV1.ProposalState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timelock","outputs":[{"internalType":"contract INounsDAOExecutor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"veto","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vetoer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":false,"internalType":"address","name":"newImplementation","type":"address"}],"name":"NewImplementation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"NewPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldVetoer","type":"address"},{"indexed":false,"internalType":"address","name":"newVetoer","type":"address"}],"name":"NewVetoer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"ProposalCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"proposer","type":"address"},{"indexed":false,"internalType":"address[]","name":"targets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"},{"indexed":false,"internalType":"string[]","name":"signatures","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"indexed":false,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endBlock","type":"uint256"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"proposer","type":"address"},{"indexed":false,"internalType":"address[]","name":"targets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"},{"indexed":false,"internalType":"string[]","name":"signatures","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"indexed":false,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"proposalThreshold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quorumVotes","type":"uint256"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ProposalCreatedWithRequirements","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"eta","type":"uint256"}],"name":"ProposalQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldProposalThresholdBPS","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newProposalThresholdBPS","type":"uint256"}],"name":"ProposalThresholdBPSSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"ProposalVetoed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldQuorumVotesBPS","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorumVotesBPS","type":"uint256"}],"name":"QuorumVotesBPSSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"support","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"votes","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"VoteCast","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldVotingDelay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVotingDelay","type":"uint256"}],"name":"VotingDelaySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldVotingPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVotingPeriod","type":"uint256"}],"name":"VotingPeriodSet","type":"event"},{"inputs":[],"name":"BALLOT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PROPOSAL_THRESHOLD_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_QUORUM_VOTES_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VOTING_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VOTING_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_PROPOSAL_THRESHOLD_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_QUORUM_VOTES_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_VOTING_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_VOTING_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"_burnVetoPower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"_setPendingAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newProposalThresholdBPS","type":"uint256"}],"name":"_setProposalThresholdBPS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newQuorumVotesBPS","type":"uint256"}],"name":"_setQuorumVotesBPS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newVetoer","type":"address"}],"name":"_setVetoer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newVotingDelay","type":"uint256"}],"name":"_setVotingDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newVotingPeriod","type":"uint256"}],"name":"_setVotingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"}],"name":"castVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"castVoteBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"},{"internalType":"string","name":"reason","type":"string"}],"name":"castVoteWithReason","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"getActions","outputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"string[]","name":"signatures","type":"string[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"}],"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":"uint8","name":"support","type":"uint8"},{"internalType":"uint96","name":"votes","type":"uint96"}],"internalType":"struct NounsDAOStorageV1.Receipt","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"timelock_","type":"address"},{"internalType":"address","name":"nouns_","type":"address"},{"internalType":"address","name":"vetoer_","type":"address"},{"internalType":"uint256","name":"votingPeriod_","type":"uint256"},{"internalType":"uint256","name":"votingDelay_","type":"uint256"},{"internalType":"uint256","name":"proposalThresholdBPS_","type":"uint256"},{"internalType":"uint256","name":"quorumVotesBPS_","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"latestProposalIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nouns","outputs":[{"internalType":"contract NounsTokenLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalMaxOperations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalThresholdBPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposals","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposer","type":"address"},{"internalType":"uint256","name":"proposalThreshold","type":"uint256"},{"internalType":"uint256","name":"quorumVotes","type":"uint256"},{"internalType":"uint256","name":"eta","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"uint256","name":"forVotes","type":"uint256"},{"internalType":"uint256","name":"againstVotes","type":"uint256"},{"internalType":"uint256","name":"abstainVotes","type":"uint256"},{"internalType":"bool","name":"canceled","type":"bool"},{"internalType":"bool","name":"vetoed","type":"bool"},{"internalType":"bool","name":"executed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"string[]","name":"signatures","type":"string[]"},{"internalType":"bytes[]","name":"calldatas","type":"bytes[]"},{"internalType":"string","name":"description","type":"string"}],"name":"propose","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"queue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"quorumVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quorumVotesBPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"state","outputs":[{"internalType":"enum NounsDAOStorageV1.ProposalState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timelock","outputs":[{"internalType":"contract INounsDAOExecutor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"veto","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vetoer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

NounsDAOLogicV1 Bytecode

608060405234801561001057600080fd5b506147b3806100206000396000f3fe608060405234801561001057600080fd5b50600436106103155760003560e01c80636f3eff28116101a7578063c82fbd08116100ee578063deaaa7cc11610097578063e9c714f211610071578063e9c714f2146107f2578063f851a440146107fa578063fe0d94c11461080d57600080fd5b8063deaaa7cc14610704578063e23a9a521461072b578063e48083fe146106a757600080fd5b8063da35c664116100c8578063da35c664146106d5578063da95691a146106de578063ddf0b009146106f157600080fd5b8063c82fbd08146106a7578063d33219b4146106af578063d8bff440146106c257600080fd5b8063a64e024a11610150578063b71d1a0c1161012a578063b71d1a0c14610683578063bb67758214610696578063bf7a29631461069f57600080fd5b8063a64e024a14610668578063b112626314610672578063b58131b01461067b57600080fd5b806383cce0e11161018157806383cce0e11461063957806396300b7d1461064257806397d048e51461065557600080fd5b80636f3eff281461060b5780637b3c71d31461061e5780637bdbe4d01461063157600080fd5b80632230e1551161026b5780633932abb11161021457806340e58ee5116101ee57806340e58ee5146105d257806356781388146105e55780635c60da1b146105f857600080fd5b80633932abb1146105965780633bccf4fd1461059f5780633e4f49e6146105b257600080fd5b80632b4656c8116102455780632b4656c81461054d5780632de45f1814610560578063328dd9821461057357600080fd5b80632230e1551461051257806324bc1a641461051a578063267822471461052257600080fd5b806317977c61116102cd5780631e7b5d3a116102a75780631e7b5d3a146104d957806320606b70146104e2578063215809ca1461050957600080fd5b806317977c61146104935780631d28dec7146104b35780631dfb1b5a146104c657600080fd5b806306fdde03116102fe57806306fdde031461042c5780630ea2d98c1461047557806314a67ea41461048a57600080fd5b8063013cf08b1461031a57806302a251a314610415575b600080fd5b6103a0610328366004613eea565b600b602081905260009182526040909120805460018201546002830154600384015460048501546009860154600a87015497870154600c880154600d890154600e9099015497996001600160a01b039097169895979496939592949192909160ff80821691610100810482169162010000909104168d565b604080519d8e526001600160a01b03909c1660208e01529a8c019990995260608b019790975260808a019590955260a089019390935260c088019190915260e08701526101008601526101208501521515610140840152151561016083015215156101808201526101a0015b60405180910390f35b61041e60055481565b60405190815260200161040c565b6104686040518060400160405280600981526020017f4e6f756e732044414f000000000000000000000000000000000000000000000081525081565b60405161040c9190614342565b610488610483366004613eea565b610820565b005b61041e60065481565b61041e6104a1366004613ce3565b600c6020526000908152604090205481565b6104886104c1366004613eea565b610972565b6104886104d4366004613eea565b610c62565b61041e6103e881565b61041e7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b61041e61168081565b61041e60c881565b61041e610da5565b600154610535906001600160a01b031681565b6040516001600160a01b03909116815260200161040c565b61048861055b366004613cfe565b610e4b565b600a54610535906001600160a01b031681565b610586610581366004613eea565b61138c565b60405161040c94939291906142a9565b61041e60045481565b6104886105ad366004613fd9565b61161d565b6105c56105c0366004613eea565b6118ce565b60405161040c9190614301565b6104886105e0366004613eea565b611abb565b6104886105f3366004613f2f565b611e2c565b600254610535906001600160a01b031681565b610488610619366004613eea565b611e9c565b61048861062c366004613f52565b611fdf565b61041e600a81565b61041e60075481565b610488610650366004613ce3565b61202f565b610488610663366004613eea565b612130565b61041e62013b0081565b61041e619d8081565b61041e612273565b610488610691366004613ce3565b6122c9565b61041e6107d081565b6104886123bb565b61041e600181565b600954610535906001600160a01b031681565b600354610535906001600160a01b031681565b61041e60085481565b61041e6106ec366004613d66565b612447565b6104886106ff366004613eea565b612b87565b61041e7f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b6107bd610739366004613f03565b6040805160608101825260008082526020820181905291810191909152506000918252600b602090815260408084206001600160a01b03939093168452600f9092018152918190208151606081018352905460ff8082161515835261010082041693820193909352620100009092046bffffffffffffffffffffffff169082015290565b6040805182511515815260208084015160ff1690820152918101516bffffffffffffffffffffffff169082015260600161040c565b610488612ed3565b600054610535906001600160a01b031681565b61048861081b366004613eea565b613024565b6000546001600160a01b031633146108a55760405162461bcd60e51b815260206004820152602660248201527f4e6f756e7344414f3a3a5f736574566f74696e67506572696f643a2061646d6960448201527f6e206f6e6c79000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61168081101580156108ba575062013b008111155b61092c5760405162461bcd60e51b815260206004820152603160248201527f4e6f756e7344414f3a3a5f736574566f74696e67506572696f643a20696e766160448201527f6c696420766f74696e6720706572696f64000000000000000000000000000000606482015260840161089c565b600580549082905560408051828152602081018490527f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e882891015b60405180910390a15050565b6003546001600160a01b03166109f05760405162461bcd60e51b815260206004820152602160248201527f4e6f756e7344414f3a3a7665746f3a207665746f20706f776572206275726e6560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015260840161089c565b6003546001600160a01b03163314610a4a5760405162461bcd60e51b815260206004820152601b60248201527f4e6f756e7344414f3a3a7665746f3a206f6e6c79207665746f65720000000000604482015260640161089c565b6007610a55826118ce565b6008811115610a6657610a666146f0565b1415610ada5760405162461bcd60e51b815260206004820152602d60248201527f4e6f756e7344414f3a3a7665746f3a2063616e6e6f74207665746f206578656360448201527f757465642070726f706f73616c00000000000000000000000000000000000000606482015260840161089c565b6000818152600b60205260408120600e810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055905b6005820154811015610c31576009546005830180546001600160a01b039092169163591fcdfe919084908110610b5057610b5061471f565b6000918252602090912001546006850180546001600160a01b039092169185908110610b7e57610b7e61471f565b9060005260206000200154856007018581548110610b9e57610b9e61471f565b90600052602060002001866008018681548110610bbd57610bbd61471f565b9060005260206000200187600401546040518663ffffffff1660e01b8152600401610bec95949392919061426f565b600060405180830381600087803b158015610c0657600080fd5b505af1158015610c1a573d6000803e3d6000fd5b505050508080610c2990614688565b915050610b18565b506040518281527fde0cea2a3a0097cc3d981d40c375407760e85bc9c5e69aea449ac3885f8615c690602001610966565b6000546001600160a01b03163314610ce25760405162461bcd60e51b815260206004820152602560248201527f4e6f756e7344414f3a3a5f736574566f74696e6744656c61793a2061646d696e60448201527f206f6e6c79000000000000000000000000000000000000000000000000000000606482015260840161089c565b60018110158015610cf55750619d808111155b610d675760405162461bcd60e51b815260206004820152602f60248201527f4e6f756e7344414f3a3a5f736574566f74696e6744656c61793a20696e76616c60448201527f696420766f74696e672064656c61790000000000000000000000000000000000606482015260840161089c565b600480549082905560408051828152602081018490527fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a939101610966565b6000610e46600754600a60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610dfb57600080fd5b505afa158015610e0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e339190614027565b6bffffffffffffffffffffffff16613262565b905090565b6009546001600160a01b031615610eca5760405162461bcd60e51b815260206004820152602e60248201527f4e6f756e7344414f3a3a696e697469616c697a653a2063616e206f6e6c79206960448201527f6e697469616c697a65206f6e6365000000000000000000000000000000000000606482015260840161089c565b6000546001600160a01b03163314610f245760405162461bcd60e51b815260206004820181905260248201527f4e6f756e7344414f3a3a696e697469616c697a653a2061646d696e206f6e6c79604482015260640161089c565b6001600160a01b038716610fa05760405162461bcd60e51b815260206004820152602e60248201527f4e6f756e7344414f3a3a696e697469616c697a653a20696e76616c696420746960448201527f6d656c6f636b2061646472657373000000000000000000000000000000000000606482015260840161089c565b6001600160a01b03861661101c5760405162461bcd60e51b815260206004820152602b60248201527f4e6f756e7344414f3a3a696e697469616c697a653a20696e76616c6964206e6f60448201527f756e732061646472657373000000000000000000000000000000000000000000606482015260840161089c565b6116808410158015611031575062013b008411155b6110a35760405162461bcd60e51b815260206004820152602b60248201527f4e6f756e7344414f3a3a696e697469616c697a653a20696e76616c696420766f60448201527f74696e6720706572696f64000000000000000000000000000000000000000000606482015260840161089c565b600183101580156110b65750619d808311155b6111285760405162461bcd60e51b815260206004820152602a60248201527f4e6f756e7344414f3a3a696e697469616c697a653a20696e76616c696420766f60448201527f74696e672064656c617900000000000000000000000000000000000000000000606482015260840161089c565b6001821015801561113b57506103e88211155b6111ad5760405162461bcd60e51b815260206004820152603060248201527f4e6f756e7344414f3a3a696e697469616c697a653a20696e76616c696420707260448201527f6f706f73616c207468726573686f6c6400000000000000000000000000000000606482015260840161089c565b60c881101580156111c057506107d08111155b6112325760405162461bcd60e51b815260206004820152603060248201527f4e6f756e7344414f3a3a696e697469616c697a653a20696e76616c696420707260448201527f6f706f73616c207468726573686f6c6400000000000000000000000000000000606482015260840161089c565b60055460408051918252602082018690527f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e8828910160405180910390a160045460408051918252602082018590527fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a93910160405180910390a160065460408051918252602082018490527ffc216faa269bf440fb06aa490693f409461bde9cdcb949c7b9f2cb79589e7a58910160405180910390a160075460408051918252602082018390527fd73ab1b53ca7a080713bcecd1a0acb2066a6a6c3d2fd6d78b67ae5005e652d9b910160405180910390a1600980547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03998a1617909155600a8054821697891697909717909655600380549096169490961693909317909355600555600491909155600655600755565b6060806060806000600b60008781526020019081526020016000209050806005018160060182600701836008018380548060200260200160405190810160405280929190818152602001828054801561140e57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116113f0575b505050505093508280548060200260200160405190810160405280929190818152602001828054801561146057602002820191906000526020600020905b81548152602001906001019080831161144c575b5050505050925081805480602002602001604051908101604052809291908181526020016000905b828210156115345783829060005260206000200180546114a79061463a565b80601f01602080910402602001604051908101604052809291908181526020018280546114d39061463a565b80156115205780601f106114f557610100808354040283529160200191611520565b820191906000526020600020905b81548152906001019060200180831161150357829003601f168201915b505050505081526020019060010190611488565b50505050915080805480602002602001604051908101604052809291908181526020016000905b8282101561160757838290600052602060002001805461157a9061463a565b80601f01602080910402602001604051908101604052809291908181526020018280546115a69061463a565b80156115f35780601f106115c8576101008083540402835291602001916115f3565b820191906000526020600020905b8154815290600101906020018083116115d657829003601f168201915b50505050508152602001906001019061155b565b5050505090509450945094509450509193509193565b604080518082018252600981527f4e6f756e732044414f000000000000000000000000000000000000000000000060209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fe1dd93b3612547b4bb7c3d429f3df8508d84f5a4f63b5e2e44340b94698e6b3b81840152466060820152306080808301919091528351808303909101815260a0820184528051908301207f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f60c083015260e0820189905260ff881661010080840191909152845180840390910181526101208301909452835193909201929092207f19010000000000000000000000000000000000000000000000000000000000006101408401526101428301829052610162830181905290916000906101820160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa1580156117c5573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661184e5760405162461bcd60e51b815260206004820152602a60248201527f4e6f756e7344414f3a3a63617374566f746542795369673a20696e76616c696460448201527f207369676e617475726500000000000000000000000000000000000000000000606482015260840161089c565b806001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda48a8a611886858e8e613282565b6040805193845260ff90921660208401526bffffffffffffffffffffffff169082015260806060820181905260009082015260a00160405180910390a2505050505050505050565b60008160085410156119475760405162461bcd60e51b8152602060048201526024808201527f4e6f756e7344414f3a3a73746174653a20696e76616c69642070726f706f736160448201527f6c20696400000000000000000000000000000000000000000000000000000000606482015260840161089c565b6000828152600b60205260409020600e810154610100900460ff16156119705750600892915050565b600e81015460ff16156119865750600292915050565b8060090154431161199a5750600092915050565b80600a015443116119ae5750600192915050565b80600c015481600b01541115806119cc5750806003015481600b0154105b156119da5750600392915050565b60048101546119ec5750600492915050565b600e81015462010000900460ff1615611a085750600792915050565b600960009054906101000a90046001600160a01b03166001600160a01b031663c1a287e26040518163ffffffff1660e01b815260040160206040518083038186803b158015611a5657600080fd5b505afa158015611a6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8e9190613e5a565b8160040154611a9d9190614563565b4210611aac5750600692915050565b50600592915050565b50919050565b6007611ac6826118ce565b6008811115611ad757611ad76146f0565b1415611b4b5760405162461bcd60e51b815260206004820152603160248201527f4e6f756e7344414f3a3a63616e63656c3a2063616e6e6f742063616e63656c2060448201527f65786563757465642070726f706f73616c000000000000000000000000000000606482015260840161089c565b6000818152600b6020526040902060018101546001600160a01b0316331480611c4057506002810154600a546001808401546001600160a01b039283169263782d6fe192911690611b9c90436145f3565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039092166004830152602482015260440160206040518083038186803b158015611bf857600080fd5b505afa158015611c0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c309190614027565b6bffffffffffffffffffffffff16105b611cb25760405162461bcd60e51b815260206004820152602a60248201527f4e6f756e7344414f3a3a63616e63656c3a2070726f706f7365722061626f766560448201527f207468726573686f6c6400000000000000000000000000000000000000000000606482015260840161089c565b600e810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560005b6005820154811015611dfb576009546005830180546001600160a01b039092169163591fcdfe919084908110611d1a57611d1a61471f565b6000918252602090912001546006850180546001600160a01b039092169185908110611d4857611d4861471f565b9060005260206000200154856007018581548110611d6857611d6861471f565b90600052602060002001866008018681548110611d8757611d8761471f565b9060005260206000200187600401546040518663ffffffff1660e01b8152600401611db695949392919061426f565b600060405180830381600087803b158015611dd057600080fd5b505af1158015611de4573d6000803e3d6000fd5b505050508080611df390614688565b915050611ce2565b506040518281527f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c90602001610966565b337fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda48383611e5b848383613282565b6040805193845260ff90921660208401526bffffffffffffffffffffffff169082015260806060820181905260009082015260a00160405180910390a25050565b6000546001600160a01b03163314611f1c5760405162461bcd60e51b815260206004820152602860248201527f4e6f756e7344414f3a3a5f73657451756f72756d566f7465734250533a20616460448201527f6d696e206f6e6c79000000000000000000000000000000000000000000000000606482015260840161089c565b60c88110158015611f2f57506107d08111155b611fa15760405162461bcd60e51b815260206004820152603b60248201527f4e6f756e7344414f3a3a5f73657450726f706f73616c5468726573686f6c643a60448201527f20696e76616c69642070726f706f73616c207468726573686f6c640000000000606482015260840161089c565b600780549082905560408051828152602081018490527fd73ab1b53ca7a080713bcecd1a0acb2066a6a6c3d2fd6d78b67ae5005e652d9b9101610966565b337fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4858561200e848383613282565b8686604051612021959493929190614491565b60405180910390a250505050565b6003546001600160a01b031633146120af5760405162461bcd60e51b815260206004820152602160248201527f4e6f756e7344414f3a3a5f7365745665746f65723a207665746f6572206f6e6c60448201527f7900000000000000000000000000000000000000000000000000000000000000606482015260840161089c565b600354604080516001600160a01b03928316815291831660208301527fc5644f3588a066b15dcf6b636b74aadca57cfaccf608d9de7d8786364b7a8d02910160405180910390a1600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000546001600160a01b031633146121b05760405162461bcd60e51b815260206004820152602e60248201527f4e6f756e7344414f3a3a5f73657450726f706f73616c5468726573686f6c644260448201527f50533a2061646d696e206f6e6c79000000000000000000000000000000000000606482015260840161089c565b600181101580156121c357506103e88111155b6122355760405162461bcd60e51b815260206004820152603b60248201527f4e6f756e7344414f3a3a5f73657450726f706f73616c5468726573686f6c643a60448201527f20696e76616c69642070726f706f73616c207468726573686f6c640000000000606482015260840161089c565b600680549082905560408051828152602081018490527ffc216faa269bf440fb06aa490693f409461bde9cdcb949c7b9f2cb79589e7a589101610966565b6000610e46600654600a60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610dfb57600080fd5b6000546001600160a01b031633146123495760405162461bcd60e51b815260206004820152602660248201527f4e6f756e7344414f3a3a5f73657450656e64696e6741646d696e3a2061646d6960448201527f6e206f6e6c790000000000000000000000000000000000000000000000000000606482015260840161089c565b600180546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101610966565b6003546001600160a01b0316331461243b5760405162461bcd60e51b815260206004820152602560248201527f4e6f756e7344414f3a3a5f6275726e5665746f506f7765723a207665746f657260448201527f206f6e6c79000000000000000000000000000000000000000000000000000000606482015260840161089c565b612445600061202f565b565b600061247b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b600a60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156124c957600080fd5b505afa1580156124dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125019190614027565b6bffffffffffffffffffffffff1680825260065461251e91613262565b60208201819052600a546001600160a01b031663782d6fe1336125426001436145f3565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039092166004830152602482015260440160206040518083038186803b15801561259e57600080fd5b505afa1580156125b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d69190614027565b6bffffffffffffffffffffffff16116126575760405162461bcd60e51b815260206004820152603a60248201527f4e6f756e7344414f3a3a70726f706f73653a2070726f706f73657220766f746560448201527f732062656c6f772070726f706f73616c207468726573686f6c64000000000000606482015260840161089c565b85518751148015612669575084518751145b8015612676575083518751145b6126e85760405162461bcd60e51b815260206004820152603f60248201527f4e6f756e7344414f3a3a70726f706f73653a2070726f706f73616c2066756e6360448201527f74696f6e20696e666f726d6174696f6e206172697479206d69736d6174636800606482015260840161089c565b865161275c5760405162461bcd60e51b815260206004820152602760248201527f4e6f756e7344414f3a3a70726f706f73653a206d7573742070726f766964652060448201527f616374696f6e7300000000000000000000000000000000000000000000000000606482015260840161089c565b600a875111156127d45760405162461bcd60e51b815260206004820152602360248201527f4e6f756e7344414f3a3a70726f706f73653a20746f6f206d616e79206163746960448201527f6f6e730000000000000000000000000000000000000000000000000000000000606482015260840161089c565b336000908152600c602052604090819020549082018190521561296057600061280082604001516118ce565b90506001816008811115612816576128166146f0565b14156128b05760405162461bcd60e51b815260206004820152605360248201527f4e6f756e7344414f3a3a70726f706f73653a206f6e65206c6976652070726f7060448201527f6f73616c207065722070726f706f7365722c20666f756e6420616e20616c726560648201527f616479206163746976652070726f706f73616c00000000000000000000000000608482015260a40161089c565b60008160088111156128c4576128c46146f0565b141561295e5760405162461bcd60e51b815260206004820152605460248201527f4e6f756e7344414f3a3a70726f706f73653a206f6e65206c6976652070726f7060448201527f6f73616c207065722070726f706f7365722c20666f756e6420616e20616c726560648201527f6164792070656e64696e672070726f706f73616c000000000000000000000000608482015260a40161089c565b505b60045461296d9043614563565b6060820181905260055461298091614563565b60808201526008805490600061299583614688565b90915550506008546000818152600b602090815260409091209182556001820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055820151600282015560075482516129f49190613262565b6003820155600060048201558751612a1590600583019060208b01906137f1565b508651612a2b90600683019060208a019061386e565b508551612a4190600783019060208901906138a9565b508451612a579060088301906020880190613902565b506060820151600982019081556080830151600a83019081556000600b8401819055600c808501829055600d8501829055600e850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000169055845460018601546001600160a01b031683526020919091526040918290208190559254915490517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e093612b1493909233928e928e928e928e9291908e90614355565b60405180910390a17f6af0134faa0f9290c1d686d55012aca80302d31d5c856e4bc7954f7613dc7f878160000154338a8a8a8a876009015488600a015489600201548a600301548e604051612b739b9a999897969594939291906143eb565b60405180910390a154979650505050505050565b6004612b92826118ce565b6008811115612ba357612ba36146f0565b14612c165760405162461bcd60e51b815260206004820152603f60248201527f4e6f756e7344414f3a3a71756575653a2070726f706f73616c2063616e206f6e60448201527f6c79206265207175657565642069662069742069732073756363656564656400606482015260840161089c565b6000818152600b6020908152604080832060095482517f6a42b8f800000000000000000000000000000000000000000000000000000000815292519194936001600160a01b0390911692636a42b8f89260048083019392829003018186803b158015612c8157600080fd5b505afa158015612c95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb99190613e5a565b612cc39042614563565b905060005b6005830154811015612e8d57612e7b836005018281548110612cec57612cec61471f565b6000918252602090912001546006850180546001600160a01b039092169184908110612d1a57612d1a61471f565b9060005260206000200154856007018481548110612d3a57612d3a61471f565b906000526020600020018054612d4f9061463a565b80601f0160208091040260200160405190810160405280929190818152602001828054612d7b9061463a565b8015612dc85780601f10612d9d57610100808354040283529160200191612dc8565b820191906000526020600020905b815481529060010190602001808311612dab57829003601f168201915b5050505050866008018581548110612de257612de261471f565b906000526020600020018054612df79061463a565b80601f0160208091040260200160405190810160405280929190818152602001828054612e239061463a565b8015612e705780601f10612e4557610100808354040283529160200191612e70565b820191906000526020600020905b815481529060010190602001808311612e5357829003601f168201915b5050505050866135fb565b80612e8581614688565b915050612cc8565b506004820181905560408051848152602081018390527f9a2e42fd6722813d69113e7d0079d3d940171428df7373df9c7f7617cfda2892910160405180910390a1505050565b6001546001600160a01b031633148015612eec57503315155b612f5e5760405162461bcd60e51b815260206004820152602a60248201527f4e6f756e7344414f3a3a5f61636365707441646d696e3a2070656e64696e672060448201527f61646d696e206f6e6c7900000000000000000000000000000000000000000000606482015260840161089c565b60008054600180546001600160a01b038082167fffffffffffffffffffffffff000000000000000000000000000000000000000080861682179096559490911690915560408051919092168082526020820184905292917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc910160405180910390a1600154604080516001600160a01b03808516825290921660208301527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101610966565b600561302f826118ce565b6008811115613040576130406146f0565b146130b5576040805162461bcd60e51b81526020600482015260248101919091527f4e6f756e7344414f3a3a657865637574653a2070726f706f73616c2063616e2060448201527f6f6e6c7920626520657865637574656420696620697420697320717565756564606482015260840161089c565b6000818152600b60205260408120600e810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000179055905b6005820154811015613231576009546005830180546001600160a01b0390921691630825f38f91908490811061312c5761312c61471f565b6000918252602090912001546006850180546001600160a01b03909216918590811061315a5761315a61471f565b906000526020600020015485600701858154811061317a5761317a61471f565b906000526020600020018660080186815481106131995761319961471f565b9060005260206000200187600401546040518663ffffffff1660e01b81526004016131c895949392919061426f565b600060405180830381600087803b1580156131e257600080fd5b505af11580156131f6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261321e9190810190613e73565b508061322981614688565b9150506130f4565b506040518281527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f90602001610966565b600061271061327184846145b6565b61327b919061457b565b9392505050565b6000600161328f846118ce565b60088111156132a0576132a06146f0565b146133135760405162461bcd60e51b815260206004820152602c60248201527f4e6f756e7344414f3a3a63617374566f7465496e7465726e616c3a20766f746960448201527f6e6720697320636c6f7365640000000000000000000000000000000000000000606482015260840161089c565b60028260ff16111561338d5760405162461bcd60e51b815260206004820152602d60248201527f4e6f756e7344414f3a3a63617374566f7465496e7465726e616c3a20696e766160448201527f6c696420766f7465207479706500000000000000000000000000000000000000606482015260840161089c565b6000838152600b602090815260408083206001600160a01b0388168452600f8101909252909120805460ff161561342c5760405162461bcd60e51b815260206004820152602f60248201527f4e6f756e7344414f3a3a63617374566f7465496e7465726e616c3a20766f746560448201527f7220616c726561647920766f7465640000000000000000000000000000000000606482015260840161089c565b600a5460045460098401546000926001600160a01b03169163782d6fe1918a91613455916145f3565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039092166004830152602482015260440160206040518083038186803b1580156134b157600080fd5b505afa1580156134c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e99190614027565b905060ff851661351b57806bffffffffffffffffffffffff1683600c01546135119190614563565b600c84015561357f565b8460ff166001141561354f57806bffffffffffffffffffffffff1683600b01546135459190614563565b600b84015561357f565b8460ff166002141561357f57806bffffffffffffffffffffffff1683600d01546135799190614563565b600d8401555b81546bffffffffffffffffffffffff821662010000027fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff60ff8816610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009093169290921760011791909116179091559150509392505050565b6009546040516001600160a01b039091169063f2b06537906136299088908890889088908890602001614222565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161365d91815260200190565b60206040518083038186803b15801561367557600080fd5b505afa158015613689573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ad9190613e38565b156137465760405162461bcd60e51b815260206004820152605060248201527f4e6f756e7344414f3a3a71756575654f72526576657274496e7465726e616c3a60448201527f206964656e746963616c2070726f706f73616c20616374696f6e20616c72656160648201527f6479207175657565642061742065746100000000000000000000000000000000608482015260a40161089c565b6009546040517f3a66f9010000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690633a66f901906137979088908890889088908890600401614222565b602060405180830381600087803b1580156137b157600080fd5b505af11580156137c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137e99190613e5a565b505050505050565b82805482825590600052602060002090810192821561385e579160200282015b8281111561385e57825182547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909116178255602090920191600190910190613811565b5061386a92915061395b565b5090565b82805482825590600052602060002090810192821561385e579160200282015b8281111561385e57825182559160200191906001019061388e565b8280548282559060005260206000209081019282156138f6579160200282015b828111156138f657825180516138e6918491602090910190613970565b50916020019190600101906138c9565b5061386a9291506139e3565b82805482825590600052602060002090810192821561394f579160200282015b8281111561394f578251805161393f918491602090910190613970565b5091602001919060010190613922565b5061386a929150613a00565b5b8082111561386a576000815560010161395c565b82805461397c9061463a565b90600052602060002090601f01602090048101928261399e576000855561385e565b82601f106139b757805160ff191683800117855561385e565b8280016001018555821561385e579182018281111561385e57825182559160200191906001019061388e565b8082111561386a5760006139f78282613a1d565b506001016139e3565b8082111561386a576000613a148282613a1d565b50600101613a00565b508054613a299061463a565b6000825580601f10613a39575050565b601f016020900490600052602060002090810190613a57919061395b565b50565b6000613a6d613a688461453b565b6144e6565b9050828152838383011115613a8157600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b0381168114613aaf57600080fd5b919050565b600082601f830112613ac557600080fd5b81356020613ad5613a6883614517565b80838252828201915082860187848660051b8901011115613af557600080fd5b60005b85811015613b1b57613b0982613a98565b84529284019290840190600101613af8565b5090979650505050505050565b600082601f830112613b3957600080fd5b81356020613b49613a6883614517565b80838252828201915082860187848660051b8901011115613b6957600080fd5b60005b85811015613b1b57813567ffffffffffffffff811115613b8b57600080fd5b8801603f81018a13613b9c57600080fd5b613bad8a8783013560408401613a5a565b8552509284019290840190600101613b6c565b600082601f830112613bd157600080fd5b81356020613be1613a6883614517565b80838252828201915082860187848660051b8901011115613c0157600080fd5b6000805b86811015613c4457823567ffffffffffffffff811115613c23578283fd5b613c318b88838d0101613cb2565b8652509385019391850191600101613c05565b509198975050505050505050565b600082601f830112613c6357600080fd5b81356020613c73613a6883614517565b80838252828201915082860187848660051b8901011115613c9357600080fd5b60005b85811015613b1b57813584529284019290840190600101613c96565b600082601f830112613cc357600080fd5b61327b83833560208501613a5a565b803560ff81168114613aaf57600080fd5b600060208284031215613cf557600080fd5b61327b82613a98565b600080600080600080600060e0888a031215613d1957600080fd5b613d2288613a98565b9650613d3060208901613a98565b9550613d3e60408901613a98565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b600080600080600060a08688031215613d7e57600080fd5b853567ffffffffffffffff80821115613d9657600080fd5b613da289838a01613ab4565b96506020880135915080821115613db857600080fd5b613dc489838a01613c52565b95506040880135915080821115613dda57600080fd5b613de689838a01613bc0565b94506060880135915080821115613dfc57600080fd5b613e0889838a01613b28565b93506080880135915080821115613e1e57600080fd5b50613e2b88828901613cb2565b9150509295509295909350565b600060208284031215613e4a57600080fd5b8151801515811461327b57600080fd5b600060208284031215613e6c57600080fd5b5051919050565b600060208284031215613e8557600080fd5b815167ffffffffffffffff811115613e9c57600080fd5b8201601f81018413613ead57600080fd5b8051613ebb613a688261453b565b818152856020838501011115613ed057600080fd5b613ee182602083016020860161460a565b95945050505050565b600060208284031215613efc57600080fd5b5035919050565b60008060408385031215613f1657600080fd5b82359150613f2660208401613a98565b90509250929050565b60008060408385031215613f4257600080fd5b82359150613f2660208401613cd2565b60008060008060608587031215613f6857600080fd5b84359350613f7860208601613cd2565b9250604085013567ffffffffffffffff80821115613f9557600080fd5b818701915087601f830112613fa957600080fd5b813581811115613fb857600080fd5b886020828501011115613fca57600080fd5b95989497505060200194505050565b600080600080600060a08688031215613ff157600080fd5b8535945061400160208701613cd2565b935061400f60408701613cd2565b94979396509394606081013594506080013592915050565b60006020828403121561403957600080fd5b81516bffffffffffffffffffffffff8116811461327b57600080fd5b600081518084526020808501945080840160005b8381101561408e5781516001600160a01b031687529582019590820190600101614069565b509495945050505050565b600081518084526020808501808196508360051b8101915082860160005b858110156140e15782840389526140cf84835161411e565b988501989350908401906001016140b7565b5091979650505050505050565b600081518084526020808501945080840160005b8381101561408e57815187529582019590820190600101614102565b6000815180845261413681602086016020860161460a565b601f01601f19169290920160200192915050565b8054600090600181811c908083168061416457607f831692505b602080841082141561419f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8388528180156141b657600181146141e857614216565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616828a0152604089019650614216565b876000528160002060005b8681101561420e5781548b82018501529085019083016141f3565b8a0183019750505b50505050505092915050565b6001600160a01b038616815284602082015260a06040820152600061424a60a083018661411e565b828103606084015261425c818661411e565b9150508260808301529695505050505050565b6001600160a01b038616815284602082015260a06040820152600061429760a083018661414a565b828103606084015261425c818661414a565b6080815260006142bc6080830187614055565b82810360208401526142ce81876140ee565b905082810360408401526142e28186614099565b905082810360608401526142f68185614099565b979650505050505050565b602081016009831061433c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60208152600061327b602083018461411e565b60006101208b83526001600160a01b038b16602084015280604084015261437e8184018b614055565b90508281036060840152614392818a6140ee565b905082810360808401526143a68189614099565b905082810360a08401526143ba8188614099565b90508560c08401528460e08401528281036101008401526143db818561411e565b9c9b505050505050505050505050565b60006101608d83526001600160a01b038d1660208401528060408401526144148184018d614055565b90508281036060840152614428818c6140ee565b9050828103608084015261443c818b614099565b905082810360a0840152614450818a614099565b90508760c08401528660e0840152856101008401528461012084015282810361014084015261447f818561411e565b9e9d5050505050505050505050505050565b85815260ff851660208201526bffffffffffffffffffffffff8416604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b604051601f8201601f1916810167ffffffffffffffff8111828210171561450f5761450f61474e565b604052919050565b600067ffffffffffffffff8211156145315761453161474e565b5060051b60200190565b600067ffffffffffffffff8211156145555761455561474e565b50601f01601f191660200190565b60008219821115614576576145766146c1565b500190565b6000826145b1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156145ee576145ee6146c1565b500290565b600082821015614605576146056146c1565b500390565b60005b8381101561462557818101518382015260200161460d565b83811115614634576000848401525b50505050565b600181811c9082168061464e57607f821691505b60208210811415611ab5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156146ba576146ba6146c1565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea26469706673582212202d219bbd5982bc04b4820b819396c18d235e46dcc014201d58710c7b14362c2364736f6c63430008060033
608060405234801561001057600080fd5b506147b3806100206000396000f3fe608060405234801561001057600080fd5b50600436106103155760003560e01c80636f3eff28116101a7578063c82fbd08116100ee578063deaaa7cc11610097578063e9c714f211610071578063e9c714f2146107f2578063f851a440146107fa578063fe0d94c11461080d57600080fd5b8063deaaa7cc14610704578063e23a9a521461072b578063e48083fe146106a757600080fd5b8063da35c664116100c8578063da35c664146106d5578063da95691a146106de578063ddf0b009146106f157600080fd5b8063c82fbd08146106a7578063d33219b4146106af578063d8bff440146106c257600080fd5b8063a64e024a11610150578063b71d1a0c1161012a578063b71d1a0c14610683578063bb67758214610696578063bf7a29631461069f57600080fd5b8063a64e024a14610668578063b112626314610672578063b58131b01461067b57600080fd5b806383cce0e11161018157806383cce0e11461063957806396300b7d1461064257806397d048e51461065557600080fd5b80636f3eff281461060b5780637b3c71d31461061e5780637bdbe4d01461063157600080fd5b80632230e1551161026b5780633932abb11161021457806340e58ee5116101ee57806340e58ee5146105d257806356781388146105e55780635c60da1b146105f857600080fd5b80633932abb1146105965780633bccf4fd1461059f5780633e4f49e6146105b257600080fd5b80632b4656c8116102455780632b4656c81461054d5780632de45f1814610560578063328dd9821461057357600080fd5b80632230e1551461051257806324bc1a641461051a578063267822471461052257600080fd5b806317977c61116102cd5780631e7b5d3a116102a75780631e7b5d3a146104d957806320606b70146104e2578063215809ca1461050957600080fd5b806317977c61146104935780631d28dec7146104b35780631dfb1b5a146104c657600080fd5b806306fdde03116102fe57806306fdde031461042c5780630ea2d98c1461047557806314a67ea41461048a57600080fd5b8063013cf08b1461031a57806302a251a314610415575b600080fd5b6103a0610328366004613eea565b600b602081905260009182526040909120805460018201546002830154600384015460048501546009860154600a87015497870154600c880154600d890154600e9099015497996001600160a01b039097169895979496939592949192909160ff80821691610100810482169162010000909104168d565b604080519d8e526001600160a01b03909c1660208e01529a8c019990995260608b019790975260808a019590955260a089019390935260c088019190915260e08701526101008601526101208501521515610140840152151561016083015215156101808201526101a0015b60405180910390f35b61041e60055481565b60405190815260200161040c565b6104686040518060400160405280600981526020017f4e6f756e732044414f000000000000000000000000000000000000000000000081525081565b60405161040c9190614342565b610488610483366004613eea565b610820565b005b61041e60065481565b61041e6104a1366004613ce3565b600c6020526000908152604090205481565b6104886104c1366004613eea565b610972565b6104886104d4366004613eea565b610c62565b61041e6103e881565b61041e7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b61041e61168081565b61041e60c881565b61041e610da5565b600154610535906001600160a01b031681565b6040516001600160a01b03909116815260200161040c565b61048861055b366004613cfe565b610e4b565b600a54610535906001600160a01b031681565b610586610581366004613eea565b61138c565b60405161040c94939291906142a9565b61041e60045481565b6104886105ad366004613fd9565b61161d565b6105c56105c0366004613eea565b6118ce565b60405161040c9190614301565b6104886105e0366004613eea565b611abb565b6104886105f3366004613f2f565b611e2c565b600254610535906001600160a01b031681565b610488610619366004613eea565b611e9c565b61048861062c366004613f52565b611fdf565b61041e600a81565b61041e60075481565b610488610650366004613ce3565b61202f565b610488610663366004613eea565b612130565b61041e62013b0081565b61041e619d8081565b61041e612273565b610488610691366004613ce3565b6122c9565b61041e6107d081565b6104886123bb565b61041e600181565b600954610535906001600160a01b031681565b600354610535906001600160a01b031681565b61041e60085481565b61041e6106ec366004613d66565b612447565b6104886106ff366004613eea565b612b87565b61041e7f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b6107bd610739366004613f03565b6040805160608101825260008082526020820181905291810191909152506000918252600b602090815260408084206001600160a01b03939093168452600f9092018152918190208151606081018352905460ff8082161515835261010082041693820193909352620100009092046bffffffffffffffffffffffff169082015290565b6040805182511515815260208084015160ff1690820152918101516bffffffffffffffffffffffff169082015260600161040c565b610488612ed3565b600054610535906001600160a01b031681565b61048861081b366004613eea565b613024565b6000546001600160a01b031633146108a55760405162461bcd60e51b815260206004820152602660248201527f4e6f756e7344414f3a3a5f736574566f74696e67506572696f643a2061646d6960448201527f6e206f6e6c79000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61168081101580156108ba575062013b008111155b61092c5760405162461bcd60e51b815260206004820152603160248201527f4e6f756e7344414f3a3a5f736574566f74696e67506572696f643a20696e766160448201527f6c696420766f74696e6720706572696f64000000000000000000000000000000606482015260840161089c565b600580549082905560408051828152602081018490527f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e882891015b60405180910390a15050565b6003546001600160a01b03166109f05760405162461bcd60e51b815260206004820152602160248201527f4e6f756e7344414f3a3a7665746f3a207665746f20706f776572206275726e6560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015260840161089c565b6003546001600160a01b03163314610a4a5760405162461bcd60e51b815260206004820152601b60248201527f4e6f756e7344414f3a3a7665746f3a206f6e6c79207665746f65720000000000604482015260640161089c565b6007610a55826118ce565b6008811115610a6657610a666146f0565b1415610ada5760405162461bcd60e51b815260206004820152602d60248201527f4e6f756e7344414f3a3a7665746f3a2063616e6e6f74207665746f206578656360448201527f757465642070726f706f73616c00000000000000000000000000000000000000606482015260840161089c565b6000818152600b60205260408120600e810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055905b6005820154811015610c31576009546005830180546001600160a01b039092169163591fcdfe919084908110610b5057610b5061471f565b6000918252602090912001546006850180546001600160a01b039092169185908110610b7e57610b7e61471f565b9060005260206000200154856007018581548110610b9e57610b9e61471f565b90600052602060002001866008018681548110610bbd57610bbd61471f565b9060005260206000200187600401546040518663ffffffff1660e01b8152600401610bec95949392919061426f565b600060405180830381600087803b158015610c0657600080fd5b505af1158015610c1a573d6000803e3d6000fd5b505050508080610c2990614688565b915050610b18565b506040518281527fde0cea2a3a0097cc3d981d40c375407760e85bc9c5e69aea449ac3885f8615c690602001610966565b6000546001600160a01b03163314610ce25760405162461bcd60e51b815260206004820152602560248201527f4e6f756e7344414f3a3a5f736574566f74696e6744656c61793a2061646d696e60448201527f206f6e6c79000000000000000000000000000000000000000000000000000000606482015260840161089c565b60018110158015610cf55750619d808111155b610d675760405162461bcd60e51b815260206004820152602f60248201527f4e6f756e7344414f3a3a5f736574566f74696e6744656c61793a20696e76616c60448201527f696420766f74696e672064656c61790000000000000000000000000000000000606482015260840161089c565b600480549082905560408051828152602081018490527fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a939101610966565b6000610e46600754600a60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610dfb57600080fd5b505afa158015610e0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e339190614027565b6bffffffffffffffffffffffff16613262565b905090565b6009546001600160a01b031615610eca5760405162461bcd60e51b815260206004820152602e60248201527f4e6f756e7344414f3a3a696e697469616c697a653a2063616e206f6e6c79206960448201527f6e697469616c697a65206f6e6365000000000000000000000000000000000000606482015260840161089c565b6000546001600160a01b03163314610f245760405162461bcd60e51b815260206004820181905260248201527f4e6f756e7344414f3a3a696e697469616c697a653a2061646d696e206f6e6c79604482015260640161089c565b6001600160a01b038716610fa05760405162461bcd60e51b815260206004820152602e60248201527f4e6f756e7344414f3a3a696e697469616c697a653a20696e76616c696420746960448201527f6d656c6f636b2061646472657373000000000000000000000000000000000000606482015260840161089c565b6001600160a01b03861661101c5760405162461bcd60e51b815260206004820152602b60248201527f4e6f756e7344414f3a3a696e697469616c697a653a20696e76616c6964206e6f60448201527f756e732061646472657373000000000000000000000000000000000000000000606482015260840161089c565b6116808410158015611031575062013b008411155b6110a35760405162461bcd60e51b815260206004820152602b60248201527f4e6f756e7344414f3a3a696e697469616c697a653a20696e76616c696420766f60448201527f74696e6720706572696f64000000000000000000000000000000000000000000606482015260840161089c565b600183101580156110b65750619d808311155b6111285760405162461bcd60e51b815260206004820152602a60248201527f4e6f756e7344414f3a3a696e697469616c697a653a20696e76616c696420766f60448201527f74696e672064656c617900000000000000000000000000000000000000000000606482015260840161089c565b6001821015801561113b57506103e88211155b6111ad5760405162461bcd60e51b815260206004820152603060248201527f4e6f756e7344414f3a3a696e697469616c697a653a20696e76616c696420707260448201527f6f706f73616c207468726573686f6c6400000000000000000000000000000000606482015260840161089c565b60c881101580156111c057506107d08111155b6112325760405162461bcd60e51b815260206004820152603060248201527f4e6f756e7344414f3a3a696e697469616c697a653a20696e76616c696420707260448201527f6f706f73616c207468726573686f6c6400000000000000000000000000000000606482015260840161089c565b60055460408051918252602082018690527f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e8828910160405180910390a160045460408051918252602082018590527fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a93910160405180910390a160065460408051918252602082018490527ffc216faa269bf440fb06aa490693f409461bde9cdcb949c7b9f2cb79589e7a58910160405180910390a160075460408051918252602082018390527fd73ab1b53ca7a080713bcecd1a0acb2066a6a6c3d2fd6d78b67ae5005e652d9b910160405180910390a1600980547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03998a1617909155600a8054821697891697909717909655600380549096169490961693909317909355600555600491909155600655600755565b6060806060806000600b60008781526020019081526020016000209050806005018160060182600701836008018380548060200260200160405190810160405280929190818152602001828054801561140e57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116113f0575b505050505093508280548060200260200160405190810160405280929190818152602001828054801561146057602002820191906000526020600020905b81548152602001906001019080831161144c575b5050505050925081805480602002602001604051908101604052809291908181526020016000905b828210156115345783829060005260206000200180546114a79061463a565b80601f01602080910402602001604051908101604052809291908181526020018280546114d39061463a565b80156115205780601f106114f557610100808354040283529160200191611520565b820191906000526020600020905b81548152906001019060200180831161150357829003601f168201915b505050505081526020019060010190611488565b50505050915080805480602002602001604051908101604052809291908181526020016000905b8282101561160757838290600052602060002001805461157a9061463a565b80601f01602080910402602001604051908101604052809291908181526020018280546115a69061463a565b80156115f35780601f106115c8576101008083540402835291602001916115f3565b820191906000526020600020905b8154815290600101906020018083116115d657829003601f168201915b50505050508152602001906001019061155b565b5050505090509450945094509450509193509193565b604080518082018252600981527f4e6f756e732044414f000000000000000000000000000000000000000000000060209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fe1dd93b3612547b4bb7c3d429f3df8508d84f5a4f63b5e2e44340b94698e6b3b81840152466060820152306080808301919091528351808303909101815260a0820184528051908301207f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f60c083015260e0820189905260ff881661010080840191909152845180840390910181526101208301909452835193909201929092207f19010000000000000000000000000000000000000000000000000000000000006101408401526101428301829052610162830181905290916000906101820160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa1580156117c5573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661184e5760405162461bcd60e51b815260206004820152602a60248201527f4e6f756e7344414f3a3a63617374566f746542795369673a20696e76616c696460448201527f207369676e617475726500000000000000000000000000000000000000000000606482015260840161089c565b806001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda48a8a611886858e8e613282565b6040805193845260ff90921660208401526bffffffffffffffffffffffff169082015260806060820181905260009082015260a00160405180910390a2505050505050505050565b60008160085410156119475760405162461bcd60e51b8152602060048201526024808201527f4e6f756e7344414f3a3a73746174653a20696e76616c69642070726f706f736160448201527f6c20696400000000000000000000000000000000000000000000000000000000606482015260840161089c565b6000828152600b60205260409020600e810154610100900460ff16156119705750600892915050565b600e81015460ff16156119865750600292915050565b8060090154431161199a5750600092915050565b80600a015443116119ae5750600192915050565b80600c015481600b01541115806119cc5750806003015481600b0154105b156119da5750600392915050565b60048101546119ec5750600492915050565b600e81015462010000900460ff1615611a085750600792915050565b600960009054906101000a90046001600160a01b03166001600160a01b031663c1a287e26040518163ffffffff1660e01b815260040160206040518083038186803b158015611a5657600080fd5b505afa158015611a6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8e9190613e5a565b8160040154611a9d9190614563565b4210611aac5750600692915050565b50600592915050565b50919050565b6007611ac6826118ce565b6008811115611ad757611ad76146f0565b1415611b4b5760405162461bcd60e51b815260206004820152603160248201527f4e6f756e7344414f3a3a63616e63656c3a2063616e6e6f742063616e63656c2060448201527f65786563757465642070726f706f73616c000000000000000000000000000000606482015260840161089c565b6000818152600b6020526040902060018101546001600160a01b0316331480611c4057506002810154600a546001808401546001600160a01b039283169263782d6fe192911690611b9c90436145f3565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039092166004830152602482015260440160206040518083038186803b158015611bf857600080fd5b505afa158015611c0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c309190614027565b6bffffffffffffffffffffffff16105b611cb25760405162461bcd60e51b815260206004820152602a60248201527f4e6f756e7344414f3a3a63616e63656c3a2070726f706f7365722061626f766560448201527f207468726573686f6c6400000000000000000000000000000000000000000000606482015260840161089c565b600e810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560005b6005820154811015611dfb576009546005830180546001600160a01b039092169163591fcdfe919084908110611d1a57611d1a61471f565b6000918252602090912001546006850180546001600160a01b039092169185908110611d4857611d4861471f565b9060005260206000200154856007018581548110611d6857611d6861471f565b90600052602060002001866008018681548110611d8757611d8761471f565b9060005260206000200187600401546040518663ffffffff1660e01b8152600401611db695949392919061426f565b600060405180830381600087803b158015611dd057600080fd5b505af1158015611de4573d6000803e3d6000fd5b505050508080611df390614688565b915050611ce2565b506040518281527f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c90602001610966565b337fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda48383611e5b848383613282565b6040805193845260ff90921660208401526bffffffffffffffffffffffff169082015260806060820181905260009082015260a00160405180910390a25050565b6000546001600160a01b03163314611f1c5760405162461bcd60e51b815260206004820152602860248201527f4e6f756e7344414f3a3a5f73657451756f72756d566f7465734250533a20616460448201527f6d696e206f6e6c79000000000000000000000000000000000000000000000000606482015260840161089c565b60c88110158015611f2f57506107d08111155b611fa15760405162461bcd60e51b815260206004820152603b60248201527f4e6f756e7344414f3a3a5f73657450726f706f73616c5468726573686f6c643a60448201527f20696e76616c69642070726f706f73616c207468726573686f6c640000000000606482015260840161089c565b600780549082905560408051828152602081018490527fd73ab1b53ca7a080713bcecd1a0acb2066a6a6c3d2fd6d78b67ae5005e652d9b9101610966565b337fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4858561200e848383613282565b8686604051612021959493929190614491565b60405180910390a250505050565b6003546001600160a01b031633146120af5760405162461bcd60e51b815260206004820152602160248201527f4e6f756e7344414f3a3a5f7365745665746f65723a207665746f6572206f6e6c60448201527f7900000000000000000000000000000000000000000000000000000000000000606482015260840161089c565b600354604080516001600160a01b03928316815291831660208301527fc5644f3588a066b15dcf6b636b74aadca57cfaccf608d9de7d8786364b7a8d02910160405180910390a1600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000546001600160a01b031633146121b05760405162461bcd60e51b815260206004820152602e60248201527f4e6f756e7344414f3a3a5f73657450726f706f73616c5468726573686f6c644260448201527f50533a2061646d696e206f6e6c79000000000000000000000000000000000000606482015260840161089c565b600181101580156121c357506103e88111155b6122355760405162461bcd60e51b815260206004820152603b60248201527f4e6f756e7344414f3a3a5f73657450726f706f73616c5468726573686f6c643a60448201527f20696e76616c69642070726f706f73616c207468726573686f6c640000000000606482015260840161089c565b600680549082905560408051828152602081018490527ffc216faa269bf440fb06aa490693f409461bde9cdcb949c7b9f2cb79589e7a589101610966565b6000610e46600654600a60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610dfb57600080fd5b6000546001600160a01b031633146123495760405162461bcd60e51b815260206004820152602660248201527f4e6f756e7344414f3a3a5f73657450656e64696e6741646d696e3a2061646d6960448201527f6e206f6e6c790000000000000000000000000000000000000000000000000000606482015260840161089c565b600180546001600160a01b038381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101610966565b6003546001600160a01b0316331461243b5760405162461bcd60e51b815260206004820152602560248201527f4e6f756e7344414f3a3a5f6275726e5665746f506f7765723a207665746f657260448201527f206f6e6c79000000000000000000000000000000000000000000000000000000606482015260840161089c565b612445600061202f565b565b600061247b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b600a60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156124c957600080fd5b505afa1580156124dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125019190614027565b6bffffffffffffffffffffffff1680825260065461251e91613262565b60208201819052600a546001600160a01b031663782d6fe1336125426001436145f3565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039092166004830152602482015260440160206040518083038186803b15801561259e57600080fd5b505afa1580156125b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d69190614027565b6bffffffffffffffffffffffff16116126575760405162461bcd60e51b815260206004820152603a60248201527f4e6f756e7344414f3a3a70726f706f73653a2070726f706f73657220766f746560448201527f732062656c6f772070726f706f73616c207468726573686f6c64000000000000606482015260840161089c565b85518751148015612669575084518751145b8015612676575083518751145b6126e85760405162461bcd60e51b815260206004820152603f60248201527f4e6f756e7344414f3a3a70726f706f73653a2070726f706f73616c2066756e6360448201527f74696f6e20696e666f726d6174696f6e206172697479206d69736d6174636800606482015260840161089c565b865161275c5760405162461bcd60e51b815260206004820152602760248201527f4e6f756e7344414f3a3a70726f706f73653a206d7573742070726f766964652060448201527f616374696f6e7300000000000000000000000000000000000000000000000000606482015260840161089c565b600a875111156127d45760405162461bcd60e51b815260206004820152602360248201527f4e6f756e7344414f3a3a70726f706f73653a20746f6f206d616e79206163746960448201527f6f6e730000000000000000000000000000000000000000000000000000000000606482015260840161089c565b336000908152600c602052604090819020549082018190521561296057600061280082604001516118ce565b90506001816008811115612816576128166146f0565b14156128b05760405162461bcd60e51b815260206004820152605360248201527f4e6f756e7344414f3a3a70726f706f73653a206f6e65206c6976652070726f7060448201527f6f73616c207065722070726f706f7365722c20666f756e6420616e20616c726560648201527f616479206163746976652070726f706f73616c00000000000000000000000000608482015260a40161089c565b60008160088111156128c4576128c46146f0565b141561295e5760405162461bcd60e51b815260206004820152605460248201527f4e6f756e7344414f3a3a70726f706f73653a206f6e65206c6976652070726f7060448201527f6f73616c207065722070726f706f7365722c20666f756e6420616e20616c726560648201527f6164792070656e64696e672070726f706f73616c000000000000000000000000608482015260a40161089c565b505b60045461296d9043614563565b6060820181905260055461298091614563565b60808201526008805490600061299583614688565b90915550506008546000818152600b602090815260409091209182556001820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055820151600282015560075482516129f49190613262565b6003820155600060048201558751612a1590600583019060208b01906137f1565b508651612a2b90600683019060208a019061386e565b508551612a4190600783019060208901906138a9565b508451612a579060088301906020880190613902565b506060820151600982019081556080830151600a83019081556000600b8401819055600c808501829055600d8501829055600e850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000169055845460018601546001600160a01b031683526020919091526040918290208190559254915490517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e093612b1493909233928e928e928e928e9291908e90614355565b60405180910390a17f6af0134faa0f9290c1d686d55012aca80302d31d5c856e4bc7954f7613dc7f878160000154338a8a8a8a876009015488600a015489600201548a600301548e604051612b739b9a999897969594939291906143eb565b60405180910390a154979650505050505050565b6004612b92826118ce565b6008811115612ba357612ba36146f0565b14612c165760405162461bcd60e51b815260206004820152603f60248201527f4e6f756e7344414f3a3a71756575653a2070726f706f73616c2063616e206f6e60448201527f6c79206265207175657565642069662069742069732073756363656564656400606482015260840161089c565b6000818152600b6020908152604080832060095482517f6a42b8f800000000000000000000000000000000000000000000000000000000815292519194936001600160a01b0390911692636a42b8f89260048083019392829003018186803b158015612c8157600080fd5b505afa158015612c95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb99190613e5a565b612cc39042614563565b905060005b6005830154811015612e8d57612e7b836005018281548110612cec57612cec61471f565b6000918252602090912001546006850180546001600160a01b039092169184908110612d1a57612d1a61471f565b9060005260206000200154856007018481548110612d3a57612d3a61471f565b906000526020600020018054612d4f9061463a565b80601f0160208091040260200160405190810160405280929190818152602001828054612d7b9061463a565b8015612dc85780601f10612d9d57610100808354040283529160200191612dc8565b820191906000526020600020905b815481529060010190602001808311612dab57829003601f168201915b5050505050866008018581548110612de257612de261471f565b906000526020600020018054612df79061463a565b80601f0160208091040260200160405190810160405280929190818152602001828054612e239061463a565b8015612e705780601f10612e4557610100808354040283529160200191612e70565b820191906000526020600020905b815481529060010190602001808311612e5357829003601f168201915b5050505050866135fb565b80612e8581614688565b915050612cc8565b506004820181905560408051848152602081018390527f9a2e42fd6722813d69113e7d0079d3d940171428df7373df9c7f7617cfda2892910160405180910390a1505050565b6001546001600160a01b031633148015612eec57503315155b612f5e5760405162461bcd60e51b815260206004820152602a60248201527f4e6f756e7344414f3a3a5f61636365707441646d696e3a2070656e64696e672060448201527f61646d696e206f6e6c7900000000000000000000000000000000000000000000606482015260840161089c565b60008054600180546001600160a01b038082167fffffffffffffffffffffffff000000000000000000000000000000000000000080861682179096559490911690915560408051919092168082526020820184905292917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc910160405180910390a1600154604080516001600160a01b03808516825290921660208301527fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99101610966565b600561302f826118ce565b6008811115613040576130406146f0565b146130b5576040805162461bcd60e51b81526020600482015260248101919091527f4e6f756e7344414f3a3a657865637574653a2070726f706f73616c2063616e2060448201527f6f6e6c7920626520657865637574656420696620697420697320717565756564606482015260840161089c565b6000818152600b60205260408120600e810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000179055905b6005820154811015613231576009546005830180546001600160a01b0390921691630825f38f91908490811061312c5761312c61471f565b6000918252602090912001546006850180546001600160a01b03909216918590811061315a5761315a61471f565b906000526020600020015485600701858154811061317a5761317a61471f565b906000526020600020018660080186815481106131995761319961471f565b9060005260206000200187600401546040518663ffffffff1660e01b81526004016131c895949392919061426f565b600060405180830381600087803b1580156131e257600080fd5b505af11580156131f6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261321e9190810190613e73565b508061322981614688565b9150506130f4565b506040518281527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f90602001610966565b600061271061327184846145b6565b61327b919061457b565b9392505050565b6000600161328f846118ce565b60088111156132a0576132a06146f0565b146133135760405162461bcd60e51b815260206004820152602c60248201527f4e6f756e7344414f3a3a63617374566f7465496e7465726e616c3a20766f746960448201527f6e6720697320636c6f7365640000000000000000000000000000000000000000606482015260840161089c565b60028260ff16111561338d5760405162461bcd60e51b815260206004820152602d60248201527f4e6f756e7344414f3a3a63617374566f7465496e7465726e616c3a20696e766160448201527f6c696420766f7465207479706500000000000000000000000000000000000000606482015260840161089c565b6000838152600b602090815260408083206001600160a01b0388168452600f8101909252909120805460ff161561342c5760405162461bcd60e51b815260206004820152602f60248201527f4e6f756e7344414f3a3a63617374566f7465496e7465726e616c3a20766f746560448201527f7220616c726561647920766f7465640000000000000000000000000000000000606482015260840161089c565b600a5460045460098401546000926001600160a01b03169163782d6fe1918a91613455916145f3565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b039092166004830152602482015260440160206040518083038186803b1580156134b157600080fd5b505afa1580156134c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e99190614027565b905060ff851661351b57806bffffffffffffffffffffffff1683600c01546135119190614563565b600c84015561357f565b8460ff166001141561354f57806bffffffffffffffffffffffff1683600b01546135459190614563565b600b84015561357f565b8460ff166002141561357f57806bffffffffffffffffffffffff1683600d01546135799190614563565b600d8401555b81546bffffffffffffffffffffffff821662010000027fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff60ff8816610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009093169290921760011791909116179091559150509392505050565b6009546040516001600160a01b039091169063f2b06537906136299088908890889088908890602001614222565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161365d91815260200190565b60206040518083038186803b15801561367557600080fd5b505afa158015613689573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ad9190613e38565b156137465760405162461bcd60e51b815260206004820152605060248201527f4e6f756e7344414f3a3a71756575654f72526576657274496e7465726e616c3a60448201527f206964656e746963616c2070726f706f73616c20616374696f6e20616c72656160648201527f6479207175657565642061742065746100000000000000000000000000000000608482015260a40161089c565b6009546040517f3a66f9010000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690633a66f901906137979088908890889088908890600401614222565b602060405180830381600087803b1580156137b157600080fd5b505af11580156137c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137e99190613e5a565b505050505050565b82805482825590600052602060002090810192821561385e579160200282015b8281111561385e57825182547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909116178255602090920191600190910190613811565b5061386a92915061395b565b5090565b82805482825590600052602060002090810192821561385e579160200282015b8281111561385e57825182559160200191906001019061388e565b8280548282559060005260206000209081019282156138f6579160200282015b828111156138f657825180516138e6918491602090910190613970565b50916020019190600101906138c9565b5061386a9291506139e3565b82805482825590600052602060002090810192821561394f579160200282015b8281111561394f578251805161393f918491602090910190613970565b5091602001919060010190613922565b5061386a929150613a00565b5b8082111561386a576000815560010161395c565b82805461397c9061463a565b90600052602060002090601f01602090048101928261399e576000855561385e565b82601f106139b757805160ff191683800117855561385e565b8280016001018555821561385e579182018281111561385e57825182559160200191906001019061388e565b8082111561386a5760006139f78282613a1d565b506001016139e3565b8082111561386a576000613a148282613a1d565b50600101613a00565b508054613a299061463a565b6000825580601f10613a39575050565b601f016020900490600052602060002090810190613a57919061395b565b50565b6000613a6d613a688461453b565b6144e6565b9050828152838383011115613a8157600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b0381168114613aaf57600080fd5b919050565b600082601f830112613ac557600080fd5b81356020613ad5613a6883614517565b80838252828201915082860187848660051b8901011115613af557600080fd5b60005b85811015613b1b57613b0982613a98565b84529284019290840190600101613af8565b5090979650505050505050565b600082601f830112613b3957600080fd5b81356020613b49613a6883614517565b80838252828201915082860187848660051b8901011115613b6957600080fd5b60005b85811015613b1b57813567ffffffffffffffff811115613b8b57600080fd5b8801603f81018a13613b9c57600080fd5b613bad8a8783013560408401613a5a565b8552509284019290840190600101613b6c565b600082601f830112613bd157600080fd5b81356020613be1613a6883614517565b80838252828201915082860187848660051b8901011115613c0157600080fd5b6000805b86811015613c4457823567ffffffffffffffff811115613c23578283fd5b613c318b88838d0101613cb2565b8652509385019391850191600101613c05565b509198975050505050505050565b600082601f830112613c6357600080fd5b81356020613c73613a6883614517565b80838252828201915082860187848660051b8901011115613c9357600080fd5b60005b85811015613b1b57813584529284019290840190600101613c96565b600082601f830112613cc357600080fd5b61327b83833560208501613a5a565b803560ff81168114613aaf57600080fd5b600060208284031215613cf557600080fd5b61327b82613a98565b600080600080600080600060e0888a031215613d1957600080fd5b613d2288613a98565b9650613d3060208901613a98565b9550613d3e60408901613a98565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b600080600080600060a08688031215613d7e57600080fd5b853567ffffffffffffffff80821115613d9657600080fd5b613da289838a01613ab4565b96506020880135915080821115613db857600080fd5b613dc489838a01613c52565b95506040880135915080821115613dda57600080fd5b613de689838a01613bc0565b94506060880135915080821115613dfc57600080fd5b613e0889838a01613b28565b93506080880135915080821115613e1e57600080fd5b50613e2b88828901613cb2565b9150509295509295909350565b600060208284031215613e4a57600080fd5b8151801515811461327b57600080fd5b600060208284031215613e6c57600080fd5b5051919050565b600060208284031215613e8557600080fd5b815167ffffffffffffffff811115613e9c57600080fd5b8201601f81018413613ead57600080fd5b8051613ebb613a688261453b565b818152856020838501011115613ed057600080fd5b613ee182602083016020860161460a565b95945050505050565b600060208284031215613efc57600080fd5b5035919050565b60008060408385031215613f1657600080fd5b82359150613f2660208401613a98565b90509250929050565b60008060408385031215613f4257600080fd5b82359150613f2660208401613cd2565b60008060008060608587031215613f6857600080fd5b84359350613f7860208601613cd2565b9250604085013567ffffffffffffffff80821115613f9557600080fd5b818701915087601f830112613fa957600080fd5b813581811115613fb857600080fd5b886020828501011115613fca57600080fd5b95989497505060200194505050565b600080600080600060a08688031215613ff157600080fd5b8535945061400160208701613cd2565b935061400f60408701613cd2565b94979396509394606081013594506080013592915050565b60006020828403121561403957600080fd5b81516bffffffffffffffffffffffff8116811461327b57600080fd5b600081518084526020808501945080840160005b8381101561408e5781516001600160a01b031687529582019590820190600101614069565b509495945050505050565b600081518084526020808501808196508360051b8101915082860160005b858110156140e15782840389526140cf84835161411e565b988501989350908401906001016140b7565b5091979650505050505050565b600081518084526020808501945080840160005b8381101561408e57815187529582019590820190600101614102565b6000815180845261413681602086016020860161460a565b601f01601f19169290920160200192915050565b8054600090600181811c908083168061416457607f831692505b602080841082141561419f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8388528180156141b657600181146141e857614216565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616828a0152604089019650614216565b876000528160002060005b8681101561420e5781548b82018501529085019083016141f3565b8a0183019750505b50505050505092915050565b6001600160a01b038616815284602082015260a06040820152600061424a60a083018661411e565b828103606084015261425c818661411e565b9150508260808301529695505050505050565b6001600160a01b038616815284602082015260a06040820152600061429760a083018661414a565b828103606084015261425c818661414a565b6080815260006142bc6080830187614055565b82810360208401526142ce81876140ee565b905082810360408401526142e28186614099565b905082810360608401526142f68185614099565b979650505050505050565b602081016009831061433c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60208152600061327b602083018461411e565b60006101208b83526001600160a01b038b16602084015280604084015261437e8184018b614055565b90508281036060840152614392818a6140ee565b905082810360808401526143a68189614099565b905082810360a08401526143ba8188614099565b90508560c08401528460e08401528281036101008401526143db818561411e565b9c9b505050505050505050505050565b60006101608d83526001600160a01b038d1660208401528060408401526144148184018d614055565b90508281036060840152614428818c6140ee565b9050828103608084015261443c818b614099565b905082810360a0840152614450818a614099565b90508760c08401528660e0840152856101008401528461012084015282810361014084015261447f818561411e565b9e9d5050505050505050505050505050565b85815260ff851660208201526bffffffffffffffffffffffff8416604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b604051601f8201601f1916810167ffffffffffffffff8111828210171561450f5761450f61474e565b604052919050565b600067ffffffffffffffff8211156145315761453161474e565b5060051b60200190565b600067ffffffffffffffff8211156145555761455561474e565b50601f01601f191660200190565b60008219821115614576576145766146c1565b500190565b6000826145b1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156145ee576145ee6146c1565b500290565b600082821015614605576146056146c1565b500390565b60005b8381101561462557818101518382015260200161460d565b83811115614634576000848401525b50505050565b600181811c9082168061464e57607f821691505b60208210811415611ab5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156146ba576146ba6146c1565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea26469706673582212202d219bbd5982bc04b4820b819396c18d235e46dcc014201d58710c7b14362c2364736f6c63430008060033

Check out more smart contracts

Build blockchain magic with Alchemy

Alchemy combines the most powerful web3 developer products and tools with resources, community and legendary support.