{"file_path":"src/dao/Voter.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\nimport { DelegatedOps } from '../dependencies/DelegatedOps.sol';\nimport { EpochTracker } from '../dependencies/EpochTracker.sol';\nimport { CoreOwnable } from '../dependencies/CoreOwnable.sol';\nimport { IGovStaker } from '../interfaces/IGovStaker.sol';\nimport { ICore } from '../interfaces/ICore.sol';\nimport { BytesLib } from \"solidity-bytes-utils/contracts/BytesLib.sol\";\n\ninterface IERC20 {\n    function decimals() external view returns (uint256);\n}\n/**\n    @title Resupply DAO Voting\n    @author Resupply Finance (code inspired by Prisma Finance)\n    @notice Primary ownership contract for all protocol contracts. Allows executing\n            arbitrary function calls only after a required percentage of stakers\n            have signalled in favor of performing the action.\n */\ncontract Voter is CoreOwnable, DelegatedOps, EpochTracker {\n\n    uint256 public immutable TOKEN_DECIMALS;\n    uint256 public constant EXECUTION_DEADLINE = 3 weeks; // Includes votingPeriod\n    uint256 public constant MAX_PCT = 10000;\n    uint256 public constant MAX_DESCRIPTION_BYTES = 384;\n\n    IGovStaker public immutable staker;\n\n    Proposal[] public proposalData;\n    // Proposal ID -> payload\n    mapping(uint256 id => Action[] payload) public proposalPayload;\n    // Proposal ID -> description\n    mapping(uint256 id => string description) public proposalDescription;\n    // Record of user's vote: account -> ID -> vote\n    mapping(address account => mapping(uint256 id => Vote vote)) public accountVoteWeights;\n    // Record of last created proposal timestamp for a given account: account -> timestamp\n    mapping(address account => uint256 timestamp) public latestProposalTimestamp;\n    // Percent of total weight required to create a new proposal\n    uint256 public minCreateProposalPct;\n    // Percent of total weight that must vote for a proposal before it can be executed\n    uint256 public quorumPct;\n    // Cooldown period between proposals for a given account\n    uint256 public minTimeBetweenProposals = 1 days;\n    // Delay between proposal passage and its eligibility for execution\n    uint256 public executionDelay = 6 hours;\n    // Voting period for a proposal\n    uint256 public votingPeriod = 3 days;\n\n    event ProposalCreated(\n        address indexed account,\n        uint256 indexed id,\n        Action[] payload,\n        uint256 epoch,\n        uint256 quorumWeight\n    );\n    event ProposalExecuted(uint256 indexed proposalId);\n    event ProposalCancelled(uint256 indexed proposalId);\n    event ProposalDescriptionUpdated(uint256 indexed proposalId, string description);\n    event VoteCast(\n        address indexed account,\n        uint256 indexed id,\n        uint256 weightYes,\n        uint256 weightNo\n    );\n    event ProposalCreationMinPctSet(uint256 weight);\n    event QuorumPctSet(uint256 weight);\n    event MinTimeBetweenProposalsSet(uint256 cooldown);\n    event ExecutionDelaySet(uint256 delay);\n    event VotingPeriodSet(uint256 period);\n\n    struct Proposal {\n        uint16 epoch; // epoch which vote weights are based upon\n        uint32 createdAt; // timestamp when the proposal was created\n        uint40 quorumWeight; // amount of weight required for the proposal to become executable\n        bool processed; // set to true once the proposal is processed\n        Vote results; //  amount of weight currently voting on either side\n    }\n\n    struct Vote {\n        uint40 weightYes;\n        uint40 weightNo;\n    }\n\n    struct Action {\n        address target;\n        bytes data;\n    }\n\n    /**\n        @notice Constructor for Voting contract\n        @param _core Address of the core contract\n        @param _staker Address of the staker contract\n        @param _minCreateProposalPct Percent (in BPS) of total weight required to create a proposal\n        @param _quorumPct Percent (in BPS) of total weight that must vote for a proposal before it can be executed\n    */\n    constructor(\n        address _core,\n        IGovStaker _staker,\n        uint256 _minCreateProposalPct,\n        uint256 _quorumPct\n    ) CoreOwnable(_core) EpochTracker(_core) {\n        staker = _staker;\n        minCreateProposalPct = _minCreateProposalPct;\n        quorumPct = _quorumPct;\n        TOKEN_DECIMALS = IERC20(_staker.stakeToken()).decimals();\n    }\n\n    /**\n        @notice The total number of votes created\n     */\n    function getProposalCount() external view returns (uint256) {\n        return proposalData.length;\n    }\n\n    function minCreateProposalWeight() public view returns (uint256) {\n        uint256 totalWeight = staker.getTotalWeightAt(getEpoch());\n        return (totalWeight * minCreateProposalPct) / MAX_PCT;\n    }\n\n    /**\n        @notice Gets information on a specific proposal\n        @dev Fetching the description can be expensive. \n            On chain integrations should consider accessing proposalData directly.\n     */\n    function getProposalData(uint256 id) external view returns (\n        string memory description,\n        uint256 epoch,\n        uint256 createdAt,\n        uint256 quorumWeight,\n        uint256 weightYes,\n        uint256 weightNo,\n        bool processed,\n        bool executable,\n        Action[] memory payload\n    ){\n        Proposal memory proposal = proposalData[id];\n        payload = proposalPayload[id];\n        return (\n            proposalDescription[id],\n            proposal.epoch,\n            proposal.createdAt,\n            proposal.quorumWeight,\n            proposal.results.weightYes,\n            proposal.results.weightNo,\n            proposal.processed,\n            _canExecute(proposal),\n            payload\n        );\n    }\n\n    /**\n        @notice Create a new proposal\n        @param account Address of the account creating the proposal\n        @param payload Tuple of [(target address, calldata), ... ] to be\n                       executed if the proposal is passed.\n        @param description Description text for the proposal\n        @dev A proposal containing a proposal canceler action is required to be an independent single-action proposal.\n     */\n    function createNewProposal(address account, Action[] calldata payload, string calldata description) external callerOrDelegated(account) returns (uint256) {\n        require(payload.length > 0, \"Empty payload\");\n        require(\n            latestProposalTimestamp[account] + minTimeBetweenProposals < block.timestamp,\n            \"Too soon\"\n        );\n        require(bytes(description).length <= MAX_DESCRIPTION_BYTES, \"Description too long\");\n        if (_containsProposalCancelerPayload(payload)) require(payload.length == 1, \"Payload length not 1\");\n\n        // week is set at -1 to the active week so that weights are finalized\n        uint256 epoch = getEpoch();\n        require(epoch > 0, \"No proposals in first epoch\");\n\n        uint256 accountWeight = staker.getAccountWeightAt(account, epoch);\n        require(accountWeight >= minCreateProposalWeight(), \"Not enough weight to propose\");\n\n        uint256 totalWeight = staker.getTotalWeightAt(epoch) / 10 ** TOKEN_DECIMALS;\n        uint40 quorumWeight = uint40((totalWeight * quorumPct) / MAX_PCT);\n        require(quorumWeight > 0, \"Too little stake weight\");\n        uint256 proposalId = proposalData.length;\n        proposalData.push(\n            Proposal({\n                epoch: uint16(epoch),\n                createdAt: uint32(block.timestamp),\n                quorumWeight: quorumWeight,\n                processed: false,\n                results: Vote(0, 0)\n            })\n        );\n        for (uint256 i = 0; i < payload.length; i++) {\n            proposalPayload[proposalId].push(payload[i]);\n        }\n        proposalDescription[proposalId] = description;\n        latestProposalTimestamp[account] = block.timestamp;\n        emit ProposalCreated(account, proposalId, payload, epoch, quorumWeight);\n        return proposalId;\n    }\n\n    /**\n        @notice Vote fully in favor of a proposal\n        @dev Each account can vote once per proposal. Uses full weight.\n        @param account Address of the account voting\n        @param id Proposal ID\n     */\n    function voteForProposal(address account, uint256 id) external callerOrDelegated(account) {\n        _voteForProposal(account, id, MAX_PCT, 0);\n    }\n    /**\n        @notice Vote in partial favor of a proposal\n        @dev Each account can vote once per proposal. Uses full weight.\n        @param account Address of the account voting\n        @param id Proposal ID\n        @param pctYes Percent of account's total weight to vote for\n        @param pctNo Percent of account's total weight to vote against\n     */\n    function voteForProposal(address account, uint256 id, uint256 pctYes, uint256 pctNo) external callerOrDelegated(account) {\n        require(pctYes + pctNo == MAX_PCT, \"Sum of pcts must equal MAX_PCT\");\n        _voteForProposal(account, id, pctYes, pctNo);\n    }\n\n    function _voteForProposal(address account, uint256 id, uint256 pctYes, uint256 pctNo) internal {\n        require(id < proposalData.length, \"Invalid ID\");\n        Vote memory vote = accountVoteWeights[account][id];\n        require(vote.weightYes + vote.weightNo == 0, \"Already voted\");\n\n        Proposal memory proposal = proposalData[id];\n        require(!proposal.processed, \"Proposal already processed\");\n        require(proposal.createdAt + votingPeriod > block.timestamp, \"Voting period has closed\");\n\n        // Reduce the account weight by the token decimals to help storage efficiency.\n        uint256 accountWeight = staker.getAccountWeightAt(account, proposal.epoch) / 10 ** TOKEN_DECIMALS;\n        require(accountWeight > 0, \"Account weight is zero\");\n\n        vote.weightYes = uint40(accountWeight * pctYes / MAX_PCT);\n        vote.weightNo = uint40(accountWeight * pctNo / MAX_PCT);\n        accountVoteWeights[account][id] = vote;\n\n        {\n            Vote memory result = proposal.results;\n            result.weightYes += vote.weightYes;\n            result.weightNo += vote.weightNo;\n            proposal.results = result;\n        }\n        \n        proposalData[id] = proposal;\n        emit VoteCast(account, id, vote.weightYes, vote.weightNo);\n    }\n\n    /**\n        @notice Cancels a pending proposal\n        @param id Proposal ID\n        @dev Can cancel any time prior to execution\n     */\n    function cancelProposal(uint256 id) external onlyOwner {\n        require(id < proposalData.length, \"Invalid ID\");\n        require(!proposalData[id].processed, \"Proposal already processed\");\n        if (proposalPayload[id].length == 1) require(!_containsProposalCancelerPayload(proposalPayload[id]), \"Contains canceler payload\");\n        proposalData[id].processed = true;\n        emit ProposalCancelled(id);\n    }\n\n    // @dev: inspects a payload to check if any actions contain a proposal canceler\n    function _containsProposalCancelerPayload(Action[] memory payload) internal view returns (bool) {\n        uint256 payloadLength = payload.length;\n        for (uint256 i = 0; i < payloadLength; i++) {\n            Action memory action = payload[i];\n            bytes memory data = action.data;\n            bytes4 selector;\n            assembly {\n                selector := mload(add(data, 32))\n            }\n            if (action.target == address(core) && selector == ICore.setOperatorPermissions.selector) {\n                // 164 bytes is the length of a properly formed action which sets operator permissions on Core\n                if (data.length < 164) return false;\n                // Use BytesLib to slice the calldata, skipping the first 4 bytes (selector)\n                bytes memory slicedData = BytesLib.slice(data, 4, data.length - 4);\n                (, address target, bytes4 permissionSelector, , ) = abi.decode(slicedData, (address, address, bytes4, bool, address));\n                if (permissionSelector != this.cancelProposal.selector) continue;\n                if (target != address(this) && target != address(0)) continue;\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n        @notice Execute a proposal's payload\n        @dev Can only be called if the proposal has received sufficient vote weight,\n             and has been active for at least `MIN_TIME_TO_EXECUTION`\n        @param id Proposal ID\n     */\n    function executeProposal(uint256 id) external {\n        require(id < proposalData.length, \"Invalid proposalID\");\n\n        Proposal memory proposal = proposalData[id];\n        require(_canExecute(proposal), \"Proposal cannot be executed\");\n        proposalData[id].processed = true;\n\n        Action[] storage payload = proposalPayload[id];\n        uint256 payloadLength = payload.length;\n\n        for (uint256 i = 0; i < payloadLength; i++) {\n            ICore(core).execute(payload[i].target, payload[i].data);\n        }\n        emit ProposalExecuted(id);\n    }\n\n    function canExecute(uint256 id) external view returns (bool) {\n        require(id < proposalData.length, \"Invalid proposalID\");\n        return _canExecute(proposalData[id]);\n    }\n\n    function _canExecute(Proposal memory proposal) internal view returns (bool) {\n        if (proposal.processed) return false;\n        if (block.timestamp < proposal.createdAt + votingPeriod + executionDelay) return false;\n        if (block.timestamp > proposal.createdAt + EXECUTION_DEADLINE) return false;\n\n        // Ensure proposal has met quorum and received more weight in favor.\n        if (!_quorumReached(proposal.quorumWeight, proposal.results)) return false;\n        if (proposal.results.weightYes <= proposal.results.weightNo) return false;\n        \n        return true;\n    }\n\n    function quorumReached(uint256 id) external view returns (bool) {\n        require(id < proposalData.length, \"Invalid proposalID\");\n        Proposal memory proposal = proposalData[id];\n        return _quorumReached(proposal.quorumWeight, proposal.results);\n    }\n\n    function _quorumReached(uint256 quorumWeight, Vote memory results) internal pure returns (bool) {\n        return results.weightYes + results.weightNo >= quorumWeight;\n    }\n\n    /**\n        @notice Set the minimum % of the total weight required to create a new proposal\n     */\n    function setMinCreateProposalPct(uint256 pct) external onlyOwner {\n        require(pct > 0, \"Too low\");\n        require(pct <= MAX_PCT, \"Invalid value\");\n        minCreateProposalPct = pct;\n        emit ProposalCreationMinPctSet(pct);\n    }\n\n    /**\n        @notice Set the required % of the total weight that must vote\n                for a proposal in order to become executable\n     */\n    function setQuorumPct(uint256 pct) external onlyOwner {\n        require(pct > 0, \"Too low\");\n        require(pct <= MAX_PCT, \"Invalid value\");\n        quorumPct = pct;\n        emit QuorumPctSet(pct);\n    }\n\n    /**\n        @notice Set the cooldown period between proposals for a given account\n        @param _cooldown The cooldown period in seconds\n     */\n    function setMinTimeBetweenProposals(uint256 _cooldown) external onlyOwner {\n        minTimeBetweenProposals = _cooldown;\n        emit MinTimeBetweenProposalsSet(_cooldown);\n    }\n\n    /**\n        @notice Set the delay between proposal passage and its eligibility for execution\n        @param _delay The delay in seconds\n     */\n    function setExecutionDelay(uint256 _delay) external onlyOwner {\n        require(_delay > 1 hours, \"Too low\");\n        require(_delay <= 2 days, \"Too high\");\n        executionDelay = _delay;\n        emit ExecutionDelaySet(_delay);\n    }\n\n    /**\n        @notice Set the voting period for a proposal\n        @param _period The voting period in seconds\n     */\n    function setVotingPeriod(uint256 _period) external onlyOwner {\n        require(_period > 1 days, \"Too low\");\n        require(_period <= 1 weeks, \"Too high\");\n        votingPeriod = _period;\n        emit VotingPeriodSet(_period);\n    }\n\n    /**\n        @notice Overwrite the description text for an existing proposal\n        @param id The ID of the proposal to update\n        @param description New description text for the proposal\n     */\n    function updateProposalDescription(uint256 id, string calldata description) external onlyOwner {\n        require(id < proposalData.length, \"Invalid ID\");\n        require(bytes(description).length <= MAX_DESCRIPTION_BYTES, \"Description too long\");\n        proposalDescription[id] = description;\n        emit ProposalDescriptionUpdated(id, description);\n    }\n}","deployed_bytecode":"0x60806040526004361015610011575f80fd5b5f3560e01c806302a251a31461026f5780630d61b5191461026a5780631930e825146102655780631a1216bb146102605780633830fdea1461025b578063398d2ce9146102565780634e3c118e1461025157806357d775f81461024c5780635b7f415c146102475780635ebaf1db146102425780636318f9e51461023d5780636e76853014610238578063757991a814610233578063759218841461022e57806378e979251461022957806382f79c29146102245780638b2579891461021f5780638c76068c1461021a5780638da5cb5b146101c55780638e7920501461021557806396dea93614610210578063a545074c1461020b578063ac4cbe7614610206578063adc36e3014610201578063b3800197146101fc578063c08cc02d146101f7578063c3c854b6146101f2578063c81ea2a0146101ed578063c91b040f146101e8578063cc63604a146101e3578063d4a8dd98146101de578063e0a8f6f5146101d9578063e2d55ed1146101d4578063e4917d9f146101cf578063ea0217cf146101ca578063f2f4eb26146101c5578063fa8f911f146101c05763fb696d6f146101bb575f80fd5b611958565b6118c7565b61107a565b611832565b61179e565b6116cf565b61157c565b611539565b6114fe565b611486565b61146a565b6113d8565b6113b1565b611395565b611378565b61135b565b6112ef565b6111c5565b6110be565b610fe9565b610fcc565b610faf565b610f75565b610f58565b610f36565b610de6565b610cef565b610cab565b610c71565b610c37565b610884565b6106d7565b610699565b610490565b610400565b610290565b3461028c575f36600319011261028c576020600a54604051908152f35b5f80fd5b3461028c57602036600319011261028c576004356102b16001548210611972565b6102d36102ce6102c96102c38461112b565b506119b3565b61288c565b611a19565b6102f36102df8261112b565b50805460ff60581b1916600160581b179055565b610305815f52600260205260405f2090565b8054907f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b03165f5b83811061036257847f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f5f80a2005b61037d61036f8285611168565b50546001600160a01b031690565b905f600161038b8387611168565b506103ac6040519586938493631cff79cd60e01b8552019060048401611ae2565b038183875af19182156103ea576001926103c8575b5001610334565b6103e3903d805f833e6103db81836105b4565b810190611a80565b505f6103c1565b611b04565b6001600160a01b0381160361028c57565b3461028c57604036600319011261028c57602060ff610457600435610424816103ef565b60243590610431826103ef565b60018060a01b03165f525f845260405f209060018060a01b03165f5260205260405f2090565b54166040519015158152f35b9181601f8401121561028c578235916001600160401b03831161028c576020838186019501011161028c57565b3461028c57606036600319011261028c576004356104ad816103ef565b602435906001600160401b03821161028c573660238301121561028c578160040135916001600160401b03831161028c573660248460051b8301011161028c57604435906001600160401b03821161028c5761053193610521936105176024943690600401610463565b9490930190611b50565b6040519081529081906020820190565b0390f35b634e487b7160e01b5f525f60045260245ffd5b90600182811c92168015610576575b602083101461056257565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610557565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b038211176105af57604052565b610580565b90601f801991011681019081106001600160401b038211176105af57604052565b9060405191825f8254926105e884610548565b8084529360018116908115610653575060011461060f575b5061060d925003836105b4565b565b90505f9291925260205f20905f915b81831061063757505090602061060d928201015f610600565b602091935080600191548385890101520191019091849261061e565b90506020925061060d94915060ff191682840152151560051b8201015f610600565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b3461028c57602036600319011261028c576004355f5260036020526105316106c360405f206105d5565b604051918291602083526020830190610675565b3461028c57604036600319011261028c576004356024356001600160401b03811161028c5761070a903690600401610463565b909190610741337f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b0316146125d7565b61074e600154831061260b565b61075c610180821115611ed7565b815f52600360205260405f20926001600160401b0382116105af5761078b826107858654610548565b8661228d565b5f93601f83116001146107fc576107da83807ffa84733cb3fd0fea0368cf9d3f2196bed5d619ee68b00423f0d70758cb9f70f896975f916107f1575b508160011b915f199060031b1c19161790565b90555b6107ec60405192839283612644565b0390a2005b90508401355f6107c7565b601f1983169461080f825f5260205f2090565b905f5b87811061086c5750847ffa84733cb3fd0fea0368cf9d3f2196bed5d619ee68b00423f0d70758cb9f70f8969710610853575b5050600183811b0190556107dd565b8301355f19600386901b60f8161c191690555f80610844565b90916020600181928588013581550193019101610812565b3461028c57604036600319011261028c576004356108a1816103ef565b602435906001600160a01b038116903382148015610c17575b6108c390611b0f565b6108d0600154841061260b565b6109036108fe846108f18460018060a01b03165f52600460205260405f2090565b905f5260205260405f2090565b61119f565b90610913825164ffffffffff1690565b9061094164ffffffffff61093a6020860194610934865164ffffffffff1690565b90612af0565b1615612b0c565b6109da6109506102c38761112b565b9361096d6109686109646060880151151590565b1590565b61272b565b61099a610993610984602088015163ffffffff1690565b63ffffffff600a549116611e93565b4210612b48565b60206109a8865161ffff1690565b60405162ff274760e31b81526001600160a01b038616600482015261ffff909116602482015292839081906044820190565b03817f00000000000000000000000022222222e9fe38f6f1fc8c61b25228adb4d8b9536001600160a01b03165afa9283156103ea577fa23fc440c6fc2e19ce408adc0b47622097fa7ea64409d71d33ba3fcdb5b4cd9595610b3883610af78b6108f1610bb696610ade610ad3610ab9610ab15f610bcd9f610bc19f90610a91918391610be8575b50610a8b7f00000000000000000000000000000000000000000000000000000000000000126120fd565b9061210b565b610a9c811515612b94565b610ace610ac3610ab9610ab161271085612129565b612710900490565b64ffffffffff1690565b64ffffffffff168c52565b612129565b64ffffffffff168d52565b6001600160a01b03165f90815260046020526040902090565b9064ffffffffff81511669ffffffffff000000000060208454938364ffffffffff198616178655015160281b169169ffffffffffffffffffff191617179055565b60808101805190610b72610b67610b54875164ffffffffff1690565b845164ffffffffff16612af0565b612af0565b64ffffffffff168352565b610ba6610b84895164ffffffffff1690565b610b9b6020850191610b62835164ffffffffff1690565b64ffffffffff169052565b52610bb08961112b565b90612188565b5164ffffffffff1690565b915164ffffffffff1690565b6040805164ffffffffff9384168152919092166020820152a3005b610c0a915060203d602011610c10575b610c0281836105b4565b8101906120a2565b5f610a61565b503d610bf8565b505f8281526020818152604080832033845290915290205460ff166108ba565b3461028c575f36600319011261028c5760206040517f0000000000000000000000000000000000000000000000000000000000093a808152f35b3461028c575f36600319011261028c5760206040517f00000000000000000000000000000000000000000000000000000000000000128152f35b3461028c575f36600319011261028c576040517f00000000000000000000000022222222e9fe38f6f1fc8c61b25228adb4d8b9536001600160a01b03168152602090f35b3461028c57602036600319011261028c57600435610d0c816103ef565b60018060a01b03165f526005602052602060405f2054604051908152f35b96949290610d479098969492986101208952610120890190610675565b97602088015260408701526060860152608085015260a0840152151560c0830152151560e0820152610100818303910152815180825260208201916020808360051b8301019401925f915b838310610da157505050505090565b9091929394602080610dd7600193601f198682030187526040838b51878060a01b03815116845201519181858201520190610675565b97019301930191939290610d92565b3461028c57602036600319011261028c57600435610e066102c38261112b565b815f52600260205260405f20918254610e1e81611f1a565b93610e2c60405195866105b4565b81855260208501905f5260205f205f915b838310610eec5764ffffffffff8661053189610e61895f52600360205260405f2090565b835161ffff1693610e79602082015163ffffffff1690565b604082015164ffffffffff16608083015191610eac6020610e9f855164ffffffffff1690565b94015164ffffffffff1690565b97610ecc610ec6610ec06060880151151590565b9661288c565b966105d5565b61ffff63ffffffff8c806040519e8f9e169816961694169216908a610d2a565b60026020600192604051610eff81610594565b848060a01b038654168152604051610f2481610f1d81898b01611249565b03826105b4565b83820152815201920192019190610e3d565b3461028c575f36600319011261028c576020610f50612664565b604051908152f35b3461028c575f36600319011261028c576020600754604051908152f35b3461028c575f36600319011261028c5760206040517f0000000000000000000000000000000000000000000000000000000067d220008152f35b3461028c575f36600319011261028c576020604051621baf808152f35b3461028c575f36600319011261028c576020600954604051908152f35b3461028c57602036600319011261028c577f8d1f94446a5b32ed366552dc6d865de8d56664c78fc568bad9d451ba3dceede46020600435611054337f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b0316146125d7565b61105f8115156126b9565b61106d6127108211156126ef565b80600655604051908152a1005b3461028c575f36600319011261028c576040517f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b03168152602090f35b3461028c57604036600319011261028c576004356110db816103ef565b6024359060018060a01b03165f52600460205260405f20905f526020526040805f205464ffffffffff825191818116835260281c166020820152f35b634e487b7160e01b5f52603260045260245ffd5b6001548110156111635760015f81815291901b7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60191565b611117565b8054821015611163575f5260205f209060011b01905f90565b6040519061060d6040836105b4565b6040519061060d60a0836105b4565b906040516111ac81610594565b602064ffffffffff829454818116845260281c16910152565b3461028c57602036600319011261028c5760043560015481101561028c576111ee60c09161112b565b5064ffffffffff602061120560018454940161119f565b60ff6040519461ffff8116865263ffffffff8160101c1684870152848160301c16604087015260581c161515606085015282815116608085015201511660a0820152f35b5f929181549161125883610548565b80835292600181169081156112ad575060011461127457505050565b5f9081526020812093945091925b838310611293575060209250010190565b600181602092949394548385870101520191019190611282565b915050602093945060ff929192191683830152151560051b010190565b6001600160a01b0390911681526040602082018190526112ec92910190610675565b90565b3461028c57604036600319011261028c57600435602435905f52600260205260405f20805482101561028c5760019161132791611168565b5061134c828060a01b03825416916113456040518095819301611249565b03836105b4565b610531604051928392836112ca565b3461028c575f36600319011261028c576020600654604051908152f35b3461028c575f36600319011261028c576020600854604051908152f35b3461028c575f36600319011261028c5760206040516127108152f35b3461028c575f36600319011261028c576020600154604051908152f35b8015150361028c57565b3461028c57604036600319011261028c576004356113f5816103ef565b60243590611402826113ce565b335f908152602081815260408083206001600160a01b038516845290915290209115159160ff1981541660ff841617905560405191825260018060a01b0316907f92d241afb0a1a9b3441bf1bd6bea0f9164cf5a2562cbe4bcc34ab943b246560860203392a3005b3461028c575f36600319011261028c5760206040516101808152f35b3461028c57602036600319011261028c577f2d14d804d16da57b1af6557207d7e5ff9230245312c2b667d5f54105327882c860206004356114f1337f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b0316146125d7565b80600855604051908152a1005b3461028c57602036600319011261028c57602061152f6102c96102c360043561152a6001548210611972565b61112b565b6040519015158152f35b3461028c57602036600319011261028c57602061152f6115656102c360043561152a6001548210611972565b608064ffffffffff60408301511691015190612e0f565b3461028c57602036600319011261028c576004356115c4337f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b0316146125d7565b6115d1600154821061260b565b6115eb60ff6115df8361112b565b505460581c161561272b565b805f526002602052600160405f205414611632575b61160c6102df8261112b565b7f416e669c63d9a3a5e36ee7cc7e2104b8db28ccd286aa18966e98fa230c73b08c5f80a2005b805f52600260205260405f20805461164981611f1a565b9161165760405193846105b4565b81835260208301905f5260205f205f915b83831061168c5750505050611682610964611687926129b4565b612777565b611600565b6002602060019260405161169f81610594565b848060a01b0386541681526040516116bd81610f1d81898b01611249565b83820152815201920192019190611668565b3461028c57608036600319011261028c576004356116ec816103ef565b6064356044356024356001600160a01b038416338114801561177a575b6117139150611b0f565b82820180831161177557612710036117305761172e93612bd9565b005b60405162461bcd60e51b815260206004820152601e60248201527f53756d206f662070637473206d75737420657175616c204d41585f50435400006044820152606490fd5b611e61565b505f908152602081815260408083203384529091529020546117139060ff16611709565b3461028c57602036600319011261028c577f7bd1929729a7db8dd565b881e0af3454665129221283a27837617df5feeff15a6020600435611809337f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b0316146125d7565b611816610e1082116126b9565b6118256202a3008211156127c3565b80600955604051908152a1005b3461028c57602036600319011261028c577fc7f7e966c446ca07890210c0a7c9571d1d6f042fb01f27e51a921b2c3285de58602060043561189d337f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b0316146125d7565b6118ab6201518082116126b9565b6118ba62093a808211156127c3565b80600a55604051908152a1005b3461028c57602036600319011261028c577fb94f7013434491d516c84c42d5de99b02ed06906f05db29edc1d6850e944fae06020600435611932337f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b0316146125d7565b61193d8115156126b9565b61194b6127108211156126ef565b80600755604051908152a1005b3461028c575f36600319011261028c576020610f506127fa565b1561197957565b60405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a59081c1c9bdc1bdcd85b125160721b6044820152606490fd5b9060405160a081018181106001600160401b038211176105af576040526080611a146001839560ff815461ffff8116875263ffffffff8160101c16602088015264ffffffffff8160301c16604088015260581c16151560608601520161119f565b910152565b15611a2057565b60405162461bcd60e51b815260206004820152601b60248201527f50726f706f73616c2063616e6e6f7420626520657865637574656400000000006044820152606490fd5b6001600160401b0381116105af57601f01601f191660200190565b60208183031261028c578051906001600160401b03821161028c570181601f8201121561028c57805190611ab382611a65565b92611ac160405194856105b4565b8284526020838301011161028c57815f9260208093018386015e8301015290565b6001600160a01b0390911681526040602082018190526112ec92910190611249565b6040513d5f823e3d90fd5b15611b1657565b60405162461bcd60e51b81526020600482015260126024820152710850d85b1b195c93dc91195b1959d85d195960721b6044820152606490fd5b9194936001600160a01b038316923384148015611e05575b611b7190611b0f565b611b7c871515611e25565b6001600160a01b0381165f908152600560205260409020611bac90611ba5905460085490611e93565b4211611ea0565b611bba610180831115611ed7565b611bcd611bc8368986611f31565b6129b4565b611df4575b611bda612664565b90611be6821515612056565b60405162ff274760e31b81526001600160a01b038281166004830152602482018490527f00000000000000000000000022222222e9fe38f6f1fc8c61b25228adb4d8b9531690602081604481855afa80156103ea57611c56915f91611dd5575b50611c4f6127fa565b11156120b1565b6040516350735f6f60e01b81526004810184905290602090829060249082905afa9081156103ea57610ab1611cbc611cc593610ab9935f91610be85750610a8b7f00000000000000000000000000000000000000000000000000000000000000126120fd565b60075490612129565b92611cd864ffffffffff8516151561213c565b60015496611d29611ce7611181565b5f81525f6020820152611cf8611190565b61ffff87168152904263ffffffff16602083015264ffffffffff881660408301525f60608301526080820152612246565b5f5b8a8110611da5575092611d9f92611d7a899a9b96937f48dd3eb1da9035a25fb1644e9b5f3e5a39a6888d5cd415bad5467791c77149ed9896611d758c5f52600360205260405f2090565b61241e565b6001600160a01b03165f908152600560205260409020429055604051948594856124fa565b0390a390565b80611dcf8c611dc9600194611dc28e5f52600260205260405f2090565b928c61226b565b906122dc565b01611d2b565b611dee915060203d602011610c1057610c0281836105b4565b5f611c46565b611e0060018814612013565b611bd2565b505f8481526020818152604080832033845290915290205460ff16611b68565b15611e2c57565b60405162461bcd60e51b815260206004820152600d60248201526c115b5c1d1e481c185e5b1bd859609a1b6044820152606490fd5b634e487b7160e01b5f52601160045260245ffd5b90621baf80820180921161177557565b90601f820180921161177557565b9190820180921161177557565b15611ea757565b60405162461bcd60e51b81526020600482015260086024820152672a37b79039b7b7b760c11b6044820152606490fd5b15611ede57565b60405162461bcd60e51b81526020600482015260146024820152734465736372697074696f6e20746f6f206c6f6e6760601b6044820152606490fd5b6001600160401b0381116105af5760051b60200190565b92919092611f3e84611f1a565b93611f4c60405195866105b4565b602085828152019060051b82019183831161028c5780915b838310611f72575050505050565b82356001600160401b03811161028c5782019060408287031261028c5760405191611f9c83610594565b8035611fa7816103ef565b83526020810135906001600160401b03821161028c57019086601f8301121561028c57813592611fd684611a65565b611fe360405191826105b4565b848152886020868601011161028c575f602086819782809801838601378301015283820152815201920191611f64565b1561201a57565b60405162461bcd60e51b81526020600482015260146024820152735061796c6f6164206c656e677468206e6f74203160601b6044820152606490fd5b1561205d57565b60405162461bcd60e51b815260206004820152601b60248201527f4e6f2070726f706f73616c7320696e2066697273742065706f636800000000006044820152606490fd5b9081602091031261028c575190565b156120b857565b60405162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f7567682077656967687420746f2070726f706f7365000000006044820152606490fd5b604d811161177557600a0a90565b8115612115570490565b634e487b7160e01b5f52601260045260245ffd5b8181029291811591840414171561177557565b1561214357565b60405162461bcd60e51b815260206004820152601760248201527f546f6f206c6974746c65207374616b65207765696768740000000000000000006044820152606490fd5b90612241578151815460208401516040850151606086015160309190911b6affffffffff0000000000001660109290921b65ffffffff00001661ffff9094166bffffffffffffffffffffffff1990931692909217929092179190911790151560581b60ff60581b1617815561060d916001906080015191019064ffffffffff81511669ffffffffff000000000060208454938364ffffffffff198616178655015160281b169169ffffffffffffffffffff191617179055565b610535565b60015490600160401b8210156105af57610bb082600161060d94016001556001611168565b91908110156111635760051b81013590603e198136030182121561028c570190565b601f821161229a57505050565b5f5260205f20906020601f840160051c830193106122d2575b601f0160051c01905b8181106122c7575050565b5f81556001016122bc565b90915081906122b3565b9190918054600160401b8110156105af576122fc91600182018155611168565b61224157600190833561230e816103ef565b828060a01b03166bffffffffffffffffffffffff60a01b8254161781550191602081013590601e198136030182121561028c57019182356001600160401b03811161028c57803603602085011361028c576123738161236d8454610548565b8461228d565b5f601f82116001146123b45781906123a29394955f926123a6575b50508160011b915f199060031b1c19161790565b9055565b602092500101355f8061238e565b601f198216946123c7845f5260205f2090565b915f5b8781106124045750836001959697106123e8575b505050811b019055565b01602001355f19600384901b60f8161c191690555f80806123de565b9092602060018192828787010135815501940191016123ca565b9092916001600160401b0381116105af5761243d8161236d8454610548565b5f601f82116001146124765781906123a29394955f9261246b5750508160011b915f199060031b1c19161790565b013590505f8061238e565b601f19821694612489845f5260205f2090565b915f5b8781106124c25750836001959697106124a957505050811b019055565b01355f19600384901b60f8161c191690555f80806123de565b9092602060018192868601358155019401910161248c565b908060209392818452848401375f828201840152601f01601f1916010190565b91909493929481606084016060855252608083019160808160051b85010192825f90603e19813603015b84831061254c5750505050505061060d9291604091956020820152019064ffffffffff169052565b909192939495607f1988820301855286358281121561028c5783018035612572816103ef565b6001600160a01b03168252602081013536829003601e190181121561028c5701602081359101906001600160401b03811161028c57803603821361028c576125c960209283926040868186600199015201916124da565b980196950193019190612524565b156125de57565b60405162461bcd60e51b815260206004820152600560248201526421636f726560d81b6044820152606490fd5b1561261257565b60405162461bcd60e51b815260206004820152600a602482015269125b9d985b1a5908125160b21b6044820152606490fd5b9160206112ec9381815201916124da565b60031981019190821161177557565b7f0000000000000000000000000000000000000000000000000000000067d220004203428111611775576112ec907f0000000000000000000000000000000000000000000000000000000000093a809061210b565b156126c057565b60405162461bcd60e51b8152602060048201526007602482015266546f6f206c6f7760c81b6044820152606490fd5b156126f657565b60405162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b6044820152606490fd5b1561273257565b60405162461bcd60e51b815260206004820152601a60248201527f50726f706f73616c20616c72656164792070726f6365737365640000000000006044820152606490fd5b1561277e57565b60405162461bcd60e51b815260206004820152601960248201527f436f6e7461696e732063616e63656c6572207061796c6f6164000000000000006044820152606490fd5b156127ca57565b60405162461bcd60e51b81526020600482015260086024820152670a8dede40d0d2ced60c31b6044820152606490fd5b612802612664565b6040516350735f6f60e01b815260048101919091526020816024817f00000000000000000000000022222222e9fe38f6f1fc8c61b25228adb4d8b9536001600160a01b03165afa9081156103ea5761271091612869915f9161286d575b5060065490612129565b0490565b612886915060203d602011610c1057610c0281836105b4565b5f61285f565b606081015161293d57602081016128b66128ad610984835163ffffffff1690565b60095490611e93565b42106129425763ffffffff6128d26128d8925163ffffffff1690565b16611e75565b421161293d5761290a61096460806128f8604085015164ffffffffff1690565b93019264ffffffffff84519116612e0f565b61293d575164ffffffffff61292c610ab96020610e9f855164ffffffffff1690565b9116111561293957600190565b5f90565b505f90565b50505f90565b80518210156111635760209160051b010190565b908160a091031261028c578051612972816103ef565b916020820151612981816103ef565b91604081015163ffffffff60e01b8116810361028c5791608060608301516129a8816113ce565b9201516112ec816103ef565b8051907f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b0316905f5b8381106129f357505050505f90565b6129fd8183612948565b5160208101519084612a29612a1d6020850151935160018060a01b031690565b6001600160a01b031690565b149081612ad5575b50612a4157506001905b016129e4565b805160a48110612acb57612a7091612a5b612a6192612655565b90612eae565b6020808251830101910161295c565b50506001600160a01b039190911691506001600160e01b031916631f57090b60e01b01612ac257308114159081612ab8575b50612ab05750505050600190565b600190612a3b565b905015155f612aa2565b50600190612a3b565b5050505050505f90565b6001600160e01b031916632fe0a06160e11b1490505f612a31565b9064ffffffffff8091169116019064ffffffffff821161177557565b15612b1357565b60405162461bcd60e51b815260206004820152600d60248201526c105b1c9958591e481d9bdd1959609a1b6044820152606490fd5b15612b4f57565b60405162461bcd60e51b815260206004820152601860248201527f566f74696e6720706572696f642068617320636c6f73656400000000000000006044820152606490fd5b15612b9b57565b60405162461bcd60e51b81526020600482015260166024820152754163636f756e7420776569676874206973207a65726f60501b6044820152606490fd5b929092612be9600154851061260b565b612c0a6108fe856108f18460018060a01b03165f52600460205260405f2090565b92612cb4612c1d855164ffffffffff1690565b94612c3e64ffffffffff61093a60208401986109348a5164ffffffffff1690565b612c4a6102c38861112b565b612c5d6109686109646060840151151590565b612c74610993610984602084015163ffffffff1690565b6020612c82825161ffff1690565b60405162ff274760e31b81526001600160a01b038816600482015261ffff909116602482015293849081906044820190565b03817f00000000000000000000000022222222e9fe38f6f1fc8c61b25228adb4d8b9536001600160a01b03165afa9081156103ea57612d8a612d7f610ab9610ab17fa23fc440c6fc2e19ce408adc0b47622097fa7ea64409d71d33ba3fcdb5b4cd959a612de699610ace612d74610ab9610ab1612d62610bb69c612dda9f5f91610be85750610a8b7f00000000000000000000000000000000000000000000000000000000000000126120fd565b94612d6e861515612b94565b85612129565b64ffffffffff168a52565b64ffffffffff168952565b612dac83610af78b6108f18a60018060a01b03165f52600460205260405f2090565b60808101805190612dc8610b67610b54875164ffffffffff1690565b610ba6610b848b5164ffffffffff1690565b935164ffffffffff1690565b6040805164ffffffffff95861681529190941660208201526001600160a01b03919091169290a3565b90612e2b64ffffffffff91826020818351169201511690612af0565b16101590565b15612e3857565b60405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606490fd5b15612e7557565b60405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606490fd5b612ec282612ebb81611e85565b1015612e31565b612ed98151612ed2846004611e93565b1115612e6e565b81612ef05750506040515f81526020810160405290565b60405191601f8116916004831560051b80858701019484860193010101905b808410612f275750508252601f01601f191660405290565b9092602080918551815201930190612f0f56fea164736f6c634300081c000a","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"none"},"optimizer":{"enabled":true,"runs":200},"remappings":[":@axelar-network/=node_modules/@axelar-network/",":@chainlink/=node_modules/@chainlink/",":@eth-optimism/=node_modules/@eth-optimism/",":@layerzerolabs/=node_modules/@layerzerolabs/",":@mean-finance/=node_modules/@mean-finance/",":@openzeppelin/=node_modules/@openzeppelin/",":@rari-capital/=node_modules/@rari-capital/",":@uniswap/=node_modules/@uniswap/",":base64-sol/=node_modules/base64-sol/",":ds-test/=node_modules/ds-test/src/",":forge-std/=node_modules/forge-std/src/",":frax-standard-solidity/=node_modules/frax-standard-solidity/",":frax-std/=node_modules/frax-standard-solidity/src/",":hardhat-deploy/=node_modules/hardhat-deploy/",":hardhat/=node_modules/hardhat/",":solidity-bytes-utils/=node_modules/solidity-bytes-utils/",":solidity-stringutils/=lib/surl/lib/solidity-stringutils/",":surl/=lib/surl/"],"viaIR":true},"optimization_runs":200,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/partial_match/1/0x11111111063874cE8dC6232cb5C1C849359476E6/","decoded_constructor_args":[["0xc07e000044F95655c11fda4cD37F70A94d7e0a7d",{"internalType":"address","name":"_core","type":"address"}],["0x22222222E9fE38F6f1FC8C61b25228adB4D8B953",{"internalType":"contract IGovStaker","name":"_staker","type":"address"}],["100",{"internalType":"uint256","name":"_minCreateProposalPct","type":"uint256"}],["3000",{"internalType":"uint256","name":"_quorumPct","type":"uint256"}]],"compiler_version":"0.8.28+commit.7893614a","is_verified_via_verifier_alliance":false,"verified_at":"2026-02-06T15:42:51.477216Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x610120806040523461021f57608081613276803803809161002082856102e3565b83398101031261021f576100338161031a565b6020820151916001600160a01b038316919082840361021f57604081810151606092909201516001600160a01b03909316608081905290516378e9792560e01b8152602081600481855afa90811561022b575f916102b0575b5060a052604051630afaeebf60e31b815290602090829060049082905afa90811561022b575f91610275575b5090600494602094939260c052620151806008556154606009556203f480600a55610100526006556007556040519283809263051ed6a360e41b82525afa90811561022b575f91610236575b5060405163313ce56760e01b815290602090829060049082906001600160a01b03165afa90811561022b575f916101f5575b5060e052604051612f47908161032f823960805181818161030a01528181610713015281816110260152818161108f015281816114c301528181611596015281816117db0152818161186f0152818161190401526129b9015260a051818181610f8c0152612666015260c051818181610c4e0152612694015260e051818181610a6701528181610c8801528181611c980152612d3e0152610100518181816109de01528181610cc001528181611c0b0152818161281f0152612cb80152f35b90506020813d602011610223575b81610210602093836102e3565b8101031261021f57515f610136565b5f80fd5b3d9150610203565b6040513d5f823e3d90fd5b90506020813d60201161026d575b81610251602093836102e3565b8101031261021f57602061026660049261031a565b9150610104565b3d9150610244565b93929190506020843d6020116102a8575b81610293602093836102e3565b8101031261021f5792519192909160046100b8565b3d9150610286565b90506020813d6020116102db575b816102cb602093836102e3565b8101031261021f5751600461008c565b3d91506102be565b601f909101601f19168101906001600160401b0382119082101761030657604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361021f5756fe60806040526004361015610011575f80fd5b5f3560e01c806302a251a31461026f5780630d61b5191461026a5780631930e825146102655780631a1216bb146102605780633830fdea1461025b578063398d2ce9146102565780634e3c118e1461025157806357d775f81461024c5780635b7f415c146102475780635ebaf1db146102425780636318f9e51461023d5780636e76853014610238578063757991a814610233578063759218841461022e57806378e979251461022957806382f79c29146102245780638b2579891461021f5780638c76068c1461021a5780638da5cb5b146101c55780638e7920501461021557806396dea93614610210578063a545074c1461020b578063ac4cbe7614610206578063adc36e3014610201578063b3800197146101fc578063c08cc02d146101f7578063c3c854b6146101f2578063c81ea2a0146101ed578063c91b040f146101e8578063cc63604a146101e3578063d4a8dd98146101de578063e0a8f6f5146101d9578063e2d55ed1146101d4578063e4917d9f146101cf578063ea0217cf146101ca578063f2f4eb26146101c5578063fa8f911f146101c05763fb696d6f146101bb575f80fd5b611958565b6118c7565b61107a565b611832565b61179e565b6116cf565b61157c565b611539565b6114fe565b611486565b61146a565b6113d8565b6113b1565b611395565b611378565b61135b565b6112ef565b6111c5565b6110be565b610fe9565b610fcc565b610faf565b610f75565b610f58565b610f36565b610de6565b610cef565b610cab565b610c71565b610c37565b610884565b6106d7565b610699565b610490565b610400565b610290565b3461028c575f36600319011261028c576020600a54604051908152f35b5f80fd5b3461028c57602036600319011261028c576004356102b16001548210611972565b6102d36102ce6102c96102c38461112b565b506119b3565b61288c565b611a19565b6102f36102df8261112b565b50805460ff60581b1916600160581b179055565b610305815f52600260205260405f2090565b8054907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165f5b83811061036257847f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f5f80a2005b61037d61036f8285611168565b50546001600160a01b031690565b905f600161038b8387611168565b506103ac6040519586938493631cff79cd60e01b8552019060048401611ae2565b038183875af19182156103ea576001926103c8575b5001610334565b6103e3903d805f833e6103db81836105b4565b810190611a80565b505f6103c1565b611b04565b6001600160a01b0381160361028c57565b3461028c57604036600319011261028c57602060ff610457600435610424816103ef565b60243590610431826103ef565b60018060a01b03165f525f845260405f209060018060a01b03165f5260205260405f2090565b54166040519015158152f35b9181601f8401121561028c578235916001600160401b03831161028c576020838186019501011161028c57565b3461028c57606036600319011261028c576004356104ad816103ef565b602435906001600160401b03821161028c573660238301121561028c578160040135916001600160401b03831161028c573660248460051b8301011161028c57604435906001600160401b03821161028c5761053193610521936105176024943690600401610463565b9490930190611b50565b6040519081529081906020820190565b0390f35b634e487b7160e01b5f525f60045260245ffd5b90600182811c92168015610576575b602083101461056257565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610557565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b038211176105af57604052565b610580565b90601f801991011681019081106001600160401b038211176105af57604052565b9060405191825f8254926105e884610548565b8084529360018116908115610653575060011461060f575b5061060d925003836105b4565b565b90505f9291925260205f20905f915b81831061063757505090602061060d928201015f610600565b602091935080600191548385890101520191019091849261061e565b90506020925061060d94915060ff191682840152151560051b8201015f610600565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b3461028c57602036600319011261028c576004355f5260036020526105316106c360405f206105d5565b604051918291602083526020830190610675565b3461028c57604036600319011261028c576004356024356001600160401b03811161028c5761070a903690600401610463565b909190610741337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146125d7565b61074e600154831061260b565b61075c610180821115611ed7565b815f52600360205260405f20926001600160401b0382116105af5761078b826107858654610548565b8661228d565b5f93601f83116001146107fc576107da83807ffa84733cb3fd0fea0368cf9d3f2196bed5d619ee68b00423f0d70758cb9f70f896975f916107f1575b508160011b915f199060031b1c19161790565b90555b6107ec60405192839283612644565b0390a2005b90508401355f6107c7565b601f1983169461080f825f5260205f2090565b905f5b87811061086c5750847ffa84733cb3fd0fea0368cf9d3f2196bed5d619ee68b00423f0d70758cb9f70f8969710610853575b5050600183811b0190556107dd565b8301355f19600386901b60f8161c191690555f80610844565b90916020600181928588013581550193019101610812565b3461028c57604036600319011261028c576004356108a1816103ef565b602435906001600160a01b038116903382148015610c17575b6108c390611b0f565b6108d0600154841061260b565b6109036108fe846108f18460018060a01b03165f52600460205260405f2090565b905f5260205260405f2090565b61119f565b90610913825164ffffffffff1690565b9061094164ffffffffff61093a6020860194610934865164ffffffffff1690565b90612af0565b1615612b0c565b6109da6109506102c38761112b565b9361096d6109686109646060880151151590565b1590565b61272b565b61099a610993610984602088015163ffffffff1690565b63ffffffff600a549116611e93565b4210612b48565b60206109a8865161ffff1690565b60405162ff274760e31b81526001600160a01b038616600482015261ffff909116602482015292839081906044820190565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9283156103ea577fa23fc440c6fc2e19ce408adc0b47622097fa7ea64409d71d33ba3fcdb5b4cd9595610b3883610af78b6108f1610bb696610ade610ad3610ab9610ab15f610bcd9f610bc19f90610a91918391610be8575b50610a8b7f00000000000000000000000000000000000000000000000000000000000000006120fd565b9061210b565b610a9c811515612b94565b610ace610ac3610ab9610ab161271085612129565b612710900490565b64ffffffffff1690565b64ffffffffff168c52565b612129565b64ffffffffff168d52565b6001600160a01b03165f90815260046020526040902090565b9064ffffffffff81511669ffffffffff000000000060208454938364ffffffffff198616178655015160281b169169ffffffffffffffffffff191617179055565b60808101805190610b72610b67610b54875164ffffffffff1690565b845164ffffffffff16612af0565b612af0565b64ffffffffff168352565b610ba6610b84895164ffffffffff1690565b610b9b6020850191610b62835164ffffffffff1690565b64ffffffffff169052565b52610bb08961112b565b90612188565b5164ffffffffff1690565b915164ffffffffff1690565b6040805164ffffffffff9384168152919092166020820152a3005b610c0a915060203d602011610c10575b610c0281836105b4565b8101906120a2565b5f610a61565b503d610bf8565b505f8281526020818152604080832033845290915290205460ff166108ba565b3461028c575f36600319011261028c5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b3461028c575f36600319011261028c5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b3461028c575f36600319011261028c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461028c57602036600319011261028c57600435610d0c816103ef565b60018060a01b03165f526005602052602060405f2054604051908152f35b96949290610d479098969492986101208952610120890190610675565b97602088015260408701526060860152608085015260a0840152151560c0830152151560e0820152610100818303910152815180825260208201916020808360051b8301019401925f915b838310610da157505050505090565b9091929394602080610dd7600193601f198682030187526040838b51878060a01b03815116845201519181858201520190610675565b97019301930191939290610d92565b3461028c57602036600319011261028c57600435610e066102c38261112b565b815f52600260205260405f20918254610e1e81611f1a565b93610e2c60405195866105b4565b81855260208501905f5260205f205f915b838310610eec5764ffffffffff8661053189610e61895f52600360205260405f2090565b835161ffff1693610e79602082015163ffffffff1690565b604082015164ffffffffff16608083015191610eac6020610e9f855164ffffffffff1690565b94015164ffffffffff1690565b97610ecc610ec6610ec06060880151151590565b9661288c565b966105d5565b61ffff63ffffffff8c806040519e8f9e169816961694169216908a610d2a565b60026020600192604051610eff81610594565b848060a01b038654168152604051610f2481610f1d81898b01611249565b03826105b4565b83820152815201920192019190610e3d565b3461028c575f36600319011261028c576020610f50612664565b604051908152f35b3461028c575f36600319011261028c576020600754604051908152f35b3461028c575f36600319011261028c5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b3461028c575f36600319011261028c576020604051621baf808152f35b3461028c575f36600319011261028c576020600954604051908152f35b3461028c57602036600319011261028c577f8d1f94446a5b32ed366552dc6d865de8d56664c78fc568bad9d451ba3dceede46020600435611054337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146125d7565b61105f8115156126b9565b61106d6127108211156126ef565b80600655604051908152a1005b3461028c575f36600319011261028c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461028c57604036600319011261028c576004356110db816103ef565b6024359060018060a01b03165f52600460205260405f20905f526020526040805f205464ffffffffff825191818116835260281c166020820152f35b634e487b7160e01b5f52603260045260245ffd5b6001548110156111635760015f81815291901b7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60191565b611117565b8054821015611163575f5260205f209060011b01905f90565b6040519061060d6040836105b4565b6040519061060d60a0836105b4565b906040516111ac81610594565b602064ffffffffff829454818116845260281c16910152565b3461028c57602036600319011261028c5760043560015481101561028c576111ee60c09161112b565b5064ffffffffff602061120560018454940161119f565b60ff6040519461ffff8116865263ffffffff8160101c1684870152848160301c16604087015260581c161515606085015282815116608085015201511660a0820152f35b5f929181549161125883610548565b80835292600181169081156112ad575060011461127457505050565b5f9081526020812093945091925b838310611293575060209250010190565b600181602092949394548385870101520191019190611282565b915050602093945060ff929192191683830152151560051b010190565b6001600160a01b0390911681526040602082018190526112ec92910190610675565b90565b3461028c57604036600319011261028c57600435602435905f52600260205260405f20805482101561028c5760019161132791611168565b5061134c828060a01b03825416916113456040518095819301611249565b03836105b4565b610531604051928392836112ca565b3461028c575f36600319011261028c576020600654604051908152f35b3461028c575f36600319011261028c576020600854604051908152f35b3461028c575f36600319011261028c5760206040516127108152f35b3461028c575f36600319011261028c576020600154604051908152f35b8015150361028c57565b3461028c57604036600319011261028c576004356113f5816103ef565b60243590611402826113ce565b335f908152602081815260408083206001600160a01b038516845290915290209115159160ff1981541660ff841617905560405191825260018060a01b0316907f92d241afb0a1a9b3441bf1bd6bea0f9164cf5a2562cbe4bcc34ab943b246560860203392a3005b3461028c575f36600319011261028c5760206040516101808152f35b3461028c57602036600319011261028c577f2d14d804d16da57b1af6557207d7e5ff9230245312c2b667d5f54105327882c860206004356114f1337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146125d7565b80600855604051908152a1005b3461028c57602036600319011261028c57602061152f6102c96102c360043561152a6001548210611972565b61112b565b6040519015158152f35b3461028c57602036600319011261028c57602061152f6115656102c360043561152a6001548210611972565b608064ffffffffff60408301511691015190612e0f565b3461028c57602036600319011261028c576004356115c4337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146125d7565b6115d1600154821061260b565b6115eb60ff6115df8361112b565b505460581c161561272b565b805f526002602052600160405f205414611632575b61160c6102df8261112b565b7f416e669c63d9a3a5e36ee7cc7e2104b8db28ccd286aa18966e98fa230c73b08c5f80a2005b805f52600260205260405f20805461164981611f1a565b9161165760405193846105b4565b81835260208301905f5260205f205f915b83831061168c5750505050611682610964611687926129b4565b612777565b611600565b6002602060019260405161169f81610594565b848060a01b0386541681526040516116bd81610f1d81898b01611249565b83820152815201920192019190611668565b3461028c57608036600319011261028c576004356116ec816103ef565b6064356044356024356001600160a01b038416338114801561177a575b6117139150611b0f565b82820180831161177557612710036117305761172e93612bd9565b005b60405162461bcd60e51b815260206004820152601e60248201527f53756d206f662070637473206d75737420657175616c204d41585f50435400006044820152606490fd5b611e61565b505f908152602081815260408083203384529091529020546117139060ff16611709565b3461028c57602036600319011261028c577f7bd1929729a7db8dd565b881e0af3454665129221283a27837617df5feeff15a6020600435611809337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146125d7565b611816610e1082116126b9565b6118256202a3008211156127c3565b80600955604051908152a1005b3461028c57602036600319011261028c577fc7f7e966c446ca07890210c0a7c9571d1d6f042fb01f27e51a921b2c3285de58602060043561189d337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146125d7565b6118ab6201518082116126b9565b6118ba62093a808211156127c3565b80600a55604051908152a1005b3461028c57602036600319011261028c577fb94f7013434491d516c84c42d5de99b02ed06906f05db29edc1d6850e944fae06020600435611932337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146125d7565b61193d8115156126b9565b61194b6127108211156126ef565b80600755604051908152a1005b3461028c575f36600319011261028c576020610f506127fa565b1561197957565b60405162461bcd60e51b8152602060048201526012602482015271125b9d985b1a59081c1c9bdc1bdcd85b125160721b6044820152606490fd5b9060405160a081018181106001600160401b038211176105af576040526080611a146001839560ff815461ffff8116875263ffffffff8160101c16602088015264ffffffffff8160301c16604088015260581c16151560608601520161119f565b910152565b15611a2057565b60405162461bcd60e51b815260206004820152601b60248201527f50726f706f73616c2063616e6e6f7420626520657865637574656400000000006044820152606490fd5b6001600160401b0381116105af57601f01601f191660200190565b60208183031261028c578051906001600160401b03821161028c570181601f8201121561028c57805190611ab382611a65565b92611ac160405194856105b4565b8284526020838301011161028c57815f9260208093018386015e8301015290565b6001600160a01b0390911681526040602082018190526112ec92910190611249565b6040513d5f823e3d90fd5b15611b1657565b60405162461bcd60e51b81526020600482015260126024820152710850d85b1b195c93dc91195b1959d85d195960721b6044820152606490fd5b9194936001600160a01b038316923384148015611e05575b611b7190611b0f565b611b7c871515611e25565b6001600160a01b0381165f908152600560205260409020611bac90611ba5905460085490611e93565b4211611ea0565b611bba610180831115611ed7565b611bcd611bc8368986611f31565b6129b4565b611df4575b611bda612664565b90611be6821515612056565b60405162ff274760e31b81526001600160a01b038281166004830152602482018490527f00000000000000000000000000000000000000000000000000000000000000001690602081604481855afa80156103ea57611c56915f91611dd5575b50611c4f6127fa565b11156120b1565b6040516350735f6f60e01b81526004810184905290602090829060249082905afa9081156103ea57610ab1611cbc611cc593610ab9935f91610be85750610a8b7f00000000000000000000000000000000000000000000000000000000000000006120fd565b60075490612129565b92611cd864ffffffffff8516151561213c565b60015496611d29611ce7611181565b5f81525f6020820152611cf8611190565b61ffff87168152904263ffffffff16602083015264ffffffffff881660408301525f60608301526080820152612246565b5f5b8a8110611da5575092611d9f92611d7a899a9b96937f48dd3eb1da9035a25fb1644e9b5f3e5a39a6888d5cd415bad5467791c77149ed9896611d758c5f52600360205260405f2090565b61241e565b6001600160a01b03165f908152600560205260409020429055604051948594856124fa565b0390a390565b80611dcf8c611dc9600194611dc28e5f52600260205260405f2090565b928c61226b565b906122dc565b01611d2b565b611dee915060203d602011610c1057610c0281836105b4565b5f611c46565b611e0060018814612013565b611bd2565b505f8481526020818152604080832033845290915290205460ff16611b68565b15611e2c57565b60405162461bcd60e51b815260206004820152600d60248201526c115b5c1d1e481c185e5b1bd859609a1b6044820152606490fd5b634e487b7160e01b5f52601160045260245ffd5b90621baf80820180921161177557565b90601f820180921161177557565b9190820180921161177557565b15611ea757565b60405162461bcd60e51b81526020600482015260086024820152672a37b79039b7b7b760c11b6044820152606490fd5b15611ede57565b60405162461bcd60e51b81526020600482015260146024820152734465736372697074696f6e20746f6f206c6f6e6760601b6044820152606490fd5b6001600160401b0381116105af5760051b60200190565b92919092611f3e84611f1a565b93611f4c60405195866105b4565b602085828152019060051b82019183831161028c5780915b838310611f72575050505050565b82356001600160401b03811161028c5782019060408287031261028c5760405191611f9c83610594565b8035611fa7816103ef565b83526020810135906001600160401b03821161028c57019086601f8301121561028c57813592611fd684611a65565b611fe360405191826105b4565b848152886020868601011161028c575f602086819782809801838601378301015283820152815201920191611f64565b1561201a57565b60405162461bcd60e51b81526020600482015260146024820152735061796c6f6164206c656e677468206e6f74203160601b6044820152606490fd5b1561205d57565b60405162461bcd60e51b815260206004820152601b60248201527f4e6f2070726f706f73616c7320696e2066697273742065706f636800000000006044820152606490fd5b9081602091031261028c575190565b156120b857565b60405162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f7567682077656967687420746f2070726f706f7365000000006044820152606490fd5b604d811161177557600a0a90565b8115612115570490565b634e487b7160e01b5f52601260045260245ffd5b8181029291811591840414171561177557565b1561214357565b60405162461bcd60e51b815260206004820152601760248201527f546f6f206c6974746c65207374616b65207765696768740000000000000000006044820152606490fd5b90612241578151815460208401516040850151606086015160309190911b6affffffffff0000000000001660109290921b65ffffffff00001661ffff9094166bffffffffffffffffffffffff1990931692909217929092179190911790151560581b60ff60581b1617815561060d916001906080015191019064ffffffffff81511669ffffffffff000000000060208454938364ffffffffff198616178655015160281b169169ffffffffffffffffffff191617179055565b610535565b60015490600160401b8210156105af57610bb082600161060d94016001556001611168565b91908110156111635760051b81013590603e198136030182121561028c570190565b601f821161229a57505050565b5f5260205f20906020601f840160051c830193106122d2575b601f0160051c01905b8181106122c7575050565b5f81556001016122bc565b90915081906122b3565b9190918054600160401b8110156105af576122fc91600182018155611168565b61224157600190833561230e816103ef565b828060a01b03166bffffffffffffffffffffffff60a01b8254161781550191602081013590601e198136030182121561028c57019182356001600160401b03811161028c57803603602085011361028c576123738161236d8454610548565b8461228d565b5f601f82116001146123b45781906123a29394955f926123a6575b50508160011b915f199060031b1c19161790565b9055565b602092500101355f8061238e565b601f198216946123c7845f5260205f2090565b915f5b8781106124045750836001959697106123e8575b505050811b019055565b01602001355f19600384901b60f8161c191690555f80806123de565b9092602060018192828787010135815501940191016123ca565b9092916001600160401b0381116105af5761243d8161236d8454610548565b5f601f82116001146124765781906123a29394955f9261246b5750508160011b915f199060031b1c19161790565b013590505f8061238e565b601f19821694612489845f5260205f2090565b915f5b8781106124c25750836001959697106124a957505050811b019055565b01355f19600384901b60f8161c191690555f80806123de565b9092602060018192868601358155019401910161248c565b908060209392818452848401375f828201840152601f01601f1916010190565b91909493929481606084016060855252608083019160808160051b85010192825f90603e19813603015b84831061254c5750505050505061060d9291604091956020820152019064ffffffffff169052565b909192939495607f1988820301855286358281121561028c5783018035612572816103ef565b6001600160a01b03168252602081013536829003601e190181121561028c5701602081359101906001600160401b03811161028c57803603821361028c576125c960209283926040868186600199015201916124da565b980196950193019190612524565b156125de57565b60405162461bcd60e51b815260206004820152600560248201526421636f726560d81b6044820152606490fd5b1561261257565b60405162461bcd60e51b815260206004820152600a602482015269125b9d985b1a5908125160b21b6044820152606490fd5b9160206112ec9381815201916124da565b60031981019190821161177557565b7f00000000000000000000000000000000000000000000000000000000000000004203428111611775576112ec907f00000000000000000000000000000000000000000000000000000000000000009061210b565b156126c057565b60405162461bcd60e51b8152602060048201526007602482015266546f6f206c6f7760c81b6044820152606490fd5b156126f657565b60405162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b6044820152606490fd5b1561273257565b60405162461bcd60e51b815260206004820152601a60248201527f50726f706f73616c20616c72656164792070726f6365737365640000000000006044820152606490fd5b1561277e57565b60405162461bcd60e51b815260206004820152601960248201527f436f6e7461696e732063616e63656c6572207061796c6f6164000000000000006044820152606490fd5b156127ca57565b60405162461bcd60e51b81526020600482015260086024820152670a8dede40d0d2ced60c31b6044820152606490fd5b612802612664565b6040516350735f6f60e01b815260048101919091526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156103ea5761271091612869915f9161286d575b5060065490612129565b0490565b612886915060203d602011610c1057610c0281836105b4565b5f61285f565b606081015161293d57602081016128b66128ad610984835163ffffffff1690565b60095490611e93565b42106129425763ffffffff6128d26128d8925163ffffffff1690565b16611e75565b421161293d5761290a61096460806128f8604085015164ffffffffff1690565b93019264ffffffffff84519116612e0f565b61293d575164ffffffffff61292c610ab96020610e9f855164ffffffffff1690565b9116111561293957600190565b5f90565b505f90565b50505f90565b80518210156111635760209160051b010190565b908160a091031261028c578051612972816103ef565b916020820151612981816103ef565b91604081015163ffffffff60e01b8116810361028c5791608060608301516129a8816113ce565b9201516112ec816103ef565b8051907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316905f5b8381106129f357505050505f90565b6129fd8183612948565b5160208101519084612a29612a1d6020850151935160018060a01b031690565b6001600160a01b031690565b149081612ad5575b50612a4157506001905b016129e4565b805160a48110612acb57612a7091612a5b612a6192612655565b90612eae565b6020808251830101910161295c565b50506001600160a01b039190911691506001600160e01b031916631f57090b60e01b01612ac257308114159081612ab8575b50612ab05750505050600190565b600190612a3b565b905015155f612aa2565b50600190612a3b565b5050505050505f90565b6001600160e01b031916632fe0a06160e11b1490505f612a31565b9064ffffffffff8091169116019064ffffffffff821161177557565b15612b1357565b60405162461bcd60e51b815260206004820152600d60248201526c105b1c9958591e481d9bdd1959609a1b6044820152606490fd5b15612b4f57565b60405162461bcd60e51b815260206004820152601860248201527f566f74696e6720706572696f642068617320636c6f73656400000000000000006044820152606490fd5b15612b9b57565b60405162461bcd60e51b81526020600482015260166024820152754163636f756e7420776569676874206973207a65726f60501b6044820152606490fd5b929092612be9600154851061260b565b612c0a6108fe856108f18460018060a01b03165f52600460205260405f2090565b92612cb4612c1d855164ffffffffff1690565b94612c3e64ffffffffff61093a60208401986109348a5164ffffffffff1690565b612c4a6102c38861112b565b612c5d6109686109646060840151151590565b612c74610993610984602084015163ffffffff1690565b6020612c82825161ffff1690565b60405162ff274760e31b81526001600160a01b038816600482015261ffff909116602482015293849081906044820190565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156103ea57612d8a612d7f610ab9610ab17fa23fc440c6fc2e19ce408adc0b47622097fa7ea64409d71d33ba3fcdb5b4cd959a612de699610ace612d74610ab9610ab1612d62610bb69c612dda9f5f91610be85750610a8b7f00000000000000000000000000000000000000000000000000000000000000006120fd565b94612d6e861515612b94565b85612129565b64ffffffffff168a52565b64ffffffffff168952565b612dac83610af78b6108f18a60018060a01b03165f52600460205260405f2090565b60808101805190612dc8610b67610b54875164ffffffffff1690565b610ba6610b848b5164ffffffffff1690565b935164ffffffffff1690565b6040805164ffffffffff95861681529190941660208201526001600160a01b03919091169290a3565b90612e2b64ffffffffff91826020818351169201511690612af0565b16101590565b15612e3857565b60405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606490fd5b15612e7557565b60405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606490fd5b612ec282612ebb81611e85565b1015612e31565b612ed98151612ed2846004611e93565b1115612e6e565b81612ef05750506040515f81526020810160405290565b60405191601f8116916004831560051b80858701019484860193010101905b808410612f275750508252601f01601f191660405290565b9092602080918551815201930190612f0f56fea164736f6c634300081c000a000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d00000000000000000000000022222222e9fe38f6f1fc8c61b25228adb4d8b95300000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000bb8","name":"Voter","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"cancun","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"node_modules/solidity-bytes-utils/contracts/BytesLib.sol","source_code":"// SPDX-License-Identifier: Unlicense\n/*\n * @title Solidity Bytes Arrays Utils\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\n *\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\n */\npragma solidity >=0.8.0 <0.9.0;\n\n\nlibrary BytesLib {\n    function concat(\n        bytes memory _preBytes,\n        bytes memory _postBytes\n    )\n        internal\n        pure\n        returns (bytes memory)\n    {\n        bytes memory tempBytes;\n\n        assembly {\n            // Get a location of some free memory and store it in tempBytes as\n            // Solidity does for memory variables.\n            tempBytes := mload(0x40)\n\n            // Store the length of the first bytes array at the beginning of\n            // the memory for tempBytes.\n            let length := mload(_preBytes)\n            mstore(tempBytes, length)\n\n            // Maintain a memory counter for the current write location in the\n            // temp bytes array by adding the 32 bytes for the array length to\n            // the starting location.\n            let mc := add(tempBytes, 0x20)\n            // Stop copying when the memory counter reaches the length of the\n            // first bytes array.\n            let end := add(mc, length)\n\n            for {\n                // Initialize a copy counter to the start of the _preBytes data,\n                // 32 bytes into its memory.\n                let cc := add(_preBytes, 0x20)\n            } lt(mc, end) {\n                // Increase both counters by 32 bytes each iteration.\n                mc := add(mc, 0x20)\n                cc := add(cc, 0x20)\n            } {\n                // Write the _preBytes data into the tempBytes memory 32 bytes\n                // at a time.\n                mstore(mc, mload(cc))\n            }\n\n            // Add the length of _postBytes to the current length of tempBytes\n            // and store it as the new length in the first 32 bytes of the\n            // tempBytes memory.\n            length := mload(_postBytes)\n            mstore(tempBytes, add(length, mload(tempBytes)))\n\n            // Move the memory counter back from a multiple of 0x20 to the\n            // actual end of the _preBytes data.\n            mc := end\n            // Stop copying when the memory counter reaches the new combined\n            // length of the arrays.\n            end := add(mc, length)\n\n            for {\n                let cc := add(_postBytes, 0x20)\n            } lt(mc, end) {\n                mc := add(mc, 0x20)\n                cc := add(cc, 0x20)\n            } {\n                mstore(mc, mload(cc))\n            }\n\n            // Update the free-memory pointer by padding our last write location\n            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the\n            // next 32 byte block, then round down to the nearest multiple of\n            // 32. If the sum of the length of the two arrays is zero then add\n            // one before rounding down to leave a blank 32 bytes (the length block with 0).\n            mstore(0x40, and(\n              add(add(end, iszero(add(length, mload(_preBytes)))), 31),\n              not(31) // Round down to the nearest 32 bytes.\n            ))\n        }\n\n        return tempBytes;\n    }\n\n    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {\n        assembly {\n            // Read the first 32 bytes of _preBytes storage, which is the length\n            // of the array. (We don't need to use the offset into the slot\n            // because arrays use the entire slot.)\n            let fslot := sload(_preBytes.slot)\n            // Arrays of 31 bytes or less have an even value in their slot,\n            // while longer arrays have an odd value. The actual length is\n            // the slot divided by two for odd values, and the lowest order\n            // byte divided by two for even values.\n            // If the slot is even, bitwise and the slot with 255 and divide by\n            // two to get the length. If the slot is odd, bitwise and the slot\n            // with -1 and divide by two.\n            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n            let mlength := mload(_postBytes)\n            let newlength := add(slength, mlength)\n            // slength can contain both the length and contents of the array\n            // if length < 32 bytes so let's prepare for that\n            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n            switch add(lt(slength, 32), lt(newlength, 32))\n            case 2 {\n                // Since the new array still fits in the slot, we just need to\n                // update the contents of the slot.\n                // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length\n                sstore(\n                    _preBytes.slot,\n                    // all the modifications to the slot are inside this\n                    // next block\n                    add(\n                        // we can just add to the slot contents because the\n                        // bytes we want to change are the LSBs\n                        fslot,\n                        add(\n                            mul(\n                                div(\n                                    // load the bytes from memory\n                                    mload(add(_postBytes, 0x20)),\n                                    // zero all bytes to the right\n                                    exp(0x100, sub(32, mlength))\n                                ),\n                                // and now shift left the number of bytes to\n                                // leave space for the length in the slot\n                                exp(0x100, sub(32, newlength))\n                            ),\n                            // increase length by the double of the memory\n                            // bytes length\n                            mul(mlength, 2)\n                        )\n                    )\n                )\n            }\n            case 1 {\n                // The stored value fits in the slot, but the combined value\n                // will exceed it.\n                // get the keccak hash to get the contents of the array\n                mstore(0x0, _preBytes.slot)\n                let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n                // save new length\n                sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n                // The contents of the _postBytes array start 32 bytes into\n                // the structure. Our first read should obtain the `submod`\n                // bytes that can fit into the unused space in the last word\n                // of the stored array. To get this, we read 32 bytes starting\n                // from `submod`, so the data we read overlaps with the array\n                // contents by `submod` bytes. Masking the lowest-order\n                // `submod` bytes allows us to add that value directly to the\n                // stored value.\n\n                let submod := sub(32, slength)\n                let mc := add(_postBytes, submod)\n                let end := add(_postBytes, mlength)\n                let mask := sub(exp(0x100, submod), 1)\n\n                sstore(\n                    sc,\n                    add(\n                        and(\n                            fslot,\n                            0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00\n                        ),\n                        and(mload(mc), mask)\n                    )\n                )\n\n                for {\n                    mc := add(mc, 0x20)\n                    sc := add(sc, 1)\n                } lt(mc, end) {\n                    sc := add(sc, 1)\n                    mc := add(mc, 0x20)\n                } {\n                    sstore(sc, mload(mc))\n                }\n\n                mask := exp(0x100, sub(mc, end))\n\n                sstore(sc, mul(div(mload(mc), mask), mask))\n            }\n            default {\n                // get the keccak hash to get the contents of the array\n                mstore(0x0, _preBytes.slot)\n                // Start copying to the last used word of the stored array.\n                let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n                // save new length\n                sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n                // Copy over the first `submod` bytes of the new data as in\n                // case 1 above.\n                let slengthmod := mod(slength, 32)\n                let mlengthmod := mod(mlength, 32)\n                let submod := sub(32, slengthmod)\n                let mc := add(_postBytes, submod)\n                let end := add(_postBytes, mlength)\n                let mask := sub(exp(0x100, submod), 1)\n\n                sstore(sc, add(sload(sc), and(mload(mc), mask)))\n\n                for {\n                    sc := add(sc, 1)\n                    mc := add(mc, 0x20)\n                } lt(mc, end) {\n                    sc := add(sc, 1)\n                    mc := add(mc, 0x20)\n                } {\n                    sstore(sc, mload(mc))\n                }\n\n                mask := exp(0x100, sub(mc, end))\n\n                sstore(sc, mul(div(mload(mc), mask), mask))\n            }\n        }\n    }\n\n    function slice(\n        bytes memory _bytes,\n        uint256 _start,\n        uint256 _length\n    )\n        internal\n        pure\n        returns (bytes memory)\n    {\n        require(_length + 31 >= _length, \"slice_overflow\");\n        require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n\n        bytes memory tempBytes;\n\n        assembly {\n            switch iszero(_length)\n            case 0 {\n                // Get a location of some free memory and store it in tempBytes as\n                // Solidity does for memory variables.\n                tempBytes := mload(0x40)\n\n                // The first word of the slice result is potentially a partial\n                // word read from the original array. To read it, we calculate\n                // the length of that partial word and start copying that many\n                // bytes into the array. The first word we copy will start with\n                // data we don't care about, but the last `lengthmod` bytes will\n                // land at the beginning of the contents of the new array. When\n                // we're done copying, we overwrite the full first word with\n                // the actual length of the slice.\n                let lengthmod := and(_length, 31)\n\n                // The multiplication in the next line is necessary\n                // because when slicing multiples of 32 bytes (lengthmod == 0)\n                // the following copy loop was copying the origin's length\n                // and then ending prematurely not copying everything it should.\n                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n                let end := add(mc, _length)\n\n                for {\n                    // The multiplication in the next line has the same exact purpose\n                    // as the one above.\n                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n                } lt(mc, end) {\n                    mc := add(mc, 0x20)\n                    cc := add(cc, 0x20)\n                } {\n                    mstore(mc, mload(cc))\n                }\n\n                mstore(tempBytes, _length)\n\n                //update free-memory pointer\n                //allocating the array padded to 32 bytes like the compiler does now\n                mstore(0x40, and(add(mc, 31), not(31)))\n            }\n            //if we want a zero-length slice let's just return a zero-length array\n            default {\n                tempBytes := mload(0x40)\n                //zero out the 32 bytes slice we are about to return\n                //we need to do it because Solidity does not garbage collect\n                mstore(tempBytes, 0)\n\n                mstore(0x40, add(tempBytes, 0x20))\n            }\n        }\n\n        return tempBytes;\n    }\n\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\n        require(_bytes.length >= _start + 20, \"toAddress_outOfBounds\");\n        address tempAddress;\n\n        assembly {\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\n        }\n\n        return tempAddress;\n    }\n\n    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {\n        require(_bytes.length >= _start + 1 , \"toUint8_outOfBounds\");\n        uint8 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x1), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {\n        require(_bytes.length >= _start + 2, \"toUint16_outOfBounds\");\n        uint16 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x2), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {\n        require(_bytes.length >= _start + 4, \"toUint32_outOfBounds\");\n        uint32 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x4), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {\n        require(_bytes.length >= _start + 8, \"toUint64_outOfBounds\");\n        uint64 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x8), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {\n        require(_bytes.length >= _start + 12, \"toUint96_outOfBounds\");\n        uint96 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0xc), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {\n        require(_bytes.length >= _start + 16, \"toUint128_outOfBounds\");\n        uint128 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x10), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {\n        require(_bytes.length >= _start + 32, \"toUint256_outOfBounds\");\n        uint256 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x20), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {\n        require(_bytes.length >= _start + 32, \"toBytes32_outOfBounds\");\n        bytes32 tempBytes32;\n\n        assembly {\n            tempBytes32 := mload(add(add(_bytes, 0x20), _start))\n        }\n\n        return tempBytes32;\n    }\n\n    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {\n        bool success = true;\n\n        assembly {\n            let length := mload(_preBytes)\n\n            // if lengths don't match the arrays are not equal\n            switch eq(length, mload(_postBytes))\n            case 1 {\n                // cb is a circuit breaker in the for loop since there's\n                //  no said feature for inline assembly loops\n                // cb = 1 - don't breaker\n                // cb = 0 - break\n                let cb := 1\n\n                let mc := add(_preBytes, 0x20)\n                let end := add(mc, length)\n\n                for {\n                    let cc := add(_postBytes, 0x20)\n                // the next line is the loop condition:\n                // while(uint256(mc < end) + cb == 2)\n                } eq(add(lt(mc, end), cb), 2) {\n                    mc := add(mc, 0x20)\n                    cc := add(cc, 0x20)\n                } {\n                    // if any of these checks fails then arrays are not equal\n                    if iszero(eq(mload(mc), mload(cc))) {\n                        // unsuccess:\n                        success := 0\n                        cb := 0\n                    }\n                }\n            }\n            default {\n                // unsuccess:\n                success := 0\n            }\n        }\n\n        return success;\n    }\n\n    function equalStorage(\n        bytes storage _preBytes,\n        bytes memory _postBytes\n    )\n        internal\n        view\n        returns (bool)\n    {\n        bool success = true;\n\n        assembly {\n            // we know _preBytes_offset is 0\n            let fslot := sload(_preBytes.slot)\n            // Decode the length of the stored array like in concatStorage().\n            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n            let mlength := mload(_postBytes)\n\n            // if lengths don't match the arrays are not equal\n            switch eq(slength, mlength)\n            case 1 {\n                // slength can contain both the length and contents of the array\n                // if length < 32 bytes so let's prepare for that\n                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n                if iszero(iszero(slength)) {\n                    switch lt(slength, 32)\n                    case 1 {\n                        // blank the last byte which is the length\n                        fslot := mul(div(fslot, 0x100), 0x100)\n\n                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {\n                            // unsuccess:\n                            success := 0\n                        }\n                    }\n                    default {\n                        // cb is a circuit breaker in the for loop since there's\n                        //  no said feature for inline assembly loops\n                        // cb = 1 - don't breaker\n                        // cb = 0 - break\n                        let cb := 1\n\n                        // get the keccak hash to get the contents of the array\n                        mstore(0x0, _preBytes.slot)\n                        let sc := keccak256(0x0, 0x20)\n\n                        let mc := add(_postBytes, 0x20)\n                        let end := add(mc, mlength)\n\n                        // the next line is the loop condition:\n                        // while(uint256(mc < end) + cb == 2)\n                        for {} eq(add(lt(mc, end), cb), 2) {\n                            sc := add(sc, 1)\n                            mc := add(mc, 0x20)\n                        } {\n                            if iszero(eq(sload(sc), mload(mc))) {\n                                // unsuccess:\n                                success := 0\n                                cb := 0\n                            }\n                        }\n                    }\n                }\n            }\n            default {\n                // unsuccess:\n                success := 0\n            }\n        }\n\n        return success;\n    }\n}\n"},{"file_path":"src/dependencies/CoreOwnable.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\nimport {ICore} from \"../interfaces/ICore.sol\";\n\n/**\n    @title Core Ownable\n    @author Prisma Finance (with edits by Resupply Finance)\n    @notice Contracts inheriting `CoreOwnable` have the same owner as `Core`.\n            The ownership cannot be independently modified or renounced.\n */\ncontract CoreOwnable {\n    ICore public immutable core;\n\n    constructor(address _core) {\n        core = ICore(_core);\n    }\n\n    modifier onlyOwner() {\n        require(msg.sender == address(core), \"!core\");\n        _;\n    }\n\n    function owner() public view returns (address) {\n        return address(core);\n    }\n}"},{"file_path":"src/dependencies/DelegatedOps.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\n/**\n    @title Delegated Operations\n    @author Prisma Finance (with edits by Resupply Finance)\n    @notice Allows delegation to specific contract functionality. Useful for creating\n            wrapper contracts to bundle multiple interactions into a single call.\n */\ncontract DelegatedOps {\n    event DelegateApprovalSet(address indexed account, address indexed delegate, bool isApproved);\n\n    mapping(address owner => mapping(address caller => bool isApproved)) public isApprovedDelegate;\n\n    modifier callerOrDelegated(address _account) {\n        require(msg.sender == _account || isApprovedDelegate[_account][msg.sender], \"!CallerOrDelegated\");\n        _;\n    }\n\n    function setDelegateApproval(address _delegate, bool _isApproved) external {\n        isApprovedDelegate[msg.sender][_delegate] = _isApproved;\n        emit DelegateApprovalSet(msg.sender, _delegate, _isApproved);\n    }\n}\n"},{"file_path":"src/dependencies/EpochTracker.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\nimport \"../interfaces/ICore.sol\";\n\n/**\n    @title EpochTracker\n    @dev Provides a unified `startTime` and `getEpoch`, used for tracking epochs.\n */\ncontract EpochTracker {\n    uint256 public immutable startTime;\n    \n    /// @notice Length of an epoch, in seconds\n    uint256 public immutable epochLength;\n\n    constructor(address _core) {\n        startTime = ICore(_core).startTime();\n        epochLength = ICore(_core).epochLength();\n    }\n\n    function getEpoch() public view returns (uint256 epoch) {\n        return (block.timestamp - startTime) / epochLength;\n    }\n}"},{"file_path":"src/interfaces/IAuthHook.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\ninterface IAuthHook {\n    function preHook(address operator, address target, bytes calldata data) external returns (bool);\n    function postHook(bytes memory result, address operator, address target, bytes calldata data) external returns (bool);\n}\n"},{"file_path":"src/interfaces/ICore.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\nimport { IAuthHook } from './IAuthHook.sol';\n\ninterface ICore {\n    struct OperatorAuth {\n        bool authorized;\n        IAuthHook hook;\n    }\n\n    event VoterSet(address indexed newVoter);\n    event OperatorExecuted(address indexed caller, address indexed target, bytes data);\n    event OperatorSet(address indexed caller, address indexed target, bool authorized, bytes4 selector, IAuthHook authHook);\n\n    function execute(address target, bytes calldata data) external returns (bytes memory);\n    function epochLength() external view returns (uint256);\n    function startTime() external view returns (uint256);\n    function voter() external view returns (address);\n    function ownershipTransferDeadline() external view returns (uint256);\n    function pendingOwner() external view returns (address);\n    function setOperatorPermissions(\n        address caller,\n        address target,\n        bytes4 selector,\n        bool authorized,\n        IAuthHook authHook\n    ) external;\n    function setVoter(address newVoter) external;\n    function operatorPermissions(address caller, address target, bytes4 selector) external view returns (bool authorized, IAuthHook hook);\n}\n"},{"file_path":"src/interfaces/IGovStaker.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\ninterface IGovStaker {\n    /* ========== EVENTS ========== */\n    event RewardAdded(address indexed rewardToken, uint256 amount);\n    event RewardTokenAdded(address indexed rewardsToken, address indexed rewardsDistributor, uint256 rewardsDuration);\n    event Recovered(address indexed token, uint256 amount);\n    event RewardsDurationUpdated(address indexed rewardsToken, uint256 duration);\n    event RewardPaid(address indexed user, address indexed rewardToken, uint256 reward);\n    event Staked(address indexed account, uint indexed epoch, uint amount);\n    event Unstaked(address indexed account, uint amount);\n    event Cooldown(address indexed account, uint amount, uint end);\n    event CooldownEpochsUpdated(uint24 newDuration);\n\n    /* ========== STRUCTS ========== */\n    struct Reward {\n        address rewardsDistributor;\n        uint256 rewardsDuration;\n        uint256 periodFinish;\n        uint256 rewardRate;\n        uint256 lastUpdateTime;\n        uint256 rewardPerTokenStored;\n    }\n\n    struct AccountData {\n        uint120 realizedStake; // Amount of stake that has fully realized weight.\n        uint120 pendingStake; // Amount of stake that has not yet fully realized weight.\n        uint16 lastUpdateEpoch;\n    }\n\n    struct UserCooldown {\n        uint104 end;\n        uint152 amount;\n    }\n\n    enum ApprovalStatus {\n        None, // 0. Default value, indicating no approval\n        StakeOnly, // 1. Approved for stake only\n        UnstakeOnly, // 2. Approved for unstake only\n        StakeAndUnstake // 3. Approved for both stake and unstake\n    }\n\n    /* ========== STATE VARIABLES ========== */\n    function rewardTokens(uint256 index) external view returns (address);\n    function rewardData(address token) external view returns (Reward memory);\n    function rewards(address account, address token) external view returns (uint256);\n    function userRewardPerTokenPaid(address account, address token) external view returns (uint256);\n    function CORE() external view returns (address);\n    function PRECISION() external view returns (uint256);\n    function ESCROW() external view returns (address);\n    function MAX_COOLDOWN_DURATION() external view returns (uint24);\n    function totalPending() external view returns (uint120);\n    function totalLastUpdateEpoch() external view returns (uint16);\n    function cooldownEpochs() external view returns (uint256);\n    function decimals() external view returns (uint8);\n    function approvedCaller(address account, address caller) external view returns (ApprovalStatus);\n\n    /* ========== EXTERNAL FUNCTIONS ========== */\n    function accountData(address account) external view returns (AccountData memory);\n    function stakeToken() external view returns (address);\n    function balanceOf(address account) external view returns (uint256);\n    function totalSupply() external view returns (uint256);\n    function getReward() external;\n    function getOneReward(address rewardsToken) external;\n    function addReward(address rewardsToken, address rewardsDistributor, uint256 rewardsDuration) external;\n    function notifyRewardAmount(address rewardsToken, uint256 rewardAmount) external;\n    function setRewardsDistributor(address rewardsToken, address rewardsDistributor) external;\n    function setRewardsDuration(address rewardsToken, uint256 rewardsDuration) external;\n    function recoverERC20(address tokenAddress, uint256 tokenAmount) external;\n    function stake(address account, uint amount) external returns (uint);\n    function stakeFor(address account, uint amount) external returns (uint);\n    function cooldown(address account, uint amount) external returns (uint);\n    function cooldowns(address account) external view returns (UserCooldown memory);\n    function cooldownFor(address account, uint amount) external returns (uint);\n    function exit(address account) external returns (uint);\n    function exitFor(address account) external returns (uint);\n    function unstake(address account, address receiver) external returns (uint);\n    function unstakeFor(address account, address receiver) external returns (uint);\n    function checkpointAccount(address account) external returns (AccountData memory, uint weight);\n    function checkpointAccountWithLimit(address account, uint epoch) external returns (AccountData memory, uint weight);\n    function checkpointTotal() external returns (uint);\n    function setApprovedCaller(address caller, ApprovalStatus status) external;\n    function setCooldownEpochs(uint24 epochs) external;\n    function getAccountWeight(address account) external view returns (uint);\n    function getAccountWeightAt(address account, uint epoch) external view returns (uint);\n    function getTotalWeight() external view returns (uint);\n    function getTotalWeightAt(uint epoch) external view returns (uint);\n    function getUnstakableAmount(address account) external view returns (uint);\n    function isCooldownEnabled() external view returns (bool);\n    function rewardTokensLength() external view returns (uint256);\n    function earned(address account, address rewardsToken) external view returns (uint256 pending);\n    function earnedMulti(address account) external view returns (uint256[] memory pending);\n    function rewardPerToken(address rewardsToken) external view returns (uint256 rewardAmount);\n    function lastTimeRewardApplicable(address rewardsToken) external view returns (uint256);\n    function getRewardForDuration(address rewardsToken) external view returns (uint256);\n    function owner() external view returns (address);\n    function guardian() external view returns (address);\n    function getEpoch() external view returns (uint);\n    function epochLength() external view returns (uint);\n    function startTime() external view returns (uint);\n    function irreversiblyCommitAccountAsPermanentStaker(address account) external;\n    function onPermaStakeMigrate(address account) external;\n    function migrateStake() external returns (uint amount);\n    function setDelegateApproval(address delegate, bool approved) external;\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"_core","type":"address"},{"internalType":"contract IGovStaker","name":"_staker","type":"address"},{"internalType":"uint256","name":"_minCreateProposalPct","type":"uint256"},{"internalType":"uint256","name":"_quorumPct","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"bool","name":"isApproved","type":"bool"}],"name":"DelegateApprovalSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"delay","type":"uint256"}],"name":"ExecutionDelaySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"cooldown","type":"uint256"}],"name":"MinTimeBetweenProposalsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct Voter.Action[]","name":"payload","type":"tuple[]"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quorumWeight","type":"uint256"}],"name":"ProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"ProposalCreationMinPctSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ProposalDescriptionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"QuorumPctSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"weightYes","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"weightNo","type":"uint256"}],"name":"VoteCast","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"period","type":"uint256"}],"name":"VotingPeriodSet","type":"event"},{"inputs":[],"name":"EXECUTION_DEADLINE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_DESCRIPTION_BYTES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PCT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"accountVoteWeights","outputs":[{"internalType":"uint40","name":"weightYes","type":"uint40"},{"internalType":"uint40","name":"weightNo","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"canExecute","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"core","outputs":[{"internalType":"contract ICore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Voter.Action[]","name":"payload","type":"tuple[]"},{"internalType":"string","name":"description","type":"string"}],"name":"createNewProposal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"epochLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"executeProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"executionDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEpoch","outputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProposalCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getProposalData","outputs":[{"internalType":"string","name":"description","type":"string"},{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"createdAt","type":"uint256"},{"internalType":"uint256","name":"quorumWeight","type":"uint256"},{"internalType":"uint256","name":"weightYes","type":"uint256"},{"internalType":"uint256","name":"weightNo","type":"uint256"},{"internalType":"bool","name":"processed","type":"bool"},{"internalType":"bool","name":"executable","type":"bool"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Voter.Action[]","name":"payload","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"caller","type":"address"}],"name":"isApprovedDelegate","outputs":[{"internalType":"bool","name":"isApproved","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"latestProposalTimestamp","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minCreateProposalPct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minCreateProposalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minTimeBetweenProposals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposalData","outputs":[{"internalType":"uint16","name":"epoch","type":"uint16"},{"internalType":"uint32","name":"createdAt","type":"uint32"},{"internalType":"uint40","name":"quorumWeight","type":"uint40"},{"internalType":"bool","name":"processed","type":"bool"},{"components":[{"internalType":"uint40","name":"weightYes","type":"uint40"},{"internalType":"uint40","name":"weightNo","type":"uint40"}],"internalType":"struct Voter.Vote","name":"results","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"proposalDescription","outputs":[{"internalType":"string","name":"description","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposalPayload","outputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quorumPct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"quorumReached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"},{"internalType":"bool","name":"_isApproved","type":"bool"}],"name":"setDelegateApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setExecutionDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pct","type":"uint256"}],"name":"setMinCreateProposalPct","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cooldown","type":"uint256"}],"name":"setMinTimeBetweenProposals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pct","type":"uint256"}],"name":"setQuorumPct","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"setVotingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"staker","outputs":[{"internalType":"contract IGovStaker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"description","type":"string"}],"name":"updateProposalDescription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"voteForProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"pctYes","type":"uint256"},{"internalType":"uint256","name":"pctNo","type":"uint256"}],"name":"voteForProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"votingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":"0x000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d00000000000000000000000022222222e9fe38f6f1fc8c61b25228adb4d8b95300000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000bb8"}