{"constructor_args":"0x0000000000000000000000000000000000000000000000000000000000000000","is_partially_verified":true,"is_changed_bytecode":false,"abi":[{"inputs":[{"internalType":"bool","name":"test","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"approver","type":"address"}],"name":"ApproverSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"concurrentProposals","type":"uint256"}],"name":"ConcurrentProposalsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":true,"internalType":"bytes4","name":"functionId","type":"bytes4"},{"indexed":false,"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"ConstitutionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"dequeueFrequency","type":"uint256"}],"name":"DequeueFrequencySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"executionStageDuration","type":"uint256"}],"name":"ExecutionStageDurationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"approver","type":"address"}],"name":"HotfixApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"HotfixExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timeDelta","type":"uint256"}],"name":"HotfixExecutionTimeWindowSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"executionLimit","type":"uint256"}],"name":"HotfixPrepared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"HotfixRecordReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minDeposit","type":"uint256"}],"name":"MinDepositSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"baselineQuorumFactor","type":"uint256"}],"name":"ParticipationBaselineQuorumFactorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"baselineUpdateFactor","type":"uint256"}],"name":"ParticipationBaselineUpdateFactorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"participationBaseline","type":"uint256"}],"name":"ParticipationBaselineUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"participationFloor","type":"uint256"}],"name":"ParticipationFloorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ProposalDequeued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalExpired","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"proposer","type":"address"},{"indexed":false,"internalType":"uint256","name":"transactionCount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deposit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ProposalQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"revokedUpvotes","type":"uint256"}],"name":"ProposalUpvoteRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"upvotes","type":"uint256"}],"name":"ProposalUpvoted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"ProposalVoteRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"yesVotes","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"noVotes","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"abstainVotes","type":"uint256"}],"name":"ProposalVoteRevokedV2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"ProposalVoted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"yesVotes","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"noVotes","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"abstainVotes","type":"uint256"}],"name":"ProposalVotedV2","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"queueExpiry","type":"uint256"}],"name":"QueueExpirySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"referendumStageDuration","type":"uint256"}],"name":"ReferendumStageDurationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registryAddress","type":"address"}],"name":"RegistrySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"council","type":"address"}],"name":"SecurityCouncilSet","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":false,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"approveHotfix","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"approver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes","name":"blsKey","type":"bytes"},{"internalType":"bytes","name":"blsPop","type":"bytes"}],"name":"checkProofOfPossession","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"concurrentProposals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"dequeueFrequency","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"dequeueProposalsIfReady","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"dequeued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"emptyIndices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"execute","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"address[]","name":"destinations","type":"address[]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256[]","name":"dataLengths","type":"uint256[]"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"executeHotfix","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"aNumerator","type":"uint256"},{"internalType":"uint256","name":"aDenominator","type":"uint256"},{"internalType":"uint256","name":"bNumerator","type":"uint256"},{"internalType":"uint256","name":"bDenominator","type":"uint256"},{"internalType":"uint256","name":"exponent","type":"uint256"},{"internalType":"uint256","name":"_decimals","type":"uint256"}],"name":"fractionMulExp","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAmountOfGoldUsedForVoting","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes","name":"header","type":"bytes"}],"name":"getBlockNumberFromHeader","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"bytes4","name":"functionId","type":"bytes4"}],"name":"getConstitution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getDequeue","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getEpochNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getEpochNumberOfBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getEpochSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getExecutionStageDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"address[]","name":"destinations","type":"address[]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256[]","name":"dataLengths","type":"uint256[]"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"getHotfixHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"getHotfixRecord","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getMostRecentReferendumProposal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getParentSealBitmap","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getParticipationParameters","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"getProposal","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"getProposalStage","outputs":[{"internalType":"enum Proposals.Stage","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getProposalTransaction","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getQueue","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getQueueLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getReferendumStageDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getUpvoteRecord","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"getUpvotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes","name":"header","type":"bytes"}],"name":"getVerifiedSealBitmapFromHeader","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getVersionNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getVoteRecord","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"getVoteTotals","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes","name":"header","type":"bytes"}],"name":"hashHeader","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"hotfixExecutionTimeWindow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"hotfixes","outputs":[{"internalType":"bool","name":"executed","type":"bool"},{"internalType":"bool","name":"approved","type":"bool"},{"internalType":"uint256","name":"deprecated_preparedEpoch","type":"uint256"},{"internalType":"bool","name":"councilApproved","type":"bool"},{"internalType":"uint256","name":"executionTimeLimit","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"registryAddress","type":"address"},{"internalType":"address","name":"_approver","type":"address"},{"internalType":"uint256","name":"_concurrentProposals","type":"uint256"},{"internalType":"uint256","name":"_minDeposit","type":"uint256"},{"internalType":"uint256","name":"_queueExpiry","type":"uint256"},{"internalType":"uint256","name":"_dequeueFrequency","type":"uint256"},{"internalType":"uint256","name":"referendumStageDuration","type":"uint256"},{"internalType":"uint256","name":"executionStageDuration","type":"uint256"},{"internalType":"uint256","name":"participationBaseline","type":"uint256"},{"internalType":"uint256","name":"participationFloor","type":"uint256"},{"internalType":"uint256","name":"baselineUpdateFactor","type":"uint256"},{"internalType":"uint256","name":"baselineQuorumFactor","type":"uint256"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"isApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"isDequeuedProposal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"isDequeuedProposalExpired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"isProposalPassing","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"isQueued","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"isQueuedProposalExpired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isVoting","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastDequeue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"minQuorumSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minQuorumSizeInCurrentSet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"numberValidatorsInCurrentSet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"numberValidatorsInSet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"prepareHotfix","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"proposalCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"proposalExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"address[]","name":"destinations","type":"address[]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256[]","name":"dataLengths","type":"uint256[]"},{"internalType":"string","name":"descriptionUrl","type":"string"}],"name":"propose","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"queueExpiry","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"refundedDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"registry","outputs":[{"internalType":"contract IRegistry","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"newVotingPower","type":"uint256"}],"name":"removeVotesWhenRevokingDelegatedVotes","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"resetHotFixRecord","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"lesser","type":"uint256"},{"internalType":"uint256","name":"greater","type":"uint256"}],"name":"revokeUpvote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"revokeVotes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"securityCouncil","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_approver","type":"address"}],"name":"setApprover","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"baselineQuorumFactor","type":"uint256"}],"name":"setBaselineQuorumFactor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"baselineUpdateFactor","type":"uint256"}],"name":"setBaselineUpdateFactor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_concurrentProposals","type":"uint256"}],"name":"setConcurrentProposals","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"bytes4","name":"functionId","type":"bytes4"},{"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"setConstitution","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_dequeueFrequency","type":"uint256"}],"name":"setDequeueFrequency","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"executionStageDuration","type":"uint256"}],"name":"setExecutionStageDuration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"timeWindow","type":"uint256"}],"name":"setHotfixExecutionTimeWindow","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_minDeposit","type":"uint256"}],"name":"setMinDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"participationBaseline","type":"uint256"}],"name":"setParticipationBaseline","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"participationFloor","type":"uint256"}],"name":"setParticipationFloor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_queueExpiry","type":"uint256"}],"name":"setQueueExpiry","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"referendumStageDuration","type":"uint256"}],"name":"setReferendumStageDuration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"registryAddress","type":"address"}],"name":"setRegistry","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_council","type":"address"}],"name":"setSecurityCouncil","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"stageDurations","outputs":[{"internalType":"uint256","name":"approval","type":"uint256"},{"internalType":"uint256","name":"referendum","type":"uint256"},{"internalType":"uint256","name":"execution","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"lesser","type":"uint256"},{"internalType":"uint256","name":"greater","type":"uint256"}],"name":"upvote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"validatorAddressFromCurrentSet","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"validatorSignerAddressFromCurrentSet","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"validatorSignerAddressFromSet","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"enum Proposals.VoteValue","name":"value","type":"uint8"}],"name":"vote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"yesVotes","type":"uint256"},{"internalType":"uint256","name":"noVotes","type":"uint256"},{"internalType":"uint256","name":"abstainVotes","type":"uint256"}],"name":"votePartially","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}],"conflicting_implementations":null,"certified":false,"additional_sources":[{"file_path":"contracts/common/interfaces/IRegistry.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface IRegistry {\n  function setAddressFor(string calldata, address) external;\n  function getAddressForOrDie(bytes32) external view returns (address);\n  function getAddressFor(bytes32) external view returns (address);\n  function getAddressForStringOrDie(string calldata identifier) external view returns (address);\n  function getAddressForString(string calldata identifier) external view returns (address);\n  function isOneOf(bytes32[] calldata, address) external view returns (bool);\n}\n"},{"file_path":"contracts/common/interfaces/IFreezer.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface IFreezer {\n  function freeze(address target) external;\n  function unfreeze(address target) external;\n  function isFrozen(address) external view returns (bool);\n}\n"},{"file_path":"contracts/governance/Proposals.sol","source_code":"pragma solidity ^0.5.13;\n\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\nimport \"openzeppelin-solidity/contracts/utils/Address.sol\";\nimport \"solidity-bytes-utils/contracts/BytesLib.sol\";\n\nimport \"../common/FixidityLib.sol\";\n\n/**\n * @title A library operating on Celo Governance proposals.\n */\nlibrary Proposals {\n  using FixidityLib for FixidityLib.Fraction;\n  using SafeMath for uint256;\n  using BytesLib for bytes;\n\n  enum Stage {\n    None,\n    Queued,\n    Approval,\n    Referendum,\n    Execution,\n    Expiration\n  }\n\n  enum VoteValue {\n    None,\n    Abstain,\n    No,\n    Yes\n  }\n\n  struct StageDurations {\n    uint256 approval;\n    uint256 referendum;\n    uint256 execution;\n  }\n\n  struct VoteTotals {\n    uint256 yes;\n    uint256 no;\n    uint256 abstain;\n  }\n\n  struct Transaction {\n    uint256 value;\n    address destination;\n    bytes data;\n  }\n\n  struct Proposal {\n    address proposer;\n    uint256 deposit;\n    uint256 timestamp;\n    VoteTotals votes;\n    Transaction[] transactions;\n    bool approved;\n    uint256 networkWeight;\n    string descriptionUrl;\n  }\n\n  /**\n   * @notice Constructs a proposal.\n   * @param proposal The proposal struct to be constructed.\n   * @param values The values of CELO to be sent in the proposed transactions.\n   * @param destinations The destination addresses of the proposed transactions.\n   * @param data The concatenated data to be included in the proposed transactions.\n   * @param dataLengths The lengths of each transaction's data.\n   * @param proposer The proposer.\n   * @param deposit The proposal deposit.\n   */\n  function make(\n    Proposal storage proposal,\n    uint256[] memory values,\n    address[] memory destinations,\n    bytes memory data,\n    uint256[] memory dataLengths,\n    address proposer,\n    uint256 deposit\n  ) public {\n    require(\n      values.length == destinations.length && destinations.length == dataLengths.length,\n      \"Array length mismatch\"\n    );\n    uint256 transactionCount = values.length;\n\n    proposal.proposer = proposer;\n    proposal.deposit = deposit;\n    // solhint-disable-next-line not-rely-on-time\n    proposal.timestamp = now;\n\n    uint256 dataPosition = 0;\n    delete proposal.transactions;\n    for (uint256 i = 0; i < transactionCount; i = i.add(1)) {\n      proposal.transactions.push(\n        Transaction(values[i], destinations[i], data.slice(dataPosition, dataLengths[i]))\n      );\n      dataPosition = dataPosition.add(dataLengths[i]);\n    }\n  }\n\n  /**\n   * @notice Adds or changes a vote on a proposal.\n   * @param proposal The proposal struct.\n   * @param previousYesVotes The previous yes votes weight.\n   * @param previousNoVotes The previous no votes weight.\n   * @param previousAbstainVotes The previous abstain votes weight.\n   * @param yesVotes The current yes votes weight.\n   * @param noVotes The current no votes weight.\n   * @param abstainVotes The current abstain votes weight.\n   */\n  function updateVote(\n    Proposal storage proposal,\n    uint256 previousYesVotes,\n    uint256 previousNoVotes,\n    uint256 previousAbstainVotes,\n    uint256 yesVotes,\n    uint256 noVotes,\n    uint256 abstainVotes\n  ) public {\n    // Subtract previous vote.\n    proposal.votes.yes = proposal.votes.yes.sub(previousYesVotes);\n    proposal.votes.no = proposal.votes.no.sub(previousNoVotes);\n    proposal.votes.abstain = proposal.votes.abstain.sub(previousAbstainVotes);\n\n    // Add new vote.\n    proposal.votes.yes = proposal.votes.yes.add(yesVotes);\n    proposal.votes.no = proposal.votes.no.add(noVotes);\n    proposal.votes.abstain = proposal.votes.abstain.add(abstainVotes);\n  }\n\n  /**\n   * @notice Executes the proposal.\n   * @param proposal The proposal struct.\n   * @dev Reverts if any transaction fails.\n   */\n  function execute(Proposal storage proposal) public {\n    executeTransactions(proposal.transactions);\n  }\n\n  /**\n   * @notice Returns a specified transaction in a proposal.\n   * @param proposal The proposal struct.\n   * @param index The index of the specified transaction in the proposal's transaction list.\n   * @return Transaction value.\n   * @return Transaction destination.\n   * @return Transaction data.\n   */\n  function getTransaction(\n    Proposal storage proposal,\n    uint256 index\n  ) public view returns (uint256, address, bytes memory) {\n    require(index < proposal.transactions.length, \"getTransaction: bad index\");\n    Transaction storage transaction = proposal.transactions[index];\n    return (transaction.value, transaction.destination, transaction.data);\n  }\n\n  function setDescriptionUrl(Proposal storage proposal, string memory descriptionUrl) internal {\n    require(bytes(descriptionUrl).length != 0, \"Description url must have non-zero length\");\n    proposal.descriptionUrl = descriptionUrl;\n  }\n\n  /**\n   * @notice Executes the proposal.\n   * @param proposal The proposal struct.\n   * @dev Reverts if any transaction fails.\n   */\n  function executeMem(Proposal memory proposal) internal {\n    executeTransactions(proposal.transactions);\n  }\n\n  /**\n   * @notice Executes a list of transactions.\n   * @param transactions The transactions to execute.\n   */\n  function executeTransactions(Transaction[] memory transactions) internal {\n    for (uint256 i = 0; i < transactions.length; i = i.add(1)) {\n      require(\n        externalCall(\n          transactions[i].destination,\n          transactions[i].value,\n          transactions[i].data.length,\n          transactions[i].data\n        ),\n        \"Proposal execution failed\"\n      );\n    }\n  }\n\n  /**\n   * @notice Computes the support ratio for a proposal with the quorum condition:\n   *   If the total number of votes (yes + no + abstain) is less than the required number of votes,\n   *   \"no\" votes are added to increase particiption to this level. The ratio of yes / (yes + no)\n   *   votes is returned.\n   * @param proposal The proposal struct.\n   * @param quorum The minimum participation at which \"no\" votes are not added.\n   * @return The support ratio with the quorum condition.\n   */\n  function getSupportWithQuorumPadding(\n    Proposal storage proposal,\n    FixidityLib.Fraction memory quorum\n  ) internal view returns (FixidityLib.Fraction memory) {\n    uint256 yesVotes = proposal.votes.yes;\n    if (yesVotes == 0) {\n      return FixidityLib.newFixed(0);\n    }\n    uint256 noVotes = proposal.votes.no;\n    uint256 totalVotes = yesVotes.add(noVotes).add(proposal.votes.abstain);\n    uint256 requiredVotes = quorum\n      .multiply(FixidityLib.newFixed(proposal.networkWeight))\n      .fromFixed();\n    if (requiredVotes > totalVotes) {\n      noVotes = noVotes.add(requiredVotes.sub(totalVotes));\n    }\n    return FixidityLib.newFixedFraction(yesVotes, yesVotes.add(noVotes));\n  }\n\n  /**\n   * @notice Constructs a proposal for use in memory.\n   * @param values The values of CELO to be sent in the proposed transactions.\n   * @param destinations The destination addresses of the proposed transactions.\n   * @param data The concatenated data to be included in the proposed transactions.\n   * @param dataLengths The lengths of each transaction's data.\n   * @param proposer The proposer.\n   * @param deposit The proposal deposit.\n   * @return The constructed proposal struct.\n   */\n  function makeMem(\n    uint256[] memory values,\n    address[] memory destinations,\n    bytes memory data,\n    uint256[] memory dataLengths,\n    address proposer,\n    uint256 deposit\n  ) internal view returns (Proposal memory) {\n    require(\n      values.length == destinations.length && destinations.length == dataLengths.length,\n      \"Array length mismatch\"\n    );\n    uint256 transactionCount = values.length;\n\n    Proposal memory proposal;\n    proposal.proposer = proposer;\n    proposal.deposit = deposit;\n    // solhint-disable-next-line not-rely-on-time\n    proposal.timestamp = now;\n\n    uint256 dataPosition = 0;\n    proposal.transactions = new Transaction[](transactionCount);\n    for (uint256 i = 0; i < transactionCount; i = i.add(1)) {\n      proposal.transactions[i] = Transaction(\n        values[i],\n        destinations[i],\n        data.slice(dataPosition, dataLengths[i])\n      );\n      dataPosition = dataPosition.add(dataLengths[i]);\n    }\n    return proposal;\n  }\n\n  /**\n   * @notice Returns the number of votes cast on the proposal over the total number\n   *   of votes in the network as a fraction.\n   * @param proposal The proposal struct.\n   * @return The participation of the proposal.\n   */\n  function getParticipation(\n    Proposal storage proposal\n  ) internal view returns (FixidityLib.Fraction memory) {\n    uint256 totalVotes = proposal.votes.yes.add(proposal.votes.no).add(proposal.votes.abstain);\n    return FixidityLib.newFixedFraction(totalVotes, proposal.networkWeight);\n  }\n\n  /**\n   * @notice Returns an unpacked proposal struct with its transaction count.\n   * @param proposal The proposal struct.\n   * @return proposer\n   * @return deposit\n   * @return timestamp\n   * @return transaction Transaction count.\n   * @return description Description url.\n   * @return networkWeight Network weight.\n   * @return Approval status.\n   */\n  function unpack(\n    Proposal storage proposal\n  ) internal view returns (address, uint256, uint256, uint256, string storage, uint256, bool) {\n    return (\n      proposal.proposer,\n      proposal.deposit,\n      proposal.timestamp,\n      proposal.transactions.length,\n      proposal.descriptionUrl,\n      proposal.networkWeight,\n      proposal.approved\n    );\n  }\n\n  /**\n   * @notice Returns the referendum vote totals for a proposal.\n   * @param proposal The proposal struct.\n   * @return The yes vote totals.\n   * @return The no vote totals.\n   * @return The abstain vote totals.\n   */\n  function getVoteTotals(\n    Proposal storage proposal\n  ) internal view returns (uint256, uint256, uint256) {\n    return (proposal.votes.yes, proposal.votes.no, proposal.votes.abstain);\n  }\n\n  /**\n   * @notice Returns whether or not a proposal has been approved.\n   * @param proposal The proposal struct.\n   * @return Whether or not the proposal has been approved.\n   */\n  function isApproved(Proposal storage proposal) internal view returns (bool) {\n    return proposal.approved;\n  }\n\n  /**\n   * @notice Returns whether or not a proposal exists.\n   * @param proposal The proposal struct.\n   * @return Whether or not the proposal exists.\n   */\n  function exists(Proposal storage proposal) internal view returns (bool) {\n    return proposal.timestamp > 0;\n  }\n\n  // call has been separated into its own function in order to take advantage\n  // of the Solidity's code generator to produce a loop that copies tx.data into memory.\n  /**\n   * @notice Executes a function call.\n   * @param value The value of CELO to be sent with the function call.\n   * @param destination The destination address of the function call.\n   * @param dataLength The length of the data to be included in the function call.\n   * @param data The data to be included in the function call.\n   */\n  function externalCall(\n    address destination,\n    uint256 value,\n    uint256 dataLength,\n    bytes memory data\n  ) private returns (bool) {\n    bool result;\n\n    if (dataLength > 0) require(Address.isContract(destination), \"Invalid contract address\");\n\n    /* solhint-disable no-inline-assembly */\n    assembly {\n      /* solhint-disable max-line-length */\n      let x := mload(0x40) // \"Allocate\" memory for output (0x40 is where \"free memory\" pointer is stored by convention)\n      let d := add(data, 32) // First 32 bytes are the padded length of data, so exclude that\n      result := call(\n        sub(gas, 34710), // 34710 is the value that solidity is currently emitting\n        // It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) +\n        // callNewAccountGas (25000, in case the destination address does not exist and needs creating)\n        destination,\n        value,\n        d,\n        dataLength, // Size of the input (in bytes) - this is what fixes the padding problem\n        x,\n        0 // Output is ignored, therefore the output size is zero\n      )\n      /* solhint-enable max-line-length */\n    }\n    /* solhint-enable no-inline-assembly */\n    return result;\n  }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/GSN/Context.sol","source_code":"pragma solidity ^0.5.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\ncontract Context {\n    // Empty internal constructor, to prevent people from mistakenly deploying\n    // an instance of this contract, which should be used via inheritance.\n    constructor () internal { }\n    // solhint-disable-previous-line no-empty-blocks\n\n    function _msgSender() internal view returns (address payable) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view returns (bytes memory) {\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n        return msg.data;\n    }\n}\n"},{"file_path":"contracts/governance/interfaces/IGovernance.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface IGovernance {\n  // constitution\n  function setConstitution(address destination, bytes4 functionId, uint256 threshold) external;\n  function getConstitution(address destination, bytes4 functionId) external view returns (uint256);\n\n  // proposal\n  function propose(\n    uint256[] calldata values,\n    address[] calldata destinations,\n    bytes calldata data,\n    uint256[] calldata dataLengths,\n    string calldata descriptionUrl\n  ) external payable returns (uint256);\n  function getProposal(\n    uint256 proposalId\n  ) external view returns (address, uint256, uint256, uint256, string memory, uint256, bool);\n  function proposalCount() external view returns (uint256);\n\n  // upvote\n  function upvote(uint256 proposalId, uint256 lesser, uint256 greater) external returns (bool);\n  function getUpvotes(uint256 proposalId) external view returns (uint256);\n\n  // approve\n  function approve(uint256 proposalId, uint256 index) external returns (bool);\n  function isApproved(uint256 proposalId) external view returns (bool);\n\n  // voting\n  // TODO: Enable once we migrate out of 0.5\n  // function vote(\n  //   uint256 proposalId,\n  //   uint256 index,\n  //   Proposals.VoteValue value\n  // ) external returns (bool);\n  function votePartially(\n    uint256 proposalId,\n    uint256 index,\n    uint256 yesVotes,\n    uint256 noVotes,\n    uint256 abstainVotes\n  ) external returns (bool);\n  function removeVotesWhenRevokingDelegatedVotes(\n    address account,\n    uint256 maxAmountAllowed\n  ) external;\n  function isVoting(address account) external view returns (bool);\n  function getVoteTotals(uint256 proposalId) external view returns (uint256, uint256, uint256);\n  function getAmountOfGoldUsedForVoting(address account) external view returns (uint256);\n\n  // referendum\n  function getReferendumStageDuration() external view returns (uint256);\n\n  // execution\n  function execute(uint256 proposalId, uint256 index) external returns (bool);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/math/Math.sol","source_code":"pragma solidity ^0.5.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a >= b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow, so we distribute\n        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);\n    }\n}\n"},{"file_path":"contracts/common/linkedlists/SortedLinkedList.sol","source_code":"pragma solidity ^0.5.13;\n\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\nimport \"./LinkedList.sol\";\n\n/**\n * @title Maintains a sorted list of unsigned ints keyed by bytes32.\n */\nlibrary SortedLinkedList {\n  using SafeMath for uint256;\n  using LinkedList for LinkedList.List;\n\n  struct List {\n    LinkedList.List list;\n    mapping(bytes32 => uint256) values;\n  }\n\n  /**\n   * @notice Inserts an element into a doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The key of the element to insert.\n   * @param value The element value.\n   * @param lesserKey The key of the element less than the element to insert.\n   * @param greaterKey The key of the element greater than the element to insert.\n   */\n  function insert(\n    List storage list,\n    bytes32 key,\n    uint256 value,\n    bytes32 lesserKey,\n    bytes32 greaterKey\n  ) internal {\n    require(\n      key != bytes32(0) && key != lesserKey && key != greaterKey && !contains(list, key),\n      \"invalid key\"\n    );\n    require(\n      (lesserKey != bytes32(0) || greaterKey != bytes32(0)) || list.list.numElements == 0,\n      \"greater and lesser key zero\"\n    );\n    require(contains(list, lesserKey) || lesserKey == bytes32(0), \"invalid lesser key\");\n    require(contains(list, greaterKey) || greaterKey == bytes32(0), \"invalid greater key\");\n    (lesserKey, greaterKey) = getLesserAndGreater(list, value, lesserKey, greaterKey);\n    list.list.insert(key, lesserKey, greaterKey);\n    list.values[key] = value;\n  }\n\n  /**\n   * @notice Removes an element from the doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The key of the element to remove.\n   */\n  function remove(List storage list, bytes32 key) internal {\n    list.list.remove(key);\n    list.values[key] = 0;\n  }\n\n  /**\n   * @notice Updates an element in the list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The element key.\n   * @param value The element value.\n   * @param lesserKey The key of the element will be just left of `key` after the update.\n   * @param greaterKey The key of the element will be just right of `key` after the update.\n   * @dev Note that only one of \"lesserKey\" or \"greaterKey\" needs to be correct to reduce friction.\n   */\n  function update(\n    List storage list,\n    bytes32 key,\n    uint256 value,\n    bytes32 lesserKey,\n    bytes32 greaterKey\n  ) internal {\n    require(contains(list, key), \"key not in list\");\n    require(key != bytes32(0) && key != lesserKey && key != greaterKey, \"invalid key\");\n    require(\n      (lesserKey != bytes32(0) || greaterKey != bytes32(0)) || list.list.numElements == 1,\n      \"greater and lesser key zero\"\n    );\n\n    bytes32 oldLesserKey = list.list.elements[key].previousKey;\n    bytes32 oldGreaterKey = list.list.elements[key].nextKey;\n\n    if (isValueBetween(list, value, oldLesserKey, oldGreaterKey)) {\n      list.values[key] = value;\n    } else {\n      remove(list, key);\n      insert(list, key, value, lesserKey, greaterKey);\n    }\n  }\n\n  /**\n   * @notice Inserts an element at the tail of the doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The key of the element to insert.\n   */\n  function push(List storage list, bytes32 key) internal {\n    insert(list, key, 0, bytes32(0), list.list.tail);\n  }\n\n  /**\n   * @notice Removes N elements from the head of the list and returns their keys.\n   * @param list A storage pointer to the underlying list.\n   * @param n The number of elements to pop.\n   * @return The keys of the popped elements.\n   */\n  function popN(List storage list, uint256 n) internal returns (bytes32[] memory) {\n    require(n <= list.list.numElements, \"not enough elements\");\n    bytes32[] memory keys = new bytes32[](n);\n    for (uint256 i = 0; i < n; i = i.add(1)) {\n      bytes32 key = list.list.head;\n      keys[i] = key;\n      remove(list, key);\n    }\n    return keys;\n  }\n\n  /**\n   * @notice Returns whether or not a particular key is present in the sorted list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The element key.\n   * @return Whether or not the key is in the sorted list.\n   */\n  function contains(List storage list, bytes32 key) internal view returns (bool) {\n    return list.list.contains(key);\n  }\n\n  /**\n   * @notice Returns the value for a particular key in the sorted list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The element key.\n   * @return The element value.\n   */\n  function getValue(List storage list, bytes32 key) internal view returns (uint256) {\n    return list.values[key];\n  }\n\n  /**\n   * @notice Gets all elements from the doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @return Array of all keys in the list.\n   * @return Values corresponding to keys, which will be ordered largest to smallest.\n   */\n  function getElements(\n    List storage list\n  ) internal view returns (bytes32[] memory, uint256[] memory) {\n    bytes32[] memory keys = getKeys(list);\n    uint256[] memory values = new uint256[](keys.length);\n    for (uint256 i = 0; i < keys.length; i = i.add(1)) {\n      values[i] = list.values[keys[i]];\n    }\n    return (keys, values);\n  }\n\n  /**\n   * @notice Gets all element keys from the doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @return All element keys from head to tail.\n   */\n  function getKeys(List storage list) internal view returns (bytes32[] memory) {\n    return list.list.getKeys();\n  }\n\n  /**\n   * @notice Returns first N greatest elements of the list.\n   * @param list A storage pointer to the underlying list.\n   * @param n The number of elements to return.\n   * @return The keys of the first n elements.\n   * @dev Reverts if n is greater than the number of elements in the list.\n   */\n  function headN(List storage list, uint256 n) internal view returns (bytes32[] memory) {\n    return list.list.headN(n);\n  }\n\n  /**\n   * @notice Returns the keys of the elements greaterKey than and less than the provided value.\n   * @param list A storage pointer to the underlying list.\n   * @param value The element value.\n   * @param lesserKey The key of the element which could be just left of the new value.\n   * @param greaterKey The key of the element which could be just right of the new value.\n   * @return The correct lesserKey keys.\n   * @return The correct greaterKey keys.\n   */\n  function getLesserAndGreater(\n    List storage list,\n    uint256 value,\n    bytes32 lesserKey,\n    bytes32 greaterKey\n  ) private view returns (bytes32, bytes32) {\n    // Check for one of the following conditions and fail if none are met:\n    //   1. The value is less than the current lowest value\n    //   2. The value is greater than the current greatest value\n    //   3. The value is just greater than the value for `lesserKey`\n    //   4. The value is just less than the value for `greaterKey`\n    if (lesserKey == bytes32(0) && isValueBetween(list, value, lesserKey, list.list.tail)) {\n      return (lesserKey, list.list.tail);\n    } else if (\n      greaterKey == bytes32(0) && isValueBetween(list, value, list.list.head, greaterKey)\n    ) {\n      return (list.list.head, greaterKey);\n    } else if (\n      lesserKey != bytes32(0) &&\n      isValueBetween(list, value, lesserKey, list.list.elements[lesserKey].nextKey)\n    ) {\n      return (lesserKey, list.list.elements[lesserKey].nextKey);\n    } else if (\n      greaterKey != bytes32(0) &&\n      isValueBetween(list, value, list.list.elements[greaterKey].previousKey, greaterKey)\n    ) {\n      return (list.list.elements[greaterKey].previousKey, greaterKey);\n    } else {\n      require(false, \"get lesser and greater failure\");\n    }\n  }\n\n  /**\n   * @notice Returns whether or not a given element is between two other elements.\n   * @param list A storage pointer to the underlying list.\n   * @param value The element value.\n   * @param lesserKey The key of the element whose value should be lesserKey.\n   * @param greaterKey The key of the element whose value should be greaterKey.\n   * @return True if the given element is between the two other elements.\n   */\n  function isValueBetween(\n    List storage list,\n    uint256 value,\n    bytes32 lesserKey,\n    bytes32 greaterKey\n  ) private view returns (bool) {\n    bool isLesser = lesserKey == bytes32(0) || list.values[lesserKey] <= value;\n    bool isGreater = greaterKey == bytes32(0) || list.values[greaterKey] >= value;\n    return isLesser && isGreater;\n  }\n}\n"},{"file_path":"contracts/common/linkedlists/IntegerSortedLinkedList.sol","source_code":"pragma solidity ^0.5.13;\n\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\n\nimport \"./SortedLinkedList.sol\";\n\n/**\n * @title Maintains a sorted list of unsigned ints keyed by uint256.\n */\nlibrary IntegerSortedLinkedList {\n  using SafeMath for uint256;\n  using SortedLinkedList for SortedLinkedList.List;\n\n  /**\n   * @notice Inserts an element into a doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The key of the element to insert.\n   * @param value The element value.\n   * @param lesserKey The key of the element less than the element to insert.\n   * @param greaterKey The key of the element greater than the element to insert.\n   */\n  function insert(\n    SortedLinkedList.List storage list,\n    uint256 key,\n    uint256 value,\n    uint256 lesserKey,\n    uint256 greaterKey\n  ) public {\n    list.insert(bytes32(key), value, bytes32(lesserKey), bytes32(greaterKey));\n  }\n\n  /**\n   * @notice Removes an element from the doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The key of the element to remove.\n   */\n  function remove(SortedLinkedList.List storage list, uint256 key) public {\n    list.remove(bytes32(key));\n  }\n\n  /**\n   * @notice Updates an element in the list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The element key.\n   * @param value The element value.\n   * @param lesserKey The key of the element will be just left of `key` after the update.\n   * @param greaterKey The key of the element will be just right of `key` after the update.\n   * @dev Note that only one of \"lesserKey\" or \"greaterKey\" needs to be correct to reduce friction.\n   */\n  function update(\n    SortedLinkedList.List storage list,\n    uint256 key,\n    uint256 value,\n    uint256 lesserKey,\n    uint256 greaterKey\n  ) public {\n    list.update(bytes32(key), value, bytes32(lesserKey), bytes32(greaterKey));\n  }\n\n  /**\n   * @notice Inserts an element at the end of the doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The key of the element to insert.\n   */\n  function push(SortedLinkedList.List storage list, uint256 key) public {\n    list.push(bytes32(key));\n  }\n\n  /**\n   * @notice Removes N elements from the head of the list and returns their keys.\n   * @param list A storage pointer to the underlying list.\n   * @param n The number of elements to pop.\n   * @return The keys of the popped elements.\n   */\n  function popN(SortedLinkedList.List storage list, uint256 n) public returns (uint256[] memory) {\n    bytes32[] memory byteKeys = list.popN(n);\n    uint256[] memory keys = new uint256[](byteKeys.length);\n    for (uint256 i = 0; i < byteKeys.length; i = i.add(1)) {\n      keys[i] = uint256(byteKeys[i]);\n    }\n    return keys;\n  }\n\n  /**\n   * @notice Returns whether or not a particular key is present in the sorted list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The element key.\n   * @return Whether or not the key is in the sorted list.\n   */\n  function contains(SortedLinkedList.List storage list, uint256 key) public view returns (bool) {\n    return list.contains(bytes32(key));\n  }\n\n  /**\n   * @notice Returns the value for a particular key in the sorted list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The element key.\n   * @return The element value.\n   */\n  function getValue(SortedLinkedList.List storage list, uint256 key) public view returns (uint256) {\n    return list.getValue(bytes32(key));\n  }\n\n  /**\n   * @notice Gets all elements from the doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @return Array of all keys in the list.\n   * @return Values corresponding to keys, which will be ordered largest to smallest.\n   */\n  function getElements(\n    SortedLinkedList.List storage list\n  ) public view returns (uint256[] memory, uint256[] memory) {\n    bytes32[] memory byteKeys = list.getKeys();\n    uint256[] memory keys = new uint256[](byteKeys.length);\n    uint256[] memory values = new uint256[](byteKeys.length);\n    for (uint256 i = 0; i < byteKeys.length; i = i.add(1)) {\n      keys[i] = uint256(byteKeys[i]);\n      values[i] = list.values[byteKeys[i]];\n    }\n    return (keys, values);\n  }\n}\n"},{"file_path":"contracts/identity/interfaces/IRandom.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface IRandom {\n  function revealAndCommit(bytes32, bytes32, address) external;\n  function randomnessBlockRetentionWindow() external view returns (uint256);\n  function random() external view returns (bytes32);\n  function getBlockRandomness(uint256) external view returns (bytes32);\n}\n"},{"file_path":"lib/mento-core/contracts/interfaces/IReserve.sol","source_code":"pragma solidity ^0.5.13;\n\ninterface IReserve {\n    function setTobinTaxStalenessThreshold(uint256) external;\n\n    function addToken(address) external returns (bool);\n\n    function removeToken(address, uint256) external returns (bool);\n\n    function transferGold(address payable, uint256) external returns (bool);\n\n    function transferExchangeGold(address payable, uint256) external returns (bool);\n\n    function getReserveGoldBalance() external view returns (uint256);\n\n    function getUnfrozenReserveGoldBalance() external view returns (uint256);\n\n    function getOrComputeTobinTax() external returns (uint256, uint256);\n\n    function getTokens() external view returns (address[] memory);\n\n    function getReserveRatio() external view returns (uint256);\n\n    function addExchangeSpender(address) external;\n\n    function removeExchangeSpender(address, uint256) external;\n\n    function addSpender(address) external;\n\n    function removeSpender(address) external;\n}\n"},{"file_path":"contracts/governance/interfaces/IEpochRewards.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface IEpochRewards {\n  function updateTargetVotingYield() external;\n  function calculateTargetEpochRewards() external view returns (uint256, uint256, uint256, uint256);\n  function getTargetVotingYieldParameters() external view returns (uint256, uint256, uint256);\n  function getRewardsMultiplierParameters() external view returns (uint256, uint256, uint256);\n  function getCommunityRewardFraction() external view returns (uint256);\n  function getCarbonOffsettingFraction() external view returns (uint256);\n  function getTargetVotingGoldFraction() external view returns (uint256);\n  function getRewardsMultiplier() external view returns (uint256);\n  function carbonOffsettingPartner() external view returns (address);\n}\n"},{"file_path":"lib/solidity-bytes-utils/contracts/BytesLib.sol","source_code":"/*\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 */\n\npragma solidity ^0.5.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        uint _start,\n        uint _length\n    )\n        internal\n        pure\n        returns (bytes memory)\n    {\n        require(_bytes.length >= (_start + _length));\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\n                mstore(0x40, add(tempBytes, 0x20))\n            }\n        }\n\n        return tempBytes;\n    }\n\n    function toAddress(bytes memory _bytes, uint _start) internal  pure returns (address) {\n        require(_bytes.length >= (_start + 20));\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, uint _start) internal  pure returns (uint8) {\n        require(_bytes.length >= (_start + 1));\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, uint _start) internal  pure returns (uint16) {\n        require(_bytes.length >= (_start + 2));\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, uint _start) internal  pure returns (uint32) {\n        require(_bytes.length >= (_start + 4));\n        uint32 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x4), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint(bytes memory _bytes, uint _start) internal  pure returns (uint256) {\n        require(_bytes.length >= (_start + 32));\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, uint _start) internal  pure returns (bytes32) {\n        require(_bytes.length >= (_start + 32));\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(uint(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(uint(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":"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol","source_code":"pragma solidity ^0.5.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\n * the optional functions; to access them see {ERC20Detailed}.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"},{"file_path":"contracts/common/interfaces/IFeeCurrencyWhitelist.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface IFeeCurrencyWhitelist {\n  function initialize() external;\n  function addToken(address) external;\n  function getWhitelist() external view returns (address[] memory);\n}\n"},{"file_path":"contracts/common/linkedlists/LinkedList.sol","source_code":"pragma solidity ^0.5.13;\n\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\n\n/**\n * @title Maintains a doubly linked list keyed by bytes32.\n * @dev Following the `next` pointers will lead you to the head, rather than the tail.\n */\nlibrary LinkedList {\n  using SafeMath for uint256;\n\n  struct Element {\n    bytes32 previousKey;\n    bytes32 nextKey;\n    bool exists;\n  }\n\n  struct List {\n    bytes32 head;\n    bytes32 tail;\n    uint256 numElements;\n    mapping(bytes32 => Element) elements;\n  }\n\n  /**\n   * @notice Inserts an element into a doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The key of the element to insert.\n   * @param previousKey The key of the element that comes before the element to insert.\n   * @param nextKey The key of the element that comes after the element to insert.\n   */\n  function insert(List storage list, bytes32 key, bytes32 previousKey, bytes32 nextKey) internal {\n    require(key != bytes32(0), \"Key must be defined\");\n    require(!contains(list, key), \"Can't insert an existing element\");\n    require(\n      previousKey != key && nextKey != key,\n      \"Key cannot be the same as previousKey or nextKey\"\n    );\n\n    Element storage element = list.elements[key];\n    element.exists = true;\n\n    if (list.numElements == 0) {\n      list.tail = key;\n      list.head = key;\n    } else {\n      require(\n        previousKey != bytes32(0) || nextKey != bytes32(0),\n        \"Either previousKey or nextKey must be defined\"\n      );\n\n      element.previousKey = previousKey;\n      element.nextKey = nextKey;\n\n      if (previousKey != bytes32(0)) {\n        require(\n          contains(list, previousKey),\n          \"If previousKey is defined, it must exist in the list\"\n        );\n        Element storage previousElement = list.elements[previousKey];\n        require(previousElement.nextKey == nextKey, \"previousKey must be adjacent to nextKey\");\n        previousElement.nextKey = key;\n      } else {\n        list.tail = key;\n      }\n\n      if (nextKey != bytes32(0)) {\n        require(contains(list, nextKey), \"If nextKey is defined, it must exist in the list\");\n        Element storage nextElement = list.elements[nextKey];\n        require(nextElement.previousKey == previousKey, \"previousKey must be adjacent to nextKey\");\n        nextElement.previousKey = key;\n      } else {\n        list.head = key;\n      }\n    }\n\n    list.numElements = list.numElements.add(1);\n  }\n\n  /**\n   * @notice Inserts an element at the tail of the doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The key of the element to insert.\n   */\n  function push(List storage list, bytes32 key) internal {\n    insert(list, key, bytes32(0), list.tail);\n  }\n\n  /**\n   * @notice Removes an element from the doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The key of the element to remove.\n   */\n  function remove(List storage list, bytes32 key) internal {\n    Element storage element = list.elements[key];\n    require(key != bytes32(0) && contains(list, key), \"key not in list\");\n    if (element.previousKey != bytes32(0)) {\n      Element storage previousElement = list.elements[element.previousKey];\n      previousElement.nextKey = element.nextKey;\n    } else {\n      list.tail = element.nextKey;\n    }\n\n    if (element.nextKey != bytes32(0)) {\n      Element storage nextElement = list.elements[element.nextKey];\n      nextElement.previousKey = element.previousKey;\n    } else {\n      list.head = element.previousKey;\n    }\n\n    delete list.elements[key];\n    list.numElements = list.numElements.sub(1);\n  }\n\n  /**\n   * @notice Updates an element in the list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The element key.\n   * @param previousKey The key of the element that comes before the updated element.\n   * @param nextKey The key of the element that comes after the updated element.\n   */\n  function update(List storage list, bytes32 key, bytes32 previousKey, bytes32 nextKey) internal {\n    require(\n      key != bytes32(0) && key != previousKey && key != nextKey && contains(list, key),\n      \"key on in list\"\n    );\n    remove(list, key);\n    insert(list, key, previousKey, nextKey);\n  }\n\n  /**\n   * @notice Returns whether or not a particular key is present in the sorted list.\n   * @param list A storage pointer to the underlying list.\n   * @param key The element key.\n   * @return Whether or not the key is in the sorted list.\n   */\n  function contains(List storage list, bytes32 key) internal view returns (bool) {\n    return list.elements[key].exists;\n  }\n\n  /**\n   * @notice Returns the keys of the N elements at the head of the list.\n   * @param list A storage pointer to the underlying list.\n   * @param n The number of elements to return.\n   * @return The keys of the N elements at the head of the list.\n   * @dev Reverts if n is greater than the number of elements in the list.\n   */\n  function headN(List storage list, uint256 n) internal view returns (bytes32[] memory) {\n    require(n <= list.numElements, \"not enough elements\");\n    bytes32[] memory keys = new bytes32[](n);\n    bytes32 key = list.head;\n    for (uint256 i = 0; i < n; i = i.add(1)) {\n      keys[i] = key;\n      key = list.elements[key].previousKey;\n    }\n    return keys;\n  }\n\n  /**\n   * @notice Gets all element keys from the doubly linked list.\n   * @param list A storage pointer to the underlying list.\n   * @return All element keys from head to tail.\n   */\n  function getKeys(List storage list) internal view returns (bytes32[] memory) {\n    return headN(list, list.numElements);\n  }\n}\n"},{"file_path":"contracts/common/UsingPrecompiles.sol","source_code":"pragma solidity ^0.5.13;\n\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\nimport \"../common/interfaces/ICeloVersionedContract.sol\";\nimport \"../common/interfaces/IEpochManager.sol\";\nimport \"../../contracts-0.8/common/IsL2Check.sol\";\n\ncontract UsingPrecompiles is IsL2Check {\n  using SafeMath for uint256;\n\n  address constant TRANSFER = address(0xff - 2);\n  address constant FRACTION_MUL = address(0xff - 3);\n  address constant PROOF_OF_POSSESSION = address(0xff - 4);\n  address constant GET_VALIDATOR = address(0xff - 5);\n  address constant NUMBER_VALIDATORS = address(0xff - 6);\n  address constant EPOCH_SIZE = address(0xff - 7);\n  address constant BLOCK_NUMBER_FROM_HEADER = address(0xff - 8);\n  address constant HASH_HEADER = address(0xff - 9);\n  address constant GET_PARENT_SEAL_BITMAP = address(0xff - 10);\n  address constant GET_VERIFIED_SEAL_BITMAP = address(0xff - 11);\n  uint256 constant DAY = 86400;\n\n  /**\n   * @notice calculate a * b^x for fractions a, b to `decimals` precision\n   * @param aNumerator Numerator of first fraction\n   * @param aDenominator Denominator of first fraction\n   * @param bNumerator Numerator of exponentiated fraction\n   * @param bDenominator Denominator of exponentiated fraction\n   * @param exponent exponent to raise b to\n   * @param _decimals precision\n   * @return Numerator of the computed quantity (not reduced).\n   * @return Denominator of the computed quantity (not reduced).\n   * @dev This function will be deprecated in L2.\n   */\n  function fractionMulExp(\n    uint256 aNumerator,\n    uint256 aDenominator,\n    uint256 bNumerator,\n    uint256 bDenominator,\n    uint256 exponent,\n    uint256 _decimals\n  ) public view onlyL1 returns (uint256, uint256) {\n    require(aDenominator != 0 && bDenominator != 0, \"a denominator is zero\");\n    uint256 returnNumerator;\n    uint256 returnDenominator;\n    bool success;\n    bytes memory out;\n    (success, out) = FRACTION_MUL.staticcall(\n      abi.encodePacked(aNumerator, aDenominator, bNumerator, bDenominator, exponent, _decimals)\n    );\n    require(success, \"error calling fractionMulExp precompile\");\n    returnNumerator = getUint256FromBytes(out, 0);\n    returnDenominator = getUint256FromBytes(out, 32);\n    return (returnNumerator, returnDenominator);\n  }\n\n  /**\n   * @notice Returns the current epoch size in blocks.\n   * @return The current epoch size in blocks.\n   * @dev This function will be deprecated in L2.\n   */\n  function getEpochSize() public view onlyL1 returns (uint256) {\n    bytes memory out;\n    bool success;\n    (success, out) = EPOCH_SIZE.staticcall(abi.encodePacked(true));\n    require(success, \"error calling getEpochSize precompile\");\n    return getUint256FromBytes(out, 0);\n  }\n\n  /**\n   * @notice Returns the epoch number at a block.\n   * @param blockNumber Block number where epoch number is calculated.\n   * @return Epoch number.\n   * @dev This function will be deprecated in L2.\n   */\n  function getEpochNumberOfBlock(uint256 blockNumber) public view onlyL1 returns (uint256) {\n    return epochNumberOfBlock(blockNumber, getEpochSize());\n  }\n\n  /**\n   * @notice Returns the epoch number at a block.\n   * @return Current epoch number.\n   * @dev This function will be deprecated in L2.\n   */\n  function getEpochNumber() public view onlyL1 returns (uint256) {\n    return getEpochNumberOfBlock(block.number);\n  }\n\n  /**\n   * @notice Gets a validator signer address from the current validator set.\n   * @param index Index of requested validator in the validator set.\n   * @return Address of validator signer at the requested index.\n   * @dev This function will be deprecated in L2.\n   */\n  function validatorSignerAddressFromCurrentSet(\n    uint256 index\n  ) public view onlyL1 returns (address) {\n    bytes memory out;\n    bool success;\n    (success, out) = GET_VALIDATOR.staticcall(abi.encodePacked(index, uint256(block.number)));\n    require(success, \"error calling validatorSignerAddressFromCurrentSet precompile\");\n    return address(uint160(getUint256FromBytes(out, 0)));\n  }\n\n  /**\n   * @notice Gets a validator signer address from the validator set at the given block number.\n   * @param index Index of requested validator in the validator set.\n   * @param blockNumber Block number to retrieve the validator set from.\n   * @return Address of validator signer at the requested index.\n   * @dev This function will be deprecated in L2.\n   */\n  function validatorSignerAddressFromSet(\n    uint256 index,\n    uint256 blockNumber\n  ) public view onlyL1 returns (address) {\n    bytes memory out;\n    bool success;\n    (success, out) = GET_VALIDATOR.staticcall(abi.encodePacked(index, blockNumber));\n    require(success, \"error calling validatorSignerAddressFromSet precompile\");\n    return address(uint160(getUint256FromBytes(out, 0)));\n  }\n\n  /**\n   * @notice Gets the size of the current elected validator set.\n   * @return Size of the current elected validator set.\n   * @dev This function will be deprecated in L2.\n   */\n  function numberValidatorsInCurrentSet() public view onlyL1 returns (uint256) {\n    bytes memory out;\n    bool success;\n    (success, out) = NUMBER_VALIDATORS.staticcall(abi.encodePacked(uint256(block.number)));\n    require(success, \"error calling numberValidatorsInCurrentSet precompile\");\n    return getUint256FromBytes(out, 0);\n  }\n\n  /**\n   * @notice Gets the size of the validator set that must sign the given block number.\n   * @param blockNumber Block number to retrieve the validator set from.\n   * @return Size of the validator set.\n   * @dev This function will be deprecated in L2.\n   */\n  function numberValidatorsInSet(uint256 blockNumber) public view onlyL1 returns (uint256) {\n    bytes memory out;\n    bool success;\n    (success, out) = NUMBER_VALIDATORS.staticcall(abi.encodePacked(blockNumber));\n    require(success, \"error calling numberValidatorsInSet precompile\");\n    return getUint256FromBytes(out, 0);\n  }\n\n  /**\n   * @notice Checks a BLS proof of possession.\n   * @param sender The address signed by the BLS key to generate the proof of possession.\n   * @param blsKey The BLS public key that the validator is using for consensus, should pass proof\n   *   of possession. 48 bytes.\n   * @param blsPop The BLS public key proof-of-possession, which consists of a signature on the\n   *   account address. 96 bytes.\n   * @return True upon success.\n   * @dev This function will be deprecated in L2.\n   */\n  function checkProofOfPossession(\n    address sender,\n    bytes memory blsKey,\n    bytes memory blsPop\n  ) public view onlyL1 returns (bool) {\n    bool success;\n    (success, ) = PROOF_OF_POSSESSION.staticcall(abi.encodePacked(sender, blsKey, blsPop));\n    return success;\n  }\n\n  /**\n   * @notice Parses block number out of header.\n   * @param header RLP encoded header\n   * @return Block number.\n   * @dev This function will be deprecated in L2.\n   */\n  function getBlockNumberFromHeader(bytes memory header) public view onlyL1 returns (uint256) {\n    bytes memory out;\n    bool success;\n    (success, out) = BLOCK_NUMBER_FROM_HEADER.staticcall(abi.encodePacked(header));\n    require(success, \"error calling getBlockNumberFromHeader precompile\");\n    return getUint256FromBytes(out, 0);\n  }\n\n  /**\n   * @notice Computes hash of header.\n   * @param header RLP encoded header\n   * @return Header hash.\n   * @dev This function will be deprecated in L2.\n   */\n  function hashHeader(bytes memory header) public view onlyL1 returns (bytes32) {\n    bytes memory out;\n    bool success;\n    (success, out) = HASH_HEADER.staticcall(abi.encodePacked(header));\n    require(success, \"error calling hashHeader precompile\");\n    return getBytes32FromBytes(out, 0);\n  }\n\n  /**\n   * @notice Gets the parent seal bitmap from the header at the given block number.\n   * @param blockNumber Block number to retrieve. Must be within 4 epochs of the current number.\n   * @return Bitmap parent seal with set bits at indices corresponding to signing validators.\n   * @dev This function will be deprecated in L2.\n   */\n  function getParentSealBitmap(uint256 blockNumber) public view onlyL1 returns (bytes32) {\n    bytes memory out;\n    bool success;\n    (success, out) = GET_PARENT_SEAL_BITMAP.staticcall(abi.encodePacked(blockNumber));\n    require(success, \"error calling getParentSealBitmap precompile\");\n    return getBytes32FromBytes(out, 0);\n  }\n\n  /**\n   * @notice Verifies the BLS signature on the header and returns the seal bitmap.\n   * The validator set used for verification is retrieved based on the parent hash field of the\n   * header.  If the parent hash is not in the blockchain, verification fails.\n   * @param header RLP encoded header\n   * @return Bitmap parent seal with set bits at indices correspoinding to signing validators.\n   * @dev This function will be deprecated in L2.\n   */\n  function getVerifiedSealBitmapFromHeader(\n    bytes memory header\n  ) public view onlyL1 returns (bytes32) {\n    bytes memory out;\n    bool success;\n    (success, out) = GET_VERIFIED_SEAL_BITMAP.staticcall(abi.encodePacked(header));\n    require(success, \"error calling getVerifiedSealBitmapFromHeader precompile\");\n    return getBytes32FromBytes(out, 0);\n  }\n\n  /**\n   * @notice Returns the minimum number of required signers for a given block number.\n   * @dev Computed in celo-blockchain as int(math.Ceil(float64(2*valSet.Size()) / 3))\n   * @dev This function will be deprecated in L2.\n   */\n  function minQuorumSize(uint256 blockNumber) public view onlyL1 returns (uint256) {\n    return numberValidatorsInSet(blockNumber).mul(2).add(2).div(3);\n  }\n\n  /**\n   * @notice Computes byzantine quorum from current validator set size\n   * @return Byzantine quorum of validators.\n   * @dev This function will be deprecated in L2.\n   */\n  function minQuorumSizeInCurrentSet() public view onlyL1 returns (uint256) {\n    return minQuorumSize(block.number);\n  }\n\n  /**\n   * @notice Returns the epoch number at a block.\n   * @param blockNumber Block number where epoch number is calculated.\n   * @param epochSize The epoch size in blocks.\n   * @return Epoch number.\n   */\n  function epochNumberOfBlock(\n    uint256 blockNumber,\n    uint256 epochSize\n  ) internal pure returns (uint256) {\n    // Follows GetEpochNumber from celo-blockchain/blob/master/consensus/istanbul/utils.go\n    uint256 epochNumber = blockNumber / epochSize;\n    if (blockNumber % epochSize == 0) {\n      return epochNumber;\n    } else {\n      return epochNumber.add(1);\n    }\n  }\n\n  /**\n   * @notice Converts bytes to uint256.\n   * @param bs byte[] data\n   * @param start offset into byte data to convert\n   * @return uint256 data\n   */\n  function getUint256FromBytes(bytes memory bs, uint256 start) internal pure returns (uint256) {\n    return uint256(getBytes32FromBytes(bs, start));\n  }\n\n  /**\n   * @notice Converts bytes to bytes32.\n   * @param bs byte[] data\n   * @param start offset into byte data to convert\n   * @return bytes32 data\n   */\n  function getBytes32FromBytes(bytes memory bs, uint256 start) internal pure returns (bytes32) {\n    require(bs.length >= start.add(32), \"slicing out of range\");\n    bytes32 x;\n    assembly {\n      x := mload(add(bs, add(start, 32)))\n    }\n    return x;\n  }\n}\n"},{"file_path":"contracts/governance/interfaces/IValidators.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface IValidators {\n  function registerValidator(bytes calldata) external returns (bool);\n  function registerValidatorNoBls(bytes calldata ecdsaPublicKey) external returns (bool);\n  function deregisterValidator(uint256) external returns (bool);\n  function affiliate(address) external returns (bool);\n  function deaffiliate() external returns (bool);\n  function registerValidatorGroup(uint256) external returns (bool);\n  function deregisterValidatorGroup(uint256) external returns (bool);\n  function addMember(address) external returns (bool);\n  function addFirstMember(address, address, address) external returns (bool);\n  function removeMember(address) external returns (bool);\n  function reorderMember(address, address, address) external returns (bool);\n  function updateCommission() external;\n  function setNextCommissionUpdate(uint256) external;\n  function resetSlashingMultiplier() external;\n\n  // only owner\n  function setCommissionUpdateDelay(uint256) external;\n  function setMaxGroupSize(uint256) external returns (bool);\n  function setMembershipHistoryLength(uint256) external returns (bool);\n  function setGroupLockedGoldRequirements(uint256, uint256) external returns (bool);\n  function setValidatorLockedGoldRequirements(uint256, uint256) external returns (bool);\n  function setSlashingMultiplierResetPeriod(uint256) external;\n\n  // only registered contract\n  function updateEcdsaPublicKey(address, address, bytes calldata) external returns (bool);\n  function mintStableToEpochManager(uint256 amount) external;\n\n  // only slasher\n  function forceDeaffiliateIfValidator(address) external;\n  function halveSlashingMultiplier(address) external;\n\n  // view functions\n  function maxGroupSize() external view returns (uint256);\n  function getCommissionUpdateDelay() external view returns (uint256);\n  function getMembershipHistory(\n    address\n  ) external view returns (uint256[] memory, address[] memory, uint256, uint256);\n  function getAccountLockedGoldRequirement(address) external view returns (uint256);\n  function meetsAccountLockedGoldRequirements(address) external view returns (bool);\n  function getValidator(\n    address account\n  ) external view returns (bytes memory, bytes memory, address, uint256, address);\n  function getValidatorsGroup(address account) external view returns (address affiliation);\n  function getValidatorGroup(\n    address\n  )\n    external\n    view\n    returns (address[] memory, uint256, uint256, uint256, uint256[] memory, uint256, uint256);\n  function getGroupNumMembers(address) external view returns (uint256);\n  function getTopGroupValidators(address, uint256) external view returns (address[] memory);\n  function getTopGroupValidatorsAccounts(address, uint256) external view returns (address[] memory);\n  function getGroupsNumMembers(\n    address[] calldata accounts\n  ) external view returns (uint256[] memory);\n  function getNumRegisteredValidators() external view returns (uint256);\n  function groupMembershipInEpoch(address, uint256, uint256) external view returns (address);\n\n  function getValidatorLockedGoldRequirements() external view returns (uint256, uint256);\n  function getGroupLockedGoldRequirements() external view returns (uint256, uint256);\n  function getRegisteredValidators() external view returns (address[] memory);\n  function getRegisteredValidatorGroups() external view returns (address[] memory);\n  function isValidatorGroup(address) external view returns (bool);\n  function isValidator(address) external view returns (bool);\n  function getValidatorGroupSlashingMultiplier(address) external view returns (uint256);\n  function getMembershipInLastEpoch(address) external view returns (address);\n  function getMembershipInLastEpochFromSigner(address) external view returns (address);\n  function computeEpochReward(\n    address account,\n    uint256 score,\n    uint256 maxPayment\n  ) external view returns (uint256);\n  function getMembershipHistoryLength() external view returns (uint256);\n}\n"},{"file_path":"contracts/common/ExtractFunctionSignature.sol","source_code":"pragma solidity ^0.5.13;\n\nlibrary ExtractFunctionSignature {\n  /**\n   * @notice Extracts the first four bytes of a byte array.\n   * @param input The byte array.\n   * @return The first four bytes of `input`.\n   */\n  function extractFunctionSignature(bytes memory input) internal pure returns (bytes4) {\n    return (bytes4(input[0]) |\n      (bytes4(input[1]) >> 8) |\n      (bytes4(input[2]) >> 16) |\n      (bytes4(input[3]) >> 24));\n  }\n}\n"},{"file_path":"lib/mento-core/contracts/interfaces/IExchange.sol","source_code":"pragma solidity ^0.5.13;\n\ninterface IExchange {\n    function buy(\n        uint256,\n        uint256,\n        bool\n    ) external returns (uint256);\n\n    function sell(\n        uint256,\n        uint256,\n        bool\n    ) external returns (uint256);\n\n    function exchange(\n        uint256,\n        uint256,\n        bool\n    ) external returns (uint256);\n\n    function setUpdateFrequency(uint256) external;\n\n    function getBuyTokenAmount(uint256, bool) external view returns (uint256);\n\n    function getSellTokenAmount(uint256, bool) external view returns (uint256);\n\n    function getBuyAndSellBuckets(bool) external view returns (uint256, uint256);\n}\n"},{"file_path":"contracts/common/FixidityLib.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\n/**\n * @title FixidityLib\n * @author Gadi Guy, Alberto Cuesta Canada\n * @notice This library provides fixed point arithmetic with protection against\n * overflow.\n * All operations are done with uint256 and the operands must have been created\n * with any of the newFrom* functions, which shift the comma digits() to the\n * right and check for limits, or with wrap() which expects a number already\n * in the internal representation of a fraction.\n * When using this library be sure to use maxNewFixed() as the upper limit for\n * creation of fixed point numbers.\n * @dev All contained functions are pure and thus marked internal to be inlined\n * on consuming contracts at compile time for gas efficiency.\n */\nlibrary FixidityLib {\n  struct Fraction {\n    uint256 value;\n  }\n\n  uint256 private constant FIXED1_UINT = 1000000000000000000000000;\n\n  /**\n   * @notice Number of positions that the comma is shifted to the right.\n   */\n  function digits() internal pure returns (uint8) {\n    return 24;\n  }\n\n  /**\n   * @notice This is 1 in the fixed point units used in this library.\n   * @dev Test fixed1() equals 10^digits()\n   * Hardcoded to 24 digits.\n   */\n  function fixed1() internal pure returns (Fraction memory) {\n    return Fraction(FIXED1_UINT);\n  }\n\n  /**\n   * @notice Wrap a uint256 that represents a 24-decimal fraction in a Fraction\n   * struct.\n   * @param x Number that already represents a 24-decimal fraction.\n   * @return A Fraction struct with contents x.\n   */\n  function wrap(uint256 x) internal pure returns (Fraction memory) {\n    return Fraction(x);\n  }\n\n  /**\n   * @notice Unwraps the uint256 inside of a Fraction struct.\n   */\n  function unwrap(Fraction memory x) internal pure returns (uint256) {\n    return x.value;\n  }\n\n  /**\n   * @notice The amount of decimals lost on each multiplication operand.\n   * @dev Test mulPrecision() equals sqrt(fixed1)\n   */\n  function mulPrecision() internal pure returns (uint256) {\n    return 1000000000000;\n  }\n\n  /**\n   * @notice Maximum value that can be converted to fixed point. Optimize for deployment.\n   * @dev\n   * Test maxNewFixed() equals maxUint256() / fixed1()\n   */\n  function maxNewFixed() internal pure returns (uint256) {\n    return 115792089237316195423570985008687907853269984665640564;\n  }\n\n  /**\n   * @notice Converts a uint256 to fixed point Fraction\n   * @dev Test newFixed(0) returns 0\n   * Test newFixed(1) returns fixed1()\n   * Test newFixed(maxNewFixed()) returns maxNewFixed() * fixed1()\n   * Test newFixed(maxNewFixed()+1) fails\n   */\n  function newFixed(uint256 x) internal pure returns (Fraction memory) {\n    require(x <= maxNewFixed(), \"can't create fixidity number larger than maxNewFixed()\");\n    return Fraction(x * FIXED1_UINT);\n  }\n\n  /**\n   * @notice Converts a uint256 in the fixed point representation of this\n   * library to a non decimal. All decimal digits will be truncated.\n   */\n  function fromFixed(Fraction memory x) internal pure returns (uint256) {\n    return x.value / FIXED1_UINT;\n  }\n\n  /**\n   * @notice Converts two uint256 representing a fraction to fixed point units,\n   * equivalent to multiplying dividend and divisor by 10^digits().\n   * @param numerator numerator must be <= maxNewFixed()\n   * @param denominator denominator must be <= maxNewFixed() and denominator can't be 0\n   * @dev\n   * Test newFixedFraction(1,0) fails\n   * Test newFixedFraction(0,1) returns 0\n   * Test newFixedFraction(1,1) returns fixed1()\n   * Test newFixedFraction(1,fixed1()) returns 1\n   */\n  function newFixedFraction(\n    uint256 numerator,\n    uint256 denominator\n  ) internal pure returns (Fraction memory) {\n    Fraction memory convertedNumerator = newFixed(numerator);\n    Fraction memory convertedDenominator = newFixed(denominator);\n    return divide(convertedNumerator, convertedDenominator);\n  }\n\n  /**\n   * @notice Returns the integer part of a fixed point number.\n   * @dev\n   * Test integer(0) returns 0\n   * Test integer(fixed1()) returns fixed1()\n   * Test integer(newFixed(maxNewFixed())) returns maxNewFixed()*fixed1()\n   */\n  function integer(Fraction memory x) internal pure returns (Fraction memory) {\n    return Fraction((x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow\n  }\n\n  /**\n   * @notice Returns the fractional part of a fixed point number.\n   * In the case of a negative number the fractional is also negative.\n   * @dev\n   * Test fractional(0) returns 0\n   * Test fractional(fixed1()) returns 0\n   * Test fractional(fixed1()-1) returns 10^24-1\n   */\n  function fractional(Fraction memory x) internal pure returns (Fraction memory) {\n    return Fraction(x.value - (x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow\n  }\n\n  /**\n   * @notice x+y.\n   * @dev The maximum value that can be safely used as an addition operator is defined as\n   * maxFixedAdd = maxUint256()-1 / 2, or\n   * 57896044618658097711785492504343953926634992332820282019728792003956564819967.\n   * Test add(maxFixedAdd,maxFixedAdd) equals maxFixedAdd + maxFixedAdd\n   * Test add(maxFixedAdd+1,maxFixedAdd+1) throws\n   */\n  function add(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {\n    uint256 z = x.value + y.value;\n    require(z >= x.value, \"add overflow detected\");\n    return Fraction(z);\n  }\n\n  /**\n   * @notice x-y.\n   * @dev\n   * Test subtract(6, 10) fails\n   */\n  function subtract(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {\n    require(x.value >= y.value, \"substraction underflow detected\");\n    return Fraction(x.value - y.value);\n  }\n\n  /**\n   * @notice x*y. If any of the operators is higher than the max multiplier value it\n   * might overflow.\n   * @dev The maximum value that can be safely used as a multiplication operator\n   * (maxFixedMul) is calculated as sqrt(maxUint256()*fixed1()),\n   * or 340282366920938463463374607431768211455999999999999\n   * Test multiply(0,0) returns 0\n   * Test multiply(maxFixedMul,0) returns 0\n   * Test multiply(0,maxFixedMul) returns 0\n   * Test multiply(fixed1()/mulPrecision(),fixed1()*mulPrecision()) returns fixed1()\n   * Test multiply(maxFixedMul,maxFixedMul) is around maxUint256()\n   * Test multiply(maxFixedMul+1,maxFixedMul+1) fails\n   */\n  function multiply(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {\n    if (x.value == 0 || y.value == 0) return Fraction(0);\n    if (y.value == FIXED1_UINT) return x;\n    if (x.value == FIXED1_UINT) return y;\n\n    // Separate into integer and fractional parts\n    // x = x1 + x2, y = y1 + y2\n    uint256 x1 = integer(x).value / FIXED1_UINT;\n    uint256 x2 = fractional(x).value;\n    uint256 y1 = integer(y).value / FIXED1_UINT;\n    uint256 y2 = fractional(y).value;\n\n    // (x1 + x2) * (y1 + y2) = (x1 * y1) + (x1 * y2) + (x2 * y1) + (x2 * y2)\n    uint256 x1y1 = x1 * y1;\n    if (x1 != 0) require(x1y1 / x1 == y1, \"overflow x1y1 detected\");\n\n    // x1y1 needs to be multiplied back by fixed1\n    // solium-disable-next-line mixedcase\n    uint256 fixed_x1y1 = x1y1 * FIXED1_UINT;\n    if (x1y1 != 0) require(fixed_x1y1 / x1y1 == FIXED1_UINT, \"overflow x1y1 * fixed1 detected\");\n    x1y1 = fixed_x1y1;\n\n    uint256 x2y1 = x2 * y1;\n    if (x2 != 0) require(x2y1 / x2 == y1, \"overflow x2y1 detected\");\n\n    uint256 x1y2 = x1 * y2;\n    if (x1 != 0) require(x1y2 / x1 == y2, \"overflow x1y2 detected\");\n\n    x2 = x2 / mulPrecision();\n    y2 = y2 / mulPrecision();\n    uint256 x2y2 = x2 * y2;\n    if (x2 != 0) require(x2y2 / x2 == y2, \"overflow x2y2 detected\");\n\n    // result = fixed1() * x1 * y1 + x1 * y2 + x2 * y1 + x2 * y2 / fixed1();\n    Fraction memory result = Fraction(x1y1);\n    result = add(result, Fraction(x2y1)); // Add checks for overflow\n    result = add(result, Fraction(x1y2)); // Add checks for overflow\n    result = add(result, Fraction(x2y2)); // Add checks for overflow\n    return result;\n  }\n\n  /**\n   * @notice 1/x\n   * @dev\n   * Test reciprocal(0) fails\n   * Test reciprocal(fixed1()) returns fixed1()\n   * Test reciprocal(fixed1()*fixed1()) returns 1 // Testing how the fractional is truncated\n   * Test reciprocal(1+fixed1()*fixed1()) returns 0 // Testing how the fractional is truncated\n   * Test reciprocal(newFixedFraction(1, 1e24)) returns newFixed(1e24)\n   */\n  function reciprocal(Fraction memory x) internal pure returns (Fraction memory) {\n    require(x.value != 0, \"can't call reciprocal(0)\");\n    return Fraction((FIXED1_UINT * FIXED1_UINT) / x.value); // Can't overflow\n  }\n\n  /**\n   * @notice x/y. If the dividend is higher than the max dividend value, it\n   * might overflow. You can use multiply(x,reciprocal(y)) instead.\n   * @dev The maximum value that can be safely used as a dividend (maxNewFixed) is defined as\n   * divide(maxNewFixed,newFixedFraction(1,fixed1())) is around maxUint256().\n   * This yields the value 115792089237316195423570985008687907853269984665640564.\n   * Test maxNewFixed equals maxUint256()/fixed1()\n   * Test divide(maxNewFixed,1) equals maxNewFixed*(fixed1)\n   * Test divide(maxNewFixed+1,multiply(mulPrecision(),mulPrecision())) throws\n   * Test divide(fixed1(),0) fails\n   * Test divide(maxNewFixed,1) = maxNewFixed*(10^digits())\n   * Test divide(maxNewFixed+1,1) throws\n   */\n  function divide(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {\n    require(y.value != 0, \"can't divide by 0\");\n    uint256 X = x.value * FIXED1_UINT;\n    require(X / FIXED1_UINT == x.value, \"overflow at divide\");\n    return Fraction(X / y.value);\n  }\n\n  /**\n   * @notice x > y\n   */\n  function gt(Fraction memory x, Fraction memory y) internal pure returns (bool) {\n    return x.value > y.value;\n  }\n\n  /**\n   * @notice x >= y\n   */\n  function gte(Fraction memory x, Fraction memory y) internal pure returns (bool) {\n    return x.value >= y.value;\n  }\n\n  /**\n   * @notice x < y\n   */\n  function lt(Fraction memory x, Fraction memory y) internal pure returns (bool) {\n    return x.value < y.value;\n  }\n\n  /**\n   * @notice x <= y\n   */\n  function lte(Fraction memory x, Fraction memory y) internal pure returns (bool) {\n    return x.value <= y.value;\n  }\n\n  /**\n   * @notice x == y\n   */\n  function equals(Fraction memory x, Fraction memory y) internal pure returns (bool) {\n    return x.value == y.value;\n  }\n\n  /**\n   * @notice x <= 1\n   */\n  function isProperFraction(Fraction memory x) internal pure returns (bool) {\n    return lte(x, fixed1());\n  }\n}\n"},{"file_path":"contracts/governance/interfaces/ILockedGold.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface ILockedGold {\n  function lock() external payable;\n  function incrementNonvotingAccountBalance(address, uint256) external;\n  function decrementNonvotingAccountBalance(address, uint256) external;\n\n  function unlock(uint256) external;\n  function relock(uint256, uint256) external;\n  function withdraw(uint256) external;\n  function slash(\n    address account,\n    uint256 penalty,\n    address reporter,\n    uint256 reward,\n    address[] calldata lessers,\n    address[] calldata greaters,\n    uint256[] calldata indices\n  ) external;\n  function addSlasher(string calldata slasherIdentifier) external;\n\n  function getAccountTotalLockedGold(address) external view returns (uint256);\n  function getTotalLockedGold() external view returns (uint256);\n  function getPendingWithdrawals(\n    address\n  ) external view returns (uint256[] memory, uint256[] memory);\n  function getPendingWithdrawal(\n    address account,\n    uint256 index\n  ) external view returns (uint256, uint256);\n  function getTotalPendingWithdrawals(address) external view returns (uint256);\n  function isSlasher(address) external view returns (bool);\n\n  function getAccountTotalDelegatedFraction(address account) external view returns (uint256);\n\n  function getAccountTotalGovernanceVotingPower(address account) external view returns (uint256);\n  function unlockingPeriod() external view returns (uint256);\n  function getAccountNonvotingLockedGold(address account) external view returns (uint256);\n}\n"},{"file_path":"lib/mento-core/contracts/interfaces/IStableToken.sol","source_code":"pragma solidity ^0.5.13;\n\n/**\n * @title This interface describes the functions specific to Celo Stable Tokens, and in the\n * absence of interface inheritance is intended as a companion to IERC20.sol and ICeloToken.sol.\n */\ninterface IStableToken {\n    function mint(address, uint256) external returns (bool);\n\n    function burn(uint256) external returns (bool);\n\n    function setInflationParameters(uint256, uint256) external;\n\n    function valueToUnits(uint256) external view returns (uint256);\n\n    function unitsToValue(uint256) external view returns (uint256);\n\n    function getInflationParameters()\n        external\n        view\n        returns (\n            uint256,\n            uint256,\n            uint256,\n            uint256\n        );\n\n    // NOTE: duplicated with IERC20.sol, remove once interface inheritance is supported.\n    function balanceOf(address) external view returns (uint256);\n}\n"},{"file_path":"contracts/common/interfaces/ICeloVersionedContract.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface ICeloVersionedContract {\n  /**\n   * @notice Returns the storage, major, minor, and patch version of the contract.\n   * @return Storage version of the contract.\n   * @return Major version of the contract.\n   * @return Minor version of the contract.\n   * @return Patch version of the contract.\n   */\n  function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256);\n}\n"},{"file_path":"contracts/common/libraries/ReentrancyGuard.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.8.20;\n\n/**\n * @title Helps contracts guard against reentrancy attacks.\n * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io>\n * @dev If you mark a function `nonReentrant`, you should also\n * mark it `external`.\n */\ncontract ReentrancyGuard {\n  /// @dev counter to allow mutex lock with only one SSTORE operation\n  uint256 private _guardCounter;\n\n  /**\n   * @dev Prevents a contract from calling itself, directly or indirectly.\n   * Calling a `nonReentrant` function from another `nonReentrant`\n   * function is not supported. It is possible to prevent this from happening\n   * by making the `nonReentrant` function external, and make it call a\n   * `private` function that does the actual work.\n   */\n  modifier nonReentrant() {\n    _guardCounter += 1;\n    uint256 localCounter = _guardCounter;\n    _;\n    require(localCounter == _guardCounter, \"reentrant call\");\n  }\n\n  constructor() public {\n    // The counter starts at one to prevent changing it from zero to a non-zero\n    // value, which is a more expensive operation.\n    _guardCounter = 1;\n  }\n}\n"},{"file_path":"contracts/stability/interfaces/ISortedOracles.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface ISortedOracles {\n  function addOracle(address, address) external;\n  function removeOracle(address, address, uint256) external;\n  function report(address, uint256, address, address) external;\n  function removeExpiredReports(address, uint256) external;\n  function isOldestReportExpired(address token) external view returns (bool, address);\n  function numRates(address) external view returns (uint256);\n  function medianRate(address) external view returns (uint256, uint256);\n  function numTimestamps(address) external view returns (uint256);\n  function medianTimestamp(address) external view returns (uint256);\n}\n"},{"file_path":"contracts/governance/interfaces/ILockedCelo.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface ILockedCelo {\n  function lock() external payable;\n  function incrementNonvotingAccountBalance(address, uint256) external;\n  function decrementNonvotingAccountBalance(address, uint256) external;\n\n  function unlock(uint256) external;\n  function relock(uint256, uint256) external;\n  function withdraw(uint256) external;\n  function slash(\n    address account,\n    uint256 penalty,\n    address reporter,\n    uint256 reward,\n    address[] calldata lessers,\n    address[] calldata greaters,\n    uint256[] calldata indices\n  ) external;\n  function addSlasher(string calldata slasherIdentifier) external;\n\n  function getAccountNonvotingLockedGold(address account) external view returns (uint256);\n  function getAccountTotalLockedCelo(address) external view returns (uint256);\n  function getTotalLockedCelo() external view returns (uint256);\n  function getPendingWithdrawals(\n    address\n  ) external view returns (uint256[] memory, uint256[] memory);\n  function getPendingWithdrawal(\n    address account,\n    uint256 index\n  ) external view returns (uint256, uint256);\n  function getTotalPendingWithdrawals(address) external view returns (uint256);\n  function isSlasher(address) external view returns (bool);\n\n  function getAccountTotalDelegatedFraction(address account) external view returns (uint256);\n\n  function getAccountTotalGovernanceVotingPower(address account) external view returns (uint256);\n  function unlockingPeriod() external view returns (uint256);\n  function getAccountNonvotingLockedCelo(address account) external view returns (uint256);\n\n  function getAccountTotalLockedGold(address account) external view returns (uint256);\n}\n"},{"file_path":"contracts/common/PrecompilesOverride.sol","source_code":"pragma solidity ^0.5.13;\n\nimport \"./interfaces/ICeloVersionedContract.sol\";\nimport \"../../contracts-0.8/common/IsL2Check.sol\";\nimport \"./UsingRegistry.sol\";\n\nimport \"./UsingPrecompiles.sol\";\n\n/**\n * @title PrecompilesOverride Contract\n * @notice This contract allows for a smoother transition from L1 to L2\n * by abstracting away the usingPrecompile contract, and taking care of the L1 to L2 switching logic.\n **/\ncontract PrecompilesOverride is UsingPrecompiles, UsingRegistry {\n  /**\n   * @notice Returns the epoch number at a block.\n   * @param blockNumber Block number where epoch number is calculated.\n   * @return Epoch number.\n   */\n  function getEpochNumberOfBlock(uint256 blockNumber) public view returns (uint256) {\n    if (isL2()) {\n      return getEpochManager().getEpochNumberOfBlock(blockNumber);\n    } else {\n      return epochNumberOfBlock(blockNumber, getEpochSize());\n    }\n  }\n\n  /**\n   * @notice Returns the epoch number at a block.\n   * @return Current epoch number.\n   */\n  function getEpochNumber() public view returns (uint256) {\n    return getEpochNumberOfBlock(block.number);\n  }\n\n  /**\n   * @notice Gets a validator signer address from the current validator set.\n   * @param index Index of requested validator in the validator set.\n   * @return Address of validator signer at the requested index.\n   */\n  function validatorSignerAddressFromCurrentSet(uint256 index) public view returns (address) {\n    if (isL2()) {\n      return getEpochManager().getElectedSignerByIndex(index);\n    } else {\n      return super.validatorSignerAddressFromCurrentSet(index);\n    }\n  }\n\n  /**\n   * @notice Gets a validator address from the current validator set.\n   * @param index Index of requested validator in the validator set.\n   * @return Address of validator at the requested index.\n   */\n  function validatorAddressFromCurrentSet(uint256 index) public view onlyL2 returns (address) {\n    return getEpochManager().getElectedAccountByIndex(index);\n  }\n\n  /**\n   * @notice Gets the size of the current elected validator set.\n   * @return Size of the current elected validator set.\n   */\n  function numberValidatorsInCurrentSet() public view returns (uint256) {\n    if (isL2()) {\n      return getEpochManager().numberOfElectedInCurrentSet();\n    } else {\n      return super.numberValidatorsInCurrentSet();\n    }\n  }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/ownership/Ownable.sol","source_code":"pragma solidity ^0.5.0;\n\nimport \"../GSN/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor () internal {\n        address msgSender = _msgSender();\n        _owner = msgSender;\n        emit OwnershipTransferred(address(0), msgSender);\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(isOwner(), \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    /**\n     * @dev Returns true if the caller is the current owner.\n     */\n    function isOwner() public view returns (bool) {\n        return _msgSender() == _owner;\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public onlyOwner {\n        emit OwnershipTransferred(_owner, address(0));\n        _owner = address(0);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public onlyOwner {\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     */\n    function _transferOwnership(address newOwner) internal {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        emit OwnershipTransferred(_owner, newOwner);\n        _owner = newOwner;\n    }\n}\n"},{"file_path":"contracts/governance/interfaces/IElection.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface IElection {\n  function vote(\n    address group,\n    uint256 value,\n    address lesser,\n    address greater\n  ) external returns (bool);\n  function activate(address group) external returns (bool);\n  function revokeActive(\n    address group,\n    uint256 value,\n    address lesser,\n    address greater,\n    uint256 index\n  ) external returns (bool);\n  function revokeAllActive(\n    address group,\n    address lesser,\n    address greater,\n    uint256 index\n  ) external returns (bool);\n  function revokePending(\n    address group,\n    uint256 value,\n    address lesser,\n    address greater,\n    uint256 index\n  ) external returns (bool);\n  function markGroupIneligible(address group) external;\n  function markGroupEligible(address group, address lesser, address greater) external;\n  function allowedToVoteOverMaxNumberOfGroups(address account) external returns (bool);\n  function forceDecrementVotes(\n    address account,\n    uint256 value,\n    address[] calldata lessers,\n    address[] calldata greaters,\n    uint256[] calldata indices\n  ) external returns (uint256);\n  function setAllowedToVoteOverMaxNumberOfGroups(bool flag) external;\n\n  // only owner\n  function setElectableValidators(uint256 min, uint256 max) external returns (bool);\n  function setMaxNumGroupsVotedFor(uint256 _maxNumGroupsVotedFor) external returns (bool);\n  function setElectabilityThreshold(uint256 threshold) external returns (bool);\n\n  // only VM\n  function distributeEpochRewards(\n    address group,\n    uint256 value,\n    address lesser,\n    address greater\n  ) external;\n\n  // view functions\n  function electValidatorSigners() external view returns (address[] memory);\n  function electValidatorAccounts() external view returns (address[] memory);\n  function electNValidatorSigners(\n    uint256 minElectableValidators,\n    uint256 maxElectableValidators\n  ) external view returns (address[] memory);\n  function electNValidatorAccounts(\n    uint256 minElectableValidators,\n    uint256 maxElectableValidators\n  ) external view returns (address[] memory);\n  function getElectableValidators() external view returns (uint256, uint256);\n  function getElectabilityThreshold() external view returns (uint256);\n  function getNumVotesReceivable(address group) external view returns (uint256);\n  function getTotalVotes() external view returns (uint256);\n  function getActiveVotes() external view returns (uint256);\n  function getTotalVotesByAccount(address account) external view returns (uint256);\n  function getPendingVotesForGroupByAccount(\n    address group,\n    address account\n  ) external view returns (uint256);\n  function getActiveVotesForGroupByAccount(\n    address group,\n    address account\n  ) external view returns (uint256);\n  function getTotalVotesForGroupByAccount(\n    address group,\n    address account\n  ) external view returns (uint256);\n  function getActiveVoteUnitsForGroupByAccount(\n    address group,\n    address account\n  ) external view returns (uint256);\n  function getTotalVotesForGroup(address group) external view returns (uint256);\n  function getActiveVotesForGroup(address group) external view returns (uint256);\n  function getPendingVotesForGroup(address group) external view returns (uint256);\n  function getGroupEligibility(address group) external view returns (bool);\n  function getGroupEpochRewardsBasedOnScore(\n    address group,\n    uint256 totalEpochRewards,\n    uint256 groupScore\n  ) external view returns (uint256);\n  function getGroupsVotedForByAccount(address account) external view returns (address[] memory);\n  function getEligibleValidatorGroups() external view returns (address[] memory);\n  function getTotalVotesForEligibleValidatorGroups()\n    external\n    view\n    returns (address[] memory, uint256[] memory);\n  function getCurrentValidatorSigners() external view returns (address[] memory);\n  function canReceiveVotes(address group, uint256 value) external view returns (bool);\n  function hasActivatablePendingVotes(address account, address group) external view returns (bool);\n  function validatorSignerAddressFromCurrentSet(uint256 index) external view returns (address);\n  function numberValidatorsInCurrentSet() external view returns (uint256);\n  function owner() external view returns (address);\n}\n"},{"file_path":"contracts/common/interfaces/IEpochManager.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface IEpochManager {\n  function initializeSystem(\n    uint256 firstEpochNumber,\n    uint256 firstEpochBlock,\n    address[] calldata firstElected\n  ) external;\n  function startNextEpochProcess() external;\n  function finishNextEpochProcess(\n    address[] calldata groups,\n    address[] calldata lessers,\n    address[] calldata greaters\n  ) external;\n  function setToProcessGroups() external;\n  function processGroup(address group, address lesser, address greater) external;\n  function sendValidatorPayment(address) external;\n  function getCurrentEpoch() external view returns (uint256, uint256, uint256, uint256);\n  function getEpochByNumber(\n    uint256 epochNumber\n  ) external view returns (uint256, uint256, uint256, uint256);\n  function getEpochByBlockNumber(\n    uint256 blockNumber\n  ) external view returns (uint256, uint256, uint256, uint256);\n  function getEpochNumberOfBlock(uint256) external view returns (uint256);\n  function getCurrentEpochNumber() external view returns (uint256);\n  function numberOfElectedInCurrentSet() external view returns (uint256);\n  function getElectedAccounts() external view returns (address[] memory);\n  function getElectedAccountByIndex(uint256 index) external view returns (address);\n  function getElectedSigners() external view returns (address[] memory);\n  function getElectedSignerByIndex(uint256 index) external view returns (address);\n  function epochDuration() external view returns (uint256);\n  function firstKnownEpoch() external view returns (uint256);\n  function getEpochProcessingState()\n    external\n    view\n    returns (uint256, uint256, uint256, uint256, uint256);\n  function systemAlreadyInitialized() external view returns (bool);\n  function isBlocked() external view returns (bool);\n  function isTimeForNextEpoch() external view returns (bool);\n  function isOnEpochProcess() external view returns (bool);\n  function getFirstBlockAtEpoch(uint256) external view returns (uint256);\n  function getLastBlockAtEpoch(uint256) external view returns (uint256);\n}\n"},{"file_path":"contracts/common/interfaces/IAccounts.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface IAccounts {\n  function setAccountDataEncryptionKey(bytes calldata) external;\n  function setMetadataURL(string calldata) external;\n  function setName(string calldata) external;\n  function setWalletAddress(address, uint8, bytes32, bytes32) external;\n  function setAccount(string calldata, bytes calldata, address, uint8, bytes32, bytes32) external;\n\n  function authorizeVoteSigner(address, uint8, bytes32, bytes32) external;\n  function authorizeValidatorSigner(address, uint8, bytes32, bytes32) external;\n  function authorizeValidatorSignerWithPublicKey(\n    address,\n    uint8,\n    bytes32,\n    bytes32,\n    bytes calldata\n  ) external;\n  function authorizeAttestationSigner(address, uint8, bytes32, bytes32) external;\n  function setEip712DomainSeparator() external;\n  function createAccount() external returns (bool);\n\n  function setPaymentDelegation(address, uint256) external;\n\n  function isAccount(address) external view returns (bool);\n  function voteSignerToAccount(address) external view returns (address);\n  function validatorSignerToAccount(address) external view returns (address);\n  function attestationSignerToAccount(address) external view returns (address);\n  function signerToAccount(address) external view returns (address);\n  function getAttestationSigner(address) external view returns (address);\n  function getValidatorSigner(address) external view returns (address);\n  function getVoteSigner(address) external view returns (address);\n  function hasAuthorizedVoteSigner(address) external view returns (bool);\n  function hasAuthorizedValidatorSigner(address) external view returns (bool);\n  function hasAuthorizedAttestationSigner(address) external view returns (bool);\n\n  function batchGetMetadataURL(\n    address[] calldata\n  ) external view returns (uint256[] memory, bytes memory);\n\n  function getDataEncryptionKey(address) external view returns (bytes memory);\n  function getWalletAddress(address) external view returns (address);\n  function getMetadataURL(address) external view returns (string memory);\n\n  function getName(address) external view returns (string memory);\n\n  function getPaymentDelegation(address) external view returns (address, uint256);\n  function isSigner(address, address, bytes32) external view returns (bool);\n}\n"},{"file_path":"contracts/identity/interfaces/IAttestations.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface IAttestations {\n  function revoke(bytes32, uint256) external;\n  function withdraw(address) external;\n\n  // only owner\n  function setAttestationRequestFee(address, uint256) external;\n  function setAttestationExpiryBlocks(uint256) external;\n  function setSelectIssuersWaitBlocks(uint256) external;\n  function setMaxAttestations(uint256) external;\n\n  // view functions\n  function getUnselectedRequest(bytes32, address) external view returns (uint32, uint32, address);\n  function getAttestationIssuers(bytes32, address) external view returns (address[] memory);\n  function getAttestationStats(bytes32, address) external view returns (uint32, uint32);\n  function batchGetAttestationStats(\n    bytes32[] calldata\n  ) external view returns (uint256[] memory, address[] memory, uint64[] memory, uint64[] memory);\n  function getAttestationState(\n    bytes32,\n    address,\n    address\n  ) external view returns (uint8, uint32, address);\n  function getCompletableAttestations(\n    bytes32,\n    address\n  ) external view returns (uint32[] memory, address[] memory, uint256[] memory, bytes memory);\n  function getAttestationRequestFee(address) external view returns (uint256);\n  function getMaxAttestations() external view returns (uint256);\n  function validateAttestationCode(\n    bytes32,\n    address,\n    uint8,\n    bytes32,\n    bytes32\n  ) external view returns (address);\n  function lookupAccountsForIdentifier(bytes32) external view returns (address[] memory);\n  function requireNAttestationsRequested(bytes32, address, uint32) external view;\n}\n"},{"file_path":"contracts/common/Initializable.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\n/**\n * @title Used with proxied contracts that have an `initialize` function.\n * @notice Ensures the `initialize` function:\n *         - gets called only once\n *         - cannot be called on the logic contract.\n */\ncontract Initializable {\n  bool public initialized;\n\n  /**\n   * @notice Ensures the initializer function cannot be called more than once.\n   */\n  modifier initializer() {\n    require(!initialized, \"contract already initialized\");\n    initialized = true;\n    _;\n  }\n\n  /**\n   * @notice By default, ensures that the `initialize` function cannot be called\n   * on the logic contract.\n   * @param testingDeployment When set to true, allows the `initialize` function\n   * to be called, which is useful in testing when not setting up with a Proxy.\n   */\n  constructor(bool testingDeployment) public {\n    if (!testingDeployment) {\n      initialized = true;\n    }\n  }\n}\n"},{"file_path":"contracts/common/UsingRegistry.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity ^0.5.13;\n\nimport \"openzeppelin-solidity/contracts/ownership/Ownable.sol\";\nimport \"openzeppelin-solidity/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./interfaces/IAccounts.sol\";\nimport \"./interfaces/IEpochManager.sol\";\nimport \"./interfaces/IFeeCurrencyWhitelist.sol\";\nimport \"./interfaces/IFreezer.sol\";\nimport \"./interfaces/IRegistry.sol\";\nimport \"./interfaces/ICeloUnreleasedTreasury.sol\";\n\nimport \"../governance/interfaces/IElection.sol\";\nimport \"../governance/interfaces/IEpochRewards.sol\";\nimport \"../governance/interfaces/IGovernance.sol\";\nimport \"../governance/interfaces/ILockedGold.sol\";\nimport \"../governance/interfaces/ILockedCelo.sol\";\nimport \"../governance/interfaces/IValidators.sol\";\n\nimport \"../identity/interfaces/IRandom.sol\";\nimport \"../identity/interfaces/IAttestations.sol\";\n\nimport \"../../lib/mento-core/contracts/interfaces/IExchange.sol\";\nimport \"../../lib/mento-core/contracts/interfaces/IReserve.sol\";\nimport \"../../lib/mento-core/contracts/interfaces/IStableToken.sol\";\nimport \"../stability/interfaces/ISortedOracles.sol\";\n\ncontract UsingRegistry is Ownable {\n  // solhint-disable state-visibility\n  bytes32 constant ACCOUNTS_REGISTRY_ID = keccak256(abi.encodePacked(\"Accounts\"));\n  bytes32 constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked(\"Attestations\"));\n  bytes32 constant DOWNTIME_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked(\"DowntimeSlasher\"));\n  bytes32 constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID =\n    keccak256(abi.encodePacked(\"DoubleSigningSlasher\"));\n  bytes32 constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked(\"Election\"));\n  bytes32 constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked(\"Exchange\"));\n  bytes32 constant FEE_CURRENCY_WHITELIST_REGISTRY_ID =\n    keccak256(abi.encodePacked(\"FeeCurrencyWhitelist\"));\n  bytes32 constant FREEZER_REGISTRY_ID = keccak256(abi.encodePacked(\"Freezer\"));\n  bytes32 constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked(\"GoldToken\"));\n  bytes32 constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked(\"Governance\"));\n  bytes32 constant GOVERNANCE_SLASHER_REGISTRY_ID =\n    keccak256(abi.encodePacked(\"GovernanceSlasher\"));\n  bytes32 constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked(\"LockedGold\"));\n  bytes32 constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked(\"Reserve\"));\n  bytes32 constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked(\"Random\"));\n  bytes32 constant SORTED_ORACLES_REGISTRY_ID = keccak256(abi.encodePacked(\"SortedOracles\"));\n  bytes32 constant STABLE_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked(\"StableToken\"));\n  bytes32 constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked(\"Validators\"));\n\n  bytes32 constant CELO_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked(\"CeloToken\"));\n  bytes32 constant LOCKED_CELO_REGISTRY_ID = keccak256(abi.encodePacked(\"LockedCelo\"));\n  bytes32 constant CELO_UNRELEASED_TREASURY_REGISTRY_ID =\n    keccak256(abi.encodePacked(\"CeloUnreleasedTreasury\"));\n  bytes32 constant EPOCH_REWARDS_REGISTRY_ID = keccak256(abi.encodePacked(\"EpochRewards\"));\n  bytes32 constant EPOCH_MANAGER_ENABLER_REGISTRY_ID =\n    keccak256(abi.encodePacked(\"EpochManagerEnabler\"));\n  bytes32 constant EPOCH_MANAGER_REGISTRY_ID = keccak256(abi.encodePacked(\"EpochManager\"));\n  // solhint-enable state-visibility\n\n  IRegistry public registry;\n\n  event RegistrySet(address indexed registryAddress);\n\n  modifier onlyRegisteredContract(bytes32 identifierHash) {\n    require(registry.getAddressForOrDie(identifierHash) == msg.sender, \"only registered contract\");\n    _;\n  }\n\n  modifier onlyRegisteredContracts(bytes32[] memory identifierHashes) {\n    require(registry.isOneOf(identifierHashes, msg.sender), \"only registered contracts\");\n    _;\n  }\n\n  /**\n   * @notice Updates the address pointing to a Registry contract.\n   * @param registryAddress The address of a registry contract for routing to other contracts.\n   */\n  function setRegistry(address registryAddress) public onlyOwner {\n    require(registryAddress != address(0), \"Cannot register the null address\");\n    registry = IRegistry(registryAddress);\n    emit RegistrySet(registryAddress);\n  }\n\n  function getAccounts() internal view returns (IAccounts) {\n    return IAccounts(registry.getAddressForOrDie(ACCOUNTS_REGISTRY_ID));\n  }\n\n  function getAttestations() internal view returns (IAttestations) {\n    return IAttestations(registry.getAddressForOrDie(ATTESTATIONS_REGISTRY_ID));\n  }\n\n  function getElection() internal view returns (IElection) {\n    return IElection(registry.getAddressForOrDie(ELECTION_REGISTRY_ID));\n  }\n\n  function getExchange() internal view returns (IExchange) {\n    return IExchange(registry.getAddressForOrDie(EXCHANGE_REGISTRY_ID));\n  }\n\n  function getFeeCurrencyWhitelistRegistry() internal view returns (IFeeCurrencyWhitelist) {\n    return IFeeCurrencyWhitelist(registry.getAddressForOrDie(FEE_CURRENCY_WHITELIST_REGISTRY_ID));\n  }\n\n  function getFreezer() internal view returns (IFreezer) {\n    return IFreezer(registry.getAddressForOrDie(FREEZER_REGISTRY_ID));\n  }\n\n  function getGoldToken() internal view returns (IERC20) {\n    return IERC20(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID));\n  }\n  function getCeloToken() internal view returns (IERC20) {\n    return IERC20(registry.getAddressForOrDie(CELO_TOKEN_REGISTRY_ID));\n  }\n\n  function getGovernance() internal view returns (IGovernance) {\n    return IGovernance(registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID));\n  }\n\n  function getLockedGold() internal view returns (ILockedGold) {\n    return ILockedGold(registry.getAddressForOrDie(LOCKED_GOLD_REGISTRY_ID));\n  }\n  function getLockedCelo() internal view returns (ILockedCelo) {\n    return ILockedCelo(registry.getAddressForOrDie(LOCKED_CELO_REGISTRY_ID));\n  }\n\n  function getRandom() internal view returns (IRandom) {\n    return IRandom(registry.getAddressForOrDie(RANDOM_REGISTRY_ID));\n  }\n\n  function getReserve() internal view returns (IReserve) {\n    return IReserve(registry.getAddressForOrDie(RESERVE_REGISTRY_ID));\n  }\n\n  function getSortedOracles() internal view returns (ISortedOracles) {\n    return ISortedOracles(registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID));\n  }\n\n  function getStableToken() internal view returns (IStableToken) {\n    return IStableToken(registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID));\n  }\n\n  function getValidators() internal view returns (IValidators) {\n    return IValidators(registry.getAddressForOrDie(VALIDATORS_REGISTRY_ID));\n  }\n\n  function getCeloUnreleasedTreasury() internal view returns (ICeloUnreleasedTreasury) {\n    return\n      ICeloUnreleasedTreasury(registry.getAddressForOrDie(CELO_UNRELEASED_TREASURY_REGISTRY_ID));\n  }\n\n  function getEpochRewards() internal view returns (IEpochRewards) {\n    return IEpochRewards(registry.getAddressForOrDie(EPOCH_REWARDS_REGISTRY_ID));\n  }\n\n  function getEpochManager() internal view returns (IEpochManager) {\n    return IEpochManager(registry.getAddressForOrDie(EPOCH_MANAGER_REGISTRY_ID));\n  }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/math/SafeMath.sol","source_code":"pragma solidity ^0.5.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 c = a + b;\n        require(c >= a, \"SafeMath: addition overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        return sub(a, b, \"SafeMath: subtraction overflow\");\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     * - Subtraction cannot overflow.\n     *\n     * _Available since v2.4.0._\n     */\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b <= a, errorMessage);\n        uint256 c = a - b;\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n        // benefit is lost if 'b' is also tested.\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n        if (a == 0) {\n            return 0;\n        }\n\n        uint256 c = a * b;\n        require(c / a == b, \"SafeMath: multiplication overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers. Reverts on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        return div(a, b, \"SafeMath: division by zero\");\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     *\n     * _Available since v2.4.0._\n     */\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        // Solidity only automatically asserts when dividing by 0\n        require(b > 0, errorMessage);\n        uint256 c = a / b;\n        // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * Reverts when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        return mod(a, b, \"SafeMath: modulo by zero\");\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * Reverts with custom message when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     *\n     * _Available since v2.4.0._\n     */\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b != 0, errorMessage);\n        return a % b;\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/Address.sol","source_code":"pragma solidity ^0.5.5;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following \n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\n        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\n        // for accounts without code, i.e. `keccak256('')`\n        bytes32 codehash;\n        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n        // solhint-disable-next-line no-inline-assembly\n        assembly { codehash := extcodehash(account) }\n        return (codehash != accountHash && codehash != 0x0);\n    }\n\n    /**\n     * @dev Converts an `address` into `address payable`. Note that this is\n     * simply a type cast: the actual underlying value is not changed.\n     *\n     * _Available since v2.4.0._\n     */\n    function toPayable(address account) internal pure returns (address payable) {\n        return address(uint160(account));\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     *\n     * _Available since v2.4.0._\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        // solhint-disable-next-line avoid-call-value\n        (bool success, ) = recipient.call.value(amount)(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n}\n"},{"file_path":"contracts/common/interfaces/ICeloUnreleasedTreasury.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.9.0;\n\ninterface ICeloUnreleasedTreasury {\n  /**\n   * @notice Releases the Celo to the specified address.\n   * @param to The address to release the amount to.\n   * @param amount The amount to release.\n   */\n  function release(address to, uint256 amount) external;\n\n  function getRemainingBalanceToRelease() external view returns (uint256);\n}\n"},{"file_path":"contracts-0.8/common/IsL2Check.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.5.13 <0.8.20;\n\n/**\n * @title Based on predeploy returns whether this is L1 or L2.\n */\ncontract IsL2Check {\n  address constant proxyAdminAddress = 0x4200000000000000000000000000000000000018;\n\n  /**\n   * @notice Throws if called on L2.\n   */\n  modifier onlyL1() {\n    allowOnlyL1();\n    _;\n  }\n\n  /**\n   * @notice Throws if called on L1.\n   */\n  modifier onlyL2() {\n    if (!isL2()) {\n      revert(\"This method is not supported in L1.\");\n    }\n    _;\n  }\n\n  /**\n   * @notice Checks to see if current network is Celo L2.\n   * @return Whether or not the current network is a Celo L2.\n   */\n  function isL2() internal view returns (bool) {\n    uint32 size;\n    address _addr = proxyAdminAddress;\n    assembly {\n      size := extcodesize(_addr)\n    }\n    return (size > 0);\n  }\n\n  /**\n   * @notice Used to restrict usage of the parent function to L1 execution.\n   * @dev Reverts if called on a Celo L2 network.\n   */\n  function allowOnlyL1() internal view {\n    if (isL2()) {\n      revert(\"This method is no longer supported in L2.\");\n    }\n  }\n}\n"}],"is_verified_via_sourcify":false,"can_be_visualized_via_sol2uml":true,"evm_version":"istanbul","language":"solidity","is_verified_via_eth_bytecode_db":false,"is_fully_verified":false,"license_type":"none","is_blueprint":false,"name":"Governance","creation_bytecode":"0x60806040523480156200001157600080fd5b506040516200e2653803806200e265833981810160405260208110156200003757600080fd5b81019080805190602001909291905050508060006200005b6200012a60201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350806200011b576001600060146101000a81548160ff0219169083151502179055505b50600180819055505062000132565b600033905090565b61e12380620001426000396000f3fe60806040526004361061050d5760003560e01c8063745407c811610297578063b0f9984211610165578063cf48eb94116100cc578063e50e652d11610085578063e50e652d146128c5578063ec68307214612914578063ed3852741461299c578063f2fde38b14612a20578063f3f6da2c14612a71578063fae8db0a14612acc5761050d565b8063cf48eb9414612560578063d142a0f2146126ef578063d704f0c51461271a578063da35c66414612812578063df4da4611461283d578063e41db455146128685761050d565b8063c73a6d781161011e578063c73a6d78146122dd578063c7f758a814612330578063c805956d1461243e578063c8d8d2b51461247e578063cd845a76146124b9578063cea69e74146125255761050d565b8063b0f9984214611fec578063b8f7700514612027578063bab0808914612052578063bbb2eab9146121f5578063c0aee5f41461225f578063c134b2fc1461228a5761050d565b80639381ab2511610209578063a91ee0dc116101c2578063a91ee0dc14611d9f578063aa2feb8314611df0578063ad78c10914611e3f578063add004df14611e6a578063af108a0e14611eb9578063af20311014611f165761050d565b80639381ab2514611bde57806397b9eba614611c0d57806398f4270214611c9b5780639a7b3be714611cea5780639b2b592f14611d155780639cb02dfc14611d645761050d565b806387ee8a0f1161025b57806387ee8a0f146119eb5780638a88362614611a165780638da5cb5b14611af25780638e905ed614611b495780638f32d59b14611b745780638fcc9cfb14611ba35761050d565b8063745407c8146118a057806377d26a2a146118db5780637910867b146119065780637b103999146119595780638018556e146119b05761050d565b80633ccfd60b116103df5780635d35a3d91161034657806366547163116102ff578063665471631461165e57806367960e91146116c35780636de8a63b1461179f5780636f2ab6931461180b578063715018a61461185e5780637385e5da146118755761050d565b80635d35a3d9146112855780635f115a85146112e25780635f8dd6491461137457806360b4d34d146113dd57806365bbdaa0146114425780636643ac58146116235761050d565b806354255be01161039857806354255be0146110645780635601eaea146110a45780635733397814611101578063582ae53b146111685780635c759394146111c55780635d180adb146112005761050d565b80633ccfd60b14610e415780633db9dd9a14610e7057806341b3d18514610eab57806345a7849914610ed65780634b2c2f4414610f4d5780635093564d146110295761050d565b80631c1083e2116104835780632c0523551161043c5780632c05235514610ca95780632edfd12e14610ce457806330a095d014610d5f5780633156560e14610d8a5780633b1eb4bf14610ddb5780633bb0ed2b14610e2a5761050d565b80631c1083e2146109775780631c65bc61146109c857806323f0ab6514610a035780632762132114610b9a57806327eb6c0f14610bed578063283aaefb14610c445761050d565b80631201a0fb116104d55780631201a0fb1461079b578063123633ea146107c65780631374b22d14610841578063141a8dd814610894578063152b4834146108eb578063158ef93e146109485761050d565b806301fce27e1461058857806304acaec91461063c5780630e0b78ae146106775780630f717e42146106e757806311fb9e8414610720575b60008036905014610586576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f756e6b6e6f776e206d6574686f6400000000000000000000000000000000000081525060200191505060405180910390fd5b005b34801561059457600080fd5b5061059d612b1b565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156105e45780820151818401526020810190506105c9565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561062657808201518184015260208101905061060b565b5050505090500194505050505060405180910390f35b34801561064857600080fd5b506106756004803603602081101561065f57600080fd5b8101908080359060200190929190505050612ce0565b005b34801561068357600080fd5b506106b06004803603602081101561069a57600080fd5b8101908080359060200190929190505050612eb8565b6040518085151515158152602001841515151581526020018315151515815260200182815260200194505050505060405180910390f35b3480156106f357600080fd5b506106fc612f50565b60405180848152602001838152602001828152602001935050505060405180910390f35b34801561072c57600080fd5b506107596004803603602081101561074357600080fd5b8101908080359060200190929190505050612f68565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a757600080fd5b506107b0613061565b6040518082815260200191505060405180910390f35b3480156107d257600080fd5b506107ff600480360360208110156107e957600080fd5b8101908080359060200190929190505050613067565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561084d57600080fd5b5061087a6004803603602081101561086457600080fd5b8101908080359060200190929190505050613121565b604051808215151515815260200191505060405180910390f35b3480156108a057600080fd5b506108a9613145565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108f757600080fd5b5061092e6004803603604081101561090e57600080fd5b81019080803590602001909291908035906020019092919050505061316b565b604051808215151515815260200191505060405180910390f35b34801561095457600080fd5b5061095d613192565b604051808215151515815260200191505060405180910390f35b34801561098357600080fd5b506109c66004803603602081101561099a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506131a5565b005b3480156109d457600080fd5b50610a01600480360360208110156109eb57600080fd5b81019080803590602001909291905050506134d1565b005b348015610a0f57600080fd5b50610b8060048036036060811015610a2657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610a6357600080fd5b820183602082011115610a7557600080fd5b80359060200191846001830284011164010000000083111715610a9757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190640100000000811115610afa57600080fd5b820183602082011115610b0c57600080fd5b80359060200191846001830284011164010000000083111715610b2e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061368c565b604051808215151515815260200191505060405180910390f35b348015610ba657600080fd5b50610bd360048036036020811015610bbd57600080fd5b810190808035906020019092919050505061384e565b604051808215151515815260200191505060405180910390f35b348015610bf957600080fd5b50610c02613872565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610c5057600080fd5b50610c9360048036036020811015610c6757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613898565b6040518082815260200191505060405180910390f35b348015610cb557600080fd5b50610ce260048036036020811015610ccc57600080fd5b81019080803590602001909291905050506138e4565b005b348015610cf057600080fd5b50610d45600480360360a0811015610d0757600080fd5b810190808035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050613a71565b604051808215151515815260200191505060405180910390f35b348015610d6b57600080fd5b50610d74613de3565b6040518082815260200191505060405180910390f35b348015610d9657600080fd5b50610dd960048036036020811015610dad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613df0565b005b348015610de757600080fd5b50610e1460048036036020811015610dfe57600080fd5b810190808035906020019092919050505061411c565b6040518082815260200191505060405180910390f35b348015610e3657600080fd5b50610e3f6141de565b005b348015610e4d57600080fd5b50610e566145dd565b604051808215151515815260200191505060405180910390f35b348015610e7c57600080fd5b50610ea960048036036020811015610e9357600080fd5b8101908080359060200190929190505050614815565b005b348015610eb757600080fd5b50610ec06149ed565b6040518082815260200191505060405180910390f35b348015610ee257600080fd5b50610f0f60048036036020811015610ef957600080fd5b81019080803590602001909291905050506149f3565b604051808615151515815260200185151515158152602001848152602001831515151581526020018281526020019550505050505060405180910390f35b348015610f5957600080fd5b5061101360048036036020811015610f7057600080fd5b8101908080359060200190640100000000811115610f8d57600080fd5b820183602082011115610f9f57600080fd5b80359060200191846001830284011164010000000083111715610fc157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050614a50565b6040518082815260200191505060405180910390f35b34801561103557600080fd5b506110626004803603602081101561104c57600080fd5b8101908080359060200190929190505050614bec565b005b34801561107057600080fd5b50611079614e2b565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b3480156110b057600080fd5b506110e7600480360360408110156110c757600080fd5b810190808035906020019092919080359060200190929190505050614e53565b604051808215151515815260200191505060405180910390f35b34801561110d57600080fd5b5061114e6004803603606081101561112457600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506150b9565b604051808215151515815260200191505060405180910390f35b34801561117457600080fd5b506111a16004803603602081101561118b57600080fd5b810190808035906020019092919050505061574e565b604051808260058111156111b157fe5b60ff16815260200191505060405180910390f35b3480156111d157600080fd5b506111fe600480360360208110156111e857600080fd5b81019080803590602001909291905050506157df565b005b34801561120c57600080fd5b506112436004803603604081101561122357600080fd5b8101908080359060200190929190803590602001909291905050506159b7565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561129157600080fd5b506112c8600480360360408110156112a857600080fd5b810190808035906020019092919080359060200190929190505050615b11565b604051808215151515815260200191505060405180910390f35b3480156112ee57600080fd5b5061133b6004803603604081101561130557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050615e17565b60405180878152602001868152602001858152602001848152602001838152602001828152602001965050505050505060405180910390f35b34801561138057600080fd5b506113c36004803603602081101561139757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615ec4565b604051808215151515815260200191505060405180910390f35b3480156113e957600080fd5b5061142c6004803603602081101561140057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615f95565b6040518082815260200191505060405180910390f35b61160d600480360360a081101561145857600080fd5b810190808035906020019064010000000081111561147557600080fd5b82018360208201111561148757600080fd5b803590602001918460208302840111640100000000831117156114a957600080fd5b9091929391929390803590602001906401000000008111156114ca57600080fd5b8201836020820111156114dc57600080fd5b803590602001918460208302840111640100000000831117156114fe57600080fd5b90919293919293908035906020019064010000000081111561151f57600080fd5b82018360208201111561153157600080fd5b8035906020019184600183028401116401000000008311171561155357600080fd5b90919293919293908035906020019064010000000081111561157457600080fd5b82018360208201111561158657600080fd5b803590602001918460208302840111640100000000831117156115a857600080fd5b9091929391929390803590602001906401000000008111156115c957600080fd5b8201836020820111156115db57600080fd5b803590602001918460018302840111640100000000831117156115fd57600080fd5b9091929391929390505050615fad565b6040518082815260200191505060405180910390f35b34801561162f57600080fd5b5061165c6004803603602081101561164657600080fd5b8101908080359060200190929190505050616329565b005b34801561166a57600080fd5b506116ad6004803603602081101561168157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506164d9565b6040518082815260200191505060405180910390f35b3480156116cf57600080fd5b50611789600480360360208110156116e657600080fd5b810190808035906020019064010000000081111561170357600080fd5b82018360208201111561171557600080fd5b8035906020019184600183028401116401000000008311171561173757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050616758565b6040518082815260200191505060405180910390f35b3480156117ab57600080fd5b506117b46168f4565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156117f75780820151818401526020810190506117dc565b505050509050019250505060405180910390f35b34801561181757600080fd5b506118446004803603602081101561182e57600080fd5b810190808035906020019092919050505061694c565b604051808215151515815260200191505060405180910390f35b34801561186a57600080fd5b5061187361697e565b005b34801561188157600080fd5b5061188a616ab7565b6040518082815260200191505060405180910390f35b3480156118ac57600080fd5b506118d9600480360360208110156118c357600080fd5b8101908080359060200190929190505050616acf565b005b3480156118e757600080fd5b506118f0616be3565b6040518082815260200191505060405180910390f35b34801561191257600080fd5b5061193f6004803603602081101561192957600080fd5b8101908080359060200190929190505050616be9565b604051808215151515815260200191505060405180910390f35b34801561196557600080fd5b5061196e616c0d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156119bc57600080fd5b506119e9600480360360208110156119d357600080fd5b8101908080359060200190929190505050616c33565b005b3480156119f757600080fd5b50611a00616dc0565b6040518082815260200191505060405180910390f35b348015611a2257600080fd5b50611adc60048036036020811015611a3957600080fd5b8101908080359060200190640100000000811115611a5657600080fd5b820183602082011115611a6857600080fd5b80359060200191846001830284011164010000000083111715611a8a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050616e6c565b6040518082815260200191505060405180910390f35b348015611afe57600080fd5b50611b07617008565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015611b5557600080fd5b50611b5e617031565b6040518082815260200191505060405180910390f35b348015611b8057600080fd5b50611b89617037565b604051808215151515815260200191505060405180910390f35b348015611baf57600080fd5b50611bdc60048036036020811015611bc657600080fd5b8101908080359060200190929190505050617095565b005b348015611bea57600080fd5b50611bf361723f565b604051808215151515815260200191505060405180910390f35b348015611c1957600080fd5b50611c8560048036036040811015611c3057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061792a565b6040518082815260200191505060405180910390f35b348015611ca757600080fd5b50611cd460048036036020811015611cbe57600080fd5b8101908080359060200190929190505050617946565b6040518082815260200191505060405180910390f35b348015611cf657600080fd5b50611cff617a5f565b6040518082815260200191505060405180910390f35b348015611d2157600080fd5b50611d4e60048036036020811015611d3857600080fd5b8101908080359060200190929190505050617a6f565b6040518082815260200191505060405180910390f35b348015611d7057600080fd5b50611d9d60048036036020811015611d8757600080fd5b8101908080359060200190929190505050617bc0565b005b348015611dab57600080fd5b50611dee60048036036020811015611dc257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050617e5f565b005b348015611dfc57600080fd5b50611e2960048036036020811015611e1357600080fd5b8101908080359060200190929190505050618003565b6040518082815260200191505060405180910390f35b348015611e4b57600080fd5b50611e54618024565b6040518082815260200191505060405180910390f35b348015611e7657600080fd5b50611ea360048036036020811015611e8d57600080fd5b8101908080359060200190929190505050618031565b6040518082815260200191505060405180910390f35b348015611ec557600080fd5b50611efc60048036036040811015611edc57600080fd5b810190808035906020019092919080359060200190929190505050618052565b604051808215151515815260200191505060405180910390f35b348015611f2257600080fd5b50611fea6004803603610180811015611f3a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291905050506184e5565b005b348015611ff857600080fd5b506120256004803603602081101561200f57600080fd5b810190808035906020019092919050505061860d565b005b34801561203357600080fd5b5061203c61894b565b6040518082815260200191505060405180910390f35b34801561205e57600080fd5b506121df600480360360a081101561207557600080fd5b810190808035906020019064010000000081111561209257600080fd5b8201836020820111156120a457600080fd5b803590602001918460208302840111640100000000831117156120c657600080fd5b9091929391929390803590602001906401000000008111156120e757600080fd5b8201836020820111156120f957600080fd5b8035906020019184602083028401116401000000008311171561211b57600080fd5b90919293919293908035906020019064010000000081111561213c57600080fd5b82018360208201111561214e57600080fd5b8035906020019184600183028401116401000000008311171561217057600080fd5b90919293919293908035906020019064010000000081111561219157600080fd5b8201836020820111156121a357600080fd5b803590602001918460208302840111640100000000831117156121c557600080fd5b90919293919293908035906020019092919050505061895b565b6040518082815260200191505060405180910390f35b34801561220157600080fd5b506122456004803603606081101561221857600080fd5b810190808035906020019092919080359060200190929190803560ff169060200190929190505050618a6c565b604051808215151515815260200191505060405180910390f35b34801561226b57600080fd5b50612274618ed4565b6040518082815260200191505060405180910390f35b34801561229657600080fd5b506122c3600480360360208110156122ad57600080fd5b8101908080359060200190929190505050618eda565b604051808215151515815260200191505060405180910390f35b3480156122e957600080fd5b506123166004803603602081101561230057600080fd5b8101908080359060200190929190505050618efe565b604051808215151515815260200191505060405180910390f35b34801561233c57600080fd5b506123696004803603602081101561235357600080fd5b8101908080359060200190929190505050618f9c565b604051808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018781526020018681526020018581526020018060200184815260200183151515158152602001828103825285818151815260200191508051906020019080838360005b838110156123fd5780820151818401526020810190506123e2565b50505050905090810190601f16801561242a5780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390f35b34801561244a57600080fd5b50612453619077565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b34801561248a57600080fd5b506124b7600480360360208110156124a157600080fd5b8101908080359060200190929190505050619113565b005b3480156124c557600080fd5b50612508600480360360208110156124dc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506192a0565b604051808381526020018281526020019250505060405180910390f35b34801561253157600080fd5b5061255e6004803603602081101561254857600080fd5b8101908080359060200190929190505050619322565b005b34801561256c57600080fd5b506126ed600480360360a081101561258357600080fd5b81019080803590602001906401000000008111156125a057600080fd5b8201836020820111156125b257600080fd5b803590602001918460208302840111640100000000831117156125d457600080fd5b9091929391929390803590602001906401000000008111156125f557600080fd5b82018360208201111561260757600080fd5b8035906020019184602083028401116401000000008311171561262957600080fd5b90919293919293908035906020019064010000000081111561264a57600080fd5b82018360208201111561265c57600080fd5b8035906020019184600183028401116401000000008311171561267e57600080fd5b90919293919293908035906020019064010000000081111561269f57600080fd5b8201836020820111156126b157600080fd5b803590602001918460208302840111640100000000831117156126d357600080fd5b9091929391929390803590602001909291905050506194d2565b005b3480156126fb57600080fd5b5061270461990d565b6040518082815260200191505060405180910390f35b34801561272657600080fd5b5061275d6004803603604081101561273d57600080fd5b810190808035906020019092919080359060200190929190505050619913565b604051808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b838110156127d55780820151818401526020810190506127ba565b50505050905090810190601f1680156128025780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b34801561281e57600080fd5b50612827619a9d565b6040518082815260200191505060405180910390f35b34801561284957600080fd5b50612852619aa3565b6040518082815260200191505060405180910390f35b34801561287457600080fd5b506128a16004803603602081101561288b57600080fd5b8101908080359060200190929190505050619bfa565b60405180848152602001838152602001828152602001935050505060405180910390f35b3480156128d157600080fd5b506128fe600480360360208110156128e857600080fd5b8101908080359060200190929190505050619c27565b6040518082815260200191505060405180910390f35b34801561292057600080fd5b5061297f600480360360c081101561293757600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050619c7a565b604051808381526020018281526020019250505060405180910390f35b3480156129a857600080fd5b50612a1e600480360360608110156129bf57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080359060200190929190505050619e96565b005b348015612a2c57600080fd5b50612a6f60048036036020811015612a4357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061a1d3565b005b348015612a7d57600080fd5b50612aca60048036036040811015612a9457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061a259565b005b348015612ad857600080fd5b50612b0560048036036020811015612aef57600080fd5b810190808035906020019092919050505061a30f565b6040518082815260200191505060405180910390f35b606080601273a86051f29c45218b5f6cd121ebafb690660d047c6369b317e390916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b158015612b7057600080fd5b505af4158015612b84573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052506040811015612bae57600080fd5b8101908080516040519392919084640100000000821115612bce57600080fd5b83820191506020820185811115612be457600080fd5b8251866020820283011164010000000082111715612c0157600080fd5b8083526020830192505050908051906020019060200280838360005b83811015612c38578082015181840152602081019050612c1d565b5050505090500160405260200180516040519392919084640100000000821115612c6157600080fd5b83820191506020820185811115612c7757600080fd5b8251866020820283011164010000000082111715612c9457600080fd5b8083526020830192505050908051906020019060200280838360005b83811015612ccb578082015181840152602081019050612cb0565b50505050905001604052505050915091509091565b612ce8617037565b612d5a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612d6261d70d565b612d6b8261a460565b9050612d768161a47e565b612dcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061db156027913960400191505060405180910390fd5b612df760196003016040518060200160405290816000820154815250508261a49890919063ffffffff16565b15612e6a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f426173656c696e652071756f72756d20666163746f7220756e6368616e67656481525060200191505060405180910390fd5b806019600301600082015181600001559050507fddfdbe55eaaa70fe2b8bc82a9b0734c25cabe7cb6f1457f9644019f0b5ff91fc826040518082815260200191505060405180910390a15050565b6000806000806011600086815260200190815260200160002060000160019054906101000a900460ff166011600087815260200190815260200160002060030160009054906101000a900460ff166011600088815260200190815260200160002060000160009054906101000a900460ff16601160008981526020019081526020016000206004015493509350935093509193509193565b60038060000154908060010154908060020154905083565b6000612f7261a4ad565b612fc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018061dfe86023913960400191505060405180910390fd5b612fcf61a4de565b73ffffffffffffffffffffffffffffffffffffffff16638657f615836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561301f57600080fd5b505afa158015613033573d6000803e3d6000fd5b505050506040513d602081101561304957600080fd5b81019080805190602001909291905050509050919050565b600a5481565b600061307161a4ad565b156131105761307e61a4de565b73ffffffffffffffffffffffffffffffffffffffff16632ba47274836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156130ce57600080fd5b505afa1580156130e2573d6000803e3d6000fd5b505050506040513d60208110156130f857600080fd5b8101908080519060200190929190505050905061311c565b6131198261a5d9565b90505b919050565b600061313e600f600084815260200190815260200160002061a732565b9050919050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061318a600f6000858152602001908152602001600020848461a742565b905092915050565b600060149054906101000a900460ff1681565b6131ad617037565b61321f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156132c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f436f756e63696c2063616e6e6f742062652061646472657373207a65726f000081525060200191505060405180910390fd5b601d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613386576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f436f756e63696c20756e6368616e67656400000000000000000000000000000081525060200191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561344a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f436f756e63696c2063616e6e6f7420626520617070726f76657200000000000081525060200191505060405180910390fd5b80601d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f7683fab01f2423e9d93e84c60129ec97b5121526e34c75e52149bc7baea934c060405160405180910390a250565b6134d9617037565b61354b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61355361d70d565b61355c8261a460565b90506135678161a47e565b6135bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061df3c6024913960400191505060405180910390fd5b6135e860196001016040518060200160405290816000820154815250508261a49890919063ffffffff16565b1561363e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061dbaf6026913960400191505060405180910390fd5b806019600101600082015181600001559050507f122a37b609e0f758b6a23c43506cb567017a4d18b21fa91312fb42b44975a5b5826040518082815260200191505060405180910390a15050565b600061369661a7d5565b600060fb73ffffffffffffffffffffffffffffffffffffffff16858585604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140183805190602001908083835b6020831061371e57805182526020820191506020810190506020830392506136fb565b6001836020036101000a03801982511681845116808217855250505050505090500182805190602001908083835b6020831061376f578051825260208201915060208101905060208303925061374c565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b602083106137d857805182526020820191506020810190506020830392506137b5565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613838576040519150601f19603f3d011682016040523d82523d6000602084013e61383d565b606091505b505080915050809150509392505050565b600061386b600f600084815260200190815260200160002061a835565b9050919050565b601d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201549050919050565b6138ec617037565b61395e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008114156139b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061d9fd6021913960400191505060405180910390fd5b600654811415613a30576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f517565756545787069727920756e6368616e676564000000000000000000000081525060200191505060405180910390fd5b806006819055507f4ecbf0bb0701615e2d6f9b0a0996056c959fe359ce76aa7ce06c5f1d57dae4d7816040518082815260200191505060405180910390a150565b60006001806000828254019250508190555060006001549050613a926141de565b600080613a9f898961aa55565b91509150613aac8261a732565b613abb57600093505050613d62565b60036005811115613ac857fe5b816005811115613ad457fe5b14613b47576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e636f72726563742070726f706f73616c207374617465000000000000000081525060200191505060405180910390fd5b6000613b5161ab31565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015613bcd57600080fd5b505afa158015613be1573d6000803e3d6000fd5b505050506040513d6020811015613bf757600080fd5b810190808051906020019092919050505090506000613c1461ac2c565b73ffffffffffffffffffffffffffffffffffffffff166361d5c570836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015613c9057600080fd5b505afa158015613ca4573d6000803e3d6000fd5b505050506040513d6020811015613cba57600080fd5b81019080805190602001909291905050509050613cf287613ce48a8c61ad2790919063ffffffff16565b61ad2790919063ffffffff16565b811015613d4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604381526020018061e00b6043913960600191505060405180910390fd5b613d59848c8c858d8d8d61adaf565b60019550505050505b6001548114613dd9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5095945050505050565b6000600360020154905090565b613df8617037565b613e6a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613f0d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f417070726f7665722063616e6e6f74206265203000000000000000000000000081525060200191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613fd1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f417070726f76657220756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b601d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415614095576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f417070726f7665722063616e6e6f7420626520636f756e63696c00000000000081525060200191505060405180910390fd5b80600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fa03757d836cb0b61c0fbba2147f5d51d6071ff3dd5bf6963beb55563d64878e160405160405180910390a250565b600061412661a4ad565b156141c55761413361a4de565b73ffffffffffffffffffffffffffffffffffffffff16633b1eb4bf836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561418357600080fd5b505afa158015614197573d6000803e3d6000fd5b505050506040513d60208110156141ad57600080fd5b810190808051906020019092919050505090506141d9565b6141d6826141d1619aa3565b61b28e565b90505b919050565b6141f560075460095461ad2790919063ffffffff16565b42106145db576000614211600a5460126000016002015461b2d6565b90506060601273a86051f29c45218b5f6cd121ebafb690660d047c6377b024799091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561426f57600080fd5b505af4158015614283573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156142ad57600080fd5b81019080805160405193929190846401000000008211156142cd57600080fd5b838201915060208201858111156142e357600080fd5b825186602082028301116401000000008211171561430057600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561433757808201518184015260208101905061431c565b505050509050016040525050509050600080905060008090505b838110156145c857600083828151811061436757fe5b602002602001015190506000600f600083815260200190815260200160002090506143918161b2ef565b156143ca57817f88e53c486703527139dfc8d97a1e559d9bd93d3f9d52cda4e06564111e7a264360405160405180910390a250506145ad565b6144448160010154600d60008460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461ad2790919063ffffffff16565b600d60008360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055504281600201819055506000601880549050146145415760006144dc600160188054905061b31490919063ffffffff16565b9050826017601883815481106144ee57fe5b90600052602060002001548154811061450357fe5b90600052602060002001819055506018818154811061451e57fe5b90600052602060002001600090558060188161453a919061d720565b505061456e565b60178290806001815401808255809150509060018203906000526020600020016000909192909190915055505b817f3e069fb74dcf5fbc07740b0d40d7f7fc48e9c0ca5dc3d19eb34d2e05d74c5543426040518082815260200191505060405180910390a26001935050505b6145c160018261ad2790919063ffffffff16565b9050614351565b5080156145d757426009819055505b5050505b565b600060018060008282540192505081905550600060015490506000600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008114156146b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f4e6f7468696e6720746f2077697468647261770000000000000000000000000081525060200191505060405180910390fd5b47811115614727576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f496e636f6e73697374656e742062616c616e636500000000000000000000000081525060200191505060405180910390fd5b6000600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550614795813373ffffffffffffffffffffffffffffffffffffffff1661b35e90919063ffffffff16565b60019250506001548114614811576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5090565b61481d617037565b61488f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61489761d70d565b6148a08261a460565b90506148ab8161a47e565b614900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061da4c6027913960400191505060405180910390fd5b61492c60196000016040518060200160405290816000820154815250508261a49890919063ffffffff16565b1561499f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f50617274696369706174696f6e20626173656c696e6520756e6368616e67656481525060200191505060405180910390fd5b806019600001600082015181600001559050507f51131d2820f04a6b6edd20e22a07d5bf847e265a3906e85256fca7d6043417c5826040518082815260200191505060405180910390a15050565b600c5481565b60116020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060010154908060030160009054906101000a900460ff16908060040154905085565b6000614a5a61a7d5565b6060600060f473ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b60208310614aad5780518252602082019150602081019050602083039250614a8a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310614b145780518252602082019150602081019050602083039250614af1565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114614b74576040519150601f19603f3d011682016040523d82523d6000602084013e614b79565b606091505b50809350819250505080614bd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603881526020018061dc366038913960400191505060405180910390fd5b614be382600061b498565b92505050919050565b806011600082815260200190815260200160002060000160009054906101000a900460ff1615614c84576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b816000601160008381526020019081526020016000206004015411614d11576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f686f74666978206e6f742070726570617265640000000000000000000000000081525060200191505060405180910390fd5b42601160008381526020019081526020016000206004015410614d7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061daee6027913960400191505060405180910390fd5b60006011600085815260200190815260200160002060000160016101000a81548160ff02191690831515021790555060006011600085815260200190815260200160002060030160006101000a81548160ff02191690831515021790555060006011600085815260200190815260200160002060040181905550827f5af07e8248de542d5637f35c0538561c1f4867fa0545011255a5de4087ecf52260405160405180910390a2505050565b6000806000806001600560016000839350829250819150809050935093509350935090919293565b60006001806000828254019250508190555060006001549050614e746141de565b600080614e81868661aa55565b915091506000614e908361a732565b9050801561503557614ea18361b539565b614f13576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f50726f706f73616c206e6f7420617070726f766564000000000000000000000081525060200191505060405180910390fd5b60046005811115614f2057fe5b826005811115614f2c57fe5b148015614f3e5750614f3d8361a835565b5b614f93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061de04602e913960400191505060405180910390fd5b827338afc0dc55415ae27b81c24b5a5fbfe433ebfba863c67e7b4b90916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b158015614fe457600080fd5b505af4158015614ff8573d6000803e3d6000fd5b50505050867f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f60405160405180910390a261503483888861b554565b5b80945050505060015481146150b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5092915050565b600060018060008282540192505081905550600060015490506150da6141de565b6150e38561b673565b156150f157600091506156cf565b60006150fb61ab31565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561517757600080fd5b505afa15801561518b573d6000803e3d6000fd5b505050506040513d60208110156151a157600080fd5b810190808051906020019092919050505090506000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050615207816000016000015461b673565b50600061521261ac2c565b73ffffffffffffffffffffffffffffffffffffffff166330ec70f5846040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561528e57600080fd5b505afa1580156152a2573d6000803e3d6000fd5b505050506040513d60208110156152b857600080fd5b8101908080519060200190929190505050905060008111615324576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061dea76022913960400191505060405180910390fd5b601273a86051f29c45218b5f6cd121ebafb690660d047c63bfc5163890918a6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561537e57600080fd5b505af4158015615392573d6000803e3d6000fd5b505050506040513d60208110156153a857600080fd5b810190808051906020019092919050505061540e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061dcc56029913960400191505060405180910390fd5b6000826000016000015414806154bd5750601273a86051f29c45218b5f6cd121ebafb690660d047c63bfc51638909184600001600001546040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561548057600080fd5b505af4158015615494573d6000803e3d6000fd5b505050506040513d60208110156154aa57600080fd5b8101908080519060200190929190505050155b615512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061dfbd602b913960400191505060405180910390fd5b60006155bb82601273a86051f29c45218b5f6cd121ebafb690660d047c637577759990918d6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561557257600080fd5b505af4158015615586573d6000803e3d6000fd5b505050506040513d602081101561559c57600080fd5b810190808051906020019092919050505061ad2790919063ffffffff16565b9050601273a86051f29c45218b5f6cd121ebafb690660d047c63239491ba90918b848c8c6040518663ffffffff1660e01b8152600401808681526020018581526020018481526020018381526020018281526020019550505050505060006040518083038186803b15801561562f57600080fd5b505af4158015615643573d6000803e3d6000fd5b5050505060405180604001604052808a8152602001838152508360000160008201518160000155602082015181600101559050508373ffffffffffffffffffffffffffffffffffffffff16897fd19965d25ef670a1e322fbf05475924b7b12d81fd6b96ab718b261782efb3d62846040518082815260200191505060405180910390a360019550505050505b6001548114615746576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b509392505050565b60008082148061575f5750600b5482115b1561576d57600090506157da565b6000600f6000848152602001908152602001600020905061578d83618efe565b156157b15761579b8161b2ef565b6157a65760016157a9565b60055b9150506157da565b60006157bc8261b746565b90506157c8828261b7fd565b6157d257806157d5565b60055b925050505b919050565b6157e7617037565b615859576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61586161d70d565b61586a8261a460565b90506158758161a47e565b6158ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061dc0f6027913960400191505060405180910390fd5b6158f660196002016040518060200160405290816000820154815250508261a49890919063ffffffff16565b15615969576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f426173656c696e652075706461746520666163746f7220756e6368616e67656481525060200191505060405180910390fd5b806019600201600082015181600001559050507f8dedb4d995dd500718c7c5f6a077fba6153a7ee063da961d9fcab90ff528ac1f826040518082815260200191505060405180910390a15050565b60006159c161a7d5565b6060600060fa73ffffffffffffffffffffffffffffffffffffffff16858560405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310615a385780518252602082019150602081019050602083039250615a15565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114615a98576040519150601f19603f3d011682016040523d82523d6000602084013e615a9d565b606091505b50809350819250505080615afc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061ddce6036913960400191505060405180910390fd5b615b0782600061b854565b9250505092915050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614615bd6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f6d73672e73656e646572206e6f7420617070726f76657200000000000000000081525060200191505060405180910390fd5b615bde6141de565b600080615beb858561aa55565b91509150615bf88261a732565b615c0757600092505050615e11565b615c108261b539565b15615c83576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f50726f706f73616c20616c726561647920617070726f7665640000000000000081525060200191505060405180910390fd5b60036005811115615c9057fe5b816005811115615c9c57fe5b1480615cbe575060046005811115615cb057fe5b816005811115615cbc57fe5b145b615d30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f50726f706f73616c206e6f7420696e20636f727265637420737461676500000081525060200191505060405180910390fd5b60018260070160006101000a81548160ff021916908315150217905550615d5561ac2c565b73ffffffffffffffffffffffffffffffffffffffff166330a61d596040518163ffffffff1660e01b815260040160206040518083038186803b158015615d9a57600080fd5b505afa158015615dae573d6000803e3d6000fd5b505050506040513d6020811015615dc457600080fd5b81019080805190602001909291905050508260080181905550847f28ec9e38ba73636ceb2f6c1574136f83bd46284a3c74734b711bf45e12f8d92960405160405180910390a26001925050505b92915050565b6000806000806000806000601060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003016000898152602001908152602001600020905080600101548160000160009054906101000a900460ff166003811115615e9957fe5b8260020154836003015484600401548560050154965096509650965096509650509295509295509295565b600080601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816000016000015490506000808214158015615f2b5750615f2a82618efe565b5b8015615f3d5750615f3b82618eda565b155b90506000600f6000856002015481526020019081526020016000209050600060036005811115615f6957fe5b615f728361b746565b6005811115615f7d57fe5b1490508280615f895750805b95505050505050919050565b600d6020528060005260406000206000915090505481565b6000615fb76141de565b600c5434101561602f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f546f6f20736d616c6c206465706f73697400000000000000000000000000000081525060200191505060405180910390fd5b6160456001600b5461ad2790919063ffffffff16565b600b819055506000600f6000600b5481526020019081526020016000209050807338afc0dc55415ae27b81c24b5a5fbfe433ebfba8633053123f90918e8e8e8e8e8e8e8e33346040518c63ffffffff1660e01b8152600401808c8152602001806020018060200180602001806020018773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186815260200185810385528f8f82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810384528d8d82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810383528b8b82818152602001925080828437600081840152601f19601f8201169050808301925050508581038252898982818152602001925060200280828437600081840152601f19601f8201169050808301925050509f5050505050505050505050505050505060006040518083038186803b1580156161ca57600080fd5b505af41580156161de573d6000803e3d6000fd5b5050505061623984848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508261b86b90919063ffffffff16565b601273a86051f29c45218b5f6cd121ebafb690660d047c63d7a8acc19091600b546040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561629557600080fd5b505af41580156162a9573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff16600b547f1bfe527f3548d9258c2512b6689f0acfccdd0557d80a53845db25fc57e93d8fe8360060180549050344260405180848152602001838152602001828152602001935050505060405180910390a3600b549150509a9950505050505050505050565b616331617037565b6163a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600081141561641a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4475726174696f6e206d757374206265206c6172676572207468616e2030000081525060200191505060405180910390fd5b600360020154811415616495576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4475726174696f6e20756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b806003600201819055507f7819c8059302d1d66abc7fe228ecc02214e0bc5c529956c13717aabefce937d8816040518082815260200191505060405180910390a150565b600080601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816000016000015490506000808214158015616540575061653f82618efe565b5b8015616552575061655082618eda565b155b9050600080905081156166215761656761ac2c565b73ffffffffffffffffffffffffffffffffffffffff166330ec70f5876040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156165e357600080fd5b505afa1580156165f7573d6000803e3d6000fd5b505050506040513d602081101561660d57600080fd5b810190808051906020019092919050505090505b600080905060008090505b6017805490508110156167415760006017828154811061664857fe5b906000526020600020015490506000600f6000838152602001908152602001600020905060006003600581111561667b57fe5b6166848361b746565b600581111561668f57fe5b1490508061669f57505050616726565b60008960030160008681526020019081526020016000209050838160010154146166cc5750505050616726565b60006166ff82600501546166f18460040154856003015461ad2790919063ffffffff16565b61ad2790919063ffffffff16565b905061671e87600083146167135782616719565b83600201545b61b8e3565b965050505050505b61673a60018261ad2790919063ffffffff16565b905061662c565b5061674c828261b8e3565b95505050505050919050565b600061676261a7d5565b6060600060f673ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b602083106167b55780518252602082019150602081019050602083039250616792565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b6020831061681c57805182526020820191506020810190506020830392506167f9565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461687c576040519150601f19603f3d011682016040523d82523d6000602084013e616881565b606091505b508093508192505050806168e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018061e04e6023913960400191505060405180910390fd5b6168eb82600061b498565b92505050919050565b6060601780548060200260200160405190810160405280929190818152602001828054801561694257602002820191906000526020600020905b81548152602001906001019080831161692e575b5050505050905090565b600080600f60008481526020019081526020016000209050616976816169718361b746565b61b7fd565b915050919050565b616986617037565b6169f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000616ac161a7d5565b616aca43619c27565b905090565b616ad7617037565b616b49576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111616ba2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061d9d96024913960400191505060405180910390fd5b80601e819055507f14990942cf0411abf738b62b62c43f745c43655bde245941493d710999f4a9cc816040518082815260200191505060405180910390a150565b60075481565b6000616c06600f600084815260200190815260200160002061b539565b9050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b616c3b617037565b616cad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000811415616d07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061de326026913960400191505060405180910390fd5b600754811415616d7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f646571756575654672657175656e637920756e6368616e67656400000000000081525060200191505060405180910390fd5b806007819055507f391e82aae76c653cd640ad1b6028e2ee39ca4f29b30152e3d0a9ddd7e1169c34816040518082815260200191505060405180910390a150565b6000616dca61a4ad565b15616e5e57616dd761a4de565b73ffffffffffffffffffffffffffffffffffffffff1663639a84d36040518163ffffffff1660e01b815260040160206040518083038186803b158015616e1c57600080fd5b505afa158015616e30573d6000803e3d6000fd5b505050506040513d6020811015616e4657600080fd5b81019080805190602001909291905050509050616e69565b616e6661b8fd565b90505b90565b6000616e7661a7d5565b6060600060f773ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b60208310616ec95780518252602082019150602081019050602083039250616ea6565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310616f305780518252602082019150602081019050602083039250616f0d565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114616f90576040519150601f19603f3d011682016040523d82523d6000602084013e616f95565b606091505b50809350819250505080616ff4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603181526020018061df8c6031913960400191505060405180910390fd5b616fff82600061b854565b92505050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60065481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661707961ba4c565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b61709d617037565b61710f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000811415617186576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f6d696e4465706f736974206d757374206265206c6172676572207468616e203081525060200191505060405180910390fd5b600c548114156171fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f4d696e696d756d206465706f73697420756e6368616e6765640000000000000081525060200191505060405180910390fd5b80600c819055507fc50a7f0bdf88c216b2541b0bdea26f22305460e39ffc672ec1a7501732c5ba81816040518082815260200191505060405180910390a150565b60006001806000828254019250508190555060006001549050600061726261ab31565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156172de57600080fd5b505afa1580156172f2573d6000803e3d6000fd5b505050506040513d602081101561730857600080fd5b810190808051906020019092919050505090506000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008090505b60178054905081101561789e57600082600301600083815260200190815260200160002090506017828154811061739757fe5b906000526020600020015481600101541480156173e95750600081600301541415806173c857506000816004015414155b806173d857506000816005015414155b806173e857506000816002015414155b5b15617882576000806173ff83600101548561aa55565b915091506003600581111561741057fe5b81600581111561741c57fe5b141561782b57600083600201541461768357600060038081111561743c57fe5b8460000160009054906101000a900460ff16600381111561745957fe5b1461746557600061746b565b83600201545b905060006002600381111561747c57fe5b8560000160009054906101000a900460ff16600381111561749957fe5b146174a55760006174ab565b84600201545b90506000600160038111156174bc57fe5b8660000160009054906101000a900460ff1660038111156174d957fe5b146174e55760006174eb565b85600201545b9050847338afc0dc55415ae27b81c24b5a5fbfe433ebfba863cd150a6d909185858560008060006040518863ffffffff1660e01b81526004018088815260200187815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060006040518083038186803b15801561757057600080fd5b505af4158015617584573d6000803e3d6000fd5b5050505061759061ac2c565b73ffffffffffffffffffffffffffffffffffffffff166330a61d596040518163ffffffff1660e01b815260040160206040518083038186803b1580156175d557600080fd5b505afa1580156175e9573d6000803e3d6000fd5b505050506040513d60208110156175ff57600080fd5b810190808051906020019092919050505085600801819055508873ffffffffffffffffffffffffffffffffffffffff1686600101547f6791653c96b4863b3768c664e9a03e1094ae334ba9d35862627ceeebd1abcc1f85858560405180848152602001838152602001828152602001935050505060405180910390a350505061782a565b817338afc0dc55415ae27b81c24b5a5fbfe433ebfba863cd150a6d909185600301548660040154876005015460008060006040518863ffffffff1660e01b81526004018088815260200187815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060006040518083038186803b15801561771257600080fd5b505af4158015617726573d6000803e3d6000fd5b5050505061773261ac2c565b73ffffffffffffffffffffffffffffffffffffffff166330a61d596040518163ffffffff1660e01b815260040160206040518083038186803b15801561777757600080fd5b505afa15801561778b573d6000803e3d6000fd5b505050506040513d60208110156177a157600080fd5b810190808051906020019092919050505082600801819055508573ffffffffffffffffffffffffffffffffffffffff1683600101547f6791653c96b4863b3768c664e9a03e1094ae334ba9d35862627ceeebd1abcc1f85600301548660040154876005015460405180848152602001838152602001828152602001935050505060405180910390a35b5b846003016000858152602001908152602001600020600080820160006101000a81549060ff021916905560018201600090556002820160009055600382016000905560048201600090556005820160009055505050505b5061789760018261ad2790919063ffffffff16565b9050617364565b50600081600201819055506001935050506001548114617926576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5090565b600061793e617939848461ba54565b61bca6565b905092915050565b600061795182618efe565b6179c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f50726f706f73616c206e6f74207175657565640000000000000000000000000081525060200191505060405180910390fd5b601273a86051f29c45218b5f6cd121ebafb690660d047c63757775999091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b158015617a1d57600080fd5b505af4158015617a31573d6000803e3d6000fd5b505050506040513d6020811015617a4757600080fd5b81019080805190602001909291905050509050919050565b6000617a6a4361411c565b905090565b6000617a7961a7d5565b6060600060f973ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b60208310617ae85780518252602082019150602081019050602083039250617ac5565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114617b48576040519150601f19603f3d011682016040523d82523d6000602084013e617b4d565b606091505b50809350819250505080617bac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061da1e602e913960400191505060405180910390fd5b617bb782600061b854565b92505050919050565b806011600082815260200190815260200160002060000160009054906101000a900460ff1615617c58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b600060116000848152602001908152602001600020905060004290506000601e5411617ccf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061dcee6024913960400191505060405180910390fd5b6000826004015414617d2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061e09c602b913960400191505060405180910390fd5b8160000160019054906101000a900460ff16617d93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061ddad6021913960400191505060405180910390fd5b8160030160009054906101000a900460ff16617dfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061e0c76028913960400191505060405180910390fd5b617e0f601e548261ad2790919063ffffffff16565b8260040181905550617e2c601e548261ad2790919063ffffffff16565b847f6f184ec313435b3307a4fe59e2293381f08419a87214464c875a2a247e8af5e060405160405180910390a350505050565b617e67617037565b617ed9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415617f7c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b6018818154811061801057fe5b906000526020600020016000915090505481565b6000600360010154905090565b6017818154811061803e57fe5b906000526020600020016000915090505481565b600060018060008282540192505081905550600060015490506180736141de565b600061807d61ab31565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156180f957600080fd5b505afa15801561810d573d6000803e3d6000fd5b505050506040513d602081101561812357600080fd5b810190808051906020019092919050505090506000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000160000154905060008114156181fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4163636f756e7420686173206e6f20686973746f726963616c207570766f746581525060200191505060405180910390fd5b6182058161b673565b50601273a86051f29c45218b5f6cd121ebafb690660d047c63bfc516389091836040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561826057600080fd5b505af4158015618274573d6000803e3d6000fd5b505050506040513d602081101561828a57600080fd5b81019080805190602001909291905050501561842e57601273a86051f29c45218b5f6cd121ebafb690660d047c63239491ba90918361836d8660000160010154601273a86051f29c45218b5f6cd121ebafb690660d047c63757775999091896040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561832457600080fd5b505af4158015618338573d6000803e3d6000fd5b505050506040513d602081101561834e57600080fd5b810190808051906020019092919050505061b31490919063ffffffff16565b8b8b6040518663ffffffff1660e01b8152600401808681526020018581526020018481526020018381526020018281526020019550505050505060006040518083038186803b1580156183bf57600080fd5b505af41580156183d3573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff16817f7dc46237a819c9171a9c037ec98928e563892905c4d23373ca0f3f500f4ed11484600001600101546040518082815260200191505060405180910390a35b60405180604001604052806000815260200160008152508260000160008201518160000155602082015181600101559050506001945050505060015481146184de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5092915050565b600060149054906101000a900460ff1615618568576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600060146101000a81548160ff02191690831515021790555061858c3361bcb4565b6185958c617e5f565b61859e8b613df0565b6185a78a619113565b6185b089617095565b6185b9886138e4565b6185c287616c33565b6185cb86619322565b6185d485616329565b6185dd84614815565b6185e6836134d1565b6185ef826157df565b6185f881612ce0565b42600981905550505050505050505050505050565b806011600082815260200190815260200160002060000160009054906101000a900460ff16156186a5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561872b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061dc6e6021913960400191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806187d45750601d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b618829576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061db84602b913960400191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156188b35760016011600084815260200190815260200160002060000160016101000a81548160ff0219169083151502179055506188e3565b60016011600084815260200190815260200160002060030160006101000a81548160ff0219169083151502179055505b817f3f6169f1efa9bebb611f332d60ad5e24e6342c099df3dab6307bcb89ab801a1333604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25050565b6000601260000160020154905090565b6000898989898989898989604051602001808060200180602001806020018060200186815260200185810385528e8e82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810384528c8c82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810383528a8a82818152602001925080828437600081840152601f19601f8201169050808301925050508581038252888882818152602001925060200280828437600081840152601f19601f8201169050808301925050509d50505050505050505050505050506040516020818303038152906040528051906020012090509998505050505050505050565b60006001806000828254019250508190555060006001549050618a8d6141de565b600080618a9a878761aa55565b91509150618aa78261a732565b618ab657600093505050618e55565b60036005811115618ac357fe5b816005811115618acf57fe5b14618b42576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e636f72726563742070726f706f73616c207374617465000000000000000081525060200191505060405180910390fd5b60006003811115618b4f57fe5b856003811115618b5b57fe5b1415618bcf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f566f74652076616c756520756e7365740000000000000000000000000000000081525060200191505060405180910390fd5b6000618bd961ab31565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015618c5557600080fd5b505afa158015618c69573d6000803e3d6000fd5b505050506040513d6020811015618c7f57600080fd5b810190808051906020019092919050505090506000618c9c61ac2c565b73ffffffffffffffffffffffffffffffffffffffff166361d5c570836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015618d1857600080fd5b505afa158015618d2c573d6000803e3d6000fd5b505050506040513d6020811015618d4257600080fd5b810190808051906020019092919050505090506000811415618dcc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f566f74657220776569676874207a65726f00000000000000000000000000000081525060200191505060405180910390fd5b618e4c848a8a85600380811115618ddf57fe5b8c6003811115618deb57fe5b14618df7576000618df9565b855b60026003811115618e0657fe5b8d6003811115618e1257fe5b14618e1e576000618e20565b865b60016003811115618e2d57fe5b8e6003811115618e3957fe5b14618e45576000618e47565b875b61adaf565b60019550505050505b6001548114618ecc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b509392505050565b60095481565b6000618ef7600f600084815260200190815260200160002061b2ef565b9050919050565b6000601273a86051f29c45218b5f6cd121ebafb690660d047c63bfc516389091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b158015618f5a57600080fd5b505af4158015618f6e573d6000803e3d6000fd5b505050506040513d6020811015618f8457600080fd5b81019080805190602001909291905050509050919050565b6000806000806060600080618fc2600f60008a815260200190815260200160002061bdf8565b828054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156190575780601f1061902c57610100808354040283529160200191619057565b820191906000526020600020905b81548152906001019060200180831161903a57829003601f168201915b505050505092509650965096509650965096509650919395979092949650565b60008060008061909f601960000160405180602001604052908160008201548152505061bca6565b6190c1601960010160405180602001604052908160008201548152505061bca6565b6190e3601960020160405180602001604052908160008201548152505061bca6565b619105601960030160405180602001604052908160008201548152505061bca6565b935093509350935090919293565b61911b617037565b61918d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008114156191e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061da73602c913960400191505060405180910390fd5b600a5481141561925f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4e756d626572206f662070726f706f73616c7320756e6368616e67656400000081525060200191505060405180910390fd5b80600a819055507f85399b9b2595eb13c392e1638ca77730156cd8d48d4733df4db068e4aa6b93a6816040518082815260200191505060405180910390a150565b6000806192ab61d74c565b601060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001604051806040016040529081600082015481526020016001820154815250509050806000015181602001519250925050915091565b61932a617037565b61939c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000811415619413576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4475726174696f6e206d757374206265206c6172676572207468616e2030000081525060200191505060405180910390fd5b60036001015481141561948e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4475726174696f6e20756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b806003600101819055507f90290eb9b27055e686a69fb810bada5381e544d07b8270021da2d355a6c96ed6816040518082815260200191505060405180910390a150565b6000898989898989898989604051602001808060200180602001806020018060200186815260200185810385528e8e82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810384528c8c82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810383528a8a82818152602001925080828437600081840152601f19601f8201169050808301925050508581038252888882818152602001925060200280828437600081840152601f19601f8201169050808301925050509d50505050505050505050505050506040516020818303038152906040528051906020012090506000806000806195e585612eb8565b93509350935093508115619661576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b836196d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f686f74666978206e6f7420617070726f7665640000000000000000000000000081525060200191505060405180910390fd5b8261972a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061dec96027913960400191505060405180910390fd5b42811015619783576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061de79602e913960400191505060405180910390fd5b6198a161989c8f8f80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508e8e80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505033600061be71565b61c09a565b60016011600087815260200190815260200160002060000160006101000a81548160ff021916908315150217905550847f708a7934acb657a77a617b1fcd5f6d7d9ad592b72934841bff01acefd10f9b6360405160405180910390a25050505050505050505050505050565b601e5481565b6000806060600f60008681526020019081526020016000207338afc0dc55415ae27b81c24b5a5fbfe433ebfba863e6a5192f9091866040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561998357600080fd5b505af4158015619997573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060608110156199c157600080fd5b810190808051906020019092919080519060200190929190805160405193929190846401000000008211156199f557600080fd5b83820191506020820185811115619a0b57600080fd5b8251866001820283011164010000000082111715619a2857600080fd5b8083526020830192505050908051906020019080838360005b83811015619a5c578082015181840152602081019050619a41565b50505050905090810190601f168015619a895780820380516001836020036101000a031916815260200191505b506040525050509250925092509250925092565b600b5481565b6000619aad61a7d5565b6060600060f873ffffffffffffffffffffffffffffffffffffffff16600160405160200180821515151560f81b81526001019150506040516020818303038152906040526040518082805190602001908083835b60208310619b245780518252602082019150602081019050602083039250619b01565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114619b84576040519150601f19603f3d011682016040523d82523d6000602084013e619b89565b606091505b50809350819250505080619be8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061df176025913960400191505060405180910390fd5b619bf382600061b854565b9250505090565b6000806000619c1a600f600086815260200190815260200160002061c0aa565b9250925092509193909250565b6000619c3161a7d5565b619c736003619c656002619c576002619c4988617a6f565b61c0d490919063ffffffff16565b61ad2790919063ffffffff16565b61c15a90919063ffffffff16565b9050919050565b600080619c8561a7d5565b60008714158015619c97575060008514155b619d09576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f612064656e6f6d696e61746f72206973207a65726f000000000000000000000081525060200191505060405180910390fd5b6000806000606060fc73ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c6040516020018087815260200186815260200185815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040526040518082805190602001908083835b60208310619da35780518252602082019150602081019050602083039250619d80565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114619e03576040519150601f19603f3d011682016040523d82523d6000602084013e619e08565b606091505b50809250819350505081619e67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061def06027913960400191505060405180910390fd5b619e7281600061b854565b9350619e7f81602061b854565b925083839550955050505050965096945050505050565b619e9e617037565b619f10576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415619fb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f44657374696e6174696f6e2063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b6969e10de76676d080000081118015619fdb5750619fd7619fd261c1a4565b61bca6565b8111155b61a030576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604881526020018061db3c6048913960600191505060405180910390fd5b600060e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141561a0b85761a0648161a460565b600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000820151816000015590505061a160565b61a0c18161a460565b600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020600082015181600001559050505b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168373ffffffffffffffffffffffffffffffffffffffff167f60c5b4756af49d7b071b00dbf0f87af605cce11896ecd3b760d19f0f9d3fbcef836040518082815260200191505060405180910390a3505050565b61a1db617037565b61a24d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61a2568161bcb4565b50565b61a26161ac2c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461a301576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f6d73672e73656e646572206e6f74206c6f636b6564476f6c640000000000000081525060200191505060405180910390fd5b61a30b828261c1ca565b5050565b600061a31961a7d5565b6060600060f573ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061a388578051825260208201915060208101905060208303925061a365565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461a3e8576040519150601f19603f3d011682016040523d82523d6000602084013e61a3ed565b606091505b5080935081925050508061a44c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061df60602c913960400191505060405180910390fd5b61a45782600061b498565b92505050919050565b61a46861d70d565b6040518060200160405280838152509050919050565b600061a4918261a48c61c1a4565b61c5c1565b9050919050565b60008160000151836000015114905092915050565b60008060007342000000000000000000000000000000000000189050803b915060008263ffffffff16119250505090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f45706f63684d616e616765720000000000000000000000000000000000000000815250600c019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561a59957600080fd5b505afa15801561a5ad573d6000803e3d6000fd5b505050506040513d602081101561a5c357600080fd5b8101908080519060200190929190505050905090565b600061a5e361a7d5565b6060600060fa73ffffffffffffffffffffffffffffffffffffffff16844360405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061a65a578051825260208201915060208101905060208303925061a637565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461a6ba576040519150601f19603f3d011682016040523d82523d6000602084013e61a6bf565b606091505b5080935081925050508061a71e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d81526020018061dd12603d913960400191505060405180910390fd5b61a72982600061b854565b92505050919050565b6000808260020154119050919050565b6000601780549050821061a7a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061e071602b913960400191505060405180910390fd5b61a7aa8461a732565b801561a7cc5750826017838154811061a7bf57fe5b9060005260206000200154145b90509392505050565b61a7dd61a4ad565b1561a833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061dd846029913960400191505060405180910390fd5b565b600061a83f61d70d565b61a89661a8876019600301604051806020016040529081600082015481525050601960000160405180602001604052908160008201548152505061c5d790919063ffffffff16565b8461ca3690919063ffffffff16565b905060008360060180549050141561a8d95761a8b061d70d565b61a8bb60008061ba54565b905061a8d0818361cb2590919063ffffffff16565b9250505061aa50565b60008090505b836006018054905081101561aa4957600061a9b185600601838154811061a90257fe5b90600052602060002090600302016002018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561a9a75780601f1061a97c5761010080835404028352916020019161a9a7565b820191906000526020600020905b81548152906001019060200180831161a98a57829003601f168201915b505050505061cb3a565b905061a9bb61d70d565b61aa0586600601848154811061a9cd57fe5b906000526020600020906003020160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168361ba54565b905061aa1a818561c5c190919063ffffffff16565b1561aa2c57600094505050505061aa50565b505061aa4260018261ad2790919063ffffffff16565b905061a8df565b5060019150505b919050565b6000806000600f6000868152602001908152602001600020905061aa7a81868661a742565b61aaec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f50726f706f73616c206e6f74206465717565756564000000000000000000000081525060200191505060405180910390fd5b600061aaf78261b746565b905061ab03828261b7fd565b1561ab215761ab1382878761b554565b81600593509350505061ab2a565b81819350935050505b9250929050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f4163636f756e74730000000000000000000000000000000000000000000000008152506008019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561abec57600080fd5b505afa15801561ac00573d6000803e3d6000fd5b505050506040513d602081101561ac1657600080fd5b8101908080519060200190929190505050905090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f4c6f636b6564476f6c6400000000000000000000000000000000000000000000815250600a019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561ace757600080fd5b505afa15801561acfb573d6000803e3d6000fd5b505050506040513d602081101561ad1157600080fd5b8101908080519060200190929190505050905090565b60008082840190508381101561ada5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000601060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600301600088815260200190815260200160002090508781600101541461aeb657887338afc0dc55415ae27b81c24b5a5fbfe433ebfba863cd150a6d909160008060008a8a8a6040518863ffffffff1660e01b81526004018088815260200187815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060006040518083038186803b15801561ae9957600080fd5b505af415801561aead573d6000803e3d6000fd5b5050505061b0b7565b600081600201541461b01057887338afc0dc55415ae27b81c24b5a5fbfe433ebfba863cd150a6d909160038081111561aeeb57fe5b8460000160009054906101000a900460ff16600381111561af0857fe5b1461af1457600061af1a565b83600201545b6002600381111561af2757fe5b8560000160009054906101000a900460ff16600381111561af4457fe5b1461af5057600061af56565b84600201545b6001600381111561af6357fe5b8660000160009054906101000a900460ff16600381111561af8057fe5b1461af8c57600061af92565b85600201545b8a8a8a6040518863ffffffff1660e01b81526004018088815260200187815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060006040518083038186803b15801561aff357600080fd5b505af415801561b007573d6000803e3d6000fd5b5050505061b0b6565b887338afc0dc55415ae27b81c24b5a5fbfe433ebfba863cd150a6d90918360030154846004015485600501548a8a8a6040518863ffffffff1660e01b81526004018088815260200187815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060006040518083038186803b15801561b09d57600080fd5b505af415801561b0b1573d6000803e3d6000fd5b505050505b5b61b0bf61ac2c565b73ffffffffffffffffffffffffffffffffffffffff166330a61d596040518163ffffffff1660e01b815260040160206040518083038186803b15801561b10457600080fd5b505afa15801561b118573d6000803e3d6000fd5b505050506040513d602081101561b12e57600080fd5b810190808051906020019092919050505089600801819055506040518060c001604052806000600381111561b15f57fe5b8152602001898152602001600081526020018681526020018581526020018481525082600301600089815260200190815260200160002060008201518160000160006101000a81548160ff0219169083600381111561b1ba57fe5b02179055506020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050155905050600f600083600201548152602001908152602001600020600201548960020154111561b224578782600201819055505b8573ffffffffffffffffffffffffffffffffffffffff16887f683ebddc94b5b0a7dae3d1b6c168ad05684fcfd831b24ecb5ea9ecdf5524d02887878760405180848152602001838152602001828152602001935050505060405180910390a3505050505050505050565b60008082848161b29a57fe5b049050600083858161b2a857fe5b06141561b2b8578091505061b2d0565b61b2cc60018261ad2790919063ffffffff16565b9150505b92915050565b600081831061b2e5578161b2e7565b825b905092915050565b600061b30a600654836002015461ad2790919063ffffffff16565b4210159050919050565b600061b35683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061cc97565b905092915050565b8047101561b3d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a20696e73756666696369656e742062616c616e636500000081525060200191505060405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168260405180600001905060006040518083038185875af1925050503d806000811461b434576040519150601f19603f3d011682016040523d82523d6000602084013e61b439565b606091505b505090508061b493576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603a81526020018061dbd5603a913960400191505060405180910390fd5b505050565b600061b4ae60208361ad2790919063ffffffff16565b8351101561b524576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f736c6963696e67206f7574206f662072616e676500000000000000000000000081525060200191505060405180910390fd5b60006020830184015190508091505092915050565b60008160070160009054906101000a900460ff169050919050565b61b55d8361b539565b801561b56e57506000836008015414155b1561b57d5761b57c8361cd57565b5b60006017828154811061b58c57fe5b90600052602060002001819055506018819080600181540180825580915050906001820390600052602060002001600090919290919091505550600f6000838152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182016000905560028201600090556003820160008082016000905560018201600090556002820160009055505060068201600061b640919061d766565b6007820160006101000a81549060ff0219169055600882016000905560098201600061b66c919061d78a565b5050505050565b600061b67e82618efe565b801561b68f575061b68e82618eda565b5b1561b73c57601273a86051f29c45218b5f6cd121ebafb690660d047c63eed5f7be9091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561b6ee57600080fd5b505af415801561b702573d6000803e3d6000fd5b50505050817f88e53c486703527139dfc8d97a1e559d9bd93d3f9d52cda4e06564111e7a264360405160405180910390a26001905061b741565b600090505b919050565b60008061b77c60036002015461b76e600360010154866002015461ad2790919063ffffffff16565b61ad2790919063ffffffff16565b905080421015801561b7b857506000836006018054905014158061b7a6575061b7a48361b539565b155b8061b7b7575061b7b58361a835565b155b5b1561b7c757600591505061b7f8565b61b7df6003600201548261b31490919063ffffffff16565b905080421061b7f257600491505061b7f8565b60039150505b919050565b60006004600581111561b80c57fe5b82600581111561b81857fe5b118061b84c57506003600581111561b82c57fe5b82600581111561b83857fe5b11801561b84b575061b8498361a835565b155b5b905092915050565b600061b860838361b498565b60001c905092915050565b60008151141561b8c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061dac56029913960400191505060405180910390fd5b8082600901908051906020019061b8de92919061d7d2565b505050565b60008183101561b8f3578161b8f5565b825b905092915050565b600061b90761a7d5565b6060600060f973ffffffffffffffffffffffffffffffffffffffff1643604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061b976578051825260208201915060208101905060208303925061b953565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461b9d6576040519150601f19603f3d011682016040523d82523d6000602084013e61b9db565b606091505b5080935081925050508061ba3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603581526020018061dd4f6035913960400191505060405180910390fd5b61ba4582600061b854565b9250505090565b600033905090565b61ba5c61d70d565b61ba6461d70d565b61ba776969e10de76676d080000061a460565b9050600061bb29600e60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060405180602001604052908160008201548152505061bca6565b1461bbdb57600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020604051806020016040529081600082015481525050905061bc9c565b600061bc3c600e60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160405180602001604052908160008201548152505061bca6565b1461bc9b57600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160405180602001604052908160008201548152505090505b5b8091505092915050565b600081600001519050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561bd3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061da9f6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008060008060008060008760000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886001015489600201548a600601805490508b6009018c600801548d60070160009054906101000a900460ff168292509650965096509650965096509650919395979092949650565b61be7961d852565b8551875114801561be8b575083518651145b61befd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4172726179206c656e677468206d69736d61746368000000000000000000000081525060200191505060405180910390fd5b60008751905061bf0b61d852565b84816000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050838160200181815250504281604001818152505060008090508260405190808252806020026020018201604052801561bf9657816020015b61bf8361d8b5565b81526020019060019003908161bf7b5790505b50826080018190525060008090505b8381101561c0895760405180606001604052808c838151811061bfc457fe5b602002602001015181526020018b838151811061bfdd57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16815260200161c028848b858151811061c01057fe5b60200260200101518d61ceed9092919063ffffffff16565b8152508360800151828151811061c03b57fe5b602002602001018190525061c06c88828151811061c05557fe5b60200260200101518361ad2790919063ffffffff16565b915061c08260018261ad2790919063ffffffff16565b905061bfa5565b508193505050509695505050505050565b61c0a7816080015161cf79565b50565b60008060008360030160000154846003016001015485600301600201549250925092509193909250565b60008083141561c0e7576000905061c154565b600082840290508284828161c0f857fe5b041461c14f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061de586021913960400191505060405180910390fd5b809150505b92915050565b600061c19c83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061d082565b905092915050565b61c1ac61d70d565b604051806020016040528069d3c21bcecceda1000000815250905090565b6000601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008090505b60178054905081101561c5bb5760006017828154811061c22f57fe5b906000526020600020015490506000600f6000838152602001908152602001600020905060006003600581111561c26257fe5b61c26b8361b746565b600581111561c27657fe5b1490508061c2865750505061c5a0565b600085600301600086815260200190815260200160002090508381600101541461c30757856003016000868152602001908152602001600020600080820160006101000a81549060ff02191690556001820160009055600282016000905560038201600090556004820160009055600582016000905550505050505061c5a0565b600061c33a826005015461c32c8460040154856003015461ad2790919063ffffffff16565b61ad2790919063ffffffff16565b90508781111561c59a57600061c359898361b31490919063ffffffff16565b9050600061c36c8285600501548561d148565b9050600061c37f8386600301548661d148565b9050600061c3928487600401548761d148565b9050600061c3bb8261c3ad858761ad2790919063ffffffff16565b61ad2790919063ffffffff16565b9050600061c3d684896003015461b31490919063ffffffff16565b9050600061c3f1848a6004015461b31490919063ffffffff16565b9050600061c40c878b6005015461b31490919063ffffffff16565b90508784101561c4d157600061c42b858a61b31490919063ffffffff16565b9050600061c439828661b2d6565b905061c44e818661b31490919063ffffffff16565b945061c463818361b31490919063ffffffff16565b91506000821461c4a45761c477828561b2d6565b905061c48c818561b31490919063ffffffff16565b935061c4a1818361b31490919063ffffffff16565b91505b6000821461c4ce5761c4b6828461b2d6565b905061c4cb818461b31490919063ffffffff16565b92505b50505b8b7338afc0dc55415ae27b81c24b5a5fbfe433ebfba863cd150a6d90918c600301548d600401548e600501548888886040518863ffffffff1660e01b81526004018088815260200187815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060006040518083038186803b15801561c55e57600080fd5b505af415801561c572573d6000803e3d6000fd5b50505050808a60050181905550828a60030181905550818a6004018190555050505050505050505b50505050505b61c5b460018261ad2790919063ffffffff16565b905061c213565b50505050565b6000816000015183600001511115905092915050565b61c5df61d70d565b60008360000151148061c5f6575060008260000151145b1561c6125760405180602001604052806000815250905061ca30565b69d3c21bcecceda10000008260000151141561c6305782905061ca30565b69d3c21bcecceda10000008360000151141561c64e5781905061ca30565b600069d3c21bcecceda100000061c6648561d17f565b600001518161c66f57fe5b049050600061c67d8561d1b6565b600001519050600069d3c21bcecceda100000061c6998661d17f565b600001518161c6a457fe5b049050600061c6b28661d1b6565b600001519050600082850290506000851461c746578285828161c6d157fe5b041461c745576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b600069d3c21bcecceda1000000820290506000821461c7e85769d3c21bcecceda100000082828161c77357fe5b041461c7e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6f766572666c6f772078317931202a206669786564312064657465637465640081525060200191505060405180910390fd5b5b809150600084860290506000861461c879578486828161c80457fe5b041461c878576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b600084880290506000881461c907578488828161c89257fe5b041461c906576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b61c90f61d1f3565b878161c91757fe5b04965061c92261d1f3565b858161c92a57fe5b049450600085880290506000881461c9bb578588828161c94657fe5b041461c9ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b61c9c361d70d565b604051806020016040528087815250905061c9ec8160405180602001604052808781525061d200565b905061ca068160405180602001604052808681525061d200565b905061ca208160405180602001604052808581525061d200565b9050809a50505050505050505050505b92915050565b61ca3e61d70d565b600083600301600001549050600081141561ca655761ca5d600061d2a9565b91505061cb1f565b600084600301600101549050600061ca9f866003016002015461ca91848661ad2790919063ffffffff16565b61ad2790919063ffffffff16565b9050600061caca61cac561cab6896008015461d2a9565b8861c5d790919063ffffffff16565b61d333565b90508181111561cafc5761caf961caea838361b31490919063ffffffff16565b8461ad2790919063ffffffff16565b92505b61cb188461cb13858761ad2790919063ffffffff16565b61d354565b9450505050505b92915050565b60008160000151836000015111905092915050565b600060188260038151811061cb4b57fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c60108360028151811061cba857fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c60088460018151811061cc0557fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c8460008151811061cc6057fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161717179050919050565b600083831115829061cd44576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561cd0957808201518184015260208101905061ccee565b50505050905090810190601f16801561cd365780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b61cd5f61d70d565b61cd688261d396565b905061cd7261d70d565b61cd9e60196002016040518060200160405290816000820154815250508361c5d790919063ffffffff16565b905061cda861d70d565b61ce0661cdde601960020160405180602001604052908160008201548152505061cdd061c1a4565b61d3f290919063ffffffff16565b601960000160405180602001604052908160008201548152505061c5d790919063ffffffff16565b905061ce1b818361d20090919063ffffffff16565b60196000016000820151816000015590505061ce726019600101604051806020016040529081600082015481525050601960000160405180602001604052908160008201548152505061d49990919063ffffffff16565b1561ce8f5760196001016019600001600082015481600001559050505b7f51131d2820f04a6b6edd20e22a07d5bf847e265a3906e85256fca7d6043417c561ced2601960000160405180602001604052908160008201548152505061bca6565b6040518082815260200191505060405180910390a150505050565b60608183018451101561ceff57600080fd5b606082156000811461cf1c5760405191506020820160405261cf6d565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561cf5a578051835260208301925060208101905061cf3d565b50868552601f19601f8301166040525050505b50809150509392505050565b60008090505b815181101561d07e5761cff182828151811061cf9757fe5b60200260200101516020015183838151811061cfaf57fe5b60200260200101516000015184848151811061cfc757fe5b6020026020010151604001515185858151811061cfe057fe5b60200260200101516040015161d4ae565b61d063576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f50726f706f73616c20657865637574696f6e206661696c65640000000000000081525060200191505060405180910390fd5b61d07760018261ad2790919063ffffffff16565b905061cf7f565b5050565b6000808311829061d12e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561d0f357808201518184015260208101905061d0d8565b50505050905090810190601f16801561d1205780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161d13a57fe5b049050809150509392505050565b600061d17661d17161d15a858561d354565b61d1638761d2a9565b61c5d790919063ffffffff16565b61d333565b90509392505050565b61d18761d70d565b604051806020016040528069d3c21bcecceda10000008085600001518161d1aa57fe5b04028152509050919050565b61d1be61d70d565b604051806020016040528069d3c21bcecceda10000008085600001518161d1e157fe5b04028460000151038152509050919050565b600064e8d4a51000905090565b61d20861d70d565b600082600001518460000151019050836000015181101561d291576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f616464206f766572666c6f77206465746563746564000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808281525091505092915050565b61d2b161d70d565b61d2b961d55a565b82111561d311576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061dc8f6036913960400191505060405180910390fd5b604051806020016040528069d3c21bcecceda100000084028152509050919050565b600069d3c21bcecceda100000082600001518161d34c57fe5b049050919050565b61d35c61d70d565b61d36461d70d565b61d36d8461d2a9565b905061d37761d70d565b61d3808461d2a9565b905061d38c828261d579565b9250505092915050565b61d39e61d70d565b600061d3da836003016002015461d3cc8560030160010154866003016000015461ad2790919063ffffffff16565b61ad2790919063ffffffff16565b905061d3ea81846008015461d354565b915050919050565b61d3fa61d70d565b81600001518360000151101561d478576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f737562737472616374696f6e20756e646572666c6f772064657465637465640081525060200191505060405180910390fd5b60405180602001604052808360000151856000015103815250905092915050565b60008160000151836000015110905092915050565b600080600084111561d5365761d4c38661d6c2565b61d535576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b5b6040516020840160008287838a8c6187965a03f19250505080915050949350505050565b60007601357c299a88ea76a58924d52ce4f26a85af186c2b9e74905090565b61d58161d70d565b60008260000151141561d5fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f63616e277420646976696465206279203000000000000000000000000000000081525060200191505060405180910390fd5b600069d3c21bcecceda10000008460000151029050836000015169d3c21bcecceda1000000828161d62957fe5b041461d69d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6f766572666c6f7720617420646976696465000000000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808460000151838161d6b557fe5b0481525091505092915050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561d70457506000801b8214155b92505050919050565b6040518060200160405280600081525090565b81548183558181111561d7475781836000526020600020918201910161d746919061d8ec565b5b505050565b604051806040016040528060008152602001600081525090565b508054600082556003029060005260206000209081019061d787919061d911565b50565b50805460018160011615610100020316600290046000825580601f1061d7b0575061d7cf565b601f01602090049060005260206000209081019061d7ce919061d8ec565b5b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061d81357805160ff191683800117855561d841565b8280016001018555821561d841579182015b8281111561d84057825182559160200191906001019061d825565b5b50905061d84e919061d8ec565b5090565b604051806101000160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200161d89161d96f565b81526020016060815260200160001515815260200160008152602001606081525090565b604051806060016040528060008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b61d90e91905b8082111561d90a57600081600090555060010161d8f2565b5090565b90565b61d96c91905b8082111561d968576000808201600090556001820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560028201600061d95f919061d990565b5060030161d917565b5090565b90565b60405180606001604052806000815260200160008152602001600081525090565b50805460018160011615610100020316600290046000825580601f1061d9b6575061d9d5565b601f01602090049060005260206000209081019061d9d4919061d8ec565b5b5056fe457865637574696f6e2074696d652077696e646f772063616e6e6f74206265207a65726f5175657565457870697279206d757374206265206c6172676572207468616e20306572726f722063616c6c696e67206e756d62657256616c696461746f7273496e53657420707265636f6d70696c6550617274696369706174696f6e20626173656c696e652067726561746572207468616e206f6e654e756d626572206f662070726f706f73616c73206d757374206265206c6172676572207468616e207a65726f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734465736372697074696f6e2075726c206d7573742068617665206e6f6e2d7a65726f206c656e677468686f7466697820657865637574696f6e2074696d65206c696d6974206e6f742072656163686564426173656c696e652071756f72756d20666163746f722067726561746572207468616e206f6e655468726573686f6c642068617320746f2062652067726561746572207468616e206d616a6f7269747920616e64206e6f742067726561746572207468616e20756e616e696d6974796d73672e73656e646572206e6f7420617070726f766572206f7220536563757269747920436f756e63696c50617274696369706174696f6e20626173656c696e6520666c6f6f7220756e6368616e676564416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564426173656c696e652075706461746520666163746f722067726561746572207468616e206f6e656572726f722063616c6c696e672067657456657269666965645365616c4269746d617046726f6d48656164657220707265636f6d70696c656d73672e73656e6465722063616e6e6f742062652061646472657373207a65726f63616e277420637265617465206669786964697479206e756d626572206c6172676572207468616e206d61784e65774669786564282963616e6e6f74207570766f746520612070726f706f73616c206e6f7420696e20746865207175657565486f7466697820657865637574696f6e2074696d652077696e646f77206e6f74207365746572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d43757272656e7453657420707265636f6d70696c656572726f722063616c6c696e67206e756d62657256616c696461746f7273496e43757272656e7453657420707265636f6d70696c6554686973206d6574686f64206973206e6f206c6f6e67657220737570706f7274656420696e204c322e486f74666978206e6f7420617070726f76656420627920617070726f766572732e6572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d53657420707265636f6d70696c6550726f706f73616c206e6f7420696e20657865637574696f6e207374616765206f72206e6f742070617373696e67646571756575654672657175656e6379206d757374206265206c6172676572207468616e2030536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77457865637574696f6e2074696d65206c696d69742068617320616c7265616479206265656e20726561636865642e63616e6e6f74207570766f746520776974686f7574206c6f636b696e6720676f6c64686f74666978206e6f7420617070726f76656420627920736563757269747920636f756e63696c6572726f722063616c6c696e67206672616374696f6e4d756c45787020707265636f6d70696c656572726f722063616c6c696e672067657445706f636853697a6520707265636f6d70696c6550617274696369706174696f6e20666c6f6f722067726561746572207468616e206f6e656572726f722063616c6c696e6720676574506172656e745365616c4269746d617020707265636f6d70696c656572726f722063616c6c696e6720676574426c6f636b4e756d62657246726f6d48656164657220707265636f6d70696c6563616e6e6f74207570766f7465206d6f7265207468616e206f6e65207175657565642070726f706f73616c54686973206d6574686f64206973206e6f7420737570706f7274656420696e204c312e566f74657220646f65736e2774206861766520656e6f756768206c6f636b65642043656c6f2028666f726d65726c79206b6e6f776e2061732043656c6f20476f6c64296572726f722063616c6c696e67206861736848656164657220707265636f6d70696c6550726f766964656420696e6465782067726561746572207468616e2064657175657565206c656e6774682e486f7466697820616c726561647920707265706172656420666f7220746869732074696d656672616d652e486f74666978206e6f7420617070726f76656420627920736563757269747920636f756e63696c2ea265627a7a72315820161d67f0c7cf7e5d92c54f296066b5241eb52ca8e9f14e50cacb7583a5f8193164736f6c634300050e00320000000000000000000000000000000000000000000000000000000000000000","external_libraries":[{"name":"IntegerSortedLinkedList","address_hash":"0xa86051f29C45218B5f6CD121eBafb690660d047C"},{"name":"Proposals","address_hash":"0x38aFc0dC55415AE27b81C24b5A5FBFE433EBFBA8"}],"proxy_type":null,"implementations":[],"verified_at":"2026-03-16T15:18:41.382496Z","is_verified_via_verifier_alliance":false,"compiler_version":"v0.5.14+commit.01f1aaa4","decoded_constructor_args":[["false",{"internalType":"bool","name":"test","type":"bool"}]],"sourcify_repo_url":null,"optimization_runs":null,"compiler_settings":{"evmVersion":"istanbul","libraries":{"contracts/common/linkedlists/IntegerSortedLinkedList.sol":{"IntegerSortedLinkedList":"0xa86051f29c45218b5f6cd121ebafb690660d047c"},"contracts/governance/Proposals.sol":{"Proposals":"0x38afc0dc55415ae27b81c24b5a5fbfe433ebfba8"}},"metadata":{"useLiteralContent":false},"optimizer":{"enabled":false,"runs":200},"outputSelection":{"*":{"":["*"],"*":["*"]}},"remappings":["@celo-contracts/=contracts/","@celo-contracts-8/=contracts-0.8/","@test-sol/=test-sol/","@migrations-sol/=migrations_sol/","@lib/=lib/","celo-foundry/=lib/celo-foundry/src/","celo-foundry-8/=lib/celo-foundry-8/src/","ds-test/=lib/celo-foundry/lib/forge-std/lib/ds-test/src/","forge-std/=lib/celo-foundry/lib/forge-std/src/","forge-std-8/=lib/celo-foundry-8/lib/forge-std/src/","@mento-core/=lib/mento-core/","openzeppelin-solidity/=lib/openzeppelin-contracts/","@openzeppelin/contracts8/=lib/openzeppelin-contracts8/contracts/","@summa-tx/memview.sol/=lib/memview.sol","solidity-bytes-utils/=lib/solidity-bytes-utils/","solidity-bytes-utils-8/=lib/solidity-bytes-utils-8/","erc4626-tests/=lib/openzeppelin-contracts8/lib/erc4626-tests/","memview.sol/=lib/memview.sol/contracts/","mento-core/=lib/mento-core/contracts/","openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/","openzeppelin-contracts8/=lib/openzeppelin-contracts8/","openzeppelin/=lib/openzeppelin-contracts8/contracts/"]},"is_verified":true,"verified_twin_address_hash":null,"optimization_enabled":false,"deployed_bytecode":"0x60806040526004361061050d5760003560e01c8063745407c811610297578063b0f9984211610165578063cf48eb94116100cc578063e50e652d11610085578063e50e652d146128c5578063ec68307214612914578063ed3852741461299c578063f2fde38b14612a20578063f3f6da2c14612a71578063fae8db0a14612acc5761050d565b8063cf48eb9414612560578063d142a0f2146126ef578063d704f0c51461271a578063da35c66414612812578063df4da4611461283d578063e41db455146128685761050d565b8063c73a6d781161011e578063c73a6d78146122dd578063c7f758a814612330578063c805956d1461243e578063c8d8d2b51461247e578063cd845a76146124b9578063cea69e74146125255761050d565b8063b0f9984214611fec578063b8f7700514612027578063bab0808914612052578063bbb2eab9146121f5578063c0aee5f41461225f578063c134b2fc1461228a5761050d565b80639381ab2511610209578063a91ee0dc116101c2578063a91ee0dc14611d9f578063aa2feb8314611df0578063ad78c10914611e3f578063add004df14611e6a578063af108a0e14611eb9578063af20311014611f165761050d565b80639381ab2514611bde57806397b9eba614611c0d57806398f4270214611c9b5780639a7b3be714611cea5780639b2b592f14611d155780639cb02dfc14611d645761050d565b806387ee8a0f1161025b57806387ee8a0f146119eb5780638a88362614611a165780638da5cb5b14611af25780638e905ed614611b495780638f32d59b14611b745780638fcc9cfb14611ba35761050d565b8063745407c8146118a057806377d26a2a146118db5780637910867b146119065780637b103999146119595780638018556e146119b05761050d565b80633ccfd60b116103df5780635d35a3d91161034657806366547163116102ff578063665471631461165e57806367960e91146116c35780636de8a63b1461179f5780636f2ab6931461180b578063715018a61461185e5780637385e5da146118755761050d565b80635d35a3d9146112855780635f115a85146112e25780635f8dd6491461137457806360b4d34d146113dd57806365bbdaa0146114425780636643ac58146116235761050d565b806354255be01161039857806354255be0146110645780635601eaea146110a45780635733397814611101578063582ae53b146111685780635c759394146111c55780635d180adb146112005761050d565b80633ccfd60b14610e415780633db9dd9a14610e7057806341b3d18514610eab57806345a7849914610ed65780634b2c2f4414610f4d5780635093564d146110295761050d565b80631c1083e2116104835780632c0523551161043c5780632c05235514610ca95780632edfd12e14610ce457806330a095d014610d5f5780633156560e14610d8a5780633b1eb4bf14610ddb5780633bb0ed2b14610e2a5761050d565b80631c1083e2146109775780631c65bc61146109c857806323f0ab6514610a035780632762132114610b9a57806327eb6c0f14610bed578063283aaefb14610c445761050d565b80631201a0fb116104d55780631201a0fb1461079b578063123633ea146107c65780631374b22d14610841578063141a8dd814610894578063152b4834146108eb578063158ef93e146109485761050d565b806301fce27e1461058857806304acaec91461063c5780630e0b78ae146106775780630f717e42146106e757806311fb9e8414610720575b60008036905014610586576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f756e6b6e6f776e206d6574686f6400000000000000000000000000000000000081525060200191505060405180910390fd5b005b34801561059457600080fd5b5061059d612b1b565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156105e45780820151818401526020810190506105c9565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561062657808201518184015260208101905061060b565b5050505090500194505050505060405180910390f35b34801561064857600080fd5b506106756004803603602081101561065f57600080fd5b8101908080359060200190929190505050612ce0565b005b34801561068357600080fd5b506106b06004803603602081101561069a57600080fd5b8101908080359060200190929190505050612eb8565b6040518085151515158152602001841515151581526020018315151515815260200182815260200194505050505060405180910390f35b3480156106f357600080fd5b506106fc612f50565b60405180848152602001838152602001828152602001935050505060405180910390f35b34801561072c57600080fd5b506107596004803603602081101561074357600080fd5b8101908080359060200190929190505050612f68565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a757600080fd5b506107b0613061565b6040518082815260200191505060405180910390f35b3480156107d257600080fd5b506107ff600480360360208110156107e957600080fd5b8101908080359060200190929190505050613067565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561084d57600080fd5b5061087a6004803603602081101561086457600080fd5b8101908080359060200190929190505050613121565b604051808215151515815260200191505060405180910390f35b3480156108a057600080fd5b506108a9613145565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108f757600080fd5b5061092e6004803603604081101561090e57600080fd5b81019080803590602001909291908035906020019092919050505061316b565b604051808215151515815260200191505060405180910390f35b34801561095457600080fd5b5061095d613192565b604051808215151515815260200191505060405180910390f35b34801561098357600080fd5b506109c66004803603602081101561099a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506131a5565b005b3480156109d457600080fd5b50610a01600480360360208110156109eb57600080fd5b81019080803590602001909291905050506134d1565b005b348015610a0f57600080fd5b50610b8060048036036060811015610a2657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610a6357600080fd5b820183602082011115610a7557600080fd5b80359060200191846001830284011164010000000083111715610a9757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190640100000000811115610afa57600080fd5b820183602082011115610b0c57600080fd5b80359060200191846001830284011164010000000083111715610b2e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061368c565b604051808215151515815260200191505060405180910390f35b348015610ba657600080fd5b50610bd360048036036020811015610bbd57600080fd5b810190808035906020019092919050505061384e565b604051808215151515815260200191505060405180910390f35b348015610bf957600080fd5b50610c02613872565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610c5057600080fd5b50610c9360048036036020811015610c6757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613898565b6040518082815260200191505060405180910390f35b348015610cb557600080fd5b50610ce260048036036020811015610ccc57600080fd5b81019080803590602001909291905050506138e4565b005b348015610cf057600080fd5b50610d45600480360360a0811015610d0757600080fd5b810190808035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050613a71565b604051808215151515815260200191505060405180910390f35b348015610d6b57600080fd5b50610d74613de3565b6040518082815260200191505060405180910390f35b348015610d9657600080fd5b50610dd960048036036020811015610dad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613df0565b005b348015610de757600080fd5b50610e1460048036036020811015610dfe57600080fd5b810190808035906020019092919050505061411c565b6040518082815260200191505060405180910390f35b348015610e3657600080fd5b50610e3f6141de565b005b348015610e4d57600080fd5b50610e566145dd565b604051808215151515815260200191505060405180910390f35b348015610e7c57600080fd5b50610ea960048036036020811015610e9357600080fd5b8101908080359060200190929190505050614815565b005b348015610eb757600080fd5b50610ec06149ed565b6040518082815260200191505060405180910390f35b348015610ee257600080fd5b50610f0f60048036036020811015610ef957600080fd5b81019080803590602001909291905050506149f3565b604051808615151515815260200185151515158152602001848152602001831515151581526020018281526020019550505050505060405180910390f35b348015610f5957600080fd5b5061101360048036036020811015610f7057600080fd5b8101908080359060200190640100000000811115610f8d57600080fd5b820183602082011115610f9f57600080fd5b80359060200191846001830284011164010000000083111715610fc157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050614a50565b6040518082815260200191505060405180910390f35b34801561103557600080fd5b506110626004803603602081101561104c57600080fd5b8101908080359060200190929190505050614bec565b005b34801561107057600080fd5b50611079614e2b565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b3480156110b057600080fd5b506110e7600480360360408110156110c757600080fd5b810190808035906020019092919080359060200190929190505050614e53565b604051808215151515815260200191505060405180910390f35b34801561110d57600080fd5b5061114e6004803603606081101561112457600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506150b9565b604051808215151515815260200191505060405180910390f35b34801561117457600080fd5b506111a16004803603602081101561118b57600080fd5b810190808035906020019092919050505061574e565b604051808260058111156111b157fe5b60ff16815260200191505060405180910390f35b3480156111d157600080fd5b506111fe600480360360208110156111e857600080fd5b81019080803590602001909291905050506157df565b005b34801561120c57600080fd5b506112436004803603604081101561122357600080fd5b8101908080359060200190929190803590602001909291905050506159b7565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561129157600080fd5b506112c8600480360360408110156112a857600080fd5b810190808035906020019092919080359060200190929190505050615b11565b604051808215151515815260200191505060405180910390f35b3480156112ee57600080fd5b5061133b6004803603604081101561130557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050615e17565b60405180878152602001868152602001858152602001848152602001838152602001828152602001965050505050505060405180910390f35b34801561138057600080fd5b506113c36004803603602081101561139757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615ec4565b604051808215151515815260200191505060405180910390f35b3480156113e957600080fd5b5061142c6004803603602081101561140057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615f95565b6040518082815260200191505060405180910390f35b61160d600480360360a081101561145857600080fd5b810190808035906020019064010000000081111561147557600080fd5b82018360208201111561148757600080fd5b803590602001918460208302840111640100000000831117156114a957600080fd5b9091929391929390803590602001906401000000008111156114ca57600080fd5b8201836020820111156114dc57600080fd5b803590602001918460208302840111640100000000831117156114fe57600080fd5b90919293919293908035906020019064010000000081111561151f57600080fd5b82018360208201111561153157600080fd5b8035906020019184600183028401116401000000008311171561155357600080fd5b90919293919293908035906020019064010000000081111561157457600080fd5b82018360208201111561158657600080fd5b803590602001918460208302840111640100000000831117156115a857600080fd5b9091929391929390803590602001906401000000008111156115c957600080fd5b8201836020820111156115db57600080fd5b803590602001918460018302840111640100000000831117156115fd57600080fd5b9091929391929390505050615fad565b6040518082815260200191505060405180910390f35b34801561162f57600080fd5b5061165c6004803603602081101561164657600080fd5b8101908080359060200190929190505050616329565b005b34801561166a57600080fd5b506116ad6004803603602081101561168157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506164d9565b6040518082815260200191505060405180910390f35b3480156116cf57600080fd5b50611789600480360360208110156116e657600080fd5b810190808035906020019064010000000081111561170357600080fd5b82018360208201111561171557600080fd5b8035906020019184600183028401116401000000008311171561173757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050616758565b6040518082815260200191505060405180910390f35b3480156117ab57600080fd5b506117b46168f4565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156117f75780820151818401526020810190506117dc565b505050509050019250505060405180910390f35b34801561181757600080fd5b506118446004803603602081101561182e57600080fd5b810190808035906020019092919050505061694c565b604051808215151515815260200191505060405180910390f35b34801561186a57600080fd5b5061187361697e565b005b34801561188157600080fd5b5061188a616ab7565b6040518082815260200191505060405180910390f35b3480156118ac57600080fd5b506118d9600480360360208110156118c357600080fd5b8101908080359060200190929190505050616acf565b005b3480156118e757600080fd5b506118f0616be3565b6040518082815260200191505060405180910390f35b34801561191257600080fd5b5061193f6004803603602081101561192957600080fd5b8101908080359060200190929190505050616be9565b604051808215151515815260200191505060405180910390f35b34801561196557600080fd5b5061196e616c0d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156119bc57600080fd5b506119e9600480360360208110156119d357600080fd5b8101908080359060200190929190505050616c33565b005b3480156119f757600080fd5b50611a00616dc0565b6040518082815260200191505060405180910390f35b348015611a2257600080fd5b50611adc60048036036020811015611a3957600080fd5b8101908080359060200190640100000000811115611a5657600080fd5b820183602082011115611a6857600080fd5b80359060200191846001830284011164010000000083111715611a8a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050616e6c565b6040518082815260200191505060405180910390f35b348015611afe57600080fd5b50611b07617008565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015611b5557600080fd5b50611b5e617031565b6040518082815260200191505060405180910390f35b348015611b8057600080fd5b50611b89617037565b604051808215151515815260200191505060405180910390f35b348015611baf57600080fd5b50611bdc60048036036020811015611bc657600080fd5b8101908080359060200190929190505050617095565b005b348015611bea57600080fd5b50611bf361723f565b604051808215151515815260200191505060405180910390f35b348015611c1957600080fd5b50611c8560048036036040811015611c3057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061792a565b6040518082815260200191505060405180910390f35b348015611ca757600080fd5b50611cd460048036036020811015611cbe57600080fd5b8101908080359060200190929190505050617946565b6040518082815260200191505060405180910390f35b348015611cf657600080fd5b50611cff617a5f565b6040518082815260200191505060405180910390f35b348015611d2157600080fd5b50611d4e60048036036020811015611d3857600080fd5b8101908080359060200190929190505050617a6f565b6040518082815260200191505060405180910390f35b348015611d7057600080fd5b50611d9d60048036036020811015611d8757600080fd5b8101908080359060200190929190505050617bc0565b005b348015611dab57600080fd5b50611dee60048036036020811015611dc257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050617e5f565b005b348015611dfc57600080fd5b50611e2960048036036020811015611e1357600080fd5b8101908080359060200190929190505050618003565b6040518082815260200191505060405180910390f35b348015611e4b57600080fd5b50611e54618024565b6040518082815260200191505060405180910390f35b348015611e7657600080fd5b50611ea360048036036020811015611e8d57600080fd5b8101908080359060200190929190505050618031565b6040518082815260200191505060405180910390f35b348015611ec557600080fd5b50611efc60048036036040811015611edc57600080fd5b810190808035906020019092919080359060200190929190505050618052565b604051808215151515815260200191505060405180910390f35b348015611f2257600080fd5b50611fea6004803603610180811015611f3a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291905050506184e5565b005b348015611ff857600080fd5b506120256004803603602081101561200f57600080fd5b810190808035906020019092919050505061860d565b005b34801561203357600080fd5b5061203c61894b565b6040518082815260200191505060405180910390f35b34801561205e57600080fd5b506121df600480360360a081101561207557600080fd5b810190808035906020019064010000000081111561209257600080fd5b8201836020820111156120a457600080fd5b803590602001918460208302840111640100000000831117156120c657600080fd5b9091929391929390803590602001906401000000008111156120e757600080fd5b8201836020820111156120f957600080fd5b8035906020019184602083028401116401000000008311171561211b57600080fd5b90919293919293908035906020019064010000000081111561213c57600080fd5b82018360208201111561214e57600080fd5b8035906020019184600183028401116401000000008311171561217057600080fd5b90919293919293908035906020019064010000000081111561219157600080fd5b8201836020820111156121a357600080fd5b803590602001918460208302840111640100000000831117156121c557600080fd5b90919293919293908035906020019092919050505061895b565b6040518082815260200191505060405180910390f35b34801561220157600080fd5b506122456004803603606081101561221857600080fd5b810190808035906020019092919080359060200190929190803560ff169060200190929190505050618a6c565b604051808215151515815260200191505060405180910390f35b34801561226b57600080fd5b50612274618ed4565b6040518082815260200191505060405180910390f35b34801561229657600080fd5b506122c3600480360360208110156122ad57600080fd5b8101908080359060200190929190505050618eda565b604051808215151515815260200191505060405180910390f35b3480156122e957600080fd5b506123166004803603602081101561230057600080fd5b8101908080359060200190929190505050618efe565b604051808215151515815260200191505060405180910390f35b34801561233c57600080fd5b506123696004803603602081101561235357600080fd5b8101908080359060200190929190505050618f9c565b604051808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018781526020018681526020018581526020018060200184815260200183151515158152602001828103825285818151815260200191508051906020019080838360005b838110156123fd5780820151818401526020810190506123e2565b50505050905090810190601f16801561242a5780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390f35b34801561244a57600080fd5b50612453619077565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b34801561248a57600080fd5b506124b7600480360360208110156124a157600080fd5b8101908080359060200190929190505050619113565b005b3480156124c557600080fd5b50612508600480360360208110156124dc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506192a0565b604051808381526020018281526020019250505060405180910390f35b34801561253157600080fd5b5061255e6004803603602081101561254857600080fd5b8101908080359060200190929190505050619322565b005b34801561256c57600080fd5b506126ed600480360360a081101561258357600080fd5b81019080803590602001906401000000008111156125a057600080fd5b8201836020820111156125b257600080fd5b803590602001918460208302840111640100000000831117156125d457600080fd5b9091929391929390803590602001906401000000008111156125f557600080fd5b82018360208201111561260757600080fd5b8035906020019184602083028401116401000000008311171561262957600080fd5b90919293919293908035906020019064010000000081111561264a57600080fd5b82018360208201111561265c57600080fd5b8035906020019184600183028401116401000000008311171561267e57600080fd5b90919293919293908035906020019064010000000081111561269f57600080fd5b8201836020820111156126b157600080fd5b803590602001918460208302840111640100000000831117156126d357600080fd5b9091929391929390803590602001909291905050506194d2565b005b3480156126fb57600080fd5b5061270461990d565b6040518082815260200191505060405180910390f35b34801561272657600080fd5b5061275d6004803603604081101561273d57600080fd5b810190808035906020019092919080359060200190929190505050619913565b604051808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b838110156127d55780820151818401526020810190506127ba565b50505050905090810190601f1680156128025780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b34801561281e57600080fd5b50612827619a9d565b6040518082815260200191505060405180910390f35b34801561284957600080fd5b50612852619aa3565b6040518082815260200191505060405180910390f35b34801561287457600080fd5b506128a16004803603602081101561288b57600080fd5b8101908080359060200190929190505050619bfa565b60405180848152602001838152602001828152602001935050505060405180910390f35b3480156128d157600080fd5b506128fe600480360360208110156128e857600080fd5b8101908080359060200190929190505050619c27565b6040518082815260200191505060405180910390f35b34801561292057600080fd5b5061297f600480360360c081101561293757600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050619c7a565b604051808381526020018281526020019250505060405180910390f35b3480156129a857600080fd5b50612a1e600480360360608110156129bf57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080359060200190929190505050619e96565b005b348015612a2c57600080fd5b50612a6f60048036036020811015612a4357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061a1d3565b005b348015612a7d57600080fd5b50612aca60048036036040811015612a9457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061a259565b005b348015612ad857600080fd5b50612b0560048036036020811015612aef57600080fd5b810190808035906020019092919050505061a30f565b6040518082815260200191505060405180910390f35b606080601273a86051f29c45218b5f6cd121ebafb690660d047c6369b317e390916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b158015612b7057600080fd5b505af4158015612b84573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052506040811015612bae57600080fd5b8101908080516040519392919084640100000000821115612bce57600080fd5b83820191506020820185811115612be457600080fd5b8251866020820283011164010000000082111715612c0157600080fd5b8083526020830192505050908051906020019060200280838360005b83811015612c38578082015181840152602081019050612c1d565b5050505090500160405260200180516040519392919084640100000000821115612c6157600080fd5b83820191506020820185811115612c7757600080fd5b8251866020820283011164010000000082111715612c9457600080fd5b8083526020830192505050908051906020019060200280838360005b83811015612ccb578082015181840152602081019050612cb0565b50505050905001604052505050915091509091565b612ce8617037565b612d5a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612d6261d70d565b612d6b8261a460565b9050612d768161a47e565b612dcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061db156027913960400191505060405180910390fd5b612df760196003016040518060200160405290816000820154815250508261a49890919063ffffffff16565b15612e6a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f426173656c696e652071756f72756d20666163746f7220756e6368616e67656481525060200191505060405180910390fd5b806019600301600082015181600001559050507fddfdbe55eaaa70fe2b8bc82a9b0734c25cabe7cb6f1457f9644019f0b5ff91fc826040518082815260200191505060405180910390a15050565b6000806000806011600086815260200190815260200160002060000160019054906101000a900460ff166011600087815260200190815260200160002060030160009054906101000a900460ff166011600088815260200190815260200160002060000160009054906101000a900460ff16601160008981526020019081526020016000206004015493509350935093509193509193565b60038060000154908060010154908060020154905083565b6000612f7261a4ad565b612fc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018061dfe86023913960400191505060405180910390fd5b612fcf61a4de565b73ffffffffffffffffffffffffffffffffffffffff16638657f615836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561301f57600080fd5b505afa158015613033573d6000803e3d6000fd5b505050506040513d602081101561304957600080fd5b81019080805190602001909291905050509050919050565b600a5481565b600061307161a4ad565b156131105761307e61a4de565b73ffffffffffffffffffffffffffffffffffffffff16632ba47274836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156130ce57600080fd5b505afa1580156130e2573d6000803e3d6000fd5b505050506040513d60208110156130f857600080fd5b8101908080519060200190929190505050905061311c565b6131198261a5d9565b90505b919050565b600061313e600f600084815260200190815260200160002061a732565b9050919050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061318a600f6000858152602001908152602001600020848461a742565b905092915050565b600060149054906101000a900460ff1681565b6131ad617037565b61321f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156132c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f436f756e63696c2063616e6e6f742062652061646472657373207a65726f000081525060200191505060405180910390fd5b601d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613386576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f436f756e63696c20756e6368616e67656400000000000000000000000000000081525060200191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561344a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f436f756e63696c2063616e6e6f7420626520617070726f76657200000000000081525060200191505060405180910390fd5b80601d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f7683fab01f2423e9d93e84c60129ec97b5121526e34c75e52149bc7baea934c060405160405180910390a250565b6134d9617037565b61354b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61355361d70d565b61355c8261a460565b90506135678161a47e565b6135bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061df3c6024913960400191505060405180910390fd5b6135e860196001016040518060200160405290816000820154815250508261a49890919063ffffffff16565b1561363e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061dbaf6026913960400191505060405180910390fd5b806019600101600082015181600001559050507f122a37b609e0f758b6a23c43506cb567017a4d18b21fa91312fb42b44975a5b5826040518082815260200191505060405180910390a15050565b600061369661a7d5565b600060fb73ffffffffffffffffffffffffffffffffffffffff16858585604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140183805190602001908083835b6020831061371e57805182526020820191506020810190506020830392506136fb565b6001836020036101000a03801982511681845116808217855250505050505090500182805190602001908083835b6020831061376f578051825260208201915060208101905060208303925061374c565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b602083106137d857805182526020820191506020810190506020830392506137b5565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613838576040519150601f19603f3d011682016040523d82523d6000602084013e61383d565b606091505b505080915050809150509392505050565b600061386b600f600084815260200190815260200160002061a835565b9050919050565b601d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201549050919050565b6138ec617037565b61395e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008114156139b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061d9fd6021913960400191505060405180910390fd5b600654811415613a30576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f517565756545787069727920756e6368616e676564000000000000000000000081525060200191505060405180910390fd5b806006819055507f4ecbf0bb0701615e2d6f9b0a0996056c959fe359ce76aa7ce06c5f1d57dae4d7816040518082815260200191505060405180910390a150565b60006001806000828254019250508190555060006001549050613a926141de565b600080613a9f898961aa55565b91509150613aac8261a732565b613abb57600093505050613d62565b60036005811115613ac857fe5b816005811115613ad457fe5b14613b47576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e636f72726563742070726f706f73616c207374617465000000000000000081525060200191505060405180910390fd5b6000613b5161ab31565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015613bcd57600080fd5b505afa158015613be1573d6000803e3d6000fd5b505050506040513d6020811015613bf757600080fd5b810190808051906020019092919050505090506000613c1461ac2c565b73ffffffffffffffffffffffffffffffffffffffff166361d5c570836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015613c9057600080fd5b505afa158015613ca4573d6000803e3d6000fd5b505050506040513d6020811015613cba57600080fd5b81019080805190602001909291905050509050613cf287613ce48a8c61ad2790919063ffffffff16565b61ad2790919063ffffffff16565b811015613d4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604381526020018061e00b6043913960600191505060405180910390fd5b613d59848c8c858d8d8d61adaf565b60019550505050505b6001548114613dd9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5095945050505050565b6000600360020154905090565b613df8617037565b613e6a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613f0d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f417070726f7665722063616e6e6f74206265203000000000000000000000000081525060200191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613fd1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f417070726f76657220756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b601d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415614095576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f417070726f7665722063616e6e6f7420626520636f756e63696c00000000000081525060200191505060405180910390fd5b80600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fa03757d836cb0b61c0fbba2147f5d51d6071ff3dd5bf6963beb55563d64878e160405160405180910390a250565b600061412661a4ad565b156141c55761413361a4de565b73ffffffffffffffffffffffffffffffffffffffff16633b1eb4bf836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561418357600080fd5b505afa158015614197573d6000803e3d6000fd5b505050506040513d60208110156141ad57600080fd5b810190808051906020019092919050505090506141d9565b6141d6826141d1619aa3565b61b28e565b90505b919050565b6141f560075460095461ad2790919063ffffffff16565b42106145db576000614211600a5460126000016002015461b2d6565b90506060601273a86051f29c45218b5f6cd121ebafb690660d047c6377b024799091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561426f57600080fd5b505af4158015614283573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156142ad57600080fd5b81019080805160405193929190846401000000008211156142cd57600080fd5b838201915060208201858111156142e357600080fd5b825186602082028301116401000000008211171561430057600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561433757808201518184015260208101905061431c565b505050509050016040525050509050600080905060008090505b838110156145c857600083828151811061436757fe5b602002602001015190506000600f600083815260200190815260200160002090506143918161b2ef565b156143ca57817f88e53c486703527139dfc8d97a1e559d9bd93d3f9d52cda4e06564111e7a264360405160405180910390a250506145ad565b6144448160010154600d60008460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461ad2790919063ffffffff16565b600d60008360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055504281600201819055506000601880549050146145415760006144dc600160188054905061b31490919063ffffffff16565b9050826017601883815481106144ee57fe5b90600052602060002001548154811061450357fe5b90600052602060002001819055506018818154811061451e57fe5b90600052602060002001600090558060188161453a919061d720565b505061456e565b60178290806001815401808255809150509060018203906000526020600020016000909192909190915055505b817f3e069fb74dcf5fbc07740b0d40d7f7fc48e9c0ca5dc3d19eb34d2e05d74c5543426040518082815260200191505060405180910390a26001935050505b6145c160018261ad2790919063ffffffff16565b9050614351565b5080156145d757426009819055505b5050505b565b600060018060008282540192505081905550600060015490506000600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008114156146b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f4e6f7468696e6720746f2077697468647261770000000000000000000000000081525060200191505060405180910390fd5b47811115614727576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f496e636f6e73697374656e742062616c616e636500000000000000000000000081525060200191505060405180910390fd5b6000600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550614795813373ffffffffffffffffffffffffffffffffffffffff1661b35e90919063ffffffff16565b60019250506001548114614811576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5090565b61481d617037565b61488f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61489761d70d565b6148a08261a460565b90506148ab8161a47e565b614900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061da4c6027913960400191505060405180910390fd5b61492c60196000016040518060200160405290816000820154815250508261a49890919063ffffffff16565b1561499f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f50617274696369706174696f6e20626173656c696e6520756e6368616e67656481525060200191505060405180910390fd5b806019600001600082015181600001559050507f51131d2820f04a6b6edd20e22a07d5bf847e265a3906e85256fca7d6043417c5826040518082815260200191505060405180910390a15050565b600c5481565b60116020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060010154908060030160009054906101000a900460ff16908060040154905085565b6000614a5a61a7d5565b6060600060f473ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b60208310614aad5780518252602082019150602081019050602083039250614a8a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310614b145780518252602082019150602081019050602083039250614af1565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114614b74576040519150601f19603f3d011682016040523d82523d6000602084013e614b79565b606091505b50809350819250505080614bd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603881526020018061dc366038913960400191505060405180910390fd5b614be382600061b498565b92505050919050565b806011600082815260200190815260200160002060000160009054906101000a900460ff1615614c84576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b816000601160008381526020019081526020016000206004015411614d11576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f686f74666978206e6f742070726570617265640000000000000000000000000081525060200191505060405180910390fd5b42601160008381526020019081526020016000206004015410614d7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061daee6027913960400191505060405180910390fd5b60006011600085815260200190815260200160002060000160016101000a81548160ff02191690831515021790555060006011600085815260200190815260200160002060030160006101000a81548160ff02191690831515021790555060006011600085815260200190815260200160002060040181905550827f5af07e8248de542d5637f35c0538561c1f4867fa0545011255a5de4087ecf52260405160405180910390a2505050565b6000806000806001600560016000839350829250819150809050935093509350935090919293565b60006001806000828254019250508190555060006001549050614e746141de565b600080614e81868661aa55565b915091506000614e908361a732565b9050801561503557614ea18361b539565b614f13576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f50726f706f73616c206e6f7420617070726f766564000000000000000000000081525060200191505060405180910390fd5b60046005811115614f2057fe5b826005811115614f2c57fe5b148015614f3e5750614f3d8361a835565b5b614f93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061de04602e913960400191505060405180910390fd5b827338afc0dc55415ae27b81c24b5a5fbfe433ebfba863c67e7b4b90916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b158015614fe457600080fd5b505af4158015614ff8573d6000803e3d6000fd5b50505050867f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f60405160405180910390a261503483888861b554565b5b80945050505060015481146150b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5092915050565b600060018060008282540192505081905550600060015490506150da6141de565b6150e38561b673565b156150f157600091506156cf565b60006150fb61ab31565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561517757600080fd5b505afa15801561518b573d6000803e3d6000fd5b505050506040513d60208110156151a157600080fd5b810190808051906020019092919050505090506000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050615207816000016000015461b673565b50600061521261ac2c565b73ffffffffffffffffffffffffffffffffffffffff166330ec70f5846040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561528e57600080fd5b505afa1580156152a2573d6000803e3d6000fd5b505050506040513d60208110156152b857600080fd5b8101908080519060200190929190505050905060008111615324576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061dea76022913960400191505060405180910390fd5b601273a86051f29c45218b5f6cd121ebafb690660d047c63bfc5163890918a6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561537e57600080fd5b505af4158015615392573d6000803e3d6000fd5b505050506040513d60208110156153a857600080fd5b810190808051906020019092919050505061540e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061dcc56029913960400191505060405180910390fd5b6000826000016000015414806154bd5750601273a86051f29c45218b5f6cd121ebafb690660d047c63bfc51638909184600001600001546040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561548057600080fd5b505af4158015615494573d6000803e3d6000fd5b505050506040513d60208110156154aa57600080fd5b8101908080519060200190929190505050155b615512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061dfbd602b913960400191505060405180910390fd5b60006155bb82601273a86051f29c45218b5f6cd121ebafb690660d047c637577759990918d6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561557257600080fd5b505af4158015615586573d6000803e3d6000fd5b505050506040513d602081101561559c57600080fd5b810190808051906020019092919050505061ad2790919063ffffffff16565b9050601273a86051f29c45218b5f6cd121ebafb690660d047c63239491ba90918b848c8c6040518663ffffffff1660e01b8152600401808681526020018581526020018481526020018381526020018281526020019550505050505060006040518083038186803b15801561562f57600080fd5b505af4158015615643573d6000803e3d6000fd5b5050505060405180604001604052808a8152602001838152508360000160008201518160000155602082015181600101559050508373ffffffffffffffffffffffffffffffffffffffff16897fd19965d25ef670a1e322fbf05475924b7b12d81fd6b96ab718b261782efb3d62846040518082815260200191505060405180910390a360019550505050505b6001548114615746576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b509392505050565b60008082148061575f5750600b5482115b1561576d57600090506157da565b6000600f6000848152602001908152602001600020905061578d83618efe565b156157b15761579b8161b2ef565b6157a65760016157a9565b60055b9150506157da565b60006157bc8261b746565b90506157c8828261b7fd565b6157d257806157d5565b60055b925050505b919050565b6157e7617037565b615859576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61586161d70d565b61586a8261a460565b90506158758161a47e565b6158ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061dc0f6027913960400191505060405180910390fd5b6158f660196002016040518060200160405290816000820154815250508261a49890919063ffffffff16565b15615969576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f426173656c696e652075706461746520666163746f7220756e6368616e67656481525060200191505060405180910390fd5b806019600201600082015181600001559050507f8dedb4d995dd500718c7c5f6a077fba6153a7ee063da961d9fcab90ff528ac1f826040518082815260200191505060405180910390a15050565b60006159c161a7d5565b6060600060fa73ffffffffffffffffffffffffffffffffffffffff16858560405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310615a385780518252602082019150602081019050602083039250615a15565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114615a98576040519150601f19603f3d011682016040523d82523d6000602084013e615a9d565b606091505b50809350819250505080615afc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061ddce6036913960400191505060405180910390fd5b615b0782600061b854565b9250505092915050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614615bd6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f6d73672e73656e646572206e6f7420617070726f76657200000000000000000081525060200191505060405180910390fd5b615bde6141de565b600080615beb858561aa55565b91509150615bf88261a732565b615c0757600092505050615e11565b615c108261b539565b15615c83576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f50726f706f73616c20616c726561647920617070726f7665640000000000000081525060200191505060405180910390fd5b60036005811115615c9057fe5b816005811115615c9c57fe5b1480615cbe575060046005811115615cb057fe5b816005811115615cbc57fe5b145b615d30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f50726f706f73616c206e6f7420696e20636f727265637420737461676500000081525060200191505060405180910390fd5b60018260070160006101000a81548160ff021916908315150217905550615d5561ac2c565b73ffffffffffffffffffffffffffffffffffffffff166330a61d596040518163ffffffff1660e01b815260040160206040518083038186803b158015615d9a57600080fd5b505afa158015615dae573d6000803e3d6000fd5b505050506040513d6020811015615dc457600080fd5b81019080805190602001909291905050508260080181905550847f28ec9e38ba73636ceb2f6c1574136f83bd46284a3c74734b711bf45e12f8d92960405160405180910390a26001925050505b92915050565b6000806000806000806000601060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003016000898152602001908152602001600020905080600101548160000160009054906101000a900460ff166003811115615e9957fe5b8260020154836003015484600401548560050154965096509650965096509650509295509295509295565b600080601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816000016000015490506000808214158015615f2b5750615f2a82618efe565b5b8015615f3d5750615f3b82618eda565b155b90506000600f6000856002015481526020019081526020016000209050600060036005811115615f6957fe5b615f728361b746565b6005811115615f7d57fe5b1490508280615f895750805b95505050505050919050565b600d6020528060005260406000206000915090505481565b6000615fb76141de565b600c5434101561602f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f546f6f20736d616c6c206465706f73697400000000000000000000000000000081525060200191505060405180910390fd5b6160456001600b5461ad2790919063ffffffff16565b600b819055506000600f6000600b5481526020019081526020016000209050807338afc0dc55415ae27b81c24b5a5fbfe433ebfba8633053123f90918e8e8e8e8e8e8e8e33346040518c63ffffffff1660e01b8152600401808c8152602001806020018060200180602001806020018773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186815260200185810385528f8f82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810384528d8d82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810383528b8b82818152602001925080828437600081840152601f19601f8201169050808301925050508581038252898982818152602001925060200280828437600081840152601f19601f8201169050808301925050509f5050505050505050505050505050505060006040518083038186803b1580156161ca57600080fd5b505af41580156161de573d6000803e3d6000fd5b5050505061623984848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508261b86b90919063ffffffff16565b601273a86051f29c45218b5f6cd121ebafb690660d047c63d7a8acc19091600b546040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561629557600080fd5b505af41580156162a9573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff16600b547f1bfe527f3548d9258c2512b6689f0acfccdd0557d80a53845db25fc57e93d8fe8360060180549050344260405180848152602001838152602001828152602001935050505060405180910390a3600b549150509a9950505050505050505050565b616331617037565b6163a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600081141561641a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4475726174696f6e206d757374206265206c6172676572207468616e2030000081525060200191505060405180910390fd5b600360020154811415616495576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4475726174696f6e20756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b806003600201819055507f7819c8059302d1d66abc7fe228ecc02214e0bc5c529956c13717aabefce937d8816040518082815260200191505060405180910390a150565b600080601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816000016000015490506000808214158015616540575061653f82618efe565b5b8015616552575061655082618eda565b155b9050600080905081156166215761656761ac2c565b73ffffffffffffffffffffffffffffffffffffffff166330ec70f5876040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156165e357600080fd5b505afa1580156165f7573d6000803e3d6000fd5b505050506040513d602081101561660d57600080fd5b810190808051906020019092919050505090505b600080905060008090505b6017805490508110156167415760006017828154811061664857fe5b906000526020600020015490506000600f6000838152602001908152602001600020905060006003600581111561667b57fe5b6166848361b746565b600581111561668f57fe5b1490508061669f57505050616726565b60008960030160008681526020019081526020016000209050838160010154146166cc5750505050616726565b60006166ff82600501546166f18460040154856003015461ad2790919063ffffffff16565b61ad2790919063ffffffff16565b905061671e87600083146167135782616719565b83600201545b61b8e3565b965050505050505b61673a60018261ad2790919063ffffffff16565b905061662c565b5061674c828261b8e3565b95505050505050919050565b600061676261a7d5565b6060600060f673ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b602083106167b55780518252602082019150602081019050602083039250616792565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b6020831061681c57805182526020820191506020810190506020830392506167f9565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461687c576040519150601f19603f3d011682016040523d82523d6000602084013e616881565b606091505b508093508192505050806168e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018061e04e6023913960400191505060405180910390fd5b6168eb82600061b498565b92505050919050565b6060601780548060200260200160405190810160405280929190818152602001828054801561694257602002820191906000526020600020905b81548152602001906001019080831161692e575b5050505050905090565b600080600f60008481526020019081526020016000209050616976816169718361b746565b61b7fd565b915050919050565b616986617037565b6169f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000616ac161a7d5565b616aca43619c27565b905090565b616ad7617037565b616b49576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111616ba2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061d9d96024913960400191505060405180910390fd5b80601e819055507f14990942cf0411abf738b62b62c43f745c43655bde245941493d710999f4a9cc816040518082815260200191505060405180910390a150565b60075481565b6000616c06600f600084815260200190815260200160002061b539565b9050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b616c3b617037565b616cad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000811415616d07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061de326026913960400191505060405180910390fd5b600754811415616d7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f646571756575654672657175656e637920756e6368616e67656400000000000081525060200191505060405180910390fd5b806007819055507f391e82aae76c653cd640ad1b6028e2ee39ca4f29b30152e3d0a9ddd7e1169c34816040518082815260200191505060405180910390a150565b6000616dca61a4ad565b15616e5e57616dd761a4de565b73ffffffffffffffffffffffffffffffffffffffff1663639a84d36040518163ffffffff1660e01b815260040160206040518083038186803b158015616e1c57600080fd5b505afa158015616e30573d6000803e3d6000fd5b505050506040513d6020811015616e4657600080fd5b81019080805190602001909291905050509050616e69565b616e6661b8fd565b90505b90565b6000616e7661a7d5565b6060600060f773ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b60208310616ec95780518252602082019150602081019050602083039250616ea6565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310616f305780518252602082019150602081019050602083039250616f0d565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114616f90576040519150601f19603f3d011682016040523d82523d6000602084013e616f95565b606091505b50809350819250505080616ff4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603181526020018061df8c6031913960400191505060405180910390fd5b616fff82600061b854565b92505050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60065481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661707961ba4c565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b61709d617037565b61710f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000811415617186576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f6d696e4465706f736974206d757374206265206c6172676572207468616e203081525060200191505060405180910390fd5b600c548114156171fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f4d696e696d756d206465706f73697420756e6368616e6765640000000000000081525060200191505060405180910390fd5b80600c819055507fc50a7f0bdf88c216b2541b0bdea26f22305460e39ffc672ec1a7501732c5ba81816040518082815260200191505060405180910390a150565b60006001806000828254019250508190555060006001549050600061726261ab31565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156172de57600080fd5b505afa1580156172f2573d6000803e3d6000fd5b505050506040513d602081101561730857600080fd5b810190808051906020019092919050505090506000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008090505b60178054905081101561789e57600082600301600083815260200190815260200160002090506017828154811061739757fe5b906000526020600020015481600101541480156173e95750600081600301541415806173c857506000816004015414155b806173d857506000816005015414155b806173e857506000816002015414155b5b15617882576000806173ff83600101548561aa55565b915091506003600581111561741057fe5b81600581111561741c57fe5b141561782b57600083600201541461768357600060038081111561743c57fe5b8460000160009054906101000a900460ff16600381111561745957fe5b1461746557600061746b565b83600201545b905060006002600381111561747c57fe5b8560000160009054906101000a900460ff16600381111561749957fe5b146174a55760006174ab565b84600201545b90506000600160038111156174bc57fe5b8660000160009054906101000a900460ff1660038111156174d957fe5b146174e55760006174eb565b85600201545b9050847338afc0dc55415ae27b81c24b5a5fbfe433ebfba863cd150a6d909185858560008060006040518863ffffffff1660e01b81526004018088815260200187815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060006040518083038186803b15801561757057600080fd5b505af4158015617584573d6000803e3d6000fd5b5050505061759061ac2c565b73ffffffffffffffffffffffffffffffffffffffff166330a61d596040518163ffffffff1660e01b815260040160206040518083038186803b1580156175d557600080fd5b505afa1580156175e9573d6000803e3d6000fd5b505050506040513d60208110156175ff57600080fd5b810190808051906020019092919050505085600801819055508873ffffffffffffffffffffffffffffffffffffffff1686600101547f6791653c96b4863b3768c664e9a03e1094ae334ba9d35862627ceeebd1abcc1f85858560405180848152602001838152602001828152602001935050505060405180910390a350505061782a565b817338afc0dc55415ae27b81c24b5a5fbfe433ebfba863cd150a6d909185600301548660040154876005015460008060006040518863ffffffff1660e01b81526004018088815260200187815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060006040518083038186803b15801561771257600080fd5b505af4158015617726573d6000803e3d6000fd5b5050505061773261ac2c565b73ffffffffffffffffffffffffffffffffffffffff166330a61d596040518163ffffffff1660e01b815260040160206040518083038186803b15801561777757600080fd5b505afa15801561778b573d6000803e3d6000fd5b505050506040513d60208110156177a157600080fd5b810190808051906020019092919050505082600801819055508573ffffffffffffffffffffffffffffffffffffffff1683600101547f6791653c96b4863b3768c664e9a03e1094ae334ba9d35862627ceeebd1abcc1f85600301548660040154876005015460405180848152602001838152602001828152602001935050505060405180910390a35b5b846003016000858152602001908152602001600020600080820160006101000a81549060ff021916905560018201600090556002820160009055600382016000905560048201600090556005820160009055505050505b5061789760018261ad2790919063ffffffff16565b9050617364565b50600081600201819055506001935050506001548114617926576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5090565b600061793e617939848461ba54565b61bca6565b905092915050565b600061795182618efe565b6179c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f50726f706f73616c206e6f74207175657565640000000000000000000000000081525060200191505060405180910390fd5b601273a86051f29c45218b5f6cd121ebafb690660d047c63757775999091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b158015617a1d57600080fd5b505af4158015617a31573d6000803e3d6000fd5b505050506040513d6020811015617a4757600080fd5b81019080805190602001909291905050509050919050565b6000617a6a4361411c565b905090565b6000617a7961a7d5565b6060600060f973ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b60208310617ae85780518252602082019150602081019050602083039250617ac5565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114617b48576040519150601f19603f3d011682016040523d82523d6000602084013e617b4d565b606091505b50809350819250505080617bac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061da1e602e913960400191505060405180910390fd5b617bb782600061b854565b92505050919050565b806011600082815260200190815260200160002060000160009054906101000a900460ff1615617c58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b600060116000848152602001908152602001600020905060004290506000601e5411617ccf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061dcee6024913960400191505060405180910390fd5b6000826004015414617d2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061e09c602b913960400191505060405180910390fd5b8160000160019054906101000a900460ff16617d93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061ddad6021913960400191505060405180910390fd5b8160030160009054906101000a900460ff16617dfa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061e0c76028913960400191505060405180910390fd5b617e0f601e548261ad2790919063ffffffff16565b8260040181905550617e2c601e548261ad2790919063ffffffff16565b847f6f184ec313435b3307a4fe59e2293381f08419a87214464c875a2a247e8af5e060405160405180910390a350505050565b617e67617037565b617ed9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415617f7c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b6018818154811061801057fe5b906000526020600020016000915090505481565b6000600360010154905090565b6017818154811061803e57fe5b906000526020600020016000915090505481565b600060018060008282540192505081905550600060015490506180736141de565b600061807d61ab31565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156180f957600080fd5b505afa15801561810d573d6000803e3d6000fd5b505050506040513d602081101561812357600080fd5b810190808051906020019092919050505090506000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000160000154905060008114156181fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4163636f756e7420686173206e6f20686973746f726963616c207570766f746581525060200191505060405180910390fd5b6182058161b673565b50601273a86051f29c45218b5f6cd121ebafb690660d047c63bfc516389091836040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561826057600080fd5b505af4158015618274573d6000803e3d6000fd5b505050506040513d602081101561828a57600080fd5b81019080805190602001909291905050501561842e57601273a86051f29c45218b5f6cd121ebafb690660d047c63239491ba90918361836d8660000160010154601273a86051f29c45218b5f6cd121ebafb690660d047c63757775999091896040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561832457600080fd5b505af4158015618338573d6000803e3d6000fd5b505050506040513d602081101561834e57600080fd5b810190808051906020019092919050505061b31490919063ffffffff16565b8b8b6040518663ffffffff1660e01b8152600401808681526020018581526020018481526020018381526020018281526020019550505050505060006040518083038186803b1580156183bf57600080fd5b505af41580156183d3573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff16817f7dc46237a819c9171a9c037ec98928e563892905c4d23373ca0f3f500f4ed11484600001600101546040518082815260200191505060405180910390a35b60405180604001604052806000815260200160008152508260000160008201518160000155602082015181600101559050506001945050505060015481146184de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5092915050565b600060149054906101000a900460ff1615618568576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600060146101000a81548160ff02191690831515021790555061858c3361bcb4565b6185958c617e5f565b61859e8b613df0565b6185a78a619113565b6185b089617095565b6185b9886138e4565b6185c287616c33565b6185cb86619322565b6185d485616329565b6185dd84614815565b6185e6836134d1565b6185ef826157df565b6185f881612ce0565b42600981905550505050505050505050505050565b806011600082815260200190815260200160002060000160009054906101000a900460ff16156186a5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561872b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061dc6e6021913960400191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806187d45750601d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b618829576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061db84602b913960400191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156188b35760016011600084815260200190815260200160002060000160016101000a81548160ff0219169083151502179055506188e3565b60016011600084815260200190815260200160002060030160006101000a81548160ff0219169083151502179055505b817f3f6169f1efa9bebb611f332d60ad5e24e6342c099df3dab6307bcb89ab801a1333604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25050565b6000601260000160020154905090565b6000898989898989898989604051602001808060200180602001806020018060200186815260200185810385528e8e82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810384528c8c82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810383528a8a82818152602001925080828437600081840152601f19601f8201169050808301925050508581038252888882818152602001925060200280828437600081840152601f19601f8201169050808301925050509d50505050505050505050505050506040516020818303038152906040528051906020012090509998505050505050505050565b60006001806000828254019250508190555060006001549050618a8d6141de565b600080618a9a878761aa55565b91509150618aa78261a732565b618ab657600093505050618e55565b60036005811115618ac357fe5b816005811115618acf57fe5b14618b42576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e636f72726563742070726f706f73616c207374617465000000000000000081525060200191505060405180910390fd5b60006003811115618b4f57fe5b856003811115618b5b57fe5b1415618bcf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f566f74652076616c756520756e7365740000000000000000000000000000000081525060200191505060405180910390fd5b6000618bd961ab31565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015618c5557600080fd5b505afa158015618c69573d6000803e3d6000fd5b505050506040513d6020811015618c7f57600080fd5b810190808051906020019092919050505090506000618c9c61ac2c565b73ffffffffffffffffffffffffffffffffffffffff166361d5c570836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015618d1857600080fd5b505afa158015618d2c573d6000803e3d6000fd5b505050506040513d6020811015618d4257600080fd5b810190808051906020019092919050505090506000811415618dcc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f566f74657220776569676874207a65726f00000000000000000000000000000081525060200191505060405180910390fd5b618e4c848a8a85600380811115618ddf57fe5b8c6003811115618deb57fe5b14618df7576000618df9565b855b60026003811115618e0657fe5b8d6003811115618e1257fe5b14618e1e576000618e20565b865b60016003811115618e2d57fe5b8e6003811115618e3957fe5b14618e45576000618e47565b875b61adaf565b60019550505050505b6001548114618ecc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b509392505050565b60095481565b6000618ef7600f600084815260200190815260200160002061b2ef565b9050919050565b6000601273a86051f29c45218b5f6cd121ebafb690660d047c63bfc516389091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b158015618f5a57600080fd5b505af4158015618f6e573d6000803e3d6000fd5b505050506040513d6020811015618f8457600080fd5b81019080805190602001909291905050509050919050565b6000806000806060600080618fc2600f60008a815260200190815260200160002061bdf8565b828054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156190575780601f1061902c57610100808354040283529160200191619057565b820191906000526020600020905b81548152906001019060200180831161903a57829003601f168201915b505050505092509650965096509650965096509650919395979092949650565b60008060008061909f601960000160405180602001604052908160008201548152505061bca6565b6190c1601960010160405180602001604052908160008201548152505061bca6565b6190e3601960020160405180602001604052908160008201548152505061bca6565b619105601960030160405180602001604052908160008201548152505061bca6565b935093509350935090919293565b61911b617037565b61918d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008114156191e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061da73602c913960400191505060405180910390fd5b600a5481141561925f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4e756d626572206f662070726f706f73616c7320756e6368616e67656400000081525060200191505060405180910390fd5b80600a819055507f85399b9b2595eb13c392e1638ca77730156cd8d48d4733df4db068e4aa6b93a6816040518082815260200191505060405180910390a150565b6000806192ab61d74c565b601060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001604051806040016040529081600082015481526020016001820154815250509050806000015181602001519250925050915091565b61932a617037565b61939c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000811415619413576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4475726174696f6e206d757374206265206c6172676572207468616e2030000081525060200191505060405180910390fd5b60036001015481141561948e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4475726174696f6e20756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b806003600101819055507f90290eb9b27055e686a69fb810bada5381e544d07b8270021da2d355a6c96ed6816040518082815260200191505060405180910390a150565b6000898989898989898989604051602001808060200180602001806020018060200186815260200185810385528e8e82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810384528c8c82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810383528a8a82818152602001925080828437600081840152601f19601f8201169050808301925050508581038252888882818152602001925060200280828437600081840152601f19601f8201169050808301925050509d50505050505050505050505050506040516020818303038152906040528051906020012090506000806000806195e585612eb8565b93509350935093508115619661576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b836196d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f686f74666978206e6f7420617070726f7665640000000000000000000000000081525060200191505060405180910390fd5b8261972a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061dec96027913960400191505060405180910390fd5b42811015619783576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061de79602e913960400191505060405180910390fd5b6198a161989c8f8f80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508e8e80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505033600061be71565b61c09a565b60016011600087815260200190815260200160002060000160006101000a81548160ff021916908315150217905550847f708a7934acb657a77a617b1fcd5f6d7d9ad592b72934841bff01acefd10f9b6360405160405180910390a25050505050505050505050505050565b601e5481565b6000806060600f60008681526020019081526020016000207338afc0dc55415ae27b81c24b5a5fbfe433ebfba863e6a5192f9091866040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561998357600080fd5b505af4158015619997573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060608110156199c157600080fd5b810190808051906020019092919080519060200190929190805160405193929190846401000000008211156199f557600080fd5b83820191506020820185811115619a0b57600080fd5b8251866001820283011164010000000082111715619a2857600080fd5b8083526020830192505050908051906020019080838360005b83811015619a5c578082015181840152602081019050619a41565b50505050905090810190601f168015619a895780820380516001836020036101000a031916815260200191505b506040525050509250925092509250925092565b600b5481565b6000619aad61a7d5565b6060600060f873ffffffffffffffffffffffffffffffffffffffff16600160405160200180821515151560f81b81526001019150506040516020818303038152906040526040518082805190602001908083835b60208310619b245780518252602082019150602081019050602083039250619b01565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114619b84576040519150601f19603f3d011682016040523d82523d6000602084013e619b89565b606091505b50809350819250505080619be8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061df176025913960400191505060405180910390fd5b619bf382600061b854565b9250505090565b6000806000619c1a600f600086815260200190815260200160002061c0aa565b9250925092509193909250565b6000619c3161a7d5565b619c736003619c656002619c576002619c4988617a6f565b61c0d490919063ffffffff16565b61ad2790919063ffffffff16565b61c15a90919063ffffffff16565b9050919050565b600080619c8561a7d5565b60008714158015619c97575060008514155b619d09576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f612064656e6f6d696e61746f72206973207a65726f000000000000000000000081525060200191505060405180910390fd5b6000806000606060fc73ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c6040516020018087815260200186815260200185815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040526040518082805190602001908083835b60208310619da35780518252602082019150602081019050602083039250619d80565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114619e03576040519150601f19603f3d011682016040523d82523d6000602084013e619e08565b606091505b50809250819350505081619e67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061def06027913960400191505060405180910390fd5b619e7281600061b854565b9350619e7f81602061b854565b925083839550955050505050965096945050505050565b619e9e617037565b619f10576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415619fb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f44657374696e6174696f6e2063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b6969e10de76676d080000081118015619fdb5750619fd7619fd261c1a4565b61bca6565b8111155b61a030576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604881526020018061db3c6048913960600191505060405180910390fd5b600060e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141561a0b85761a0648161a460565b600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000016000820151816000015590505061a160565b61a0c18161a460565b600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020600082015181600001559050505b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168373ffffffffffffffffffffffffffffffffffffffff167f60c5b4756af49d7b071b00dbf0f87af605cce11896ecd3b760d19f0f9d3fbcef836040518082815260200191505060405180910390a3505050565b61a1db617037565b61a24d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61a2568161bcb4565b50565b61a26161ac2c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461a301576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f6d73672e73656e646572206e6f74206c6f636b6564476f6c640000000000000081525060200191505060405180910390fd5b61a30b828261c1ca565b5050565b600061a31961a7d5565b6060600060f573ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061a388578051825260208201915060208101905060208303925061a365565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461a3e8576040519150601f19603f3d011682016040523d82523d6000602084013e61a3ed565b606091505b5080935081925050508061a44c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061df60602c913960400191505060405180910390fd5b61a45782600061b498565b92505050919050565b61a46861d70d565b6040518060200160405280838152509050919050565b600061a4918261a48c61c1a4565b61c5c1565b9050919050565b60008160000151836000015114905092915050565b60008060007342000000000000000000000000000000000000189050803b915060008263ffffffff16119250505090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f45706f63684d616e616765720000000000000000000000000000000000000000815250600c019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561a59957600080fd5b505afa15801561a5ad573d6000803e3d6000fd5b505050506040513d602081101561a5c357600080fd5b8101908080519060200190929190505050905090565b600061a5e361a7d5565b6060600060fa73ffffffffffffffffffffffffffffffffffffffff16844360405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061a65a578051825260208201915060208101905060208303925061a637565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461a6ba576040519150601f19603f3d011682016040523d82523d6000602084013e61a6bf565b606091505b5080935081925050508061a71e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d81526020018061dd12603d913960400191505060405180910390fd5b61a72982600061b854565b92505050919050565b6000808260020154119050919050565b6000601780549050821061a7a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061e071602b913960400191505060405180910390fd5b61a7aa8461a732565b801561a7cc5750826017838154811061a7bf57fe5b9060005260206000200154145b90509392505050565b61a7dd61a4ad565b1561a833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061dd846029913960400191505060405180910390fd5b565b600061a83f61d70d565b61a89661a8876019600301604051806020016040529081600082015481525050601960000160405180602001604052908160008201548152505061c5d790919063ffffffff16565b8461ca3690919063ffffffff16565b905060008360060180549050141561a8d95761a8b061d70d565b61a8bb60008061ba54565b905061a8d0818361cb2590919063ffffffff16565b9250505061aa50565b60008090505b836006018054905081101561aa4957600061a9b185600601838154811061a90257fe5b90600052602060002090600302016002018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561a9a75780601f1061a97c5761010080835404028352916020019161a9a7565b820191906000526020600020905b81548152906001019060200180831161a98a57829003601f168201915b505050505061cb3a565b905061a9bb61d70d565b61aa0586600601848154811061a9cd57fe5b906000526020600020906003020160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168361ba54565b905061aa1a818561c5c190919063ffffffff16565b1561aa2c57600094505050505061aa50565b505061aa4260018261ad2790919063ffffffff16565b905061a8df565b5060019150505b919050565b6000806000600f6000868152602001908152602001600020905061aa7a81868661a742565b61aaec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f50726f706f73616c206e6f74206465717565756564000000000000000000000081525060200191505060405180910390fd5b600061aaf78261b746565b905061ab03828261b7fd565b1561ab215761ab1382878761b554565b81600593509350505061ab2a565b81819350935050505b9250929050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f4163636f756e74730000000000000000000000000000000000000000000000008152506008019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561abec57600080fd5b505afa15801561ac00573d6000803e3d6000fd5b505050506040513d602081101561ac1657600080fd5b8101908080519060200190929190505050905090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f4c6f636b6564476f6c6400000000000000000000000000000000000000000000815250600a019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561ace757600080fd5b505afa15801561acfb573d6000803e3d6000fd5b505050506040513d602081101561ad1157600080fd5b8101908080519060200190929190505050905090565b60008082840190508381101561ada5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000601060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600301600088815260200190815260200160002090508781600101541461aeb657887338afc0dc55415ae27b81c24b5a5fbfe433ebfba863cd150a6d909160008060008a8a8a6040518863ffffffff1660e01b81526004018088815260200187815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060006040518083038186803b15801561ae9957600080fd5b505af415801561aead573d6000803e3d6000fd5b5050505061b0b7565b600081600201541461b01057887338afc0dc55415ae27b81c24b5a5fbfe433ebfba863cd150a6d909160038081111561aeeb57fe5b8460000160009054906101000a900460ff16600381111561af0857fe5b1461af1457600061af1a565b83600201545b6002600381111561af2757fe5b8560000160009054906101000a900460ff16600381111561af4457fe5b1461af5057600061af56565b84600201545b6001600381111561af6357fe5b8660000160009054906101000a900460ff16600381111561af8057fe5b1461af8c57600061af92565b85600201545b8a8a8a6040518863ffffffff1660e01b81526004018088815260200187815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060006040518083038186803b15801561aff357600080fd5b505af415801561b007573d6000803e3d6000fd5b5050505061b0b6565b887338afc0dc55415ae27b81c24b5a5fbfe433ebfba863cd150a6d90918360030154846004015485600501548a8a8a6040518863ffffffff1660e01b81526004018088815260200187815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060006040518083038186803b15801561b09d57600080fd5b505af415801561b0b1573d6000803e3d6000fd5b505050505b5b61b0bf61ac2c565b73ffffffffffffffffffffffffffffffffffffffff166330a61d596040518163ffffffff1660e01b815260040160206040518083038186803b15801561b10457600080fd5b505afa15801561b118573d6000803e3d6000fd5b505050506040513d602081101561b12e57600080fd5b810190808051906020019092919050505089600801819055506040518060c001604052806000600381111561b15f57fe5b8152602001898152602001600081526020018681526020018581526020018481525082600301600089815260200190815260200160002060008201518160000160006101000a81548160ff0219169083600381111561b1ba57fe5b02179055506020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050155905050600f600083600201548152602001908152602001600020600201548960020154111561b224578782600201819055505b8573ffffffffffffffffffffffffffffffffffffffff16887f683ebddc94b5b0a7dae3d1b6c168ad05684fcfd831b24ecb5ea9ecdf5524d02887878760405180848152602001838152602001828152602001935050505060405180910390a3505050505050505050565b60008082848161b29a57fe5b049050600083858161b2a857fe5b06141561b2b8578091505061b2d0565b61b2cc60018261ad2790919063ffffffff16565b9150505b92915050565b600081831061b2e5578161b2e7565b825b905092915050565b600061b30a600654836002015461ad2790919063ffffffff16565b4210159050919050565b600061b35683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061cc97565b905092915050565b8047101561b3d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a20696e73756666696369656e742062616c616e636500000081525060200191505060405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168260405180600001905060006040518083038185875af1925050503d806000811461b434576040519150601f19603f3d011682016040523d82523d6000602084013e61b439565b606091505b505090508061b493576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603a81526020018061dbd5603a913960400191505060405180910390fd5b505050565b600061b4ae60208361ad2790919063ffffffff16565b8351101561b524576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f736c6963696e67206f7574206f662072616e676500000000000000000000000081525060200191505060405180910390fd5b60006020830184015190508091505092915050565b60008160070160009054906101000a900460ff169050919050565b61b55d8361b539565b801561b56e57506000836008015414155b1561b57d5761b57c8361cd57565b5b60006017828154811061b58c57fe5b90600052602060002001819055506018819080600181540180825580915050906001820390600052602060002001600090919290919091505550600f6000838152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600182016000905560028201600090556003820160008082016000905560018201600090556002820160009055505060068201600061b640919061d766565b6007820160006101000a81549060ff0219169055600882016000905560098201600061b66c919061d78a565b5050505050565b600061b67e82618efe565b801561b68f575061b68e82618eda565b5b1561b73c57601273a86051f29c45218b5f6cd121ebafb690660d047c63eed5f7be9091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561b6ee57600080fd5b505af415801561b702573d6000803e3d6000fd5b50505050817f88e53c486703527139dfc8d97a1e559d9bd93d3f9d52cda4e06564111e7a264360405160405180910390a26001905061b741565b600090505b919050565b60008061b77c60036002015461b76e600360010154866002015461ad2790919063ffffffff16565b61ad2790919063ffffffff16565b905080421015801561b7b857506000836006018054905014158061b7a6575061b7a48361b539565b155b8061b7b7575061b7b58361a835565b155b5b1561b7c757600591505061b7f8565b61b7df6003600201548261b31490919063ffffffff16565b905080421061b7f257600491505061b7f8565b60039150505b919050565b60006004600581111561b80c57fe5b82600581111561b81857fe5b118061b84c57506003600581111561b82c57fe5b82600581111561b83857fe5b11801561b84b575061b8498361a835565b155b5b905092915050565b600061b860838361b498565b60001c905092915050565b60008151141561b8c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061dac56029913960400191505060405180910390fd5b8082600901908051906020019061b8de92919061d7d2565b505050565b60008183101561b8f3578161b8f5565b825b905092915050565b600061b90761a7d5565b6060600060f973ffffffffffffffffffffffffffffffffffffffff1643604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061b976578051825260208201915060208101905060208303925061b953565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461b9d6576040519150601f19603f3d011682016040523d82523d6000602084013e61b9db565b606091505b5080935081925050508061ba3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603581526020018061dd4f6035913960400191505060405180910390fd5b61ba4582600061b854565b9250505090565b600033905090565b61ba5c61d70d565b61ba6461d70d565b61ba776969e10de76676d080000061a460565b9050600061bb29600e60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060405180602001604052908160008201548152505061bca6565b1461bbdb57600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020604051806020016040529081600082015481525050905061bc9c565b600061bc3c600e60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160405180602001604052908160008201548152505061bca6565b1461bc9b57600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160405180602001604052908160008201548152505090505b5b8091505092915050565b600081600001519050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561bd3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061da9f6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008060008060008060008760000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886001015489600201548a600601805490508b6009018c600801548d60070160009054906101000a900460ff168292509650965096509650965096509650919395979092949650565b61be7961d852565b8551875114801561be8b575083518651145b61befd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4172726179206c656e677468206d69736d61746368000000000000000000000081525060200191505060405180910390fd5b60008751905061bf0b61d852565b84816000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050838160200181815250504281604001818152505060008090508260405190808252806020026020018201604052801561bf9657816020015b61bf8361d8b5565b81526020019060019003908161bf7b5790505b50826080018190525060008090505b8381101561c0895760405180606001604052808c838151811061bfc457fe5b602002602001015181526020018b838151811061bfdd57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16815260200161c028848b858151811061c01057fe5b60200260200101518d61ceed9092919063ffffffff16565b8152508360800151828151811061c03b57fe5b602002602001018190525061c06c88828151811061c05557fe5b60200260200101518361ad2790919063ffffffff16565b915061c08260018261ad2790919063ffffffff16565b905061bfa5565b508193505050509695505050505050565b61c0a7816080015161cf79565b50565b60008060008360030160000154846003016001015485600301600201549250925092509193909250565b60008083141561c0e7576000905061c154565b600082840290508284828161c0f857fe5b041461c14f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061de586021913960400191505060405180910390fd5b809150505b92915050565b600061c19c83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061d082565b905092915050565b61c1ac61d70d565b604051806020016040528069d3c21bcecceda1000000815250905090565b6000601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008090505b60178054905081101561c5bb5760006017828154811061c22f57fe5b906000526020600020015490506000600f6000838152602001908152602001600020905060006003600581111561c26257fe5b61c26b8361b746565b600581111561c27657fe5b1490508061c2865750505061c5a0565b600085600301600086815260200190815260200160002090508381600101541461c30757856003016000868152602001908152602001600020600080820160006101000a81549060ff02191690556001820160009055600282016000905560038201600090556004820160009055600582016000905550505050505061c5a0565b600061c33a826005015461c32c8460040154856003015461ad2790919063ffffffff16565b61ad2790919063ffffffff16565b90508781111561c59a57600061c359898361b31490919063ffffffff16565b9050600061c36c8285600501548561d148565b9050600061c37f8386600301548661d148565b9050600061c3928487600401548761d148565b9050600061c3bb8261c3ad858761ad2790919063ffffffff16565b61ad2790919063ffffffff16565b9050600061c3d684896003015461b31490919063ffffffff16565b9050600061c3f1848a6004015461b31490919063ffffffff16565b9050600061c40c878b6005015461b31490919063ffffffff16565b90508784101561c4d157600061c42b858a61b31490919063ffffffff16565b9050600061c439828661b2d6565b905061c44e818661b31490919063ffffffff16565b945061c463818361b31490919063ffffffff16565b91506000821461c4a45761c477828561b2d6565b905061c48c818561b31490919063ffffffff16565b935061c4a1818361b31490919063ffffffff16565b91505b6000821461c4ce5761c4b6828461b2d6565b905061c4cb818461b31490919063ffffffff16565b92505b50505b8b7338afc0dc55415ae27b81c24b5a5fbfe433ebfba863cd150a6d90918c600301548d600401548e600501548888886040518863ffffffff1660e01b81526004018088815260200187815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060006040518083038186803b15801561c55e57600080fd5b505af415801561c572573d6000803e3d6000fd5b50505050808a60050181905550828a60030181905550818a6004018190555050505050505050505b50505050505b61c5b460018261ad2790919063ffffffff16565b905061c213565b50505050565b6000816000015183600001511115905092915050565b61c5df61d70d565b60008360000151148061c5f6575060008260000151145b1561c6125760405180602001604052806000815250905061ca30565b69d3c21bcecceda10000008260000151141561c6305782905061ca30565b69d3c21bcecceda10000008360000151141561c64e5781905061ca30565b600069d3c21bcecceda100000061c6648561d17f565b600001518161c66f57fe5b049050600061c67d8561d1b6565b600001519050600069d3c21bcecceda100000061c6998661d17f565b600001518161c6a457fe5b049050600061c6b28661d1b6565b600001519050600082850290506000851461c746578285828161c6d157fe5b041461c745576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b600069d3c21bcecceda1000000820290506000821461c7e85769d3c21bcecceda100000082828161c77357fe5b041461c7e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6f766572666c6f772078317931202a206669786564312064657465637465640081525060200191505060405180910390fd5b5b809150600084860290506000861461c879578486828161c80457fe5b041461c878576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b600084880290506000881461c907578488828161c89257fe5b041461c906576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b61c90f61d1f3565b878161c91757fe5b04965061c92261d1f3565b858161c92a57fe5b049450600085880290506000881461c9bb578588828161c94657fe5b041461c9ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b61c9c361d70d565b604051806020016040528087815250905061c9ec8160405180602001604052808781525061d200565b905061ca068160405180602001604052808681525061d200565b905061ca208160405180602001604052808581525061d200565b9050809a50505050505050505050505b92915050565b61ca3e61d70d565b600083600301600001549050600081141561ca655761ca5d600061d2a9565b91505061cb1f565b600084600301600101549050600061ca9f866003016002015461ca91848661ad2790919063ffffffff16565b61ad2790919063ffffffff16565b9050600061caca61cac561cab6896008015461d2a9565b8861c5d790919063ffffffff16565b61d333565b90508181111561cafc5761caf961caea838361b31490919063ffffffff16565b8461ad2790919063ffffffff16565b92505b61cb188461cb13858761ad2790919063ffffffff16565b61d354565b9450505050505b92915050565b60008160000151836000015111905092915050565b600060188260038151811061cb4b57fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c60108360028151811061cba857fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c60088460018151811061cc0557fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c8460008151811061cc6057fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161717179050919050565b600083831115829061cd44576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561cd0957808201518184015260208101905061ccee565b50505050905090810190601f16801561cd365780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b61cd5f61d70d565b61cd688261d396565b905061cd7261d70d565b61cd9e60196002016040518060200160405290816000820154815250508361c5d790919063ffffffff16565b905061cda861d70d565b61ce0661cdde601960020160405180602001604052908160008201548152505061cdd061c1a4565b61d3f290919063ffffffff16565b601960000160405180602001604052908160008201548152505061c5d790919063ffffffff16565b905061ce1b818361d20090919063ffffffff16565b60196000016000820151816000015590505061ce726019600101604051806020016040529081600082015481525050601960000160405180602001604052908160008201548152505061d49990919063ffffffff16565b1561ce8f5760196001016019600001600082015481600001559050505b7f51131d2820f04a6b6edd20e22a07d5bf847e265a3906e85256fca7d6043417c561ced2601960000160405180602001604052908160008201548152505061bca6565b6040518082815260200191505060405180910390a150505050565b60608183018451101561ceff57600080fd5b606082156000811461cf1c5760405191506020820160405261cf6d565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561cf5a578051835260208301925060208101905061cf3d565b50868552601f19601f8301166040525050505b50809150509392505050565b60008090505b815181101561d07e5761cff182828151811061cf9757fe5b60200260200101516020015183838151811061cfaf57fe5b60200260200101516000015184848151811061cfc757fe5b6020026020010151604001515185858151811061cfe057fe5b60200260200101516040015161d4ae565b61d063576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f50726f706f73616c20657865637574696f6e206661696c65640000000000000081525060200191505060405180910390fd5b61d07760018261ad2790919063ffffffff16565b905061cf7f565b5050565b6000808311829061d12e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561d0f357808201518184015260208101905061d0d8565b50505050905090810190601f16801561d1205780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161d13a57fe5b049050809150509392505050565b600061d17661d17161d15a858561d354565b61d1638761d2a9565b61c5d790919063ffffffff16565b61d333565b90509392505050565b61d18761d70d565b604051806020016040528069d3c21bcecceda10000008085600001518161d1aa57fe5b04028152509050919050565b61d1be61d70d565b604051806020016040528069d3c21bcecceda10000008085600001518161d1e157fe5b04028460000151038152509050919050565b600064e8d4a51000905090565b61d20861d70d565b600082600001518460000151019050836000015181101561d291576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f616464206f766572666c6f77206465746563746564000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808281525091505092915050565b61d2b161d70d565b61d2b961d55a565b82111561d311576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061dc8f6036913960400191505060405180910390fd5b604051806020016040528069d3c21bcecceda100000084028152509050919050565b600069d3c21bcecceda100000082600001518161d34c57fe5b049050919050565b61d35c61d70d565b61d36461d70d565b61d36d8461d2a9565b905061d37761d70d565b61d3808461d2a9565b905061d38c828261d579565b9250505092915050565b61d39e61d70d565b600061d3da836003016002015461d3cc8560030160010154866003016000015461ad2790919063ffffffff16565b61ad2790919063ffffffff16565b905061d3ea81846008015461d354565b915050919050565b61d3fa61d70d565b81600001518360000151101561d478576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f737562737472616374696f6e20756e646572666c6f772064657465637465640081525060200191505060405180910390fd5b60405180602001604052808360000151856000015103815250905092915050565b60008160000151836000015110905092915050565b600080600084111561d5365761d4c38661d6c2565b61d535576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b5b6040516020840160008287838a8c6187965a03f19250505080915050949350505050565b60007601357c299a88ea76a58924d52ce4f26a85af186c2b9e74905090565b61d58161d70d565b60008260000151141561d5fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f63616e277420646976696465206279203000000000000000000000000000000081525060200191505060405180910390fd5b600069d3c21bcecceda10000008460000151029050836000015169d3c21bcecceda1000000828161d62957fe5b041461d69d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6f766572666c6f7720617420646976696465000000000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808460000151838161d6b557fe5b0481525091505092915050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561d70457506000801b8214155b92505050919050565b6040518060200160405280600081525090565b81548183558181111561d7475781836000526020600020918201910161d746919061d8ec565b5b505050565b604051806040016040528060008152602001600081525090565b508054600082556003029060005260206000209081019061d787919061d911565b50565b50805460018160011615610100020316600290046000825580601f1061d7b0575061d7cf565b601f01602090049060005260206000209081019061d7ce919061d8ec565b5b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061d81357805160ff191683800117855561d841565b8280016001018555821561d841579182015b8281111561d84057825182559160200191906001019061d825565b5b50905061d84e919061d8ec565b5090565b604051806101000160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200161d89161d96f565b81526020016060815260200160001515815260200160008152602001606081525090565b604051806060016040528060008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b61d90e91905b8082111561d90a57600081600090555060010161d8f2565b5090565b90565b61d96c91905b8082111561d968576000808201600090556001820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560028201600061d95f919061d990565b5060030161d917565b5090565b90565b60405180606001604052806000815260200160008152602001600081525090565b50805460018160011615610100020316600290046000825580601f1061d9b6575061d9d5565b601f01602090049060005260206000209081019061d9d4919061d8ec565b5b5056fe457865637574696f6e2074696d652077696e646f772063616e6e6f74206265207a65726f5175657565457870697279206d757374206265206c6172676572207468616e20306572726f722063616c6c696e67206e756d62657256616c696461746f7273496e53657420707265636f6d70696c6550617274696369706174696f6e20626173656c696e652067726561746572207468616e206f6e654e756d626572206f662070726f706f73616c73206d757374206265206c6172676572207468616e207a65726f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734465736372697074696f6e2075726c206d7573742068617665206e6f6e2d7a65726f206c656e677468686f7466697820657865637574696f6e2074696d65206c696d6974206e6f742072656163686564426173656c696e652071756f72756d20666163746f722067726561746572207468616e206f6e655468726573686f6c642068617320746f2062652067726561746572207468616e206d616a6f7269747920616e64206e6f742067726561746572207468616e20756e616e696d6974796d73672e73656e646572206e6f7420617070726f766572206f7220536563757269747920436f756e63696c50617274696369706174696f6e20626173656c696e6520666c6f6f7220756e6368616e676564416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564426173656c696e652075706461746520666163746f722067726561746572207468616e206f6e656572726f722063616c6c696e672067657456657269666965645365616c4269746d617046726f6d48656164657220707265636f6d70696c656d73672e73656e6465722063616e6e6f742062652061646472657373207a65726f63616e277420637265617465206669786964697479206e756d626572206c6172676572207468616e206d61784e65774669786564282963616e6e6f74207570766f746520612070726f706f73616c206e6f7420696e20746865207175657565486f7466697820657865637574696f6e2074696d652077696e646f77206e6f74207365746572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d43757272656e7453657420707265636f6d70696c656572726f722063616c6c696e67206e756d62657256616c696461746f7273496e43757272656e7453657420707265636f6d70696c6554686973206d6574686f64206973206e6f206c6f6e67657220737570706f7274656420696e204c322e486f74666978206e6f7420617070726f76656420627920617070726f766572732e6572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d53657420707265636f6d70696c6550726f706f73616c206e6f7420696e20657865637574696f6e207374616765206f72206e6f742070617373696e67646571756575654672657175656e6379206d757374206265206c6172676572207468616e2030536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77457865637574696f6e2074696d65206c696d69742068617320616c7265616479206265656e20726561636865642e63616e6e6f74207570766f746520776974686f7574206c6f636b696e6720676f6c64686f74666978206e6f7420617070726f76656420627920736563757269747920636f756e63696c6572726f722063616c6c696e67206672616374696f6e4d756c45787020707265636f6d70696c656572726f722063616c6c696e672067657445706f636853697a6520707265636f6d70696c6550617274696369706174696f6e20666c6f6f722067726561746572207468616e206f6e656572726f722063616c6c696e6720676574506172656e745365616c4269746d617020707265636f6d70696c656572726f722063616c6c696e6720676574426c6f636b4e756d62657246726f6d48656164657220707265636f6d70696c6563616e6e6f74207570766f7465206d6f7265207468616e206f6e65207175657565642070726f706f73616c54686973206d6574686f64206973206e6f7420737570706f7274656420696e204c312e566f74657220646f65736e2774206861766520656e6f756768206c6f636b65642043656c6f2028666f726d65726c79206b6e6f776e2061732043656c6f20476f6c64296572726f722063616c6c696e67206861736848656164657220707265636f6d70696c6550726f766964656420696e6465782067726561746572207468616e2064657175657565206c656e6774682e486f7466697820616c726561647920707265706172656420666f7220746869732074696d656672616d652e486f74666978206e6f7420617070726f76656420627920736563757269747920636f756e63696c2ea265627a7a72315820161d67f0c7cf7e5d92c54f296066b5241eb52ca8e9f14e50cacb7583a5f8193164736f6c634300050e0032","source_code":"pragma solidity ^0.5.13;\n\nimport \"openzeppelin-solidity/contracts/ownership/Ownable.sol\";\nimport \"openzeppelin-solidity/contracts/math/Math.sol\";\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\nimport \"openzeppelin-solidity/contracts/utils/Address.sol\";\n\nimport \"./interfaces/IGovernance.sol\";\nimport \"./Proposals.sol\";\nimport \"../common/interfaces/IAccounts.sol\";\nimport \"../common/ExtractFunctionSignature.sol\";\nimport \"../common/Initializable.sol\";\nimport \"../common/FixidityLib.sol\";\nimport \"../common/linkedlists/IntegerSortedLinkedList.sol\";\nimport \"../common/UsingRegistry.sol\";\nimport \"../common/PrecompilesOverride.sol\";\nimport \"../common/interfaces/ICeloVersionedContract.sol\";\nimport \"../common/libraries/ReentrancyGuard.sol\";\n\n/**\n * @title A contract for making, passing, and executing on-chain governance proposals.\n */\ncontract Governance is\n  IGovernance,\n  ICeloVersionedContract,\n  Ownable,\n  Initializable,\n  ReentrancyGuard,\n  UsingRegistry,\n  PrecompilesOverride\n{\n  using Proposals for Proposals.Proposal;\n  using FixidityLib for FixidityLib.Fraction;\n  using SafeMath for uint256;\n  using IntegerSortedLinkedList for SortedLinkedList.List;\n  using BytesLib for bytes;\n  using Address for address payable; // prettier-ignore\n\n  enum VoteValue {\n    None,\n    Abstain,\n    No,\n    Yes\n  }\n\n  struct UpvoteRecord {\n    uint256 proposalId;\n    uint256 weight;\n  }\n\n  struct VoteRecord {\n    Proposals.VoteValue deprecated_value; // obsolete\n    uint256 proposalId;\n    uint256 deprecated_weight; // obsolete\n    uint256 yesVotes;\n    uint256 noVotes;\n    uint256 abstainVotes;\n  }\n\n  struct Voter {\n    // Key of the proposal voted for in the proposal queue\n    UpvoteRecord upvote;\n    uint256 mostRecentReferendumProposal;\n    // Maps a `dequeued` index to a voter's vote record.\n    mapping(uint256 => VoteRecord) referendumVotes;\n  }\n\n  struct ContractConstitution {\n    FixidityLib.Fraction defaultThreshold;\n    // Maps a function ID to a corresponding threshold, overriding the default.\n    mapping(bytes4 => FixidityLib.Fraction) functionThresholds;\n  }\n\n  struct HotfixRecord {\n    bool executed;\n    bool approved;\n    uint256 deprecated_preparedEpoch; // obsolete\n    mapping(address => bool) deprecated_whitelisted; // obsolete\n    bool councilApproved;\n    uint256 executionTimeLimit;\n  }\n\n  // The baseline is updated as\n  // max{floor, (1 - baselineUpdateFactor) * baseline + baselineUpdateFactor * participation}\n  struct ParticipationParameters {\n    // The average network participation in governance, weighted toward recent proposals.\n    FixidityLib.Fraction baseline;\n    // The lower bound on the participation baseline.\n    FixidityLib.Fraction baselineFloor;\n    // The weight of the most recent proposal's participation on the baseline.\n    FixidityLib.Fraction baselineUpdateFactor;\n    // The proportion of the baseline that constitutes quorum.\n    FixidityLib.Fraction baselineQuorumFactor;\n  }\n\n  uint256 private constant FIXED_HALF = 500000000000000000000000;\n\n  Proposals.StageDurations public stageDurations;\n  uint256 public queueExpiry;\n  uint256 public dequeueFrequency;\n  address public approver;\n  uint256 public lastDequeue;\n  uint256 public concurrentProposals;\n  uint256 public proposalCount;\n  uint256 public minDeposit;\n  mapping(address => uint256) public refundedDeposits;\n  mapping(address => ContractConstitution) private constitution;\n  mapping(uint256 => Proposals.Proposal) private proposals;\n  mapping(address => Voter) internal voters;\n  mapping(bytes32 => HotfixRecord) public hotfixes;\n  SortedLinkedList.List private queue;\n  uint256[] public dequeued;\n  uint256[] public emptyIndices;\n  ParticipationParameters private participationParameters;\n  address public securityCouncil;\n  uint256 public hotfixExecutionTimeWindow;\n\n  event ApproverSet(address indexed approver);\n\n  event ConcurrentProposalsSet(uint256 concurrentProposals);\n\n  event MinDepositSet(uint256 minDeposit);\n\n  event QueueExpirySet(uint256 queueExpiry);\n\n  event DequeueFrequencySet(uint256 dequeueFrequency);\n\n  event ReferendumStageDurationSet(uint256 referendumStageDuration);\n\n  event ExecutionStageDurationSet(uint256 executionStageDuration);\n\n  event ConstitutionSet(address indexed destination, bytes4 indexed functionId, uint256 threshold);\n\n  event ProposalQueued(\n    uint256 indexed proposalId,\n    address indexed proposer,\n    uint256 transactionCount,\n    uint256 deposit,\n    uint256 timestamp\n  );\n\n  event ProposalUpvoted(uint256 indexed proposalId, address indexed account, uint256 upvotes);\n\n  event ProposalUpvoteRevoked(\n    uint256 indexed proposalId,\n    address indexed account,\n    uint256 revokedUpvotes\n  );\n\n  event ProposalDequeued(uint256 indexed proposalId, uint256 timestamp);\n\n  event ProposalApproved(uint256 indexed proposalId);\n\n  event ProposalVoted(\n    uint256 indexed proposalId,\n    address indexed account,\n    uint256 value,\n    uint256 weight\n  );\n\n  event ProposalVotedV2(\n    uint256 indexed proposalId,\n    address indexed account,\n    uint256 yesVotes,\n    uint256 noVotes,\n    uint256 abstainVotes\n  );\n\n  event ProposalVoteRevoked(\n    uint256 indexed proposalId,\n    address indexed account,\n    uint256 value,\n    uint256 weight\n  );\n\n  event ProposalVoteRevokedV2(\n    uint256 indexed proposalId,\n    address indexed account,\n    uint256 yesVotes,\n    uint256 noVotes,\n    uint256 abstainVotes\n  );\n\n  event ProposalExecuted(uint256 indexed proposalId);\n\n  event ProposalExpired(uint256 indexed proposalId);\n\n  event ParticipationBaselineUpdated(uint256 participationBaseline);\n\n  event ParticipationFloorSet(uint256 participationFloor);\n\n  event ParticipationBaselineUpdateFactorSet(uint256 baselineUpdateFactor);\n\n  event ParticipationBaselineQuorumFactorSet(uint256 baselineQuorumFactor);\n\n  event HotfixApproved(bytes32 indexed hash, address approver);\n\n  event HotfixPrepared(bytes32 indexed hash, uint256 indexed executionLimit);\n\n  event HotfixExecuted(bytes32 indexed hash);\n\n  event SecurityCouncilSet(address indexed council);\n\n  event HotfixExecutionTimeWindowSet(uint256 timeDelta);\n\n  event HotfixRecordReset(bytes32 indexed hash);\n\n  /**\n   * @notice Ensures a hotfix can be executed only once.\n   * @param hash Hash of the hotfix.\n   * @dev Reverts if the hotfix has already been executed.\n   */\n  modifier hotfixNotExecuted(bytes32 hash) {\n    require(!hotfixes[hash].executed, \"hotfix already executed\");\n    _;\n  }\n\n  /**\n   * @notice Ensures function can only be called by the approver address.\n   */\n  modifier onlyApprover() {\n    require(msg.sender == approver, \"msg.sender not approver\");\n    _;\n  }\n\n  /**\n   * @notice Ensures function can only be called by the LockedGold contract.\n   */\n  modifier onlyLockedGold() {\n    require(msg.sender == address(getLockedGold()), \"msg.sender not lockedGold\");\n    _;\n  }\n\n  /**\n   * @notice Ensures a hotfix cannot be executed after the time limit.\n   * @param hash Hash of the hotfix.\n   * @dev Reverts if the hotfix time limit has been reached, or the hotfix is\n   * not prepared yet.\n   */\n  modifier hotfixTimedOut(bytes32 hash) {\n    require(hotfixes[hash].executionTimeLimit > 0, \"hotfix not prepared\");\n    require(hotfixes[hash].executionTimeLimit < now, \"hotfix execution time limit not reached\");\n    _;\n  }\n\n  /**\n   * @notice Sets initialized == true on implementation contracts\n   * @param test Set to true to skip implementation initialization\n   */\n  constructor(bool test) public Initializable(test) {}\n\n  /**\n   * @notice Used in place of the constructor to allow the contract to be upgradable via proxy.\n   * @param registryAddress The address of the registry contract.\n   * @param _approver The address that needs to approve proposals to move to the referendum stage.\n   * @param _concurrentProposals The number of proposals to dequeue at once.\n   * @param _minDeposit The minimum CELO deposit needed to make a proposal.\n   * @param _queueExpiry The number of seconds a proposal can stay in the queue before expiring.\n   * @param _dequeueFrequency The number of seconds before the next batch of proposals can be\n   *   dequeued.\n   * @param referendumStageDuration The number of seconds users have to vote on a dequeued proposal\n   *   after the approval stage ends.\n   * @param executionStageDuration The number of seconds users have to execute a passed proposal\n   *   after the referendum stage ends.\n   * @param participationBaseline The initial value of the participation baseline.\n   * @param participationFloor The participation floor.\n   * @param baselineUpdateFactor The weight of the new participation in the baseline update rule.\n   * @param baselineQuorumFactor The proportion of the baseline that constitutes quorum.\n   * @dev Should be called only once.\n   */\n  function initialize(\n    address registryAddress,\n    address _approver,\n    uint256 _concurrentProposals,\n    uint256 _minDeposit,\n    uint256 _queueExpiry,\n    uint256 _dequeueFrequency,\n    uint256 referendumStageDuration,\n    uint256 executionStageDuration,\n    uint256 participationBaseline,\n    uint256 participationFloor,\n    uint256 baselineUpdateFactor,\n    uint256 baselineQuorumFactor\n  ) external initializer {\n    _transferOwnership(msg.sender);\n    setRegistry(registryAddress);\n    setApprover(_approver);\n    setConcurrentProposals(_concurrentProposals);\n    setMinDeposit(_minDeposit);\n    setQueueExpiry(_queueExpiry);\n    setDequeueFrequency(_dequeueFrequency);\n    setReferendumStageDuration(referendumStageDuration);\n    setExecutionStageDuration(executionStageDuration);\n    setParticipationBaseline(participationBaseline);\n    setParticipationFloor(participationFloor);\n    setBaselineUpdateFactor(baselineUpdateFactor);\n    setBaselineQuorumFactor(baselineQuorumFactor);\n    // solhint-disable-next-line not-rely-on-time\n    lastDequeue = now;\n  }\n\n  function() external payable {\n    require(msg.data.length == 0, \"unknown method\");\n  }\n\n  /**\n   * @notice Updates the ratio of yes:yes+no votes needed for a specific class of proposals to pass.\n   * @param destination The destination of proposals for which this threshold should apply.\n   * @param functionId The function ID of proposals for which this threshold should apply. Zero\n   *   will set the default.\n   * @param threshold The threshold.\n   * @dev If no constitution is explicitly set the default is a simple majority, i.e. 1:2.\n   */\n  function setConstitution(\n    address destination,\n    bytes4 functionId,\n    uint256 threshold\n  ) external onlyOwner {\n    require(destination != address(0), \"Destination cannot be zero\");\n    require(\n      threshold > FIXED_HALF && threshold <= FixidityLib.fixed1().unwrap(),\n      \"Threshold has to be greater than majority and not greater than unanimity\"\n    );\n    if (functionId == 0) {\n      constitution[destination].defaultThreshold = FixidityLib.wrap(threshold);\n    } else {\n      constitution[destination].functionThresholds[functionId] = FixidityLib.wrap(threshold);\n    }\n    emit ConstitutionSet(destination, functionId, threshold);\n  }\n\n  /**\n   * @notice Updates the address that has permission to whitelist hotfix proposals.\n   * @param _council The address that has permission to whitelist hotfix proposals.\n   */\n  function setSecurityCouncil(address _council) external onlyOwner {\n    require(_council != address(0), \"Council cannot be address zero\");\n    require(_council != securityCouncil, \"Council unchanged\");\n    require(_council != approver, \"Council cannot be approver\");\n\n    securityCouncil = _council;\n    emit SecurityCouncilSet(_council);\n  }\n\n  /**\n   * @notice Sets the time window during which a hotfix has to be executed.\n   * @param timeWindow The time (in seconds) during which a hotfix can be\n   * executed after it has been prepared.\n   */\n  function setHotfixExecutionTimeWindow(uint256 timeWindow) external onlyOwner {\n    require(timeWindow > 0, \"Execution time window cannot be zero\");\n    hotfixExecutionTimeWindow = timeWindow;\n    emit HotfixExecutionTimeWindowSet(timeWindow);\n  }\n\n  /**\n   * @notice Creates a new proposal and adds it to end of the queue with no upvotes.\n   * @param values The values of CELO to be sent in the proposed transactions.\n   * @param destinations The destination addresses of the proposed transactions.\n   * @param data The concatenated data to be included in the proposed transactions.\n   * @param dataLengths The lengths of each transaction's data.\n   * @return The ID of the newly proposed proposal.\n   * @dev The minimum deposit must be included with the proposal, returned if/when the proposal is\n   *   dequeued.\n   */\n  function propose(\n    uint256[] calldata values,\n    address[] calldata destinations,\n    bytes calldata data,\n    uint256[] calldata dataLengths,\n    string calldata descriptionUrl\n  ) external payable returns (uint256) {\n    dequeueProposalsIfReady();\n    require(msg.value >= minDeposit, \"Too small deposit\");\n\n    proposalCount = proposalCount.add(1);\n    Proposals.Proposal storage proposal = proposals[proposalCount];\n    proposal.make(values, destinations, data, dataLengths, msg.sender, msg.value);\n    proposal.setDescriptionUrl(descriptionUrl);\n    queue.push(proposalCount);\n    // solhint-disable-next-line not-rely-on-time\n    emit ProposalQueued(proposalCount, msg.sender, proposal.transactions.length, msg.value, now);\n    return proposalCount;\n  }\n\n  /**\n   * @notice Upvotes a queued proposal.\n   * @param proposalId The ID of the proposal to upvote.\n   * @param lesser The ID of the proposal that will be just behind `proposalId` in the queue.\n   * @param greater The ID of the proposal that will be just ahead `proposalId` in the queue.\n   * @return Whether or not the upvote was made successfully.\n   * @dev Provide 0 for `lesser`/`greater` when the proposal will be at the tail/head of the queue.\n   * @dev Reverts if the account has already upvoted a proposal in the queue.\n   */\n  function upvote(\n    uint256 proposalId,\n    uint256 lesser,\n    uint256 greater\n  ) external nonReentrant returns (bool) {\n    dequeueProposalsIfReady();\n    // If acting on an expired proposal, expire the proposal and take no action.\n    if (removeIfQueuedAndExpired(proposalId)) {\n      return false;\n    }\n\n    address account = getAccounts().voteSignerToAccount(msg.sender);\n    Voter storage voter = voters[account];\n    removeIfQueuedAndExpired(voter.upvote.proposalId);\n\n    // We can upvote a proposal in the queue if we're not already upvoting a proposal in the queue.\n    uint256 weight = getLockedGold().getAccountTotalLockedGold(account);\n    require(weight > 0, \"cannot upvote without locking gold\");\n    require(queue.contains(proposalId), \"cannot upvote a proposal not in the queue\");\n    require(\n      voter.upvote.proposalId == 0 || !queue.contains(voter.upvote.proposalId),\n      \"cannot upvote more than one queued proposal\"\n    );\n    uint256 upvotes = queue.getValue(proposalId).add(weight);\n    queue.update(proposalId, upvotes, lesser, greater);\n    voter.upvote = UpvoteRecord(proposalId, weight);\n    emit ProposalUpvoted(proposalId, account, weight);\n    return true;\n  }\n\n  /**\n   * @notice Revokes an upvote on a queued proposal.\n   * @param lesser The ID of the proposal that will be just behind the previously upvoted proposal\n   *   in the queue.\n   * @param greater The ID of the proposal that will be just ahead of the previously upvoted\n   *   proposal in the queue.\n   * @return Whether or not the upvote was revoked successfully.\n   * @dev Provide 0 for `lesser`/`greater` when the proposal will be at the tail/head of the queue.\n   */\n  function revokeUpvote(uint256 lesser, uint256 greater) external nonReentrant returns (bool) {\n    dequeueProposalsIfReady();\n    address account = getAccounts().voteSignerToAccount(msg.sender);\n    Voter storage voter = voters[account];\n    uint256 proposalId = voter.upvote.proposalId;\n    require(proposalId != 0, \"Account has no historical upvote\");\n    removeIfQueuedAndExpired(proposalId);\n    if (queue.contains(proposalId)) {\n      queue.update(\n        proposalId,\n        queue.getValue(proposalId).sub(voter.upvote.weight),\n        lesser,\n        greater\n      );\n      emit ProposalUpvoteRevoked(proposalId, account, voter.upvote.weight);\n    }\n    voter.upvote = UpvoteRecord(0, 0);\n    return true;\n  }\n\n  /**\n   * @notice Approves a proposal in the approval stage.\n   * @param proposalId The ID of the proposal to approve.\n   * @param index The index of the proposal ID in `dequeued`.\n   * @return Whether or not the approval was made successfully.\n   */\n  function approve(uint256 proposalId, uint256 index) external onlyApprover returns (bool) {\n    dequeueProposalsIfReady();\n    (Proposals.Proposal storage proposal, Proposals.Stage stage) = requireDequeuedAndDeleteExpired(\n      proposalId,\n      index\n    );\n    if (!proposal.exists()) {\n      return false;\n    }\n\n    require(!proposal.isApproved(), \"Proposal already approved\");\n    require(\n      stage == Proposals.Stage.Referendum || stage == Proposals.Stage.Execution,\n      \"Proposal not in correct stage\"\n    );\n    proposal.approved = true;\n    // Ensures networkWeight is set by the end of the Referendum stage, even if 0 votes are cast.\n    proposal.networkWeight = getLockedGold().getTotalLockedGold();\n    emit ProposalApproved(proposalId);\n    return true;\n  }\n\n  /**\n   * @notice Votes on a proposal in the referendum stage.\n   * @param proposalId The ID of the proposal to vote on.\n   * @param index The index of the proposal ID in `dequeued`.\n   * @param value Whether to vote yes, no, or abstain.\n   * @return Whether or not the vote was cast successfully.\n   */\n  /* solhint-disable code-complexity */\n  function vote(\n    uint256 proposalId,\n    uint256 index,\n    Proposals.VoteValue value\n  ) external nonReentrant returns (bool) {\n    dequeueProposalsIfReady();\n    (Proposals.Proposal storage proposal, Proposals.Stage stage) = requireDequeuedAndDeleteExpired(\n      proposalId,\n      index\n    );\n    if (!proposal.exists()) {\n      return false;\n    }\n\n    require(stage == Proposals.Stage.Referendum, \"Incorrect proposal state\");\n    require(value != Proposals.VoteValue.None, \"Vote value unset\");\n\n    address account = getAccounts().voteSignerToAccount(msg.sender);\n    uint256 weight = getLockedGold().getAccountTotalGovernanceVotingPower(account);\n    require(weight != 0, \"Voter weight zero\");\n\n    _vote(\n      proposal,\n      proposalId,\n      index,\n      account,\n      value == Proposals.VoteValue.Yes ? weight : 0,\n      value == Proposals.VoteValue.No ? weight : 0,\n      value == Proposals.VoteValue.Abstain ? weight : 0\n    );\n    return true;\n  }\n\n  /**\n   * @notice Votes partially on a proposal in the referendum stage.\n   * @param proposalId The ID of the proposal to vote on.\n   * @param index The index of the proposal ID in `dequeued`.\n   * @param yesVotes The yes votes weight.\n   * @param noVotes The no votes weight.\n   * @param abstainVotes The abstain votes weight.\n   * @return Whether or not the vote was cast successfully.\n   */\n  /* solhint-disable code-complexity */\n  function votePartially(\n    uint256 proposalId,\n    uint256 index,\n    uint256 yesVotes,\n    uint256 noVotes,\n    uint256 abstainVotes\n  ) external nonReentrant returns (bool) {\n    dequeueProposalsIfReady();\n    (Proposals.Proposal storage proposal, Proposals.Stage stage) = requireDequeuedAndDeleteExpired(\n      proposalId,\n      index\n    );\n    if (!proposal.exists()) {\n      return false;\n    }\n\n    require(stage == Proposals.Stage.Referendum, \"Incorrect proposal state\");\n\n    address account = getAccounts().voteSignerToAccount(msg.sender);\n    uint256 totalVotingPower = getLockedGold().getAccountTotalGovernanceVotingPower(account);\n\n    require(\n      totalVotingPower >= yesVotes.add(noVotes).add(abstainVotes),\n      \"Voter doesn't have enough locked Celo (formerly known as Celo Gold)\"\n    );\n    _vote(proposal, proposalId, index, account, yesVotes, noVotes, abstainVotes);\n\n    return true;\n  }\n\n  /**\n   * @notice Revoke votes on all proposals of sender in the referendum stage.\n   * @return Whether or not all votes of an account were successfully revoked.\n   */\n  function revokeVotes() external nonReentrant returns (bool) {\n    address account = getAccounts().voteSignerToAccount(msg.sender);\n    Voter storage voter = voters[account];\n    for (\n      uint256 dequeueIndex = 0;\n      dequeueIndex < dequeued.length;\n      dequeueIndex = dequeueIndex.add(1)\n    ) {\n      VoteRecord storage voteRecord = voter.referendumVotes[dequeueIndex];\n\n      // Skip proposals where there was no vote cast by the user AND\n      // ensure vote record proposal matches identifier of dequeued index proposal.\n      if (\n        voteRecord.proposalId == dequeued[dequeueIndex] &&\n        (voteRecord.yesVotes != 0 ||\n          voteRecord.noVotes != 0 ||\n          voteRecord.abstainVotes != 0 ||\n          voteRecord.deprecated_weight != 0)\n      ) {\n        (Proposals.Proposal storage proposal, Proposals.Stage stage) =\n          requireDequeuedAndDeleteExpired(voteRecord.proposalId, dequeueIndex); // prettier-ignore\n\n        // only revoke from proposals which are still in referendum\n        if (stage == Proposals.Stage.Referendum) {\n          if (voteRecord.deprecated_weight != 0) {\n            // backward compatibility for transition period - this should be deleted later on\n            uint256 previousYes = voteRecord.deprecated_value == Proposals.VoteValue.Yes\n              ? voteRecord.deprecated_weight\n              : 0;\n            uint256 previousNo = voteRecord.deprecated_value == Proposals.VoteValue.No\n              ? voteRecord.deprecated_weight\n              : 0;\n            uint256 previousAbstain = voteRecord.deprecated_value == Proposals.VoteValue.Abstain\n              ? voteRecord.deprecated_weight\n              : 0;\n            proposal.updateVote(previousYes, previousNo, previousAbstain, 0, 0, 0);\n\n            proposal.networkWeight = getLockedGold().getTotalLockedGold();\n            emit ProposalVoteRevokedV2(\n              voteRecord.proposalId,\n              account,\n              previousYes,\n              previousNo,\n              previousAbstain\n            );\n          } else {\n            proposal.updateVote(\n              voteRecord.yesVotes,\n              voteRecord.noVotes,\n              voteRecord.abstainVotes,\n              0,\n              0,\n              0\n            );\n            proposal.networkWeight = getLockedGold().getTotalLockedGold();\n            emit ProposalVoteRevokedV2(\n              voteRecord.proposalId,\n              account,\n              voteRecord.yesVotes,\n              voteRecord.noVotes,\n              voteRecord.abstainVotes\n            );\n          }\n        }\n\n        // always delete dequeue vote records for gas refund as they must be expired or revoked\n        delete voter.referendumVotes[dequeueIndex];\n      }\n    }\n\n    // reset most recent referendum proposal ID to guarantee isVotingReferendum == false\n    voter.mostRecentReferendumProposal = 0;\n    return true;\n  }\n\n  /**\n   * @notice Executes a proposal in the execution stage, removing it from `dequeued`.\n   * @param proposalId The ID of the proposal to vote on.\n   * @param index The index of the proposal ID in `dequeued`.\n   * @return Whether or not the proposal was executed successfully.\n   * @dev Does not remove the proposal if the execution fails.\n   */\n  function execute(uint256 proposalId, uint256 index) external nonReentrant returns (bool) {\n    dequeueProposalsIfReady();\n    (Proposals.Proposal storage proposal, Proposals.Stage stage) = requireDequeuedAndDeleteExpired(\n      proposalId,\n      index\n    );\n    bool notExpired = proposal.exists();\n    if (notExpired) {\n      require(proposal.isApproved(), \"Proposal not approved\");\n      require(\n        stage == Proposals.Stage.Execution && _isProposalPassing(proposal),\n        \"Proposal not in execution stage or not passing\"\n      );\n      proposal.execute();\n      emit ProposalExecuted(proposalId);\n      deleteDequeuedProposal(proposal, proposalId, index);\n    }\n    return notExpired;\n  }\n\n  /**\n   * @notice Approves the hash of a hotfix transaction(s).\n   * @param hash The abi encoded keccak256 hash of the hotfix transaction(s) to be approved.\n   */\n  function approveHotfix(bytes32 hash) external hotfixNotExecuted(hash) {\n    require(msg.sender != address(0), \"msg.sender cannot be address zero\");\n    require(\n      msg.sender == approver || msg.sender == securityCouncil,\n      \"msg.sender not approver or Security Council\"\n    );\n\n    if (msg.sender == approver) {\n      hotfixes[hash].approved = true;\n    } else {\n      hotfixes[hash].councilApproved = true;\n    }\n    emit HotfixApproved(hash, msg.sender);\n  }\n\n  /**\n   * @notice Gives hotfix a time limit for execution.\n   * @param hash The hash of the hotfix to be prepared.\n   */\n  function prepareHotfix(bytes32 hash) external hotfixNotExecuted(hash) {\n    HotfixRecord storage _currentHotfix = hotfixes[hash];\n\n    uint256 _currentTime = now;\n    require(hotfixExecutionTimeWindow > 0, \"Hotfix execution time window not set\");\n    require(_currentHotfix.executionTimeLimit == 0, \"Hotfix already prepared for this timeframe.\");\n    require(_currentHotfix.approved, \"Hotfix not approved by approvers.\");\n    require(_currentHotfix.councilApproved, \"Hotfix not approved by security council.\");\n\n    _currentHotfix.executionTimeLimit = _currentTime.add(hotfixExecutionTimeWindow);\n    emit HotfixPrepared(hash, _currentTime.add(hotfixExecutionTimeWindow));\n  }\n\n  /**\n   * @notice Executes a whitelisted proposal.\n   * @param values The values of CELO to be sent in the proposed transactions.\n   * @param destinations The destination addresses of the proposed transactions.\n   * @param data The concatenated data to be included in the proposed transactions.\n   * @param dataLengths The lengths of each transaction's data.\n   * @param salt Arbitrary salt associated with hotfix which guarantees uniqueness of hash.\n   * @dev Reverts if hotfix is already executed, not approved, or not prepared for current epoch.\n   */\n  function executeHotfix(\n    uint256[] calldata values,\n    address[] calldata destinations,\n    bytes calldata data,\n    uint256[] calldata dataLengths,\n    bytes32 salt\n  ) external {\n    bytes32 hash = keccak256(abi.encode(values, destinations, data, dataLengths, salt));\n\n    (\n      bool approved,\n      bool councilApproved,\n      bool executed,\n      uint256 executionTimeLimit\n    ) = getHotfixRecord(hash);\n    require(!executed, \"hotfix already executed\");\n    require(approved, \"hotfix not approved\");\n    require(councilApproved, \"hotfix not approved by security council\");\n    require(executionTimeLimit >= now, \"Execution time limit has already been reached.\");\n    Proposals.makeMem(values, destinations, data, dataLengths, msg.sender, 0).executeMem();\n\n    hotfixes[hash].executed = true;\n    emit HotfixExecuted(hash);\n  }\n\n  /**\n   * @notice Withdraws refunded CELO deposits.\n   * @return Whether or not the withdraw was successful.\n   */\n  function withdraw() external nonReentrant returns (bool) {\n    uint256 value = refundedDeposits[msg.sender];\n    require(value != 0, \"Nothing to withdraw\");\n    require(value <= address(this).balance, \"Inconsistent balance\");\n    refundedDeposits[msg.sender] = 0;\n    msg.sender.sendValue(value);\n    return true;\n  }\n\n  /**\n   * @notice Returns whether or not a particular proposal is passing according to the constitution\n   *   and the participation levels.\n   * @param proposalId The ID of the proposal.\n   * @return Whether or not the proposal is passing.\n   */\n  function isProposalPassing(uint256 proposalId) external view returns (bool) {\n    return _isProposalPassing(proposals[proposalId]);\n  }\n\n  /**\n   * @notice Returns whether a proposal is dequeued at the given index.\n   * @param proposalId The ID of the proposal.\n   * @param index The index of the proposal ID in `dequeued`.\n   * @return Whether the proposal is in `dequeued`.\n   */\n  function isDequeuedProposal(uint256 proposalId, uint256 index) external view returns (bool) {\n    return _isDequeuedProposal(proposals[proposalId], proposalId, index);\n  }\n\n  /**\n   * @notice Returns whether or not a dequeued proposal has expired.\n   * @param proposalId The ID of the proposal.\n   * @return Whether or not the dequeued proposal has expired.\n   */\n  function isDequeuedProposalExpired(uint256 proposalId) external view returns (bool) {\n    Proposals.Proposal storage proposal = proposals[proposalId];\n    return _isDequeuedProposalExpired(proposal, getProposalDequeuedStage(proposal));\n  }\n\n  /**\n   * @notice Returns the constitution for a particular destination and function ID.\n   * @param destination The destination address to get the constitution for.\n   * @param functionId The function ID to get the constitution for, zero for the destination\n   *   default.\n   * @return The ratio of yes:no votes needed to exceed in order to pass the proposal.\n   */\n  function getConstitution(address destination, bytes4 functionId) external view returns (uint256) {\n    return _getConstitution(destination, functionId).unwrap();\n  }\n\n  /**\n   * @notice Returns whether or not a particular account is voting on proposals.\n   * @param account The address of the account.\n   * @return Whether or not the account is voting on proposals.\n   */\n  function isVoting(address account) external view returns (bool) {\n    Voter storage voter = voters[account];\n    uint256 upvotedProposal = voter.upvote.proposalId;\n    bool isVotingQueue = upvotedProposal != 0 &&\n      isQueued(upvotedProposal) &&\n      !isQueuedProposalExpired(upvotedProposal);\n    Proposals.Proposal storage proposal = proposals[voter.mostRecentReferendumProposal];\n    bool isVotingReferendum = (getProposalDequeuedStage(proposal) == Proposals.Stage.Referendum);\n    return isVotingQueue || isVotingReferendum;\n  }\n\n  /**\n   * @notice Returns the number of seconds proposals stay in the referendum stage.\n   * @return The number of seconds proposals stay in the referendum stage.\n   */\n  function getReferendumStageDuration() external view returns (uint256) {\n    return stageDurations.referendum;\n  }\n\n  /**\n   * @notice Returns the number of seconds proposals stay in the execution stage.\n   * @return The number of seconds proposals stay in the execution stage.\n   */\n  function getExecutionStageDuration() external view returns (uint256) {\n    return stageDurations.execution;\n  }\n\n  /**\n   * @notice Returns the participation parameters.\n   * @return baseline The participation baseline parameter.\n   * @return baselineFloor The participation baseline floor parameter.\n   * @return baselineUpdateFactor The participation baseline update factor parameter.\n   * @return baselineQuorumFactor The participation baseline quorum factor parameter.\n   */\n  function getParticipationParameters() external view returns (uint256, uint256, uint256, uint256) {\n    return (\n      participationParameters.baseline.unwrap(),\n      participationParameters.baselineFloor.unwrap(),\n      participationParameters.baselineUpdateFactor.unwrap(),\n      participationParameters.baselineQuorumFactor.unwrap()\n    );\n  }\n\n  /**\n   * @notice Returns whether or not a proposal exists.\n   * @param proposalId The ID of the proposal.\n   * @return Whether or not the proposal exists.\n   */\n  function proposalExists(uint256 proposalId) external view returns (bool) {\n    return proposals[proposalId].exists();\n  }\n\n  /**\n   * @notice Returns an unpacked proposal struct with its transaction count.\n   * @param proposalId The ID of the proposal to unpack.\n   * @return proposer\n   * @return deposit\n   * @return timestamp\n   * @return transaction Transaction count.\n   * @return description Description url.\n   */\n  function getProposal(\n    uint256 proposalId\n  ) external view returns (address, uint256, uint256, uint256, string memory, uint256, bool) {\n    return proposals[proposalId].unpack();\n  }\n\n  /**\n   * @notice Returns a specified transaction in a proposal.\n   * @param proposalId The ID of the proposal to query.\n   * @param index The index of the specified transaction in the proposal's transaction list.\n   * @return value Transaction value.\n   * @return destination Transaction destination.\n   * @return data Transaction data.\n   */\n  function getProposalTransaction(\n    uint256 proposalId,\n    uint256 index\n  ) external view returns (uint256, address, bytes memory) {\n    return proposals[proposalId].getTransaction(index);\n  }\n\n  /**\n   * @notice Returns whether or not a proposal has been approved.\n   * @param proposalId The ID of the proposal.\n   * @return Whether or not the proposal has been approved.\n   */\n  function isApproved(uint256 proposalId) external view returns (bool) {\n    return proposals[proposalId].isApproved();\n  }\n\n  /**\n   * @notice Returns the referendum vote totals for a proposal.\n   * @param proposalId The ID of the proposal.\n   * @return yes The yes vote totals.\n   * @return no The no vote totals.\n   * @return abstain The abstain vote totals.\n   */\n  function getVoteTotals(uint256 proposalId) external view returns (uint256, uint256, uint256) {\n    return proposals[proposalId].getVoteTotals();\n  }\n\n  /**\n   * @notice Returns an accounts vote record on a particular index in `dequeued`.\n   * @param account The address of the account to get the record for.\n   * @param index The index in `dequeued`.\n   * @return The corresponding proposal ID, vote value, and weight.\n   * @return The depreciated vote value.\n   * @return The deprecieated weight.\n   * @return The yes weight.\n   * @return The no weight.\n   * @return The abstain weight.\n   */\n  function getVoteRecord(\n    address account,\n    uint256 index\n  ) external view returns (uint256, uint256, uint256, uint256, uint256, uint256) {\n    VoteRecord storage record = voters[account].referendumVotes[index];\n    return (\n      record.proposalId,\n      uint256(record.deprecated_value),\n      record.deprecated_weight,\n      record.yesVotes,\n      record.noVotes,\n      record.abstainVotes\n    );\n  }\n\n  /**\n   * @notice Returns the number of proposals in the queue.\n   * @return The number of proposals in the queue.\n   */\n  function getQueueLength() external view returns (uint256) {\n    return queue.list.numElements;\n  }\n\n  /**\n   * @notice Returns the number of upvotes the queued proposal has received.\n   * @param proposalId The ID of the proposal.\n   * @return The number of upvotes a queued proposal has received.\n   */\n  function getUpvotes(uint256 proposalId) external view returns (uint256) {\n    require(isQueued(proposalId), \"Proposal not queued\");\n    return queue.getValue(proposalId);\n  }\n\n  /**\n   * @notice Returns the proposal ID and upvote total for all queued proposals.\n   * @return proposalID The proposal ID for all queued proposals.\n   * @return total The upvote total for all queued proposals.\n   * @dev Note that this includes expired proposals that have yet to be removed from the queue.\n   */\n  function getQueue() external view returns (uint256[] memory, uint256[] memory) {\n    return queue.getElements();\n  }\n\n  /**\n   * @notice Returns the dequeued proposal IDs.\n   * @return The dequeued proposal IDs.\n   * @dev Note that this includes unused indices with proposalId == 0 from deleted proposals.\n   */\n  function getDequeue() external view returns (uint256[] memory) {\n    return dequeued;\n  }\n\n  /**\n   * @notice Returns the ID of the proposal upvoted by `account` and the weight of that upvote.\n   * @param account The address of the account.\n   * @return The ID of the proposal upvoted by `account`.\n   * @return The weight of that upvote.\n   */\n  function getUpvoteRecord(address account) external view returns (uint256, uint256) {\n    UpvoteRecord memory upvoteRecord = voters[account].upvote;\n    return (upvoteRecord.proposalId, upvoteRecord.weight);\n  }\n\n  /**\n   * @notice Returns the ID of the most recently dequeued proposal voted on by `account`.\n   * @param account The address of the account.\n   * @return The ID of the most recently dequeued proposal voted on by `account`..\n   */\n  function getMostRecentReferendumProposal(address account) external view returns (uint256) {\n    return voters[account].mostRecentReferendumProposal;\n  }\n\n  /**\n   * @notice Returns stage of governance process given proposal is in\n   * @param proposalId The ID of the proposal to query.\n   * @return proposal stage\n   */\n  function getProposalStage(uint256 proposalId) external view returns (Proposals.Stage) {\n    if (proposalId == 0 || proposalId > proposalCount) {\n      return Proposals.Stage.None;\n    }\n    Proposals.Proposal storage proposal = proposals[proposalId];\n    if (isQueued(proposalId)) {\n      return\n        _isQueuedProposalExpired(proposal) ? Proposals.Stage.Expiration : Proposals.Stage.Queued;\n    } else {\n      Proposals.Stage stage = getProposalDequeuedStage(proposal);\n      return _isDequeuedProposalExpired(proposal, stage) ? Proposals.Stage.Expiration : stage;\n    }\n  }\n\n  /**\n   * @notice Returns the storage, major, minor, and patch version of the contract.\n   * @return Storage version of the contract.\n   * @return Major version of the contract.\n   * @return Minor version of the contract.\n   * @return Patch version of the contract.\n   */\n  function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) {\n    return (1, 5, 1, 0);\n  }\n\n  /**\n   * @param values The values of CELO to be sent in the proposed transactions.\n   * @param destinations The destination addresses of the proposed transactions.\n   * @param data The concatenated data to be included in the proposed transactions.\n   * @param dataLengths The lengths of each transaction's data.\n   * @param salt Arbitrary salt associated with hotfix which guarantees uniqueness of hash.\n   * @return The hash of the hotfix.\n   */\n  function getHotfixHash(\n    uint256[] calldata values,\n    address[] calldata destinations,\n    bytes calldata data,\n    uint256[] calldata dataLengths,\n    bytes32 salt\n  ) external pure returns (bytes32) {\n    return keccak256(abi.encode(values, destinations, data, dataLengths, salt));\n  }\n\n  /**\n   * @notice Updates the address that has permission to approve proposals in the approval stage.\n   * @param _approver The address that has permission to approve proposals in the approval stage.\n   */\n  function setApprover(address _approver) public onlyOwner {\n    require(_approver != address(0), \"Approver cannot be 0\");\n    require(_approver != approver, \"Approver unchanged\");\n    require(_approver != securityCouncil, \"Approver cannot be council\");\n    approver = _approver;\n    emit ApproverSet(_approver);\n  }\n\n  /**\n   * @notice Updates the number of proposals to dequeue at a time.\n   * @param _concurrentProposals The number of proposals to dequeue at a time.\n   */\n  function setConcurrentProposals(uint256 _concurrentProposals) public onlyOwner {\n    require(_concurrentProposals != 0, \"Number of proposals must be larger than zero\");\n    require(_concurrentProposals != concurrentProposals, \"Number of proposals unchanged\");\n    concurrentProposals = _concurrentProposals;\n    emit ConcurrentProposalsSet(_concurrentProposals);\n  }\n\n  /**\n   * @notice Updates the minimum deposit needed to make a proposal.\n   * @param _minDeposit The minimum CELO deposit needed to make a proposal.\n   */\n  function setMinDeposit(uint256 _minDeposit) public onlyOwner {\n    require(_minDeposit != 0, \"minDeposit must be larger than 0\");\n    require(_minDeposit != minDeposit, \"Minimum deposit unchanged\");\n    minDeposit = _minDeposit;\n    emit MinDepositSet(_minDeposit);\n  }\n\n  /**\n   * @notice Updates the number of seconds before a queued proposal expires.\n   * @param _queueExpiry The number of seconds a proposal can stay in the queue before expiring.\n   */\n  function setQueueExpiry(uint256 _queueExpiry) public onlyOwner {\n    require(_queueExpiry != 0, \"QueueExpiry must be larger than 0\");\n    require(_queueExpiry != queueExpiry, \"QueueExpiry unchanged\");\n    queueExpiry = _queueExpiry;\n    emit QueueExpirySet(_queueExpiry);\n  }\n\n  /**\n   * @notice Updates the minimum number of seconds before the next batch of proposals can be\n   *   dequeued.\n   * @param _dequeueFrequency The number of seconds before the next batch of proposals can be\n   *   dequeued.\n   */\n  function setDequeueFrequency(uint256 _dequeueFrequency) public onlyOwner {\n    require(_dequeueFrequency != 0, \"dequeueFrequency must be larger than 0\");\n    require(_dequeueFrequency != dequeueFrequency, \"dequeueFrequency unchanged\");\n    dequeueFrequency = _dequeueFrequency;\n    emit DequeueFrequencySet(_dequeueFrequency);\n  }\n\n  /**\n   * @notice Updates the number of seconds proposals stay in the referendum stage.\n   * @param referendumStageDuration The number of seconds proposals stay in the referendum stage.\n   */\n  function setReferendumStageDuration(uint256 referendumStageDuration) public onlyOwner {\n    require(referendumStageDuration != 0, \"Duration must be larger than 0\");\n    require(referendumStageDuration != stageDurations.referendum, \"Duration unchanged\");\n    stageDurations.referendum = referendumStageDuration;\n    emit ReferendumStageDurationSet(referendumStageDuration);\n  }\n\n  /**\n   * @notice Updates the number of seconds proposals stay in the execution stage.\n   * @param executionStageDuration The number of seconds proposals stay in the execution stage.\n   */\n  function setExecutionStageDuration(uint256 executionStageDuration) public onlyOwner {\n    require(executionStageDuration != 0, \"Duration must be larger than 0\");\n    require(executionStageDuration != stageDurations.execution, \"Duration unchanged\");\n    stageDurations.execution = executionStageDuration;\n    emit ExecutionStageDurationSet(executionStageDuration);\n  }\n\n  /**\n   * @notice Updates the participation baseline.\n   * @param participationBaseline The value of the baseline.\n   */\n  function setParticipationBaseline(uint256 participationBaseline) public onlyOwner {\n    FixidityLib.Fraction memory participationBaselineFrac = FixidityLib.wrap(participationBaseline);\n    require(\n      FixidityLib.isProperFraction(participationBaselineFrac),\n      \"Participation baseline greater than one\"\n    );\n    require(\n      !participationBaselineFrac.equals(participationParameters.baseline),\n      \"Participation baseline unchanged\"\n    );\n    participationParameters.baseline = participationBaselineFrac;\n    emit ParticipationBaselineUpdated(participationBaseline);\n  }\n\n  /**\n   * @notice Updates the floor of the participation baseline.\n   * @param participationFloor The value at which the baseline is floored.\n   */\n  function setParticipationFloor(uint256 participationFloor) public onlyOwner {\n    FixidityLib.Fraction memory participationFloorFrac = FixidityLib.wrap(participationFloor);\n    require(\n      FixidityLib.isProperFraction(participationFloorFrac),\n      \"Participation floor greater than one\"\n    );\n    require(\n      !participationFloorFrac.equals(participationParameters.baselineFloor),\n      \"Participation baseline floor unchanged\"\n    );\n    participationParameters.baselineFloor = participationFloorFrac;\n    emit ParticipationFloorSet(participationFloor);\n  }\n\n  /**\n   * @notice Updates the weight of the new participation in the baseline update rule.\n   * @param baselineUpdateFactor The new baseline update factor.\n   */\n  function setBaselineUpdateFactor(uint256 baselineUpdateFactor) public onlyOwner {\n    FixidityLib.Fraction memory baselineUpdateFactorFrac = FixidityLib.wrap(baselineUpdateFactor);\n    require(\n      FixidityLib.isProperFraction(baselineUpdateFactorFrac),\n      \"Baseline update factor greater than one\"\n    );\n    require(\n      !baselineUpdateFactorFrac.equals(participationParameters.baselineUpdateFactor),\n      \"Baseline update factor unchanged\"\n    );\n    participationParameters.baselineUpdateFactor = baselineUpdateFactorFrac;\n    emit ParticipationBaselineUpdateFactorSet(baselineUpdateFactor);\n  }\n\n  /**\n   * @notice Updates the proportion of the baseline that constitutes quorum.\n   * @param baselineQuorumFactor The new baseline quorum factor.\n   */\n  function setBaselineQuorumFactor(uint256 baselineQuorumFactor) public onlyOwner {\n    FixidityLib.Fraction memory baselineQuorumFactorFrac = FixidityLib.wrap(baselineQuorumFactor);\n    require(\n      FixidityLib.isProperFraction(baselineQuorumFactorFrac),\n      \"Baseline quorum factor greater than one\"\n    );\n    require(\n      !baselineQuorumFactorFrac.equals(participationParameters.baselineQuorumFactor),\n      \"Baseline quorum factor unchanged\"\n    );\n    participationParameters.baselineQuorumFactor = baselineQuorumFactorFrac;\n    emit ParticipationBaselineQuorumFactorSet(baselineQuorumFactor);\n  }\n\n  /**\n   * @notice Removes the proposals with the most upvotes from the queue, moving them to the\n   *   approval stage.\n   * @dev If any of the top proposals have expired, they are deleted.\n   */\n  function dequeueProposalsIfReady() public {\n    // solhint-disable-next-line not-rely-on-time\n    if (now >= lastDequeue.add(dequeueFrequency)) {\n      uint256 numProposalsToDequeue = Math.min(concurrentProposals, queue.list.numElements);\n      uint256[] memory dequeuedIds = queue.popN(numProposalsToDequeue);\n\n      bool wasAnyProposalDequeued = false;\n      for (uint256 i = 0; i < numProposalsToDequeue; i = i.add(1)) {\n        uint256 proposalId = dequeuedIds[i];\n        Proposals.Proposal storage proposal = proposals[proposalId];\n        if (_isQueuedProposalExpired(proposal)) {\n          emit ProposalExpired(proposalId);\n          continue;\n        }\n        refundedDeposits[proposal.proposer] = refundedDeposits[proposal.proposer].add(\n          proposal.deposit\n        );\n        // solhint-disable-next-line not-rely-on-time\n        proposal.timestamp = now;\n        if (emptyIndices.length != 0) {\n          uint256 indexOfLastEmptyIndex = emptyIndices.length.sub(1);\n          dequeued[emptyIndices[indexOfLastEmptyIndex]] = proposalId;\n          delete emptyIndices[indexOfLastEmptyIndex];\n          emptyIndices.length = indexOfLastEmptyIndex;\n        } else {\n          dequeued.push(proposalId);\n        }\n        // solhint-disable-next-line not-rely-on-time\n        emit ProposalDequeued(proposalId, now);\n        wasAnyProposalDequeued = true;\n      }\n      if (wasAnyProposalDequeued) {\n        // solhint-disable-next-line not-rely-on-time\n        lastDequeue = now;\n      }\n    }\n  }\n\n  /**\n   * @notice When delegator removes votes from delegatee during the time when delegator is voting\n   * for governance proposal, this method will remove votes from voted proposal proportionally.\n   * @param account The address of the account.\n   * @param newVotingPower The adjusted voting power of delegatee.\n   */\n  function removeVotesWhenRevokingDelegatedVotes(\n    address account,\n    uint256 newVotingPower\n  ) public onlyLockedGold {\n    _removeVotesWhenRevokingDelegatedVotes(account, newVotingPower);\n  }\n\n  /**\n   * @notice Resets the hotfix record when after the execution time limit has elapsed.\n   * @param hash The abi encoded keccak256 hash of the hotfix transaction.\n   */\n  function resetHotFixRecord(bytes32 hash) public hotfixNotExecuted(hash) hotfixTimedOut(hash) {\n    hotfixes[hash].approved = false;\n    hotfixes[hash].councilApproved = false;\n    hotfixes[hash].executionTimeLimit = 0;\n    emit HotfixRecordReset(hash);\n  }\n\n  /**\n   * @notice Gets information about a hotfix.\n   * @param hash The abi encoded keccak256 hash of the hotfix transaction.\n   * @return Hotfix approved by approver.\n   * @return Hotfix approved by SecurityCouncil.\n   * @return Hotfix executed.\n   * @return Hotfix execution time limit.\n   */\n  function getHotfixRecord(bytes32 hash) public view returns (bool, bool, bool, uint256) {\n    return (\n      hotfixes[hash].approved,\n      hotfixes[hash].councilApproved,\n      hotfixes[hash].executed,\n      hotfixes[hash].executionTimeLimit\n    );\n  }\n\n  /**\n   * @notice Returns whether or not a proposal is in the queue.\n   * @dev NOTE: proposal may be expired\n   * @param proposalId The ID of the proposal.\n   * @return Whether or not the proposal is in the queue.\n   */\n  function isQueued(uint256 proposalId) public view returns (bool) {\n    return queue.contains(proposalId);\n  }\n\n  /**\n   * @notice Returns whether or not a queued proposal has expired.\n   * @param proposalId The ID of the proposal.\n   * @return Whether or not the dequeued proposal has expired.\n   */\n  function isQueuedProposalExpired(uint256 proposalId) public view returns (bool) {\n    return _isQueuedProposalExpired(proposals[proposalId]);\n  }\n\n  /**\n   * @notice Returns max number of votes cast by an account.\n   * @param account The address of the account.\n   * @return The total number of votes cast by an account.\n   */\n  function getAmountOfGoldUsedForVoting(address account) public view returns (uint256) {\n    Voter storage voter = voters[account];\n\n    uint256 upvotedProposalId = voter.upvote.proposalId;\n    bool isVotingQueue = upvotedProposalId != 0 &&\n      isQueued(upvotedProposalId) &&\n      !isQueuedProposalExpired(upvotedProposalId);\n\n    // Calculate queue upvote weight using locked gold (upvotes use locked gold weight)\n    uint256 queueWeight = 0;\n    if (isVotingQueue) {\n      queueWeight = getLockedGold().getAccountTotalLockedGold(account);\n    }\n\n    uint256 maxReferendumUsed = 0;\n    for (uint256 index = 0; index < dequeued.length; index = index.add(1)) {\n      uint256 proposalId = dequeued[index];\n      Proposals.Proposal storage proposal = proposals[proposalId];\n      bool isVotingReferendum = (getProposalDequeuedStage(proposal) == Proposals.Stage.Referendum);\n\n      if (!isVotingReferendum) {\n        continue;\n      }\n\n      VoteRecord storage voteRecord = voter.referendumVotes[index];\n      // skip if vote record is not for this proposal\n      if (voteRecord.proposalId != proposalId) {\n        continue;\n      }\n\n      uint256 votesCast = voteRecord.yesVotes.add(voteRecord.noVotes).add(voteRecord.abstainVotes);\n      maxReferendumUsed = Math.max(\n        maxReferendumUsed,\n        // backward compatibility for transition period - this should be updated later on\n        votesCast == 0 ? voteRecord.deprecated_weight : votesCast\n      );\n    }\n\n    // Return the maximum of queue upvote weight and referendum votes\n    return Math.max(queueWeight, maxReferendumUsed);\n  }\n\n  /**\n   * @notice When delegator removes votes from delegatee during the time when delegator is voting\n   * for governance proposal, this method will remove votes from voted proposal proportionally.\n   * @param account The address of the account.\n   * @param newVotingPower The adjusted voting power of delegatee.\n   */\n  function _removeVotesWhenRevokingDelegatedVotes(\n    address account,\n    uint256 newVotingPower\n  ) internal {\n    Voter storage voter = voters[account];\n\n    for (uint256 index = 0; index < dequeued.length; index = index.add(1)) {\n      uint256 proposalId = dequeued[index];\n      Proposals.Proposal storage proposal = proposals[proposalId];\n      bool isVotingReferendum = (getProposalDequeuedStage(proposal) == Proposals.Stage.Referendum);\n\n      if (!isVotingReferendum) {\n        continue;\n      }\n\n      VoteRecord storage voteRecord = voter.referendumVotes[index];\n\n      // skip if vote record is not for this proposal\n      if (voteRecord.proposalId != proposalId) {\n        delete voter.referendumVotes[index];\n        continue;\n      }\n\n      uint256 sumOfVotes = voteRecord.yesVotes.add(voteRecord.noVotes).add(voteRecord.abstainVotes);\n\n      if (sumOfVotes > newVotingPower) {\n        uint256 toRemove = sumOfVotes.sub(newVotingPower);\n\n        uint256 abstainToRemove = getVotesPortion(toRemove, voteRecord.abstainVotes, sumOfVotes);\n        uint256 yesToRemove = getVotesPortion(toRemove, voteRecord.yesVotes, sumOfVotes);\n        uint256 noToRemove = getVotesPortion(toRemove, voteRecord.noVotes, sumOfVotes);\n\n        uint256 totalRemoved = abstainToRemove.add(yesToRemove).add(noToRemove);\n\n        uint256 yesVotes = voteRecord.yesVotes.sub(yesToRemove);\n        uint256 noVotes = voteRecord.noVotes.sub(noToRemove);\n        uint256 abstainVotes = voteRecord.abstainVotes.sub(abstainToRemove);\n\n        if (totalRemoved < toRemove) {\n          // in case of rounding error\n          uint256 roundingToRemove = toRemove.sub(totalRemoved);\n\n          uint256 toRemoveRounding = Math.min(roundingToRemove, yesVotes);\n          yesVotes = yesVotes.sub(toRemoveRounding);\n          roundingToRemove = roundingToRemove.sub(toRemoveRounding);\n\n          if (roundingToRemove != 0) {\n            toRemoveRounding = Math.min(roundingToRemove, noVotes);\n            noVotes = noVotes.sub(toRemoveRounding);\n            roundingToRemove = roundingToRemove.sub(toRemoveRounding);\n          }\n\n          if (roundingToRemove != 0) {\n            toRemoveRounding = Math.min(roundingToRemove, abstainVotes);\n            abstainVotes = abstainVotes.sub(toRemoveRounding);\n          }\n        }\n\n        proposal.updateVote(\n          voteRecord.yesVotes,\n          voteRecord.noVotes,\n          voteRecord.abstainVotes,\n          yesVotes,\n          noVotes,\n          abstainVotes\n        );\n\n        voteRecord.abstainVotes = abstainVotes;\n        voteRecord.yesVotes = yesVotes;\n        voteRecord.noVotes = noVotes;\n      }\n    }\n  }\n\n  function _getConstitution(\n    address destination,\n    bytes4 functionId\n  ) internal view returns (FixidityLib.Fraction memory) {\n    // Default to a simple majority.\n    FixidityLib.Fraction memory threshold = FixidityLib.wrap(FIXED_HALF);\n    if (constitution[destination].functionThresholds[functionId].unwrap() != 0) {\n      threshold = constitution[destination].functionThresholds[functionId];\n    } else if (constitution[destination].defaultThreshold.unwrap() != 0) {\n      threshold = constitution[destination].defaultThreshold;\n    }\n    return threshold;\n  }\n\n  /**\n   * @notice Returns the stage of a dequeued proposal.\n   * @param proposal The proposal struct.\n   * @return The stage of the dequeued proposal.\n   * @dev Must be called on a dequeued proposal.\n   */\n  function getProposalDequeuedStage(\n    Proposals.Proposal storage proposal\n  ) internal view returns (Proposals.Stage) {\n    uint256 stageStartTime = proposal.timestamp.add(stageDurations.referendum).add(\n      stageDurations.execution\n    );\n    // solhint-disable-next-line not-rely-on-time\n    if (\n      now >= stageStartTime &&\n      (proposal.transactions.length != 0 ||\n        // proposals with 0 transactions can expire only when not approved or not passing\n        !proposal.isApproved() ||\n        !_isProposalPassing(proposal))\n    ) {\n      return Proposals.Stage.Expiration;\n    }\n    stageStartTime = stageStartTime.sub(stageDurations.execution);\n    // solhint-disable-next-line not-rely-on-time\n    if (now >= stageStartTime) {\n      return Proposals.Stage.Execution;\n    }\n    return Proposals.Stage.Referendum;\n  }\n\n  /**\n   * @notice Removes a proposal if it is queued and expired.\n   * @param proposalId The ID of the proposal to remove.\n   * @return Whether the proposal was removed.\n   */\n  function removeIfQueuedAndExpired(uint256 proposalId) private returns (bool) {\n    if (isQueued(proposalId) && isQueuedProposalExpired(proposalId)) {\n      queue.remove(proposalId);\n      emit ProposalExpired(proposalId);\n      return true;\n    }\n    return false;\n  }\n\n  /**\n   * @notice Requires a proposal is dequeued and removes it if expired.\n   * @param proposalId The ID of the proposal.\n   * @return The proposal storage struct corresponding to `proposalId`.\n   * @return The proposal stage corresponding to `proposalId`.\n   */\n  function requireDequeuedAndDeleteExpired(\n    uint256 proposalId,\n    uint256 index\n  ) private returns (Proposals.Proposal storage, Proposals.Stage) {\n    Proposals.Proposal storage proposal = proposals[proposalId];\n    require(_isDequeuedProposal(proposal, proposalId, index), \"Proposal not dequeued\");\n    Proposals.Stage stage = getProposalDequeuedStage(proposal);\n    if (_isDequeuedProposalExpired(proposal, stage)) {\n      deleteDequeuedProposal(proposal, proposalId, index);\n      return (proposal, Proposals.Stage.Expiration);\n    }\n    return (proposal, stage);\n  }\n\n  /**\n   * @notice Votes on a proposal in the referendum stage.\n   * @param proposal The proposal struct.\n   * @param proposalId The ID of the proposal to vote on.\n   * @param index The index of the proposal ID in `dequeued`.\n   * @param account Account based on signer.\n   * @param yesVotes The yes votes weight.\n   * @param noVotes The no votes weight.\n   * @param abstainVotes The abstain votes weight.\n   * @return Whether or not the proposal is passing.\n   */\n  function _vote(\n    Proposals.Proposal storage proposal,\n    uint256 proposalId,\n    uint256 index,\n    address account,\n    uint256 yesVotes,\n    uint256 noVotes,\n    uint256 abstainVotes\n  ) private {\n    Voter storage voter = voters[account];\n\n    VoteRecord storage previousVoteRecord = voter.referendumVotes[index];\n\n    if (previousVoteRecord.proposalId != proposalId) {\n      // VoteRecord is being stored based on index (in `dequeued`) rather than proposalId.\n      // It can happen that user voted on proposal that later gets deleted.\n      // VoteRecord will still stay in `referendumVotes` mapping.\n      // Once new proposal is created it might get same index as previous proposal.\n      // In such case we need to check whether existing VoteRecord is relevant to new\n      // proposal of whether it is just left over data.\n      proposal.updateVote(0, 0, 0, yesVotes, noVotes, abstainVotes);\n    } else if (previousVoteRecord.deprecated_weight != 0) {\n      // backward compatibility for transition period - this should be deleted later on\n      proposal.updateVote(\n        previousVoteRecord.deprecated_value == Proposals.VoteValue.Yes\n          ? previousVoteRecord.deprecated_weight\n          : 0,\n        previousVoteRecord.deprecated_value == Proposals.VoteValue.No\n          ? previousVoteRecord.deprecated_weight\n          : 0,\n        previousVoteRecord.deprecated_value == Proposals.VoteValue.Abstain\n          ? previousVoteRecord.deprecated_weight\n          : 0,\n        yesVotes,\n        noVotes,\n        abstainVotes\n      );\n    } else {\n      proposal.updateVote(\n        previousVoteRecord.yesVotes,\n        previousVoteRecord.noVotes,\n        previousVoteRecord.abstainVotes,\n        yesVotes,\n        noVotes,\n        abstainVotes\n      );\n    }\n\n    proposal.networkWeight = getLockedGold().getTotalLockedGold();\n    voter.referendumVotes[index] = VoteRecord(\n      Proposals.VoteValue.None,\n      proposalId,\n      0,\n      yesVotes,\n      noVotes,\n      abstainVotes\n    );\n    if (proposal.timestamp > proposals[voter.mostRecentReferendumProposal].timestamp) {\n      voter.mostRecentReferendumProposal = proposalId;\n    }\n\n    emit ProposalVotedV2(proposalId, account, yesVotes, noVotes, abstainVotes);\n  }\n\n  /**\n   * @notice Deletes a dequeued proposal.\n   * @param proposal The proposal struct.\n   * @param proposalId The ID of the proposal to delete.\n   * @param index The index of the proposal ID in `dequeued`.\n   * @dev Must always be preceded by `isDequeuedProposal`, which checks `index`.\n   */\n  function deleteDequeuedProposal(\n    Proposals.Proposal storage proposal,\n    uint256 proposalId,\n    uint256 index\n  ) private {\n    if (proposal.isApproved() && proposal.networkWeight != 0) {\n      updateParticipationBaseline(proposal);\n    }\n    dequeued[index] = 0;\n    emptyIndices.push(index);\n    delete proposals[proposalId];\n  }\n\n  /**\n   * @notice Updates the participation baseline based on the proportion of BondedDeposit weight\n   *   that participated in the proposal's Referendum stage.\n   * @param proposal The proposal struct.\n   */\n  function updateParticipationBaseline(Proposals.Proposal storage proposal) private {\n    FixidityLib.Fraction memory participation = proposal.getParticipation();\n    FixidityLib.Fraction memory participationComponent = participation.multiply(\n      participationParameters.baselineUpdateFactor\n    );\n    FixidityLib.Fraction memory baselineComponent = participationParameters.baseline.multiply(\n      FixidityLib.fixed1().subtract(participationParameters.baselineUpdateFactor)\n    );\n    participationParameters.baseline = participationComponent.add(baselineComponent);\n    if (participationParameters.baseline.lt(participationParameters.baselineFloor)) {\n      participationParameters.baseline = participationParameters.baselineFloor;\n    }\n    emit ParticipationBaselineUpdated(participationParameters.baseline.unwrap());\n  }\n\n  /**\n   * @notice Returns whether or not a particular proposal is passing according to the constitution\n   *   and the participation levels.\n   * @param proposal The proposal struct.\n   * @return Whether or not the proposal is passing.\n   */\n  function _isProposalPassing(Proposals.Proposal storage proposal) private view returns (bool) {\n    FixidityLib.Fraction memory support = proposal.getSupportWithQuorumPadding(\n      participationParameters.baseline.multiply(participationParameters.baselineQuorumFactor)\n    );\n\n    if (proposal.transactions.length == 0) {\n      // default treshold\n      FixidityLib.Fraction memory threshold = _getConstitution(address(0), \"\");\n      return support.gt(threshold);\n    }\n\n    for (uint256 i = 0; i < proposal.transactions.length; i = i.add(1)) {\n      bytes4 functionId = ExtractFunctionSignature.extractFunctionSignature(\n        proposal.transactions[i].data\n      );\n      FixidityLib.Fraction memory threshold = _getConstitution(\n        proposal.transactions[i].destination,\n        functionId\n      );\n      if (support.lte(threshold)) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  /**\n   * @notice Returns whether a proposal is dequeued at the given index.\n   * @param proposal The proposal struct.\n   * @param proposalId The ID of the proposal.\n   * @param index The index of the proposal ID in `dequeued`.\n   * @return Whether the proposal is in `dequeued` at index.\n   */\n  function _isDequeuedProposal(\n    Proposals.Proposal storage proposal,\n    uint256 proposalId,\n    uint256 index\n  ) private view returns (bool) {\n    require(index < dequeued.length, \"Provided index greater than dequeue length.\");\n    return proposal.exists() && dequeued[index] == proposalId;\n  }\n\n  /**\n   * @notice Returns whether or not a dequeued proposal has expired.\n   * @param proposal The proposal struct.\n   * @return Whether or not the dequeued proposal has expired.\n   */\n  function _isDequeuedProposalExpired(\n    Proposals.Proposal storage proposal,\n    Proposals.Stage stage\n  ) private view returns (bool) {\n    // The proposal is considered expired under the following conditions:\n    //   1. Past the referendum stage and not passing.\n    //   2. Past the execution stage.\n    return ((stage > Proposals.Stage.Execution) ||\n      (stage > Proposals.Stage.Referendum && !_isProposalPassing(proposal)));\n  }\n\n  /**\n   * @notice Returns whether or not a queued proposal has expired.\n   * @param proposal The proposal struct.\n   * @return Whether or not the dequeued proposal has expired.\n   */\n  function _isQueuedProposalExpired(\n    Proposals.Proposal storage proposal\n  ) private view returns (bool) {\n    // solhint-disable-next-line not-rely-on-time\n    return now >= proposal.timestamp.add(queueExpiry);\n  }\n\n  /**\n   * Returns amount of votes that should be removed from delegatee's proposal voting.\n   * @param totalToRemove Total votes to be removed.\n   * @param votes Yes/no/abstrain votes\n   * @param sumOfAllVotes Sum of yes, no, and abstain votes.\n   */\n  function getVotesPortion(\n    uint256 totalToRemove,\n    uint256 votes,\n    uint256 sumOfAllVotes\n  ) private pure returns (uint256) {\n    return\n      FixidityLib\n        .newFixed(totalToRemove)\n        .multiply(FixidityLib.newFixedFraction(votes, sumOfAllVotes))\n        .fromFixed();\n  }\n}\n","creation_status":"success","file_path":"contracts/governance/Governance.sol"}