Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Compensation Fund V1
- Optimization enabled
- true
- Compiler version
- v0.5.16+commit.9c3226ce
- Optimization runs
- 200
- EVM Version
- petersburg
- Verified at
- 2021-08-20 08:18:32.304087Z
Constructor Arguments
000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000001
Arg [0] (address) : 0x0000000000000000000000000000000000000317
Arg [1] (address) : 0x0000000000000000000000000000000000000302
Arg [2] (uint256) : 1
Contract source code
// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.pragma solidity 0.5.16;//pragma experimental SMTChecker;/** * Genesis version of GovernedContract interface. * * Base Consensus interface for upgradable contracts. * Unlike common approach, the implementation is NOT expected to be * called through delegatecall() to minimize risks of shared storage. * * NOTE: it MUST NOT change after blockchain launch! */interface IGovernedContract { // Return actual proxy address for secure validation function proxy() external returns(address); // It must check that the caller is the proxy // and copy all required data from the old address. function migrate(IGovernedContract _oldImpl) external; // It must check that the caller is the proxy // and self destruct to the new address. function destroy(IGovernedContract _newImpl) external; function () external payable;}// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;/** * Base for contract storage (SC-14). * * NOTE: it MUST NOT change after blockchain launch! */contract StorageBase { address payable internal owner; modifier requireOwner { require(msg.sender == address(owner), "Not owner!"); _; } constructor() public { owner = msg.sender; } function setOwner(IGovernedContract _newOwner) external requireOwner { owner = address(_newOwner); } function kill() external requireOwner { selfdestruct(msg.sender); }}// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;interface IProposal { function parent() external view returns(address); function created_block() external view returns(uint); function deadline() external view returns(uint); function fee_payer() external view returns(address payable); function fee_amount() external view returns(uint); function accepted_weight() external view returns(uint); function rejected_weight() external view returns(uint); function total_weight() external view returns(uint); function quorum_weight() external view returns(uint); function isFinished() external view returns(bool); function isAccepted() external view returns(bool); function withdraw() external; function destroy() external; function collect() external; function voteAccept() external; function voteReject() external; function setFee() external payable; function canVote(address owner) external view returns(bool);}// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;/** * Global constants with no storage space. * NOTE: it could be a library, but Solidity does not support such case. */contract GlobalConstants { address payable constant internal TREASURY = address(0x301); address payable constant internal MASTERNODE_REGISTRY = address(0x302); address payable constant internal STAKE_REWARD = address(0x303); address payable constant internal BACKBONE_REWARD = address(0x304); address payable constant internal SPORK_REGISTRY = address(0x305); address payable constant internal CHECKPOINT_REGISTRY = address(0x306); address payable constant internal BLACKLIST_REGISTRY = address(0x307); address constant internal MIGRATION_CONTRACT = address(0x308); address payable constant internal MASTERNODE_TOKEN = address(0x309); address constant internal SYSTEM_FAUCET = address(0x310); uint constant internal FEE_UPGRADE_V1 = 10000 ether; uint constant internal FEE_BUDGET_V1 = 100 ether; uint constant internal FEE_CHECKPOINT_V1 = 1000 ether; uint constant internal FEE_BLACKLIST_V1 = 1000 ether; uint constant internal FEE_BLACKLIST_REVOKE_V1 = 100 ether; uint constant internal FEE_BLACKLIST_DRAIN_V1 = 100 ether; uint constant internal PERIOD_UPGRADE_MIN = 2 weeks; uint constant internal PERIOD_UPGRADE_MAX = 365 days; uint constant internal PERIOD_BUDGET_MIN = 2 weeks; uint constant internal PERIOD_BUDGET_MAX = 30 days; uint constant internal PERIOD_CHECKPOINT = 1 weeks; uint constant internal PERIOD_BLACKLIST = 1 weeks; uint8 constant internal QUORUM_MIN = 1; uint8 constant internal QUORUM_MAJORITY = 51; uint8 constant internal QUORUM_MAX = 100; uint constant internal REWARD_STAKER_V1 = 2.28 ether; uint constant internal REWARD_BACKBONE_V1 = 2.28 ether; uint constant internal REWARD_MASTERNODE_V1 = 9.14 ether; uint constant internal REWARD_TREASURY_V1 = 184000 ether; uint constant internal MN_COLLATERAL_MIN = 10000 ether; uint constant internal MN_COLLATERAL_MAX = 100000 ether; uint constant internal MN_HEARTBEAT_INTERVAL = 60 minutes; uint constant internal MN_HEARTBEAT_INTERVAL_MIN = MN_HEARTBEAT_INTERVAL / 2; uint constant internal MN_HEARTBEAT_INTERVAL_MAX = MN_HEARTBEAT_INTERVAL * 2; uint constant internal MN_HEARTBEAT_PAST_BLOCKS = 10; uint constant internal BUDGET_AMOUNT_MIN = FEE_BUDGET_V1; uint constant internal BUDGET_AMOUNT_MAX = REWARD_TREASURY_V1; uint constant internal BUDGET_PROPOSAL_MAX = 100;}// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;/** * Genesis version of GovernedContract common base. * * Base Consensus interface for upgradable contracts. * Unlike common approach, the implementation is NOT expected to be * called through delegatecall() to minimize risks of shared storage. * * NOTE: it MUST NOT change after blockchain launch! */contract GovernedContract is IGovernedContract { address public proxy; constructor(address _proxy) public { proxy = _proxy; } modifier requireProxy { require(msg.sender == proxy, "Not proxy"); _; } function migrate(IGovernedContract _oldImpl) external requireProxy { _migrate(_oldImpl); } function destroy(IGovernedContract _newImpl) external requireProxy { _destroy(_newImpl); selfdestruct(address(_newImpl)); } // solium-disable-next-line no-empty-blocks function _migrate(IGovernedContract) internal {} // solium-disable-next-line no-empty-blocks function _destroy(IGovernedContract) internal {} function _callerAddress() internal view returns (address payable) { if (msg.sender == proxy) { // This is guarantee of the GovernedProxy // solium-disable-next-line security/no-tx-origin return tx.origin; } else { return msg.sender; } }}// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;/** * Genesis version of BlacklistRegistry interface. * * Base Consensus interface for contracts which receive block rewards. * * NOTE: it MUST NOT change after blockchain launch! */interface IBlockReward { // NOTE: it must NEVER fail function reward() external payable; // NOTE: it must NEVER fail function getReward(uint _blockNumber) external view returns(uint amount);}// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;/** * Interface of BudgetProposal */contract IBudgetProposal is IProposal { function payout_address() external view returns(address payable); function proposed_amount() external view returns(uint); function paid_amount() external view returns(uint); function ref_uuid() external view returns(uint); function distributePayout() external payable; function budgetStatus() external view returns( uint _ref_uuid, bool _is_accepted, bool _is_finished, uint _unpaid);}/** * Interface for the Treasury */interface ITreasury { event BudgetProposal( uint indexed ref_uuid, IBudgetProposal proposal, address payout_address, uint amount, uint deadline ); event Contribution( address from, uint amount ); event Payout( uint indexed ref_uuid, IBudgetProposal proposal, uint amount ); function uuid_proposal(uint _ref_uuid) external view returns(IBudgetProposal); function proposal_uuid(IBudgetProposal proposal) external view returns(uint); function propose(uint _amount, uint _ref_uuid, uint _period) external payable returns(IBudgetProposal proposal); function listProposals() external view returns(IBudgetProposal[] memory proposals); function isSuperblock(uint _blockNumber) external view returns(bool); function contribute() external payable; function balance() external view returns(uint amount);}// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;/** * Interface of UpgradeProposal */contract IUpgradeProposal is IProposal { function impl() external view returns(IGovernedContract);}/** * Genesis version of IGovernedProxy interface. * * Base Consensus interface for upgradable contracts proxy. * Unlike common approach, the implementation is NOT expected to be * called through delegatecall() to minimize risks of shared storage. * * NOTE: it MUST NOT change after blockchain launch! */interface IGovernedProxy { event UpgradeProposal( IGovernedContract indexed impl, IUpgradeProposal proposal ); event Upgraded( IGovernedContract indexed impl, IUpgradeProposal proposal ); function impl() external view returns(IGovernedContract); function proposeUpgrade(IGovernedContract _newImpl, uint _period) external payable returns(IUpgradeProposal); function upgrade(IUpgradeProposal _proposal) external; function upgradeProposalImpl(IUpgradeProposal _proposal) external view returns(IGovernedContract new_impl); function listUpgradeProposals() external view returns(IUpgradeProposal[] memory proposals); function collectUpgradeProposal(IUpgradeProposal _proposal) external; function () external payable;}// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;/** * Genesis version of MasternodeRegistry interface. * * Base Consensus interface for masternodes. * * NOTE: it MUST NOT change after blockchain launch! */interface IMasternodeRegistry { event Announced( address indexed masternode, address indexed owner, uint32 ipv4address, bytes32[2] enode, uint collateral ); event Denounced( address indexed masternode, address indexed owner ); event Invalidation( address indexed masternode, address indexed validator ); event Deactivated( address indexed masternode ); function token_proxy() external view returns(IGovernedProxy); function treasury_proxy() external view returns(IGovernedProxy); function announce(address masternode, uint32 ipv4address, bytes32[2] calldata enode) external; function denounce(address masternode) external; function heartbeat(uint block_number, bytes32 block_hash, uint sw_features) external; function invalidate(address masternode) external; function validationTarget(address masternode) external view returns(address target); function isActive(address masternode) external view returns(bool); function count() external view returns( uint active, uint total, uint active_collateral, uint total_collateral, uint max_of_all_times); function info(address masternode) external view returns(address owner, uint32 ipv4address, bytes32[2] memory enode, uint collateral, uint announced_block, uint sw_features); function ownerInfo(address owner) external view returns(address masternode, uint32 ipv4address, bytes32[2] memory enode, uint collateral, uint announced_block, uint sw_features); function onCollateralUpdate(address owner) external; function enumerate() external view returns(address[] memory masternodes); function enumerateActive() external view returns(address[] memory masternodes);}// solium-disable security/no-block-members/** * Genesis hardcoded version of GenericProposal V1 * * NOTE: it MUST NOT change after blockchain launch! */contract GenericProposalV1 is GlobalConstants, IProposal{ IGovernedProxy public mnregistry_proxy; address public parent; //! Block of proposal creation to check Masternode eligibility uint public created_block; //! Deadline for voting uint public deadline; //! The one who initiated the voting address payable public fee_payer; //! Fee amount uint public fee_amount; //! Weight of approval votes uint public accepted_weight; //! Weight of rejection votes uint public rejected_weight; //! Total masternode weight at the moment of proposal creation uint public total_weight; //! Weight of votes when the result is consider eligible uint public quorum_weight; //! Weight of votes when the voting can finalize before deadline uint public finish_weight; //! Registry of votes masternodes (vote once only) mapping(address => bool) public voted; /** * C-tor * * @param _mnregistry_proxy - IMasternodeRegistry proxy * @param _quorum - 1..100 * @param _period - in seconds until deadline * @param _feePayer - the proposal initiator */ constructor( IGovernedProxy _mnregistry_proxy, uint8 _quorum, uint _period, address payable _feePayer ) public { parent = msg.sender; created_block = block.number; mnregistry_proxy = _mnregistry_proxy; deadline = block.timestamp + _period; fee_payer = _feePayer; ( , , uint _total_weight, // active_collaterel , // total_collateral uint _ever_weight ) = IMasternodeRegistry(address(_mnregistry_proxy.impl())).count(); require(_ever_weight > 0, "Not ready for proposals"); require(_total_weight >= (_ever_weight/2), "Active weight < 1/2 ever weight"); require(_quorum >= QUORUM_MIN, "Quorum min"); require(_quorum <= QUORUM_MAX, "Quorum max"); total_weight = _total_weight; quorum_weight = _total_weight * _quorum / QUORUM_MAX; if (_quorum >= QUORUM_MAJORITY) { finish_weight = quorum_weight; } else { finish_weight = _total_weight * QUORUM_MAJORITY / QUORUM_MAX; } require(quorum_weight > 0, "Quorum weight"); require(finish_weight > 0, "Finish weight"); } /** * Check if the proposal is considered accepted. * NOTE: It can happen before the deadline. */ function isAccepted() public view returns(bool) { // Before the deadline condition if (accepted_weight >= finish_weight) { return true; } // Ensure finish condition is reaches otherwise if (!isFinished()) { return false; } // Check quorum if ((accepted_weight + rejected_weight) < quorum_weight) { return false; } // Simply majority return accepted_weight > rejected_weight; } /** * Check finish condition */ function isFinished() public view returns(bool) { return ( (deadline <= block.timestamp) || (accepted_weight >= finish_weight) || (rejected_weight > finish_weight) ); } function _voteCommon() internal returns(uint collateral) { // NOTE: do not use isFinished() to allow to accept votes before the deadline require(deadline > block.timestamp, "Finished"); IMasternodeRegistry registry = IMasternodeRegistry(address(mnregistry_proxy.impl())); address owner = msg.sender; uint announced_block; (,,, collateral, announced_block,) = registry.ownerInfo(owner); require(announced_block < created_block, "Not eligible"); require(!voted[owner], "Already voted"); voted[owner] = true; } /** * Check if particular MN owner can vote */ function canVote(address owner) external view returns(bool) { IMasternodeRegistry registry = IMasternodeRegistry(address(mnregistry_proxy.impl())); uint announced_block; (,,,, announced_block,) = registry.ownerInfo(owner); return ( (deadline > block.timestamp) && (announced_block < created_block) && !voted[owner] ); } /** * Masternode Owner approval vote */ function voteAccept() external { accepted_weight += _voteCommon(); } /** * Masternode Owner rejection vote */ function voteReject() external { rejected_weight += _voteCommon(); } /** * Withdrawal from accepted proposal. * NOTE: Usually for fee, but can be for budget as well. */ function withdraw() external { // NOTE: anyone should be able to do that for cases when payer is a contract require(isAccepted(), "Not accepted"); fee_payer.transfer(address(this).balance); } /** * Destruction via Governance logic. */ function destroy() external { // NOTE: unfinished voting must get canceled require(msg.sender == parent, "Only parent"); selfdestruct(fee_payer); } /** * Allow Treasury to collect the fee of rejected proposals. */ function collect() external { require(isFinished() && !isAccepted(), "Not collectable"); require(msg.sender == parent, "Only parent"); IMasternodeRegistry registry = IMasternodeRegistry(address(mnregistry_proxy.impl())); ITreasury treasury = ITreasury(address(registry.treasury_proxy().impl())); treasury.contribute.value(address(this).balance)(); } /** * Set fee amount by parent */ function setFee() external payable { require(msg.sender == parent, "Only parent"); // NOTE: make sure it correctly handles multiple calls fee_amount += msg.value; } /** * Only accept fee from the parent creating contract */ function () external payable { revert("Not allowed"); }}/** * Budget Proposal V1 for Treasury distribution */contract BudgetProposalV1 is GenericProposalV1, IBudgetProposal{ uint public paid_amount; uint public proposed_amount; uint public ref_uuid; constructor( IGovernedProxy _mnregistry_proxy, address payable _payout_address, uint _ref_uuid, uint _proposed_amount, uint _period ) public GenericProposalV1( _mnregistry_proxy, 7, _period, _payout_address ) { ref_uuid = _ref_uuid; proposed_amount = _proposed_amount; } // IBudgetProposal //--------------------------------- // Just an alias function payout_address() external view returns(address payable) { return fee_payer; } // Called by Treasury on reward() function distributePayout() external payable { paid_amount += msg.value; assert(paid_amount <= proposed_amount); } // Optimized status retrieval in single call function budgetStatus() external view returns( uint uuid, bool is_accepted, bool is_finished, uint unpaid ) { uuid = ref_uuid; is_accepted = isAccepted(); is_finished = isFinished(); assert(paid_amount <= proposed_amount); unpaid = proposed_amount - paid_amount; }}// Copyright 2019 The Energi Core Authors// This file is part of Energi Core.//// Energi Core is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Energi Core is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.// Energi Governance system is the fundamental part of Energi Core.// NOTE: It's not allowed to change the compiler due to byte-to-byte// match requirement.//pragma experimental SMTChecker;/** * A little helper to protect contract from being re-entrant in state * modifying functions. */contract NonReentrant { uint private entry_guard; modifier noReentry { require(entry_guard == 0, "Reentry"); entry_guard = 1; _; entry_guard = 0; }}/** * Permanent storage of Treasury V1 data. */contract StorageTreasuryV1 is StorageBase{ mapping(uint => IBudgetProposal) public uuid_proposal; mapping(address => uint) public proposal_uuid; function setProposal(uint _uuid, IBudgetProposal _proposal) external requireOwner { uuid_proposal[_uuid] = _proposal; proposal_uuid[address(_proposal)] = _uuid; } function deleteProposal(IBudgetProposal _proposal) external requireOwner { uint uuid = proposal_uuid[address(_proposal)]; delete proposal_uuid[address(_proposal)]; delete uuid_proposal[uuid]; }}/** * Genesis hardcoded version of Treasury * * NOTE: it MUST NOT change after blockchain launch! */contract TreasuryV1 is GlobalConstants, GovernedContract, NonReentrant, IBlockReward, ITreasury{ // Data for migration //--------------------------------- StorageTreasuryV1 public v1storage; IGovernedProxy public mnregistry_proxy; uint public superblock_cycle; IBudgetProposal[BUDGET_PROPOSAL_MAX] public active_proposals; //--------------------------------- constructor(address _proxy, IGovernedProxy _mnregistry_proxy, uint _superblock_cycle) public GovernedContract(_proxy) { v1storage = new StorageTreasuryV1(); mnregistry_proxy = _mnregistry_proxy; superblock_cycle = _superblock_cycle; assert(superblock_cycle > 0); } // IGovernedContract //--------------------------------- function _destroy(IGovernedContract _newImpl) internal { v1storage.setOwner(_newImpl); } // ITreasury //--------------------------------- function uuid_proposal(uint _ref_uuid) external view returns(IBudgetProposal) { return v1storage.uuid_proposal(_ref_uuid); } function proposal_uuid(IBudgetProposal proposal) external view returns(uint) { return v1storage.proposal_uuid(address(proposal)); } function propose(uint _amount, uint _ref_uuid, uint _period) external payable noReentry returns(IBudgetProposal proposal) { require(msg.value == FEE_BUDGET_V1, "Invalid fee"); require(_amount >= BUDGET_AMOUNT_MIN, "Too small amount"); require(_amount <= BUDGET_AMOUNT_MAX, "Too large amount"); require(_period >= PERIOD_BUDGET_MIN, "Too small period"); require(_period <= PERIOD_BUDGET_MAX, "Too large period"); StorageTreasuryV1 store = v1storage; address payable payout_address = _callerAddress(); require(address(store.uuid_proposal(_ref_uuid)) == address(0), "UUID in use"); // Find, if proposal slot is available. for (uint i = 0; i < BUDGET_PROPOSAL_MAX; ++i) { if (address(active_proposals[i]) == address(0)) { proposal = new BudgetProposalV1( mnregistry_proxy, payout_address, _ref_uuid, _amount, _period ); active_proposals[i] = proposal; break; } } require(address(proposal) != address(0), "Too many active proposals"); //--- proposal.setFee.value(msg.value)(); store.setProposal(_ref_uuid, proposal); // NOTE: it's the only way to retrieve proposal on regular transaction emit BudgetProposal( _ref_uuid, proposal, payout_address, _amount, proposal.deadline() ); return proposal; } function listProposals() external view returns(IBudgetProposal[] memory proposals) { IBudgetProposal[] memory tmp = new IBudgetProposal[](BUDGET_PROPOSAL_MAX); uint tmp_len = 0; for (uint i = 0; i < BUDGET_PROPOSAL_MAX; ++i) { IBudgetProposal p = active_proposals[i]; if (address(p) != address(0)) { tmp[tmp_len++] = p; } } proposals = new IBudgetProposal[](tmp_len); for (uint i = 0; i < tmp_len; ++i) { proposals[i] = tmp[i]; } return proposals; } function isSuperblock(uint _blockNumber) public view returns(bool) { return (_blockNumber % superblock_cycle) == 0 && (_blockNumber > 0); } function contribute() external payable { if (msg.value > 0) { emit Contribution(_callerAddress(), msg.value); } } // NOTE: usually Treasury is behind proxy and this one // minimizes possible errors. function balance() external view returns(uint amount) { return address(this).balance; } // IBlockReward //--------------------------------- struct AcceptedProposal { IBudgetProposal proposal; uint ref_uuid; uint unpaid; } function reward() external payable noReentry { AcceptedProposal[BUDGET_PROPOSAL_MAX] memory accepted; uint unpaid_total = _reward_status(accepted); uint curr_balance = address(this).balance; if ((curr_balance > 0) && (unpaid_total > 0)) { uint permille = 1000; if (unpaid_total > curr_balance) { // Due to lack of floating-point precision, // it may require a few blocks to process // full payouts. permille = curr_balance * 1000 / unpaid_total; } _reward_distribute(permille, accepted); } } function _reward_status(AcceptedProposal[BUDGET_PROPOSAL_MAX] memory accepted) internal returns(uint unpaid_total) { IBudgetProposal proposal; uint ref_uuid; bool is_accepted; bool is_finished; uint unpaid = 0; for (uint i = 0; i < BUDGET_PROPOSAL_MAX; ++i) { proposal = active_proposals[i]; if (address(proposal) != address(0)) { (ref_uuid, is_accepted, is_finished, unpaid) = proposal.budgetStatus(); if (is_accepted) { if (unpaid > 0) { unpaid_total += unpaid; accepted[i].proposal = proposal; accepted[i].ref_uuid = ref_uuid; accepted[i].unpaid = unpaid; } else { // Fulfilled proposal.destroy(); delete active_proposals[i]; } } else if (is_finished) { // Rejected proposal.collect(); delete active_proposals[i]; } } } } function _reward_distribute( uint permille, AcceptedProposal[BUDGET_PROPOSAL_MAX] memory accepted ) internal { IBudgetProposal proposal; for (uint i = 0; i < BUDGET_PROPOSAL_MAX; ++i) { proposal = accepted[i].proposal; if (address(proposal) != address(0)) { uint amount = accepted[i].unpaid * permille / 1000; assert(amount <= accepted[i].unpaid); proposal.distributePayout.value(amount)(); emit Payout( accepted[i].ref_uuid, proposal, amount ); } } } function getReward(uint _blockNumber) external view returns(uint amount) { if (isSuperblock(_blockNumber)) { amount = REWARD_TREASURY_V1; } } // Safety //--------------------------------- function () external payable { revert("Not supported"); }}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","payable":false,"inputs":[{"type":"address","name":"_proxy","internalType":"address"},{"type":"address","name":"_mnregistry_proxy","internalType":"contractIGovernedProxy"},{"type":"uint256","name":"_superblock_cycle","internalType":"uint256"}]},{"type":"event","name":"BudgetProposal","inputs":[{"type":"uint256","name":"ref_uuid","internalType":"uint256","indexed":true},{"type":"address","name":"proposal","internalType":"contractIBudgetProposal","indexed":false},{"type":"address","name":"payout_address","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"deadline","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Contribution","inputs":[{"type":"address","name":"from","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Payout","inputs":[{"type":"uint256","name":"ref_uuid","internalType":"uint256","indexed":true},{"type":"address","name":"proposal","internalType":"contractIBudgetProposal","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contractIBudgetProposal"}],"name":"active_proposals","inputs":[{"type":"uint256","name":"","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"amount","internalType":"uint256"}],"name":"balance","inputs":[],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[],"name":"contribute","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"destroy","inputs":[{"type":"address","name":"_newImpl","internalType":"contractIGovernedContract"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"amount","internalType":"uint256"}],"name":"getReward","inputs":[{"type":"uint256","name":"_blockNumber","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isSuperblock","inputs":[{"type":"uint256","name":"_blockNumber","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"proposals","internalType":"contractIBudgetProposal[]"}],"name":"listProposals","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"migrate","inputs":[{"type":"address","name":"_oldImpl","internalType":"contractIGovernedContract"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contractIGovernedProxy"}],"name":"mnregistry_proxy","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"proposal_uuid","inputs":[{"type":"address","name":"proposal","internalType":"contractIBudgetProposal"}],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[{"type":"address","name":"proposal","internalType":"contractIBudgetProposal"}],"name":"propose","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"uint256","name":"_ref_uuid","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"proxy","inputs":[],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[],"name":"reward","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"superblock_cycle","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contractIBudgetProposal"}],"name":"uuid_proposal","inputs":[{"type":"uint256","name":"_ref_uuid","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contractStorageTreasuryV1"}],"name":"v1storage","inputs":[],"constant":true}]
Deployed ByteCode
0x3630383036303430353233343830313536313030313035373630303038306664356235303630343035313631323866333338303338303631323866333833333938313831303136303430353236303630383131303135363130303333353736303030383066643562353038303531363032303832303135313630343039323833303135313630303038303534363030313630303136306130316230333139313636303031363030313630613031623033383531363137393035353932353139313932393039313631303036623930363130306362353635623630343035313830393130333930363030306630383031353830313536313030383735373364363030303830336533643630303066643562353036303032383035343630303136303031363061303162303331393930383131363630303136303031363061303162303339333834313631373930393135353630303338303534393039313136393138343136393139303931313739303535363030343831393035353830363130306333353766653562353035303530363130306438353635623631303361373830363132353463383333393031393035363562363132343635383036313030653736303030333936303030663366653630383036303430353236303034333631303632303030313039353736303030333536306530316338303633356330393932313531313632303030303937353738303633643566393937383931313632303030303631353738303633643566393937383931343632303030336131353738303633643762623939626131343632303030336366353738303633656335353638383931343632303030336439353738303633666537333334653831343632303030336631353736323030303130393536356238303633356330393932313531343632303030326564353738303633623639656638613831343632303030333162353738303633636165663164356131343632303030333333353738303633636535343934626231343632303030333661353736323030303130393536356238303633323663376562316331313632303030306439353738303633323663376562316331343632303030316531353738303633326430353933303531343632303030323462353738303633343033373664353631343632303030323766353738303633353237383264383631343632303030326162353736323030303130393536356238303632663535643964313436323030303134363537383036333065663334373435313436323030303137663537383036333163346237373462313436323030303161393537383036333232386362373333313436323030303164373537356236303430383035313632343631626364363065353162383135323630323036303034383230313532363030643630323438323031353236633133396264643038316364643563316331626463396431393539363039613162363034343832303135323930353139303831393030333630363430313930666435623334383031353632303030313533353736303030383066643562353036323030303137643630303438303336303336303230383131303135363230303031366335373630303038306664356235303335363030313630303136306130316230333136363230303034303935363562303035623334383031353632303030313863353736303030383066643562353036323030303139373632303030343663353635623630343038303531393138323532353139303831393030333630323030313930663335623334383031353632303030316236353736303030383066643562353036323030303139373630303438303336303336303230383131303135363230303031636635373630303038306664356235303335363230303034373235363562363230303031376436323030303439373536356233343830313536323030303165653537363030303830666435623530363230303031663936323030303534323536356236303430383035313630323038303832353238333531383138333031353238333531393139323833393239303833303139313835383130313931303238303833383336303030356238333831313031353632303030323337353738313831303135313833383230313532363032303031363230303032316435363562353035303530353039303530303139323530353035303630343035313830393130333930663335623334383031353632303030323538353736303030383066643562353036323030303236333632303030363630353635623630343038303531363030313630303136306130316230333930393231363832353235313930383139303033363032303031393066333562363230303032363336303034383033363033363036303831313031353632303030323937353736303030383066643562353038303335393036303230383130313335393036303430303133353632303030363666353635623334383031353632303030326238353736303030383066643562353036323030303264393630303438303336303336303230383131303135363230303032643135373630303038306664356235303335363230303062656335363562363034303830353139313135313538323532353139303831393030333630323030313930663335623334383031353632303030326661353736303030383066643562353036323030303236333630303438303336303336303230383131303135363230303033313335373630303038306664356235303335363230303063306635363562333438303135363230303033323835373630303038306664356235303632303030313937363230303063393035363562333438303135363230303033343035373630303038306664356235303632303030313937363030343830333630333630323038313130313536323030303335393537363030303830666435623530333536303031363030313630613031623033313636323030306339353536356233343830313536323030303337373537363030303830666435623530363230303031376436303034383033363033363032303831313031353632303030333930353736303030383066643562353033353630303136303031363061303162303331363632303030636537353635623334383031353632303030336165353736303030383066643562353036323030303236333630303438303336303336303230383131303135363230303033633735373630303038306664356235303335363230303064336335363562363230303031376436323030306435613536356233343830313536323030303365363537363030303830666435623530363230303032363336323030306461663536356233343830313536323030303366653537363030303830666435623530363230303032363336323030306462653536356236303030353436303031363030313630613031623033313633333134363230303034353535373630343038303531363234363162636436306535316238313532363032303630303438323031353236303039363032343832303135323638346536663734323037303732366637383739363062383162363034343832303135323930353139303831393030333630363430313930666435623632303030343630383136323030306463643536356238303630303136303031363061303162303331366666356236303034353438313536356236303030363230303034376638323632303030626563353635623135363230303034393235373530363932366636613866346536333830333030303030303562393139303530353635623630303135343135363230303034643735373630343038303531363234363162636436306535316238313532363032303630303438323031353236303037363032343832303135323636353236353635366537343732373936306338316236303434383230313532393035313930383139303033363036343031393066643562363030313830353536323030303465353632303031316366353635623630303036323030303466323832363230303065333835363562393035303330333138303135383031353930363230303035303635373530363030303832313135623135363230303035333835373631303365383831383331313135363230303035326135373832383236313033653830323831363230303035323635376665356230343930353035623632303030353336383138353632303031303631353635623530356235303530363030303630303135353530353635623630343038303531363036343830383235323631306361303832303139303932353236303630393138323931393036303230383230313631306338303830333838333339303139303530353039303530363030303830356236303634383131303135363230303035646235373630303036303035383236303634383131303632303030353838353766653562303135343630303136303031363061303162303331363930353038303135363230303035643135373830383438343830363030313031393535303831353138313130363230303035623035376665356236303230303236303230303130313930363030313630303136306130316230333136393038313630303136303031363061303162303331363831353235303530356235303630303130313632303030353665353635623530383036303430353139303830383235323830363032303032363032303031383230313630343035323830313536323030303630373537383136303230303136303230383230323830333838333339303139303530356235303932353036303030356238313831313031353632303030363539353738323831383135313831313036323030303632333537666535623630323030323630323030313031353138343832383135313831313036323030303633383537666535623630303136303031363061303162303339303932313636303230393238333032393139303931303139303931303135323630303130313632303030363064353635623530353035303562393035363562363030323534363030313630303136306130316230333136383135363562363030303630303135343630303031343632303030366233353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030373630323438323031353236363532363536353665373437323739363063383162363034343832303135323930353139303831393030333630363430313930666435623630303138303535333436383035366263373565326436333130303030303134363230303037303335373630343038303531363234363162636436306535316238313532363032303630303438323031353236303062363032343832303135323661343936653736363136633639363432303636363536353630613831623630343438323031353239303531393038313930303336303634303139306664356236383035366263373565326436333130303030303834313031353632303030373535353736303430383035313632343631626364363065353162383135323630323036303034383230313532363031303630323438323031353236663135316264626338316364623538356231623038313835623562646435623964363038323162363034343832303135323930353139303831393030333630363430313930666435623639323666366138663465363338303330303030303038343131313536323030303761383537363034303830353136323436316263643630653531623831353236303230363030343832303135323630313036303234383230313532366631353162646263383162313835633939643934383138356235626464356239643630383231623630343438323031353239303531393038313930303336303634303139306664356236323132373530303832313031353632303030376634353736303430383035313632343631626364363065353162383135323630323036303034383230313532363031303630323438323031353236663135316264626338316364623538356231623038316331393563396135626439363038323162363034343832303135323930353139303831393030333630363430313930666435623632323738643030383231313135363230303038343035373630343038303531363234363162636436306535316238313532363032303630303438323031353236303130363032343832303135323666313531626462633831623138356339396439343831633139356339613562643936303832316236303434383230313532393035313930383139303033363036343031393066643562363030323534363030313630303136306130316230333136363030303632303030383538363230303131616135363562393035303630303036303031363030313630613031623033313638323630303136303031363061303162303331363633356330393932313538373630343035313832363366666666666666663136363065303162383135323630303430313830383238313532363032303031393135303530363032303630343035313830383330333831383638303362313538303135363230303038616135373630303038306664356235303561666131353830313536323030303862663537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353632303030386436353736303030383066643562353035313630303136303031363061303162303331363134363230303039323235373630343038303531363234363162636436306535316238313532363032303630303438323031353236303062363032343832303135323661353535353439343432303639366532303735373336353630613831623630343438323031353239303531393038313930303336303634303139306664356236303030356236303634383131303135363230303061303535373630303036303035383236303634383131303632303030393366353766653562303135343630303136303031363061303162303331363134313536323030303966633537363030333630303039303534393036313031303030613930303436303031363030313630613031623033313638323837383938383630343035313632303030393739393036323030313230303536356236303031363030313630613031623033393538363136383135323933393039343136363032303834303135323630343038303834303139323930393235323630363038333031353236303830383230313932393039323532393035313930383139303033363061303031393036303030663038303135383031353632303030396335353733643630303038303365336436303030666435623530393335303833363030353832363036343831313036323030303964373537666535623031383035343630303136303031363061303162303331393136363030313630303136306130316230333932393039323136393139303931313739303535363230303061303535363562363030313031363230303039323535363562353036303031363030313630613031623033383331363632303030613632353736303430383035313632343631626364363065353162383135323630323036303034383230313532363031393630323438323031353237663534366636663230366436313665373932303631363337343639373636353230373037323666373036663733363136633733303030303030303030303030303036303434383230313532393035313930383139303033363036343031393066643562383236303031363030313630613031623033313636333264656433323237333436303430353138323633666666666666666631363630653031623831353236303034303136303030363034303531383038333033383138353838383033623135383031353632303030613965353736303030383066643562353035616631313538303135363230303061623335373364363030303830336533643630303066643562353035303630343038303531363232653765353536306532316238313532363030343831303138613930353236303031363030313630613031623033383838313136363032343833303135323931353139313837313639343530363262396639353439333530363034343830383230313933353036303030393239313832393030333031383138333837383033623135383031353632303030623037353736303030383066643562353035616631313538303135363230303062316335373364363030303830336533643630303066643562353035303530353038343766613934626566613363653138313937343133306665333665383534613238326337306662373565346465636234326266656364656362643666383866306635643834383338393837363030313630303136306130316230333136363332396463623063663630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353632303030623766353736303030383066643562353035616661313538303135363230303062393435373364363030303830336533643630303066643562353035303530353036303430353133643630323038313130313536323030306261623537363030303830666435623530353136303430383035313630303136303031363061303162303339353836313638313532393339303934313636303230383430313532383238343031393139303931353236303630383230313532393035313930383139303033363038303031393061323530353036303030363030313535393339323530353035303536356236303030363030343534383238313632303030626661353766653562303631353830313536323030306330393537353036303030383231313562393239313530353035363562363030323534363034303830353136333563303939323135363065303162383135323630303438313031383439303532393035313630303039323630303136303031363061303162303331363931363335633039393231353931363032343830383330313932363032303932393139303832393030333031383138363830336231353830313536323030306335633537363030303830666435623530356166613135383031353632303030633731353733643630303038303365336436303030666435623530353035303530363034303531336436303230383131303135363230303063383835373630303038306664356235303531393239313530353035363562333033313930353635623630303235343630343038303531363336353737386561643630653131623831353236303031363030313630613031623033383438313136363030343833303135323931353136303030393339323930393231363931363363616566316435613931363032343830383230313932363032303932393039313930383239303033303138313836383033623135383031353632303030633563353736303030383066643562363030303534363030313630303136306130316230333136333331343632303030643333353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030393630323438323031353236383465366637343230373037323666373837393630623831623630343438323031353239303531393038313930303336303634303139306664356236323030306433393831356235303536356236303035383136303634383131303632303030643461353766653562303135343630303136303031363061303162303331363930353038313536356233343135363230303064616435373766346431353464346161653231366265643664303932366462373763303064663262353763366235626134656565303537373564653230666163656465336137623632303030643863363230303131616135363562363034303830353136303031363030313630613031623033393039323136383235323334363032303833303135323830353139313832393030333031393061313562353635623630303035343630303136303031363061303162303331363831353635623630303335343630303136303031363061303162303331363831353635623630303235343630343038303531363331336166343033353630653031623831353236303031363030313630613031623033383438313136363030343833303135323931353139313930393231363931363331336166343033353931363032343830383330313932363030303932393139303832393030333031383138333837383033623135383031353632303030653163353736303030383066643562353035616631313538303135363230303065333135373364363030303830336533643630303066643562353035303530353035303536356236303030383038303830383038303830356236303634383131303135363230303130353635373630303538313630363438313130363230303065353935376665356230313534363030313630303136306130316230333136393535303835313536323030313034643537383536303031363030313630613031623033313636333362326131623134363034303531383136336666666666666666313636306530316238313532363030343031363038303630343035313830383330333831383638303362313538303135363230303065613735373630303038306664356235303561666131353830313536323030306562633537336436303030383033653364363030306664356235303530353035303630343035313364363038303831313031353632303030656433353736303030383066643562353038303531363032303832303135313630343038333031353136303630393039333031353139313937353039353530393039333530393135303833313536323030306664333537383131353632303030663561353739353831303139353835383838323630363438313130363230303066313035376665356236303230303230313531363030313630303136306130316230333930393131363930353238343838383236303634383131303632303030663330353766653562363032303032303135313630323030313831383135323530353038313838383236303634383131303632303030663462353766653562363032303032303135313630343030313532363230303066636435363562383536303031363030313630613031623033313636333833313937656630363034303531383136336666666666666666313636306530316238313532363030343031363030303630343035313830383330333831363030303837383033623135383031353632303030663936353736303030383066643562353035616631313538303135363230303066616235373364363030303830336533643630303066643562353035303530353036303035383136303634383131303632303030666264353766653562303138303534363030313630303136306130316230333139313639303535356236323030313034643536356238323135363230303130346435373835363030313630303136306130316230333136363365353232353338313630343035313831363366666666666666663136363065303162383135323630303430313630303036303430353138303833303338313630303038373830336231353830313536323030313031363537363030303830666435623530356166313135383031353632303031303262353733643630303038303365336436303030666435623530353035303530363030353831363036343831313036323030313033643537666535623031383035343630303136303031363061303162303331393136393035353562363030313031363230303065343135363562353035303530353035303530393139303530353635623630303038303562363036343831313031353632303031316134353738323831363036343831313036323030313037633537666535623630323030323031353135313931353036303031363030313630613031623033383231363135363230303131396235373630303036313033653838353835383436303634383131303632303031306137353766653562363032303032303135313630343030313531303238313632303031306239353766653562303439303530383338323630363438313130363230303130633935376665356236303230303230313531363034303031353138313131313536323030313064633537666535623832363030313630303136306130316230333136363331306361633861353832363034303531383236336666666666666666313636306530316238313532363030343031363030303630343035313830383330333831383538383830336231353830313536323030313131383537363030303830666435623530356166313135383031353632303031313264353733643630303038303365336436303030666435623530353035303530353038333832363036343831313036323030313133663537666535623630323030323031353136303230303135313766356637333431613535326165326434353262303731393137313034633035666261633336363339333661363962653736386130356334303630353035366537643834383336303430353138303833363030313630303136306130316230333136363030313630303136306130316230333136383135323630323030313832383135323630323030313932353035303530363034303531383039313033393061323530356236303031303136323030313036353536356235303530353035303536356236303030383035343630303136303031363061303162303331363333313431353632303031316337353735303332363230303036356435363562353033333632303030363564353635623630343035313830363130633830303136303430353238303630363439303562363230303131653936323030313230653536356238313532363032303031393036303031393030333930383136323030313164663537393035303530393035363562363131316638383036323030313233393833333930313930353635623630343035313830363036303031363034303532383036303030363030313630303136306130316230333136383135323630323030313630303038313532363032303031363030303831353235303930353666653630383036303430353233343830313536313030313035373630303038306664356235303630343035313631313166383338303338303631313166383833333938313831303136303430353236306130383131303135363130303333353736303030383066643562353038303531363032303830383330313531363034303830383530313531363036303836303135313630383039303936303135313630303138303534333336303031363030313630613031623033313939313832313631373930393135353433363030323535363030303830353438323136363030313630303136306130316230333830386131363931383231373833353534323835303136303033353536303034383035343930393431363930383831363137383335353835353137663861626636303737303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303038313532393535313938393939363938393439373933393538613935363030373935383839353863393539343835393439303933363338616266363037373933383238343031393339303932383239303033303138313836383033623135383031353631303065633537363030303830666435623530356166613135383031353631303130303537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631303131363537363030303830666435623530353136303430383035313766303636363161626430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303831353239303531363030313630303136306130316230333930393231363931363330363636316162643931363030343830383230313932363061303932393039313930383239303033303138313836383033623135383031353631303137333537363030303830666435623530356166613135383031353631303138373537336436303030383033653364363030306664356235303530353035303630343035313364363061303831313031353631303139643537363030303830666435623530363034303831303135313630383039303931303135313930393235303930353038303631303231613537363034303830353137663038633337396130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303038313532363032303630303438323031353236303137363032343832303135323766346536663734323037323635363136343739323036363666373232303730373236663730366637333631366337333030303030303030303030303030303030303630343438323031353239303531393038313930303336303634303139306664356236303032383130343832313031353631303238633537363034303830353137663038633337396130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303038313532363032303630303438323031353236303166363032343832303135323766343136333734363937363635323037373635363936373638373432303363323033313266333232303635373636353732323037373635363936373638373430303630343438323031353239303531393038313930303336303634303139306664356236303031363066663836313631303135363130326666353736303430383035313766303863333739613030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303831353236303230363030343832303135323630306136303234383230313532376635313735366637323735366432303664363936653030303030303030303030303030303030303030303030303030303030303030303030303030303030303030363034343832303135323930353139303831393030333630363430313930666435623630363436306666383631363131313536313033373235373630343038303531376630386333373961303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030383135323630323036303034383230313532363030613630323438323031353237663531373536663732373536643230366436313738303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036303434383230313532393035313930383139303033363036343031393066643562363030383832393035353630363436306666383631363833303230343630303935353630333336306666383631363130363130333939353736303039353436303061353536313033613435363562363036343630333338333032303436303061353535623630303036303039353431313631303431353537363034303830353137663038633337396130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303038313532363032303630303438323031353236303064363032343832303135323766353137353666373237353664323037373635363936373638373430303030303030303030303030303030303030303030303030303030303030303030303030303630343438323031353239303531393038313930303336303634303139306664356236303030363030613534313136313034383635373630343038303531376630386333373961303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030383135323630323036303034383230313532363030643630323438323031353237663436363936653639373336383230373736353639363736383734303030303030303030303030303030303030303030303030303030303030303030303030303036303434383230313532393035313930383139303033363036343031393066643562353035303530363030653935393039353535353035303530363030643535353035303530363130643531383036313034613736303030333936303030663366653630383036303430353236303034333631303631303139633537363030303335363065303163383036333736333962316562313136313030656335373830363361656332636361653131363130303861353738303633633430613730663831313631303036343537383036336334306137306638313436313034343635373830363363383665366331353134363130343562353738303633653532323533383131343631303437303537383036336665373333346538313436313034383535373631303139633536356238303633616563326363616531343631303365393537383036336264346331663339313436313034316335373830363363323437326566383134363130343331353736313031396335363562383036333931383430613662313136313030633635373830363339313834306136623134363130333737353738303633393930613636336231343631303338633537383036333964356536633964313436313033613135373830363361646661613732653134363130336236353736313031396335363562383036333736333962316562313436313033333835373830363337623335323936323134363130333464353738303633383331393765663031343631303336323537363130313963353635623830363333643164623365393131363130313539353738303633353035316135656331313631303133333537383036333530353161356563313436313032623435373830363335366332613061313134363130326464353738303633363066393661386631343631303266323537383036333735646630663939313436313033323335373631303139633536356238303633336431646233653931343631303237353537383036333463616664666232313436313032386135373830363335303438383164663134363130323966353736313031396335363562383036333062363262653435313436313031643735373830363331306361633861353134363130316665353738303633323964636230636631343631303230383537383036333264656433323237313436313032316435373830363333623261316231343134363130323235353738303633336363666436306231343631303236303537356236303430383035313632343631626364363065353162383135323630323036303034383230313532363030623630323438323031353236613133396264643038313835623162316264646439353936306161316236303434383230313532393035313930383139303033363036343031393066643562333438303135363130316533353736303030383066643562353036313031656336313034396135363562363034303830353139313832353235313930383139303033363032303031393066333562363130323036363130346130353635623030356233343830313536313032313435373630303038306664356235303631303165633631303462373536356236313032303636313034626435363562333438303135363130323331353736303030383066643562353036313032336136313035313435363562363034303830353139343835353239323135313536303230383530313532393031353135383338333031353236303630383330313532353139303831393030333630383030313930663335623334383031353631303236633537363030303830666435623530363130323036363130353463353635623334383031353631303238313537363030303830666435623530363130316563363130356431353635623334383031353631303239363537363030303830666435623530363130316563363130356437353635623334383031353631303261623537363030303830666435623530363130316563363130356464353635623334383031353631303263303537363030303830666435623530363130326339363130356533353635623630343038303531393131353135383235323531393038313930303336303230303139306633356233343830313536313032653935373630303038306664356235303631303230363631303633303536356233343830313536313032666535373630303038306664356235303631303330373631303634333536356236303430383035313630303136303031363061303162303339303932313638323532353139303831393030333630323030313930663335623334383031353631303332663537363030303830666435623530363130316563363130363532353635623334383031353631303334343537363030303830666435623530363130316563363130363538353635623334383031353631303335393537363030303830666435623530363130326339363130363565353635623334383031353631303336653537363030303830666435623530363130323036363130363838353635623334383031353631303338333537363030303830666435623530363130316563363130366533353635623334383031353631303339383537363030303830666435623530363130316563363130366539353635623334383031353631303361643537363030303830666435623530363130333037363130366566353635623334383031353631303363323537363030303830666435623530363130326339363030343830333630333630323038313130313536313033643935373630303038306664356235303335363030313630303136306130316230333136363130366665353635623334383031353631303366353537363030303830666435623530363130326339363030343830333630333630323038313130313536313034306335373630303038306664356235303335363030313630303136306130316230333136363130383366353635623334383031353631303432383537363030303830666435623530363130316563363130383534353635623334383031353631303433643537363030303830666435623530363130323036363130383561353635623334383031353631303435323537363030303830666435623530363130333037363130383664353635623334383031353631303436373537363030303830666435623530363130316563363130383763353635623334383031353631303437633537363030303830666435623530363130323036363130383832353635623334383031353631303439313537363030303830666435623530363130333037363130616561353635623630303235343831353635623630306338303534333430313930383139303535363030643534313031353631303462353537666535623536356236303033353438313536356236303031353436303031363030313630613031623033313633333134363130353061353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030623630323438323031353236613133646239623165343831633138356339393562396436306161316236303434383230313532393035313930383139303033363036343031393066643562363030353830353433343031393035353536356236303065353436303030383038303631303532333631303565333536356239323530363130353264363130363565353635623931353036303064353436303063353431313135363130353364353766653562363030633534363030643534303339303530393039313932393335363562363130353534363130356533353635623631303539343537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306336303234383230313532366231333962646430383138353864386439356331643139353936306132316236303434383230313532393035313930383139303033363036343031393066643562363030343534363034303531363030313630303136306130316230333930393131363930333033313830313536313038666330323931363030303831383138313835383838386631393335303530353035303135383031353631303563653537336436303030383033653364363030306664356235303536356236303061353438313536356236303064353438313536356236303063353438313536356236303030363030613534363030363534313036313035663835373530363030313631303632643536356236313036303036313036356535363562363130363063353735303630303036313036326435363562363030393534363030373534363030363534303131303135363130363234353735303630303036313036326435363562353036303037353436303036353431313562393035363562363130363338363130616639353635623630303738303534393039313031393035353536356236303031353436303031363030313630613031623033313638313536356236303039353438313536356236303036353438313536356236303030343236303033353431313135383036313036373535373530363030613534363030363534313031353562383036313036383335373530363030613534363030373534313135623930353039303536356236303031353436303031363030313630613031623033313633333134363130366435353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030623630323438323031353236613133646239623165343831633138356339393562396436306161316236303434383230313532393035313930383139303033363036343031393066643562363030343534363030313630303136306130316230333136666635623630303835343831353635623630303535343831353635623630303435343630303136303031363061303162303331363930353635623630303038303534363034303830353136333861626636303737363065303162383135323930353138333932363030313630303136306130316230333136393136333861626636303737393136303034383038333031393236303230393239313930383239303033303138313836383033623135383031353631303734333537363030303830666435623530356166613135383031353631303735373537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631303736643537363030303830666435623530353136303430383035313633623833653136303536306530316238313532363030313630303136306130316230333836383131363630303438333031353239313531393239333530363030303932393138343136393136336238336531363035393136303234383038323031393236306530393239303931393038323930303330313831383638303362313538303135363130376266353736303030383066643562353035616661313538303135363130376433353733643630303038303365336436303030666435623530353035303530363034303531336436303166313936303166383230313136383230313830363034303532353036306530383131303135363130376638353736303030383066643562353036306130303135313630303335343930393135303432313038303135363130383132353735303630303235343831313035623830313536313038333735373530363030313630303136306130316230333834313636303030393038313532363030623630323035323630343039303230353436306666313631353562393439333530353035303530353635623630306236303230353236303030393038313532363034303930323035343630666631363831353635623630306535343831353635623631303836323631306166393536356236303036383035343930393130313930353535363562363030343534363030313630303136306130316230333136383135363562363030373534383135363562363130383861363130363565353635623830313536313038396235373530363130383939363130356533353635623135356236313038646535373630343038303531363234363162636436306535316238313532363032303630303438323031353236303066363032343832303135323665346536663734323036333666366336633635363337343631363236633635363038383162363034343832303135323930353139303831393030333630363430313930666435623630303135343630303136303031363061303162303331363333313436313039326235373630343038303531363234363162636436306535316238313532363032303630303438323031353236303062363032343832303135323661313364623962316534383163313835633939356239643630616131623630343438323031353239303531393038313930303336303634303139306664356236303030383036303030393035343930363130313030306139303034363030313630303136306130316230333136363030313630303136306130316230333136363338616266363037373630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631303937613537363030303830666435623530356166613135383031353631303938653537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631303961343537363030303830666435623530353136303430383035313633323839636335653136306532316238313532393035313931393235303630303039313630303136303031363061303162303338343136393136336132373331373834393136303034383038333031393236303230393239313930383239303033303138313836383033623135383031353631303965633537363030303830666435623530356166613135383031353631306130303537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631306131363537363030303830666435623530353136303430383035313633386162663630373736306530316238313532393035313630303136303031363061303162303339303932313639313633386162663630373739313630303438303832303139323630323039323930393139303832393030333031383138363830336231353830313536313061356135373630303038306664356235303561666131353830313536313061366535373364363030303830336533643630303066643562353035303530353036303430353133643630323038313130313536313061383435373630303038306664356235303531363034303830353136333662646463636464363065313162383135323930353139313932353036303031363030313630613031623033383331363931363364376262393962613931333033313931363030343830383330313932363030303932393139303832393030333031383138353838383033623135383031353631306163643537363030303830666435623530356166313135383031353631306165313537336436303030383033653364363030306664356235303530353035303530353035303536356236303030353436303031363030313630613031623033313638313536356236303030343236303033353431313631306233633537363034303830353136323436316263643630653531623831353236303230363030343832303135323630303836303234383230313532363731313961356239613563646131393539363063323162363034343832303135323930353139303831393030333630363430313930666435623630303038303630303039303534393036313031303030613930303436303031363030313630613031623033313636303031363030313630613031623033313636333861626636303737363034303531383136336666666666666666313636306530316238313532363030343031363032303630343035313830383330333831383638303362313538303135363130623862353736303030383066643562353035616661313538303135363130623966353733643630303038303365336436303030666435623530353035303530363034303531336436303230383131303135363130626235353736303030383066643562353035313630343038303531363362383365313630353630653031623831353233333630303438323031383139303532393135313932393335303930393136303030393136303031363030313630613031623033383531363931363362383365313630353931363032343830383230313932363065303932393039313930383239303033303138313836383033623135383031353631306330383537363030303830666435623530356166613135383031353631306331633537336436303030383033653364363030306664356235303530353035303630343035313364363031663139363031663832303131363832303138303630343035323530363065303831313031353631306334313537363030303830666435623530363038303831303135313630613039303931303135313630303235343931393535303931353038313130363130633937353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030633630323438323031353236623465366637343230363536633639363736393632366336353630613031623630343438323031353239303531393038313930303336303634303139306664356236303031363030313630613031623033383231363630303039303831353236303062363032303532363034303930323035343630666631363135363130636635353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030643630323438323031353236633130356231633939353835393165343831643962646431393539363039613162363034343832303135323930353139303831393030333630363430313930666435623530363030313630303136306130316230333136363030303930383135323630306236303230353236303430393032303830353436306666313931363630303131373930353535303930353666656132363536323761376137323331353832306262643231313539616364386634353538326463313361323238386336616436303033663839373538343264353062376161353732306465666530303938326636343733366636633633343330303035313030303332613236353632376137613732333135383230326435663731613564353033643331363033386464343833383236623334646431333336663037313964663231363263393664626530663839376566666639393634373336663663363334333030303531303030333236303830363034303532363030303830353436303031363030313630613031623033313931363333313739303535363130333832383036313030323536303030333936303030663366653630383036303430353233343830313536313030313035373630303038306664356235303630303433363130363130303631353736303030333536306530316338303632623966393534313436313030363635373830363331336166343033353134363130303934353738303633336339376632393431343631303062613537383036333431633065316235313436313030653035373830363335633039393231353134363130306538353738303633636165663164356131343631303132313537356236303030383066643562363130303932363030343830333630333630343038313130313536313030376335373630303038306664356235303830333539303630323030313335363030313630303136306130316230333136363130313539353635623030356236313030393236303034383033363033363032303831313031353631303061613537363030303830666435623530333536303031363030313630613031623033313636313031646535363562363130303932363030343830333630333630323038313130313536313030643035373630303038306664356235303335363030313630303136306130316230333136363130323463353635623631303039323631303264313536356236313031303536303034383033363033363032303831313031353631303066653537363030303830666435623530333536313033323035363562363034303830353136303031363030313630613031623033393039323136383235323531393038313930303336303230303139306633356236313031343736303034383033363033363032303831313031353631303133373537363030303830666435623530333536303031363030313630613031623033313636313033336235363562363034303830353139313832353235313930383139303033363032303031393066333562363030303534363030313630303136306130316230333136333331343631303161353537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306136303234383230313532363934653666373432303666373736653635373232313630623031623630343438323031353239303531393038313930303336303634303139306664356236303030383238313532363030313630323039303831353236303430383038333230383035343630303136303031363061303162303339303935313636303031363030313630613031623033313939303935313638353137393035353932383235323630303239303532323035353536356236303030353436303031363030313630613031623033313633333134363130323261353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030613630323438323031353236393465366637343230366637373665363537323231363062303162363034343832303135323930353139303831393030333630363430313930666435623630303038303534363030313630303136306130316230333139313636303031363030313630613031623033393239303932313639313930393131373930353535363562363030303534363030313630303136306130316230333136333331343631303239383537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306136303234383230313532363934653666373432303666373736653635373232313630623031623630343438323031353239303531393038313930303336303634303139306664356236303031363030313630613031623033313636303030393038313532363030323630323039303831353236303430383038333230383035343930383439303535383335323630303139303931353239303230383035343630303136303031363061303162303331393136393035353536356236303030353436303031363030313630613031623033313633333134363130333164353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030613630323438323031353236393465366637343230366637373665363537323231363062303162363034343832303135323930353139303831393030333630363430313930666435623333666635623630303136303230353236303030393038313532363034303930323035343630303136303031363061303162303331363831353635623630303236303230353236303030393038313532363034303930323035343831353666656132363536323761376137323331353832303861393239393764373739616263303664373363333462326536343636653462366461633238303161656163393136653232616331653938616362633363616236343733366636633633343330303035313030303332