Contract Address Details

0x0000000000000000000000000000000000000318

Contract Name
Compensation Fund V1
Creator
Energi Governance Smart Contract
Balance
158.80 NRG
Tokens
Fetching tokens...
Transactions
31 Transactions
Transfers
0 Transfers
Gas Used
14,833,952
Last Balance Update
1987194
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
Compensation Fund V1




Optimization enabled
true
Compiler version
v0.5.16+commit.9c3226ce




Optimization runs
200
EVM Version
petersburg




Verified at
2021-08-20 08:18:32.304087Z

Constructor Arguments

000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000001

Arg [0] (address) : 0x0000000000000000000000000000000000000317
Arg [1] (address) : 0x0000000000000000000000000000000000000302
Arg [2] (uint256) : 1

              

Contract source code

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

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","payable":false,"inputs":[{"type":"address","name":"_proxy","internalType":"address"},{"type":"address","name":"_mnregistry_proxy","internalType":"contractIGovernedProxy"},{"type":"uint256","name":"_superblock_cycle","internalType":"uint256"}]},{"type":"event","name":"BudgetProposal","inputs":[{"type":"uint256","name":"ref_uuid","internalType":"uint256","indexed":true},{"type":"address","name":"proposal","internalType":"contractIBudgetProposal","indexed":false},{"type":"address","name":"payout_address","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"deadline","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Contribution","inputs":[{"type":"address","name":"from","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Payout","inputs":[{"type":"uint256","name":"ref_uuid","internalType":"uint256","indexed":true},{"type":"address","name":"proposal","internalType":"contractIBudgetProposal","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contractIBudgetProposal"}],"name":"active_proposals","inputs":[{"type":"uint256","name":"","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"amount","internalType":"uint256"}],"name":"balance","inputs":[],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[],"name":"contribute","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"destroy","inputs":[{"type":"address","name":"_newImpl","internalType":"contractIGovernedContract"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"amount","internalType":"uint256"}],"name":"getReward","inputs":[{"type":"uint256","name":"_blockNumber","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isSuperblock","inputs":[{"type":"uint256","name":"_blockNumber","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"proposals","internalType":"contractIBudgetProposal[]"}],"name":"listProposals","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"migrate","inputs":[{"type":"address","name":"_oldImpl","internalType":"contractIGovernedContract"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contractIGovernedProxy"}],"name":"mnregistry_proxy","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"proposal_uuid","inputs":[{"type":"address","name":"proposal","internalType":"contractIBudgetProposal"}],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[{"type":"address","name":"proposal","internalType":"contractIBudgetProposal"}],"name":"propose","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"uint256","name":"_ref_uuid","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"proxy","inputs":[],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[],"name":"reward","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"superblock_cycle","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contractIBudgetProposal"}],"name":"uuid_proposal","inputs":[{"type":"uint256","name":"_ref_uuid","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contractStorageTreasuryV1"}],"name":"v1storage","inputs":[],"constant":true}]
            

Deployed ByteCode

0x3630383036303430353233343830313536313030313035373630303038306664356235303630343035313631323866333338303338303631323866333833333938313831303136303430353236303630383131303135363130303333353736303030383066643562353038303531363032303832303135313630343039323833303135313630303038303534363030313630303136306130316230333139313636303031363030313630613031623033383531363137393035353932353139313932393039313631303036623930363130306362353635623630343035313830393130333930363030306630383031353830313536313030383735373364363030303830336533643630303066643562353036303032383035343630303136303031363061303162303331393930383131363630303136303031363061303162303339333834313631373930393135353630303338303534393039313136393138343136393139303931313739303535363030343831393035353830363130306333353766653562353035303530363130306438353635623631303361373830363132353463383333393031393035363562363132343635383036313030653736303030333936303030663366653630383036303430353236303034333631303632303030313039353736303030333536306530316338303633356330393932313531313632303030303937353738303633643566393937383931313632303030303631353738303633643566393937383931343632303030336131353738303633643762623939626131343632303030336366353738303633656335353638383931343632303030336439353738303633666537333334653831343632303030336631353736323030303130393536356238303633356330393932313531343632303030326564353738303633623639656638613831343632303030333162353738303633636165663164356131343632303030333333353738303633636535343934626231343632303030333661353736323030303130393536356238303633323663376562316331313632303030306439353738303633323663376562316331343632303030316531353738303633326430353933303531343632303030323462353738303633343033373664353631343632303030323766353738303633353237383264383631343632303030326162353736323030303130393536356238303632663535643964313436323030303134363537383036333065663334373435313436323030303137663537383036333163346237373462313436323030303161393537383036333232386362373333313436323030303164373537356236303430383035313632343631626364363065353162383135323630323036303034383230313532363030643630323438323031353236633133396264643038316364643563316331626463396431393539363039613162363034343832303135323930353139303831393030333630363430313930666435623334383031353632303030313533353736303030383066643562353036323030303137643630303438303336303336303230383131303135363230303031366335373630303038306664356235303335363030313630303136306130316230333136363230303034303935363562303035623334383031353632303030313863353736303030383066643562353036323030303139373632303030343663353635623630343038303531393138323532353139303831393030333630323030313930663335623334383031353632303030316236353736303030383066643562353036323030303139373630303438303336303336303230383131303135363230303031636635373630303038306664356235303335363230303034373235363562363230303031376436323030303439373536356233343830313536323030303165653537363030303830666435623530363230303031663936323030303534323536356236303430383035313630323038303832353238333531383138333031353238333531393139323833393239303833303139313835383130313931303238303833383336303030356238333831313031353632303030323337353738313831303135313833383230313532363032303031363230303032316435363562353035303530353039303530303139323530353035303630343035313830393130333930663335623334383031353632303030323538353736303030383066643562353036323030303236333632303030363630353635623630343038303531363030313630303136306130316230333930393231363832353235313930383139303033363032303031393066333562363230303032363336303034383033363033363036303831313031353632303030323937353736303030383066643562353038303335393036303230383130313335393036303430303133353632303030363666353635623334383031353632303030326238353736303030383066643562353036323030303264393630303438303336303336303230383131303135363230303032643135373630303038306664356235303335363230303062656335363562363034303830353139313135313538323532353139303831393030333630323030313930663335623334383031353632303030326661353736303030383066643562353036323030303236333630303438303336303336303230383131303135363230303033313335373630303038306664356235303335363230303063306635363562333438303135363230303033323835373630303038306664356235303632303030313937363230303063393035363562333438303135363230303033343035373630303038306664356235303632303030313937363030343830333630333630323038313130313536323030303335393537363030303830666435623530333536303031363030313630613031623033313636323030306339353536356233343830313536323030303337373537363030303830666435623530363230303031376436303034383033363033363032303831313031353632303030333930353736303030383066643562353033353630303136303031363061303162303331363632303030636537353635623334383031353632303030336165353736303030383066643562353036323030303236333630303438303336303336303230383131303135363230303033633735373630303038306664356235303335363230303064336335363562363230303031376436323030306435613536356233343830313536323030303365363537363030303830666435623530363230303032363336323030306461663536356233343830313536323030303366653537363030303830666435623530363230303032363336323030306462653536356236303030353436303031363030313630613031623033313633333134363230303034353535373630343038303531363234363162636436306535316238313532363032303630303438323031353236303039363032343832303135323638346536663734323037303732366637383739363062383162363034343832303135323930353139303831393030333630363430313930666435623632303030343630383136323030306463643536356238303630303136303031363061303162303331366666356236303034353438313536356236303030363230303034376638323632303030626563353635623135363230303034393235373530363932366636613866346536333830333030303030303562393139303530353635623630303135343135363230303034643735373630343038303531363234363162636436306535316238313532363032303630303438323031353236303037363032343832303135323636353236353635366537343732373936306338316236303434383230313532393035313930383139303033363036343031393066643562363030313830353536323030303465353632303031316366353635623630303036323030303466323832363230303065333835363562393035303330333138303135383031353930363230303035303635373530363030303832313135623135363230303035333835373631303365383831383331313135363230303035326135373832383236313033653830323831363230303035323635376665356230343930353035623632303030353336383138353632303031303631353635623530356235303530363030303630303135353530353635623630343038303531363036343830383235323631306361303832303139303932353236303630393138323931393036303230383230313631306338303830333838333339303139303530353039303530363030303830356236303634383131303135363230303035646235373630303036303035383236303634383131303632303030353838353766653562303135343630303136303031363061303162303331363930353038303135363230303035643135373830383438343830363030313031393535303831353138313130363230303035623035376665356236303230303236303230303130313930363030313630303136306130316230333136393038313630303136303031363061303162303331363831353235303530356235303630303130313632303030353665353635623530383036303430353139303830383235323830363032303032363032303031383230313630343035323830313536323030303630373537383136303230303136303230383230323830333838333339303139303530356235303932353036303030356238313831313031353632303030363539353738323831383135313831313036323030303632333537666535623630323030323630323030313031353138343832383135313831313036323030303633383537666535623630303136303031363061303162303339303932313636303230393238333032393139303931303139303931303135323630303130313632303030363064353635623530353035303562393035363562363030323534363030313630303136306130316230333136383135363562363030303630303135343630303031343632303030366233353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030373630323438323031353236363532363536353665373437323739363063383162363034343832303135323930353139303831393030333630363430313930666435623630303138303535333436383035366263373565326436333130303030303134363230303037303335373630343038303531363234363162636436306535316238313532363032303630303438323031353236303062363032343832303135323661343936653736363136633639363432303636363536353630613831623630343438323031353239303531393038313930303336303634303139306664356236383035366263373565326436333130303030303834313031353632303030373535353736303430383035313632343631626364363065353162383135323630323036303034383230313532363031303630323438323031353236663135316264626338316364623538356231623038313835623562646435623964363038323162363034343832303135323930353139303831393030333630363430313930666435623639323666366138663465363338303330303030303038343131313536323030303761383537363034303830353136323436316263643630653531623831353236303230363030343832303135323630313036303234383230313532366631353162646263383162313835633939643934383138356235626464356239643630383231623630343438323031353239303531393038313930303336303634303139306664356236323132373530303832313031353632303030376634353736303430383035313632343631626364363065353162383135323630323036303034383230313532363031303630323438323031353236663135316264626338316364623538356231623038316331393563396135626439363038323162363034343832303135323930353139303831393030333630363430313930666435623632323738643030383231313135363230303038343035373630343038303531363234363162636436306535316238313532363032303630303438323031353236303130363032343832303135323666313531626462633831623138356339396439343831633139356339613562643936303832316236303434383230313532393035313930383139303033363036343031393066643562363030323534363030313630303136306130316230333136363030303632303030383538363230303131616135363562393035303630303036303031363030313630613031623033313638323630303136303031363061303162303331363633356330393932313538373630343035313832363366666666666666663136363065303162383135323630303430313830383238313532363032303031393135303530363032303630343035313830383330333831383638303362313538303135363230303038616135373630303038306664356235303561666131353830313536323030303862663537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353632303030386436353736303030383066643562353035313630303136303031363061303162303331363134363230303039323235373630343038303531363234363162636436306535316238313532363032303630303438323031353236303062363032343832303135323661353535353439343432303639366532303735373336353630613831623630343438323031353239303531393038313930303336303634303139306664356236303030356236303634383131303135363230303061303535373630303036303035383236303634383131303632303030393366353766653562303135343630303136303031363061303162303331363134313536323030303966633537363030333630303039303534393036313031303030613930303436303031363030313630613031623033313638323837383938383630343035313632303030393739393036323030313230303536356236303031363030313630613031623033393538363136383135323933393039343136363032303834303135323630343038303834303139323930393235323630363038333031353236303830383230313932393039323532393035313930383139303033363061303031393036303030663038303135383031353632303030396335353733643630303038303365336436303030666435623530393335303833363030353832363036343831313036323030303964373537666535623031383035343630303136303031363061303162303331393136363030313630303136306130316230333932393039323136393139303931313739303535363230303061303535363562363030313031363230303039323535363562353036303031363030313630613031623033383331363632303030613632353736303430383035313632343631626364363065353162383135323630323036303034383230313532363031393630323438323031353237663534366636663230366436313665373932303631363337343639373636353230373037323666373036663733363136633733303030303030303030303030303036303434383230313532393035313930383139303033363036343031393066643562383236303031363030313630613031623033313636333264656433323237333436303430353138323633666666666666666631363630653031623831353236303034303136303030363034303531383038333033383138353838383033623135383031353632303030613965353736303030383066643562353035616631313538303135363230303061623335373364363030303830336533643630303066643562353035303630343038303531363232653765353536306532316238313532363030343831303138613930353236303031363030313630613031623033383838313136363032343833303135323931353139313837313639343530363262396639353439333530363034343830383230313933353036303030393239313832393030333031383138333837383033623135383031353632303030623037353736303030383066643562353035616631313538303135363230303062316335373364363030303830336533643630303066643562353035303530353038343766613934626566613363653138313937343133306665333665383534613238326337306662373565346465636234326266656364656362643666383866306635643834383338393837363030313630303136306130316230333136363332396463623063663630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353632303030623766353736303030383066643562353035616661313538303135363230303062393435373364363030303830336533643630303066643562353035303530353036303430353133643630323038313130313536323030306261623537363030303830666435623530353136303430383035313630303136303031363061303162303339353836313638313532393339303934313636303230383430313532383238343031393139303931353236303630383230313532393035313930383139303033363038303031393061323530353036303030363030313535393339323530353035303536356236303030363030343534383238313632303030626661353766653562303631353830313536323030306330393537353036303030383231313562393239313530353035363562363030323534363034303830353136333563303939323135363065303162383135323630303438313031383439303532393035313630303039323630303136303031363061303162303331363931363335633039393231353931363032343830383330313932363032303932393139303832393030333031383138363830336231353830313536323030306335633537363030303830666435623530356166613135383031353632303030633731353733643630303038303365336436303030666435623530353035303530363034303531336436303230383131303135363230303063383835373630303038306664356235303531393239313530353035363562333033313930353635623630303235343630343038303531363336353737386561643630653131623831353236303031363030313630613031623033383438313136363030343833303135323931353136303030393339323930393231363931363363616566316435613931363032343830383230313932363032303932393039313930383239303033303138313836383033623135383031353632303030633563353736303030383066643562363030303534363030313630303136306130316230333136333331343632303030643333353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030393630323438323031353236383465366637343230373037323666373837393630623831623630343438323031353239303531393038313930303336303634303139306664356236323030306433393831356235303536356236303035383136303634383131303632303030643461353766653562303135343630303136303031363061303162303331363930353038313536356233343135363230303064616435373766346431353464346161653231366265643664303932366462373763303064663262353763366235626134656565303537373564653230666163656465336137623632303030643863363230303131616135363562363034303830353136303031363030313630613031623033393039323136383235323334363032303833303135323830353139313832393030333031393061313562353635623630303035343630303136303031363061303162303331363831353635623630303335343630303136303031363061303162303331363831353635623630303235343630343038303531363331336166343033353630653031623831353236303031363030313630613031623033383438313136363030343833303135323931353139313930393231363931363331336166343033353931363032343830383330313932363030303932393139303832393030333031383138333837383033623135383031353632303030653163353736303030383066643562353035616631313538303135363230303065333135373364363030303830336533643630303066643562353035303530353035303536356236303030383038303830383038303830356236303634383131303135363230303130353635373630303538313630363438313130363230303065353935376665356230313534363030313630303136306130316230333136393535303835313536323030313034643537383536303031363030313630613031623033313636333362326131623134363034303531383136336666666666666666313636306530316238313532363030343031363038303630343035313830383330333831383638303362313538303135363230303065613735373630303038306664356235303561666131353830313536323030306562633537336436303030383033653364363030306664356235303530353035303630343035313364363038303831313031353632303030656433353736303030383066643562353038303531363032303832303135313630343038333031353136303630393039333031353139313937353039353530393039333530393135303833313536323030306664333537383131353632303030663561353739353831303139353835383838323630363438313130363230303066313035376665356236303230303230313531363030313630303136306130316230333930393131363930353238343838383236303634383131303632303030663330353766653562363032303032303135313630323030313831383135323530353038313838383236303634383131303632303030663462353766653562363032303032303135313630343030313532363230303066636435363562383536303031363030313630613031623033313636333833313937656630363034303531383136336666666666666666313636306530316238313532363030343031363030303630343035313830383330333831363030303837383033623135383031353632303030663936353736303030383066643562353035616631313538303135363230303066616235373364363030303830336533643630303066643562353035303530353036303035383136303634383131303632303030666264353766653562303138303534363030313630303136306130316230333139313639303535356236323030313034643536356238323135363230303130346435373835363030313630303136306130316230333136363365353232353338313630343035313831363366666666666666663136363065303162383135323630303430313630303036303430353138303833303338313630303038373830336231353830313536323030313031363537363030303830666435623530356166313135383031353632303031303262353733643630303038303365336436303030666435623530353035303530363030353831363036343831313036323030313033643537666535623031383035343630303136303031363061303162303331393136393035353562363030313031363230303065343135363562353035303530353035303530393139303530353635623630303038303562363036343831313031353632303031316134353738323831363036343831313036323030313037633537666535623630323030323031353135313931353036303031363030313630613031623033383231363135363230303131396235373630303036313033653838353835383436303634383131303632303031306137353766653562363032303032303135313630343030313531303238313632303031306239353766653562303439303530383338323630363438313130363230303130633935376665356236303230303230313531363034303031353138313131313536323030313064633537666535623832363030313630303136306130316230333136363331306361633861353832363034303531383236336666666666666666313636306530316238313532363030343031363030303630343035313830383330333831383538383830336231353830313536323030313131383537363030303830666435623530356166313135383031353632303031313264353733643630303038303365336436303030666435623530353035303530353038333832363036343831313036323030313133663537666535623630323030323031353136303230303135313766356637333431613535326165326434353262303731393137313034633035666261633336363339333661363962653736386130356334303630353035366537643834383336303430353138303833363030313630303136306130316230333136363030313630303136306130316230333136383135323630323030313832383135323630323030313932353035303530363034303531383039313033393061323530356236303031303136323030313036353536356235303530353035303536356236303030383035343630303136303031363061303162303331363333313431353632303031316337353735303332363230303036356435363562353033333632303030363564353635623630343035313830363130633830303136303430353238303630363439303562363230303131653936323030313230653536356238313532363032303031393036303031393030333930383136323030313164663537393035303530393035363562363131316638383036323030313233393833333930313930353635623630343035313830363036303031363034303532383036303030363030313630303136306130316230333136383135323630323030313630303038313532363032303031363030303831353235303930353666653630383036303430353233343830313536313030313035373630303038306664356235303630343035313631313166383338303338303631313166383833333938313831303136303430353236306130383131303135363130303333353736303030383066643562353038303531363032303830383330313531363034303830383530313531363036303836303135313630383039303936303135313630303138303534333336303031363030313630613031623033313939313832313631373930393135353433363030323535363030303830353438323136363030313630303136306130316230333830386131363931383231373833353534323835303136303033353536303034383035343930393431363930383831363137383335353835353137663861626636303737303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303038313532393535313938393939363938393439373933393538613935363030373935383839353863393539343835393439303933363338616266363037373933383238343031393339303932383239303033303138313836383033623135383031353631303065633537363030303830666435623530356166613135383031353631303130303537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631303131363537363030303830666435623530353136303430383035313766303636363161626430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303831353239303531363030313630303136306130316230333930393231363931363330363636316162643931363030343830383230313932363061303932393039313930383239303033303138313836383033623135383031353631303137333537363030303830666435623530356166613135383031353631303138373537336436303030383033653364363030306664356235303530353035303630343035313364363061303831313031353631303139643537363030303830666435623530363034303831303135313630383039303931303135313930393235303930353038303631303231613537363034303830353137663038633337396130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303038313532363032303630303438323031353236303137363032343832303135323766346536663734323037323635363136343739323036363666373232303730373236663730366637333631366337333030303030303030303030303030303030303630343438323031353239303531393038313930303336303634303139306664356236303032383130343832313031353631303238633537363034303830353137663038633337396130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303038313532363032303630303438323031353236303166363032343832303135323766343136333734363937363635323037373635363936373638373432303363323033313266333232303635373636353732323037373635363936373638373430303630343438323031353239303531393038313930303336303634303139306664356236303031363066663836313631303135363130326666353736303430383035313766303863333739613030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303831353236303230363030343832303135323630306136303234383230313532376635313735366637323735366432303664363936653030303030303030303030303030303030303030303030303030303030303030303030303030303030303030363034343832303135323930353139303831393030333630363430313930666435623630363436306666383631363131313536313033373235373630343038303531376630386333373961303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030383135323630323036303034383230313532363030613630323438323031353237663531373536663732373536643230366436313738303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036303434383230313532393035313930383139303033363036343031393066643562363030383832393035353630363436306666383631363833303230343630303935353630333336306666383631363130363130333939353736303039353436303061353536313033613435363562363036343630333338333032303436303061353535623630303036303039353431313631303431353537363034303830353137663038633337396130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303038313532363032303630303438323031353236303064363032343832303135323766353137353666373237353664323037373635363936373638373430303030303030303030303030303030303030303030303030303030303030303030303030303630343438323031353239303531393038313930303336303634303139306664356236303030363030613534313136313034383635373630343038303531376630386333373961303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030383135323630323036303034383230313532363030643630323438323031353237663436363936653639373336383230373736353639363736383734303030303030303030303030303030303030303030303030303030303030303030303030303036303434383230313532393035313930383139303033363036343031393066643562353035303530363030653935393039353535353035303530363030643535353035303530363130643531383036313034613736303030333936303030663366653630383036303430353236303034333631303631303139633537363030303335363065303163383036333736333962316562313136313030656335373830363361656332636361653131363130303861353738303633633430613730663831313631303036343537383036336334306137306638313436313034343635373830363363383665366331353134363130343562353738303633653532323533383131343631303437303537383036336665373333346538313436313034383535373631303139633536356238303633616563326363616531343631303365393537383036336264346331663339313436313034316335373830363363323437326566383134363130343331353736313031396335363562383036333931383430613662313136313030633635373830363339313834306136623134363130333737353738303633393930613636336231343631303338633537383036333964356536633964313436313033613135373830363361646661613732653134363130336236353736313031396335363562383036333736333962316562313436313033333835373830363337623335323936323134363130333464353738303633383331393765663031343631303336323537363130313963353635623830363333643164623365393131363130313539353738303633353035316135656331313631303133333537383036333530353161356563313436313032623435373830363335366332613061313134363130326464353738303633363066393661386631343631303266323537383036333735646630663939313436313033323335373631303139633536356238303633336431646233653931343631303237353537383036333463616664666232313436313032386135373830363335303438383164663134363130323966353736313031396335363562383036333062363262653435313436313031643735373830363331306361633861353134363130316665353738303633323964636230636631343631303230383537383036333264656433323237313436313032316435373830363333623261316231343134363130323235353738303633336363666436306231343631303236303537356236303430383035313632343631626364363065353162383135323630323036303034383230313532363030623630323438323031353236613133396264643038313835623162316264646439353936306161316236303434383230313532393035313930383139303033363036343031393066643562333438303135363130316533353736303030383066643562353036313031656336313034396135363562363034303830353139313832353235313930383139303033363032303031393066333562363130323036363130346130353635623030356233343830313536313032313435373630303038306664356235303631303165633631303462373536356236313032303636313034626435363562333438303135363130323331353736303030383066643562353036313032336136313035313435363562363034303830353139343835353239323135313536303230383530313532393031353135383338333031353236303630383330313532353139303831393030333630383030313930663335623334383031353631303236633537363030303830666435623530363130323036363130353463353635623334383031353631303238313537363030303830666435623530363130316563363130356431353635623334383031353631303239363537363030303830666435623530363130316563363130356437353635623334383031353631303261623537363030303830666435623530363130316563363130356464353635623334383031353631303263303537363030303830666435623530363130326339363130356533353635623630343038303531393131353135383235323531393038313930303336303230303139306633356233343830313536313032653935373630303038306664356235303631303230363631303633303536356233343830313536313032666535373630303038306664356235303631303330373631303634333536356236303430383035313630303136303031363061303162303339303932313638323532353139303831393030333630323030313930663335623334383031353631303332663537363030303830666435623530363130316563363130363532353635623334383031353631303334343537363030303830666435623530363130316563363130363538353635623334383031353631303335393537363030303830666435623530363130326339363130363565353635623334383031353631303336653537363030303830666435623530363130323036363130363838353635623334383031353631303338333537363030303830666435623530363130316563363130366533353635623334383031353631303339383537363030303830666435623530363130316563363130366539353635623334383031353631303361643537363030303830666435623530363130333037363130366566353635623334383031353631303363323537363030303830666435623530363130326339363030343830333630333630323038313130313536313033643935373630303038306664356235303335363030313630303136306130316230333136363130366665353635623334383031353631303366353537363030303830666435623530363130326339363030343830333630333630323038313130313536313034306335373630303038306664356235303335363030313630303136306130316230333136363130383366353635623334383031353631303432383537363030303830666435623530363130316563363130383534353635623334383031353631303433643537363030303830666435623530363130323036363130383561353635623334383031353631303435323537363030303830666435623530363130333037363130383664353635623334383031353631303436373537363030303830666435623530363130316563363130383763353635623334383031353631303437633537363030303830666435623530363130323036363130383832353635623334383031353631303439313537363030303830666435623530363130333037363130616561353635623630303235343831353635623630306338303534333430313930383139303535363030643534313031353631303462353537666535623536356236303033353438313536356236303031353436303031363030313630613031623033313633333134363130353061353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030623630323438323031353236613133646239623165343831633138356339393562396436306161316236303434383230313532393035313930383139303033363036343031393066643562363030353830353433343031393035353536356236303065353436303030383038303631303532333631303565333536356239323530363130353264363130363565353635623931353036303064353436303063353431313135363130353364353766653562363030633534363030643534303339303530393039313932393335363562363130353534363130356533353635623631303539343537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306336303234383230313532366231333962646430383138353864386439356331643139353936306132316236303434383230313532393035313930383139303033363036343031393066643562363030343534363034303531363030313630303136306130316230333930393131363930333033313830313536313038666330323931363030303831383138313835383838386631393335303530353035303135383031353631303563653537336436303030383033653364363030306664356235303536356236303061353438313536356236303064353438313536356236303063353438313536356236303030363030613534363030363534313036313035663835373530363030313631303632643536356236313036303036313036356535363562363130363063353735303630303036313036326435363562363030393534363030373534363030363534303131303135363130363234353735303630303036313036326435363562353036303037353436303036353431313562393035363562363130363338363130616639353635623630303738303534393039313031393035353536356236303031353436303031363030313630613031623033313638313536356236303039353438313536356236303036353438313536356236303030343236303033353431313135383036313036373535373530363030613534363030363534313031353562383036313036383335373530363030613534363030373534313135623930353039303536356236303031353436303031363030313630613031623033313633333134363130366435353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030623630323438323031353236613133646239623165343831633138356339393562396436306161316236303434383230313532393035313930383139303033363036343031393066643562363030343534363030313630303136306130316230333136666635623630303835343831353635623630303535343831353635623630303435343630303136303031363061303162303331363930353635623630303038303534363034303830353136333861626636303737363065303162383135323930353138333932363030313630303136306130316230333136393136333861626636303737393136303034383038333031393236303230393239313930383239303033303138313836383033623135383031353631303734333537363030303830666435623530356166613135383031353631303735373537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631303736643537363030303830666435623530353136303430383035313633623833653136303536306530316238313532363030313630303136306130316230333836383131363630303438333031353239313531393239333530363030303932393138343136393136336238336531363035393136303234383038323031393236306530393239303931393038323930303330313831383638303362313538303135363130376266353736303030383066643562353035616661313538303135363130376433353733643630303038303365336436303030666435623530353035303530363034303531336436303166313936303166383230313136383230313830363034303532353036306530383131303135363130376638353736303030383066643562353036306130303135313630303335343930393135303432313038303135363130383132353735303630303235343831313035623830313536313038333735373530363030313630303136306130316230333834313636303030393038313532363030623630323035323630343039303230353436306666313631353562393439333530353035303530353635623630306236303230353236303030393038313532363034303930323035343630666631363831353635623630306535343831353635623631303836323631306166393536356236303036383035343930393130313930353535363562363030343534363030313630303136306130316230333136383135363562363030373534383135363562363130383861363130363565353635623830313536313038396235373530363130383939363130356533353635623135356236313038646535373630343038303531363234363162636436306535316238313532363032303630303438323031353236303066363032343832303135323665346536663734323036333666366336633635363337343631363236633635363038383162363034343832303135323930353139303831393030333630363430313930666435623630303135343630303136303031363061303162303331363333313436313039326235373630343038303531363234363162636436306535316238313532363032303630303438323031353236303062363032343832303135323661313364623962316534383163313835633939356239643630616131623630343438323031353239303531393038313930303336303634303139306664356236303030383036303030393035343930363130313030306139303034363030313630303136306130316230333136363030313630303136306130316230333136363338616266363037373630343035313831363366666666666666663136363065303162383135323630303430313630323036303430353138303833303338313836383033623135383031353631303937613537363030303830666435623530356166613135383031353631303938653537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631303961343537363030303830666435623530353136303430383035313633323839636335653136306532316238313532393035313931393235303630303039313630303136303031363061303162303338343136393136336132373331373834393136303034383038333031393236303230393239313930383239303033303138313836383033623135383031353631303965633537363030303830666435623530356166613135383031353631306130303537336436303030383033653364363030306664356235303530353035303630343035313364363032303831313031353631306131363537363030303830666435623530353136303430383035313633386162663630373736306530316238313532393035313630303136303031363061303162303339303932313639313633386162663630373739313630303438303832303139323630323039323930393139303832393030333031383138363830336231353830313536313061356135373630303038306664356235303561666131353830313536313061366535373364363030303830336533643630303066643562353035303530353036303430353133643630323038313130313536313061383435373630303038306664356235303531363034303830353136333662646463636464363065313162383135323930353139313932353036303031363030313630613031623033383331363931363364376262393962613931333033313931363030343830383330313932363030303932393139303832393030333031383138353838383033623135383031353631306163643537363030303830666435623530356166313135383031353631306165313537336436303030383033653364363030306664356235303530353035303530353035303536356236303030353436303031363030313630613031623033313638313536356236303030343236303033353431313631306233633537363034303830353136323436316263643630653531623831353236303230363030343832303135323630303836303234383230313532363731313961356239613563646131393539363063323162363034343832303135323930353139303831393030333630363430313930666435623630303038303630303039303534393036313031303030613930303436303031363030313630613031623033313636303031363030313630613031623033313636333861626636303737363034303531383136336666666666666666313636306530316238313532363030343031363032303630343035313830383330333831383638303362313538303135363130623862353736303030383066643562353035616661313538303135363130623966353733643630303038303365336436303030666435623530353035303530363034303531336436303230383131303135363130626235353736303030383066643562353035313630343038303531363362383365313630353630653031623831353233333630303438323031383139303532393135313932393335303930393136303030393136303031363030313630613031623033383531363931363362383365313630353931363032343830383230313932363065303932393039313930383239303033303138313836383033623135383031353631306330383537363030303830666435623530356166613135383031353631306331633537336436303030383033653364363030306664356235303530353035303630343035313364363031663139363031663832303131363832303138303630343035323530363065303831313031353631306334313537363030303830666435623530363038303831303135313630613039303931303135313630303235343931393535303931353038313130363130633937353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030633630323438323031353236623465366637343230363536633639363736393632366336353630613031623630343438323031353239303531393038313930303336303634303139306664356236303031363030313630613031623033383231363630303039303831353236303062363032303532363034303930323035343630666631363135363130636635353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030643630323438323031353236633130356231633939353835393165343831643962646431393539363039613162363034343832303135323930353139303831393030333630363430313930666435623530363030313630303136306130316230333136363030303930383135323630306236303230353236303430393032303830353436306666313931363630303131373930353535303930353666656132363536323761376137323331353832306262643231313539616364386634353538326463313361323238386336616436303033663839373538343264353062376161353732306465666530303938326636343733366636633633343330303035313030303332613236353632376137613732333135383230326435663731613564353033643331363033386464343833383236623334646431333336663037313964663231363263393664626530663839376566666639393634373336663663363334333030303531303030333236303830363034303532363030303830353436303031363030313630613031623033313931363333313739303535363130333832383036313030323536303030333936303030663366653630383036303430353233343830313536313030313035373630303038306664356235303630303433363130363130303631353736303030333536306530316338303632623966393534313436313030363635373830363331336166343033353134363130303934353738303633336339376632393431343631303062613537383036333431633065316235313436313030653035373830363335633039393231353134363130306538353738303633636165663164356131343631303132313537356236303030383066643562363130303932363030343830333630333630343038313130313536313030376335373630303038306664356235303830333539303630323030313335363030313630303136306130316230333136363130313539353635623030356236313030393236303034383033363033363032303831313031353631303061613537363030303830666435623530333536303031363030313630613031623033313636313031646535363562363130303932363030343830333630333630323038313130313536313030643035373630303038306664356235303335363030313630303136306130316230333136363130323463353635623631303039323631303264313536356236313031303536303034383033363033363032303831313031353631303066653537363030303830666435623530333536313033323035363562363034303830353136303031363030313630613031623033393039323136383235323531393038313930303336303230303139306633356236313031343736303034383033363033363032303831313031353631303133373537363030303830666435623530333536303031363030313630613031623033313636313033336235363562363034303830353139313832353235313930383139303033363032303031393066333562363030303534363030313630303136306130316230333136333331343631303161353537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306136303234383230313532363934653666373432303666373736653635373232313630623031623630343438323031353239303531393038313930303336303634303139306664356236303030383238313532363030313630323039303831353236303430383038333230383035343630303136303031363061303162303339303935313636303031363030313630613031623033313939303935313638353137393035353932383235323630303239303532323035353536356236303030353436303031363030313630613031623033313633333134363130323261353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030613630323438323031353236393465366637343230366637373665363537323231363062303162363034343832303135323930353139303831393030333630363430313930666435623630303038303534363030313630303136306130316230333139313636303031363030313630613031623033393239303932313639313930393131373930353535363562363030303534363030313630303136306130316230333136333331343631303239383537363034303830353136323436316263643630653531623831353236303230363030343832303135323630306136303234383230313532363934653666373432303666373736653635373232313630623031623630343438323031353239303531393038313930303336303634303139306664356236303031363030313630613031623033313636303030393038313532363030323630323039303831353236303430383038333230383035343930383439303535383335323630303139303931353239303230383035343630303136303031363061303162303331393136393035353536356236303030353436303031363030313630613031623033313633333134363130333164353736303430383035313632343631626364363065353162383135323630323036303034383230313532363030613630323438323031353236393465366637343230366637373665363537323231363062303162363034343832303135323930353139303831393030333630363430313930666435623333666635623630303136303230353236303030393038313532363034303930323035343630303136303031363061303162303331363831353635623630303236303230353236303030393038313532363034303930323035343831353666656132363536323761376137323331353832303861393239393764373739616263303664373363333462326536343636653462366461633238303161656163393136653232616331653938616362633363616236343733366636633633343330303035313030303332