creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/governance/NounsDAOLogicV4.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\n\n/// @title The Nouns DAO logic version 4\n\n/*********************************\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░██░░░████░░██░░░████░░░ *\n * ░░██████░░░████████░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n *********************************/\n\n// LICENSE\n// NounsDAOLogicV2.sol is a modified version of Compound Lab's GovernorBravoDelegate.sol:\n// https://github.com/compound-finance/compound-protocol/blob/b9b14038612d846b83f8a009a82c38974ff2dcfe/contracts/Governance/GovernorBravoDelegate.sol\n//\n// GovernorBravoDelegate.sol source code Copyright 2020 Compound Labs, Inc. licensed under the BSD-3-Clause license.\n// With modifications by Nounders DAO.\n//\n// Additional conditions of BSD-3-Clause can be found here: https://opensource.org/licenses/BSD-3-Clause\n//\n// MODIFICATIONS\n// See NounsDAOLogicV1 for initial GovernorBravoDelegate modifications.\n// See NounsDAOLogicV2 for additional modifications\n//\n// NounsDAOLogicV3 adds:\n// - Contract has been broken down to use libraries because of contract size limitations\n// - Proposal editing: allowing proposers to update their proposal’s transactions and text description,\n// during the Updatable period only, which is the state upon proposal creation. Editing also works with signatures,\n// assuming the proposer is able to accumulate signatures from the same signers.\n// - Propose by signature: allowing Nouners and delegates to pool their voting power towards submitting a proposal,\n// by submitting their signature, instead of the current approach where sponsors must delegate their votes to help\n// a proposer achieve threshold.\n// - Objection-only Period: a conditional voting period that gets activated upon a last-minute proposal swing\n// from defeated to successful, affording against voters more reaction time.\n// Only against votes are possible during the objection period.\n// - Votes snapshot after voting delay: moving votes snapshot up, to provide Nouners with reaction time per proposal,\n// to get their votes ready (e.g. some might want to move their delegations around).\n// In NounsDAOLogicV2 the vote snapshot block is the proposal creation block.\n// - Nouns fork: any token holder can signal to fork (exit) in response to a governance proposal.\n// If a quorum of a configured threshold amount of tokens signals to exit, the fork will succeed.\n// This will deploy a new DAO and send part of the treasury to the new DAO.\n//\n// 2 new states have been added to the proposal state machine: Updatable, ObjectionPeriod\n//\n// Updated state machine:\n// Updatable -> Pending -> Active -> ObjectionPeriod (conditional) -> Succeeded -> Queued -> Executed\n//                                                                 ┖> Defeated\n//\n\npragma solidity ^0.8.19;\n\nimport './NounsDAOInterfaces.sol';\nimport { NounsDAOAdmin } from './NounsDAOAdmin.sol';\nimport { NounsDAODynamicQuorum } from './NounsDAODynamicQuorum.sol';\nimport { NounsDAOVotes } from './NounsDAOVotes.sol';\nimport { NounsDAOProposals } from './NounsDAOProposals.sol';\nimport { NounsDAOFork } from './fork/NounsDAOFork.sol';\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\n\ncontract NounsDAOLogicV4 is NounsDAOStorage, NounsDAOEventsV3 {\n    using NounsDAOAdmin for Storage;\n    using NounsDAODynamicQuorum for Storage;\n    using NounsDAOVotes for Storage;\n    using NounsDAOProposals for Storage;\n    using NounsDAOFork for Storage;\n\n    /**\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     *   CONSTANTS\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     */\n\n    /// @notice The minimum setable proposal threshold\n    function MIN_PROPOSAL_THRESHOLD_BPS() public pure returns (uint256) {\n        return NounsDAOAdmin.MIN_PROPOSAL_THRESHOLD_BPS;\n    }\n\n    /// @notice The maximum setable proposal threshold\n    function MAX_PROPOSAL_THRESHOLD_BPS() public pure returns (uint256) {\n        return NounsDAOAdmin.MAX_PROPOSAL_THRESHOLD_BPS;\n    }\n\n    /// @notice The minimum setable voting period in blocks\n    function MIN_VOTING_PERIOD() public pure returns (uint256) {\n        return NounsDAOAdmin.MIN_VOTING_PERIOD_BLOCKS;\n    }\n\n    /// @notice The max setable voting period in blocks\n    function MAX_VOTING_PERIOD() public pure returns (uint256) {\n        return NounsDAOAdmin.MAX_VOTING_PERIOD_BLOCKS;\n    }\n\n    /// @notice The min setable voting delay in blocks\n    function MIN_VOTING_DELAY() public pure returns (uint256) {\n        return NounsDAOAdmin.MIN_VOTING_DELAY_BLOCKS;\n    }\n\n    /// @notice The max setable voting delay in blocks\n    function MAX_VOTING_DELAY() public pure returns (uint256) {\n        return NounsDAOAdmin.MAX_VOTING_DELAY_BLOCKS;\n    }\n\n    /// @notice The maximum number of actions that can be included in a proposal\n    function proposalMaxOperations() public pure returns (uint256) {\n        return NounsDAOProposals.PROPOSAL_MAX_OPERATIONS;\n    }\n\n    /**\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     *   ERRORS\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     */\n\n    error AdminOnly();\n    error CanOnlyInitializeOnce();\n    error InvalidTimelockAddress();\n    error InvalidNounsAddress();\n\n    /**\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     *   INITIALIZER\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     */\n\n    /**\n     * @notice Used to initialize the contract during delegator contructor\n     * @dev This will only be called for a newly deployed DAO, not as part of an upgrade from V2 to V3\n     * @param timelock_ The address of the NounsDAOExecutor\n     * @param nouns_ The address of the NOUN tokens\n     * @param forkEscrow_ The escrow contract used for creating forks\n     * @param forkDAODeployer_ The contract used to deploy new forked DAOs\n     * @param vetoer_ The address allowed to unilaterally veto proposals\n     * @param daoParams_ Initial DAO parameters\n     * @param dynamicQuorumParams_ The initial dynamic quorum parameters\n     */\n    function initialize(\n        address timelock_,\n        address nouns_,\n        address forkEscrow_,\n        address forkDAODeployer_,\n        address vetoer_,\n        NounsDAOParams calldata daoParams_,\n        DynamicQuorumParams calldata dynamicQuorumParams_\n    ) public virtual {\n        if (address(ds.timelock) != address(0)) revert CanOnlyInitializeOnce();\n        if (msg.sender != ds.admin) revert AdminOnly();\n        if (timelock_ == address(0)) revert InvalidTimelockAddress();\n        if (nouns_ == address(0)) revert InvalidNounsAddress();\n\n        NounsDAOAdmin._setVotingPeriod(daoParams_.votingPeriod);\n        NounsDAOAdmin._setVotingDelay(daoParams_.votingDelay);\n        NounsDAOAdmin._setProposalThresholdBPS(daoParams_.proposalThresholdBPS);\n        ds.timelock = INounsDAOExecutorV2(timelock_);\n        ds.nouns = NounsTokenLike(nouns_);\n        ds.forkEscrow = INounsDAOForkEscrow(forkEscrow_);\n        ds.forkDAODeployer = IForkDAODeployer(forkDAODeployer_);\n        ds.vetoer = vetoer_;\n        NounsDAOAdmin._setDynamicQuorumParams(\n            dynamicQuorumParams_.minQuorumVotesBPS,\n            dynamicQuorumParams_.maxQuorumVotesBPS,\n            dynamicQuorumParams_.quorumCoefficient\n        );\n\n        NounsDAOAdmin._setLastMinuteWindowInBlocks(daoParams_.lastMinuteWindowInBlocks);\n        NounsDAOAdmin._setObjectionPeriodDurationInBlocks(daoParams_.objectionPeriodDurationInBlocks);\n        NounsDAOAdmin._setProposalUpdatablePeriodInBlocks(daoParams_.proposalUpdatablePeriodInBlocks);\n    }\n\n    /**\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     *   PROPOSALS\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     */\n\n    /**\n     * @notice Function used to propose a new proposal. Sender must have delegates above the proposal threshold\n     * @param targets Target addresses for proposal calls\n     * @param values Eth values for proposal calls\n     * @param signatures Function signatures for proposal calls\n     * @param calldatas Calldatas for proposal calls\n     * @param description String description of the proposal\n     * @return uint256 Proposal id of new proposal\n     */\n    function propose(\n        address[] memory targets,\n        uint256[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas,\n        string memory description\n    ) external returns (uint256) {\n        return propose(targets, values, signatures, calldatas, description, 0);\n    }\n\n    /**\n     * @notice Function used to propose a new proposal. Sender must have delegates above the proposal threshold\n     * @param targets Target addresses for proposal calls\n     * @param values Eth values for proposal calls\n     * @param signatures Function signatures for proposal calls\n     * @param calldatas Calldatas for proposal calls\n     * @param description String description of the proposal\n     * @param clientId The ID of the client that faciliated posting the proposal onchain\n     * @return uint256 Proposal id of new proposal\n     */\n    function propose(\n        address[] memory targets,\n        uint256[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas,\n        string memory description,\n        uint32 clientId\n    ) public returns (uint256) {\n        return ds.propose(NounsDAOProposals.ProposalTxs(targets, values, signatures, calldatas), description, clientId);\n    }\n\n    /**\n     * @notice Function used to propose a new proposal. Sender must have delegates above the proposal threshold.\n     * This proposal would be executed via the timelockV1 contract. This is meant to be used in case timelockV1\n     * is still holding funds or has special permissions to execute on certain contracts.\n     * @param targets Target addresses for proposal calls\n     * @param values Eth values for proposal calls\n     * @param signatures Function signatures for proposal calls\n     * @param calldatas Calldatas for proposal calls\n     * @param description String description of the proposal\n     * @return uint256 Proposal id of new proposal\n     */\n    function proposeOnTimelockV1(\n        address[] memory targets,\n        uint256[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas,\n        string memory description\n    ) public returns (uint256) {\n        return\n            ds.proposeOnTimelockV1(\n                NounsDAOProposals.ProposalTxs(targets, values, signatures, calldatas),\n                description,\n                0\n            );\n    }\n\n    /**\n     * @notice Function used to propose a new proposal. Sender must have delegates above the proposal threshold.\n     * This proposal would be executed via the timelockV1 contract. This is meant to be used in case timelockV1\n     * is still holding funds or has special permissions to execute on certain contracts.\n     * @param targets Target addresses for proposal calls\n     * @param values Eth values for proposal calls\n     * @param signatures Function signatures for proposal calls\n     * @param calldatas Calldatas for proposal calls\n     * @param description String description of the proposal\n     * @param clientId The ID of the client that faciliated posting the proposal onchain\n     * @return uint256 Proposal id of new proposal\n     */\n    function proposeOnTimelockV1(\n        address[] memory targets,\n        uint256[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas,\n        string memory description,\n        uint32 clientId\n    ) public returns (uint256) {\n        return\n            ds.proposeOnTimelockV1(\n                NounsDAOProposals.ProposalTxs(targets, values, signatures, calldatas),\n                description,\n                clientId\n            );\n    }\n\n    /**\n     * @notice Function used to propose a new proposal. Sender and signers must have delegates above the proposal threshold\n     * Signers are regarded as co-proposers, and therefore have the ability to cancel the proposal at any time.\n     * @param proposerSignatures Array of signers who have signed the proposal and their signatures.\n     * @dev The signatures follow EIP-712. See `PROPOSAL_TYPEHASH` in NounsDAOProposals.sol\n     * @param targets Target addresses for proposal calls\n     * @param values Eth values for proposal calls\n     * @param signatures Function signatures for proposal calls\n     * @param calldatas Calldatas for proposal calls\n     * @param description String description of the proposal\n     * @return uint256 Proposal id of new proposal\n     */\n    function proposeBySigs(\n        ProposerSignature[] memory proposerSignatures,\n        address[] memory targets,\n        uint256[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas,\n        string memory description\n    ) external returns (uint256) {\n        return proposeBySigs(proposerSignatures, targets, values, signatures, calldatas, description, 0);\n    }\n\n    /**\n     * @notice Function used to propose a new proposal. Sender and signers must have delegates above the proposal threshold\n     * Signers are regarded as co-proposers, and therefore have the ability to cancel the proposal at any time.\n     * @param proposerSignatures Array of signers who have signed the proposal and their signatures.\n     * @dev The signatures follow EIP-712. See `PROPOSAL_TYPEHASH` in NounsDAOProposals.sol\n     * @param targets Target addresses for proposal calls\n     * @param values Eth values for proposal calls\n     * @param signatures Function signatures for proposal calls\n     * @param calldatas Calldatas for proposal calls\n     * @param description String description of the proposal\n     * @param clientId The ID of the client that faciliated posting the proposal onchain\n     * @return uint256 Proposal id of new proposal\n     */\n    function proposeBySigs(\n        ProposerSignature[] memory proposerSignatures,\n        address[] memory targets,\n        uint256[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas,\n        string memory description,\n        uint32 clientId\n    ) public returns (uint256) {\n        return\n            ds.proposeBySigs(\n                proposerSignatures,\n                NounsDAOProposals.ProposalTxs(targets, values, signatures, calldatas),\n                description,\n                clientId\n            );\n    }\n\n    /**\n     * @notice Invalidates a signature that may be used for signing a new proposal.\n     * Once a signature is canceled, the sender can no longer use it again.\n     * If the sender changes their mind and want to sign the proposal, they can change the expiry timestamp\n     * in order to produce a new signature.\n     * The signature will only be invalidated when used by the sender. If used by a different account, it will\n     * not be invalidated.\n     * Cancelling a signature for an existing proposal will have no effect. Signers have the ability to cancel\n     * a proposal they signed if necessary.\n     * @param sig The signature to cancel\n     */\n    function cancelSig(bytes calldata sig) external {\n        ds.cancelSig(sig);\n    }\n\n    /**\n     * @notice Update a proposal transactions and description.\n     * Only the proposer can update it, and only during the updateable period.\n     * @param proposalId Proposal's id\n     * @param targets Updated target addresses for proposal calls\n     * @param values Updated eth values for proposal calls\n     * @param signatures Updated function signatures for proposal calls\n     * @param calldatas Updated calldatas for proposal calls\n     * @param description Updated description of the proposal\n     * @param updateMessage Short message to explain the update\n     */\n    function updateProposal(\n        uint256 proposalId,\n        address[] memory targets,\n        uint256[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas,\n        string memory description,\n        string memory updateMessage\n    ) external {\n        ds.updateProposal(proposalId, targets, values, signatures, calldatas, description, updateMessage);\n    }\n\n    /**\n     * @notice Updates the proposal's description. Only the proposer can update it, and only during the updateable period.\n     * @param proposalId Proposal's id\n     * @param description Updated description of the proposal\n     * @param updateMessage Short message to explain the update\n     */\n    function updateProposalDescription(\n        uint256 proposalId,\n        string calldata description,\n        string calldata updateMessage\n    ) external {\n        ds.updateProposalDescription(proposalId, description, updateMessage);\n    }\n\n    /**\n     * @notice Updates the proposal's transactions. Only the proposer can update it, and only during the updateable period.\n     * @param proposalId Proposal's id\n     * @param targets Updated target addresses for proposal calls\n     * @param values Updated eth values for proposal calls\n     * @param signatures Updated function signatures for proposal calls\n     * @param calldatas Updated calldatas for proposal calls\n     * @param updateMessage Short message to explain the update\n     */\n    function updateProposalTransactions(\n        uint256 proposalId,\n        address[] memory targets,\n        uint256[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas,\n        string memory updateMessage\n    ) external {\n        ds.updateProposalTransactions(proposalId, targets, values, signatures, calldatas, updateMessage);\n    }\n\n    /**\n     * @notice Update a proposal's transactions and description that was created with proposeBySigs.\n     * Only the proposer can update it, during the updateable period.\n     * Requires the original signers to sign the update.\n     * @param proposalId Proposal's id\n     * @param proposerSignatures Array of signers who have signed the proposal and their signatures.\n     * @dev The signatures follow EIP-712. See `UPDATE_PROPOSAL_TYPEHASH` in NounsDAOProposals.sol\n     * @param targets Updated target addresses for proposal calls\n     * @param values Updated eth values for proposal calls\n     * @param signatures Updated function signatures for proposal calls\n     * @param calldatas Updated calldatas for proposal calls\n     * @param description Updated description of the proposal\n     * @param updateMessage Short message to explain the update\n     */\n    function updateProposalBySigs(\n        uint256 proposalId,\n        ProposerSignature[] memory proposerSignatures,\n        address[] memory targets,\n        uint256[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas,\n        string memory description,\n        string memory updateMessage\n    ) external {\n        ds.updateProposalBySigs(\n            proposalId,\n            proposerSignatures,\n            NounsDAOProposals.ProposalTxs(targets, values, signatures, calldatas),\n            description,\n            updateMessage\n        );\n    }\n\n    /**\n     * @notice Queues a proposal of state succeeded\n     * @param proposalId The id of the proposal to queue\n     */\n    function queue(uint256 proposalId) external {\n        ds.queue(proposalId);\n    }\n\n    /**\n     * @notice Executes a queued proposal if eta has passed\n     * @param proposalId The id of the proposal to execute\n     */\n    function execute(uint256 proposalId) external {\n        ds.execute(proposalId);\n    }\n\n    /**\n     * @notice Cancels a proposal only if sender is the proposer or a signer, or proposer & signers voting power\n     * dropped below proposal threshold\n     * @param proposalId The id of the proposal to cancel\n     */\n    function cancel(uint256 proposalId) external {\n        ds.cancel(proposalId);\n    }\n\n    /**\n     * @notice Gets the state of a proposal\n     * @param proposalId The id of the proposal\n     * @return Proposal state\n     */\n    function state(uint256 proposalId) public view returns (ProposalState) {\n        return ds.state(proposalId);\n    }\n\n    /**\n     * @notice Gets actions of a proposal\n     * @param proposalId the id of the proposal\n     * @return targets\n     * @return values\n     * @return signatures\n     * @return calldatas\n     */\n    function getActions(\n        uint256 proposalId\n    )\n        external\n        view\n        returns (\n            address[] memory targets,\n            uint256[] memory values,\n            string[] memory signatures,\n            bytes[] memory calldatas\n        )\n    {\n        return ds.getActions(proposalId);\n    }\n\n    /**\n     * @notice Gets the receipt for a voter on a given proposal\n     * @param proposalId the id of proposal\n     * @param voter The address of the voter\n     * @return The voting receipt\n     */\n    function getReceipt(uint256 proposalId, address voter) external view returns (Receipt memory) {\n        return ds.getReceipt(proposalId, voter);\n    }\n\n    /**\n     * @notice Returns the proposal details given a proposal id.\n     *     The `quorumVotes` member holds the *current* quorum, given the current votes.\n     * @param proposalId the proposal id to get the data for\n     * @return A `ProposalCondensed` struct with the proposal data, backwards compatible with V1 and V2\n     */\n    function proposals(uint256 proposalId) external view returns (NounsDAOTypes.ProposalCondensedV2 memory) {\n        return ds.proposals(proposalId);\n    }\n\n    /**\n     * @notice Returns the proposal details given a proposal id.\n     *     The `quorumVotes` member holds the *current* quorum, given the current votes.\n     * @param proposalId the proposal id to get the data for\n     * @return A `ProposalCondensed` struct with the proposal data, not backwards compatible as it contains additional values\n     * like `objectionPeriodEndBlock` and `signers`\n     */\n    function proposalsV3(uint256 proposalId) external view returns (ProposalCondensedV3 memory) {\n        return ds.proposalsV3(proposalId);\n    }\n\n    /**\n     * @notice Get a range of proposals, in the format of a samller struct tailored to client incentives rewards.\n     * @param firstProposalId the id of the first proposal to get the data for\n     * @param lastProposalId the id of the last proposal to get the data for\n     * @param proposalEligibilityQuorumBps filters proposals with for-votes/total-supply higher than this quorum\n     * @param excludeCanceled if true, excludes canceled proposals\n     * @param requireVotingEnded if true, reverts if one of the proposals hasn't finished voting yet\n     * @param votingClientIds the ids of the clients that facilitated votes on the proposals\n     * @return An array of `ProposalForRewards` structs with the proposal data\n     */\n    function proposalDataForRewards(\n        uint256 firstProposalId,\n        uint256 lastProposalId,\n        uint16 proposalEligibilityQuorumBps,\n        bool excludeCanceled,\n        bool requireVotingEnded,\n        uint32[] calldata votingClientIds\n    ) external view returns (ProposalForRewards[] memory) {\n        return\n            ds.proposalDataForRewards(\n                firstProposalId,\n                lastProposalId,\n                proposalEligibilityQuorumBps,\n                excludeCanceled,\n                requireVotingEnded,\n                votingClientIds\n            );\n    }\n\n    /**\n     * @notice Current proposal threshold using Noun Total Supply\n     * Differs from `GovernerBravo` which uses fixed amount\n     */\n    function proposalThreshold() public view returns (uint256) {\n        return ds.proposalThreshold(adjustedTotalSupply());\n    }\n\n    /**\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     *   DAO FORK\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     */\n\n    /**\n     * @notice Escrow Nouns to contribute to the fork threshold\n     * @dev Requires approving the tokenIds or the entire noun token to the DAO contract\n     * @param tokenIds the tokenIds to escrow. They will be sent to the DAO once the fork threshold is reached and the escrow is closed.\n     * @param proposalIds array of proposal ids which are the reason for wanting to fork. This will only be used to emit event.\n     * @param reason the reason for want to fork. This will only be used to emit event.\n     */\n    function escrowToFork(\n        uint256[] calldata tokenIds,\n        uint256[] calldata proposalIds,\n        string calldata reason\n    ) external {\n        ds.escrowToFork(tokenIds, proposalIds, reason);\n    }\n\n    /**\n     * @notice Withdraw Nouns from the fork escrow. Only possible if the fork has not been executed.\n     * Only allowed to withdraw tokens that the sender has escrowed.\n     * @param tokenIds the tokenIds to withdraw\n     */\n    function withdrawFromForkEscrow(uint256[] calldata tokenIds) external {\n        ds.withdrawFromForkEscrow(tokenIds);\n    }\n\n    /**\n     * @notice Execute the fork. Only possible if the fork threshold has been met.\n     * This will deploy a new DAO and send part of the treasury to the new DAO's treasury.\n     * This will also close the active escrow and all nouns in the escrow belong to the original DAO.\n     * @return forkTreasury The address of the new DAO's treasury\n     * @return forkToken The address of the new DAO's token\n     */\n    function executeFork() external returns (address forkTreasury, address forkToken) {\n        return ds.executeFork();\n    }\n\n    /**\n     * @notice Joins a fork while a fork is active\n     * @param tokenIds the tokenIds to send to the DAO in exchange for joining the fork\n     * @param proposalIds array of proposal ids which are the reason for wanting to fork. This will only be used to emit event.\n     * @param reason the reason for want to fork. This will only be used to emit event.\n     */\n    function joinFork(uint256[] calldata tokenIds, uint256[] calldata proposalIds, string calldata reason) external {\n        ds.joinFork(tokenIds, proposalIds, reason);\n    }\n\n    /**\n     * @notice Withdraws nouns from the fork escrow to the treasury after the fork has been executed\n     * @dev Only the DAO can call this function\n     * @param tokenIds the tokenIds to withdraw\n     */\n    function withdrawDAONounsFromEscrowToTreasury(uint256[] calldata tokenIds) external {\n        ds.withdrawDAONounsFromEscrowToTreasury(tokenIds);\n    }\n\n    /**\n     * @notice Withdraws nouns from the fork escrow after the fork has been executed to an address other than the treasury\n     * @dev Only the DAO can call this function\n     * @param tokenIds the tokenIds to withdraw\n     * @param to the address to send the nouns to\n     */\n    function withdrawDAONounsFromEscrowIncreasingTotalSupply(uint256[] calldata tokenIds, address to) external {\n        ds.withdrawDAONounsFromEscrowIncreasingTotalSupply(tokenIds, to);\n    }\n\n    /**\n     * @notice Returns the number of nouns in supply minus nouns owned by the DAO, i.e. held in the treasury or in an\n     * escrow after it has closed.\n     * This is used when calculating proposal threshold, quorum, fork threshold & treasury split.\n     */\n    function adjustedTotalSupply() public view returns (uint256) {\n        return ds.adjustedTotalSupply();\n    }\n\n    /**\n     * @notice returns the required number of tokens to escrow to trigger a fork\n     */\n    function forkThreshold() external view returns (uint256) {\n        return ds.forkThreshold();\n    }\n\n    /**\n     * @notice Returns the number of tokens currently in escrow, contributing to the fork threshold\n     */\n    function numTokensInForkEscrow() external view returns (uint256) {\n        return ds.numTokensInForkEscrow();\n    }\n\n    /**\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     *   VOTES\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     */\n\n    /**\n     * @notice Vetoes a proposal only if sender is the vetoer and the proposal has not been executed.\n     * @param proposalId The id of the proposal to veto\n     */\n    function veto(uint256 proposalId) external {\n        ds.veto(proposalId);\n    }\n\n    /**\n     * @notice Cast a vote for a proposal\n     * @param proposalId The id of the proposal to vote on\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     */\n    function castVote(uint256 proposalId, uint8 support) external {\n        ds.castVote(proposalId, support);\n    }\n\n    /**\n     * @notice Cast a vote for a proposal, asking the DAO to refund gas costs.\n     * Users with > 0 votes receive refunds. Refunds are partial when using a gas priority fee higher than the DAO's cap.\n     * Refunds are partial when the DAO's balance is insufficient.\n     * No refund is sent when the DAO's balance is empty. No refund is sent to users with no votes.\n     * Voting takes place regardless of refund success.\n     * @param proposalId The id of the proposal to vote on\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     * @dev Reentrancy is defended against in `castVoteInternal` at the `receipt.hasVoted == false` require statement.\n     */\n    function castRefundableVote(uint256 proposalId, uint8 support) external {\n        ds.castRefundableVote(proposalId, support, 0);\n    }\n\n    /**\n     * @notice Cast a vote for a proposal, asking the DAO to refund gas costs.\n     * Users with > 0 votes receive refunds. Refunds are partial when using a gas priority fee higher than the DAO's cap.\n     * Refunds are partial when the DAO's balance is insufficient.\n     * No refund is sent when the DAO's balance is empty. No refund is sent to users with no votes.\n     * Voting takes place regardless of refund success.\n     * @param proposalId The id of the proposal to vote on\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     * @param clientId The ID of the client that faciliated posting the vote onchain\n     * @dev Reentrancy is defended against in `castVoteInternal` at the `receipt.hasVoted == false` require statement.\n     */\n    function castRefundableVote(uint256 proposalId, uint8 support, uint32 clientId) external {\n        ds.castRefundableVote(proposalId, support, clientId);\n    }\n\n    /**\n     * @notice Cast a vote for a proposal, asking the DAO to refund gas costs.\n     * Users with > 0 votes receive refunds. Refunds are partial when using a gas priority fee higher than the DAO's cap.\n     * Refunds are partial when the DAO's balance is insufficient.\n     * No refund is sent when the DAO's balance is empty. No refund is sent to users with no votes.\n     * Voting takes place regardless of refund success.\n     * @param proposalId The id of the proposal to vote on\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     * @param reason The reason given for the vote by the voter\n     * @dev Reentrancy is defended against in `castVoteInternal` at the `receipt.hasVoted == false` require statement.\n     */\n    function castRefundableVoteWithReason(uint256 proposalId, uint8 support, string calldata reason) public {\n        ds.castRefundableVoteWithReason(proposalId, support, reason, 0);\n    }\n\n    /**\n     * @notice Cast a vote for a proposal, asking the DAO to refund gas costs.\n     * Users with > 0 votes receive refunds. Refunds are partial when using a gas priority fee higher than the DAO's cap.\n     * Refunds are partial when the DAO's balance is insufficient.\n     * No refund is sent when the DAO's balance is empty. No refund is sent to users with no votes.\n     * Voting takes place regardless of refund success.\n     * @param proposalId The id of the proposal to vote on\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     * @param reason The reason given for the vote by the voter\n     * @param clientId The ID of the client that faciliated posting the vote onchain\n     * @dev Reentrancy is defended against in `castVoteInternal` at the `receipt.hasVoted == false` require statement.\n     */\n    function castRefundableVoteWithReason(\n        uint256 proposalId,\n        uint8 support,\n        string calldata reason,\n        uint32 clientId\n    ) public {\n        ds.castRefundableVoteWithReason(proposalId, support, reason, clientId);\n    }\n\n    /**\n     * @notice Cast a vote for a proposal with a reason\n     * @param proposalId The id of the proposal to vote on\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     * @param reason The reason given for the vote by the voter\n     */\n    function castVoteWithReason(uint256 proposalId, uint8 support, string calldata reason) external {\n        ds.castVoteWithReason(proposalId, support, reason);\n    }\n\n    /**\n     * @notice Cast a vote for a proposal by signature\n     * @dev External function that accepts EIP-712 signatures for voting on proposals.\n     */\n    function castVoteBySig(uint256 proposalId, uint8 support, uint8 v, bytes32 r, bytes32 s) external {\n        ds.castVoteBySig(proposalId, support, v, r, s);\n    }\n\n    /**\n     * @dev All other calls are called via NounsDAOAdmin\n     */\n    fallback(bytes calldata) external payable returns (bytes memory) {\n        return Address.functionDelegateCall(address(NounsDAOAdmin), msg.data);\n    }\n\n    /**\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     *   DYNAMIC QUORUM\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     */\n\n    /**\n     * @notice Quorum votes required for a specific proposal to succeed\n     * Differs from `GovernerBravo` which uses fixed amount\n     */\n    function quorumVotes(uint256 proposalId) public view returns (uint256) {\n        return ds.quorumVotes(proposalId);\n    }\n\n    /**\n     * @notice Calculates the required quorum of for-votes based on the amount of against-votes\n     *     The more against-votes there are for a proposal, the higher the required quorum is.\n     *     The quorum BPS is between `params.minQuorumVotesBPS` and params.maxQuorumVotesBPS.\n     *     The additional quorum is calculated as:\n     *       quorumCoefficient * againstVotesBPS\n     * @dev Note the coefficient is a fixed point integer with 6 decimals\n     * @param againstVotes Number of against-votes in the proposal\n     * @param adjustedTotalSupply_ The adjusted total supply of Nouns at the time of proposal creation\n     * @param params Configurable parameters for calculating the quorum based on againstVotes. See `DynamicQuorumParams` definition for additional details.\n     * @return quorumVotes The required quorum\n     */\n    function dynamicQuorumVotes(\n        uint256 againstVotes,\n        uint256 adjustedTotalSupply_,\n        DynamicQuorumParams memory params\n    ) public pure returns (uint256) {\n        return NounsDAODynamicQuorum.dynamicQuorumVotes(againstVotes, adjustedTotalSupply_, params);\n    }\n\n    /**\n     * @notice returns the dynamic quorum parameters values at a certain block number\n     * @dev The checkpoints array must not be empty, and the block number must be higher than or equal to\n     *     the block of the first checkpoint\n     * @param blockNumber_ the block number to get the params at\n     * @return The dynamic quorum parameters that were set at the given block number\n     */\n    function getDynamicQuorumParamsAt(uint256 blockNumber_) public view returns (DynamicQuorumParams memory) {\n        return ds.getDynamicQuorumParamsAt(blockNumber_);\n    }\n\n    /**\n     * @notice Current min quorum votes using Nouns adjusted total supply\n     */\n    function minQuorumVotes() public view returns (uint256) {\n        return ds.minQuorumVotes(ds.adjustedTotalSupply());\n    }\n\n    /**\n     * @notice Current max quorum votes using Nouns adjusted total supply\n     */\n    function maxQuorumVotes() public view returns (uint256) {\n        return ds.maxQuorumVotes(ds.adjustedTotalSupply());\n    }\n\n    /**\n     * @notice Get all quorum params checkpoints\n     */\n    function quorumParamsCheckpoints() public view returns (DynamicQuorumParamsCheckpoint[] memory) {\n        return ds.quorumParamsCheckpoints;\n    }\n\n    /**\n     * @notice Get a quorum params checkpoint by its index\n     */\n    function quorumParamsCheckpoints(uint256 index) public view returns (DynamicQuorumParamsCheckpoint memory) {\n        return ds.quorumParamsCheckpoints[index];\n    }\n\n    /**\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     *   STATE VARIABLE GETTERS\n     * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n     */\n\n    function admin() public view returns (address) {\n        return ds.admin;\n    }\n\n    function vetoer() public view returns (address) {\n        return ds.vetoer;\n    }\n\n    function pendingVetoer() public view returns (address) {\n        return ds.pendingVetoer;\n    }\n\n    function votingDelay() public view returns (uint256) {\n        return ds.votingDelay;\n    }\n\n    function votingPeriod() public view returns (uint256) {\n        return ds.votingPeriod;\n    }\n\n    function proposalThresholdBPS() public view returns (uint256) {\n        return ds.proposalThresholdBPS;\n    }\n\n    function quorumVotesBPS() public view returns (uint256) {\n        return ds.quorumVotesBPS;\n    }\n\n    function proposalCount() public view returns (uint256) {\n        return ds.proposalCount;\n    }\n\n    function timelock() public view returns (INounsDAOExecutor) {\n        return ds.timelock;\n    }\n\n    function nouns() public view returns (NounsTokenLike) {\n        return ds.nouns;\n    }\n\n    function latestProposalIds(address account) public view returns (uint256) {\n        return ds.latestProposalIds[account];\n    }\n\n    function lastMinuteWindowInBlocks() public view returns (uint256) {\n        return ds.lastMinuteWindowInBlocks;\n    }\n\n    function objectionPeriodDurationInBlocks() public view returns (uint256) {\n        return ds.objectionPeriodDurationInBlocks;\n    }\n\n    function erc20TokensToIncludeInFork() public view returns (address[] memory) {\n        return ds.erc20TokensToIncludeInFork;\n    }\n\n    function forkEscrow() public view returns (INounsDAOForkEscrow) {\n        return ds.forkEscrow;\n    }\n\n    function forkDAODeployer() public view returns (IForkDAODeployer) {\n        return ds.forkDAODeployer;\n    }\n\n    function forkEndTimestamp() public view returns (uint256) {\n        return ds.forkEndTimestamp;\n    }\n\n    function forkPeriod() public view returns (uint256) {\n        return ds.forkPeriod;\n    }\n\n    function forkThresholdBPS() public view returns (uint256) {\n        return ds.forkThresholdBPS;\n    }\n\n    function proposalUpdatablePeriodInBlocks() public view returns (uint256) {\n        return ds.proposalUpdatablePeriodInBlocks;\n    }\n\n    function timelockV1() public view returns (address) {\n        return address(ds.timelockV1);\n    }\n\n    function voteSnapshotBlockSwitchProposalId() public view returns (uint256) {\n        return ds.voteSnapshotBlockSwitchProposalId;\n    }\n\n    receive() external payable {}\n}\n"
      },
      "contracts/governance/NounsDAOInterfaces.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\n\n/// @title Nouns DAO Logic interfaces and events\n\n/*********************************\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░██░░░████░░██░░░████░░░ *\n * ░░██████░░░████████░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n *********************************/\n\n// LICENSE\n// NounsDAOInterfaces.sol is a modified version of Compound Lab's GovernorBravoInterfaces.sol:\n// https://github.com/compound-finance/compound-protocol/blob/b9b14038612d846b83f8a009a82c38974ff2dcfe/contracts/Governance/GovernorBravoInterfaces.sol\n//\n// GovernorBravoInterfaces.sol source code Copyright 2020 Compound Labs, Inc. licensed under the BSD-3-Clause license.\n// With modifications by Nounders DAO.\n//\n// Additional conditions of BSD-3-Clause can be found here: https://opensource.org/licenses/BSD-3-Clause\n//\n// MODIFICATIONS\n// NounsDAOEvents, NounsDAOProxyStorage, NounsDAOStorageV1 add support for changes made by Nouns DAO to GovernorBravo.sol\n// See NounsDAOLogicV1.sol for more details.\n// NounsDAOStorageV1Adjusted and NounsDAOStorageV2 add support for a dynamic vote quorum.\n// See NounsDAOLogicV2.sol for more details.\n// NounsDAOStorageV3\n// See NounsDAOLogicV3.sol for more details.\n\npragma solidity ^0.8.19;\n\ninterface NounsDAOEventsV3 {\n    /// @notice An event emitted when a new proposal is created\n    event ProposalCreated(\n        uint256 id,\n        address proposer,\n        address[] targets,\n        uint256[] values,\n        string[] signatures,\n        bytes[] calldatas,\n        uint256 startBlock,\n        uint256 endBlock,\n        string description\n    );\n\n    /// @notice An event emitted when a new proposal is created, which includes additional information\n    event ProposalCreatedWithRequirements(\n        uint256 id,\n        address proposer,\n        address[] targets,\n        uint256[] values,\n        string[] signatures,\n        bytes[] calldatas,\n        uint256 startBlock,\n        uint256 endBlock,\n        uint256 proposalThreshold,\n        uint256 quorumVotes,\n        string description\n    );\n\n    /// @notice An event emitted when a vote has been cast on a proposal\n    /// @param voter The address which casted a vote\n    /// @param proposalId The proposal id which was voted on\n    /// @param support Support value for the vote. 0=against, 1=for, 2=abstain\n    /// @param votes Number of votes which were cast by the voter\n    /// @param reason The reason given for the vote by the voter\n    event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 votes, string reason);\n\n    /// @notice An event emitted when a proposal has been canceled\n    event ProposalCanceled(uint256 id);\n\n    /// @notice An event emitted when a proposal has been queued in the NounsDAOExecutor\n    event ProposalQueued(uint256 id, uint256 eta);\n\n    /// @notice An event emitted when a proposal has been executed in the NounsDAOExecutor\n    event ProposalExecuted(uint256 id);\n\n    /// @notice An event emitted when a proposal has been vetoed by vetoAddress\n    event ProposalVetoed(uint256 id);\n\n    /// @notice An event emitted when the voting delay is set\n    event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);\n\n    /// @notice An event emitted when the voting period is set\n    event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);\n\n    /// @notice Emitted when proposal threshold basis points is set\n    event ProposalThresholdBPSSet(uint256 oldProposalThresholdBPS, uint256 newProposalThresholdBPS);\n\n    /// @notice Emitted when quorum votes basis points is set\n    event QuorumVotesBPSSet(uint256 oldQuorumVotesBPS, uint256 newQuorumVotesBPS);\n\n    /// @notice Emitted when pendingAdmin is changed\n    event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n    /// @notice Emitted when pendingAdmin is accepted, which means admin is updated\n    event NewAdmin(address oldAdmin, address newAdmin);\n\n    /// @notice Emitted when vetoer is changed\n    event NewVetoer(address oldVetoer, address newVetoer);\n\n    /// @notice Emitted when minQuorumVotesBPS is set\n    event MinQuorumVotesBPSSet(uint16 oldMinQuorumVotesBPS, uint16 newMinQuorumVotesBPS);\n\n    /// @notice Emitted when maxQuorumVotesBPS is set\n    event MaxQuorumVotesBPSSet(uint16 oldMaxQuorumVotesBPS, uint16 newMaxQuorumVotesBPS);\n\n    /// @notice Emitted when quorumCoefficient is set\n    event QuorumCoefficientSet(uint32 oldQuorumCoefficient, uint32 newQuorumCoefficient);\n\n    /// @notice Emitted when a voter cast a vote requesting a gas refund.\n    event RefundableVote(address indexed voter, uint256 refundAmount, bool refundSent);\n\n    /// @notice Emitted when admin withdraws the DAO's balance.\n    event Withdraw(uint256 amount, bool sent);\n\n    /// @notice Emitted when pendingVetoer is changed\n    event NewPendingVetoer(address oldPendingVetoer, address newPendingVetoer);\n\n    /// @notice An event emitted when a new proposal is created, which includes additional information\n    /// @dev V3 adds `signers`, `updatePeriodEndBlock` compared to the V1/V2 event.\n    /// @dev V4: Removed data that's already emitted in `ProposalCreated`, added clientId\n    event ProposalCreatedWithRequirements(\n        uint256 id,\n        address[] signers,\n        uint256 updatePeriodEndBlock,\n        uint256 proposalThreshold,\n        uint256 quorumVotes,\n        uint32 indexed clientId\n    );\n\n    /// @notice Emitted when a proposal is created to be executed on timelockV1\n    event ProposalCreatedOnTimelockV1(uint256 id);\n\n    /// @notice Emitted when a proposal is updated\n    event ProposalUpdated(\n        uint256 indexed id,\n        address indexed proposer,\n        address[] targets,\n        uint256[] values,\n        string[] signatures,\n        bytes[] calldatas,\n        string description,\n        string updateMessage\n    );\n\n    /// @notice Emitted when a proposal's transactions are updated\n    event ProposalTransactionsUpdated(\n        uint256 indexed id,\n        address indexed proposer,\n        address[] targets,\n        uint256[] values,\n        string[] signatures,\n        bytes[] calldatas,\n        string updateMessage\n    );\n\n    /// @notice Emitted when a proposal's description is updated\n    event ProposalDescriptionUpdated(\n        uint256 indexed id,\n        address indexed proposer,\n        string description,\n        string updateMessage\n    );\n\n    /// @notice Emitted when a proposal is set to have an objection period\n    event ProposalObjectionPeriodSet(uint256 indexed id, uint256 objectionPeriodEndBlock);\n\n    /// @notice Emitted when someone cancels a signature\n    event SignatureCancelled(address indexed signer, bytes sig);\n\n    /// @notice An event emitted when the objection period duration is set\n    event ObjectionPeriodDurationSet(\n        uint32 oldObjectionPeriodDurationInBlocks,\n        uint32 newObjectionPeriodDurationInBlocks\n    );\n\n    /// @notice An event emitted when the objection period last minute window is set\n    event LastMinuteWindowSet(uint32 oldLastMinuteWindowInBlocks, uint32 newLastMinuteWindowInBlocks);\n\n    /// @notice An event emitted when the proposal updatable period is set\n    event ProposalUpdatablePeriodSet(\n        uint32 oldProposalUpdatablePeriodInBlocks,\n        uint32 newProposalUpdatablePeriodInBlocks\n    );\n\n    /// @notice Emitted when the erc20 tokens to include in a fork are set\n    event ERC20TokensToIncludeInForkSet(address[] oldErc20Tokens, address[] newErc20tokens);\n\n    /// @notice Emitted when the fork DAO deployer is set\n    event ForkDAODeployerSet(address oldForkDAODeployer, address newForkDAODeployer);\n\n    /// @notice Emitted when the during of the forking period is set\n    event ForkPeriodSet(uint256 oldForkPeriod, uint256 newForkPeriod);\n\n    /// @notice Emitted when the threhsold for forking is set\n    event ForkThresholdSet(uint256 oldForkThreshold, uint256 newForkThreshold);\n\n    /// @notice Emitted when the main timelock, timelockV1 and admin are set\n    event TimelocksAndAdminSet(address timelock, address timelockV1, address admin);\n\n    /// @notice Emitted when someones adds nouns to the fork escrow\n    event EscrowedToFork(\n        uint32 indexed forkId,\n        address indexed owner,\n        uint256[] tokenIds,\n        uint256[] proposalIds,\n        string reason\n    );\n\n    /// @notice Emitted when the owner withdraws their nouns from the fork escrow\n    event WithdrawFromForkEscrow(uint32 indexed forkId, address indexed owner, uint256[] tokenIds);\n\n    /// @notice Emitted when the fork is executed and the forking period begins\n    event ExecuteFork(\n        uint32 indexed forkId,\n        address forkTreasury,\n        address forkToken,\n        uint256 forkEndTimestamp,\n        uint256 tokensInEscrow\n    );\n\n    /// @notice Emitted when someone joins a fork during the forking period\n    event JoinFork(\n        uint32 indexed forkId,\n        address indexed owner,\n        uint256[] tokenIds,\n        uint256[] proposalIds,\n        string reason\n    );\n\n    /// @notice Emitted when the DAO withdraws nouns from the fork escrow after a fork has been executed\n    event DAOWithdrawNounsFromEscrow(uint256[] tokenIds, address to);\n\n    /// @notice Emitted when withdrawing nouns from escrow increases adjusted total supply\n    event DAONounsSupplyIncreasedFromEscrow(uint256 numTokens, address to);\n\n    /// @notice An event emitted when a vote has been cast with a non-zero client Id.\n    /// @dev Assumes the `VoteCast` event is emitted, and that indexers can use the voter address and propose ID to\n    /// find the relevant vote and set its client ID.\n    event VoteCastWithClientId(address indexed voter, uint256 indexed proposalId, uint32 indexed clientId);\n}\n\ninterface INounsDAOExecutor {\n    function delay() external view returns (uint256);\n\n    function GRACE_PERIOD() external view returns (uint256);\n\n    function acceptAdmin() external;\n\n    function queuedTransactions(bytes32 hash) external view returns (bool);\n\n    function queueTransaction(\n        address target,\n        uint256 value,\n        string calldata signature,\n        bytes calldata data,\n        uint256 eta\n    ) external returns (bytes32);\n\n    function cancelTransaction(\n        address target,\n        uint256 value,\n        string calldata signature,\n        bytes calldata data,\n        uint256 eta\n    ) external;\n\n    function executeTransaction(\n        address target,\n        uint256 value,\n        string calldata signature,\n        bytes calldata data,\n        uint256 eta\n    ) external payable returns (bytes memory);\n}\n\ninterface NounsTokenLike {\n    function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96);\n\n    function totalSupply() external view returns (uint256);\n\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    function minter() external view returns (address);\n\n    function mint() external returns (uint256);\n\n    function setApprovalForAll(address operator, bool approved) external;\n}\n\ninterface IForkDAODeployer {\n    function deployForkDAO(\n        uint256 forkingPeriodEndTimestamp,\n        INounsDAOForkEscrow forkEscrowAddress\n    ) external returns (address treasury, address token);\n\n    function tokenImpl() external view returns (address);\n\n    function auctionImpl() external view returns (address);\n\n    function governorImpl() external view returns (address);\n\n    function treasuryImpl() external view returns (address);\n}\n\ninterface INounsDAOExecutorV2 is INounsDAOExecutor {\n    function sendETH(address recipient, uint256 ethToSend) external;\n\n    function sendERC20(address recipient, address erc20Token, uint256 tokensToSend) external;\n}\n\ninterface INounsDAOForkEscrow {\n    function markOwner(address owner, uint256[] calldata tokenIds) external;\n\n    function returnTokensToOwner(address owner, uint256[] calldata tokenIds) external;\n\n    function closeEscrow() external returns (uint32);\n\n    function numTokensInEscrow() external view returns (uint256);\n\n    function numTokensOwnedByDAO() external view returns (uint256);\n\n    function withdrawTokens(uint256[] calldata tokenIds, address to) external;\n\n    function forkId() external view returns (uint32);\n\n    function nounsToken() external view returns (NounsTokenLike);\n\n    function dao() external view returns (address);\n\n    function ownerOfEscrowedToken(uint32 forkId_, uint256 tokenId) external view returns (address);\n}\n\ninterface NounsDAOTypes {\n    struct Storage {\n        // ================ PROXY ================ //\n        /// @notice Administrator for this contract\n        address admin;\n        /// @notice Pending administrator for this contract\n        address pendingAdmin;\n        /// @notice Active brains of Governor\n        address implementation;\n        // ================ V1 ================ //\n        /// @notice Vetoer who has the ability to veto any proposal\n        address vetoer;\n        /// @notice The delay before voting on a proposal may take place, once proposed, in blocks\n        uint256 votingDelay;\n        /// @notice The duration of voting on a proposal, in blocks\n        uint256 votingPeriod;\n        /// @notice The basis point number of votes required in order for a voter to become a proposer. *DIFFERS from GovernerBravo\n        uint256 proposalThresholdBPS;\n        /// @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\n        uint256 quorumVotesBPS;\n        /// @notice The total number of proposals\n        uint256 proposalCount;\n        /// @notice The address of the Nouns DAO Executor NounsDAOExecutor\n        INounsDAOExecutorV2 timelock;\n        /// @notice The address of the Nouns tokens\n        NounsTokenLike nouns;\n        /// @notice The official record of all proposals ever proposed\n        mapping(uint256 => Proposal) _proposals;\n        /// @notice The latest proposal for each proposer\n        mapping(address => uint256) latestProposalIds;\n        // ================ V2 ================ //\n        DynamicQuorumParamsCheckpoint[] quorumParamsCheckpoints;\n        /// @notice Pending new vetoer\n        address pendingVetoer;\n        // ================ V3 ================ //\n        /// @notice user => sig => isCancelled: signatures that have been cancelled by the signer and are no longer valid\n        mapping(address => mapping(bytes32 => bool)) cancelledSigs;\n        /// @notice The number of blocks before voting ends during which the objection period can be initiated\n        uint32 lastMinuteWindowInBlocks;\n        /// @notice Length of the objection period in blocks\n        uint32 objectionPeriodDurationInBlocks;\n        /// @notice Length of proposal updatable period in block\n        uint32 proposalUpdatablePeriodInBlocks;\n        /// @notice address of the DAO's fork escrow contract\n        INounsDAOForkEscrow forkEscrow;\n        /// @notice address of the DAO's fork deployer contract\n        IForkDAODeployer forkDAODeployer;\n        /// @notice ERC20 tokens to include when sending funds to a deployed fork\n        address[] erc20TokensToIncludeInFork;\n        /// @notice The treasury contract of the last deployed fork\n        address forkDAOTreasury;\n        /// @notice The token contract of the last deployed fork\n        address forkDAOToken;\n        /// @notice Timestamp at which the last fork period ends\n        uint256 forkEndTimestamp;\n        /// @notice Fork period in seconds\n        uint256 forkPeriod;\n        /// @notice Threshold defined in basis points (10,000 = 100%) required for forking\n        uint256 forkThresholdBPS;\n        /// @notice Address of the original timelock\n        INounsDAOExecutor timelockV1;\n        /// @dev Make sure this stays the last variable in this struct, so we can delete it in the next version\n        /// @dev To be zeroed-out in the upcoming DAO upgrade.\n        uint256 voteSnapshotBlockSwitchProposalId;\n    }\n\n    struct Proposal {\n        /// @notice Unique id for looking up a proposal\n        uint32 id;\n        /// @notice client id for rewards\n        uint32 clientId;\n        /// @notice currently unused\n        uint192 _gap;\n        /// @notice Creator of the proposal\n        address proposer;\n        /// @notice The number of votes needed to create a proposal at the time of proposal creation. *DIFFERS from GovernerBravo\n        uint256 proposalThreshold;\n        /// @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\n        uint256 quorumVotes;\n        /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds\n        uint256 eta;\n        /// @notice the ordered list of target addresses for calls to be made\n        address[] targets;\n        /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made\n        uint256[] values;\n        /// @notice The ordered list of function signatures to be called\n        string[] signatures;\n        /// @notice The ordered list of calldata to be passed to each call\n        bytes[] calldatas;\n        /// @notice The block at which voting begins: holders must delegate their votes prior to this block\n        uint256 startBlock;\n        /// @notice The block at which voting ends: votes must be cast prior to this block\n        uint256 endBlock;\n        /// @notice Current number of votes in favor of this proposal\n        uint256 forVotes;\n        /// @notice Current number of votes in opposition to this proposal\n        uint256 againstVotes;\n        /// @notice Current number of votes for abstaining for this proposal\n        uint256 abstainVotes;\n        /// @notice Flag marking whether the proposal has been canceled\n        bool canceled;\n        /// @notice Flag marking whether the proposal has been vetoed\n        bool vetoed;\n        /// @notice Flag marking whether the proposal has been executed\n        bool executed;\n        /// @notice Receipts of ballots for the entire set of voters\n        mapping(address => Receipt) receipts;\n        /// @notice The total supply at the time of proposal creation\n        uint256 totalSupply;\n        /// @notice The block at which this proposal was created\n        uint32 creationBlock;\n        /// @notice The timestamp of the block at which this proposal was created\n        uint32 creationTimestamp;\n        /// @notice The last block which allows updating a proposal's description and transactions\n        uint64 updatePeriodEndBlock;\n        /// @notice Starts at 0 and is set to the block at which the objection period ends when the objection period is initiated\n        uint64 objectionPeriodEndBlock;\n        /// @dev unused for now\n        uint64 placeholder;\n        /// @notice The signers of a proposal, when using proposeBySigs\n        address[] signers;\n        /// @notice When true, a proposal would be executed on timelockV1 instead of the current timelock\n        bool executeOnTimelockV1;\n        /// @notice How many votes and vote transactions each clientId contributed to this proposal\n        mapping(uint32 => ClientVoteData) voteClients;\n    }\n\n    struct ClientVoteData {\n        /// @notice The number of votes the client facilitated on a proposal\n        uint32 votes;\n        /// @notice The number of vote transactions the client facilitated on a proposal\n        uint32 txs;\n    }\n\n    /// @notice Ballot receipt record for a voter\n    struct Receipt {\n        /// @notice Whether or not a vote has been cast\n        bool hasVoted;\n        /// @notice Whether or not the voter supports the proposal or abstains\n        uint8 support;\n        /// @notice The number of votes the voter had, which were cast\n        uint96 votes;\n    }\n\n    struct ProposerSignature {\n        /// @notice Signature of a proposal\n        bytes sig;\n        /// @notice The address of the signer\n        address signer;\n        /// @notice The timestamp until which the signature is valid\n        uint256 expirationTimestamp;\n    }\n\n    /// @notice A subset of Proposal data, used for client rewards calculation\n    struct ProposalForRewards {\n        /// @notice The proposal's voting period end block\n        uint256 endBlock;\n        /// @notice The proposal's objection period end block\n        uint256 objectionPeriodEndBlock;\n        /// @notice The proposal's For votes count\n        uint256 forVotes;\n        /// @notice The proposal's Against votes count\n        uint256 againstVotes;\n        /// @notice The proposal's Abstain votes count\n        uint256 abstainVotes;\n        /// @notice The proposal's snapshot of total supply\n        uint256 totalSupply;\n        /// @notice The timestamp of the block at which the proposal was created\n        uint256 creationTimestamp;\n        /// @notice The ID for the client that facilitated the proposal\n        uint32 clientId;\n        ClientVoteData[] voteData;\n    }\n\n    struct ProposalCondensedV3 {\n        /// @notice Unique id for looking up a proposal\n        uint256 id;\n        /// @notice Creator of the proposal\n        address proposer;\n        /// @notice The number of votes needed to create a proposal at the time of proposal creation. *DIFFERS from GovernerBravo\n        uint256 proposalThreshold;\n        /// @notice The minimum 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\n        uint256 quorumVotes;\n        /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds\n        uint256 eta;\n        /// @notice The block at which voting begins: holders must delegate their votes prior to this block\n        uint256 startBlock;\n        /// @notice The block at which voting ends: votes must be cast prior to this block\n        uint256 endBlock;\n        /// @notice Current number of votes in favor of this proposal\n        uint256 forVotes;\n        /// @notice Current number of votes in opposition to this proposal\n        uint256 againstVotes;\n        /// @notice Current number of votes for abstaining for this proposal\n        uint256 abstainVotes;\n        /// @notice Flag marking whether the proposal has been canceled\n        bool canceled;\n        /// @notice Flag marking whether the proposal has been vetoed\n        bool vetoed;\n        /// @notice Flag marking whether the proposal has been executed\n        bool executed;\n        /// @notice The total supply at the time of proposal creation\n        uint256 totalSupply;\n        /// @notice The block at which this proposal was created\n        uint256 creationBlock;\n        /// @notice The signers of a proposal, when using proposeBySigs\n        address[] signers;\n        /// @notice The last block which allows updating a proposal's description and transactions\n        uint256 updatePeriodEndBlock;\n        /// @notice Starts at 0 and is set to the block at which the objection period ends when the objection period is initiated\n        uint256 objectionPeriodEndBlock;\n        /// @notice When true, a proposal would be executed on timelockV1 instead of the current timelock\n        bool executeOnTimelockV1;\n    }\n\n    struct ProposalCondensedV2 {\n        /// @notice Unique id for looking up a proposal\n        uint256 id;\n        /// @notice Creator of the proposal\n        address proposer;\n        /// @notice The number of votes needed to create a proposal at the time of proposal creation. *DIFFERS from GovernerBravo\n        uint256 proposalThreshold;\n        /// @notice The minimum 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\n        uint256 quorumVotes;\n        /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds\n        uint256 eta;\n        /// @notice The block at which voting begins: holders must delegate their votes prior to this block\n        uint256 startBlock;\n        /// @notice The block at which voting ends: votes must be cast prior to this block\n        uint256 endBlock;\n        /// @notice Current number of votes in favor of this proposal\n        uint256 forVotes;\n        /// @notice Current number of votes in opposition to this proposal\n        uint256 againstVotes;\n        /// @notice Current number of votes for abstaining for this proposal\n        uint256 abstainVotes;\n        /// @notice Flag marking whether the proposal has been canceled\n        bool canceled;\n        /// @notice Flag marking whether the proposal has been vetoed\n        bool vetoed;\n        /// @notice Flag marking whether the proposal has been executed\n        bool executed;\n        /// @notice The total supply at the time of proposal creation\n        uint256 totalSupply;\n        /// @notice The block at which this proposal was created\n        uint256 creationBlock;\n    }\n\n    struct DynamicQuorumParams {\n        /// @notice The minimum 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.\n        uint16 minQuorumVotesBPS;\n        /// @notice The maximum 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.\n        uint16 maxQuorumVotesBPS;\n        /// @notice The dynamic quorum coefficient\n        /// @dev Assumed to be fixed point integer with 6 decimals, i.e 0.2 is represented as 0.2 * 1e6 = 200000\n        uint32 quorumCoefficient;\n    }\n\n    struct NounsDAOParams {\n        uint256 votingPeriod;\n        uint256 votingDelay;\n        uint256 proposalThresholdBPS;\n        uint32 lastMinuteWindowInBlocks;\n        uint32 objectionPeriodDurationInBlocks;\n        uint32 proposalUpdatablePeriodInBlocks;\n    }\n\n    /// @notice A checkpoint for storing dynamic quorum params from a given block\n    struct DynamicQuorumParamsCheckpoint {\n        /// @notice The block at which the new values were set\n        uint32 fromBlock;\n        /// @notice The parameter values of this checkpoint\n        DynamicQuorumParams params;\n    }\n\n    /// @notice Possible states that a proposal may be in\n    enum ProposalState {\n        Pending,\n        Active,\n        Canceled,\n        Defeated,\n        Succeeded,\n        Queued,\n        Expired,\n        Executed,\n        Vetoed,\n        ObjectionPeriod,\n        Updatable\n    }\n}\n\ncontract NounsDAOStorage is NounsDAOTypes {\n    Storage ds;\n}\n"
      },
      "contracts/governance/NounsDAOAdmin.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\n/// @title Library for Nouns DAO Logic containing admin related functions\n\n/*********************************\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░██░░░████░░██░░░████░░░ *\n * ░░██████░░░████████░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n *********************************/\n\npragma solidity ^0.8.19;\n\nimport './NounsDAOInterfaces.sol';\nimport { NounsDAODynamicQuorum } from './NounsDAODynamicQuorum.sol';\n\nlibrary NounsDAOAdmin {\n    using NounsDAODynamicQuorum for NounsDAOTypes.Storage;\n\n    error AdminOnly();\n    error VetoerOnly();\n    error PendingVetoerOnly();\n    error InvalidMinQuorumVotesBPS();\n    error InvalidMaxQuorumVotesBPS();\n    error MinQuorumBPSGreaterThanMaxQuorumBPS();\n    error ForkPeriodTooLong();\n    error ForkPeriodTooShort();\n    error InvalidObjectionPeriodDurationInBlocks();\n    error InvalidProposalUpdatablePeriodInBlocks();\n    error VoteSnapshotSwitchAlreadySet();\n    error DuplicateTokenAddress();\n\n    /// @notice Emitted when proposal threshold basis points is set\n    event ProposalThresholdBPSSet(uint256 oldProposalThresholdBPS, uint256 newProposalThresholdBPS);\n\n    /// @notice An event emitted when the voting delay is set\n    event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);\n\n    /// @notice An event emitted when the voting period is set\n    event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);\n\n    /// @notice An event emitted when the objection period duration is set\n    event ObjectionPeriodDurationSet(\n        uint32 oldObjectionPeriodDurationInBlocks,\n        uint32 newObjectionPeriodDurationInBlocks\n    );\n\n    /// @notice An event emitted when the objection period last minute window is set\n    event LastMinuteWindowSet(uint32 oldLastMinuteWindowInBlocks, uint32 newLastMinuteWindowInBlocks);\n\n    /// @notice An event emitted when the proposal updatable period is set\n    event ProposalUpdatablePeriodSet(\n        uint32 oldProposalUpdatablePeriodInBlocks,\n        uint32 newProposalUpdatablePeriodInBlocks\n    );\n\n    /// @notice Emitted when pendingAdmin is changed\n    event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n    /// @notice Emitted when pendingAdmin is accepted, which means admin is updated\n    event NewAdmin(address oldAdmin, address newAdmin);\n\n    /// @notice Emitted when pendingVetoer is changed\n    event NewPendingVetoer(address oldPendingVetoer, address newPendingVetoer);\n\n    /// @notice Emitted when vetoer is changed\n    event NewVetoer(address oldVetoer, address newVetoer);\n\n    /// @notice Emitted when minQuorumVotesBPS is set\n    event MinQuorumVotesBPSSet(uint16 oldMinQuorumVotesBPS, uint16 newMinQuorumVotesBPS);\n\n    /// @notice Emitted when maxQuorumVotesBPS is set\n    event MaxQuorumVotesBPSSet(uint16 oldMaxQuorumVotesBPS, uint16 newMaxQuorumVotesBPS);\n\n    /// @notice Emitted when quorumCoefficient is set\n    event QuorumCoefficientSet(uint32 oldQuorumCoefficient, uint32 newQuorumCoefficient);\n\n    /// @notice Emitted when admin withdraws the DAO's balance.\n    event Withdraw(uint256 amount, bool sent);\n\n    /// @notice Emitted when the fork DAO deployer is set\n    event ForkDAODeployerSet(address oldForkDAODeployer, address newForkDAODeployer);\n\n    /// @notice Emitted when the erc20 tokens to include in a fork are set\n    event ERC20TokensToIncludeInForkSet(address[] oldErc20Tokens, address[] newErc20tokens);\n\n    /// @notice Emitted when the fork escrow contract address is set\n    event ForkEscrowSet(address oldForkEscrow, address newForkEscrow);\n\n    /// @notice Emitted when the during of the forking period is set\n    event ForkPeriodSet(uint256 oldForkPeriod, uint256 newForkPeriod);\n\n    /// @notice Emitted when the threhsold for forking is set\n    event ForkThresholdSet(uint256 oldForkThreshold, uint256 newForkThreshold);\n\n    /// @notice Emitted when the main timelock, timelockV1 and admin are set\n    event TimelocksAndAdminSet(address timelock, address timelockV1, address admin);\n\n    /// @notice The minimum setable proposal threshold\n    uint256 public constant MIN_PROPOSAL_THRESHOLD_BPS = 1; // 1 basis point or 0.01%\n\n    /// @notice The maximum setable proposal threshold\n    uint256 public constant MAX_PROPOSAL_THRESHOLD_BPS = 1_000; // 1,000 basis points or 10%\n\n    /// @notice The minimum setable voting period in blocks\n    uint256 public constant MIN_VOTING_PERIOD_BLOCKS = 1 days / 12;\n\n    /// @notice The max setable voting period in blocks\n    uint256 public constant MAX_VOTING_PERIOD_BLOCKS = 2 weeks / 12;\n\n    /// @notice The min setable voting delay in blocks\n    uint256 public constant MIN_VOTING_DELAY_BLOCKS = 1;\n\n    /// @notice The max setable voting delay in blocks\n    uint256 public constant MAX_VOTING_DELAY_BLOCKS = 2 weeks / 12;\n\n    /// @notice The lower bound of minimum quorum votes basis points\n    uint256 public constant MIN_QUORUM_VOTES_BPS_LOWER_BOUND = 200; // 200 basis points or 2%\n\n    /// @notice The upper bound of minimum quorum votes basis points\n    uint256 public constant MIN_QUORUM_VOTES_BPS_UPPER_BOUND = 2_000; // 2,000 basis points or 20%\n\n    /// @notice The upper bound of maximum quorum votes basis points\n    uint256 public constant MAX_QUORUM_VOTES_BPS_UPPER_BOUND = 6_000; // 6,000 basis points or 60%\n\n    /// @notice Upper bound for forking period. If forking period is too high it can block proposals for too long.\n    uint256 public constant MAX_FORK_PERIOD = 14 days;\n\n    /// @notice Lower bound for forking period\n    uint256 public constant MIN_FORK_PERIOD = 2 days;\n\n    /// @notice Upper bound for objection period duration in blocks.\n    uint256 public constant MAX_OBJECTION_PERIOD_BLOCKS = 7 days / 12;\n\n    /// @notice Upper bound for proposal updatable period duration in blocks.\n    uint256 public constant MAX_UPDATABLE_PERIOD_BLOCKS = 7 days / 12;\n\n    modifier onlyAdmin() {\n        if (msg.sender != ds().admin) {\n            revert AdminOnly();\n        }\n        _;\n    }\n\n    /**\n     * @notice Admin function for setting the voting delay. Best to set voting delay to at least a few days, to give\n     * voters time to make sense of proposals, e.g. 21,600 blocks which should be at least 3 days.\n     * @param newVotingDelay new voting delay, in blocks\n     */\n    function _setVotingDelay(uint256 newVotingDelay) external onlyAdmin {\n        require(\n            newVotingDelay >= MIN_VOTING_DELAY_BLOCKS && newVotingDelay <= MAX_VOTING_DELAY_BLOCKS,\n            'NounsDAO::_setVotingDelay: invalid voting delay'\n        );\n        uint256 oldVotingDelay = ds().votingDelay;\n        ds().votingDelay = newVotingDelay;\n\n        emit VotingDelaySet(oldVotingDelay, newVotingDelay);\n    }\n\n    /**\n     * @notice Admin function for setting the voting period\n     * @param newVotingPeriod new voting period, in blocks\n     */\n    function _setVotingPeriod(uint256 newVotingPeriod) external onlyAdmin {\n        require(\n            newVotingPeriod >= MIN_VOTING_PERIOD_BLOCKS && newVotingPeriod <= MAX_VOTING_PERIOD_BLOCKS,\n            'NounsDAO::_setVotingPeriod: invalid voting period'\n        );\n        uint256 oldVotingPeriod = ds().votingPeriod;\n        ds().votingPeriod = newVotingPeriod;\n\n        emit VotingPeriodSet(oldVotingPeriod, newVotingPeriod);\n    }\n\n    /**\n     * @notice Admin function for setting the proposal threshold basis points\n     * @dev newProposalThresholdBPS must be in [`MIN_PROPOSAL_THRESHOLD_BPS`,`MAX_PROPOSAL_THRESHOLD_BPS`]\n     * @param newProposalThresholdBPS new proposal threshold\n     */\n    function _setProposalThresholdBPS(uint256 newProposalThresholdBPS) external onlyAdmin {\n        require(\n            newProposalThresholdBPS >= MIN_PROPOSAL_THRESHOLD_BPS &&\n                newProposalThresholdBPS <= MAX_PROPOSAL_THRESHOLD_BPS,\n            'NounsDAO::_setProposalThreshold: invalid proposal threshold bps'\n        );\n        uint256 oldProposalThresholdBPS = ds().proposalThresholdBPS;\n        ds().proposalThresholdBPS = newProposalThresholdBPS;\n\n        emit ProposalThresholdBPSSet(oldProposalThresholdBPS, newProposalThresholdBPS);\n    }\n\n    /**\n     * @notice Admin function for setting the objection period duration\n     * @param newObjectionPeriodDurationInBlocks new objection period duration, in blocks\n     */\n    function _setObjectionPeriodDurationInBlocks(uint32 newObjectionPeriodDurationInBlocks) external onlyAdmin {\n        if (newObjectionPeriodDurationInBlocks > MAX_OBJECTION_PERIOD_BLOCKS)\n            revert InvalidObjectionPeriodDurationInBlocks();\n\n        uint32 oldObjectionPeriodDurationInBlocks = ds().objectionPeriodDurationInBlocks;\n        ds().objectionPeriodDurationInBlocks = newObjectionPeriodDurationInBlocks;\n\n        emit ObjectionPeriodDurationSet(oldObjectionPeriodDurationInBlocks, newObjectionPeriodDurationInBlocks);\n    }\n\n    /**\n     * @notice Admin function for setting the objection period last minute window\n     * @param newLastMinuteWindowInBlocks new objection period last minute window, in blocks\n     */\n    function _setLastMinuteWindowInBlocks(uint32 newLastMinuteWindowInBlocks) external onlyAdmin {\n        uint32 oldLastMinuteWindowInBlocks = ds().lastMinuteWindowInBlocks;\n        ds().lastMinuteWindowInBlocks = newLastMinuteWindowInBlocks;\n\n        emit LastMinuteWindowSet(oldLastMinuteWindowInBlocks, newLastMinuteWindowInBlocks);\n    }\n\n    /**\n     * @notice Admin function for setting the proposal updatable period\n     * @param newProposalUpdatablePeriodInBlocks the new proposal updatable period, in blocks\n     */\n    function _setProposalUpdatablePeriodInBlocks(uint32 newProposalUpdatablePeriodInBlocks) external onlyAdmin {\n        if (newProposalUpdatablePeriodInBlocks > MAX_UPDATABLE_PERIOD_BLOCKS)\n            revert InvalidProposalUpdatablePeriodInBlocks();\n\n        uint32 oldProposalUpdatablePeriodInBlocks = ds().proposalUpdatablePeriodInBlocks;\n        ds().proposalUpdatablePeriodInBlocks = newProposalUpdatablePeriodInBlocks;\n\n        emit ProposalUpdatablePeriodSet(oldProposalUpdatablePeriodInBlocks, newProposalUpdatablePeriodInBlocks);\n    }\n\n    /**\n     * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n     * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n     * @param newPendingAdmin New pending admin.\n     */\n    function _setPendingAdmin(address newPendingAdmin) external onlyAdmin {\n        // Save current value, if any, for inclusion in log\n        address oldPendingAdmin = ds().pendingAdmin;\n\n        // Store pendingAdmin with value newPendingAdmin\n        ds().pendingAdmin = newPendingAdmin;\n\n        // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n        emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n    }\n\n    /**\n     * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n     * @dev Admin function for pending admin to accept role and update admin\n     */\n    function _acceptAdmin() external {\n        // Check caller is pendingAdmin and pendingAdmin ≠ address(0)\n        require(\n            msg.sender == ds().pendingAdmin && msg.sender != address(0),\n            'NounsDAO::_acceptAdmin: pending admin only'\n        );\n\n        // Save current values for inclusion in log\n        address oldAdmin = ds().admin;\n        address oldPendingAdmin = ds().pendingAdmin;\n\n        // Store admin with value pendingAdmin\n        ds().admin = ds().pendingAdmin;\n\n        // Clear the pending value\n        ds().pendingAdmin = address(0);\n\n        emit NewAdmin(oldAdmin, ds().admin);\n        emit NewPendingAdmin(oldPendingAdmin, address(0));\n    }\n\n    /**\n     * @notice Begins transition of vetoer. The newPendingVetoer must call _acceptVetoer to finalize the transfer.\n     * @param newPendingVetoer New Pending Vetoer\n     */\n    function _setPendingVetoer(address newPendingVetoer) public {\n        if (msg.sender != ds().vetoer) {\n            revert VetoerOnly();\n        }\n\n        emit NewPendingVetoer(ds().pendingVetoer, newPendingVetoer);\n\n        ds().pendingVetoer = newPendingVetoer;\n    }\n\n    /**\n     * @notice Called by the pendingVetoer to accept role and update vetoer\n     */\n    function _acceptVetoer() external {\n        if (msg.sender != ds().pendingVetoer) {\n            revert PendingVetoerOnly();\n        }\n\n        // Update vetoer\n        emit NewVetoer(ds().vetoer, ds().pendingVetoer);\n        ds().vetoer = ds().pendingVetoer;\n\n        // Clear the pending value\n        emit NewPendingVetoer(ds().pendingVetoer, address(0));\n        ds().pendingVetoer = address(0);\n    }\n\n    /**\n     * @notice Burns veto priviledges\n     * @dev Vetoer function destroying veto power forever\n     */\n    function _burnVetoPower() public {\n        // Check caller is vetoer\n        require(msg.sender == ds().vetoer, 'NounsDAO::_burnVetoPower: vetoer only');\n\n        // Update vetoer to 0x0\n        emit NewVetoer(ds().vetoer, address(0));\n        ds().vetoer = address(0);\n\n        // Clear the pending value\n        emit NewPendingVetoer(ds().pendingVetoer, address(0));\n        ds().pendingVetoer = address(0);\n    }\n\n    /**\n     * @notice Admin function for setting the minimum quorum votes bps\n     * @param newMinQuorumVotesBPS minimum quorum votes bps\n     *     Must be between `MIN_QUORUM_VOTES_BPS_LOWER_BOUND` and `MIN_QUORUM_VOTES_BPS_UPPER_BOUND`\n     *     Must be lower than or equal to maxQuorumVotesBPS\n     */\n    function _setMinQuorumVotesBPS(uint16 newMinQuorumVotesBPS) external onlyAdmin {\n        NounsDAOTypes.DynamicQuorumParams memory params = ds().getDynamicQuorumParamsAt(block.number);\n\n        require(\n            newMinQuorumVotesBPS >= MIN_QUORUM_VOTES_BPS_LOWER_BOUND &&\n                newMinQuorumVotesBPS <= MIN_QUORUM_VOTES_BPS_UPPER_BOUND,\n            'NounsDAO::_setMinQuorumVotesBPS: invalid min quorum votes bps'\n        );\n        require(\n            newMinQuorumVotesBPS <= params.maxQuorumVotesBPS,\n            'NounsDAO::_setMinQuorumVotesBPS: min quorum votes bps greater than max'\n        );\n\n        uint16 oldMinQuorumVotesBPS = params.minQuorumVotesBPS;\n        params.minQuorumVotesBPS = newMinQuorumVotesBPS;\n\n        _writeQuorumParamsCheckpoint(params);\n\n        emit MinQuorumVotesBPSSet(oldMinQuorumVotesBPS, newMinQuorumVotesBPS);\n    }\n\n    /**\n     * @notice Admin function for setting the maximum quorum votes bps\n     * @param newMaxQuorumVotesBPS maximum quorum votes bps\n     *     Must be lower than `MAX_QUORUM_VOTES_BPS_UPPER_BOUND`\n     *     Must be higher than or equal to minQuorumVotesBPS\n     */\n    function _setMaxQuorumVotesBPS(uint16 newMaxQuorumVotesBPS) external onlyAdmin {\n        NounsDAOTypes.DynamicQuorumParams memory params = ds().getDynamicQuorumParamsAt(block.number);\n\n        require(\n            newMaxQuorumVotesBPS <= MAX_QUORUM_VOTES_BPS_UPPER_BOUND,\n            'NounsDAO::_setMaxQuorumVotesBPS: invalid max quorum votes bps'\n        );\n        require(\n            params.minQuorumVotesBPS <= newMaxQuorumVotesBPS,\n            'NounsDAO::_setMaxQuorumVotesBPS: min quorum votes bps greater than max'\n        );\n\n        uint16 oldMaxQuorumVotesBPS = params.maxQuorumVotesBPS;\n        params.maxQuorumVotesBPS = newMaxQuorumVotesBPS;\n\n        _writeQuorumParamsCheckpoint(params);\n\n        emit MaxQuorumVotesBPSSet(oldMaxQuorumVotesBPS, newMaxQuorumVotesBPS);\n    }\n\n    /**\n     * @notice Admin function for setting the dynamic quorum coefficient\n     * @param newQuorumCoefficient the new coefficient, as a fixed point integer with 6 decimals\n     */\n    function _setQuorumCoefficient(uint32 newQuorumCoefficient) external onlyAdmin {\n        NounsDAOTypes.DynamicQuorumParams memory params = ds().getDynamicQuorumParamsAt(block.number);\n\n        uint32 oldQuorumCoefficient = params.quorumCoefficient;\n        params.quorumCoefficient = newQuorumCoefficient;\n\n        _writeQuorumParamsCheckpoint(params);\n\n        emit QuorumCoefficientSet(oldQuorumCoefficient, newQuorumCoefficient);\n    }\n\n    /**\n     * @notice Admin function for setting all the dynamic quorum parameters\n     * @param newMinQuorumVotesBPS minimum quorum votes bps\n     *     Must be between `MIN_QUORUM_VOTES_BPS_LOWER_BOUND` and `MIN_QUORUM_VOTES_BPS_UPPER_BOUND`\n     *     Must be lower than or equal to maxQuorumVotesBPS\n     * @param newMaxQuorumVotesBPS maximum quorum votes bps\n     *     Must be lower than `MAX_QUORUM_VOTES_BPS_UPPER_BOUND`\n     *     Must be higher than or equal to minQuorumVotesBPS\n     * @param newQuorumCoefficient the new coefficient, as a fixed point integer with 6 decimals\n     */\n    function _setDynamicQuorumParams(\n        uint16 newMinQuorumVotesBPS,\n        uint16 newMaxQuorumVotesBPS,\n        uint32 newQuorumCoefficient\n    ) public onlyAdmin {\n        if (\n            newMinQuorumVotesBPS < MIN_QUORUM_VOTES_BPS_LOWER_BOUND ||\n            newMinQuorumVotesBPS > MIN_QUORUM_VOTES_BPS_UPPER_BOUND\n        ) {\n            revert InvalidMinQuorumVotesBPS();\n        }\n        if (newMaxQuorumVotesBPS > MAX_QUORUM_VOTES_BPS_UPPER_BOUND) {\n            revert InvalidMaxQuorumVotesBPS();\n        }\n        if (newMinQuorumVotesBPS > newMaxQuorumVotesBPS) {\n            revert MinQuorumBPSGreaterThanMaxQuorumBPS();\n        }\n\n        NounsDAOTypes.DynamicQuorumParams memory oldParams = ds().getDynamicQuorumParamsAt(block.number);\n\n        NounsDAOTypes.DynamicQuorumParams memory params = NounsDAOTypes.DynamicQuorumParams({\n            minQuorumVotesBPS: newMinQuorumVotesBPS,\n            maxQuorumVotesBPS: newMaxQuorumVotesBPS,\n            quorumCoefficient: newQuorumCoefficient\n        });\n        _writeQuorumParamsCheckpoint(params);\n\n        emit MinQuorumVotesBPSSet(oldParams.minQuorumVotesBPS, params.minQuorumVotesBPS);\n        emit MaxQuorumVotesBPSSet(oldParams.maxQuorumVotesBPS, params.maxQuorumVotesBPS);\n        emit QuorumCoefficientSet(oldParams.quorumCoefficient, params.quorumCoefficient);\n    }\n\n    /**\n     * @notice Withdraws all the ETH in the contract. This is callable only by the admin (timelock).\n     */\n    function _withdraw() external onlyAdmin returns (uint256, bool) {\n        uint256 amount = address(this).balance;\n        (bool sent, ) = msg.sender.call{ value: amount }('');\n\n        emit Withdraw(amount, sent);\n\n        return (amount, sent);\n    }\n\n    /**\n     * @notice Admin function for setting the fork DAO deployer contract\n     */\n    function _setForkDAODeployer(address newForkDAODeployer) public onlyAdmin {\n        address oldForkDAODeployer = address(ds().forkDAODeployer);\n        ds().forkDAODeployer = IForkDAODeployer(newForkDAODeployer);\n\n        emit ForkDAODeployerSet(oldForkDAODeployer, newForkDAODeployer);\n    }\n\n    /**\n     * @notice Admin function for setting the ERC20 tokens that are used when splitting funds to a fork\n     */\n    function _setErc20TokensToIncludeInFork(address[] calldata erc20tokens) public onlyAdmin {\n        checkForDuplicates(erc20tokens);\n\n        emit ERC20TokensToIncludeInForkSet(ds().erc20TokensToIncludeInFork, erc20tokens);\n\n        ds().erc20TokensToIncludeInFork = erc20tokens;\n    }\n\n    /**\n     * @notice Admin function for setting the fork escrow contract\n     */\n    function _setForkEscrow(address newForkEscrow) public onlyAdmin {\n        emit ForkEscrowSet(address(ds().forkEscrow), newForkEscrow);\n\n        ds().forkEscrow = INounsDAOForkEscrow(newForkEscrow);\n    }\n\n    function _setForkPeriod(uint256 newForkPeriod) public onlyAdmin {\n        if (newForkPeriod > MAX_FORK_PERIOD) {\n            revert ForkPeriodTooLong();\n        }\n\n        if (newForkPeriod < MIN_FORK_PERIOD) {\n            revert ForkPeriodTooShort();\n        }\n\n        emit ForkPeriodSet(ds().forkPeriod, newForkPeriod);\n\n        ds().forkPeriod = newForkPeriod;\n    }\n\n    /**\n     * @notice Admin function for setting the fork threshold\n     * @param newForkThresholdBPS the new fork proposal threshold, in basis points\n     */\n    function _setForkThresholdBPS(uint256 newForkThresholdBPS) public onlyAdmin {\n        emit ForkThresholdSet(ds().forkThresholdBPS, newForkThresholdBPS);\n\n        ds().forkThresholdBPS = newForkThresholdBPS;\n    }\n\n    /**\n     * @notice Admin function for setting the fork related parameters\n     * @param forkEscrow_ the fork escrow contract\n     * @param forkDAODeployer_ the fork dao deployer contract\n     * @param erc20TokensToIncludeInFork_ the ERC20 tokens used when splitting funds to a fork\n     * @param forkPeriod_ the period during which it's possible to join a fork after exeuction\n     * @param forkThresholdBPS_ the threshold required of escrowed nouns in order to execute a fork\n     */\n    function _setForkParams(\n        address forkEscrow_,\n        address forkDAODeployer_,\n        address[] calldata erc20TokensToIncludeInFork_,\n        uint256 forkPeriod_,\n        uint256 forkThresholdBPS_\n    ) external {\n        _setForkEscrow(forkEscrow_);\n        _setForkDAODeployer(forkDAODeployer_);\n        _setErc20TokensToIncludeInFork(erc20TokensToIncludeInFork_);\n        _setForkPeriod(forkPeriod_);\n        _setForkThresholdBPS(forkThresholdBPS_);\n    }\n\n    /**\n     * @notice Admin function for setting the timelocks and admin\n     * @param timelock the new timelock contract\n     * @param timelockV1 the new timelockV1 contract\n     * @param admin the new admin address\n     */\n    function _setTimelocksAndAdmin(address timelock, address timelockV1, address admin) external onlyAdmin {\n        ds().timelock = INounsDAOExecutorV2(timelock);\n        ds().timelockV1 = INounsDAOExecutor(timelockV1);\n        ds().admin = admin;\n\n        emit TimelocksAndAdminSet(timelock, timelockV1, admin);\n    }\n\n    /**\n     * @notice Admin function for zeroing out the state variable `voteSnapshotBlockSwitchProposalId`\n     * @dev We want to zero-out this state slot so we can remove this temporary variable from contract code and \n     * be ready to reuse this slot.\n     */\n    function _zeroOutVoteSnapshotBlockSwitchProposalId() external onlyAdmin {\n        ds().voteSnapshotBlockSwitchProposalId = 0;\n    }\n\n    function _writeQuorumParamsCheckpoint(NounsDAOTypes.DynamicQuorumParams memory params) internal {\n        uint32 blockNumber = safe32(block.number, 'block number exceeds 32 bits');\n        uint256 pos = ds().quorumParamsCheckpoints.length;\n        if (pos > 0 && ds().quorumParamsCheckpoints[pos - 1].fromBlock == blockNumber) {\n            ds().quorumParamsCheckpoints[pos - 1].params = params;\n        } else {\n            ds().quorumParamsCheckpoints.push(\n                NounsDAOTypes.DynamicQuorumParamsCheckpoint({ fromBlock: blockNumber, params: params })\n            );\n        }\n    }\n\n    function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n        require(n <= type(uint32).max, errorMessage);\n        return uint32(n);\n    }\n\n    function checkForDuplicates(address[] calldata erc20tokens) internal pure {\n        if (erc20tokens.length == 0) return;\n\n        for (uint256 i = 0; i < erc20tokens.length - 1; i++) {\n            for (uint256 j = i + 1; j < erc20tokens.length; j++) {\n                if (erc20tokens[i] == erc20tokens[j]) revert DuplicateTokenAddress();\n            }\n        }\n    }\n\n    /***\n     * @dev Used to access the DAO's storage struct without receiving it as a function argument.\n     * Created as part of the DAO logic refactor where this admin library is called in the DAO's fallback function,\n     * since the DAO no longer makes explicit calls to this library.\n     * This function assumes the storage struct starts at slot 0.\n     */\n    function ds() internal pure returns (NounsDAOTypes.Storage storage ds_) {\n        assembly {\n            ds_.slot := 0\n        }\n    }\n}\n"
      },
      "contracts/governance/NounsDAODynamicQuorum.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\n/// @title Library for Nouns DAO Logic containing functions related to quorum calculations\n\n/*********************************\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░██░░░████░░██░░░████░░░ *\n * ░░██████░░░████████░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n *********************************/\n\npragma solidity ^0.8.19;\n\nimport './NounsDAOInterfaces.sol';\nimport { NounsDAOFork } from './fork/NounsDAOFork.sol';\n\nlibrary NounsDAODynamicQuorum {\n    using NounsDAOFork for NounsDAOTypes.Storage;\n\n    error UnsafeUint16Cast();\n\n    /**\n     * @notice Quorum votes required for a specific proposal to succeed\n     * Differs from `GovernerBravo` which uses fixed amount\n     */\n    function quorumVotes(NounsDAOTypes.Storage storage ds, uint256 proposalId) internal view returns (uint256) {\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n        if (proposal.totalSupply == 0) {\n            return proposal.quorumVotes;\n        }\n\n        return\n            dynamicQuorumVotes(\n                proposal.againstVotes,\n                proposal.totalSupply,\n                getDynamicQuorumParamsAt(ds, proposal.creationBlock)\n            );\n    }\n\n    /**\n     * @notice Calculates the required quorum of for-votes based on the amount of against-votes\n     *     The more against-votes there are for a proposal, the higher the required quorum is.\n     *     The quorum BPS is between `params.minQuorumVotesBPS` and params.maxQuorumVotesBPS.\n     *     The additional quorum is calculated as:\n     *       quorumCoefficient * againstVotesBPS\n     * @dev Note the coefficient is a fixed point integer with 6 decimals\n     * @param againstVotes Number of against-votes in the proposal\n     * @param totalSupply The total supply of Nouns at the time of proposal creation\n     * @param params Configurable parameters for calculating the quorum based on againstVotes. See `DynamicQuorumParams` definition for additional details.\n     * @return quorumVotes The required quorum\n     */\n    function dynamicQuorumVotes(\n        uint256 againstVotes,\n        uint256 totalSupply,\n        NounsDAOTypes.DynamicQuorumParams memory params\n    ) public pure returns (uint256) {\n        uint256 againstVotesBPS = (10000 * againstVotes) / totalSupply;\n        uint256 quorumAdjustmentBPS = (params.quorumCoefficient * againstVotesBPS) / 1e6;\n        uint256 adjustedQuorumBPS = params.minQuorumVotesBPS + quorumAdjustmentBPS;\n        uint256 quorumBPS = min(params.maxQuorumVotesBPS, adjustedQuorumBPS);\n        return bps2Uint(quorumBPS, totalSupply);\n    }\n\n    /**\n     * @notice returns the dynamic quorum parameters values at a certain block number\n     * @dev The checkpoints array must not be empty, and the block number must be higher than or equal to\n     *     the block of the first checkpoint\n     * @param blockNumber_ the block number to get the params at\n     * @return The dynamic quorum parameters that were set at the given block number\n     */\n    function getDynamicQuorumParamsAt(\n        NounsDAOTypes.Storage storage ds,\n        uint256 blockNumber_\n    ) internal view returns (NounsDAOTypes.DynamicQuorumParams memory) {\n        uint32 blockNumber = safe32(blockNumber_, 'NounsDAO::getDynamicQuorumParamsAt: block number exceeds 32 bits');\n        uint256 len = ds.quorumParamsCheckpoints.length;\n\n        if (len == 0) {\n            return\n                NounsDAOTypes.DynamicQuorumParams({\n                    minQuorumVotesBPS: safe16(ds.quorumVotesBPS),\n                    maxQuorumVotesBPS: safe16(ds.quorumVotesBPS),\n                    quorumCoefficient: 0\n                });\n        }\n\n        if (ds.quorumParamsCheckpoints[len - 1].fromBlock <= blockNumber) {\n            return ds.quorumParamsCheckpoints[len - 1].params;\n        }\n\n        if (ds.quorumParamsCheckpoints[0].fromBlock > blockNumber) {\n            return\n                NounsDAOTypes.DynamicQuorumParams({\n                    minQuorumVotesBPS: safe16(ds.quorumVotesBPS),\n                    maxQuorumVotesBPS: safe16(ds.quorumVotesBPS),\n                    quorumCoefficient: 0\n                });\n        }\n\n        uint256 lower = 0;\n        uint256 upper = len - 1;\n        while (upper > lower) {\n            uint256 center = upper - (upper - lower) / 2;\n            NounsDAOTypes.DynamicQuorumParamsCheckpoint memory cp = ds.quorumParamsCheckpoints[center];\n            if (cp.fromBlock == blockNumber) {\n                return cp.params;\n            } else if (cp.fromBlock < blockNumber) {\n                lower = center;\n            } else {\n                upper = center - 1;\n            }\n        }\n        return ds.quorumParamsCheckpoints[lower].params;\n    }\n\n    /**\n     * @notice Current min quorum votes using Nouns adjusted total supply\n     */\n    function minQuorumVotes(\n        NounsDAOTypes.Storage storage ds,\n        uint256 adjustedTotalSupply\n    ) internal view returns (uint256) {\n        return bps2Uint(getDynamicQuorumParamsAt(ds, block.number).minQuorumVotesBPS, adjustedTotalSupply);\n    }\n\n    /**\n     * @notice Current max quorum votes using Nouns adjusted total supply\n     */\n    function maxQuorumVotes(\n        NounsDAOTypes.Storage storage ds,\n        uint256 adjustedTotalSupply\n    ) internal view returns (uint256) {\n        return bps2Uint(getDynamicQuorumParamsAt(ds, block.number).maxQuorumVotesBPS, adjustedTotalSupply);\n    }\n\n    function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n        require(n <= type(uint32).max, errorMessage);\n        return uint32(n);\n    }\n\n    function safe16(uint256 n) internal pure returns (uint16) {\n        if (n > type(uint16).max) {\n            revert UnsafeUint16Cast();\n        }\n        return uint16(n);\n    }\n\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    function bps2Uint(uint256 bps, uint256 number) internal pure returns (uint256) {\n        return (number * bps) / 10000;\n    }\n}\n"
      },
      "contracts/governance/NounsDAOVotes.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\n/// @title Library for Nouns DAO Logic containing all the voting related code\n\n/*********************************\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░██░░░████░░██░░░████░░░ *\n * ░░██████░░░████████░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n *********************************/\n\npragma solidity ^0.8.19;\n\nimport './NounsDAOInterfaces.sol';\nimport { NounsDAOProposals } from './NounsDAOProposals.sol';\nimport { SafeCast } from '@openzeppelin/contracts/utils/math/SafeCast.sol';\n\nlibrary NounsDAOVotes {\n    using NounsDAOProposals for NounsDAOTypes.Storage;\n\n    error CanOnlyVoteAgainstDuringObjectionPeriod();\n\n    /// @notice An event emitted when a vote has been cast on a proposal\n    /// @param voter The address which casted a vote\n    /// @param proposalId The proposal id which was voted on\n    /// @param support Support value for the vote. 0=against, 1=for, 2=abstain\n    /// @param votes Number of votes which were cast by the voter\n    /// @param reason The reason given for the vote by the voter\n    event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 votes, string reason);\n\n    /// @notice Emitted when a voter cast a vote requesting a gas refund.\n    event RefundableVote(address indexed voter, uint256 refundAmount, bool refundSent);\n\n    /// @notice Emitted when a proposal is set to have an objection period\n    event ProposalObjectionPeriodSet(uint256 indexed id, uint256 objectionPeriodEndBlock);\n\n    /// @notice The name of this contract\n    string public constant name = 'Nouns DAO';\n\n    /// @notice The EIP-712 typehash for the contract's domain\n    bytes32 public constant DOMAIN_TYPEHASH =\n        keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');\n\n    /// @notice The EIP-712 typehash for the ballot struct used by the contract\n    bytes32 public constant BALLOT_TYPEHASH = keccak256('Ballot(uint256 proposalId,uint8 support)');\n\n    /// @notice The maximum priority fee used to cap gas refunds in `castRefundableVote`\n    uint256 public constant MAX_REFUND_PRIORITY_FEE = 2 gwei;\n\n    /// @notice The vote refund gas overhead, including 7K for ETH transfer and 29K for general transaction overhead\n    uint256 public constant REFUND_BASE_GAS = 36000;\n\n    /// @notice The maximum gas units the DAO will refund voters on; supports about 9,190 characters\n    uint256 public constant MAX_REFUND_GAS_USED = 200_000;\n\n    /// @notice The maximum basefee the DAO will refund voters on\n    uint256 public constant MAX_REFUND_BASE_FEE = 200 gwei;\n\n    /**\n     * @notice Cast a vote for a proposal\n     * @param proposalId The id of the proposal to vote on\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     */\n    function castVote(NounsDAOTypes.Storage storage ds, uint256 proposalId, uint8 support) external {\n        emit VoteCast(msg.sender, proposalId, support, castVoteInternal(ds, msg.sender, proposalId, support, 0), '');\n    }\n\n    /**\n     * @notice Cast a vote for a proposal, asking the DAO to refund gas costs.\n     * Users with > 0 votes receive refunds. Refunds are partial when using a gas priority fee higher than the DAO's cap.\n     * Refunds are partial when the DAO's balance is insufficient.\n     * No refund is sent when the DAO's balance is empty. No refund is sent to users with no votes.\n     * Voting takes place regardless of refund success.\n     * @param proposalId The id of the proposal to vote on\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     * @param clientId The ID of the client that faciliated posting the vote onchain\n     * @dev Reentrancy is defended against in `castVoteInternal` at the `receipt.hasVoted == false` require statement.\n     */\n    function castRefundableVote(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        uint8 support,\n        uint32 clientId\n    ) external {\n        castRefundableVoteInternal(ds, proposalId, support, '', clientId);\n    }\n\n    /**\n     * @notice Cast a vote for a proposal, asking the DAO to refund gas costs.\n     * Users with > 0 votes receive refunds. Refunds are partial when using a gas priority fee higher than the DAO's cap.\n     * Refunds are partial when the DAO's balance is insufficient.\n     * No refund is sent when the DAO's balance is empty. No refund is sent to users with no votes.\n     * Voting takes place regardless of refund success.\n     * @param proposalId The id of the proposal to vote on\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     * @param reason The reason given for the vote by the voter\n     * @dev Reentrancy is defended against in `castVoteInternal` at the `receipt.hasVoted == false` require statement.\n     */\n    function castRefundableVoteWithReason(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        uint8 support,\n        string calldata reason,\n        uint32 clientId\n    ) external {\n        castRefundableVoteInternal(ds, proposalId, support, reason, clientId);\n    }\n\n    /**\n     * @notice Internal function that carries out refundable voting logic\n     * @param proposalId The id of the proposal to vote on\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     * @param reason The reason given for the vote by the voter\n     * @param clientId The ID of the client that faciliated posting the vote onchain\n     * @dev Reentrancy is defended against in `castVoteInternal` at the `receipt.hasVoted == false` require statement.\n     */\n    function castRefundableVoteInternal(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        uint8 support,\n        string memory reason,\n        uint32 clientId\n    ) internal {\n        uint256 startGas = gasleft();\n        uint96 votes = castVoteInternal(ds, msg.sender, proposalId, support, clientId);\n        emit VoteCast(msg.sender, proposalId, support, votes, reason);\n        if (clientId > 0) emit NounsDAOEventsV3.VoteCastWithClientId(msg.sender, proposalId, clientId);\n        if (votes > 0) {\n            _refundGas(startGas);\n        }\n    }\n\n    /**\n     * @notice Cast a vote for a proposal with a reason\n     * @param proposalId The id of the proposal to vote on\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     * @param reason The reason given for the vote by the voter\n     */\n    function castVoteWithReason(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        uint8 support,\n        string calldata reason\n    ) external {\n        emit VoteCast(\n            msg.sender,\n            proposalId,\n            support,\n            castVoteInternal(ds, msg.sender, proposalId, support, 0),\n            reason\n        );\n    }\n\n    /**\n     * @notice Cast a vote for a proposal by signature\n     * @dev External function that accepts EIP-712 signatures for voting on proposals.\n     */\n    function castVoteBySig(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        uint8 support,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external {\n        bytes32 domainSeparator = keccak256(\n            abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), block.chainid, address(this))\n        );\n        bytes32 structHash = keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support));\n        bytes32 digest = keccak256(abi.encodePacked('\\x19\\x01', domainSeparator, structHash));\n        address signatory = ecrecover(digest, v, r, s);\n        require(signatory != address(0), 'NounsDAO::castVoteBySig: invalid signature');\n        emit VoteCast(signatory, proposalId, support, castVoteInternal(ds, signatory, proposalId, support, 0), '');\n    }\n\n    /**\n     * @notice Internal function that caries out voting logic\n     * In case of a vote during the 'last minute window', which changes the proposal outcome from being defeated to\n     * passing, and objection period is adding to the proposal's voting period.\n     * During the objection period, only votes against a proposal can be cast.\n     * @param voter The voter that is casting their vote\n     * @param proposalId The id of the proposal to vote on\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     * @param clientId The ID of the client that faciliated posting the vote onchain\n     * @return votes The number of votes cast\n     */\n    function castVoteInternal(\n        NounsDAOTypes.Storage storage ds,\n        address voter,\n        uint256 proposalId,\n        uint8 support,\n        uint32 clientId\n    ) internal returns (uint96 votes) {\n        NounsDAOTypes.ProposalState proposalState = ds.stateInternal(proposalId);\n\n        if (proposalState == NounsDAOTypes.ProposalState.Active) {\n            votes = castVoteDuringVotingPeriodInternal(ds, proposalId, voter, support);\n        } else if (proposalState == NounsDAOTypes.ProposalState.ObjectionPeriod) {\n            if (support != 0) revert CanOnlyVoteAgainstDuringObjectionPeriod();\n            votes = castObjectionInternal(ds, proposalId, voter);\n        } else {\n            revert('NounsDAO::castVoteInternal: voting is closed');\n        }\n\n        NounsDAOTypes.ClientVoteData memory voteData = ds._proposals[proposalId].voteClients[clientId];\n        ds._proposals[proposalId].voteClients[clientId] = NounsDAOTypes.ClientVoteData({\n            votes: uint32(voteData.votes + votes),\n            txs: voteData.txs + 1\n        });\n    }\n\n    /**\n     * @notice Internal function that handles voting logic during the voting period.\n     * @dev Assumes it's only called by `castVoteInternal` which ensures the proposal is active.\n     * @param proposalId The id of the proposal being voted on\n     * @param voter The address of the voter\n     * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n     * @return The number of votes cast\n     */\n    function castVoteDuringVotingPeriodInternal(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        address voter,\n        uint8 support\n    ) internal returns (uint96) {\n        require(support <= 2, 'NounsDAO::castVoteDuringVotingPeriodInternal: invalid vote type');\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n        NounsDAOTypes.Receipt storage receipt = proposal.receipts[voter];\n        require(receipt.hasVoted == false, 'NounsDAO::castVoteDuringVotingPeriodInternal: voter already voted');\n\n        uint96 votes = ds.nouns.getPriorVotes(voter, proposal.startBlock);\n\n        bool isForVoteInLastMinuteWindow = false;\n        if (support == 1) {\n            isForVoteInLastMinuteWindow = (proposal.endBlock - block.number < ds.lastMinuteWindowInBlocks);\n        }\n\n        bool isDefeatedBefore = false;\n        if (isForVoteInLastMinuteWindow) isDefeatedBefore = ds.isDefeated(proposal);\n\n        if (support == 0) {\n            proposal.againstVotes = proposal.againstVotes + votes;\n        } else if (support == 1) {\n            proposal.forVotes = proposal.forVotes + votes;\n        } else if (support == 2) {\n            proposal.abstainVotes = proposal.abstainVotes + votes;\n        }\n\n        if (\n            // only for votes can trigger an objection period\n            // we're in the last minute window\n            isForVoteInLastMinuteWindow &&\n            // first part of the vote flip check\n            // separated from the second part to optimize gas\n            isDefeatedBefore &&\n            // haven't turn on objection yet\n            proposal.objectionPeriodEndBlock == 0 &&\n            // second part of the vote flip check\n            !ds.isDefeated(proposal)\n        ) {\n            proposal.objectionPeriodEndBlock = SafeCast.toUint64(\n                proposal.endBlock + ds.objectionPeriodDurationInBlocks\n            );\n\n            emit ProposalObjectionPeriodSet(proposal.id, proposal.objectionPeriodEndBlock);\n        }\n\n        receipt.hasVoted = true;\n        receipt.support = support;\n        receipt.votes = votes;\n\n        return votes;\n    }\n\n    /**\n     * @notice Internal function that handles against votes during an objection period.\n     * @dev Assumes it's being called by `castVoteInternal` which ensures:\n     * 1. The proposal is in the objection period state.\n     * 2. The vote is an against vote.\n     * @param proposalId The id of the proposal being voted on\n     * @param voter The address of the voter\n     * @return The number of votes cast\n     */\n    function castObjectionInternal(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        address voter\n    ) internal returns (uint96) {\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n        NounsDAOTypes.Receipt storage receipt = proposal.receipts[voter];\n        require(receipt.hasVoted == false, 'NounsDAO::castVoteInternal: voter already voted');\n\n        uint96 votes = receipt.votes = ds.nouns.getPriorVotes(voter, proposal.startBlock);\n        receipt.hasVoted = true;\n        receipt.support = 0;\n        proposal.againstVotes = proposal.againstVotes + votes;\n\n        return votes;\n    }\n\n    function _refundGas(uint256 startGas) internal {\n        unchecked {\n            uint256 balance = address(this).balance;\n            if (balance == 0) {\n                return;\n            }\n            uint256 basefee = min(block.basefee, MAX_REFUND_BASE_FEE);\n            uint256 gasPrice = min(tx.gasprice, basefee + MAX_REFUND_PRIORITY_FEE);\n            uint256 gasUsed = min(startGas - gasleft() + REFUND_BASE_GAS, MAX_REFUND_GAS_USED);\n            uint256 refundAmount = min(gasPrice * gasUsed, balance);\n            (bool refundSent, ) = tx.origin.call{ value: refundAmount }('');\n            emit RefundableVote(tx.origin, refundAmount, refundSent);\n        }\n    }\n\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n}\n"
      },
      "contracts/governance/NounsDAOProposals.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\n/// @title Library for Nouns DAO Logic containing the proposal lifecycle code\n\n/*********************************\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░██░░░████░░██░░░████░░░ *\n * ░░██████░░░████████░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n *********************************/\n\npragma solidity ^0.8.19;\n\nimport './NounsDAOInterfaces.sol';\nimport { NounsDAODynamicQuorum } from './NounsDAODynamicQuorum.sol';\nimport { NounsDAOFork } from './fork/NounsDAOFork.sol';\nimport { SignatureChecker } from '../external/openzeppelin/SignatureChecker.sol';\nimport { ECDSA } from '../external/openzeppelin/ECDSA.sol';\nimport { SafeCast } from '@openzeppelin/contracts/utils/math/SafeCast.sol';\n\nlibrary NounsDAOProposals {\n    using NounsDAODynamicQuorum for NounsDAOTypes.Storage;\n    using NounsDAOFork for NounsDAOTypes.Storage;\n\n    error CantCancelProposalAtFinalState();\n    error ProposalInfoArityMismatch();\n    error MustProvideActions();\n    error TooManyActions();\n    error ProposerAlreadyHasALiveProposal();\n    error InvalidSignature();\n    error SignatureExpired();\n    error CanOnlyEditUpdatableProposals();\n    error OnlyProposerCanEdit();\n    error SignerCountMismtach();\n    error ProposerCannotUpdateProposalWithSigners();\n    error MustProvideSignatures();\n    error SignatureIsCancelled();\n    error CannotExecuteDuringForkingPeriod();\n    error VetoerBurned();\n    error VetoerOnly();\n    error CantVetoExecutedProposal();\n    error VotesBelowProposalThreshold();\n\n    // Created to solve stack-too-deep errors\n    struct ProposalTxs {\n        address[] targets;\n        uint256[] values;\n        string[] signatures;\n        bytes[] calldatas;\n    }\n\n    /// @notice The maximum number of actions that can be included in a proposal\n    uint256 public constant PROPOSAL_MAX_OPERATIONS = 10; // 10 actions\n\n    bytes32 public constant DOMAIN_TYPEHASH =\n        keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');\n\n    bytes32 public constant PROPOSAL_TYPEHASH =\n        keccak256(\n            'Proposal(address proposer,address[] targets,uint256[] values,string[] signatures,bytes[] calldatas,string description,uint256 expiry)'\n        );\n\n    bytes32 public constant UPDATE_PROPOSAL_TYPEHASH =\n        keccak256(\n            'UpdateProposal(uint256 proposalId,address proposer,address[] targets,uint256[] values,string[] signatures,bytes[] calldatas,string description,uint256 expiry)'\n        );\n\n    /**\n     * @notice Function used to propose a new proposal. Sender must have delegates above the proposal threshold\n     * @param txs Target addresses, eth values, function signatures and calldatas for proposal calls\n     * @param description String description of the proposal\n     * @param clientId The ID of the client that faciliated posting the proposal onchain\n     * @return Proposal id of new proposal\n     */\n    function propose(\n        NounsDAOTypes.Storage storage ds,\n        ProposalTxs memory txs,\n        string memory description,\n        uint32 clientId\n    ) internal returns (uint256) {\n        uint256 adjustedTotalSupply = ds.adjustedTotalSupply();\n        uint256 proposalThreshold_ = checkPropThreshold(\n            ds,\n            ds.nouns.getPriorVotes(msg.sender, block.number - 1),\n            adjustedTotalSupply\n        );\n        checkProposalTxs(txs);\n        checkNoActiveProp(ds, msg.sender);\n\n        ds.proposalCount = ds.proposalCount + 1;\n        uint32 proposalId = SafeCast.toUint32(ds.proposalCount);\n        NounsDAOTypes.Proposal storage newProposal = createNewProposal(\n            ds,\n            proposalId,\n            proposalThreshold_,\n            adjustedTotalSupply,\n            txs,\n            clientId\n        );\n        ds.latestProposalIds[msg.sender] = proposalId;\n\n        emitNewPropEvents(\n            newProposal,\n            new address[](0),\n            ds.minQuorumVotes(adjustedTotalSupply),\n            txs,\n            description,\n            clientId\n        );\n\n        return proposalId;\n    }\n\n    /**\n     * @notice Function used to propose a new proposal. Sender must have delegates above the proposal threshold.\n     * This proposal would be executed via the timelockV1 contract. This is meant to be used in case timelockV1\n     * is still holding funds or has special permissions to execute on certain contracts.\n     * @param txs Target addresses, eth values, function signatures and calldatas for proposal calls\n     * @param description String description of the proposal\n     * @param clientId The ID of the client that faciliated posting the proposal onchain\n     * @return uint256 Proposal id of new proposal\n     */\n    function proposeOnTimelockV1(\n        NounsDAOTypes.Storage storage ds,\n        ProposalTxs memory txs,\n        string memory description,\n        uint32 clientId\n    ) internal returns (uint256) {\n        uint256 newProposalId = propose(ds, txs, description, clientId);\n\n        NounsDAOTypes.Proposal storage newProposal = ds._proposals[newProposalId];\n        newProposal.executeOnTimelockV1 = true;\n\n        emit NounsDAOEventsV3.ProposalCreatedOnTimelockV1(newProposalId);\n\n        return newProposalId;\n    }\n\n    struct ProposalTemp {\n        uint32 proposalId;\n        uint256 adjustedTotalSupply;\n        uint256 propThreshold;\n    }\n\n    /**\n     * @notice Function used to propose a new proposal. Sender and signers must have delegates above the proposal threshold\n     * @param proposerSignatures Array of signers who have signed the proposal and their signatures.\n     * @dev The signatures follow EIP-712. See `PROPOSAL_TYPEHASH` in NounsDAOProposals.sol\n     * @param txs Target addresses, eth values, function signatures and calldatas for proposal calls\n     * @param description String description of the proposal\n     * @param clientId The ID of the client that faciliated posting the proposal onchain\n     * @return uint256 Proposal id of new proposal\n     */\n    function proposeBySigs(\n        NounsDAOTypes.Storage storage ds,\n        NounsDAOTypes.ProposerSignature[] memory proposerSignatures,\n        ProposalTxs memory txs,\n        string memory description,\n        uint32 clientId\n    ) external returns (uint256) {\n        if (proposerSignatures.length == 0) revert MustProvideSignatures();\n        checkProposalTxs(txs);\n\n        ProposalTemp memory temp;\n        ds.proposalCount = ds.proposalCount + 1;\n        temp.proposalId = SafeCast.toUint32(ds.proposalCount);\n        temp.adjustedTotalSupply = ds.adjustedTotalSupply();\n        temp.propThreshold = proposalThreshold(ds, temp.adjustedTotalSupply);\n\n        NounsDAOTypes.Proposal storage newProposal = createNewProposal(\n            ds,\n            temp.proposalId,\n            temp.propThreshold,\n            temp.adjustedTotalSupply,\n            txs,\n            clientId\n        );\n\n        // important that the proposal is created before the verification call in order to ensure\n        // the same signer is not trying to sign this proposal more than once\n        (uint256 votes, address[] memory signers) = verifySignersCanBackThisProposalAndCountTheirVotes(\n            ds,\n            proposerSignatures,\n            txs,\n            description,\n            temp.proposalId\n        );\n        if (signers.length == 0) revert MustProvideSignatures();\n        if (votes <= temp.propThreshold) revert VotesBelowProposalThreshold();\n\n        newProposal.signers = signers;\n\n        emitNewPropEvents(\n            newProposal,\n            signers,\n            ds.minQuorumVotes(temp.adjustedTotalSupply),\n            txs,\n            description,\n            clientId\n        );\n\n        return temp.proposalId;\n    }\n\n    /**\n     * @notice Invalidates a signature that may be used for signing a proposal.\n     * Once a signature is canceled, the sender can no longer use it again.\n     * If the sender changes their mind and want to sign the proposal, they can change the expiry timestamp\n     * in order to produce a new signature.\n     * The signature will only be invalidated when used by the sender. If used by a different account, it will\n     * not be invalidated.\n     * @param sig The signature to cancel\n     */\n    function cancelSig(NounsDAOTypes.Storage storage ds, bytes calldata sig) external {\n        bytes32 sigHash = keccak256(sig);\n        ds.cancelledSigs[msg.sender][sigHash] = true;\n\n        emit NounsDAOEventsV3.SignatureCancelled(msg.sender, sig);\n    }\n\n    /**\n     * @notice Update a proposal transactions and description.\n     * Only the proposer can update it, and only during the updateable period.\n     * @param proposalId Proposal's id\n     * @param targets Updated target addresses for proposal calls\n     * @param values Updated eth values for proposal calls\n     * @param signatures Updated function signatures for proposal calls\n     * @param calldatas Updated calldatas for proposal calls\n     * @param description Updated description of the proposal\n     * @param updateMessage Short message to explain the update\n     */\n    function updateProposal(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        address[] memory targets,\n        uint256[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas,\n        string memory description,\n        string memory updateMessage\n    ) external {\n        updateProposalTransactionsInternal(ds, proposalId, targets, values, signatures, calldatas);\n\n        emit NounsDAOEventsV3.ProposalUpdated(\n            proposalId,\n            msg.sender,\n            targets,\n            values,\n            signatures,\n            calldatas,\n            description,\n            updateMessage\n        );\n    }\n\n    /**\n     * @notice Updates the proposal's transactions. Only the proposer can update it, and only during the updateable period.\n     * @param proposalId Proposal's id\n     * @param targets Updated target addresses for proposal calls\n     * @param values Updated eth values for proposal calls\n     * @param signatures Updated function signatures for proposal calls\n     * @param calldatas Updated calldatas for proposal calls\n     * @param updateMessage Short message to explain the update\n     */\n    function updateProposalTransactions(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        address[] memory targets,\n        uint256[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas,\n        string memory updateMessage\n    ) external {\n        updateProposalTransactionsInternal(ds, proposalId, targets, values, signatures, calldatas);\n\n        emit NounsDAOEventsV3.ProposalTransactionsUpdated(\n            proposalId,\n            msg.sender,\n            targets,\n            values,\n            signatures,\n            calldatas,\n            updateMessage\n        );\n    }\n\n    function updateProposalTransactionsInternal(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        address[] memory targets,\n        uint256[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas\n    ) internal {\n        checkProposalTxs(ProposalTxs(targets, values, signatures, calldatas));\n\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n        checkProposalUpdatable(ds, proposalId, proposal);\n\n        proposal.targets = targets;\n        proposal.values = values;\n        proposal.signatures = signatures;\n        proposal.calldatas = calldatas;\n    }\n\n    /**\n     * @notice Updates the proposal's description. Only the proposer can update it, and only during the updateable period.\n     * @param proposalId Proposal's id\n     * @param description Updated description of the proposal\n     * @param updateMessage Short message to explain the update\n     */\n    function updateProposalDescription(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        string calldata description,\n        string calldata updateMessage\n    ) external {\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n        checkProposalUpdatable(ds, proposalId, proposal);\n\n        emit NounsDAOEventsV3.ProposalDescriptionUpdated(proposalId, msg.sender, description, updateMessage);\n    }\n\n    /**\n     * @notice Update a proposal's transactions and description that was created with proposeBySigs.\n     * Only the proposer can update it, during the updateable period.\n     * Requires the original signers to sign the update.\n     * @param proposalId Proposal's id\n     * @param proposerSignatures Array of signers who have signed the proposal and their signatures.\n     * @dev The signatures follow EIP-712. See `UPDATE_PROPOSAL_TYPEHASH` in NounsDAOProposals.sol\n     * @param txs Updated transactions for the proposal\n     * @param description Updated description of the proposal\n     * @param updateMessage Short message to explain the update\n     */\n    function updateProposalBySigs(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        NounsDAOTypes.ProposerSignature[] memory proposerSignatures,\n        ProposalTxs memory txs,\n        string memory description,\n        string memory updateMessage\n    ) external {\n        checkProposalTxs(txs);\n        // without this check it's possible to run through this function and update a proposal without signatures\n        // this problem doesn't exist in the propose function because we check for prop threshold there\n        if (proposerSignatures.length == 0) revert MustProvideSignatures();\n\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n        if (stateInternal(ds, proposalId) != NounsDAOTypes.ProposalState.Updatable)\n            revert CanOnlyEditUpdatableProposals();\n        if (msg.sender != proposal.proposer) revert OnlyProposerCanEdit();\n\n        address[] memory signers = proposal.signers;\n        if (proposerSignatures.length != signers.length) revert SignerCountMismtach();\n\n        bytes memory proposalEncodeData = abi.encodePacked(\n            proposalId,\n            calcProposalEncodeData(msg.sender, txs, description)\n        );\n\n        for (uint256 i = 0; i < proposerSignatures.length; ++i) {\n            verifyProposalSignature(ds, proposalEncodeData, proposerSignatures[i], UPDATE_PROPOSAL_TYPEHASH);\n\n            // To avoid the gas cost of having to search signers in proposal.signers, we're assuming the sigs we get\n            // use the same amount of signers and the same order.\n            if (signers[i] != proposerSignatures[i].signer) revert OnlyProposerCanEdit();\n        }\n\n        proposal.targets = txs.targets;\n        proposal.values = txs.values;\n        proposal.signatures = txs.signatures;\n        proposal.calldatas = txs.calldatas;\n\n        emit NounsDAOEventsV3.ProposalUpdated(\n            proposalId,\n            msg.sender,\n            txs.targets,\n            txs.values,\n            txs.signatures,\n            txs.calldatas,\n            description,\n            updateMessage\n        );\n    }\n\n    /**\n     * @notice Queues a proposal of state succeeded\n     * @param proposalId The id of the proposal to queue\n     */\n    function queue(NounsDAOTypes.Storage storage ds, uint256 proposalId) external {\n        require(\n            stateInternal(ds, proposalId) == NounsDAOTypes.ProposalState.Succeeded,\n            'NounsDAO::queue: proposal can only be queued if it is succeeded'\n        );\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n        INounsDAOExecutor timelock = getProposalTimelock(ds, proposal);\n        uint256 eta = block.timestamp + timelock.delay();\n        for (uint256 i = 0; i < proposal.targets.length; i++) {\n            queueOrRevertInternal(\n                timelock,\n                proposal.targets[i],\n                proposal.values[i],\n                proposal.signatures[i],\n                proposal.calldatas[i],\n                eta\n            );\n        }\n        proposal.eta = eta;\n        emit NounsDAOEventsV3.ProposalQueued(proposalId, eta);\n    }\n\n    function queueOrRevertInternal(\n        INounsDAOExecutor timelock,\n        address target,\n        uint256 value,\n        string memory signature,\n        bytes memory data,\n        uint256 eta\n    ) internal {\n        require(\n            !timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))),\n            'NounsDAO::queueOrRevertInternal: identical proposal action already queued at eta'\n        );\n        timelock.queueTransaction(target, value, signature, data, eta);\n    }\n\n    /**\n     * @notice Executes a queued proposal if eta has passed\n     * @param proposalId The id of the proposal to execute\n     */\n    function execute(NounsDAOTypes.Storage storage ds, uint256 proposalId) external {\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n        INounsDAOExecutor timelock = getProposalTimelock(ds, proposal);\n        executeInternal(ds, proposal, timelock);\n    }\n\n    function executeInternal(\n        NounsDAOTypes.Storage storage ds,\n        NounsDAOTypes.Proposal storage proposal,\n        INounsDAOExecutor timelock\n    ) internal {\n        require(\n            stateInternal(ds, proposal.id) == NounsDAOTypes.ProposalState.Queued,\n            'NounsDAO::execute: proposal can only be executed if it is queued'\n        );\n        if (ds.isForkPeriodActive()) revert CannotExecuteDuringForkingPeriod();\n\n        proposal.executed = true;\n\n        for (uint256 i = 0; i < proposal.targets.length; i++) {\n            timelock.executeTransaction(\n                proposal.targets[i],\n                proposal.values[i],\n                proposal.signatures[i],\n                proposal.calldatas[i],\n                proposal.eta\n            );\n        }\n        emit NounsDAOEventsV3.ProposalExecuted(proposal.id);\n    }\n\n    function getProposalTimelock(\n        NounsDAOTypes.Storage storage ds,\n        NounsDAOTypes.Proposal storage proposal\n    ) internal view returns (INounsDAOExecutor) {\n        if (proposal.executeOnTimelockV1) {\n            return ds.timelockV1;\n        } else {\n            return ds.timelock;\n        }\n    }\n\n    /**\n     * @notice Vetoes a proposal only if sender is the vetoer and the proposal has not been executed.\n     * @param proposalId The id of the proposal to veto\n     */\n    function veto(NounsDAOTypes.Storage storage ds, uint256 proposalId) external {\n        if (ds.vetoer == address(0)) {\n            revert VetoerBurned();\n        }\n\n        if (msg.sender != ds.vetoer) {\n            revert VetoerOnly();\n        }\n\n        if (stateInternal(ds, proposalId) == NounsDAOTypes.ProposalState.Executed) {\n            revert CantVetoExecutedProposal();\n        }\n\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n\n        proposal.vetoed = true;\n        INounsDAOExecutor timelock = getProposalTimelock(ds, proposal);\n        for (uint256 i = 0; i < proposal.targets.length; i++) {\n            timelock.cancelTransaction(\n                proposal.targets[i],\n                proposal.values[i],\n                proposal.signatures[i],\n                proposal.calldatas[i],\n                proposal.eta\n            );\n        }\n\n        emit NounsDAOEventsV3.ProposalVetoed(proposalId);\n    }\n\n    /**\n     * @notice Cancels a proposal only if sender is the proposer or a signer, or proposer & signers voting power\n     * dropped below proposal threshold\n     * @param proposalId The id of the proposal to cancel\n     */\n    function cancel(NounsDAOTypes.Storage storage ds, uint256 proposalId) external {\n        NounsDAOTypes.ProposalState proposalState = stateInternal(ds, proposalId);\n        if (\n            proposalState == NounsDAOTypes.ProposalState.Canceled ||\n            proposalState == NounsDAOTypes.ProposalState.Defeated ||\n            proposalState == NounsDAOTypes.ProposalState.Expired ||\n            proposalState == NounsDAOTypes.ProposalState.Executed ||\n            proposalState == NounsDAOTypes.ProposalState.Vetoed\n        ) {\n            revert CantCancelProposalAtFinalState();\n        }\n\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n        address proposer = proposal.proposer;\n        NounsTokenLike nouns = ds.nouns;\n\n        uint256 votes = nouns.getPriorVotes(proposer, block.number - 1);\n        bool msgSenderIsProposer = proposer == msg.sender;\n        address[] memory signers = proposal.signers;\n        for (uint256 i = 0; i < signers.length; ++i) {\n            msgSenderIsProposer = msgSenderIsProposer || msg.sender == signers[i];\n            votes += nouns.getPriorVotes(signers[i], block.number - 1);\n        }\n\n        require(\n            msgSenderIsProposer || votes <= proposal.proposalThreshold,\n            'NounsDAO::cancel: proposer above threshold'\n        );\n\n        proposal.canceled = true;\n        INounsDAOExecutor timelock = getProposalTimelock(ds, proposal);\n        for (uint256 i = 0; i < proposal.targets.length; i++) {\n            timelock.cancelTransaction(\n                proposal.targets[i],\n                proposal.values[i],\n                proposal.signatures[i],\n                proposal.calldatas[i],\n                proposal.eta\n            );\n        }\n\n        emit NounsDAOEventsV3.ProposalCanceled(proposalId);\n    }\n\n    /**\n     * @notice Gets the state of a proposal\n     * @param ds the DAO's state struct\n     * @param proposalId The id of the proposal\n     * @return Proposal state\n     */\n    function state(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId\n    ) public view returns (NounsDAOTypes.ProposalState) {\n        return stateInternal(ds, proposalId);\n    }\n\n    /**\n     * @notice Gets the state of a proposal\n     * @dev This internal function is used by other libraries to embed in compile time and save the runtime gas cost of a delegate call\n     * @param ds the DAO's state struct\n     * @param proposalId The id of the proposal\n     * @return Proposal state\n     */\n    function stateInternal(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId\n    ) internal view returns (NounsDAOTypes.ProposalState) {\n        require(ds.proposalCount >= proposalId, 'NounsDAO::state: invalid proposal id');\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n\n        if (proposal.vetoed) {\n            return NounsDAOTypes.ProposalState.Vetoed;\n        } else if (proposal.canceled) {\n            return NounsDAOTypes.ProposalState.Canceled;\n        } else if (block.number <= proposal.updatePeriodEndBlock) {\n            return NounsDAOTypes.ProposalState.Updatable;\n        } else if (block.number <= proposal.startBlock) {\n            return NounsDAOTypes.ProposalState.Pending;\n        } else if (block.number <= proposal.endBlock) {\n            return NounsDAOTypes.ProposalState.Active;\n        } else if (block.number <= proposal.objectionPeriodEndBlock) {\n            return NounsDAOTypes.ProposalState.ObjectionPeriod;\n        } else if (isDefeated(ds, proposal)) {\n            return NounsDAOTypes.ProposalState.Defeated;\n        } else if (proposal.eta == 0) {\n            return NounsDAOTypes.ProposalState.Succeeded;\n        } else if (proposal.executed) {\n            return NounsDAOTypes.ProposalState.Executed;\n        } else if (block.timestamp >= proposal.eta + getProposalTimelock(ds, proposal).GRACE_PERIOD()) {\n            return NounsDAOTypes.ProposalState.Expired;\n        } else {\n            return NounsDAOTypes.ProposalState.Queued;\n        }\n    }\n\n    /**\n     * @notice Gets actions of a proposal\n     * @param proposalId the id of the proposal\n     * @return targets\n     * @return values\n     * @return signatures\n     * @return calldatas\n     */\n    function getActions(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId\n    )\n        internal\n        view\n        returns (\n            address[] memory targets,\n            uint256[] memory values,\n            string[] memory signatures,\n            bytes[] memory calldatas\n        )\n    {\n        NounsDAOTypes.Proposal storage p = ds._proposals[proposalId];\n        return (p.targets, p.values, p.signatures, p.calldatas);\n    }\n\n    /**\n     * @notice Gets the receipt for a voter on a given proposal\n     * @param proposalId the id of proposal\n     * @param voter The address of the voter\n     * @return The voting receipt\n     */\n    function getReceipt(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        address voter\n    ) internal view returns (NounsDAOTypes.Receipt memory) {\n        return ds._proposals[proposalId].receipts[voter];\n    }\n\n    /**\n     * @notice Returns the proposal details given a proposal id.\n     *     The `quorumVotes` member holds the *current* quorum, given the current votes.\n     * @param proposalId the proposal id to get the data for\n     * @return A `ProposalCondensed` struct with the proposal data\n     */\n    function proposals(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId\n    ) external view returns (NounsDAOTypes.ProposalCondensedV2 memory) {\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n        return\n            NounsDAOTypes.ProposalCondensedV2({\n                id: proposal.id,\n                proposer: proposal.proposer,\n                proposalThreshold: proposal.proposalThreshold,\n                quorumVotes: ds.quorumVotes(proposal.id),\n                eta: proposal.eta,\n                startBlock: proposal.startBlock,\n                endBlock: proposal.endBlock,\n                forVotes: proposal.forVotes,\n                againstVotes: proposal.againstVotes,\n                abstainVotes: proposal.abstainVotes,\n                canceled: proposal.canceled,\n                vetoed: proposal.vetoed,\n                executed: proposal.executed,\n                totalSupply: proposal.totalSupply,\n                creationBlock: proposal.creationBlock\n            });\n    }\n\n    /**\n     * @notice Returns the proposal details given a proposal id.\n     *     The `quorumVotes` member holds the *current* quorum, given the current votes.\n     * @param proposalId the proposal id to get the data for\n     * @return A `ProposalCondensed` struct with the proposal data\n     */\n    function proposalsV3(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId\n    ) external view returns (NounsDAOTypes.ProposalCondensedV3 memory) {\n        NounsDAOTypes.Proposal storage proposal = ds._proposals[proposalId];\n        return\n            NounsDAOTypes.ProposalCondensedV3({\n                id: proposal.id,\n                proposer: proposal.proposer,\n                proposalThreshold: proposal.proposalThreshold,\n                quorumVotes: ds.quorumVotes(proposal.id),\n                eta: proposal.eta,\n                startBlock: proposal.startBlock,\n                endBlock: proposal.endBlock,\n                forVotes: proposal.forVotes,\n                againstVotes: proposal.againstVotes,\n                abstainVotes: proposal.abstainVotes,\n                canceled: proposal.canceled,\n                vetoed: proposal.vetoed,\n                executed: proposal.executed,\n                totalSupply: proposal.totalSupply,\n                creationBlock: proposal.creationBlock,\n                signers: proposal.signers,\n                updatePeriodEndBlock: proposal.updatePeriodEndBlock,\n                objectionPeriodEndBlock: proposal.objectionPeriodEndBlock,\n                executeOnTimelockV1: proposal.executeOnTimelockV1\n            });\n    }\n\n    struct Temp {\n        uint256 endBlock;\n        uint256 objectionPeriodEndBlock;\n    }\n\n    function proposalDataForRewards(\n        NounsDAOTypes.Storage storage ds,\n        uint256 firstProposalId,\n        uint256 lastProposalId,\n        uint16 proposalEligibilityQuorumBps,\n        bool excludeCanceled,\n        bool requireVotingEnded,\n        uint32[] calldata votingClientIds\n    ) internal view returns (NounsDAOTypes.ProposalForRewards[] memory) {\n        require(lastProposalId >= firstProposalId, 'lastProposalId >= firstProposalId');\n        uint256 numProposals = lastProposalId - firstProposalId + 1;\n        NounsDAOTypes.ProposalForRewards[] memory data = new NounsDAOTypes.ProposalForRewards[](numProposals);\n\n        NounsDAOTypes.Proposal storage proposal;\n        uint256 i;\n        Temp memory t;\n        for (uint256 pid = firstProposalId; pid <= lastProposalId; ++pid) {\n            proposal = ds._proposals[pid];\n\n            if (excludeCanceled && proposal.canceled) continue;\n\n            t.endBlock = proposal.endBlock;\n            t.objectionPeriodEndBlock = proposal.objectionPeriodEndBlock;\n            if (requireVotingEnded) {\n                uint256 votingEndBlock = max(t.endBlock, t.objectionPeriodEndBlock);\n                require(block.number > votingEndBlock, 'all proposals must be done with voting');\n            }\n\n            uint256 forVotes = proposal.forVotes;\n            uint256 totalSupply = proposal.totalSupply;\n            if (forVotes < (totalSupply * proposalEligibilityQuorumBps) / 10_000) continue;\n\n            NounsDAOTypes.ClientVoteData[] memory c = new NounsDAOTypes.ClientVoteData[](votingClientIds.length);\n            for (uint256 j; j < votingClientIds.length; ++j) {\n                c[j] = proposal.voteClients[votingClientIds[j]];\n            }\n\n            data[i++] = NounsDAOTypes.ProposalForRewards({\n                endBlock: t.endBlock,\n                objectionPeriodEndBlock: t.objectionPeriodEndBlock,\n                forVotes: forVotes,\n                againstVotes: proposal.againstVotes,\n                abstainVotes: proposal.abstainVotes,\n                totalSupply: totalSupply,\n                creationTimestamp: proposal.creationTimestamp,\n                clientId: proposal.clientId,\n                voteData: c\n            });\n        }\n\n        // change array size to the actually used size\n        assembly {\n            mstore(data, i)\n        }\n\n        return data;\n    }\n\n    /**\n     * @notice Current proposal threshold using Noun Total Supply\n     * Differs from `GovernerBravo` which uses fixed amount\n     */\n    function proposalThreshold(\n        NounsDAOTypes.Storage storage ds,\n        uint256 adjustedTotalSupply\n    ) internal view returns (uint256) {\n        return bps2Uint(ds.proposalThresholdBPS, adjustedTotalSupply);\n    }\n\n    function isDefeated(\n        NounsDAOTypes.Storage storage ds,\n        NounsDAOTypes.Proposal storage proposal\n    ) internal view returns (bool) {\n        uint256 forVotes = proposal.forVotes;\n        return forVotes <= proposal.againstVotes || forVotes < ds.quorumVotes(proposal.id);\n    }\n\n    /**\n     * @notice reverts if `proposer` is the proposer or signer of an active proposal.\n     * This is a spam protection mechanism to limit the number of proposals each noun can back.\n     */\n    function checkNoActiveProp(NounsDAOTypes.Storage storage ds, address proposer) internal view {\n        uint256 latestProposalId = ds.latestProposalIds[proposer];\n        if (latestProposalId != 0) {\n            NounsDAOTypes.ProposalState proposersLatestProposalState = stateInternal(ds, latestProposalId);\n            if (\n                proposersLatestProposalState == NounsDAOTypes.ProposalState.ObjectionPeriod ||\n                proposersLatestProposalState == NounsDAOTypes.ProposalState.Active ||\n                proposersLatestProposalState == NounsDAOTypes.ProposalState.Pending ||\n                proposersLatestProposalState == NounsDAOTypes.ProposalState.Updatable\n            ) revert ProposerAlreadyHasALiveProposal();\n        }\n    }\n\n    /**\n     * @dev Extracted this function to fix the `Stack too deep` error `proposeBySigs` hit.\n     */\n    function verifySignersCanBackThisProposalAndCountTheirVotes(\n        NounsDAOTypes.Storage storage ds,\n        NounsDAOTypes.ProposerSignature[] memory proposerSignatures,\n        ProposalTxs memory txs,\n        string memory description,\n        uint256 proposalId\n    ) internal returns (uint256 votes, address[] memory signers) {\n        NounsTokenLike nouns = ds.nouns;\n        bytes memory proposalEncodeData = calcProposalEncodeData(msg.sender, txs, description);\n\n        signers = new address[](proposerSignatures.length);\n        uint256 numSigners = 0;\n        for (uint256 i = 0; i < proposerSignatures.length; ++i) {\n            verifyProposalSignature(ds, proposalEncodeData, proposerSignatures[i], PROPOSAL_TYPEHASH);\n\n            address signer = proposerSignatures[i].signer;\n            checkNoActiveProp(ds, signer);\n\n            uint256 signerVotes = nouns.getPriorVotes(signer, block.number - 1);\n            if (signerVotes == 0) {\n                continue;\n            }\n\n            signers[numSigners++] = signer;\n            ds.latestProposalIds[signer] = proposalId;\n            votes += signerVotes;\n        }\n\n        if (numSigners < proposerSignatures.length) {\n            // this assembly trims the signer array, getting rid of unused cells\n            assembly {\n                mstore(signers, numSigners)\n            }\n        }\n\n        checkNoActiveProp(ds, msg.sender);\n        ds.latestProposalIds[msg.sender] = proposalId;\n        votes += nouns.getPriorVotes(msg.sender, block.number - 1);\n    }\n\n    function calcProposalEncodeData(\n        address proposer,\n        ProposalTxs memory txs,\n        string memory description\n    ) internal pure returns (bytes memory) {\n        bytes32[] memory signatureHashes = new bytes32[](txs.signatures.length);\n        for (uint256 i = 0; i < txs.signatures.length; ++i) {\n            signatureHashes[i] = keccak256(bytes(txs.signatures[i]));\n        }\n\n        bytes32[] memory calldatasHashes = new bytes32[](txs.calldatas.length);\n        for (uint256 i = 0; i < txs.calldatas.length; ++i) {\n            calldatasHashes[i] = keccak256(txs.calldatas[i]);\n        }\n\n        return\n            abi.encode(\n                proposer,\n                keccak256(abi.encodePacked(txs.targets)),\n                keccak256(abi.encodePacked(txs.values)),\n                keccak256(abi.encodePacked(signatureHashes)),\n                keccak256(abi.encodePacked(calldatasHashes)),\n                keccak256(bytes(description))\n            );\n    }\n\n    function checkProposalUpdatable(\n        NounsDAOTypes.Storage storage ds,\n        uint256 proposalId,\n        NounsDAOTypes.Proposal storage proposal\n    ) internal view {\n        if (stateInternal(ds, proposalId) != NounsDAOTypes.ProposalState.Updatable)\n            revert CanOnlyEditUpdatableProposals();\n        if (msg.sender != proposal.proposer) revert OnlyProposerCanEdit();\n        if (proposal.signers.length > 0) revert ProposerCannotUpdateProposalWithSigners();\n    }\n\n    function createNewProposal(\n        NounsDAOTypes.Storage storage ds,\n        uint32 proposalId,\n        uint256 proposalThreshold_,\n        uint256 adjustedTotalSupply,\n        ProposalTxs memory txs,\n        uint32 clientId\n    ) internal returns (NounsDAOTypes.Proposal storage newProposal) {\n        uint64 updatePeriodEndBlock = SafeCast.toUint64(block.number + ds.proposalUpdatablePeriodInBlocks);\n        uint256 startBlock = updatePeriodEndBlock + ds.votingDelay;\n        uint256 endBlock = startBlock + ds.votingPeriod;\n\n        newProposal = ds._proposals[proposalId];\n        newProposal.id = proposalId;\n        newProposal.clientId = clientId;\n        newProposal.proposer = msg.sender;\n        newProposal.proposalThreshold = proposalThreshold_;\n        newProposal.targets = txs.targets;\n        newProposal.values = txs.values;\n        newProposal.signatures = txs.signatures;\n        newProposal.calldatas = txs.calldatas;\n        newProposal.startBlock = startBlock;\n        newProposal.endBlock = endBlock;\n        newProposal.totalSupply = adjustedTotalSupply;\n        newProposal.creationBlock = SafeCast.toUint32(block.number);\n        newProposal.creationTimestamp = SafeCast.toUint32(block.timestamp);\n        newProposal.updatePeriodEndBlock = updatePeriodEndBlock;\n    }\n\n    function emitNewPropEvents(\n        NounsDAOTypes.Proposal storage newProposal,\n        address[] memory signers,\n        uint256 minQuorumVotes,\n        ProposalTxs memory txs,\n        string memory description,\n        uint32 clientId\n    ) internal {\n        /// @notice Maintains backwards compatibility with GovernorBravo events\n        emit NounsDAOEventsV3.ProposalCreated(\n            newProposal.id,\n            msg.sender,\n            txs.targets,\n            txs.values,\n            txs.signatures,\n            txs.calldatas,\n            newProposal.startBlock,\n            newProposal.endBlock,\n            description\n        );\n\n        /// @notice V1: Updated event with `proposalThreshold` and `quorumVotes` `minQuorumVotes`\n        /// @notice V2: `quorumVotes` changed to `minQuorumVotes`\n        /// @notice V3: Added signers and updatePeriodEndBlock\n        /// @notice V4: Removed data that's already emitted in `ProposalCreated`, added clientId\n        emit NounsDAOEventsV3.ProposalCreatedWithRequirements(\n            newProposal.id,\n            signers,\n            newProposal.updatePeriodEndBlock,\n            newProposal.proposalThreshold,\n            minQuorumVotes,\n            clientId\n        );\n    }\n\n    function checkPropThreshold(\n        NounsDAOTypes.Storage storage ds,\n        uint256 votes,\n        uint256 adjustedTotalSupply\n    ) internal view returns (uint256 propThreshold) {\n        propThreshold = proposalThreshold(ds, adjustedTotalSupply);\n        if (votes <= propThreshold) revert VotesBelowProposalThreshold();\n    }\n\n    function checkProposalTxs(ProposalTxs memory txs) internal pure {\n        if (\n            txs.targets.length != txs.values.length ||\n            txs.targets.length != txs.signatures.length ||\n            txs.targets.length != txs.calldatas.length\n        ) revert ProposalInfoArityMismatch();\n        if (txs.targets.length == 0) revert MustProvideActions();\n        if (txs.targets.length > PROPOSAL_MAX_OPERATIONS) revert TooManyActions();\n    }\n\n    function verifyProposalSignature(\n        NounsDAOTypes.Storage storage ds,\n        bytes memory proposalEncodeData,\n        NounsDAOTypes.ProposerSignature memory proposerSignature,\n        bytes32 typehash\n    ) internal view {\n        bytes32 sigHash = keccak256(proposerSignature.sig);\n        if (ds.cancelledSigs[proposerSignature.signer][sigHash]) revert SignatureIsCancelled();\n\n        bytes32 digest = sigDigest(typehash, proposalEncodeData, proposerSignature.expirationTimestamp, address(this));\n        if (!SignatureChecker.isValidSignatureNow(proposerSignature.signer, digest, proposerSignature.sig))\n            revert InvalidSignature();\n\n        if (block.timestamp > proposerSignature.expirationTimestamp) revert SignatureExpired();\n    }\n\n    /**\n     * @notice Generate the digest (hash) used to verify proposal signatures.\n     * @param typehash the EIP 712 type hash of the signed message, e.g. `PROPOSAL_TYPEHASH` or `UPDATE_PROPOSAL_TYPEHASH`.\n     * @param proposalEncodeData the abi encoded proposal data, identical to the output of `calcProposalEncodeData`.\n     * @param expirationTimestamp the signature's expiration timestamp.\n     * @param verifyingContract the contract verifying the signature, e.g. the DAO proxy by default.\n     * @return bytes32 the signature's typed data hash.\n     */\n    function sigDigest(\n        bytes32 typehash,\n        bytes memory proposalEncodeData,\n        uint256 expirationTimestamp,\n        address verifyingContract\n    ) internal view returns (bytes32) {\n        bytes32 structHash = keccak256(abi.encodePacked(typehash, proposalEncodeData, expirationTimestamp));\n\n        bytes32 domainSeparator = keccak256(\n            abi.encode(DOMAIN_TYPEHASH, keccak256(bytes('Nouns DAO')), block.chainid, verifyingContract)\n        );\n\n        return ECDSA.toTypedDataHash(domainSeparator, structHash);\n    }\n\n    function bps2Uint(uint256 bps, uint256 number) internal pure returns (uint256) {\n        return (number * bps) / 10000;\n    }\n\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n}\n"
      },
      "contracts/governance/fork/NounsDAOFork.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\n/// @title Library for Nouns DAO Logic containing the dao fork logic\n\n/*********************************\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░██░░░████░░██░░░████░░░ *\n * ░░██████░░░████████░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n *********************************/\n\npragma solidity ^0.8.19;\n\nimport { NounsDAOTypes, INounsDAOForkEscrow, INounsDAOExecutorV2 } from '../NounsDAOInterfaces.sol';\nimport { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport { NounsTokenFork } from './newdao/token/NounsTokenFork.sol';\n\nlibrary NounsDAOFork {\n    error ForkThresholdNotMet();\n    error ForkPeriodNotActive();\n    error ForkPeriodActive();\n    error AdminOnly();\n    error UseAlternativeWithdrawFunction();\n\n    /// @notice Emitted when someones adds nouns to the fork escrow\n    event EscrowedToFork(\n        uint32 indexed forkId,\n        address indexed owner,\n        uint256[] tokenIds,\n        uint256[] proposalIds,\n        string reason\n    );\n\n    /// @notice Emitted when the owner withdraws their nouns from the fork escrow\n    event WithdrawFromForkEscrow(uint32 indexed forkId, address indexed owner, uint256[] tokenIds);\n\n    /// @notice Emitted when the fork is executed and the forking period begins\n    event ExecuteFork(\n        uint32 indexed forkId,\n        address forkTreasury,\n        address forkToken,\n        uint256 forkEndTimestamp,\n        uint256 tokensInEscrow\n    );\n\n    /// @notice Emitted when someone joins a fork during the forking period\n    event JoinFork(\n        uint32 indexed forkId,\n        address indexed owner,\n        uint256[] tokenIds,\n        uint256[] proposalIds,\n        string reason\n    );\n\n    /// @notice Emitted when the DAO withdraws nouns from the fork escrow after a fork has been executed\n    event DAOWithdrawNounsFromEscrow(uint256[] tokenIds, address to);\n\n    /// @notice Emitted when withdrawing nouns from escrow increases adjusted total supply\n    event DAONounsSupplyIncreasedFromEscrow(uint256 numTokens, address to);\n\n    /**\n     * @notice Escrow Nouns to contribute to the fork threshold\n     * @dev Requires approving the tokenIds or the entire noun token to the DAO contract\n     * @param tokenIds the tokenIds to escrow. They will be sent to the DAO once the fork threshold is reached and the escrow is closed.\n     * @param proposalIds array of proposal ids which are the reason for wanting to fork. This will only be used to emit event.\n     * @param reason the reason for want to fork. This will only be used to emit event.\n     */\n    function escrowToFork(\n        NounsDAOTypes.Storage storage ds,\n        uint256[] calldata tokenIds,\n        uint256[] calldata proposalIds,\n        string calldata reason\n    ) external {\n        if (isForkPeriodActive(ds)) revert ForkPeriodActive();\n        INounsDAOForkEscrow forkEscrow = ds.forkEscrow;\n\n        for (uint256 i = 0; i < tokenIds.length; i++) {\n            ds.nouns.safeTransferFrom(msg.sender, address(forkEscrow), tokenIds[i]);\n        }\n\n        emit EscrowedToFork(forkEscrow.forkId(), msg.sender, tokenIds, proposalIds, reason);\n    }\n\n    /**\n     * @notice Withdraw Nouns from the fork escrow. Only possible if the fork has not been executed.\n     * Only allowed to withdraw tokens that the sender has escrowed.\n     * @param tokenIds the tokenIds to withdraw\n     */\n    function withdrawFromForkEscrow(NounsDAOTypes.Storage storage ds, uint256[] calldata tokenIds) external {\n        if (isForkPeriodActive(ds)) revert ForkPeriodActive();\n\n        INounsDAOForkEscrow forkEscrow = ds.forkEscrow;\n        forkEscrow.returnTokensToOwner(msg.sender, tokenIds);\n\n        emit WithdrawFromForkEscrow(forkEscrow.forkId(), msg.sender, tokenIds);\n    }\n\n    /**\n     * @notice Execute the fork. Only possible if the fork threshold has been exceeded.\n     * This will deploy a new DAO and send the prorated part of the treasury to the new DAO's treasury.\n     * This will also close the active escrow and all nouns in the escrow will belong to the original DAO.\n     * @return forkTreasury The address of the new DAO's treasury\n     * @return forkToken The address of the new DAO's token\n     */\n    function executeFork(NounsDAOTypes.Storage storage ds) external returns (address forkTreasury, address forkToken) {\n        if (isForkPeriodActive(ds)) revert ForkPeriodActive();\n        INounsDAOForkEscrow forkEscrow = ds.forkEscrow;\n\n        uint256 tokensInEscrow = forkEscrow.numTokensInEscrow();\n        if (tokensInEscrow <= forkThreshold(ds)) revert ForkThresholdNotMet();\n\n        uint256 forkEndTimestamp = block.timestamp + ds.forkPeriod;\n\n        (forkTreasury, forkToken) = ds.forkDAODeployer.deployForkDAO(forkEndTimestamp, forkEscrow);\n        sendProRataTreasury(ds, forkTreasury, tokensInEscrow, adjustedTotalSupply(ds));\n        uint32 forkId = forkEscrow.closeEscrow();\n\n        ds.forkDAOTreasury = forkTreasury;\n        ds.forkDAOToken = forkToken;\n        ds.forkEndTimestamp = forkEndTimestamp;\n\n        emit ExecuteFork(forkId, forkTreasury, forkToken, forkEndTimestamp, tokensInEscrow);\n    }\n\n    /**\n     * @notice Joins a fork while a fork is active\n     * Sends the tokens to the timelock contract.\n     * Sends a prorated part of the treasury to the new fork DAO's treasury.\n     * Mints new tokens in the new fork DAO with the same token ids.\n     * @param tokenIds the tokenIds to send to the DAO in exchange for joining the fork\n     */\n    function joinFork(\n        NounsDAOTypes.Storage storage ds,\n        uint256[] calldata tokenIds,\n        uint256[] calldata proposalIds,\n        string calldata reason\n    ) external {\n        if (!isForkPeriodActive(ds)) revert ForkPeriodNotActive();\n\n        INounsDAOForkEscrow forkEscrow = ds.forkEscrow;\n        address timelock = address(ds.timelock);\n        sendProRataTreasury(ds, ds.forkDAOTreasury, tokenIds.length, adjustedTotalSupply(ds));\n\n        for (uint256 i = 0; i < tokenIds.length; i++) {\n            ds.nouns.transferFrom(msg.sender, timelock, tokenIds[i]);\n        }\n\n        NounsTokenFork(ds.forkDAOToken).claimDuringForkPeriod(msg.sender, tokenIds);\n\n        emit JoinFork(forkEscrow.forkId() - 1, msg.sender, tokenIds, proposalIds, reason);\n    }\n\n    /**\n     * @notice Withdraws nouns from the fork escrow to the treasury after the fork has been executed\n     * @dev Only the DAO can call this function\n     * @param tokenIds the tokenIds to withdraw\n     */\n    function withdrawDAONounsFromEscrowToTreasury(\n        NounsDAOTypes.Storage storage ds,\n        uint256[] calldata tokenIds\n    ) external {\n        withdrawDAONounsFromEscrow(ds, tokenIds, address(ds.timelock));\n    }\n\n    /**\n     * @notice Withdraws nouns from the fork escrow after the fork has been executed to an address other than the treasury\n     * @dev Only the DAO can call this function\n     * @param tokenIds the tokenIds to withdraw\n     * @param to the address to send the nouns to\n     */\n    function withdrawDAONounsFromEscrowIncreasingTotalSupply(\n        NounsDAOTypes.Storage storage ds,\n        uint256[] calldata tokenIds,\n        address to\n    ) external {\n        if (to == address(ds.timelock)) revert UseAlternativeWithdrawFunction();\n\n        withdrawDAONounsFromEscrow(ds, tokenIds, to);\n\n        emit DAONounsSupplyIncreasedFromEscrow(tokenIds.length, to);\n    }\n\n    function withdrawDAONounsFromEscrow(\n        NounsDAOTypes.Storage storage ds,\n        uint256[] calldata tokenIds,\n        address to\n    ) private {\n        if (msg.sender != ds.admin) {\n            revert AdminOnly();\n        }\n\n        ds.forkEscrow.withdrawTokens(tokenIds, to);\n\n        emit DAOWithdrawNounsFromEscrow(tokenIds, to);\n    }\n\n    /**\n     * @notice Returns the required number of tokens to escrow to trigger a fork\n     */\n    function forkThreshold(NounsDAOTypes.Storage storage ds) public view returns (uint256) {\n        return (adjustedTotalSupply(ds) * ds.forkThresholdBPS) / 10_000;\n    }\n\n    /**\n     * @notice Returns the number of tokens currently in escrow, contributing to the fork threshold\n     */\n    function numTokensInForkEscrow(NounsDAOTypes.Storage storage ds) public view returns (uint256) {\n        return ds.forkEscrow.numTokensInEscrow();\n    }\n\n    /**\n     * @notice Returns the number of nouns in supply minus nouns owned by the DAO, i.e. held in the treasury or in an\n     * escrow after it has closed.\n     * This is used when calculating proposal threshold, quorum, fork threshold & treasury split.\n     */\n    function adjustedTotalSupply(NounsDAOTypes.Storage storage ds) internal view returns (uint256) {\n        return ds.nouns.totalSupply() - ds.nouns.balanceOf(address(ds.timelock)) - ds.forkEscrow.numTokensOwnedByDAO();\n    }\n\n    /**\n     * @notice Returns true if noun holders can currently join a fork\n     */\n    function isForkPeriodActive(NounsDAOTypes.Storage storage ds) internal view returns (bool) {\n        return ds.forkEndTimestamp > block.timestamp;\n    }\n\n    /**\n     * @notice Sends part of the DAO's treasury to the `newDAOTreasury` address.\n     * The amount sent is proportional to the `tokenCount` out of `totalSupply`.\n     * Sends ETH and ERC20 tokens listed in `ds.erc20TokensToIncludeInFork`.\n     */\n    function sendProRataTreasury(\n        NounsDAOTypes.Storage storage ds,\n        address newDAOTreasury,\n        uint256 tokenCount,\n        uint256 totalSupply\n    ) internal {\n        INounsDAOExecutorV2 timelock = ds.timelock;\n        uint256 ethToSend = (address(timelock).balance * tokenCount) / totalSupply;\n\n        timelock.sendETH(newDAOTreasury, ethToSend);\n\n        uint256 erc20Count = ds.erc20TokensToIncludeInFork.length;\n        for (uint256 i = 0; i < erc20Count; ++i) {\n            IERC20 erc20token = IERC20(ds.erc20TokensToIncludeInFork[i]);\n            uint256 tokensToSend = (erc20token.balanceOf(address(timelock)) * tokenCount) / totalSupply;\n            if (tokensToSend > 0) {\n                timelock.sendERC20(newDAOTreasury, address(erc20token), tokensToSend);\n            }\n        }\n    }\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (utils/Address.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize, which returns 0 for contracts in\n        // construction, since the code is only stored at the end of the\n        // constructor execution.\n\n        uint256 size;\n        assembly {\n            size := extcodesize(account)\n        }\n        return size > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (utils/math/SafeCast.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits.\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value >= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128) {\n        require(value >= type(int128).min && value <= type(int128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return int128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64) {\n        require(value >= type(int64).min && value <= type(int64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return int64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32) {\n        require(value >= type(int32).min && value <= type(int32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return int32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16) {\n        require(value >= type(int16).min && value <= type(int16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return int16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits.\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8) {\n        require(value >= type(int8).min && value <= type(int8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return int8(value);\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n"
      },
      "contracts/external/openzeppelin/SignatureChecker.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol)\n\npragma solidity ^0.8.0;\n\nimport './ECDSA.sol';\nimport '@openzeppelin/contracts/interfaces/IERC1271.sol';\n\n/**\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\n * Argent and Gnosis Safe.\n *\n * _Available since v4.1._\n */\nlibrary SignatureChecker {\n    /**\n     * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\n     * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\n     *\n     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n     * change through time. It could return true at block N and false at block N+1 (or the opposite).\n     */\n    function isValidSignatureNow(\n        address signer,\n        bytes32 hash,\n        bytes memory signature\n    ) internal view returns (bool) {\n        (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\n        return\n            (error == ECDSA.RecoverError.NoError && recovered == signer) ||\n            isValidERC1271SignatureNow(signer, hash, signature);\n    }\n\n    /**\n     * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated\n     * against the signer smart contract using ERC1271.\n     *\n     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n     * change through time. It could return true at block N and false at block N+1 (or the opposite).\n     */\n    function isValidERC1271SignatureNow(\n        address signer,\n        bytes32 hash,\n        bytes memory signature\n    ) internal view returns (bool) {\n        (bool success, bytes memory result) = signer.staticcall(\n            abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\n        );\n        return (success &&\n            result.length >= 32 &&\n            abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\n    }\n}\n"
      },
      "contracts/external/openzeppelin/ECDSA.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport { Strings } from '@openzeppelin/contracts/utils/Strings.sol';\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS,\n        InvalidSignatureV // Deprecated in v4.8\n    }\n\n    function _throwError(RecoverError error) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert('ECDSA: invalid signature');\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert('ECDSA: invalid signature length');\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert(\"ECDSA: invalid signature 's' value\");\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature` or error string. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            /// @solidity memory-safe-assembly\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength);\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, signature);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (address, RecoverError) {\n        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n        uint8 v = uint8((uint256(vs) >> 255) + 27);\n        return tryRecover(hash, v, r, s);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     *\n     * _Available since v4.2._\n     */\n    function recover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address, RecoverError) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature);\n        }\n\n        return (signer, RecoverError.NoError);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n        // 32 is the length in bytes of hash,\n        // enforced by the type signature above\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, '\\x19Ethereum Signed Message:\\n32')\n            mstore(0x1c, hash)\n            message := keccak256(0x00, 0x3c)\n        }\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from `s`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked('\\x19Ethereum Signed Message:\\n', Strings.toString(s.length), s));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Typed Data, created from a\n     * `domainSeparator` and a `structHash`. This produces hash corresponding\n     * to the one signed with the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n     * JSON-RPC method as part of EIP-712.\n     *\n     * See {recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let ptr := mload(0x40)\n            mstore(ptr, '\\x19\\x01')\n            mstore(add(ptr, 0x02), domainSeparator)\n            mstore(add(ptr, 0x22), structHash)\n            data := keccak256(ptr, 0x42)\n        }\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Data with intended validator, created from a\n     * `validator` and `data` according to the version 0 of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked('\\x19\\x00', validator, data));\n    }\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
      },
      "contracts/governance/fork/newdao/token/NounsTokenFork.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\n/// @title The Nouns ERC-721 token, adjusted for forks\n\n/*********************************\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░██░░░████░░██░░░████░░░ *\n * ░░██████░░░████████░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n *********************************/\n\npragma solidity ^0.8.19;\n\nimport { OwnableUpgradeable } from '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';\nimport { ERC721CheckpointableUpgradeable } from './base/ERC721CheckpointableUpgradeable.sol';\nimport { INounsDescriptorMinimal } from '../../../../interfaces/INounsDescriptorMinimal.sol';\nimport { INounsSeeder } from '../../../../interfaces/INounsSeeder.sol';\nimport { INounsTokenFork } from './INounsTokenFork.sol';\nimport { IERC721 } from '@openzeppelin/contracts/token/ERC721/IERC721.sol';\nimport { UUPSUpgradeable } from '@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol';\nimport { INounsDAOForkEscrow } from '../../../NounsDAOInterfaces.sol';\n\n/**\n * @dev This contract is a fork of NounsToken, with the following changes:\n * - Added upgradeablity via UUPSUpgradeable.\n * - Inheriting from an unmodified ERC721, so that the double Transfer event emission that\n *   NounsToken performs is gone, in favor of the standard single event.\n * - Added functions to claim tokens from a Nouns Fork escrow, or during the forking period.\n * - Removed the proxyRegistry feature that whitelisted OpenSea.\n * - Removed `noundersDAO` and the founder reward every 10 mints.\n * For additional context see `ERC721CheckpointableUpgradeable`.\n */\ncontract NounsTokenFork is INounsTokenFork, OwnableUpgradeable, ERC721CheckpointableUpgradeable, UUPSUpgradeable {\n    error OnlyOwner();\n    error OnlyTokenOwnerCanClaim();\n    error OnlyOriginalDAO();\n    error NoundersCannotBeAddressZero();\n    error OnlyDuringForkingPeriod();\n\n    string public constant NAME = 'NounsTokenFork';\n\n    /// @notice  An address who has permissions to mint Nouns\n    address public minter;\n\n    /// @notice The Nouns token URI descriptor\n    INounsDescriptorMinimal public descriptor;\n\n    /// @notice The Nouns token seeder\n    INounsSeeder public seeder;\n\n    /// @notice The escrow contract used to verify ownership of the original Nouns in the post-fork claiming process\n    INounsDAOForkEscrow public escrow;\n\n    /// @notice The fork ID, used when querying the escrow for token ownership\n    uint32 public forkId;\n\n    /// @notice How many tokens are still available to be claimed by Nouners who put their original Nouns in escrow\n    uint256 public remainingTokensToClaim;\n\n    /// @notice The forking period expiration timestamp, after which new tokens cannot be claimed by the original DAO\n    uint256 public forkingPeriodEndTimestamp;\n\n    /// @notice Whether the minter can be updated\n    bool public isMinterLocked;\n\n    /// @notice Whether the descriptor can be updated\n    bool public isDescriptorLocked;\n\n    /// @notice Whether the seeder can be updated\n    bool public isSeederLocked;\n\n    /// @notice The noun seeds\n    mapping(uint256 => INounsSeeder.Seed) public seeds;\n\n    /// @notice The internal noun ID tracker\n    uint256 private _currentNounId;\n\n    /// @notice IPFS content hash of contract-level metadata\n    string private _contractURIHash = 'QmZi1n79FqWt2tTLwCqiy6nLM6xLGRsEPQ5JmReJQKNNzX';\n\n    /**\n     * @notice Require that the minter has not been locked.\n     */\n    modifier whenMinterNotLocked() {\n        require(!isMinterLocked, 'Minter is locked');\n        _;\n    }\n\n    /**\n     * @notice Require that the descriptor has not been locked.\n     */\n    modifier whenDescriptorNotLocked() {\n        require(!isDescriptorLocked, 'Descriptor is locked');\n        _;\n    }\n\n    /**\n     * @notice Require that the seeder has not been locked.\n     */\n    modifier whenSeederNotLocked() {\n        require(!isSeederLocked, 'Seeder is locked');\n        _;\n    }\n\n    /**\n     * @notice Require that the sender is the minter.\n     */\n    modifier onlyMinter() {\n        require(msg.sender == minter, 'Sender is not the minter');\n        _;\n    }\n\n    constructor() initializer {}\n\n    function initialize(\n        address _owner,\n        address _minter,\n        INounsDAOForkEscrow _escrow,\n        uint32 _forkId,\n        uint256 startNounId,\n        uint256 tokensToClaim,\n        uint256 _forkingPeriodEndTimestamp\n    ) external initializer {\n        __ERC721_init('Nouns', 'NOUN');\n        _transferOwnership(_owner);\n        minter = _minter;\n        escrow = _escrow;\n        forkId = _forkId;\n        _currentNounId = startNounId;\n        remainingTokensToClaim = tokensToClaim;\n        forkingPeriodEndTimestamp = _forkingPeriodEndTimestamp;\n\n        NounsTokenFork originalToken = NounsTokenFork(address(escrow.nounsToken()));\n        descriptor = originalToken.descriptor();\n        seeder = originalToken.seeder();\n    }\n\n    /**\n     * @notice Claim new tokens if you escrowed original Nouns and forked into a new DAO governed by holders of this\n     * token.\n     * @dev Reverts if the sender is not the owner of the escrowed token.\n     * @param tokenIds The token IDs to claim\n     */\n    function claimFromEscrow(uint256[] calldata tokenIds) external {\n        for (uint256 i = 0; i < tokenIds.length; i++) {\n            uint256 nounId = tokenIds[i];\n            if (escrow.ownerOfEscrowedToken(forkId, nounId) != msg.sender) revert OnlyTokenOwnerCanClaim();\n\n            _mintWithOriginalSeed(msg.sender, nounId);\n        }\n\n        remainingTokensToClaim -= tokenIds.length;\n    }\n\n    /**\n     * @notice The original DAO can claim tokens during the forking period, on behalf of Nouners who choose to join\n     * a new fork DAO. Does not allow the original DAO to claim once the forking period has ended.\n     * @dev Assumes the original DAO is honest during the forking period.\n     * @param to The recipient of the tokens\n     * @param tokenIds The token IDs to claim\n     */\n    function claimDuringForkPeriod(address to, uint256[] calldata tokenIds) external {\n        uint256 currentNounId = _currentNounId;\n        uint256 maxNounId = 0;\n        if (msg.sender != escrow.dao()) revert OnlyOriginalDAO();\n        if (block.timestamp >= forkingPeriodEndTimestamp) revert OnlyDuringForkingPeriod();\n\n        for (uint256 i = 0; i < tokenIds.length; i++) {\n            uint256 nounId = tokenIds[i];\n            _mintWithOriginalSeed(to, nounId);\n\n            if (tokenIds[i] > maxNounId) maxNounId = tokenIds[i];\n        }\n\n        // This treats an important case:\n        // During a forking period, people can buy new Nouns on auction, with a higher ID than the auction ID at forking\n        // They can then join the fork with those IDs\n        // If we don't increment currentNounId, unpausing the fork auction house would revert\n        // Since it would attempt to mint a noun with an ID that already exists\n        if (maxNounId >= currentNounId) _currentNounId = maxNounId + 1;\n    }\n\n    /**\n     * @notice The IPFS URI of contract-level metadata.\n     */\n    function contractURI() public view returns (string memory) {\n        return string(abi.encodePacked('ipfs://', _contractURIHash));\n    }\n\n    /**\n     * @notice Set the _contractURIHash.\n     * @dev Only callable by the owner.\n     */\n    function setContractURIHash(string memory newContractURIHash) external onlyOwner {\n        _contractURIHash = newContractURIHash;\n    }\n\n    /**\n     * @notice Mint a Noun to the minter\n     * @dev Call _mintTo with the to address(es).\n     */\n    function mint() public override onlyMinter returns (uint256) {\n        return _mintTo(minter, _currentNounId++);\n    }\n\n    /**\n     * @notice Burn a noun.\n     */\n    function burn(uint256 nounId) public override onlyMinter {\n        _burn(nounId);\n        emit NounBurned(nounId);\n    }\n\n    /**\n     * @notice A distinct Uniform Resource Identifier (URI) for a given asset.\n     * @dev See {IERC721Metadata-tokenURI}.\n     */\n    function tokenURI(uint256 tokenId) public view override returns (string memory) {\n        require(_exists(tokenId), 'NounsToken: URI query for nonexistent token');\n        return descriptor.tokenURI(tokenId, seeds[tokenId]);\n    }\n\n    /**\n     * @notice Similar to `tokenURI`, but always serves a base64 encoded data URI\n     * with the JSON contents directly inlined.\n     */\n    function dataURI(uint256 tokenId) public view override returns (string memory) {\n        require(_exists(tokenId), 'NounsToken: URI query for nonexistent token');\n        return descriptor.dataURI(tokenId, seeds[tokenId]);\n    }\n\n    /**\n     * @notice Set the token minter.\n     * @dev Only callable by the owner when not locked.\n     */\n    function setMinter(address _minter) external override onlyOwner whenMinterNotLocked {\n        minter = _minter;\n\n        emit MinterUpdated(_minter);\n    }\n\n    /**\n     * @notice Lock the minter.\n     * @dev This cannot be reversed and is only callable by the owner when not locked.\n     */\n    function lockMinter() external override onlyOwner whenMinterNotLocked {\n        isMinterLocked = true;\n\n        emit MinterLocked();\n    }\n\n    /**\n     * @notice Set the token URI descriptor.\n     * @dev Only callable by the owner when not locked.\n     */\n    function setDescriptor(INounsDescriptorMinimal _descriptor) external override onlyOwner whenDescriptorNotLocked {\n        descriptor = _descriptor;\n\n        emit DescriptorUpdated(_descriptor);\n    }\n\n    /**\n     * @notice Lock the descriptor.\n     * @dev This cannot be reversed and is only callable by the owner when not locked.\n     */\n    function lockDescriptor() external override onlyOwner whenDescriptorNotLocked {\n        isDescriptorLocked = true;\n\n        emit DescriptorLocked();\n    }\n\n    /**\n     * @notice Set the token seeder.\n     * @dev Only callable by the owner when not locked.\n     */\n    function setSeeder(INounsSeeder _seeder) external override onlyOwner whenSeederNotLocked {\n        seeder = _seeder;\n\n        emit SeederUpdated(_seeder);\n    }\n\n    /**\n     * @notice Lock the seeder.\n     * @dev This cannot be reversed and is only callable by the owner when not locked.\n     */\n    function lockSeeder() external override onlyOwner whenSeederNotLocked {\n        isSeederLocked = true;\n\n        emit SeederLocked();\n    }\n\n    /**\n     * @notice Mint a Noun with `nounId` to the provided `to` address.\n     */\n    function _mintTo(address to, uint256 nounId) internal returns (uint256) {\n        INounsSeeder.Seed memory seed = seeds[nounId] = seeder.generateSeed(nounId, descriptor);\n\n        _mint(to, nounId);\n        emit NounCreated(nounId, seed);\n\n        return nounId;\n    }\n\n    /**\n     * @notice Mint a new token using the original Nouns seed.\n     */\n    function _mintWithOriginalSeed(address to, uint256 nounId) internal {\n        (uint48 background, uint48 body, uint48 accessory, uint48 head, uint48 glasses) = NounsTokenFork(\n            address(escrow.nounsToken())\n        ).seeds(nounId);\n        INounsSeeder.Seed memory seed = INounsSeeder.Seed(background, body, accessory, head, glasses);\n\n        seeds[nounId] = seed;\n        _mint(to, nounId);\n\n        emit NounCreated(nounId, seed);\n    }\n\n    /**\n     * @dev Reverts when `msg.sender` is not the owner of this contract; in the case of Noun DAOs it should be the\n     * DAO's treasury contract.\n     */\n    function _authorizeUpgrade(address) internal view override onlyOwner {}\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts/interfaces/IERC1271.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC1271 standard signature validation method for\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\n *\n * _Available since v4.1._\n */\ninterface IERC1271 {\n    /**\n     * @dev Should return whether the signature provided is valid for the provided data\n     * @param hash      Hash of the data to be signed\n     * @param signature Signature byte array associated with _data\n     */\n    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts/utils/Strings.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        // Inspired by OraclizeAPI's implementation - MIT licence\n        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n        if (value == 0) {\n            return \"0\";\n        }\n        uint256 temp = value;\n        uint256 digits;\n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n        bytes memory buffer = new bytes(digits);\n        while (value != 0) {\n            digits -= 1;\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n            value /= 10;\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) {\n            return \"0x00\";\n        }\n        uint256 temp = value;\n        uint256 length = 0;\n        while (temp != 0) {\n            length++;\n            temp >>= 8;\n        }\n        return toHexString(value, length);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _HEX_SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal initializer {\n        __Context_init_unchained();\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal initializer {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n    uint256[49] private __gap;\n}\n"
      },
      "contracts/governance/fork/newdao/token/base/ERC721CheckpointableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\n\n/// @title Vote checkpointing for an ERC-721 token\n\n/*********************************\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░██░░░████░░██░░░████░░░ *\n * ░░██████░░░████████░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n *********************************/\n\n// LICENSE\n// ERC721CheckpointableUpgradeable.sol is a modified version of ERC721Checkpointable.sol in this repository.\n// ERC721Checkpointable.sol uses and modifies part of Compound Lab's Comp.sol:\n// https://github.com/compound-finance/compound-protocol/blob/ae4388e780a8d596d97619d9704a931a2752c2bc/contracts/Governance/Comp.sol\n//\n// Comp.sol source code Copyright 2020 Compound Labs, Inc. licensed under the BSD-3-Clause license.\n// With modifications by Nounders DAO.\n//\n// Additional conditions of BSD-3-Clause can be found here: https://opensource.org/licenses/BSD-3-Clause\n//\n// ERC721CheckpointableUpgradeable.sol MODIFICATIONS:\n// - Inherits from OpenZeppelin's ERC721EnumerableUpgradeable.sol, removing the original modification Nouns made to\n//   ERC721.sol, where for each mint two Transfer events were emitted; this modified implementation sticks with the\n//   OpenZeppelin standard.\n// - More importantly, this inheritance change makes the token upgradable, which we deemed important in the context of\n//   forks, in order to give new Nouns forks enough of a chance to modify their contracts to the new DAO's needs.\n// - Fixes a critical bug in `delegateBySig`, where the previous version allowed delegating to address zero, which then\n//   reverts whenever that owner tries to delegate anew or transfer their tokens. The fix is simply to revert on any\n//   attempt to delegate to address zero.\n//\n// ERC721Checkpointable.sol MODIFICATIONS:\n// Checkpointing logic from Comp.sol has been used with the following modifications:\n// - `delegates` is renamed to `_delegates` and is set to private\n// - `delegates` is a public function that uses the `_delegates` mapping look-up, but unlike\n//   Comp.sol, returns the delegator's own address if there is no delegate.\n//   This avoids the delegator needing to \"delegate to self\" with an additional transaction\n// - `_transferTokens()` is renamed `_beforeTokenTransfer()` and adapted to hook into OpenZeppelin's ERC721 hooks.\n\npragma solidity ^0.8.19;\n\nimport { ERC721EnumerableUpgradeable } from '@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol';\n\nabstract contract ERC721CheckpointableUpgradeable is ERC721EnumerableUpgradeable {\n    /// @notice Defines decimals as per ERC-20 convention to make integrations with 3rd party governance platforms easier\n    uint8 public constant decimals = 0;\n\n    /// @notice A record of each accounts delegate\n    mapping(address => address) private _delegates;\n\n    /// @notice A checkpoint for marking number of votes from a given block\n    struct Checkpoint {\n        uint32 fromBlock;\n        uint96 votes;\n    }\n\n    /// @notice A record of votes checkpoints for each account, by index\n    mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n    /// @notice The number of checkpoints for each account\n    mapping(address => uint32) public numCheckpoints;\n\n    /// @notice The EIP-712 typehash for the contract's domain\n    bytes32 public constant DOMAIN_TYPEHASH =\n        keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');\n\n    /// @notice The EIP-712 typehash for the delegation struct used by the contract\n    bytes32 public constant DELEGATION_TYPEHASH =\n        keccak256('Delegation(address delegatee,uint256 nonce,uint256 expiry)');\n\n    /// @notice A record of states for signing / validating signatures\n    mapping(address => uint256) public nonces;\n\n    /// @notice An event thats emitted when an account changes its delegate\n    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n    /// @notice An event thats emitted when a delegate account's vote balance changes\n    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n    /**\n     * @notice The votes a delegator can delegate, which is the current balance of the delegator.\n     * @dev Used when calling `_delegate()`\n     */\n    function votesToDelegate(address delegator) public view returns (uint96) {\n        return safe96(balanceOf(delegator), 'ERC721Checkpointable::votesToDelegate: amount exceeds 96 bits');\n    }\n\n    /**\n     * @notice Overrides the standard `Comp.sol` delegates mapping to return\n     * the delegator's own address if they haven't delegated.\n     * This avoids having to delegate to oneself.\n     */\n    function delegates(address delegator) public view returns (address) {\n        address current = _delegates[delegator];\n        return current == address(0) ? delegator : current;\n    }\n\n    /**\n     * @notice Adapted from `_transferTokens()` in `Comp.sol` to update delegate votes.\n     * @dev hooks into OpenZeppelin's `ERC721._transfer`\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal override {\n        super._beforeTokenTransfer(from, to, tokenId);\n\n        /// @notice Differs from `_transferTokens()` to use `delegates` override method to simulate auto-delegation\n        _moveDelegates(delegates(from), delegates(to), 1);\n    }\n\n    /**\n     * @notice Delegate votes from `msg.sender` to `delegatee`\n     * @param delegatee The address to delegate votes to\n     */\n    function delegate(address delegatee) public {\n        if (delegatee == address(0)) delegatee = msg.sender;\n        return _delegate(msg.sender, delegatee);\n    }\n\n    /**\n     * @notice Delegates votes from signatory to `delegatee`\n     * @param delegatee The address to delegate votes to\n     * @param nonce The contract state required to match the signature\n     * @param expiry The time at which to expire the signature\n     * @param v The recovery byte of the signature\n     * @param r Half of the ECDSA signature pair\n     * @param s Half of the ECDSA signature pair\n     */\n    function delegateBySig(\n        address delegatee,\n        uint256 nonce,\n        uint256 expiry,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) public {\n        require(delegatee != address(0), 'ERC721Checkpointable::delegateBySig: delegatee cannot be zero address');\n        bytes32 domainSeparator = keccak256(\n            abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name())), block.chainid, address(this))\n        );\n        bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\n        bytes32 digest = keccak256(abi.encodePacked('\\x19\\x01', domainSeparator, structHash));\n        address signatory = ecrecover(digest, v, r, s);\n        require(signatory != address(0), 'ERC721Checkpointable::delegateBySig: invalid signature');\n        require(nonce == nonces[signatory]++, 'ERC721Checkpointable::delegateBySig: invalid nonce');\n        require(block.timestamp <= expiry, 'ERC721Checkpointable::delegateBySig: signature expired');\n        return _delegate(signatory, delegatee);\n    }\n\n    /**\n     * @notice Gets the current votes balance for `account`\n     * @param account The address to get votes balance\n     * @return The number of current votes for `account`\n     */\n    function getCurrentVotes(address account) external view returns (uint96) {\n        uint32 nCheckpoints = numCheckpoints[account];\n        return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\n    }\n\n    /**\n     * @notice Determine the prior number of votes for an account as of a block number\n     * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n     * @param account The address of the account to check\n     * @param blockNumber The block number to get the vote balance at\n     * @return The number of votes the account had as of the given block\n     */\n    function getPriorVotes(address account, uint256 blockNumber) public view returns (uint96) {\n        require(blockNumber < block.number, 'ERC721Checkpointable::getPriorVotes: not yet determined');\n\n        uint32 nCheckpoints = numCheckpoints[account];\n        if (nCheckpoints == 0) {\n            return 0;\n        }\n\n        // First check most recent balance\n        if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\n            return checkpoints[account][nCheckpoints - 1].votes;\n        }\n\n        // Next check implicit zero balance\n        if (checkpoints[account][0].fromBlock > blockNumber) {\n            return 0;\n        }\n\n        uint32 lower = 0;\n        uint32 upper = nCheckpoints - 1;\n        while (upper > lower) {\n            uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n            Checkpoint memory cp = checkpoints[account][center];\n            if (cp.fromBlock == blockNumber) {\n                return cp.votes;\n            } else if (cp.fromBlock < blockNumber) {\n                lower = center;\n            } else {\n                upper = center - 1;\n            }\n        }\n        return checkpoints[account][lower].votes;\n    }\n\n    function _delegate(address delegator, address delegatee) internal {\n        /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation\n        address currentDelegate = delegates(delegator);\n\n        _delegates[delegator] = delegatee;\n\n        emit DelegateChanged(delegator, currentDelegate, delegatee);\n\n        uint96 amount = votesToDelegate(delegator);\n\n        _moveDelegates(currentDelegate, delegatee, amount);\n    }\n\n    function _moveDelegates(\n        address srcRep,\n        address dstRep,\n        uint96 amount\n    ) internal {\n        if (srcRep != dstRep && amount > 0) {\n            if (srcRep != address(0)) {\n                uint32 srcRepNum = numCheckpoints[srcRep];\n                uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\n                uint96 srcRepNew = sub96(srcRepOld, amount, 'ERC721Checkpointable::_moveDelegates: amount underflows');\n                _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);\n            }\n\n            if (dstRep != address(0)) {\n                uint32 dstRepNum = numCheckpoints[dstRep];\n                uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\n                uint96 dstRepNew = add96(dstRepOld, amount, 'ERC721Checkpointable::_moveDelegates: amount overflows');\n                _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\n            }\n        }\n    }\n\n    function _writeCheckpoint(\n        address delegatee,\n        uint32 nCheckpoints,\n        uint96 oldVotes,\n        uint96 newVotes\n    ) internal {\n        uint32 blockNumber = safe32(\n            block.number,\n            'ERC721Checkpointable::_writeCheckpoint: block number exceeds 32 bits'\n        );\n\n        if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\n            checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\n        } else {\n            checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\n            numCheckpoints[delegatee] = nCheckpoints + 1;\n        }\n\n        emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\n    }\n\n    function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n        require(n < 2**32, errorMessage);\n        return uint32(n);\n    }\n\n    function safe96(uint256 n, string memory errorMessage) internal pure returns (uint96) {\n        require(n < 2**96, errorMessage);\n        return uint96(n);\n    }\n\n    function add96(\n        uint96 a,\n        uint96 b,\n        string memory errorMessage\n    ) internal pure returns (uint96) {\n        uint96 c = a + b;\n        require(c >= a, errorMessage);\n        return c;\n    }\n\n    function sub96(\n        uint96 a,\n        uint96 b,\n        string memory errorMessage\n    ) internal pure returns (uint96) {\n        require(b <= a, errorMessage);\n        return a - b;\n    }\n}\n"
      },
      "contracts/interfaces/INounsDescriptorMinimal.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\n/// @title Common interface for NounsDescriptor versions, as used by NounsToken and NounsSeeder.\n\n/*********************************\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░██░░░████░░██░░░████░░░ *\n * ░░██████░░░████████░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n *********************************/\n\npragma solidity ^0.8.6;\n\nimport { INounsSeeder } from './INounsSeeder.sol';\n\ninterface INounsDescriptorMinimal {\n    ///\n    /// USED BY TOKEN\n    ///\n\n    function tokenURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view returns (string memory);\n\n    function dataURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view returns (string memory);\n\n    ///\n    /// USED BY SEEDER\n    ///\n\n    function backgroundCount() external view returns (uint256);\n\n    function bodyCount() external view returns (uint256);\n\n    function accessoryCount() external view returns (uint256);\n\n    function headCount() external view returns (uint256);\n\n    function glassesCount() external view returns (uint256);\n}\n"
      },
      "contracts/interfaces/INounsSeeder.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\n/// @title Interface for NounsSeeder\n\n/*********************************\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░██░░░████░░██░░░████░░░ *\n * ░░██████░░░████████░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n *********************************/\n\npragma solidity ^0.8.6;\n\nimport { INounsDescriptorMinimal } from './INounsDescriptorMinimal.sol';\n\ninterface INounsSeeder {\n    struct Seed {\n        uint48 background;\n        uint48 body;\n        uint48 accessory;\n        uint48 head;\n        uint48 glasses;\n    }\n\n    function generateSeed(uint256 nounId, INounsDescriptorMinimal descriptor) external view returns (Seed memory);\n}\n"
      },
      "contracts/governance/fork/newdao/token/INounsTokenFork.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\n/// @title Interface for NounsTokenFork\n\n/*********************************\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░██░░░████░░██░░░████░░░ *\n * ░░██████░░░████████░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░██░░██░░░████░░██░░░████░░░ *\n * ░░░░░░█████████░░█████████░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *\n *********************************/\n\npragma solidity ^0.8.19;\n\nimport { IERC721Upgradeable } from '@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol';\nimport { INounsDescriptorMinimal } from '../../../../interfaces/INounsDescriptorMinimal.sol';\nimport { INounsSeeder } from '../../../../interfaces/INounsSeeder.sol';\n\ninterface INounsTokenFork is IERC721Upgradeable {\n    event NounCreated(uint256 indexed tokenId, INounsSeeder.Seed seed);\n\n    event NounBurned(uint256 indexed tokenId);\n\n    event MinterUpdated(address minter);\n\n    event MinterLocked();\n\n    event DescriptorUpdated(INounsDescriptorMinimal descriptor);\n\n    event DescriptorLocked();\n\n    event SeederUpdated(INounsSeeder seeder);\n\n    event SeederLocked();\n\n    function mint() external returns (uint256);\n\n    function burn(uint256 tokenId) external;\n\n    function dataURI(uint256 tokenId) external returns (string memory);\n\n    function setMinter(address minter) external;\n\n    function lockMinter() external;\n\n    function setDescriptor(INounsDescriptorMinimal descriptor) external;\n\n    function lockDescriptor() external;\n\n    function setSeeder(INounsSeeder seeder) external;\n\n    function lockSeeder() external;\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool _approved) external;\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes calldata data\n    ) external;\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is ERC1967Upgrade {\n    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n    address private immutable __self = address(this);\n\n    /**\n     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n     * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n     * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n     * fail.\n     */\n    modifier onlyProxy() {\n        require(address(this) != __self, \"Function must be called through delegatecall\");\n        require(_getImplementation() == __self, \"Function must be called through active proxy\");\n        _;\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy to `newImplementation`.\n     *\n     * Calls {_authorizeUpgrade}.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function upgradeTo(address newImplementation) external virtual onlyProxy {\n        _authorizeUpgrade(newImplementation);\n        _upgradeToAndCallSecure(newImplementation, new bytes(0), false);\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n     * encoded in `data`.\n     *\n     * Calls {_authorizeUpgrade}.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {\n        _authorizeUpgrade(newImplementation);\n        _upgradeToAndCallSecure(newImplementation, data, true);\n    }\n\n    /**\n     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n     * {upgradeTo} and {upgradeToAndCall}.\n     *\n     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n     *\n     * ```solidity\n     * function _authorizeUpgrade(address) internal override onlyOwner {}\n     * ```\n     */\n    function _authorizeUpgrade(address newImplementation) internal virtual;\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal initializer {\n        __Context_init_unchained();\n    }\n\n    function __Context_init_unchained() internal initializer {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n    uint256[50] private __gap;\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the\n * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() initializer {}\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     */\n    bool private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Modifier to protect an initializer function from being invoked twice.\n     */\n    modifier initializer() {\n        require(_initializing || !_initialized, \"Initializable: contract is already initialized\");\n\n        bool isTopLevelCall = !_initializing;\n        if (isTopLevelCall) {\n            _initializing = true;\n            _initialized = true;\n        }\n\n        _;\n\n        if (isTopLevelCall) {\n            _initializing = false;\n        }\n    }\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (token/ERC721/extensions/ERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC721Upgradeable.sol\";\nimport \"./IERC721EnumerableUpgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\n * enumerability of all the token ids in the contract as well as all token ids owned by each\n * account.\n */\nabstract contract ERC721EnumerableUpgradeable is Initializable, ERC721Upgradeable, IERC721EnumerableUpgradeable {\n    function __ERC721Enumerable_init() internal initializer {\n        __Context_init_unchained();\n        __ERC165_init_unchained();\n        __ERC721Enumerable_init_unchained();\n    }\n\n    function __ERC721Enumerable_init_unchained() internal initializer {\n    }\n    // Mapping from owner to list of owned token IDs\n    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\n\n    // Mapping from token ID to index of the owner tokens list\n    mapping(uint256 => uint256) private _ownedTokensIndex;\n\n    // Array with all token ids, used for enumeration\n    uint256[] private _allTokens;\n\n    // Mapping from token id to position in the allTokens array\n    mapping(uint256 => uint256) private _allTokensIndex;\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165Upgradeable, ERC721Upgradeable) returns (bool) {\n        return interfaceId == type(IERC721EnumerableUpgradeable).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\n     */\n    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {\n        require(index < ERC721Upgradeable.balanceOf(owner), \"ERC721Enumerable: owner index out of bounds\");\n        return _ownedTokens[owner][index];\n    }\n\n    /**\n     * @dev See {IERC721Enumerable-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _allTokens.length;\n    }\n\n    /**\n     * @dev See {IERC721Enumerable-tokenByIndex}.\n     */\n    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {\n        require(index < ERC721EnumerableUpgradeable.totalSupply(), \"ERC721Enumerable: global index out of bounds\");\n        return _allTokens[index];\n    }\n\n    /**\n     * @dev Hook that is called before any token transfer. This includes minting\n     * and burning.\n     *\n     * Calling conditions:\n     *\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n     * transferred to `to`.\n     * - When `from` is zero, `tokenId` will be minted for `to`.\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual override {\n        super._beforeTokenTransfer(from, to, tokenId);\n\n        if (from == address(0)) {\n            _addTokenToAllTokensEnumeration(tokenId);\n        } else if (from != to) {\n            _removeTokenFromOwnerEnumeration(from, tokenId);\n        }\n        if (to == address(0)) {\n            _removeTokenFromAllTokensEnumeration(tokenId);\n        } else if (to != from) {\n            _addTokenToOwnerEnumeration(to, tokenId);\n        }\n    }\n\n    /**\n     * @dev Private function to add a token to this extension's ownership-tracking data structures.\n     * @param to address representing the new owner of the given token ID\n     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\n     */\n    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {\n        uint256 length = ERC721Upgradeable.balanceOf(to);\n        _ownedTokens[to][length] = tokenId;\n        _ownedTokensIndex[tokenId] = length;\n    }\n\n    /**\n     * @dev Private function to add a token to this extension's token tracking data structures.\n     * @param tokenId uint256 ID of the token to be added to the tokens list\n     */\n    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {\n        _allTokensIndex[tokenId] = _allTokens.length;\n        _allTokens.push(tokenId);\n    }\n\n    /**\n     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\n     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\n     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\n     * This has O(1) time complexity, but alters the order of the _ownedTokens array.\n     * @param from address representing the previous owner of the given token ID\n     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\n     */\n    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {\n        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and\n        // then delete the last slot (swap and pop).\n\n        uint256 lastTokenIndex = ERC721Upgradeable.balanceOf(from) - 1;\n        uint256 tokenIndex = _ownedTokensIndex[tokenId];\n\n        // When the token to delete is the last token, the swap operation is unnecessary\n        if (tokenIndex != lastTokenIndex) {\n            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];\n\n            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n        }\n\n        // This also deletes the contents at the last position of the array\n        delete _ownedTokensIndex[tokenId];\n        delete _ownedTokens[from][lastTokenIndex];\n    }\n\n    /**\n     * @dev Private function to remove a token from this extension's token tracking data structures.\n     * This has O(1) time complexity, but alters the order of the _allTokens array.\n     * @param tokenId uint256 ID of the token to be removed from the tokens list\n     */\n    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {\n        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and\n        // then delete the last slot (swap and pop).\n\n        uint256 lastTokenIndex = _allTokens.length - 1;\n        uint256 tokenIndex = _allTokensIndex[tokenId];\n\n        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so\n        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding\n        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)\n        uint256 lastTokenId = _allTokens[lastTokenIndex];\n\n        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token\n        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index\n\n        // This also deletes the contents at the last position of the array\n        delete _allTokensIndex[tokenId];\n        _allTokens.pop();\n    }\n    uint256[46] private __gap;\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721Upgradeable is IERC165Upgradeable {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool _approved) external;\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes calldata data\n    ) external;\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n    // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n    /**\n     * @dev Storage slot with the address of the current implementation.\n     * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n     * validated in the constructor.\n     */\n    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /**\n     * @dev Emitted when the implementation is upgraded.\n     */\n    event Upgraded(address indexed implementation);\n\n    /**\n     * @dev Returns the current implementation address.\n     */\n    function _getImplementation() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 implementation slot.\n     */\n    function _setImplementation(address newImplementation) private {\n        require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n    }\n\n    /**\n     * @dev Perform implementation upgrade\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeTo(address newImplementation) internal {\n        _setImplementation(newImplementation);\n        emit Upgraded(newImplementation);\n    }\n\n    /**\n     * @dev Perform implementation upgrade with additional setup call.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeToAndCall(\n        address newImplementation,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        _upgradeTo(newImplementation);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(newImplementation, data);\n        }\n    }\n\n    /**\n     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeToAndCallSecure(\n        address newImplementation,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        address oldImplementation = _getImplementation();\n\n        // Initial upgrade and setup call\n        _setImplementation(newImplementation);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(newImplementation, data);\n        }\n\n        // Perform rollback test if not already in progress\n        StorageSlot.BooleanSlot storage rollbackTesting = StorageSlot.getBooleanSlot(_ROLLBACK_SLOT);\n        if (!rollbackTesting.value) {\n            // Trigger rollback using upgradeTo from the new implementation\n            rollbackTesting.value = true;\n            Address.functionDelegateCall(\n                newImplementation,\n                abi.encodeWithSignature(\"upgradeTo(address)\", oldImplementation)\n            );\n            rollbackTesting.value = false;\n            // Check rollback was effective\n            require(oldImplementation == _getImplementation(), \"ERC1967Upgrade: upgrade breaks further upgrades\");\n            // Finally reset to the new implementation and log the upgrade\n            _upgradeTo(newImplementation);\n        }\n    }\n\n    /**\n     * @dev Storage slot with the admin of the contract.\n     * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n     * validated in the constructor.\n     */\n    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /**\n     * @dev Emitted when the admin account has changed.\n     */\n    event AdminChanged(address previousAdmin, address newAdmin);\n\n    /**\n     * @dev Returns the current admin.\n     */\n    function _getAdmin() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 admin slot.\n     */\n    function _setAdmin(address newAdmin) private {\n        require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n    }\n\n    /**\n     * @dev Changes the admin of the proxy.\n     *\n     * Emits an {AdminChanged} event.\n     */\n    function _changeAdmin(address newAdmin) internal {\n        emit AdminChanged(_getAdmin(), newAdmin);\n        _setAdmin(newAdmin);\n    }\n\n    /**\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n     */\n    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n    /**\n     * @dev Emitted when the beacon is upgraded.\n     */\n    event BeaconUpgraded(address indexed beacon);\n\n    /**\n     * @dev Returns the current beacon.\n     */\n    function _getBeacon() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new beacon in the EIP1967 beacon slot.\n     */\n    function _setBeacon(address newBeacon) private {\n        require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n        require(\n            Address.isContract(IBeacon(newBeacon).implementation()),\n            \"ERC1967: beacon implementation is not a contract\"\n        );\n        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n    }\n\n    /**\n     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n     *\n     * Emits a {BeaconUpgraded} event.\n     */\n    function _upgradeBeaconToAndCall(\n        address newBeacon,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        _setBeacon(newBeacon);\n        emit BeaconUpgraded(newBeacon);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n        }\n    }\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721Upgradeable.sol\";\nimport \"./IERC721ReceiverUpgradeable.sol\";\nimport \"./extensions/IERC721MetadataUpgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../utils/StringsUpgradeable.sol\";\nimport \"../../utils/introspection/ERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable {\n    using AddressUpgradeable for address;\n    using StringsUpgradeable for uint256;\n\n    // Token name\n    string private _name;\n\n    // Token symbol\n    string private _symbol;\n\n    // Mapping from token ID to owner address\n    mapping(uint256 => address) private _owners;\n\n    // Mapping owner address to token count\n    mapping(address => uint256) private _balances;\n\n    // Mapping from token ID to approved address\n    mapping(uint256 => address) private _tokenApprovals;\n\n    // Mapping from owner to operator approvals\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n    /**\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n     */\n    function __ERC721_init(string memory name_, string memory symbol_) internal initializer {\n        __Context_init_unchained();\n        __ERC165_init_unchained();\n        __ERC721_init_unchained(name_, symbol_);\n    }\n\n    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal initializer {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {\n        return\n            interfaceId == type(IERC721Upgradeable).interfaceId ||\n            interfaceId == type(IERC721MetadataUpgradeable).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC721-balanceOf}.\n     */\n    function balanceOf(address owner) public view virtual override returns (uint256) {\n        require(owner != address(0), \"ERC721: balance query for the zero address\");\n        return _balances[owner];\n    }\n\n    /**\n     * @dev See {IERC721-ownerOf}.\n     */\n    function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n        address owner = _owners[tokenId];\n        require(owner != address(0), \"ERC721: owner query for nonexistent token\");\n        return owner;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-name}.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-symbol}.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-tokenURI}.\n     */\n    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n        require(_exists(tokenId), \"ERC721Metadata: URI query for nonexistent token\");\n\n        string memory baseURI = _baseURI();\n        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n    }\n\n    /**\n     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n     * by default, can be overriden in child contracts.\n     */\n    function _baseURI() internal view virtual returns (string memory) {\n        return \"\";\n    }\n\n    /**\n     * @dev See {IERC721-approve}.\n     */\n    function approve(address to, uint256 tokenId) public virtual override {\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\n        require(to != owner, \"ERC721: approval to current owner\");\n\n        require(\n            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n            \"ERC721: approve caller is not owner nor approved for all\"\n        );\n\n        _approve(to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-getApproved}.\n     */\n    function getApproved(uint256 tokenId) public view virtual override returns (address) {\n        require(_exists(tokenId), \"ERC721: approved query for nonexistent token\");\n\n        return _tokenApprovals[tokenId];\n    }\n\n    /**\n     * @dev See {IERC721-setApprovalForAll}.\n     */\n    function setApprovalForAll(address operator, bool approved) public virtual override {\n        _setApprovalForAll(_msgSender(), operator, approved);\n    }\n\n    /**\n     * @dev See {IERC721-isApprovedForAll}.\n     */\n    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n        return _operatorApprovals[owner][operator];\n    }\n\n    /**\n     * @dev See {IERC721-transferFrom}.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) public virtual override {\n        //solhint-disable-next-line max-line-length\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n\n        _transfer(from, to, tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) public virtual override {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory _data\n    ) public virtual override {\n        require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n        _safeTransfer(from, to, tokenId, _data);\n    }\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * `_data` is additional data, it has no specified format and it is sent in call to `to`.\n     *\n     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeTransfer(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory _data\n    ) internal virtual {\n        _transfer(from, to, tokenId);\n        require(_checkOnERC721Received(from, to, tokenId, _data), \"ERC721: transfer to non ERC721Receiver implementer\");\n    }\n\n    /**\n     * @dev Returns whether `tokenId` exists.\n     *\n     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n     *\n     * Tokens start existing when they are minted (`_mint`),\n     * and stop existing when they are burned (`_burn`).\n     */\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\n        return _owners[tokenId] != address(0);\n    }\n\n    /**\n     * @dev Returns whether `spender` is allowed to manage `tokenId`.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n        require(_exists(tokenId), \"ERC721: operator query for nonexistent token\");\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\n        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));\n    }\n\n    /**\n     * @dev Safely mints `tokenId` and transfers it to `to`.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeMint(address to, uint256 tokenId) internal virtual {\n        _safeMint(to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeMint(\n        address to,\n        uint256 tokenId,\n        bytes memory _data\n    ) internal virtual {\n        _mint(to, tokenId);\n        require(\n            _checkOnERC721Received(address(0), to, tokenId, _data),\n            \"ERC721: transfer to non ERC721Receiver implementer\"\n        );\n    }\n\n    /**\n     * @dev Mints `tokenId` and transfers it to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - `to` cannot be the zero address.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _mint(address to, uint256 tokenId) internal virtual {\n        require(to != address(0), \"ERC721: mint to the zero address\");\n        require(!_exists(tokenId), \"ERC721: token already minted\");\n\n        _beforeTokenTransfer(address(0), to, tokenId);\n\n        _balances[to] += 1;\n        _owners[tokenId] = to;\n\n        emit Transfer(address(0), to, tokenId);\n    }\n\n    /**\n     * @dev Destroys `tokenId`.\n     * The approval is cleared when the token is burned.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _burn(uint256 tokenId) internal virtual {\n        address owner = ERC721Upgradeable.ownerOf(tokenId);\n\n        _beforeTokenTransfer(owner, address(0), tokenId);\n\n        // Clear approvals\n        _approve(address(0), tokenId);\n\n        _balances[owner] -= 1;\n        delete _owners[tokenId];\n\n        emit Transfer(owner, address(0), tokenId);\n    }\n\n    /**\n     * @dev Transfers `tokenId` from `from` to `to`.\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _transfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {\n        require(ERC721Upgradeable.ownerOf(tokenId) == from, \"ERC721: transfer of token that is not own\");\n        require(to != address(0), \"ERC721: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, tokenId);\n\n        // Clear approvals from the previous owner\n        _approve(address(0), tokenId);\n\n        _balances[from] -= 1;\n        _balances[to] += 1;\n        _owners[tokenId] = to;\n\n        emit Transfer(from, to, tokenId);\n    }\n\n    /**\n     * @dev Approve `to` to operate on `tokenId`\n     *\n     * Emits a {Approval} event.\n     */\n    function _approve(address to, uint256 tokenId) internal virtual {\n        _tokenApprovals[tokenId] = to;\n        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId);\n    }\n\n    /**\n     * @dev Approve `operator` to operate on all of `owner` tokens\n     *\n     * Emits a {ApprovalForAll} event.\n     */\n    function _setApprovalForAll(\n        address owner,\n        address operator,\n        bool approved\n    ) internal virtual {\n        require(owner != operator, \"ERC721: approve to caller\");\n        _operatorApprovals[owner][operator] = approved;\n        emit ApprovalForAll(owner, operator, approved);\n    }\n\n    /**\n     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n     * The call is not executed if the target address is not a contract.\n     *\n     * @param from address representing the previous owner of the given token ID\n     * @param to target address that will receive the tokens\n     * @param tokenId uint256 ID of the token to be transferred\n     * @param _data bytes optional data to send along with the call\n     * @return bool whether the call correctly returned the expected magic value\n     */\n    function _checkOnERC721Received(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory _data\n    ) private returns (bool) {\n        if (to.isContract()) {\n            try IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\n                return retval == IERC721ReceiverUpgradeable.onERC721Received.selector;\n            } catch (bytes memory reason) {\n                if (reason.length == 0) {\n                    revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n                } else {\n                    assembly {\n                        revert(add(32, reason), mload(reason))\n                    }\n                }\n            }\n        } else {\n            return true;\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any token transfer. This includes minting\n     * and burning.\n     *\n     * Calling conditions:\n     *\n     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n     * transferred to `to`.\n     * - When `from` is zero, `tokenId` will be minted for `to`.\n     * - When `to` is zero, ``from``'s `tokenId` will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {}\n    uint256[44] private __gap;\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721EnumerableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721Upgradeable.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721EnumerableUpgradeable is IERC721Upgradeable {\n    /**\n     * @dev Returns the total amount of tokens stored by the contract.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n     */\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);\n\n    /**\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n     * Use along with {totalSupply} to enumerate all tokens.\n     */\n    function tokenByIndex(uint256 index) external view returns (uint256);\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts/proxy/beacon/IBeacon.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n    /**\n     * @dev Must return an address that can be used as a delegate call target.\n     *\n     * {BeaconProxy} will check that this address is a contract.\n     */\n    function implementation() external view returns (address);\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts/utils/StorageSlot.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly {\n            r.slot := slot\n        }\n    }\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721ReceiverUpgradeable {\n    /**\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n     * by `operator` from `from`, this function is called.\n     *\n     * It must return its Solidity selector to confirm the token transfer.\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n     *\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\n     */\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721Upgradeable.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (utils/Address.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize, which returns 0 for contracts in\n        // construction, since the code is only stored at the end of the\n        // constructor execution.\n\n        uint256 size;\n        assembly {\n            size := extcodesize(account)\n        }\n        return size > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n    bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        // Inspired by OraclizeAPI's implementation - MIT licence\n        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n        if (value == 0) {\n            return \"0\";\n        }\n        uint256 temp = value;\n        uint256 digits;\n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n        bytes memory buffer = new bytes(digits);\n        while (value != 0) {\n            digits -= 1;\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n            value /= 10;\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) {\n            return \"0x00\";\n        }\n        uint256 temp = value;\n        uint256 length = 0;\n        while (temp != 0) {\n            length++;\n            temp >>= 8;\n        }\n        return toHexString(value, length);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _HEX_SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n}\n"
      },
      "../../node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.0 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\n    function __ERC165_init() internal initializer {\n        __ERC165_init_unchained();\n    }\n\n    function __ERC165_init_unchained() internal initializer {\n    }\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165Upgradeable).interfaceId;\n    }\n    uint256[50] private __gap;\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "@ensdomains/=../../node_modules/@ensdomains/",
        "@openzeppelin/=../../node_modules/@openzeppelin/",
        "base64-sol/=../../node_modules/base64-sol/",
        "eth-gas-reporter/=../../node_modules/eth-gas-reporter/",
        "hardhat/=../../node_modules/hardhat/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": false,
      "libraries": {
        "contracts/governance/NounsDAOAdmin.sol": {
          "NounsDAOAdmin": "0xd7c7c3c447Df757a77C81FcFf07f10bB22d98f4a"
        },
        "contracts/governance/NounsDAODynamicQuorum.sol": {
          "NounsDAODynamicQuorum": "0xB5Aa61EfF82Ea7B4ea6443532dF15B7d4B40C3A0"
        },
        "contracts/governance/NounsDAOProposals.sol": {
          "NounsDAOProposals": "0xac6eefcC699047856c07c8679e1339903bd5ffCC"
        },
        "contracts/governance/NounsDAOVotes.sol": {
          "NounsDAOVotes": "0x3e4e4D094a73AAC69Ff6592CDa602B76134951d6"
        },
        "contracts/governance/fork/NounsDAOFork.sol": {
          "NounsDAOFork": "0x3d4F1EE041C31aFc0FBda4f058D34544d71EB6aD"
        }
      }
    }
  }}