Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Blacklist Registry V1
- Optimization enabled
- true
- Compiler version
- v0.5.16+commit.9c3226ce
- Optimization runs
- 200
- EVM Version
- petersburg
- Verified at
- 2021-08-20 08:12:26.855163Z
Constructor Arguments
0000000000000000000000000000000000000000000000000000000000000307000000000000000000000000000000000000000000000000000000000000030200000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000318000000000000000000000000f7ec1411b51eebd813f71545ec6b5dc8a7ab71bc
Arg [0] (address) : 0x0000000000000000000000000000000000000307
Arg [1] (address) : 0x0000000000000000000000000000000000000302
Arg [2] (address) : 0x0000000000000000000000000000000000000308
Arg [3] (address) : 0x0000000000000000000000000000000000000318
Arg [4] (address) : 0xf7ec1411b51eebd813f71545ec6b5dc8a7ab71bc
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;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;/** * 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;/** * 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;/** * 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;/** * 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;/** * Interface of BlacklistProposal */contract IBlacklistProposal is IProposal { function isObeyed() external view returns(bool);}/** * Genesis version of BlacklistRegistry interface. * * Base Consensus interface for blocking outgoing transactions from * blacklisted accounts. * * NOTE: it MUST NOT change after blockchain launch! */interface IBlacklistRegistry { event BlacklistProposal( address indexed target, IBlacklistProposal proposal ); event WhitelistProposal( address indexed target, IBlacklistProposal proposal ); event DrainProposal( address indexed target, IBlacklistProposal proposal ); function compensation_fund() external view returns(ITreasury); function EBI_signer() external view returns(address); function proposals(address) external view returns( IBlacklistProposal enforce, IBlacklistProposal revoke, IBlacklistProposal drain); function propose(address) external payable returns(IBlacklistProposal); function proposeRevoke(address) external payable returns(IBlacklistProposal); function proposeDrain(address) external payable returns(IBlacklistProposal); function isBlacklisted(address) external view returns(bool); function isDrainable(address) external view returns(bool); function collect(address) external; function drainMigration(uint item_id, bytes20 owner) external; function enumerateAll() external view returns(address[] memory addresses); function enumerateBlocked() external view returns(address[] memory addresses); function enumerateDrainable() external view returns(address[] memory addresses); function onDrain(address) external;}// 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;/** * Genesis version of DelegatedPoS interface. * * Base Consensus interface for contracts which which allow another address * to stake on behalf of them. * * NOTE: it MUST NOT change after blockchain launch! */interface IDelegatedPoS { function signerAddress() external view returns(address);}/** * Genesis hardcoded version of Gen 2 Migration * * NOTE: it MUST NOT change after blockchain launch! */contract Gen2Migration is GlobalConstants, IDelegatedPoS{ struct UnspentCoins { bytes20 owner; // Gen 2 P2PKH uint amount; } event Migrated( uint item_id, address destination, uint amount ); IGovernedProxy public blacklist_proxy; uint public chain_id; address public signerAddress; // IDelegatedPoS uint public totalAmount; UnspentCoins[] public coins; mapping(bytes20 => bool) hard_blacklist; // NOTE: this c-tor is used during testing constructor(IGovernedProxy _blacklist_proxy, uint _chain_id, address _signer) public { blacklist_proxy = _blacklist_proxy; chain_id = _chain_id; signerAddress = _signer; } function setSnapshot( bytes20[] calldata _owners, uint[] calldata _amounts, bytes20[] calldata _blacklist ) external { require(coins.length == 0, "Already set"); require(msg.sender == signerAddress, "Invalid sender"); require(_owners.length == _amounts.length, "match length"); require(_owners.length > 0, "has data"); coins.length = _owners.length; uint total; for (uint i = _owners.length; i-- > 0;) { coins[i].owner = _owners[i]; coins[i].amount = _amounts[i]; total += _amounts[i]; } totalAmount = total; // NOTE: there is a special consensus procedure to setup account balance based on // totalAmount(). for (uint i = _blacklist.length; i-- > 0;) { hard_blacklist[_blacklist[i]] = true; } } function itemCount() external view returns(uint) { return coins.length; } function hashToSign(address payable _destination) public view returns(bytes32) { return keccak256( abi.encodePacked( _destination, "||Energi Gen 2 migration claim||", chain_id ) ); } function verifyClaim(uint _item_id, address payable _destination, uint8 sig_v, bytes32 sig_r, bytes32 sig_s) public view returns(uint amount) { // Check ID require(_item_id < coins.length, "Invalid ID"); // Recover owner bytes32 hash = hashToSign(_destination); bytes20 owner = bytes20(ecrecover(hash, sig_v, sig_r, sig_s)); // Validate Owner require(coins[_item_id].owner == owner, "Invalid signature"); // Check if blacklisted IBlacklistRegistry blacklist = IBlacklistRegistry(address(blacklist_proxy.impl())); require(!blacklist.isBlacklisted(address(owner)), "Owner is blacklisted"); require(!hard_blacklist[owner], "Owner is hard blacklisted"); // Validate amount amount = coins[_item_id].amount; } function claim(uint _item_id, address payable _destination, uint8 sig_v, bytes32 sig_r, bytes32 sig_s) external { uint amount = verifyClaim(_item_id, _destination, sig_v, sig_r, sig_s); require(amount > 0, "Already spent"); // Spend coins[_item_id].amount = 0; emit Migrated( _item_id, _destination, amount ); _destination.transfer(amount); } // SECURITY: emergency drain procedure has to be implemented as blacklist // followed by consensus-level drain to Blacklist registry. function blacklistClaim(uint _item_id, bytes20 _owner) external { require(_item_id < coins.length, "Invalid ID"); uint amount = coins[_item_id].amount; require(amount > 0, "Already spent"); require(coins[_item_id].owner == _owner, "Invalid Owner"); IBlacklistRegistry blacklist = IBlacklistRegistry(address(blacklist_proxy.impl())); require(msg.sender == address(blacklist), "Not blacklist registry"); // Spend coins[_item_id].amount = 0; blacklist.compensation_fund().contribute.value(amount)(); } // Safety //--------------------------------- function () external payable { revert("Not supported"); }}// 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"); }}// 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; }}contract BlacklistProposalV1 is GenericProposalV1, IBlacklistProposal{ constructor(IGovernedProxy _mnregistry_proxy, address payable fee_payer) public GenericProposalV1( _mnregistry_proxy, 10, 1 weeks, fee_payer ) // solium-disable-next-line no-empty-blocks {} function isObeyed() external view returns(bool) { if (isAccepted()) { return true; } uint accepted = accepted_weight; uint rejected = rejected_weight; if ((accepted > (rejected*2)) && (accepted > MN_COLLATERAL_MAX)) { return true; } return false; }}/** * A workaround for BlacklistRegistryV1 deploy-time gas consumption */contract BlacklistV1ProposalCreator is StorageBase{ function create(IGovernedProxy mnregistry_proxy, address payable fee_payer) external payable requireOwner returns(IBlacklistProposal) { BlacklistProposalV1 proposal = new BlacklistProposalV1( mnregistry_proxy, fee_payer ); proposal.setFee.value(msg.value)(); return proposal; }}/** * Permanent storage of Blacklist Registry V1 data. */contract StorageBlacklistRegistryV1 is StorageBase{ // NOTE: ABIEncoderV2 is not acceptable at the moment of development! struct Info { IBlacklistProposal enforce; IBlacklistProposal revoke; IBlacklistProposal drain; uint index; } mapping(address => Info) public address_info; address[] public address_list; function setEnforce(address addr, IBlacklistProposal proposal) external requireOwner { Info storage item = address_info[addr]; assert(address(item.enforce) == address(0)); item.enforce = proposal; item.index = address_list.length; address_list.push(addr); } function setRevoke(address addr, IBlacklistProposal proposal) external requireOwner { Info storage item = address_info[addr]; assert(address(item.enforce) != address(0)); item.revoke = proposal; } function setDrain(address addr, IBlacklistProposal proposal) external requireOwner { Info storage item = address_info[addr]; assert(address(item.enforce) != address(0)); item.drain = proposal; } function remove(address addr) external requireOwner { Info storage item = address_info[addr]; assert(address(item.enforce) != address(0)); // Ensure re-ordered index is updated address last = address_list[address_list.length - 1]; address_info[last].index = item.index; // Move the last into the gap, NOOP on on match address_list[item.index] = last; address_list.pop(); delete address_info[addr]; } function addresses() external view returns(address[] memory result) { uint len = address_list.length; result = new address[](len); for (uint i = 0; i < len; ++i) { result[i] = address_list[i]; } }}/** * Genesis hardcoded version of BlacklistRegistry. * * NOTE: it MUST NOT change after blockchain launch! */contract BlacklistRegistryV1 is GovernedContract, NonReentrant, GlobalConstants, IBlacklistRegistry{ // Data for migration //--------------------------------- BlacklistV1ProposalCreator public proposal_creator; StorageBlacklistRegistryV1 public v1storage; IGovernedProxy public mnregistry_proxy; Gen2Migration public migration; ITreasury public compensation_fund; address public EBI_signer; //--------------------------------- constructor( address _proxy, IGovernedProxy _mnregistry_proxy, Gen2Migration _migration, ITreasury _compensation_fund, address _ebi_signer ) public GovernedContract(_proxy) { proposal_creator = new BlacklistV1ProposalCreator(); v1storage = new StorageBlacklistRegistryV1(); mnregistry_proxy = _mnregistry_proxy; migration = _migration; compensation_fund = _compensation_fund; EBI_signer = _ebi_signer; } // IGovernedContract //--------------------------------- function _destroy(IGovernedContract _newImpl) internal { v1storage.setOwner(_newImpl); proposal_creator.kill(); } // IBlacklistRegistry //--------------------------------- function proposals(address addr) external view returns(IBlacklistProposal enforce, IBlacklistProposal revoke, IBlacklistProposal drain) { (enforce, revoke, drain,) = v1storage.address_info(addr); } function _createProposal() internal returns(IBlacklistProposal) { // solium-disable-next-line security/no-low-level-calls (bool s, bytes memory r) = address(proposal_creator).delegatecall( abi.encodeWithSelector( proposal_creator.create.selector, mnregistry_proxy, _callerAddress()) ); require(s, string(r)); return abi.decode(r, (IBlacklistProposal)); } // solium-disable-next-line security/no-assign-params function _requireFee(uint fee) internal { if (_callerAddress() == EBI_signer) { fee = 0; } require(msg.value == fee, "Invalid fee"); } function propose(address addr) external payable noReentry returns(IBlacklistProposal) { _requireFee(FEE_BLACKLIST_V1); StorageBlacklistRegistryV1 store = v1storage; (IBlacklistProposal enforce, IBlacklistProposal revoke, IBlacklistProposal drain,) = store.address_info(addr); // Cleanup old if (address(enforce) != address(0)) { if (address(revoke) != address(0)) { // assume enforced if (revoke.isAccepted()) { enforce.destroy(); revoke.destroy(); if (address(drain) != address(0)) { drain.destroy(); } store.remove(addr); } else if (revoke.isFinished()) { revert("Already active (1)"); } } else if (enforce.isFinished() && !enforce.isAccepted()) { enforce.collect(); // See below if (address(drain) != address(0)) { drain.destroy(); } store.remove(addr); } else { revert("Already active (2)"); } } // Create new IBlacklistProposal proposal = _createProposal(); store.setEnforce(addr, proposal); emit BlacklistProposal(addr, proposal); return proposal; } function proposeRevoke(address addr) external payable noReentry returns(IBlacklistProposal) { _requireFee(FEE_BLACKLIST_REVOKE_V1); StorageBlacklistRegistryV1 store = v1storage; (IBlacklistProposal enforce, IBlacklistProposal revoke,,) = store.address_info(addr); // Cleanup old require(address(enforce) != address(0), "No need (1)"); if (address(revoke) != address(0)) { // assume enforced if (!revoke.isFinished()) { revert("Already active"); } else if (!revoke.isAccepted()) { revoke.collect(); } } else if (!enforce.isFinished()) { revert("Not applicable"); } else if (!enforce.isAccepted()) { revert("No need (2)"); } // Create new IBlacklistProposal proposal = _createProposal(); store.setRevoke(addr, proposal); emit WhitelistProposal(addr, proposal); return proposal; } function proposeDrain(address addr) external payable noReentry returns(IBlacklistProposal) { _requireFee(FEE_BLACKLIST_DRAIN_V1); require(isBlacklisted(address(addr)), "Not blacklisted"); StorageBlacklistRegistryV1 store = v1storage; (,, IBlacklistProposal drain,) = store.address_info(addr); if (address(drain) != address(0)) { if (drain.isAccepted()) { revert("Not need"); } else if (drain.isFinished()) { drain.collect(); } else { revert("Voting in progress"); } } // Create new IBlacklistProposal proposal = _createProposal(); store.setDrain(addr, proposal); emit DrainProposal(addr, proposal); return proposal; } function isBlacklisted(address addr) public view returns(bool) { StorageBlacklistRegistryV1 store = v1storage; (IBlacklistProposal enforce, IBlacklistProposal revoke,,) = store.address_info(addr); if ((address(revoke) != address(0)) && revoke.isAccepted()) { return false; } if ((address(enforce) != address(0)) && enforce.isObeyed()) { return true; } return false; } function isDrainable(address addr) public view returns(bool) { (IBlacklistProposal enforce, IBlacklistProposal revoke, IBlacklistProposal drain,) = v1storage.address_info(addr); if (address(enforce) == address(0)) { return false; } if (!enforce.isAccepted()) { return false; } if ((address(revoke) != address(0)) && revoke.isAccepted()) { return false; } if (address(drain) == address(0)) { return false; } return drain.isAccepted(); } function collect(address addr) external noReentry { StorageBlacklistRegistryV1 store = v1storage; (IBlacklistProposal enforce, IBlacklistProposal revoke, IBlacklistProposal drain,) = store.address_info(addr); require(address(enforce) != address(0), "Nothing to collect"); require(enforce.isFinished(), "Enforce voting in progress"); if (!enforce.isAccepted()) { enforce.collect(); store.remove(addr); return; } if (address(drain) != address(0)) { require(drain.isFinished(), "Drain voting in progress"); if (drain.isAccepted()) { revert("Account must be drained"); } drain.collect(); store.setDrain(addr, IBlacklistProposal(address(0))); return; } if (address(revoke) != address(0)) { require(revoke.isFinished(), "Revoke voting in progress"); if (revoke.isAccepted()) { enforce.destroy(); revoke.destroy(); assert(address(drain) == address(0)); store.remove(addr); } else { revoke.collect(); store.setRevoke(addr, IBlacklistProposal(address(0))); } return; } revert("No proposals ready to collect"); } function drainMigration(uint item_id, bytes20 owner) external noReentry { require(isDrainable(address(owner)), "Not drainable"); migration.blacklistClaim(item_id, owner); _onDrain(address(owner)); } function enumerateAll() external view returns(address[] memory addresses) { return v1storage.addresses(); } function enumerateBlocked() external view returns(address[] memory addresses) { addresses = v1storage.addresses(); for (uint i = addresses.length; i-- > 0;) { if (!isBlacklisted(addresses[i])) { addresses[i] = address(0); } } } function enumerateDrainable() external view returns(address[] memory addresses) { addresses = v1storage.addresses(); for (uint i = addresses.length; i-- > 0;) { if (!isDrainable(addresses[i])) { addresses[i] = address(0); } } } function onDrain(address addr) external noReentry { // solium-disable-next-line security/no-tx-origin require(tx.origin == proxy, "Not consensus"); _onDrain(addr); } function _onDrain(address addr) internal { StorageBlacklistRegistryV1 store = v1storage; (IBlacklistProposal enforce, IBlacklistProposal revoke, IBlacklistProposal drain,) = store.address_info(addr); if (address(enforce) != address(0)) { enforce.destroy(); if (address(revoke) != address(0)) { revoke.destroy(); } if (address(drain) != address(0)) { drain.destroy(); } store.remove(addr); } } // 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":"address","name":"_migration","internalType":"contractGen2Migration"},{"type":"address","name":"_compensation_fund","internalType":"contractITreasury"},{"type":"address","name":"_ebi_signer","internalType":"address"}]},{"type":"event","name":"BlacklistProposal","inputs":[{"type":"address","name":"target","internalType":"address","indexed":true},{"type":"address","name":"proposal","internalType":"contractIBlacklistProposal","indexed":false}],"anonymous":false},{"type":"event","name":"DrainProposal","inputs":[{"type":"address","name":"target","internalType":"address","indexed":true},{"type":"address","name":"proposal","internalType":"contractIBlacklistProposal","indexed":false}],"anonymous":false},{"type":"event","name":"WhitelistProposal","inputs":[{"type":"address","name":"target","internalType":"address","indexed":true},{"type":"address","name":"proposal","internalType":"contractIBlacklistProposal","indexed":false}],"anonymous":false},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"EBI_signer","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"collect","inputs":[{"type":"address","name":"addr","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contractITreasury"}],"name":"compensation_fund","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"destroy","inputs":[{"type":"address","name":"_newImpl","internalType":"contractIGovernedContract"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"drainMigration","inputs":[{"type":"uint256","name":"item_id","internalType":"uint256"},{"type":"bytes20","name":"owner","internalType":"bytes20"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"addresses","internalType":"address[]"}],"name":"enumerateAll","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"addresses","internalType":"address[]"}],"name":"enumerateBlocked","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"addresses","internalType":"address[]"}],"name":"enumerateDrainable","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isBlacklisted","inputs":[{"type":"address","name":"addr","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isDrainable","inputs":[{"type":"address","name":"addr","internalType":"address"}],"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":"contractGen2Migration"}],"name":"migration","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contractIGovernedProxy"}],"name":"mnregistry_proxy","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"onDrain","inputs":[{"type":"address","name":"addr","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contractBlacklistV1ProposalCreator"}],"name":"proposal_creator","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"enforce","internalType":"contractIBlacklistProposal"},{"type":"address","name":"revoke","internalType":"contractIBlacklistProposal"},{"type":"address","name":"drain","internalType":"contractIBlacklistProposal"}],"name":"proposals","inputs":[{"type":"address","name":"addr","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[{"type":"address","name":"","internalType":"contractIBlacklistProposal"}],"name":"propose","inputs":[{"type":"address","name":"addr","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"payable","payable":true,"outputs":[{"type":"address","name":"","internalType":"contractIBlacklistProposal"}],"name":"proposeDrain","inputs":[{"type":"address","name":"addr","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"payable","payable":true,"outputs":[{"type":"address","name":"","internalType":"contractIBlacklistProposal"}],"name":"proposeRevoke","inputs":[{"type":"address","name":"addr","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"proxy","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contractStorageBlacklistRegistryV1"}],"name":"v1storage","inputs":[],"constant":true}]
Deployed ByteCode
0x3630383036303430353233343830313536323030303031313537363030303830666435623530363034303531363230303461383633383033383036323030346138363833333938313831303136303430353236306130383131303135363230303030333735373630303038306664356235303830353136303230383230313531363034303830383430313531363036303835303135313630383039303935303135313630303038303534363030313630303136306130316230333139313636303031363030313630613031623033383731363137393035353931353139333934393239333930393239313930363230303030383039303632303030313463353635623630343035313830393130333930363030306630383031353830313536323030303039643537336436303030383033653364363030306664356235303630303238303534363030313630303136306130316230333139313636303031363030313630613031623033393239303932313639313930393131373930353536303430353136323030303063633930363230303031356135363562363034303531383039313033393036303030663038303135383031353632303030306539353733643630303038303365336436303030666435623530363030333830353436303031363030313630613031623033313939303831313636303031363030313630613031623033393338343136313739303931353536303034383035343832313639363833313639363930393631373930393535353630303538303534383631363934383231363934393039343137393039333535363030363830353438353136393238343136393239303932313739303931353536303037383035343930393331363931313631373930353535303632303030313638353635623631313362633830363230303265656538333339303139303536356236313037646338303632303034326161383333393031393035363562363132643736383036323030303137383630303033393630303066336665363038303630343035323630303433363130363130313239353736303030333536306530316338303633373964376263303731313631303061623537383036336431653865626461313136313030366635373830363364316538656264613134363130343465353738303633656335353638383931343631303437343537383036336565333366396432313436313034383935373830363366343434313135323134363130343965353738303633666535373561383731343631303462333537383036336665373333346538313436313034653635373631303132393536356238303633373964376263303731343631303361393537383036333861643430313266313436313033646335373830363339346332313066633134363130336631353738303633626333393361666231343631303430363537383036336365353439346262313436313034316235373631303132393536356238303633326430353933303531313631303066323537383036333264303539333035313436313032346235373830363333333033626262313134363130323630353738303633333334316234343531343631303261373537383036333335303261313330313436313033303535373830363335363033313235633134363130333434353736313031323935363562383036326635356439643134363130313636353738303633303132363739353131343631303139623537383036333036656331366638313436313031646435373830363331373035613362643134363130323130353738303633323434666365613531343631303232353537356236303430383035313632343631626364363065353162383135323630323036303034383230313532363030643630323438323031353236633133396264643038316364643563316331626463396431393539363039613162363034343832303135323930353139303831393030333630363430313930666435623334383031353631303137323537363030303830666435623530363130313939363030343830333630333630323038313130313536313031383935373630303038306664356235303335363030313630303136306130316230333136363130346662353635623030356236313031633136303034383033363033363032303831313031353631303162313537363030303830666435623530333536303031363030313630613031623033313636313035356235363562363034303830353136303031363030313630613031623033393039323136383235323531393038313930303336303230303139306633356233343830313536313031653935373630303038306664356235303631303139393630303438303336303336303230383131303135363130323030353736303030383066643562353033353630303136303031363061303162303331363631306330653536356233343830313536313032316335373630303038306664356235303631303163313631313439623536356236313031633136303034383033363033363032303831313031353631303233623537363030303830666435623530333536303031363030313630613031623033313636313134616135363562333438303135363130323537353736303030383066643562353036313031633136313139363335363562333438303135363130323663353736303030383066643562353036313032393336303034383033363033363032303831313031353631303238333537363030303830666435623530333536303031363030313630613031623033313636313139373235363562363034303830353139313135313538323532353139303831393030333630323030313930663335623334383031353631303262333537363030303830666435623530363130326461363030343830333630333630323038313130313536313032636135373630303038306664356235303335363030313630303136306130316230333136363131626162353635623630343038303531363030313630303136306130316230333934383531363831353239323834313636303230383430313532393231363831383330313532393035313930383139303033363036303031393066333562333438303135363130333131353736303030383066643562353036313031393936303034383033363033363034303831313031353631303332383537363030303830666435623530383033353930363032303031333536626666666666666666666666666666666666666666666666663139313636313163343235363562333438303135363130333530353736303030383066643562353036313033353936313164363235363562363034303830353136303230383038323532383335313831383330313532383335313931393238333932393038333031393138353831303139313032383038333833363030303562383338313130313536313033393535373831383130313531383338323031353236303230303136313033376435363562353035303530353039303530303139323530353035303630343035313830393130333930663335623334383031353631303362353537363030303830666435623530363130313939363030343830333630333630323038313130313536313033636335373630303038306664356235303335363030313630303136306130316230333136363131656463353635623334383031353631303365383537363030303830666435623530363130316331363131663737353635623334383031353631303366643537363030303830666435623530363130316331363131663836353635623334383031353631303431323537363030303830666435623530363130333539363131663935353635623334383031353631303432373537363030303830666435623530363130313939363030343830333630333630323038313130313536313034336535373630303038306664356235303335363030313630303136306130316230333136363132306139353635623631303163313630303438303336303336303230383131303135363130343634353736303030383066643562353033353630303136303031363061303162303331363631323066633536356233343830313536313034383035373630303038306664356235303631303163313631323439663536356233343830313536313034393535373630303038306664356235303631303335393631323461653536356233343830313536313034616135373630303038306664356235303631303163313631323632343536356233343830313536313034626635373630303038306664356235303631303239333630303438303336303336303230383131303135363130346436353736303030383066643562353033353630303136303031363061303162303331363631323633333536356233343830313536313034663235373630303038306664356235303631303163313631323765303536356236303030353436303031363030313630613031623033313633333134363130353436353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030393630323438323031353236383465366637343230373037323666373837393630623831623630343438323031353239303531393038313930303336303634303139306664356236313035346638313631323765663536356238303630303136303031363061303162303331366666356236303030363030313534363030303134363130353965353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030373630323438323031353236363532363536353665373437323739363063383162363034343832303135323930353139303831393030333630363430313930666435623630303138303535363130356234363833363335633961646335646561303030303036313238633035363562363030333534363034303830353136333332336162343039363065303162383135323630303136303031363061303162303338353831313636303034383330313532393135313931393039323136393136303030393138323931383239313835393136333332336162343039393136303234383038333031393236303830393239313930383239303033303138313836383033623135383031353631303630613537363030303830666435623530356166613135383031353631303631653537336436303030383033653364363030306664356235303530353035303630343035313364363038303831313031353631303633343537363030303830666435623530383035313630323038323031353136303430393039323031353139303934353039303932353039303530363030313630303136306130316230333833313631353631306234363537363030313630303136306130316230333832313631353631303930313537383136303031363030313630613031623033313636333530353161356563363034303531383136336666666666666666313636306530316238313532363030343031363032303630343035313830383330333831383638303362313538303135363130366131353736303030383066643562353035616661313538303135363130366235353733643630303038303365336436303030666435623530353035303530363034303531336436303230383131303135363130366362353736303030383066643562353035313135363130383530353738323630303136303031363061303162303331363633383331393765663036303430353138313633666666666666666631363630653031623831353236303034303136303030363034303531383038333033383136303030383738303362313538303135363130373064353736303030383066643562353035616631313538303135363130373231353733643630303038303365336436303030666435623530353035303530383136303031363030313630613031623033313636333833313937656630363034303531383136336666666666666666313636306530316238313532363030343031363030303630343035313830383330333831363030303837383033623135383031353631303736303537363030303830666435623530356166313135383031353631303737343537336436303030383033653364363030306664356235303530353035303630303136303031363061303162303338313136313536313037646235373830363030313630303136306130316230333136363338333139376566303630343035313831363366666666666666663136363065303162383135323630303430313630303036303430353138303833303338313630303038373830336231353830313536313037633235373630303038306664356235303561663131353830313536313037643635373364363030303830336533643630303066643562353035303530353035623833363030313630303136306130316230333136363332393039326430653837363034303531383236336666666666666666313636306530316238313532363030343031383038323630303136303031363061303162303331363630303136303031363061303162303331363831353236303230303139313530353036303030363034303531383038333033383136303030383738303362313538303135363130383333353736303030383066643562353035616631313538303135363130383437353733643630303038303365336436303030666435623530353035303530363130386663353635623831363030313630303136306130316230333136363337623335323936323630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631303838393537363030303830666435623530356166613135383031353631303839643537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631303862333537363030303830666435623530353131353631303866633537363034303830353136323436316263643630653531623831353236303230363030343832303135323630313236303234383230313532373134313663373236353631363437393230363136333734363937363635323032383331323936303730316236303434383230313532393035313930383139303033363036343031393066643562363130623436353635623832363030313630303136306130316230333136363337623335323936323630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631303933613537363030303830666435623530356166613135383031353631303934653537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631303936343537363030303830666435623530353138303135363130396434353735303832363030313630303136306130316230333136363335303531613565633630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631303961363537363030303830666435623530356166613135383031353631303962613537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631303964303537363030303830666435623530353131353562313536313062303435373832363030313630303136306130316230333136363365353232353338313630343035313831363366666666666666663136363065303162383135323630303430313630303036303430353138303833303338313630303038373830336231353830313536313061313435373630303038306664356235303561663131353830313536313061323835373364363030303830336533643630303066643562353035303530353036303031363030313630613031623033383131363135363130613866353738303630303136303031363061303162303331363633383331393765663036303430353138313633666666666666666631363630653031623831353236303034303136303030363034303531383038333033383136303030383738303362313538303135363130613736353736303030383066643562353035616631313538303135363130613861353733643630303038303365336436303030666435623530353035303530356238333630303136303031363061303162303331363633323930393264306538373630343035313832363366666666666666663136363065303162383135323630303430313830383236303031363030313630613031623033313636303031363030313630613031623033313638313532363032303031393135303530363030303630343035313830383330333831363030303837383033623135383031353631306165373537363030303830666435623530356166313135383031353631306166623537336436303030383033653364363030306664356235303530353035303631306234363536356236303430383035313632343631626364363065353162383135323630323036303034383230313532363031323630323438323031353237313431366337323635363136343739323036313633373436393736363532303238333232393630373031623630343438323031353239303531393038313930303336303634303139306664356236303030363130623530363132393239353635623630343038303531363335363138656231313630653131623831353236303031363030313630613031623033386138313136363030343833303135323830383431363630323438333031353239313531393239333530393038373136393136336163333164363232393136303434383038323031393236303030393239303931393038323930303330313831383338373830336231353830313536313062613635373630303038306664356235303561663131353830313536313062626135373364363030303830336533643630303066643562353035303630343038303531363030313630303136306130316230333835383131363832353239313531393138623136393335303766656130643362316166633761613137353466393032623237376436663437336532663461343532366539343739373831346332303432343035643639323535373932353038313930303336303230303139306132363030303630303135353936393535303530353035303530353035363562363030313534313536313063346435373630343038303531363234363162636436306535316238313532363032303630303438323031353236303037363032343832303135323636353236353635366537343732373936306338316236303434383230313532393035313930383139303033363036343031393066643562363030313830353536303033353436303430383035313633333233616234303936306530316238313532363030313630303136306130316230333834383131363630303438333031353239313531393139303932313639313630303039313832393138323931383539313633333233616234303939313630323438303833303139323630383039323931393038323930303330313831383638303362313538303135363130636137353736303030383066643562353035616661313538303135363130636262353733643630303038303365336436303030666435623530353035303530363034303531336436303830383131303135363130636431353736303030383066643562353038303531363032303832303135313630343039303932303135313930393435303930393235303930353036303031363030313630613031623033383331363631306433373537363034303830353136323436316263643630653531623831353236303230363030343832303135323630313236303234383230313532373131333962646431613161356239396338316431626338313864626462316231393538646436303732316236303434383230313532393035313930383139303033363036343031393066643562383236303031363030313630613031623033313636333762333532393632363034303531383136336666666666666666313636306530316238313532363030343031363032303630343035313830383330333831383638303362313538303135363130643730353736303030383066643562353035616661313538303135363130643834353733643630303038303365336436303030666435623530353035303530363034303531336436303230383131303135363130643961353736303030383066643562353035313631306465643537363034303830353136323436316263643630653531623831353236303230363030343832303135323630316136303234383230313532376634353665363636663732363336353230373636663734363936653637323036393665323037303732366636373732363537333733303030303030303030303030363034343832303135323930353139303831393030333630363430313930666435623832363030313630303136306130316230333136363335303531613565633630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631306532363537363030303830666435623530356166613135383031353631306533613537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631306535303537363030303830666435623530353136313066323235373832363030313630303136306130316230333136363365353232353338313630343035313831363366666666666666663136363065303162383135323630303430313630303036303430353138303833303338313630303038373830336231353830313536313065393135373630303038306664356235303561663131353830313536313065613535373364363030303830336533643630303066643562353035303530353038333630303136303031363061303162303331363633323930393264306538363630343035313832363366666666666666663136363065303162383135323630303430313830383236303031363030313630613031623033313636303031363030313630613031623033313638313532363032303031393135303530363030303630343035313830383330333831363030303837383033623135383031353631306630313537363030303830666435623530356166313135383031353631306631353537336436303030383033653364363030306664356235303530353035303530353035303530363131343933353635623630303136303031363061303162303338313136313536313131343035373830363030313630303136306130316230333136363337623335323936323630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631306636613537363030303830666435623530356166613135383031353631306637653537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631306639343537363030303830666435623530353136313066653735373630343038303531363234363162636436306535316238313532363032303630303438323031353236303138363032343832303135323766343437323631363936653230373636663734363936653637323036393665323037303732366636373732363537333733303030303030303030303030303030303630343438323031353239303531393038313930303336303634303139306664356238303630303136303031363061303162303331363633353035316135656336303430353138313633666666666666666631363630653031623831353236303034303136303230363034303531383038333033383138363830336231353830313536313130323035373630303038306664356235303561666131353830313536313130333435373364363030303830336533643630303066643562353035303530353036303430353133643630323038313130313536313130346135373630303038306664356235303531313536313130396535373630343038303531363234363162636436306535316238313532363032303630303438323031353236303137363032343832303135323766343136333633366637353665373432303664373537333734323036323635323036343732363136393665363536343030303030303030303030303030303030303630343438323031353239303531393038313930303336303634303139306664356238303630303136303031363061303162303331363633653532323533383136303430353138313633666666666666666631363630653031623831353236303034303136303030363034303531383038333033383136303030383738303362313538303135363131306439353736303030383066643562353035616631313538303135363131306564353733643630303038303365336436303030666435623530353036303430383035313633313337353663386636306530316238313532363030313630303136306130316230333839383131363630303438333031353236303030363032343833303138313930353239323531393038393136393435303633313337353663386639333530363034343830383330313933393238323930303330313831383338373830336231353830313536313066303135373630303038306664356236303031363030313630613031623033383231363135363131343436353738313630303136303031363061303162303331363633376233353239363236303430353138313633666666666666666631363630653031623831353236303034303136303230363034303531383038333033383138363830336231353830313536313131383835373630303038306664356235303561666131353830313536313131396335373364363030303830336533643630303066643562353035303530353036303430353133643630323038313130313536313131623235373630303038306664356235303531363131323035353736303430383035313632343631626364363065353162383135323630323036303034383230313532363031393630323438323031353237663532363537363666366236353230373636663734363936653637323036393665323037303732366636373732363537333733303030303030303030303030303036303434383230313532393035313930383139303033363036343031393066643562383136303031363030313630613031623033313636333530353161356563363034303531383136336666666666666666313636306530316238313532363030343031363032303630343035313830383330333831383638303362313538303135363131323365353736303030383066643562353035616661313538303135363131323532353733643630303038303365336436303030666435623530353035303530363034303531336436303230383131303135363131323638353736303030383066643562353035313135363131333962353738323630303136303031363061303162303331363633383331393765663036303430353138313633666666666666666631363630653031623831353236303034303136303030363034303531383038333033383136303030383738303362313538303135363131326161353736303030383066643562353035616631313538303135363131326265353733643630303038303365336436303030666435623530353035303530383136303031363030313630613031623033313636333833313937656630363034303531383136336666666666666666313636306530316238313532363030343031363030303630343035313830383330333831363030303837383033623135383031353631313266643537363030303830666435623530356166313135383031353631313331313537336436303030383033653364363030306664356235303530353035303630303136303031363061303162303338313136313536313133323635376665356238333630303136303031363061303162303331363633323930393264306538363630343035313832363366666666666666663136363065303162383135323630303430313830383236303031363030313630613031623033313636303031363030313630613031623033313638313532363032303031393135303530363030303630343035313830383330333831363030303837383033623135383031353631313337653537363030303830666435623530356166313135383031353631313339323537336436303030383033653364363030306664356235303530353035303631313433643536356238313630303136303031363061303162303331363633653532323533383136303430353138313633666666666666666631363630653031623831353236303034303136303030363034303531383038333033383136303030383738303362313538303135363131336436353736303030383066643562353035616631313538303135363131336561353733643630303038303365336436303030666435623530353036303430383035313633323261383364346636306531316238313532363030313630303136306130316230333839383131363630303438333031353236303030363032343833303138313930353239323531393038393136393435303633343535303761396539333530363034343830383330313933393238323930303330313831383338373830336231353830313536313066303135373630303038306664356235303530353035303631313439333536356236303430383035313632343631626364363065353162383135323630323036303034383230313532363031643630323438323031353237663465366632303730373236663730366637333631366337333230373236353631363437393230373436663230363336663663366336353633373430303030303036303434383230313532393035313930383139303033363036343031393066643562353036303030363030313535353635623630303535343630303136303031363061303162303331363831353635623630303036303031353436303030313436313134656435373630343038303531363234363162636436306535316238313532363032303630303438323031353236303037363032343832303135323636353236353635366537343732373936306338316236303434383230313532393035313930383139303033363036343031393066643562363030313830353536313135303336383035366263373565326436333130303030303631323863303536356236303033353436303430383035313633333233616234303936306530316238313532363030313630303136306130316230333835383131363630303438333031353239313531393139303932313639313630303039313832393138343931363333323361623430393931363032343830383230313932363038303932393039313930383239303033303138313836383033623135383031353631313535383537363030303830666435623530356166613135383031353631313536633537336436303030383033653364363030306664356235303530353035303630343035313364363038303831313031353631313538323537363030303830666435623530383035313630323039303931303135313930393235303930353036303031363030313630613031623033383231363631313564393537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306236303234383230313532366134653666323036653635363536343230323833313239363061383162363034343832303135323930353139303831393030333630363430313930666435623630303136303031363061303162303338313136313536313137353135373830363030313630303136306130316230333136363337623335323936323630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631313632313537363030303830666435623530356166613135383031353631313633353537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631313634623537363030303830666435623530353136313136386635373630343038303531363234363162636436306535316238313532363032303630303438323031353236303065363032343832303135323664343136633732363536313634373932303631363337343639373636353630393031623630343438323031353239303531393038313930303336303634303139306664356238303630303136303031363061303162303331363633353035316135656336303430353138313633666666666666666631363630653031623831353236303034303136303230363034303531383038333033383138363830336231353830313536313136633835373630303038306664356235303561666131353830313536313136646335373364363030303830336533643630303066643562353035303530353036303430353133643630323038313130313536313136663235373630303038306664356235303531363131373463353738303630303136303031363061303162303331363633653532323533383136303430353138313633666666666666666631363630653031623831353236303034303136303030363034303531383038333033383136303030383738303362313538303135363131373333353736303030383066643562353035616631313538303135363131373437353733643630303038303365336436303030666435623530353035303530356236313138396335363562383136303031363030313630613031623033313636333762333532393632363034303531383136336666666666666666313636306530316238313532363030343031363032303630343035313830383330333831383638303362313538303135363131373861353736303030383066643562353035616661313538303135363131373965353733643630303038303365336436303030666435623530353035303530363034303531336436303230383131303135363131376234353736303030383066643562353035313631313766383537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306536303234383230313532366434653666373432303631373037303663363936333631363236633635363039303162363034343832303135323930353139303831393030333630363430313930666435623831363030313630303136306130316230333136363335303531613565633630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631313833313537363030303830666435623530356166613135383031353631313834353537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631313835623537363030303830666435623530353136313138396335373630343038303531363234363162636436306535316238313532363032303630303438323031353236303062363032343832303135323661346536663230366536353635363432303238333232393630613831623630343438323031353239303531393038313930303336303634303139306664356236303030363131386136363132393239353635623630343038303531363332326138336434663630653131623831353236303031363030313630613031623033383938313136363030343833303135323830383431363630323438333031353239313531393239333530393038363136393136333435353037613965393136303434383038323031393236303030393239303931393038323930303330313831383338373830336231353830313536313138666335373630303038306664356235303561663131353830313536313139313035373364363030303830336533643630303066643562353035303630343038303531363030313630303136306130316230333835383131363832353239313531393138613136393335303766326534366665386535303261343462303561383564343334366433653230386663383435633831613831633962376534646230386133336463613539666166663932353038313930303336303230303139306132363030303630303135353935393435303530353035303530353635623630303335343630303136303031363061303162303331363831353635623630303335343630343038303531363333323361623430393630653031623831353236303031363030313630613031623033383438313136363030343833303135323931353136303030393338343933383439333834393339313930393231363931363333323361623430393931363032343830383330313932363038303932393139303832393030333031383138363830336231353830313536313139633835373630303038306664356235303561666131353830313536313139646335373364363030303830336533643630303066643562353035303530353036303430353133643630383038313130313536313139663235373630303038306664356235303830353136303230383230313531363034303930393230313531393039343530393039323530393035303630303136303031363061303162303338333136363131613232353736303030393335303530353035303631316261363536356238323630303136303031363061303162303331363633353035316135656336303430353138313633666666666666666631363630653031623831353236303034303136303230363034303531383038333033383138363830336231353830313536313161356235373630303038306664356235303561666131353830313536313161366635373364363030303830336533643630303066643562353035303530353036303430353133643630323038313130313536313161383535373630303038306664356235303531363131613937353736303030393335303530353035303631316261363536356236303031363030313630613031623033383231363135383031353930363131623130353735303831363030313630303136306130316230333136363335303531613565633630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631316165333537363030303830666435623530356166613135383031353631316166373537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631316230643537363030303830666435623530353135623135363131623231353736303030393335303530353035303631316261363536356236303031363030313630613031623033383131363631316233623537363030303933353035303530353036313162613635363562383036303031363030313630613031623033313636333530353161356563363034303531383136336666666666666666313636306530316238313532363030343031363032303630343035313830383330333831383638303362313538303135363131623734353736303030383066643562353035616661313538303135363131623838353733643630303038303365336436303030666435623530353035303530363034303531336436303230383131303135363131623965353736303030383066643562353035313933353035303530353035623931393035303536356236303033353436303430383035313633333233616234303936306530316238313532363030313630303136306130316230333834383131363630303438333031353239313531363030303933383439333834393339313136393136333332336162343039393136303234383038323031393236303830393239303931393038323930303330313831383638303362313538303135363131626665353736303030383066643562353035616661313538303135363131633132353733643630303038303365336436303030666435623530353035303530363034303531336436303830383131303135363131633238353736303030383066643562353038303531363032303832303135313630343039303932303135313930393639313935353039333530393135303530353635623630303135343135363131633831353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030373630323438323031353236363532363536353665373437323739363063383162363034343832303135323930353139303831393030333630363430313930666435623630303138303535363131633932363036303832393031633631313937323536356236313163643335373630343038303531363234363162636436306535316238313532363032303630303438323031353236303064363032343832303135323663346536663734323036343732363136393665363136323663363536303938316236303434383230313532393035313930383139303033363036343031393066643562363030353534363034303830353136333533393164396164363065313162383135323630303438313031383539303532366266666666666666666666666666666666666666666666666631393834313636303234383230313532393035313630303136303031363061303162303339303932313639313633613732336233356139313630343438303832303139323630303039323930393139303832393030333031383138333837383033623135383031353631316433353537363030303830666435623530356166313135383031353631316434393537336436303030383033653364363030306664356235303530353035303631316435393831363036303163363132616561353635623530353036303030363030313535353635623630303335343630343038303531363364613033323163643630653031623831353239303531363036303932363030313630303136306130316230333136393136336461303332316364393136303034383038333031393236303030393239313930383239303033303138313836383033623135383031353631316461373537363030303830666435623530356166613135383031353631316462623537336436303030383033653364363030306664356235303530353035303630343035313364363030303832336536303166336439303831303136303166313931363832303136303430353236303230383131303135363131646534353736303030383066643562383130313930383038303531363034303531393339323931393038343634303130303030303030303832313131353631316530343537363030303830666435623930383330313930363032303832303138353831313131353631316531393537363030303830666435623832353138363630323038323032383330313131363430313030303030303030383231313137313536313165333635373630303038306664356238323532353038313531363032303931383230313932383230313931303238303833383336303030356238333831313031353631316536333537383138313031353138333832303135323630323030313631316534623536356235303530353035303930353030313630343035323530353035303930353036303030383135313930353035623630303031393831303139303135363131656438353736313165613038323832383135313831313036313165393335376665356236303230303236303230303130313531363132363333353635623631316564333537363030303832383238313531383131303631316562323537666535623630323030323630323030313031393036303031363030313630613031623033313639303831363030313630303136306130316230333136383135323530353035623631316537393536356235303930353635623630303135343135363131663162353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030373630323438323031353236363532363536353665373437323739363063383162363034343832303135323930353139303831393030333630363430313930666435623630303138303535363030303534363030313630303136306130316230333136333231343631316636653537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306436303234383230313532366334653666373432303633366636653733363536653733373537333630393831623630343438323031353239303531393038313930303336303634303139306664356236313134393338313631326165613536356236303032353436303031363030313630613031623033313638313536356236303037353436303031363030313630613031623033313638313536356236303033353436303430383035313633646130333231636436306530316238313532393035313630363039323630303136303031363061303162303331363931363364613033323163643931363030343830383330313932363030303932393139303832393030333031383138363830336231353830313536313166646135373630303038306664356235303561666131353830313536313166656535373364363030303830336533643630303066643562353035303530353036303430353133643630303038323365363031663364393038313031363031663139313638323031363034303532363032303831313031353631323031373537363030303830666435623831303139303830383035313630343035313933393239313930383436343031303030303030303038323131313536313230333735373630303038306664356239303833303139303630323038323031383538313131313536313230346335373630303038306664356238323531383636303230383230323833303131313634303130303030303030303832313131373135363132303639353736303030383066643562383235323530383135313630323039313832303139323832303139313032383038333833363030303562383338313130313536313230393635373831383130313531383338323031353236303230303136313230376535363562353035303530353039303530303136303430353235303530353039303530356239303536356236303030353436303031363030313630613031623033313633333134363132306634353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030393630323438323031353236383465366637343230373037323666373837393630623831623630343438323031353239303531393038313930303336303634303139306664356236313230663938313562353035363562363030303630303135343630303031343631323133663537363034303830353136323436316263643630653531623831353236303230363030343832303135323630303736303234383230313532363635323635363536653734373237393630633831623630343438323031353239303531393038313930303336303634303139306664356236303031383035353631323135353638303536626337356532643633313030303030363132386330353635623631323135653832363132363333353635623631323161313537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306636303234383230313532366531333962646430383138396231383538646164623161356364643139353936303861316236303434383230313532393035313930383139303033363036343031393066643562363030333534363034303830353136333332336162343039363065303162383135323630303136303031363061303162303338353831313636303034383330313532393135313931393039323136393136303030393138333931363333323361623430393931363032343830383330313932363038303932393139303832393030333031383138363830336231353830313536313231663335373630303038306664356235303561666131353830313536313232303735373364363030303830336533643630303066643562353035303530353036303430353133643630383038313130313536313232316435373630303038306664356235303630343030313531393035303630303136303031363061303162303338313136313536313233643935373830363030313630303136306130316230333136363335303531613565633630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631323236633537363030303830666435623530356166613135383031353631323238303537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631323239363537363030303830666435623530353131353631323264353537363034303830353136323436316263643630653531623831353236303230363030343832303135323630303836303234383230313532363731333962646430383162393935393539363063323162363034343832303135323930353139303831393030333630363430313930666435623830363030313630303136306130316230333136363337623335323936323630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631323330653537363030303830666435623530356166613135383031353631323332323537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631323333383537363030303830666435623530353131353631323339373537383036303031363030313630613031623033313636336535323235333831363034303531383136336666666666666666313636306530316238313532363030343031363030303630343035313830383330333831363030303837383033623135383031353631323337613537363030303830666435623530356166313135383031353631323338653537336436303030383033653364363030306664356235303530353035303631323364393536356236303430383035313632343631626364363065353162383135323630323036303034383230313532363031323630323438323031353237313536366637343639366536373230363936653230373037323666363737323635373337333630373031623630343438323031353239303531393038313930303336303634303139306664356236303030363132336533363132393239353635623630343038303531363331333735366338663630653031623831353236303031363030313630613031623033383838313136363030343833303135323830383431363630323438333031353239313531393239333530393038353136393136333133373536633866393136303434383038323031393236303030393239303931393038323930303330313831383338373830336231353830313536313234333935373630303038306664356235303561663131353830313536313234346435373364363030303830336533643630303066643562353035303630343038303531363030313630303136306130316230333835383131363832353239313531393138393136393335303766623031363362333330333362636561343161373864326434613963353936633239623036363732353935343364366435366238636163386364393264326365613932353038313930303336303230303139306132363030303630303135353934393335303530353035303536356236303030353436303031363030313630613031623033313638313536356236303033353436303430383035313633646130333231636436306530316238313532393035313630363039323630303136303031363061303162303331363931363364613033323163643931363030343830383330313932363030303932393139303832393030333031383138363830336231353830313536313234663335373630303038306664356235303561666131353830313536313235303735373364363030303830336533643630303066643562353035303530353036303430353133643630303038323365363031663364393038313031363031663139313638323031363034303532363032303831313031353631323533303537363030303830666435623831303139303830383035313630343035313933393239313930383436343031303030303030303038323131313536313235353035373630303038306664356239303833303139303630323038323031383538313131313536313235363535373630303038306664356238323531383636303230383230323833303131313634303130303030303030303832313131373135363132353832353736303030383066643562383235323530383135313630323039313832303139323832303139313032383038333833363030303562383338313130313536313235616635373831383130313531383338323031353236303230303136313235393735363562353035303530353039303530303136303430353235303530353039303530363030303831353139303530356236303030313938313031393031353631316564383537363132356563383238323831353138313130363132356466353766653562363032303032363032303031303135313631313937323536356236313236316635373630303038323832383135313831313036313235666535376665356236303230303236303230303130313930363030313630303136306130316230333136393038313630303136303031363061303162303331363831353235303530356236313235633535363562363030363534363030313630303136306130316230333136383135363562363030333534363034303830353136333332336162343039363065303162383135323630303136303031363061303162303338343831313636303034383330313532393135313630303039333932393039323136393138333931383239313834393136333332336162343039393136303234383038333031393236303830393239313930383239303033303138313836383033623135383031353631323638393537363030303830666435623530356166613135383031353631323639643537336436303030383033653364363030306664356235303530353035303630343035313364363038303831313031353631323662333537363030303830666435623530383035313630323039303931303135313930393235303930353036303031363030313630613031623033383131363135383031353930363132373361353735303830363030313630303136306130316230333136363335303531613565633630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631323730643537363030303830666435623530356166613135383031353631323732313537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631323733373537363030303830666435623530353135623135363132373462353736303030393335303530353035303631316261363536356236303031363030313630613031623033383231363135383031353930363132376334353735303831363030313630303136306130316230333136363332313733613866393630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631323739373537363030303830666435623530356166613135383031353631323761623537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631323763313537363030303830666435623530353135623135363132376435353736303031393335303530353035303631316261363536356235303630303039343933353035303530353035363562363030343534363030313630303136306130316230333136383135363562363030333534363034303830353136333133616634303335363065303162383135323630303136303031363061303162303338343831313636303034383330313532393135313931393039323136393136333133616634303335393136303234383038333031393236303030393239313930383239303033303138313833383738303362313538303135363132383364353736303030383066643562353035616631313538303135363132383531353733643630303038303365336436303030666435623530353035303530363030323630303039303534393036313031303030613930303436303031363030313630613031623033313636303031363030313630613031623033313636333431633065316235363034303531383136336666666666666666313636306530316238313532363030343031363030303630343035313830383330333831363030303837383033623135383031353631323861353537363030303830666435623530356166313135383031353631323862393537336436303030383033653364363030306664356235303530353035303530353635623630303735343630303136303031363061303162303331363631323864343631326431663536356236303031363030313630613031623033313631343135363132386537353735303630303035623830333431343631323066393537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306236303234383230313532366134393665373636313663363936343230363636353635363061383162363034343832303135323930353139303831393030333630363430313930666435623630303235343630303435343630303039313832393136303630393136303031363030313630613031623033393038313136393136333166333433343035363065313162393131363631323935353631326431663536356236303430383035313630303136303031363061303162303339333834313636303234383230313532393139303932313636303434383038333031393139303931353238323531383038333033393039313031383135323630363439303931303138323532363032303831303138303531363030313630303136306530316230333136363030313630303136306530316230333139393039343136393339303933313738333532393035313831353139313932393039313832393139303830383338333562363032303833313036313239643635373830353138323532363031663139393039323031393136303230393138323031393130313631323962373536356236303031383336303230303336313031303030613033383031393832353131363831383435313136383038323137383535323530353035303530353035303930353030313931353035303630303036303430353138303833303338313835356166343931353035303364383036303030383131343631326133363537363034303531393135303630316631393630336633643031313638323031363034303532336438323532336436303030363032303834303133653631326133623536356236303630393135303562353039313530393135303831383139303631326163623537363034303531363234363162636436306535316238313532363030343031383038303630323030313832383130333832353238333831383135313831353236303230303139313530383035313930363032303031393038303833383336303030356238333831313031353631326139303537383138313031353138333832303135323630323030313631326137383536356235303530353035303930353039303831303139303630316631363830313536313261626435373830383230333830353136303031383336303230303336313031303030613033313931363831353236303230303139313530356235303932353035303530363034303531383039313033393066643562353038303830363032303031393035313630323038313130313536313261653135373630303038306664356235303531393235303530353039303536356236303033353436303430383035313633333233616234303936306530316238313532363030313630303136306130316230333834383131363630303438333031353239313531393139303932313639313630303039313832393138323931383539313633333233616234303939313630323438303833303139323630383039323931393038323930303330313831383638303362313538303135363132623430353736303030383066643562353035616661313538303135363132623534353733643630303038303365336436303030666435623530353035303530363034303531336436303830383131303135363132623661353736303030383066643562353038303531363032303832303135313630343039303932303135313930393435303930393235303930353036303031363030313630613031623033383331363135363132386239353738323630303136303031363061303162303331363633383331393765663036303430353138313633666666666666666631363630653031623831353236303034303136303030363034303531383038333033383136303030383738303362313538303135363132626361353736303030383066643562353035616631313538303135363132626465353733643630303038303365336436303030666435623530353035303530363030313630303136306130316230333832313631353631326334353537383136303031363030313630613031623033313636333833313937656630363034303531383136336666666666666666313636306530316238313532363030343031363030303630343035313830383330333831363030303837383033623135383031353631326332633537363030303830666435623530356166313135383031353631326334303537336436303030383033653364363030306664356235303530353035303562363030313630303136306130316230333831313631353631326361383537383036303031363030313630613031623033313636333833313937656630363034303531383136336666666666666666313636306530316238313532363030343031363030303630343035313830383330333831363030303837383033623135383031353631326338663537363030303830666435623530356166313135383031353631326361333537336436303030383033653364363030306664356235303530353035303562383336303031363030313630613031623033313636333239303932643065383636303430353138323633666666666666666631363630653031623831353236303034303138303832363030313630303136306130316230333136363030313630303136306130316230333136383135323630323030313931353035303630303036303430353138303833303338313630303038373830336231353830313536313264303035373630303038306664356235303561663131353830313536313264313435373364363030303830336533643630303066643562353035303530353035303530353035303530353635623630303038303534363030313630303136306130316230333136333331343135363132643361353735303332363132306136353635623530333336313230613635366665613236353632376137613732333135383230616461633661363239393639616639653765396439353138366230663531666639653064313163363464666638326636313133323537666439653638353838653634373336663663363334333030303531303030333236303830363034303532363030303830353436303031363030313630613031623033313931363333313739303535363131333937383036313030323536303030333936303030663366653630383036303430353236303034333631303631303033343537363030303335363065303163383036333133616634303335313436313030333935373830363333653638363830613134363130303665353738303633343163306531623531343631303062383537356236303030383066643562333438303135363130303435353736303030383066643562353036313030366336303034383033363033363032303831313031353631303035633537363030303830666435623530333536303031363030313630613031623033313636313030636435363562303035623631303039633630303438303336303336303430383131303135363130303834353736303030383066643562353036303031363030313630613031623033383133353831313639313630323030313335313636313031336235363562363034303830353136303031363030313630613031623033393039323136383235323531393038313930303336303230303139306633356233343830313536313030633435373630303038306664356235303631303036633631303232613536356236303030353436303031363030313630613031623033313633333134363130313139353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030613630323438323031353236393465366637343230366637373665363537323231363062303162363034343832303135323930353139303831393030333630363430313930666435623630303038303534363030313630303136306130316230333139313636303031363030313630613031623033393239303932313639313930393131373930353535363562363030303830353436303031363030313630613031623033313633333134363130313838353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030613630323438323031353236393465366637343230366637373665363537323231363062303162363034343832303135323930353139303831393030333630363430313930666435623630303038333833363034303531363130313938393036313032373935363562363030313630303136306130316230333932383331363831353239313136363032303832303135323630343038303531393138323930303330313930363030306630383031353830313536313031636235373364363030303830336533643630303066643562353039303530383036303031363030313630613031623033313636333264656433323237333436303430353138323633666666666666666631363630653031623831353236303034303136303030363034303531383038333033383138353838383033623135383031353631303230393537363030303830666435623530356166313135383031353631303231643537336436303030383033653364363030306664356235303933393739363530353035303530353035303530353635623630303035343630303136303031363061303162303331363333313436313032373635373630343038303531363234363162636436306535316238313532363032303630303438323031353236303061363032343832303135323639346536663734323036663737366536353732323136306230316236303434383230313532393035313930383139303033363036343031393066643562333366663562363131306463383036313032383738333339303139303536666536303830363034303532333438303135363130303130353736303030383066643562353036303430353136313130646333383033383036313130646338333339383138313031363034303532363034303831313031353631303033333537363030303830666435623530383035313630323039313832303135313630303138303534333336303031363030313630613031623033313939313832313631373930393135353433363030323535363030303830353438323136363030313630303136306130316230333830383631363931383231373833353536323039336138303432383130313630303335353630303438303534393039353136393138363136393139303931313738343535363034303830353137663861626636303737303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303038313532393035313936393739353936383839363630306139363933393538393935393039343835393439313933363338616266363037373933383338333031393339303932393038323930303330313831383638303362313538303135363130306532353736303030383066643562353035616661313538303135363130306636353733643630303038303365336436303030666435623530353035303530363034303531336436303230383131303135363130313063353736303030383066643562353035313630343038303531376630363636316162643030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030383135323930353136303031363030313630613031623033393039323136393136333036363631616264393136303034383038323031393236306130393239303931393038323930303330313831383638303362313538303135363130313639353736303030383066643562353035616661313538303135363130313764353733643630303038303365336436303030666435623530353035303530363034303531336436306130383131303135363130313933353736303030383066643562353036303430383130313531363038303930393130313531393039323530393035303830363130323130353736303430383035313766303863333739613030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303831353236303230363030343832303135323630313736303234383230313532376634653666373432303732363536313634373932303636366637323230373037323666373036663733363136633733303030303030303030303030303030303030363034343832303135323930353139303831393030333630363430313930666435623630303238313034383231303135363130323832353736303430383035313766303863333739613030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303831353236303230363030343832303135323630316636303234383230313532376634313633373436393736363532303737363536393637363837343230336332303331326633323230363537363635373232303737363536393637363837343030363034343832303135323930353139303831393030333630363430313930666435623630303136306666383631363130313536313032663535373630343038303531376630386333373961303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030383135323630323036303034383230313532363030613630323438323031353237663531373536663732373536643230366436393665303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036303434383230313532393035313930383139303033363036343031393066643562363036343630666638363136313131353631303336383537363034303830353137663038633337396130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303038313532363032303630303438323031353236303061363032343832303135323766353137353666373237353664323036643631373830303030303030303030303030303030303030303030303030303030303030303030303030303030303030303630343438323031353239303531393038313930303336303634303139306664356236303038383239303535363036343630666638363136383330323034363030393535363033333630666638363136313036313033386635373630303935343630306135353631303339613536356236303634363033333833303230343630306135353562363030303630303935343131363130343062353736303430383035313766303863333739613030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303831353236303230363030343832303135323630306436303234383230313532376635313735366637323735366432303737363536393637363837343030303030303030303030303030303030303030303030303030303030303030303030303030363034343832303135323930353139303831393030333630363430313930666435623630303036303061353431313631303437633537363034303830353137663038633337396130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303038313532363032303630303438323031353236303064363032343832303135323766343636393665363937333638323037373635363936373638373430303030303030303030303030303030303030303030303030303030303030303030303030303630343438323031353239303531393038313930303336303634303139306664356235303530353035303530353035303530363130633439383036313034393336303030333936303030663366653630383036303430353236303034333631303631303133353537363030303335363065303163383036333762333532393632313136313030616235373830363361656332636361653131363130303666353738303633616563326363616531343631303331353537383036336332343732656638313436313033343835373830363363343061373066383134363130333564353738303633633836653663313531343631303337323537383036336535323235333831313436313033383735373830363366653733333465383134363130333963353736313031333535363562383036333762333532393632313436313032386535373830363338333139376566303134363130326133353738303633393138343061366231343631303262383537383036333939306136363362313436313032636435373830363361646661613732653134363130326532353736313031333535363562383036333364316462336539313136313030666435373830363333643164623365393134363130316634353738303633353035316135656331343631303230393537383036333536633261306131313436313032316535373830363336306639366138663134363130323333353738303633373564663066393931343631303236343537383036333736333962316562313436313032373935373631303133353536356238303633306236326265343531343631303137303537383036333231373361386639313436313031393735373830363332396463623063663134363130316330353738303633326465643332323731343631303164353537383036333363636664363062313436313031646635373562363034303830353136323436316263643630653531623831353236303230363030343832303135323630306236303234383230313532366131333962646430383138356231623162646464393539363061613162363034343832303135323930353139303831393030333630363430313930666435623334383031353631303137633537363030303830666435623530363130313835363130336231353635623630343038303531393138323532353139303831393030333630323030313930663335623334383031353631303161333537363030303830666435623530363130316163363130336237353635623630343038303531393131353135383235323531393038313930303336303230303139306633356233343830313536313031636335373630303038306664356235303631303138353631303430393536356236313031646436313034306635363562303035623334383031353631303165623537363030303830666435623530363130316464363130343636353635623334383031353631303230303537363030303830666435623530363130313835363130346562353635623334383031353631303231353537363030303830666435623530363130316163363130346631353635623334383031353631303232613537363030303830666435623530363130316464363130353364353635623334383031353631303233663537363030303830666435623530363130323438363130353530353635623630343038303531363030313630303136306130316230333930393231363832353235313930383139303033363032303031393066333562333438303135363130323730353736303030383066643562353036313031383536313035356635363562333438303135363130323835353736303030383066643562353036313031383536313035363535363562333438303135363130323961353736303030383066643562353036313031616336313035366235363562333438303135363130326166353736303030383066643562353036313031646436313035393535363562333438303135363130326334353736303030383066643562353036313031383536313035663035363562333438303135363130326439353736303030383066643562353036313031383536313035663635363562333438303135363130326565353736303030383066643562353036313031616336303034383033363033363032303831313031353631303330353537363030303830666435623530333536303031363030313630613031623033313636313035666335363562333438303135363130333231353736303030383066643562353036313031616336303034383033363033363032303831313031353631303333383537363030303830666435623530333536303031363030313630613031623033313636313037336435363562333438303135363130333534353736303030383066643562353036313031646436313037353235363562333438303135363130333639353736303030383066643562353036313032343836313037363535363562333438303135363130333765353736303030383066643562353036313031383536313037373435363562333438303135363130333933353736303030383066643562353036313031646436313037376135363562333438303135363130336138353736303030383066643562353036313032343836313039653235363562363030323534383135363562363030303631303363313631303466313536356231353631303363653537353036303031363130343036353635623630303635343630303735343630303238313032383231313830313536313033656635373530363931353264303263376531346166363830303030303832313135623135363130336666353736303031393235303530353036313034303635363562363030303932353035303530356239303536356236303033353438313536356236303031353436303031363030313630613031623033313633333134363130343563353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030623630323438323031353236613133646239623165343831633138356339393562396436306161316236303434383230313532393035313930383139303033363036343031393066643562363030353830353433343031393035353536356236313034366536313034663135363562363130346165353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030633630323438323031353236623133396264643038313835386438643935633164313935393630613231623630343438323031353239303531393038313930303336303634303139306664356236303034353436303430353136303031363030313630613031623033393039313136393033303331383031353631303866633032393136303030383138313831383538383838663139333530353035303530313538303135363130346538353733643630303038303365336436303030666435623530353635623630306135343831353635623630303036303061353436303036353431303631303530363537353036303031363130343036353635623631303530653631303536623536356236313035316135373530363030303631303430363536356236303039353436303037353436303036353430313130313536313035333235373530363030303631303430363536356235303630303735343630303635343131393035363562363130353435363130396631353635623630303738303534393039313031393035353536356236303031353436303031363030313630613031623033313638313536356236303039353438313536356236303036353438313536356236303030343236303033353431313135383036313035383235373530363030613534363030363534313031353562383036313035393035373530363030613534363030373534313135623930353039303536356236303031353436303031363030313630613031623033313633333134363130356532353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030623630323438323031353236613133646239623165343831633138356339393562396436306161316236303434383230313532393035313930383139303033363036343031393066643562363030343534363030313630303136306130316230333136666635623630303835343831353635623630303535343831353635623630303038303534363034303830353136333861626636303737363065303162383135323930353138333932363030313630303136306130316230333136393136333861626636303737393136303034383038333031393236303230393239313930383239303033303138313836383033623135383031353631303634313537363030303830666435623530356166613135383031353631303635353537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631303636623537363030303830666435623530353136303430383035313633623833653136303536306530316238313532363030313630303136306130316230333836383131363630303438333031353239313531393239333530363030303932393138343136393136336238336531363035393136303234383038323031393236306530393239303931393038323930303330313831383638303362313538303135363130366264353736303030383066643562353035616661313538303135363130366431353733643630303038303365336436303030666435623530353035303530363034303531336436303166313936303166383230313136383230313830363034303532353036306530383131303135363130366636353736303030383066643562353036306130303135313630303335343930393135303432313038303135363130373130353735303630303235343831313035623830313536313037333535373530363030313630303136306130316230333834313636303030393038313532363030623630323035323630343039303230353436306666313631353562393439333530353035303530353635623630306236303230353236303030393038313532363034303930323035343630666631363831353635623631303735613631303966313536356236303036383035343930393130313930353535363562363030343534363030313630303136306130316230333136383135363562363030373534383135363562363130373832363130353662353635623830313536313037393335373530363130373931363130346631353635623135356236313037643635373630343038303531363234363162636436306535316238313532363032303630303438323031353236303066363032343832303135323665346536663734323036333666366336633635363337343631363236633635363038383162363034343832303135323930353139303831393030333630363430313930666435623630303135343630303136303031363061303162303331363333313436313038323335373630343038303531363234363162636436306535316238313532363032303630303438323031353236303062363032343832303135323661313364623962316534383163313835633939356239643630616131623630343438323031353239303531393038313930303336303634303139306664356236303030383036303030393035343930363130313030306139303034363030313630303136306130316230333136363030313630303136306130316230333136363338616266363037373630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631303837323537363030303830666435623530356166613135383031353631303838363537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631303839633537363030303830666435623530353136303430383035313633323839636335653136306532316238313532393035313931393235303630303039313630303136303031363061303162303338343136393136336132373331373834393136303034383038333031393236303230393239313930383239303033303138313836383033623135383031353631303865343537363030303830666435623530356166613135383031353631303866383537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631303930653537363030303830666435623530353136303430383035313633386162663630373736306530316238313532393035313630303136303031363061303162303339303932313639313633386162663630373739313630303438303832303139323630323039323930393139303832393030333031383138363830336231353830313536313039353235373630303038306664356235303561666131353830313536313039363635373364363030303830336533643630303066643562353035303530353036303430353133643630323038313130313536313039376335373630303038306664356235303531363034303830353136333662646463636464363065313162383135323930353139313932353036303031363030313630613031623033383331363931363364376262393962613931333033313931363030343830383330313932363030303932393139303832393030333031383138353838383033623135383031353631303963353537363030303830666435623530356166313135383031353631303964393537336436303030383033653364363030306664356235303530353035303530353035303536356236303030353436303031363030313630613031623033313638313536356236303030343236303033353431313631306133343537363034303830353136323436316263643630653531623831353236303230363030343832303135323630303836303234383230313532363731313961356239613563646131393539363063323162363034343832303135323930353139303831393030333630363430313930666435623630303038303630303039303534393036313031303030613930303436303031363030313630613031623033313636303031363030313630613031623033313636333861626636303737363034303531383136336666666666666666313636306530316238313532363030343031363032303630343035313830383330333831383638303362313538303135363130613833353736303030383066643562353035616661313538303135363130613937353733643630303038303365336436303030666435623530353035303530363034303531336436303230383131303135363130616164353736303030383066643562353035313630343038303531363362383365313630353630653031623831353233333630303438323031383139303532393135313932393335303930393136303030393136303031363030313630613031623033383531363931363362383365313630353931363032343830383230313932363065303932393039313930383239303033303138313836383033623135383031353631306230303537363030303830666435623530356166613135383031353631306231343537336436303030383033653364363030306664356235303530353035303630343035313364363031663139363031663832303131363832303138303630343035323530363065303831313031353631306233393537363030303830666435623530363038303831303135313630613039303931303135313630303235343931393535303931353038313130363130623866353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030633630323438323031353236623465366637343230363536633639363736393632366336353630613031623630343438323031353239303531393038313930303336303634303139306664356236303031363030313630613031623033383231363630303039303831353236303062363032303532363034303930323035343630666631363135363130626564353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030643630323438323031353236633130356231633939353835393165343831643962646431393539363039613162363034343832303135323930353139303831393030333630363430313930666435623530363030313630303136306130316230333136363030303930383135323630306236303230353236303430393032303830353436306666313931363630303131373930353535303930353666656132363536323761376137323331353832303530656133656331326338323538373264313830653332306331393733333734386661653134653131393366346638646336336233303763663431323661333536343733366636633633343330303035313030303332613236353632376137613732333135383230656437356335613736353931616664386665353934626666326132386562373233616430346531323832636337613030393037393939323833363631373430643634373336663663363334333030303531303030333236303830363034303532363030303830353436303031363030313630613031623033313931363333313739303535363130376237383036313030323536303030333936303030663366653630383036303430353233343830313536313030313035373630303038306664356235303630303433363130363130303933353736303030333536306530316338303633343163306531623531313631303036363537383036333431633065316235313436313031366635373830363334353530376139653134363130313737353738303633396161356236633431343631303161353537383036336163333164363232313436313031646535373830363364613033323163643134363130323063353736313030393335363562383036333133373536633866313436313030393835373830363331336166343033353134363130306338353738303633323930393264306531343631303065653537383036333332336162343039313436313031313435373562363030303830666435623631303063363630303438303336303336303430383131303135363130306165353736303030383066643562353036303031363030313630613031623033383133353831313639313630323030313335313636313032363435363562303035623631303063363630303438303336303336303230383131303135363130306465353736303030383066643562353033353630303136303031363061303162303331363631303266383536356236313030633636303034383033363033363032303831313031353631303130343537363030303830666435623530333536303031363030313630613031623033313636313033363635363562363130313361363030343830333630333630323038313130313536313031326135373630303038306664356235303335363030313630303136306130316230333136363130346366353635623630343038303531363030313630303136306130316230333935383631363831353239333835313636303230383530313532393139303933313638323832303135323630363038323031393239303932353239303531393038313930303336303830303139306633356236313030633636313035303835363562363130306336363030343830333630333630343038313130313536313031386435373630303038306664356235303630303136303031363061303162303338313335383131363931363032303031333531363631303535373536356236313031633236303034383033363033363032303831313031353631303162623537363030303830666435623530333536313035656235363562363034303830353136303031363030313630613031623033393039323136383235323531393038313930303336303230303139306633356236313030633636303034383033363033363034303831313031353631303166343537363030303830666435623530363030313630303136306130316230333831333538313136393136303230303133353136363130363132353635623631303231343631303665383536356236303430383035313630323038303832353238333531383138333031353238333531393139323833393239303833303139313835383130313931303238303833383336303030356238333831313031353631303235303537383138313031353138333832303135323630323030313631303233383536356235303530353035303930353030313932353035303530363034303531383039313033393066333562363030303534363030313630303136306130316230333136333331343631303262303537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306136303234383230313532363934653666373432303666373736653635373232313630623031623630343438323031353239303531393038313930303336303634303139306664356236303031363030313630613031623033383038333136363030303930383135323630303136303230353236303430393032303830353439303931313636313032643435376665356236303032303138303534363030313630303136306130316230333139313636303031363030313630613031623033393239303932313639313930393131373930353535303536356236303030353436303031363030313630613031623033313633333134363130333434353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030613630323438323031353236393465366637343230366637373665363537323231363062303162363034343832303135323930353139303831393030333630363430313930666435623630303038303534363030313630303136306130316230333139313636303031363030313630613031623033393239303932313639313930393131373930353535363562363030303534363030313630303136306130316230333136333331343631303362323537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306136303234383230313532363934653666373432303666373736653635373232313630623031623630343438323031353239303531393038313930303336303634303139306664356236303031363030313630613031623033383038323136363030303930383135323630303136303230353236303430393032303830353439303931313636313033643635376665356236303032383035343630303039313930363030303139383130313930383131303631303365633537666535623630303039313832353236303230383038333230393039313031353436303033383038363031353436303031363030313630613031623033393039323136383038353532363030313930393335323630343039303933323039303932303138323930353536303032383035343931393335303833393239303931383131303631303433313537666535623930363030303532363032303630303032303031363030303631303130303061383135343831363030313630303136306130316230333032313931363930383336303031363030313630613031623033313630323137393035353530363030323830353438303631303436613537666535623630303038323831353236303230383038323230383330313630303031393930383130313830353436303031363030313630613031623033313939303831313639303931353539333031393039333535363030313630303136306130316230333935393039353136383535323630303139313832393035323630343038353230383035343832313638313535393138323031383035343832313639303535363030323832303138303534393039313136393035353630303330313932393039323535353035303536356236303031363032303831393035323630303039313832353236303430393039313230383035343931383130313534363030323832303135343630303339303932303135343630303136303031363061303162303339333834313639333931383231363932393039313136393038343536356236303030353436303031363030313630613031623033313633333134363130353534353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030613630323438323031353236393465366637343230366637373665363537323231363062303162363034343832303135323930353139303831393030333630363430313930666435623333666635623630303035343630303136303031363061303162303331363333313436313035613335373630343038303531363234363162636436306535316238313532363032303630303438323031353236303061363032343832303135323639346536663734323036663737366536353732323136306230316236303434383230313532393035313930383139303033363036343031393066643562363030313630303136306130316230333830383331363630303039303831353236303031363032303532363034303930323038303534393039313136363130356337353766653562363030313031383035343630303136303031363061303162303331393136363030313630303136306130316230333932393039323136393139303931313739303535353035363562363030323831383135343831313036313035663835376665356236303030393138323532363032303930393132303031353436303031363030313630613031623033313639303530383135363562363030303534363030313630303136306130316230333136333331343631303635653537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306136303234383230313532363934653666373432303666373736653635373232313630623031623630343438323031353239303531393038313930303336303634303139306664356236303031363030313630613031623033383038333136363030303930383135323630303136303230353236303430393032303830353439303931313631353631303638333537666535623830353436303031363030313630613031623033393238333136363030313630303136306130316230333139393138323136313738323535363030323830353436303033393039333031383339303535363030313833303138313535363030303532376634303537383766613132613832336530663262373633316363343162336261383832386233333231636138313131313166613735636433616133626235616365393039313031383035343933393039323136393231363931393039313137393035353536356236303032353436303430383035313832383135323630323038303834303238323031303139303931353236303630393139303831383031353631303731383537383136303230303136303230383230323830333838333339303139303530356235303931353036303030356238313831313031353631303737643537363030323831383135343831313036313037333335376665356239303630303035323630323036303030323030313630303039303534393036313031303030613930303436303031363030313630613031623033313638333832383135313831313036313037356435376665356236303031363030313630613031623033393039323136363032303932383330323931393039313031393039313031353236303031303136313037316535363562353035303930353666656132363536323761376137323331353832303534383938343938396437663033313562333036616330333935623533626234623138353134303430356639633362376265646136663637303266373735336336343733366636633633343330303035313030303332