POA is joining the xDai ecosystem, and token holders can now swap POA for STAKE on the xDai chain! More info and instructions here

Contract Address Details

0x0C31e682d401c465fdD05e40cE7149F8497B18E5

Contract Name
PoaMania
Creator
0x78bccb–fd6e91 at 0x21466d–00bb8f
Balance
0 POA ( )
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
24619085
Contract name:
PoaMania




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




EVM Version
petersburg




Verified at
2020-04-03 18:09:27.615740Z

Contract source code

// File: @openzeppelin/upgrades/contracts/Initializable.sol
pragma solidity >=0.4.24 <0.7.0;
/**
* @title Initializable
*
* @dev Helper contract to support initializer functions. To use it, replace
* the constructor with a function that has the `initializer` modifier.
* WARNING: Unlike constructors, initializer functions must be manually
* invoked. This applies both to deploying an Initializable contract, as well
* as extending an Initializable contract via inheritance.
* WARNING: When used with inheritance, manual care must be taken to not invoke
* a parent initializer twice, or ensure that all initializers are idempotent,
* because this is not dealt with automatically as with constructors.
*/
contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private initializing;
/**
* @dev Modifier to use in the initializer function of a contract.
*/
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
/// @dev Returns true if and only if the function is running in the constructor
function isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
address self = address(this);
uint256 cs;
assembly { cs := extcodesize(self) }
return cs == 0;
}
// Reserved storage space to allow for layout changes in the future.
uint256[50] private ______gap;
}
// File: @openzeppelin/contracts-ethereum-package/contracts/GSN/Context.sol
pragma solidity ^0.5.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
contract Context is Initializable {
// Empty internal constructor, to prevent people from mistakenly deploying
// an instance of this contract, which should be used via inheritance.
constructor () internal { }
// solhint-disable-previous-line no-empty-blocks
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
// File: @openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol
pragma solidity ^0.5.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be aplied to your functions to restrict their use to
* the owner.
*/
contract Ownable is Initializable, Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function initialize(address sender) public initializer {
_owner = sender;
emit OwnershipTransferred(address(0), _owner);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* > Note: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[50] private ______gap;
}
// File: @openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol
pragma solidity ^0.5.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* _Available since v2.4.0._
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
// File: contracts/IPOSDAORandom.sol
pragma solidity ^0.5.16;
interface IPOSDAORandom {
function collectRoundLength() external view returns(uint256);
function currentSeed() external view returns(uint256);
function isCommitPhase() external view returns(bool);
}
// File: contracts/Random.sol
pragma solidity ^0.5.16;
contract Random {
IPOSDAORandom public posdaoRandomContract;
uint256 private _seed;
uint256 private _seedLastBlock;
uint256 randomUpdateInterval;
function _init(address _randomContract) internal {
require(_randomContract != address(0), "Random/contract-zero");
posdaoRandomContract = IPOSDAORandom(_randomContract);
_seed = posdaoRandomContract.currentSeed();
_seedLastBlock = block.number;
randomUpdateInterval = posdaoRandomContract.collectRoundLength();
require(randomUpdateInterval != 0, "Random/interval-zero");
}
function _useSeed() internal returns (uint256) {
require(_wasSeedUpdated(), "Random/seed-not-updated");
require(posdaoRandomContract.isCommitPhase(), "Random/not-commit-phase");
return _seed;
}
function _wasSeedUpdated() private returns (bool) {
if (block.number - _seedLastBlock <= randomUpdateInterval) {
return false;
}
randomUpdateInterval = posdaoRandomContract.collectRoundLength();
uint256 remoteSeed = posdaoRandomContract.currentSeed();
if (remoteSeed != _seed) {
_seed = remoteSeed;
_seedLastBlock = block.number;
return true;
}
return false;
}
function getNewRandom(uint256 _value) public pure returns (uint256) {
return uint256(keccak256(abi.encodePacked(_value)));
}
}
// File: @kleros/kleros/contracts/data-structures/SortitionSumTreeFactory.sol
/**
* @reviewers: [@clesaege, @unknownunknown1, @ferittuncer]
* @auditors: []
* @bounties: [<14 days 10 ETH max payout>]
* @deployments: []
*/
pragma solidity ^0.5.0;
/**
* @title SortitionSumTreeFactory
* @author Enrique Piqueras - <[email protected]>
* @dev A factory of trees that keep track of staked values for sortition.
*/
library SortitionSumTreeFactory {
/* Structs */
struct SortitionSumTree {
uint K; // The maximum number of childs per node.
// We use this to keep track of vacant positions in the tree after removing a leaf. This is for keeping the tree as balanced as possible without spending gas on moving nodes around.
uint[] stack;
uint[] nodes;
// Two-way mapping of IDs to node indexes. Note that node index 0 is reserved for the root node, and means the ID does not have a node.
mapping(bytes32 => uint) IDsToNodeIndexes;
mapping(uint => bytes32) nodeIndexesToIDs;
}
/* Storage */
struct SortitionSumTrees {
mapping(bytes32 => SortitionSumTree) sortitionSumTrees;
}
/* Public */
/**
* @dev Create a sortition sum tree at the specified key.
* @param _key The key of the new tree.
* @param _K The number of children each node in the tree should have.
*/
function createTree(SortitionSumTrees storage self, bytes32 _key, uint _K) public {
SortitionSumTree storage tree = self.sortitionSumTrees[_key];
require(tree.K == 0, "Tree already exists.");
require(_K > 1, "K must be greater than one.");
tree.K = _K;
tree.stack.length = 0;
tree.nodes.length = 0;
tree.nodes.push(0);
}
/**
* @dev Set a value of a tree.
* @param _key The key of the tree.
* @param _value The new value.
* @param _ID The ID of the value.
* `O(log_k(n))` where
* `k` is the maximum number of childs per node in the tree,
* and `n` is the maximum number of nodes ever appended.
*/
function set(SortitionSumTrees storage self, bytes32 _key, uint _value, bytes32 _ID) public {
SortitionSumTree storage tree = self.sortitionSumTrees[_key];
uint treeIndex = tree.IDsToNodeIndexes[_ID];
if (treeIndex == 0) { // No existing node.
if (_value != 0) { // Non zero value.
// Append.
// Add node.
if (tree.stack.length == 0) { // No vacant spots.
// Get the index and append the value.
treeIndex = tree.nodes.length;
tree.nodes.push(_value);
// Potentially append a new node and make the parent a sum node.
if (treeIndex != 1 && (treeIndex - 1) % tree.K == 0) { // Is first child.
uint parentIndex = treeIndex / tree.K;
bytes32 parentID = tree.nodeIndexesToIDs[parentIndex];
uint newIndex = treeIndex + 1;
tree.nodes.push(tree.nodes[parentIndex]);
delete tree.nodeIndexesToIDs[parentIndex];
tree.IDsToNodeIndexes[parentID] = newIndex;
tree.nodeIndexesToIDs[newIndex] = parentID;
}
} else { // Some vacant spot.
// Pop the stack and append the value.
treeIndex = tree.stack[tree.stack.length - 1];
tree.stack.length--;
tree.nodes[treeIndex] = _value;
}
// Add label.
tree.IDsToNodeIndexes[_ID] = treeIndex;
tree.nodeIndexesToIDs[treeIndex] = _ID;
updateParents(self, _key, treeIndex, true, _value);
}
} else { // Existing node.
if (_value == 0) { // Zero value.
// Remove.
// Remember value and set to 0.
uint value = tree.nodes[treeIndex];
tree.nodes[treeIndex] = 0;
// Push to stack.
tree.stack.push(treeIndex);
// Clear label.
delete tree.IDsToNodeIndexes[_ID];
delete tree.nodeIndexesToIDs[treeIndex];
updateParents(self, _key, treeIndex, false, value);
} else if (_value != tree.nodes[treeIndex]) { // New, non zero value.
// Set.
bool plusOrMinus = tree.nodes[treeIndex] <= _value;
uint plusOrMinusValue = plusOrMinus ? _value - tree.nodes[treeIndex] : tree.nodes[treeIndex] - _value;
tree.nodes[treeIndex] = _value;
updateParents(self, _key, treeIndex, plusOrMinus, plusOrMinusValue);
}
}
}
/* Public Views */
/**
* @dev Query the leaves of a tree. Note that if `startIndex == 0`, the tree is empty and the root node will be returned.
* @param _key The key of the tree to get the leaves from.
* @param _cursor The pagination cursor.
* @param _count The number of items to return.
* @return The index at which leaves start, the values of the returned leaves, and whether there are more for pagination.
* `O(n)` where
* `n` is the maximum number of nodes ever appended.
*/
function queryLeafs(
SortitionSumTrees storage self,
bytes32 _key,
uint _cursor,
uint _count
) public view returns(uint startIndex, uint[] memory values, bool hasMore) {
SortitionSumTree storage tree = self.sortitionSumTrees[_key];
// Find the start index.
for (uint i = 0; i < tree.nodes.length; i++) {
if ((tree.K * i) + 1 >= tree.nodes.length) {
startIndex = i;
break;
}
}
// Get the values.
uint loopStartIndex = startIndex + _cursor;
values = new uint[](loopStartIndex + _count > tree.nodes.length ? tree.nodes.length - loopStartIndex : _count);
uint valuesIndex = 0;
for (uint j = loopStartIndex; j < tree.nodes.length; j++) {
if (valuesIndex < _count) {
values[valuesIndex] = tree.nodes[j];
valuesIndex++;
} else {
hasMore = true;
break;
}
}
}
/**
* @dev Draw an ID from a tree using a number. Note that this function reverts if the sum of all values in the tree is 0.
* @param _key The key of the tree.
* @param _drawnNumber The drawn number.
* @return The drawn ID.
* `O(k * log_k(n))` where
* `k` is the maximum number of childs per node in the tree,
* and `n` is the maximum number of nodes ever appended.
*/
function draw(SortitionSumTrees storage self, bytes32 _key, uint _drawnNumber) public view returns(bytes32 ID) {
SortitionSumTree storage tree = self.sortitionSumTrees[_key];
uint treeIndex = 0;
uint currentDrawnNumber = _drawnNumber % tree.nodes[0];
while ((tree.K * treeIndex) + 1 < tree.nodes.length) // While it still has children.
for (uint i = 1; i <= tree.K; i++) { // Loop over children.
uint nodeIndex = (tree.K * treeIndex) + i;
uint nodeValue = tree.nodes[nodeIndex];
if (currentDrawnNumber >= nodeValue) currentDrawnNumber -= nodeValue; // Go to the next child.
else { // Pick this child.
treeIndex = nodeIndex;
break;
}
}
ID = tree.nodeIndexesToIDs[treeIndex];
}
/** @dev Gets a specified ID's associated value.
* @param _key The key of the tree.
* @param _ID The ID of the value.
* @return The associated value.
*/
function stakeOf(SortitionSumTrees storage self, bytes32 _key, bytes32 _ID) public view returns(uint value) {
SortitionSumTree storage tree = self.sortitionSumTrees[_key];
uint treeIndex = tree.IDsToNodeIndexes[_ID];
if (treeIndex == 0) value = 0;
else value = tree.nodes[treeIndex];
}
function total(SortitionSumTrees storage self, bytes32 _key) public view returns (uint) {
SortitionSumTree storage tree = self.sortitionSumTrees[_key];
if (tree.nodes.length == 0) {
return 0;
} else {
return tree.nodes[0];
}
}
function numberOfNodes(SortitionSumTrees storage self, bytes32 _key) public view returns (uint256) {
SortitionSumTree storage tree = self.sortitionSumTrees[_key];
uint256 treeIndex = tree.nodes.length;
if (treeIndex < 2) {
return 0;
}
uint256 numberOfChildNodes = treeIndex - ((treeIndex - 2) / tree.K) - 1;
if (numberOfChildNodes < tree.stack.length) {
return 0;
}
return numberOfChildNodes - tree.stack.length;
}
/* Private */
/**
* @dev Update all the parents of a node.
* @param _key The key of the tree to update.
* @param _treeIndex The index of the node to start from.
* @param _plusOrMinus Wether to add (true) or substract (false).
* @param _value The value to add or substract.
* `O(log_k(n))` where
* `k` is the maximum number of childs per node in the tree,
* and `n` is the maximum number of nodes ever appended.
*/
function updateParents(SortitionSumTrees storage self, bytes32 _key, uint _treeIndex, bool _plusOrMinus, uint _value) private {
SortitionSumTree storage tree = self.sortitionSumTrees[_key];
uint parentIndex = _treeIndex;
while (parentIndex != 0) {
parentIndex = (parentIndex - 1) / tree.K;
tree.nodes[parentIndex] = _plusOrMinus ? tree.nodes[parentIndex] + _value : tree.nodes[parentIndex] - _value;
}
}
}
// File: contracts/DrawManager.sol
pragma solidity ^0.5.16;
library DrawManager {
using SortitionSumTreeFactory for SortitionSumTreeFactory.SortitionSumTrees;
using SafeMath for uint256;
bytes32 public constant TREE_OF_STAKES = "TreeOfStakes";
uint8 public constant MAX_BRANCHES_PER_NODE = 10;
struct State {
SortitionSumTreeFactory.SortitionSumTrees sortitionSumTrees;
}
function create(State storage self) public {
self.sortitionSumTrees.createTree(TREE_OF_STAKES, MAX_BRANCHES_PER_NODE);
}
function deposit(State storage self, address _addr, uint256 _amount) public {
bytes32 userId = bytes32(uint256(_addr));
uint256 currentAmount = self.sortitionSumTrees.stakeOf(TREE_OF_STAKES, userId);
currentAmount = currentAmount.add(_amount);
self.sortitionSumTrees.set(TREE_OF_STAKES, currentAmount, userId);
}
function withdraw(State storage self, address _addr) public returns (uint256) {
bytes32 userId = bytes32(uint256(_addr));
uint256 currentAmount = self.sortitionSumTrees.stakeOf(TREE_OF_STAKES, userId);
return withdraw(self, _addr, currentAmount);
}
function withdraw(State storage self, address _addr, uint256 _amount) public returns (uint256) {
bytes32 userId = bytes32(uint256(_addr));
uint256 currentAmount = self.sortitionSumTrees.stakeOf(TREE_OF_STAKES, userId);
uint256 remainingAmount = currentAmount.sub(_amount);
self.sortitionSumTrees.set(TREE_OF_STAKES, remainingAmount, userId);
return _amount;
}
function draw(State storage self, uint256 _drawnNumber) public view returns (address) {
if (totalBalance(self) == 0) {
return address(0);
}
return address(uint256(self.sortitionSumTrees.draw(TREE_OF_STAKES, _drawnNumber)));
}
function balanceOf(State storage self, address _addr) public view returns (uint256) {
bytes32 userId = bytes32(uint256(_addr));
return self.sortitionSumTrees.stakeOf(TREE_OF_STAKES, userId);
}
function totalBalance(State storage self) public view returns (uint256) {
return self.sortitionSumTrees.total(TREE_OF_STAKES);
}
function numberOfParticipants(State storage self) public view returns (uint256) {
return self.sortitionSumTrees.numberOfNodes(TREE_OF_STAKES);
}
}
// File: contracts/Sacrifice.sol
pragma solidity ^0.5.16;
contract Sacrifice {
constructor(address payable _recipient) public payable {
selfdestruct(_recipient);
}
}
// File: contracts/PoaMania.sol
pragma solidity ^0.5.16;
contract PoaMania is Ownable, Random {
using SafeMath for uint256;
using DrawManager for DrawManager.State;
event Rewarded(
uint256 indexed roundId,
address[3] winners,
uint256[3] prizes,
uint256 fee,
address feeReceiver,
uint256 jackpotShare,
uint256 executorReward,
address executor
);
event Jackpot(
uint256 indexed roundId,
address winner,
uint256 prize
);
event Deposited(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
DrawManager.State internal drawManager;
uint256 public roundId;
uint256 public startedAt;
uint256 public blockTime; // avg block time in seconds
uint256 public roundDuration;
uint256 public minDeposit;
uint256 public maxDeposit;
uint256 public fee;
address public feeReceiver;
uint256 public executorShare;
uint256 public jackpotShare;
uint256 public jackpotChance;
uint256 public jackpot;
// 1st and 2nd winners prizes (in percentage. 100% == 1 ether).
// The 3rd one is calculated using 2 previous
uint256[2] prizeSizes;
modifier notLocked() {
uint256 lockStart = getLockStart();
require(block.timestamp < lockStart, "locked");
_;
}
function () external payable {}
function initialize(
address _owner,
address _randomContract,
uint256 _roundDuration,
uint256 _blockTime,
uint256 _minDeposit,
uint256 _maxDeposit,
uint256[2] memory _prizeSizes,
uint256 _fee,
address _feeReceiver,
uint256 _executorShare,
uint256 _jackpotShare,
uint256 _jackpotChance
) public initializer {
require(_owner != address(0), "zero address");
Ownable.initialize(_owner);
_setRoundDuration(_roundDuration);
_setFee(_fee);
_setFeeReceiver(_feeReceiver);
_setJackpotShare(_jackpotShare);
_setJackpotChance(_jackpotChance);
_setExecutorShare(_executorShare);
_validateSumOfShares();
_setPrizeSizes(_prizeSizes);
_setBlockTime(_blockTime);
_setMinDeposit(_minDeposit);
_setMaxDeposit(_maxDeposit);
jackpot = 0;
Random._init(_randomContract);
drawManager.create();
_nextRound();
}
function deposit() external payable notLocked {
require(msg.value > 0, "zero value");
drawManager.deposit(msg.sender, msg.value);
uint256 newDepositValue = balanceOf(msg.sender);
require(newDepositValue >= minDeposit, "should be greater than or equal to min deposit");
require(newDepositValue <= maxDeposit, "should be less than or equal to max deposit");
emit Deposited(msg.sender, msg.value);
}
function withdraw() public notLocked {
uint256 amount = balanceOf(msg.sender);
withdraw(amount);
}
function withdraw(uint256 _amount) public notLocked {
require(_amount > 0, "zero value");
drawManager.withdraw(msg.sender, _amount);
uint256 newDepositValue = balanceOf(msg.sender);
require(
newDepositValue >= minDeposit || newDepositValue == 0,
"should be greater than or equal to min deposit"
);
_send(msg.sender, _amount);
emit Withdrawn(msg.sender, _amount);
}
function nextRound() public {
_reward();
_nextRound();
}
function _nextRound() internal {
startedAt = block.timestamp;
roundId = roundId.add(1);
}
function _reward() internal {
require(block.timestamp > startedAt.add(roundDuration), "the round is not over yet");
uint256 totalReward = address(this).balance.sub(totalDepositedBalance()).sub(jackpot);
uint256 feeValue = _calculatePercentage(totalReward, fee);
uint256 jackpotShareValue = _calculatePercentage(totalReward, jackpotShare);
uint256 executorShareValue = _calculatePercentage(totalReward, executorShare);
uint256 winnersTotalPrize = totalReward.sub(feeValue).sub(jackpotShareValue).sub(executorShareValue);
address[3] memory winners;
uint256[3] memory winnersCurrentDeposits;
uint256[3] memory prizeValues;
prizeValues[0] = _calculatePercentage(winnersTotalPrize, prizeSizes[0]);
prizeValues[1] = _calculatePercentage(winnersTotalPrize, prizeSizes[1]);
prizeValues[2] = winnersTotalPrize.sub(prizeValues[0]).sub(prizeValues[1]);
uint256 seed = _useSeed();
address jackpotWinner;
if (seed % 1 ether < jackpotChance && jackpot > 0) {
jackpotWinner = drawManager.draw(seed);
seed = getNewRandom(seed);
}
for (uint256 i = 0; i < 3; i++) {
winners[i] = drawManager.draw(seed);
if (winners[i] == address(0)) break;
winnersCurrentDeposits[i] = drawManager.withdraw(winners[i]);
seed = getNewRandom(seed);
}
for (uint256 i = 0; i < 3; i++) {
if (winners[i] == address(0)) break;
drawManager.deposit(winners[i], winnersCurrentDeposits[i].add(prizeValues[i]));
}
if (feeReceiver != address(0)) {
_send(address(uint160(feeReceiver)), feeValue);
}
drawManager.deposit(msg.sender, executorShareValue);
emit Rewarded(
roundId,
winners,
prizeValues,
feeValue,
feeReceiver,
jackpotShareValue,
executorShareValue,
msg.sender
);
if (jackpotWinner != address(0)) {
drawManager.deposit(jackpotWinner, jackpot);
emit Jackpot(roundId, jackpotWinner, jackpot);
jackpot = 0;
}
jackpot = jackpot.add(jackpotShareValue);
}
function setRoundDuration(uint256 _roundDuration) external onlyOwner {
_setRoundDuration(_roundDuration);
}
function setFee(uint256 _fee) external onlyOwner {
_setFee(_fee);
_validateSumOfShares();
}
function setFeeReceiver(address _feeReceiver) external onlyOwner {
_setFeeReceiver(_feeReceiver);
}
function setJackpotShare(uint256 _jackpotShare) external onlyOwner {
_setJackpotShare(_jackpotShare);
_validateSumOfShares();
}
function setJackpotChance(uint256 _jackpotChance) external onlyOwner {
_setJackpotChance(_jackpotChance);
}
function setExecutorShare(uint256 _executorShare) external onlyOwner {
_setExecutorShare(_executorShare);
_validateSumOfShares();
}
function setPrizeSizes(uint256[2] calldata _prizeSizes) external onlyOwner {
_setPrizeSizes(_prizeSizes);
}
function setBlockTime(uint256 _blockTime) external onlyOwner {
_setBlockTime(_blockTime);
}
function setMinDeposit(uint256 _minDeposit) external onlyOwner {
_setMinDeposit(_minDeposit);
}
function setMaxDeposit(uint256 _maxDeposit) external onlyOwner {
_setMaxDeposit(_maxDeposit);
}
function balanceOf(address _user) public view returns (uint256) {
return drawManager.balanceOf(_user);
}
function totalDepositedBalance() public view returns (uint256) {
return drawManager.totalBalance();
}
function numberOfParticipants() public view returns (uint256) {
return drawManager.numberOfParticipants();
}
function getPrizeSizes() public view returns (uint256[2] memory) {
return prizeSizes;
}
function getLockStart() public view returns (uint256) {
return startedAt.add(roundDuration).sub(randomUpdateInterval.mul(blockTime));
}
function getRoundInfo() external view returns (
uint256 _roundId,
uint256 _startedAt,
uint256 _roundDuration,
uint256 _blockTime,
uint256 _minDeposit,
uint256 _maxDeposit,
uint256 _jackpot,
uint256 _lockStart,
uint256 _totalDeposited
) {
return (
roundId,
startedAt,
roundDuration,
blockTime,
minDeposit,
maxDeposit,
jackpot,
getLockStart(),
totalDepositedBalance()
);
}
function getShares() external view returns (
uint256[2] memory _prizeSizes,
uint256 _fee,
address _feeReceiver,
uint256 _executorShare,
uint256 _jackpotShare,
uint256 _jackpotChance
) {
return (
prizeSizes,
fee,
feeReceiver,
executorShare,
jackpotShare,
jackpotChance
);
}
function _setRoundDuration(uint256 _roundDuration) internal {
require(_roundDuration > 0, "should be greater than 0");
roundDuration = _roundDuration;
}
function _setFee(uint256 _fee) internal {
fee = _fee;
}
function _setFeeReceiver(address _feeReceiver) internal {
require(_feeReceiver != address(0), "zero address");
feeReceiver = _feeReceiver;
}
function _setJackpotShare(uint256 _jackpotShare) internal {
jackpotShare = _jackpotShare;
}
function _setJackpotChance(uint256 _jackpotChance) internal {
require(_jackpotChance <= 1 ether, "should be less than or equal to 1 ether");
jackpotChance = _jackpotChance;
}
function _setExecutorShare(uint256 _executorShare) internal {
executorShare = _executorShare;
}
function _setPrizeSizes(uint256[2] memory _prizeSizes) internal {
uint256 sum = _prizeSizes[0].add(_prizeSizes[1]);
require(sum > 0 && sum <= 1 ether, "should be less than or equal to 1 ether");
prizeSizes = _prizeSizes;
}
function _setBlockTime(uint256 _blockTime) internal {
require(_blockTime > 0, "should be greater than 0");
blockTime = _blockTime;
}
function _setMinDeposit(uint256 _minDeposit) internal {
minDeposit = _minDeposit;
}
function _setMaxDeposit(uint256 _maxDeposit) internal {
maxDeposit = _maxDeposit;
}
function _validateSumOfShares() internal view {
uint256 sum = fee.add(jackpotShare).add(executorShare);
require(sum < 1 ether, "should be less than 1 ether");
}
function _calculatePercentage(uint256 _value, uint256 _percentage) internal pure returns (uint256) {
return _value.mul(_percentage).div(1 ether);
}
function _send(address payable _to, uint256 _value) internal {
if (!_to.send(_value)) {
(new Sacrifice).value(_value)(_to);
}
}
}

Contract ABI

[{"type":"event","name":"Deposited","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Jackpot","inputs":[{"type":"uint256","name":"roundId","internalType":"uint256","indexed":true},{"type":"address","name":"winner","internalType":"address","indexed":false},{"type":"uint256","name":"prize","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Rewarded","inputs":[{"type":"uint256","name":"roundId","internalType":"uint256","indexed":true},{"type":"address[3]","name":"winners","internalType":"address[3]","indexed":false},{"type":"uint256[3]","name":"prizes","internalType":"uint256[3]","indexed":false},{"type":"uint256","name":"fee","internalType":"uint256","indexed":false},{"type":"address","name":"feeReceiver","internalType":"address","indexed":false},{"type":"uint256","name":"jackpotShare","internalType":"uint256","indexed":false},{"type":"uint256","name":"executorReward","internalType":"uint256","indexed":false},{"type":"address","name":"executor","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Withdrawn","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"_user","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"blockTime","inputs":[],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[],"name":"deposit","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"executorShare","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"fee","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"feeReceiver","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getLockStart","inputs":[],"constant":true},{"type":"function","stateMutability":"pure","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getNewRandom","inputs":[{"type":"uint256","name":"_value","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256[2]","name":"","internalType":"uint256[2]"}],"name":"getPrizeSizes","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"_roundId","internalType":"uint256"},{"type":"uint256","name":"_startedAt","internalType":"uint256"},{"type":"uint256","name":"_roundDuration","internalType":"uint256"},{"type":"uint256","name":"_blockTime","internalType":"uint256"},{"type":"uint256","name":"_minDeposit","internalType":"uint256"},{"type":"uint256","name":"_maxDeposit","internalType":"uint256"},{"type":"uint256","name":"_jackpot","internalType":"uint256"},{"type":"uint256","name":"_lockStart","internalType":"uint256"},{"type":"uint256","name":"_totalDeposited","internalType":"uint256"}],"name":"getRoundInfo","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256[2]","name":"_prizeSizes","internalType":"uint256[2]"},{"type":"uint256","name":"_fee","internalType":"uint256"},{"type":"address","name":"_feeReceiver","internalType":"address"},{"type":"uint256","name":"_executorShare","internalType":"uint256"},{"type":"uint256","name":"_jackpotShare","internalType":"uint256"},{"type":"uint256","name":"_jackpotChance","internalType":"uint256"}],"name":"getShares","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"initialize","inputs":[{"type":"address","name":"_owner","internalType":"address"},{"type":"address","name":"_randomContract","internalType":"address"},{"type":"uint256","name":"_roundDuration","internalType":"uint256"},{"type":"uint256","name":"_blockTime","internalType":"uint256"},{"type":"uint256","name":"_minDeposit","internalType":"uint256"},{"type":"uint256","name":"_maxDeposit","internalType":"uint256"},{"type":"uint256[2]","name":"_prizeSizes","internalType":"uint256[2]"},{"type":"uint256","name":"_fee","internalType":"uint256"},{"type":"address","name":"_feeReceiver","internalType":"address"},{"type":"uint256","name":"_executorShare","internalType":"uint256"},{"type":"uint256","name":"_jackpotShare","internalType":"uint256"},{"type":"uint256","name":"_jackpotChance","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"initialize","inputs":[{"type":"address","name":"sender","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOwner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"jackpot","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"jackpotChance","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"jackpotShare","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxDeposit","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minDeposit","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"nextRound","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"numberOfParticipants","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contract IPOSDAORandom"}],"name":"posdaoRandomContract","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"renounceOwnership","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"roundDuration","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"roundId","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setBlockTime","inputs":[{"type":"uint256","name":"_blockTime","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setExecutorShare","inputs":[{"type":"uint256","name":"_executorShare","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setFee","inputs":[{"type":"uint256","name":"_fee","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setFeeReceiver","inputs":[{"type":"address","name":"_feeReceiver","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setJackpotChance","inputs":[{"type":"uint256","name":"_jackpotChance","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setJackpotShare","inputs":[{"type":"uint256","name":"_jackpotShare","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setMaxDeposit","inputs":[{"type":"uint256","name":"_maxDeposit","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setMinDeposit","inputs":[{"type":"uint256","name":"_minDeposit","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setPrizeSizes","inputs":[{"type":"uint256[2]","name":"_prizeSizes","internalType":"uint256[2]"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setRoundDuration","inputs":[{"type":"uint256","name":"_roundDuration","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"startedAt","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalDepositedBalance","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"withdraw","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"withdraw","inputs":[],"constant":false}]
            

Deployed ByteCode

0x6080604052600436106102465760003560e01c80638da5cb5b11610139578063c4d66de8116100b6578063ddca3f431161007a578063ddca3f4314610b1b578063e7da769314610b46578063efdcd97414610b9d578063f21f537d14610bee578063f2fde38b14610c19578063f7cb789a14610c6a57610246565b8063c4d66de8146109b8578063c776fc8914610a09578063d0e30db014610a44578063d73fe0aa14610a4e578063d8f9cecb14610af057610246565b8063b3f00674116100fd578063b3f006741461085d578063b7b59dfa146108b4578063bb371fdd146108ef578063bdf0f1aa1461092a578063c492701c1461096557610246565b80638da5cb5b1461064e5780638f32d59b146106a55780638fcc9cfb146106d45780639aea63e61461070f5780639c9650521461083257610246565b806369fe0e2d116101c75780637417040e1161018b5780637417040e1461052f578063758b1ce31461055a57806379e9dc811461059557806384bc76a6146105c05780638cd221c91461062357610246565b806369fe0e2d146104225780636b31ee011461045d5780636efd17d61461048857806370a08231146104b3578063715018a61461051857610246565b806347e405531161020e57806347e405531461032b57806348b15166146103425780635aa5ee191461036d5780635fc1cb94146103bc5780636083e59a146103f757610246565b80630604ce27146102485780632e1a7d4d1461027357806336c92c3f146102ae5780633ccfd60b146102e957806341b3d18514610300575b005b34801561025457600080fd5b5061025d610c95565b6040518082815260200191505060405180910390f35b34801561027f57600080fd5b506102ac6004803603602081101561029657600080fd5b8101908080359060200190929190505050610c9b565b005b3480156102ba57600080fd5b506102e7600480360360208110156102d157600080fd5b8101908080359060200190929190505050610f2c565b005b3480156102f557600080fd5b506102fe610fb2565b005b34801561030c57600080fd5b5061031561104d565b6040518082815260200191505060405180910390f35b34801561033757600080fd5b50610340611053565b005b34801561034e57600080fd5b50610357611065565b6040518082815260200191505060405180910390f35b34801561037957600080fd5b506103a66004803603602081101561039057600080fd5b810190808035906020019092919050505061106b565b6040518082815260200191505060405180910390f35b3480156103c857600080fd5b506103f5600480360360208110156103df57600080fd5b810190808035906020019092919050505061109e565b005b34801561040357600080fd5b5061040c61112c565b6040518082815260200191505060405180910390f35b34801561042e57600080fd5b5061045b6004803603602081101561044557600080fd5b8101908080359060200190929190505050611132565b005b34801561046957600080fd5b506104726111c0565b6040518082815260200191505060405180910390f35b34801561049457600080fd5b5061049d6111c6565b6040518082815260200191505060405180910390f35b3480156104bf57600080fd5b50610502600480360360208110156104d657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506111cc565b6040518082815260200191505060405180910390f35b34801561052457600080fd5b5061052d611296565b005b34801561053b57600080fd5b506105446113d1565b6040518082815260200191505060405180910390f35b34801561056657600080fd5b506105936004803603602081101561057d57600080fd5b8101908080359060200190929190505050611465565b005b3480156105a157600080fd5b506105aa6114eb565b6040518082815260200191505060405180910390f35b3480156105cc57600080fd5b506105d56114f1565b604051808a8152602001898152602001888152602001878152602001868152602001858152602001848152602001838152602001828152602001995050505050505050505060405180910390f35b34801561062f57600080fd5b50610638611541565b6040518082815260200191505060405180910390f35b34801561065a57600080fd5b50610663611547565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156106b157600080fd5b506106ba611571565b604051808215151515815260200191505060405180910390f35b3480156106e057600080fd5b5061070d600480360360208110156106f757600080fd5b81019080803590602001909291905050506115d0565b005b34801561071b57600080fd5b5061083060048036036101a081101561073357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080604001906002806020026040519081016040528092919082600260200280828437600081840152601f19601f820116905080830192505050505050919291929080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050611656565b005b34801561083e57600080fd5b506108476118f2565b6040518082815260200191505060405180910390f35b34801561086957600080fd5b50610872611938565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108c057600080fd5b506108ed600480360360408110156108d757600080fd5b810190808060400190919291929050505061195e565b005b3480156108fb57600080fd5b506109286004803603602081101561091257600080fd5b8101908080359060200190929190505050611a1b565b005b34801561093657600080fd5b506109636004803603602081101561094d57600080fd5b8101908080359060200190929190505050611aa1565b005b34801561097157600080fd5b5061097a611b27565b6040518082600260200280838360005b838110156109a557808201518184015260208101905061098a565b5050505090500191505060405180910390f35b3480156109c457600080fd5b50610a07600480360360208110156109db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611b72565b005b348015610a1557600080fd5b50610a4260048036036020811015610a2c57600080fd5b8101908080359060200190929190505050611d30565b005b610a4c611dbe565b005b348015610a5a57600080fd5b50610a63612070565b6040518087600260200280838360005b83811015610a8e578082015181840152602081019050610a73565b505050509050018681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001838152602001828152602001965050505050505060405180910390f35b348015610afc57600080fd5b50610b05612104565b6040518082815260200191505060405180910390f35b348015610b2757600080fd5b50610b30612198565b6040518082815260200191505060405180910390f35b348015610b5257600080fd5b50610b5b61219e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610ba957600080fd5b50610bec60048036036020811015610bc057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506121c4565b005b348015610bfa57600080fd5b50610c0361224a565b6040518082815260200191505060405180910390f35b348015610c2557600080fd5b50610c6860048036036020811015610c3c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612250565b005b348015610c7657600080fd5b50610c7f6122d6565b6040518082815260200191505060405180910390f35b60755481565b6000610ca56118f2565b9050804210610d1c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260068152602001807f6c6f636b6564000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008211610d92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f7a65726f2076616c75650000000000000000000000000000000000000000000081525060200191505060405180910390fd5b606a73a604ae3ce64d99774061b861b39212d020f78ee863f5a98e46909133856040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060206040518083038186803b158015610e2057600080fd5b505af4158015610e34573d6000803e3d6000fd5b505050506040513d6020811015610e4a57600080fd5b8101908080519060200190929190505050506000610e67336111cc565b9050606f5481101580610e7a5750600081145b610ecf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613dc9602e913960400191505060405180910390fd5b610ed933846122dc565b3373ffffffffffffffffffffffffffffffffffffffff167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5846040518082815260200191505060405180910390a2505050565b610f34611571565b610fa6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b610faf8161237d565b50565b6000610fbc6118f2565b9050804210611033576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260068152602001807f6c6f636b6564000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600061103e336111cc565b905061104981610c9b565b5050565b606f5481565b61105b6123fd565b611063612e41565b565b606d5481565b600081604051602001808281526020019150506040516020818303038152906040528051906020012060001c9050919050565b6110a6611571565b611118576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61112181612e66565b611129612e70565b50565b60705481565b61113a611571565b6111ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6111b581612f1f565b6111bd612e70565b50565b60765481565b60745481565b6000606a73a604ae3ce64d99774061b861b39212d020f78ee863b41297e09091846040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b15801561125457600080fd5b505af4158015611268573d6000803e3d6000fd5b505050506040513d602081101561127e57600080fd5b81019080805190602001909291905050509050919050565b61129e611571565b611310576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000606a73a604ae3ce64d99774061b861b39212d020f78ee86311d31a7190916040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561142557600080fd5b505af4158015611439573d6000803e3d6000fd5b505050506040513d602081101561144f57600080fd5b8101908080519060200190929190505050905090565b61146d611571565b6114df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6114e881612f29565b50565b60735481565b6000806000806000806000806000606b54606c54606e54606d54606f5460705460765461151c6118f2565b611524612104565b985098509850985098509850985098509850909192939495969798565b606b5481565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166115b4612fa9565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b6115d8611571565b61164a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61165381612fb1565b50565b600060019054906101000a900460ff16806116755750611674612fbb565b5b8061168c57506000809054906101000a900460ff16155b6116e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613e18602e913960400191505060405180910390fd5b60008060019054906101000a900460ff161590508015611731576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b600073ffffffffffffffffffffffffffffffffffffffff168d73ffffffffffffffffffffffffffffffffffffffff1614156117d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f7a65726f2061646472657373000000000000000000000000000000000000000081525060200191505060405180910390fd5b6117dd8d611b72565b6117e68b61237d565b6117ef86612f1f565b6117f885612fd2565b61180183612e66565b61180a826130b9565b61181384613124565b61181b612e70565b6118248761312e565b61182d8a612f29565b61183689612fb1565b61183f886131ea565b60006076819055506118508c6131f4565b606a73a604ae3ce64d99774061b861b39212d020f78ee86316f47ec190916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b1580156118a257600080fd5b505af41580156118b6573d6000803e3d6000fd5b505050506118c2612e41565b80156118e35760008060016101000a81548160ff0219169083151502179055505b50505050505050505050505050565b600061193361190e606d546069546134ad90919063ffffffff16565b611925606e54606c5461353390919063ffffffff16565b6135bb90919063ffffffff16565b905090565b607260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611966611571565b6119d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611a18816002806020026040519081016040528092919082600260200280828437600081840152601f19601f82011690508083019250505050505061312e565b50565b611a23611571565b611a95576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611a9e816131ea565b50565b611aa9611571565b611b1b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611b24816130b9565b50565b611b2f613c7d565b6077600280602002604051908101604052809291908260028015611b68576020028201915b815481526020019060010190808311611b54575b5050505050905090565b600060019054906101000a900460ff1680611b915750611b90612fbb565b5b80611ba857506000809054906101000a900460ff16155b611bfd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613e18602e913960400191505060405180910390fd5b60008060019054906101000a900460ff161590508015611c4d576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b81603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a38015611d2c5760008060016101000a81548160ff0219169083151502179055505b5050565b611d38611571565b611daa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611db381613124565b611dbb612e70565b50565b6000611dc86118f2565b9050804210611e3f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260068152602001807f6c6f636b6564000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60003411611eb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f7a65726f2076616c75650000000000000000000000000000000000000000000081525060200191505060405180910390fd5b606a73a604ae3ce64d99774061b861b39212d020f78ee863e3451b76909133346040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060006040518083038186803b158015611f4357600080fd5b505af4158015611f57573d6000803e3d6000fd5b505050506000611f66336111cc565b9050606f54811015611fc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180613dc9602e913960400191505060405180910390fd5b60705481111561201e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180613e46602b913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4346040518082815260200191505060405180910390a25050565b612078613c7d565b60008060008060006077607154607260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16607354607454607554856002806020026040519081016040528092919082600280156120e9576020028201915b8154815260200190600101908083116120d5575b50505050509550955095509550955095509550909192939495565b6000606a73a604ae3ce64d99774061b861b39212d020f78ee8639e8a5f5c90916040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561215857600080fd5b505af415801561216c573d6000803e3d6000fd5b505050506040513d602081101561218257600080fd5b8101908080519060200190929190505050905090565b60715481565b606660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6121cc611571565b61223e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61224781612fd2565b50565b606c5481565b612258611571565b6122ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6122d381613605565b50565b606e5481565b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505061237957808260405161232390613c9f565b808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019150506040518091039082f080158015612374573d6000803e3d6000fd5b509050505b5050565b600081116123f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f73686f756c642062652067726561746572207468616e2030000000000000000081525060200191505060405180910390fd5b80606e8190555050565b612414606e54606c5461353390919063ffffffff16565b4211612488576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f74686520726f756e64206973206e6f74206f766572207965740000000000000081525060200191505060405180910390fd5b60006124cf6076546124c161249b612104565b3073ffffffffffffffffffffffffffffffffffffffff16316135bb90919063ffffffff16565b6135bb90919063ffffffff16565b905060006124df8260715461374b565b905060006124ef8360745461374b565b905060006124ff8460735461374b565b9050600061253a8261252c8561251e888a6135bb90919063ffffffff16565b6135bb90919063ffffffff16565b6135bb90919063ffffffff16565b9050612544613cab565b61254c613ccd565b612554613ccd565b61256d84607760006002811061256657fe5b015461374b565b8160006003811061257a57fe5b60200201818152505061259c84607760016002811061259557fe5b015461374b565b816001600381106125a957fe5b6020020181815250506125f9816001600381106125c257fe5b60200201516125eb836000600381106125d757fe5b6020020151876135bb90919063ffffffff16565b6135bb90919063ffffffff16565b8160026003811061260657fe5b6020020181815250506000612619613782565b90506000607554670de0b6b3a7640000838161263157fe5b0610801561264157506000607654115b156126e957606a73a604ae3ce64d99774061b861b39212d020f78ee863ddfe5e3e9091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156126a057600080fd5b505af41580156126b4573d6000803e3d6000fd5b505050506040513d60208110156126ca57600080fd5b810190808051906020019092919050505090506126e68261106b565b91505b60008090505b600381101561291857606a73a604ae3ce64d99774061b861b39212d020f78ee863ddfe5e3e9091856040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561275257600080fd5b505af4158015612766573d6000803e3d6000fd5b505050506040513d602081101561277c57600080fd5b810190808051906020019092919050505086826003811061279957fe5b602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600073ffffffffffffffffffffffffffffffffffffffff168682600381106127f457fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16141561281a57612918565b606a73a604ae3ce64d99774061b861b39212d020f78ee8634c9b9e9c909188846003811061284457fe5b60200201516040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b1580156128b057600080fd5b505af41580156128c4573d6000803e3d6000fd5b505050506040513d60208110156128da57600080fd5b81019080805190602001909291905050508582600381106128f757fe5b6020020181815250506129098361106b565b925080806001019150506126ef565b5060008090505b6003811015612a6757600073ffffffffffffffffffffffffffffffffffffffff1686826003811061294c57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16141561297257612a67565b606a73a604ae3ce64d99774061b861b39212d020f78ee863e3451b76909188846003811061299c57fe5b60200201516129d48886600381106129b057fe5b60200201518a87600381106129c157fe5b602002015161353390919063ffffffff16565b6040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060006040518083038186803b158015612a4257600080fd5b505af4158015612a56573d6000803e3d6000fd5b50505050808060010191505061291f565b50600073ffffffffffffffffffffffffffffffffffffffff16607260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612aeb57612aea607260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a6122dc565b5b606a73a604ae3ce64d99774061b861b39212d020f78ee863e3451b769091338a6040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060006040518083038186803b158015612b7957600080fd5b505af4158015612b8d573d6000803e3d6000fd5b50505050606b547f939c7aa4e354380dd02a08218dca03dc98cd946a3608a5a888a487d003f2bb9e86858c607260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d336040518088600360200280838360005b83811015612c09578082015181840152602081019050612bee565b5050505090500187600360200280838360005b83811015612c37578082015181840152602081019050612c1c565b505050509050018681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200197505050505050505060405180910390a2600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612e1a57606a73a604ae3ce64d99774061b861b39212d020f78ee863e3451b769091836076546040518463ffffffff1660e01b8152600401808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060006040518083038186803b158015612d8957600080fd5b505af4158015612d9d573d6000803e3d6000fd5b50505050606b547ffc61e5433984a216c29840c13f713b564e2967f2a449609c32e4b3182f6399f382607654604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a260006076819055505b612e2f8860765461353390919063ffffffff16565b60768190555050505050505050505050565b42606c81905550612e5e6001606b5461353390919063ffffffff16565b606b81905550565b8060748190555050565b6000612e9d607354612e8f60745460715461353390919063ffffffff16565b61353390919063ffffffff16565b9050670de0b6b3a76400008110612f1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f73686f756c64206265206c657373207468616e2031206574686572000000000081525060200191505060405180910390fd5b50565b8060718190555050565b60008111612f9f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f73686f756c642062652067726561746572207468616e2030000000000000000081525060200191505060405180910390fd5b80606d8190555050565b600033905090565b80606f8190555050565b6000803090506000813b9050600081149250505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613075576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f7a65726f2061646472657373000000000000000000000000000000000000000081525060200191505060405180910390fd5b80607260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b670de0b6b3a764000081111561311a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180613e716027913960400191505060405180910390fd5b8060758190555050565b8060738190555050565b60006131658260016002811061314057fe5b60200201518360006002811061315257fe5b602002015161353390919063ffffffff16565b905060008111801561317f5750670de0b6b3a76400008111155b6131d4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180613e716027913960400191505060405180910390fd5b8160779060026131e5929190613cef565b505050565b8060708190555050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613297576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f52616e646f6d2f636f6e74726163742d7a65726f00000000000000000000000081525060200191505060405180910390fd5b80606660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663832206266040518163ffffffff1660e01b815260040160206040518083038186803b15801561334057600080fd5b505afa158015613354573d6000803e3d6000fd5b505050506040513d602081101561336a57600080fd5b810190808051906020019092919050505060678190555043606881905550606660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631c77c58c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156133f057600080fd5b505afa158015613404573d6000803e3d6000fd5b505050506040513d602081101561341a57600080fd5b8101908080519060200190929190505050606981905550600060695414156134aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f52616e646f6d2f696e74657276616c2d7a65726f00000000000000000000000081525060200191505060405180910390fd5b50565b6000808314156134c0576000905061352d565b60008284029050828482816134d157fe5b0414613528576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613df76021913960400191505060405180910390fd5b809150505b92915050565b6000808284019050838110156135b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60006135fd83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061391b565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561368b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613da36026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061377a670de0b6b3a764000061376c84866134ad90919063ffffffff16565b6139db90919063ffffffff16565b905092915050565b600061378c613a25565b6137fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f52616e646f6d2f736565642d6e6f742d7570646174656400000000000000000081525060200191505060405180910390fd5b606660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166374ce90676040518163ffffffff1660e01b815260040160206040518083038186803b15801561386657600080fd5b505afa15801561387a573d6000803e3d6000fd5b505050506040513d602081101561389057600080fd5b8101908080519060200190929190505050613913576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f52616e646f6d2f6e6f742d636f6d6d69742d706861736500000000000000000081525060200191505060405180910390fd5b606754905090565b60008383111582906139c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561398d578082015181840152602081019050613972565b50505050905090810190601f1680156139ba5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6000613a1d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613bb7565b905092915050565b6000606954606854430311613a3d5760009050613bb4565b606660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631c77c58c6040518163ffffffff1660e01b815260040160206040518083038186803b158015613aa557600080fd5b505afa158015613ab9573d6000803e3d6000fd5b505050506040513d6020811015613acf57600080fd5b81019080805190602001909291905050506069819055506000606660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663832206266040518163ffffffff1660e01b815260040160206040518083038186803b158015613b5057600080fd5b505afa158015613b64573d6000803e3d6000fd5b505050506040513d6020811015613b7a57600080fd5b810190808051906020019092919050505090506067548114613bae5780606781905550436068819055506001915050613bb4565b60009150505b90565b60008083118290613c63576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c28578082015181840152602081019050613c0d565b50505050905090810190601f168015613c555780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581613c6f57fe5b049050809150509392505050565b6040518060400160405280600290602082028038833980820191505090505090565b604e80613d5583390190565b6040518060600160405280600390602082028038833980820191505090505090565b6040518060600160405280600390602082028038833980820191505090505090565b8260028101928215613d1e579160200282015b82811115613d1d578251825591602001919060010190613d02565b5b509050613d2b9190613d2f565b5090565b613d5191905b80821115613d4d576000816000905550600101613d35565b5090565b9056fe6080604052604051604e380380604e83398181016040526020811015602357600080fd5b81019080805190602001909291905050508073ffffffffffffffffffffffffffffffffffffffff16fffe4f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737373686f756c642062652067726561746572207468616e206f7220657175616c20746f206d696e206465706f736974536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a656473686f756c64206265206c657373207468616e206f7220657175616c20746f206d6178206465706f73697473686f756c64206265206c657373207468616e206f7220657175616c20746f2031206574686572a265627a7a72315820235141e7ffaf44266f09e054b40a926a5ce8f3ed71efb1c1adae361390252d0064736f6c63430005100032

External libraries