Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Staking
- Optimization enabled
- true
- Compiler version
- v0.8.6+commit.11564f7e
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2024-09-26T15:34:37.273394Z
Contract source code
// File: contracts/EnumerableSet.sol pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256` * (`UintSet`) are supported. */ library EnumerableSet { struct AddressSet { // Storage of set values address[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping (address => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { if (!contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. address lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { require(set._values.length > index, "EnumerableSet: index out of bounds"); return set._values[index]; } } // File: contracts/StakingBIC.sol pragma solidity ^0.8.0; interface IBEP20 { function transfer(address recipient, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); function mint(address user, uint256 amount) external; function balanceOf(address account) external view returns (uint256); } abstract contract Ownable { address internal _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ /* we use proxy, so owner will be set in initialize() function constructor () { _owner = msg.sender; emit OwnershipTransferred(address(0), msg.sender); } */ /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == msg.sender, "Ownable: caller is not the owner"); _; } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } contract Staking is Ownable { using EnumerableSet for EnumerableSet.AddressSet; address public token; // BIC token EnumerableSet.AddressSet usersList; // list of users with stake struct User { uint256 amount; // amount of deposit uint256 weightedTokens; // the user's weighted tokens balance. (weighted tokens = token amount * staked days) uint256 previousWeightedTokens; // the user's weighted tokens balance for previous month. uint256 reward; // amount of reward that user may withdraw before ends of staking. uint64 unlockTime; // when can be unstake uint64 updated; // day when updated uint64 multiplier; // multiplier (with 2 decimals) applied to deposit ([0.25 .. 1]) uint8 status; // 0 - active, 1 - ended (weightedTokens > 0), 2 - ended (previousWeightedTokens > 0), 3 - ended, but not withdrawn } mapping(address => User[]) public users; // users deposits array mapping(uint256 => uint256) public multiplier; // staking days => multiplier (with 2 decimals) uint256 public withdrawWindow; // user may withdraw during this time when previous lock period ends. uint256 public prolongate; // if user did not withdraw, money locked on next 30 days. uint256 public minimumAmount; // minimum amount for staking // for TEST /* uint256 public withdrawWindow = 1 days; // user may withdraw during this time when previous lock period ends. uint256 public prolongate = 2 days; // if user user did not withdraw, money locked on next 30 days. uint256 public minimumAmount = 1; // minimum amount for staking */ uint256 public totalStaked; uint256 public totalStakedWeight; uint256 public previousTotalStakedWeight; // the total staked weight for previous month. int256 public amountPerWeightedToken; // amount (with 18 decimals) of profit/loss per weighted token for previous month. int256 public monthResultAmount; // result for previous month uint256 public processingStep; // 0 - processing complete, 1 - recalculate Weight, 2 - split result uint256 public processedDay; // last day that was processed uint256 public precessedMonth; // month when profit/loss was added. Admin can add profit/loss only once per month. uint256 public nextProcessUser; mapping (address => bool) public admins; event SetAdmin(address admin, bool isActive); event Stake(address user, uint256 amount, uint256 period, uint256 multiplier); event Unstake(address user, uint256 amount); event WithdrawUSD(address user, uint256 amount); event Processed(uint256 number, uint256 total, uint256 step); event RemoveUser(address user); event RemoveDeposit(address user, uint256 depositId); event MonthResult(int256 amount); event SplitResult(address user, uint256 depositId, int256 amount); event MonthBalances(uint256 totalStaked, uint256 totalBalance); // run only once from proxy function initialize(address newOwner, address _token) external { require(newOwner != address(0) && _owner == address(0)); // run only once _owner = newOwner; token = _token; emit OwnershipTransferred(address(0), msg.sender); withdrawWindow = 5 days; // user may withdraw during this time when previous lock period ends. prolongate = 30 days; // if user did not withdraw, money locked on next 30 days. minimumAmount = 200 ether; // minimum amount for staking multiplier[90] = 25; // staking for 90 days = multiplier 0.25 multiplier[180] = 50; // staking for 180 days = multiplier 0.5 multiplier[270] = 75; // staking for 270 days = multiplier 0.75 multiplier[360] = 100; // staking for 180 days = multiplier 1 } /** * @dev Throws if called by any account other than the admin. */ modifier onlyAdmin() { require(admins[msg.sender] || owner() == msg.sender, "Caller is not admin"); _; } function setAdmin(address admin, bool isActive) external onlyOwner { admins[admin] = isActive; emit SetAdmin(admin, isActive); } // set multiplier (with 2 decimals) function setMultiplier(uint256 _days, uint256 _multiplier) external onlyOwner { require(_multiplier <= 100, "Wrong multiplier"); multiplier[_days] = _multiplier; } // set minimumAmount function setMinimumAmount(uint256 _minAmount) external onlyOwner { minimumAmount = _minAmount; } // set withdrawWindow in seconds function setWithdrawWindow(uint256 time) external onlyOwner { withdrawWindow = time; } // set prolongate in seconds function setProlongate(uint256 time) external onlyOwner { prolongate = time; } // get total number of users function getUsersNumber() external view returns(uint256) { return usersList.length(); } // get total number of deposits of user function getUsersDepositsNumber(address user) external view returns(uint256) { return users[user].length; } // get deposits of user function getUsersDeposits(address user) external view returns(User[] memory) { return users[user]; } // get deposits of user function getUsersDepositsByNumber(uint256 userNumber) external view returns(User[] memory) { address user = usersList.at(userNumber); return users[user]; } function getTotalBalance() public view returns(uint256 balance) { uint256 lastUser = usersList.length(); for(uint256 precessedUsers = 0; precessedUsers < lastUser; precessedUsers++) { address user = usersList.at(precessedUsers); uint256 deposits = users[user].length; for (uint256 i = 0; i < deposits; i++) { balance += users[user][i].amount; } } } // Step 0. Call this function 1st day of each month // Enter result for previous month function monthResult(int256 amount) external onlyOwner { require(processingStep == 0, "Previous result was not processed"); _updateWeight(); (,uint256 month,) = timestampToDate(block.timestamp); //month = block.timestamp / 1 days; // for TEST require(precessedMonth != month, "Result may be added only once per month"); precessedMonth = month; monthResultAmount = amount; require (int256(totalStaked) + amount >= 0, "totalStaked less then amount"); if (amount > 0) { _safeTransferFrom(token, msg.sender, address(this), uint256(amount)); } processingStep = 1; nextProcessUser = 0; emit MonthResult(amount); } // recalculate users weights and total weights to exclude expired staking. // Step 1. Call this function 1st day of each month // numberUsers - is number of users that will processed at one transaction. Repeat call this function until emit event with number == total. function recalculateWeight(uint256 numberUsers) external onlyAdmin { require(processingStep == 1, "Wrong step"); uint256 currentDay = block.timestamp / 1 days; // number of days that passed //uint256 currentDay = block.timestamp / 1 hours; // for TEST uint256 precessedUsers = nextProcessUser; uint256 lastUser = usersList.length(); while (precessedUsers < lastUser) { address user = usersList.at(precessedUsers); uint256 deposits = users[user].length; if (numberUsers >= deposits) { numberUsers -= deposits; } else { nextProcessUser = precessedUsers; emit Processed(precessedUsers, lastUser, processingStep); return; } for (uint256 i = 0; i < deposits; i++) { _updateUser(currentDay, users[user][i]); } precessedUsers++; } processingStep = 2; nextProcessUser = 0; emit Processed(precessedUsers, lastUser, 1); } // call this function 1st day of each month to split month's result among users. // numberUsers - is number of users that will processed at one transaction. Repeat call this function until emit event with number == total. function splitResult(uint256 numberUsers) external onlyAdmin { require(processingStep == 2, "Wrong step"); int256 _monthResult = monthResultAmount; uint256 lastUser = usersList.length(); if (_monthResult == 0) { // exit if no amount to split processingStep = 0; emit Processed(lastUser, lastUser, 2); return; } int256 _previousTotalStakedWeight = int256(previousTotalStakedWeight); int256 split; uint256 precessedUsers = nextProcessUser; while (precessedUsers < lastUser) { address user = usersList.at(precessedUsers); uint256 deposits = users[user].length; if (numberUsers >= deposits) { numberUsers -= deposits; } else { nextProcessUser = precessedUsers; totalStaked = uint256(int256(totalStaked) + split); // add to totalStaked split amount emit Processed(precessedUsers, lastUser, processingStep); return; } for (uint256 i = 0; i < deposits; i++) { int256 wight = int256(users[user][i].previousWeightedTokens); if (wight != 0) { int256 stakedAmount = int256(users[user][i].amount); int256 reward = _monthResult * wight * int64(users[user][i].multiplier) / (_previousTotalStakedWeight * 100); split += reward; if (reward > 0) users[user][i].reward += uint256(reward); stakedAmount = stakedAmount + reward; if (stakedAmount < 0) { split = split - stakedAmount; // unsplit negative values stakedAmount = 0; } users[user][i].amount = uint256(stakedAmount); users[user][i].previousWeightedTokens = 0; emit SplitResult(user, i, reward); } } precessedUsers++; } totalStaked = uint256(int256(totalStaked) + split); // add to totalStaked split amount processingStep = 0; nextProcessUser = 0; uint256 bal = IBEP20(token).balanceOf(address(this)); uint256 totalBalance = getTotalBalance(); emit MonthBalances(totalStaked, totalBalance); if (totalBalance >= totalStaked && bal > totalBalance) // send rest of money to owner _safeTransfer(token, owner(), bal - totalBalance); emit Processed(precessedUsers, lastUser, 2); } // allow owner to unstake token's on user behalf without waiting unlock time. // user's deposit will be deleted. function unstakeAdmin(address user, uint256 depositId, bool withdrawUSD) external onlyOwner { uint256 currentDay = _updateWeight(); // number of days that passed User storage u = users[user][depositId]; _updateUser(currentDay, u); uint256 totalAmount = u.amount; if (totalAmount != 0) { if (withdrawUSD) { _safeTransfer(token, owner(), totalAmount); emit WithdrawUSD(user, totalAmount); } else { _safeTransfer(token, user, totalAmount); emit Unstake(user, totalAmount); } } if (u.status == 0) totalStaked -= totalAmount; totalStakedWeight -= u.weightedTokens; previousTotalStakedWeight -= u.previousWeightedTokens; // delete deposit records uint256 lastDepositId = users[user].length - 1; if (lastDepositId == 0) { users[user].pop(); // delete last deposit usersList.remove(user); // remove user from list emit RemoveUser(user); } else { if (depositId != lastDepositId) users[user][depositId] = users[user][lastDepositId]; users[user].pop(); emit RemoveDeposit(user, depositId); } } // User stake amount of tokens. // User can't withdraw tokens/USD at least 90 days after first deposit or 30 days after further deposits function stake(uint256 amount, uint256 period) external { require(amount >= minimumAmount, "Staked amount is less then minimum"); uint256 mp = multiplier[period]; require(mp != 0, "Wrong period"); _safeTransferFrom(token, msg.sender, address(this), amount); _stake(msg.sender, amount, period, mp); } // Owner stake amount of tokens on user behalf. // user - address of user's wallet // amount - amount of token to transfer on stake // period - number of days when tokens will be locked on stake // multiplier_ - multiplier (with 2 decimals) applied to deposit ([0.25 .. 1]). I.e. 25 means 0.25 function stakeBehalf(address user, uint256 amount, uint256 period, uint256 multiplier_) external onlyOwner { require(multiplier_ <= 100, "Wrong multiplier"); _safeTransferFrom(token, msg.sender, address(this), amount); _stake(user, amount, period, multiplier_); } // Withdraw rewards during allowed window. function withdrawRewards(uint256 depositId, uint256 amount, bool withdrawUSD) external { User storage u = users[msg.sender][depositId]; uint256 unlockTime = u.unlockTime; if (block.timestamp < unlockTime) { uint256 _days = unlockTime - block.timestamp; _days = _days % prolongate; require(_days > prolongate - withdrawWindow || _days == 0, "Out of withdraw window"); uint256 reward = u.reward; require(amount <= reward && amount <= u.amount, "Not enough rewards"); uint256 currentDay = _updateWeight(); // number of days that passed _updateUser(currentDay, u); u.reward = reward - amount; u.amount -= amount; if (u.status == 0) totalStaked -= amount; if (withdrawUSD) { _safeTransfer(token, owner(), amount); emit WithdrawUSD(msg.sender, amount); } else { _safeTransfer(token, msg.sender, amount); emit Unstake(msg.sender, amount); } } else { _unstake(msg.sender, depositId, withdrawUSD); } } // unstake tokens to user wallet or withdraw USD (tokens will be send to owner()) // User can't unstake/withdraw at least 90 days after first deposit or 30 days after further deposits function unstake(uint256 depositId, bool withdrawUSD) external { require(block.timestamp >= users[msg.sender][depositId].unlockTime, "Account locked"); _unstake(msg.sender, depositId, withdrawUSD); } // Stake amount for selected period (in days) function _stake(address user, uint256 amount, uint256 period, uint256 multiplier_) internal { _updateWeight(); require(users[user].length < 10, "Allowed 10 deposits per wallet"); totalStaked += amount; usersList.add(user); users[user].push( User({ amount: amount, weightedTokens: 0, previousWeightedTokens: 0, reward: 0, unlockTime: uint64(block.timestamp + (period * 1 days)), updated: uint64(block.timestamp / 1 days), //unlockTime: uint64(block.timestamp + (period * 1 hours)), // for TEST //updated: uint64(block.timestamp / 1 hours), // for TEST multiplier: uint64(multiplier_), status: 0 }) ); emit Stake(user, amount, period, multiplier_); } function _unstake(address user, uint256 depositId, bool withdrawUSD) internal { uint256 currentDay = _updateWeight(); // number of days that passed User storage u = users[user][depositId]; _updateUser(currentDay, u); uint256 totalAmount = u.amount; u.amount = 0; u.reward = 0; if (totalAmount != 0) { if (withdrawUSD) { _safeTransfer(token, owner(), totalAmount); emit WithdrawUSD(user, totalAmount); } else { _safeTransfer(token, user, totalAmount); emit Unstake(user, totalAmount); } } if(u.previousWeightedTokens == 0 && u.weightedTokens == 0) { // delete deposit records uint256 lastDepositId = users[user].length - 1; if (lastDepositId == 0) { users[user].pop(); // delete last deposit usersList.remove(user); // remove user from list emit RemoveUser(user); } else { if (depositId != lastDepositId) users[user][depositId] = users[user][lastDepositId]; users[user].pop(); emit RemoveDeposit(user, depositId); } } } function _updateUser(uint256 currentDay, User storage u) internal { uint8 status = u.status; // 0 - active, 1 - ended (weightedTokens > 0), 2 - ended (previousWeightedTokens > 0), 3 - ended, but not withdrawn if (status == 0) { uint256 amount = u.amount; uint256 weightedTokens = u.weightedTokens; uint256 unlockDay = u.unlockTime / 1 days; if (unlockDay <= currentDay) { // Stacking ends. Fix previous weight. (uint256 previousStakedWeight, uint256 stakedWeight) = _calculateWeight(currentDay, unlockDay, amount, weightedTokens); totalStakedWeight -= stakedWeight; if (previousStakedWeight != 0) previousTotalStakedWeight -= previousStakedWeight; (previousStakedWeight, stakedWeight) = _calculateWeight(unlockDay, u.updated, amount, weightedTokens); u.updated = uint64(currentDay); u.weightedTokens = stakedWeight; if (previousStakedWeight != 0) u.previousWeightedTokens = previousStakedWeight; if(stakedWeight != 0) { u.status = 1; // no active staked amount } else if (previousStakedWeight != 0) { u.status = 2; } else { u.status = 3; } totalStaked -= amount; } else { (uint256 previousStakedWeight, uint256 stakedWeight) = _calculateWeight(currentDay, u.updated, amount, weightedTokens); u.updated = uint64(currentDay); u.weightedTokens = stakedWeight; if (previousStakedWeight != 0) u.previousWeightedTokens = previousStakedWeight; } } else if (status == 1 && u.updated < currentDay && u.previousWeightedTokens == 0) { u.previousWeightedTokens = u.weightedTokens; u.weightedTokens = 0; if (u.previousWeightedTokens != 0) { u.status = 2; } else { u.status = 3; } } } function _updateWeight() internal returns(uint256 currentDay) { currentDay = block.timestamp / 1 days; // number of days that passed //currentDay = block.timestamp / 1 hours; // for TEST if (currentDay > processedDay) { (uint256 previousStakedWeight, uint256 stakedWeight) = _calculateWeight(currentDay, processedDay, totalStaked, totalStakedWeight); processedDay = currentDay; totalStakedWeight = stakedWeight; if (previousStakedWeight != 0) previousTotalStakedWeight = previousStakedWeight; } } function _calculateWeight(uint256 currentDay, uint256 lastUpdate, uint256 amount, uint256 currentStakedWeight) internal pure returns(uint256 previousStakedWeight, uint256 stakedWeight) { stakedWeight = currentStakedWeight; if (currentDay > lastUpdate) { uint256 interval = currentDay - lastUpdate; (,,uint day) = _daysToDate(currentDay); if (day <= interval) { // new month starts uint256 previousInterval = interval - day + 1; previousStakedWeight = currentStakedWeight + (amount * previousInterval); interval = interval - previousInterval; // number of days passed in current month stakedWeight = amount * interval; // start total staked weight from zero } else { stakedWeight = currentStakedWeight + (amount * interval); } } } // TEST ======================================================================================================== /* function TEST_calculateWeight(uint256 currentDay, uint256 lastUpdate, uint256 amount, uint256 currentStakedWeight) public pure returns(uint256 previousStakedWeight, uint256 stakedWeight) { stakedWeight = currentStakedWeight; if (currentDay > lastUpdate) { uint256 interval = currentDay - lastUpdate; uint day = (currentDay % 24) + 1; // 1 hour = 1 day, 24 hours = 1 month if (day <= interval) { // new month starts uint256 previousInterval = interval - day + 1; previousStakedWeight = currentStakedWeight + (amount * previousInterval); interval = interval - previousInterval; // number of days passed in current month stakedWeight = amount * interval; // start total staked weight from zero } else { stakedWeight = currentStakedWeight + (amount * interval); } } } */ // END TEST ==================================================================================================== function _safeTransfer(address _token, address to, uint value) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = _token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); } function _safeTransferFrom(address _token, address from, address to, uint value) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = _token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); } /** * @dev Calculate number of days from 1/1/1970 to selected date. * @param year The year number * @param month The month number * @param day The day number * @return _days number of day. */ function _daysFromDate(uint year, uint month, uint day) internal pure returns (uint _days) { require(year >= 1970); int _year = int(year); int _month = int(month); int _day = int(day); int __days = _day - 32075 + 1461 * (_year + 4800 + (_month - 14) / 12) / 4 + 367 * (_month - 2 - (_month - 14) / 12 * 12) / 12 - 3 * ((_year + 4900 + (_month - 14) / 12) / 100) / 4 - 2440588; _days = uint(__days); } /** * @dev Calculate timestamp (UNIX time) of selected date and time. * @param year The year number * @param month The month number * @param day The day number * @param hour number of hours * @param minute number of minutes * @param second number of seconds * @return timestamp UNIX time */ function timestampFromDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (uint timestamp) { timestamp = _daysFromDate(year, month, day) * 86400 + hour * 3600 + minute * 60 + second; } function _daysToDate(uint _days) internal pure returns (uint year, uint month, uint day) { int __days = int(_days); int L = __days + 68569 + 2440588; int N = 4 * L / 146097; L = L - (146097 * N + 3) / 4; int _year = 4000 * (L + 1) / 1461001; L = L - 1461 * _year / 4 + 31; int _month = 80 * L / 2447; int _day = L - 2447 * _month / 80; L = _month / 11; _month = _month + 2 - 12 * L; _year = 100 * (N - 49) + _year + L; year = uint(_year); month = uint(_month); day = uint(_day); } /** * @dev Calculate date from timestamp (UNIX time) . * @param timestamp UNIX time * @return year The year number * @return month The month number * @return day The day number */ function timestampToDate(uint timestamp) internal pure returns (uint year, uint month, uint day) { (year, month, day) = _daysToDate(timestamp / 86400); } }
Contract ABI
[{"type":"event","name":"MonthBalances","inputs":[{"type":"uint256","name":"totalStaked","internalType":"uint256","indexed":false},{"type":"uint256","name":"totalBalance","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"MonthResult","inputs":[{"type":"int256","name":"amount","internalType":"int256","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":"Processed","inputs":[{"type":"uint256","name":"number","internalType":"uint256","indexed":false},{"type":"uint256","name":"total","internalType":"uint256","indexed":false},{"type":"uint256","name":"step","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RemoveDeposit","inputs":[{"type":"address","name":"user","internalType":"address","indexed":false},{"type":"uint256","name":"depositId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RemoveUser","inputs":[{"type":"address","name":"user","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"SetAdmin","inputs":[{"type":"address","name":"admin","internalType":"address","indexed":false},{"type":"bool","name":"isActive","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"SplitResult","inputs":[{"type":"address","name":"user","internalType":"address","indexed":false},{"type":"uint256","name":"depositId","internalType":"uint256","indexed":false},{"type":"int256","name":"amount","internalType":"int256","indexed":false}],"anonymous":false},{"type":"event","name":"Stake","inputs":[{"type":"address","name":"user","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"period","internalType":"uint256","indexed":false},{"type":"uint256","name":"multiplier","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Unstake","inputs":[{"type":"address","name":"user","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"WithdrawUSD","inputs":[{"type":"address","name":"user","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"admins","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"","internalType":"int256"}],"name":"amountPerWeightedToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"balance","internalType":"uint256"}],"name":"getTotalBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct Staking.User[]","components":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"weightedTokens","internalType":"uint256"},{"type":"uint256","name":"previousWeightedTokens","internalType":"uint256"},{"type":"uint256","name":"reward","internalType":"uint256"},{"type":"uint64","name":"unlockTime","internalType":"uint64"},{"type":"uint64","name":"updated","internalType":"uint64"},{"type":"uint64","name":"multiplier","internalType":"uint64"},{"type":"uint8","name":"status","internalType":"uint8"}]}],"name":"getUsersDeposits","inputs":[{"type":"address","name":"user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct Staking.User[]","components":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"weightedTokens","internalType":"uint256"},{"type":"uint256","name":"previousWeightedTokens","internalType":"uint256"},{"type":"uint256","name":"reward","internalType":"uint256"},{"type":"uint64","name":"unlockTime","internalType":"uint64"},{"type":"uint64","name":"updated","internalType":"uint64"},{"type":"uint64","name":"multiplier","internalType":"uint64"},{"type":"uint8","name":"status","internalType":"uint8"}]}],"name":"getUsersDepositsByNumber","inputs":[{"type":"uint256","name":"userNumber","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getUsersDepositsNumber","inputs":[{"type":"address","name":"user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getUsersNumber","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"newOwner","internalType":"address"},{"type":"address","name":"_token","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minimumAmount","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"monthResult","inputs":[{"type":"int256","name":"amount","internalType":"int256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"","internalType":"int256"}],"name":"monthResultAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"multiplier","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nextProcessUser","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"precessedMonth","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"previousTotalStakedWeight","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"processedDay","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"processingStep","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"prolongate","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"recalculateWeight","inputs":[{"type":"uint256","name":"numberUsers","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAdmin","inputs":[{"type":"address","name":"admin","internalType":"address"},{"type":"bool","name":"isActive","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinimumAmount","inputs":[{"type":"uint256","name":"_minAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMultiplier","inputs":[{"type":"uint256","name":"_days","internalType":"uint256"},{"type":"uint256","name":"_multiplier","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setProlongate","inputs":[{"type":"uint256","name":"time","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setWithdrawWindow","inputs":[{"type":"uint256","name":"time","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"splitResult","inputs":[{"type":"uint256","name":"numberUsers","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stake","inputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"period","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stakeBehalf","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"period","internalType":"uint256"},{"type":"uint256","name":"multiplier_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"token","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalStaked","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalStakedWeight","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unstake","inputs":[{"type":"uint256","name":"depositId","internalType":"uint256"},{"type":"bool","name":"withdrawUSD","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unstakeAdmin","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"depositId","internalType":"uint256"},{"type":"bool","name":"withdrawUSD","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"weightedTokens","internalType":"uint256"},{"type":"uint256","name":"previousWeightedTokens","internalType":"uint256"},{"type":"uint256","name":"reward","internalType":"uint256"},{"type":"uint64","name":"unlockTime","internalType":"uint64"},{"type":"uint64","name":"updated","internalType":"uint64"},{"type":"uint64","name":"multiplier","internalType":"uint64"},{"type":"uint8","name":"status","internalType":"uint8"}],"name":"users","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawRewards","inputs":[{"type":"uint256","name":"depositId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"bool","name":"withdrawUSD","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"withdrawWindow","inputs":[]}]
Contract Creation Code
0x608060405234801561001057600080fd5b506131a3806100206000396000f3fe608060405234801561001057600080fd5b50600436106102275760003560e01c80639652b12111610130578063e6fc015e116100b8578063eeb4a9c81161007c578063eeb4a9c8146104b6578063f2fde38b146104c9578063f7cb8124146104dc578063fc0c546a146104e5578063ff293df3146104f857600080fd5b8063e6fc015e1461046b578063ebda3b051461047e578063ed47ab5b14610487578063edcb208b1461049a578063ee79da19146104ad57600080fd5b8063bb0c8298116100ff578063bb0c829814610434578063bbe0d9f61461043d578063bc10b17214610450578063cb028a8314610459578063e03aabe61461046257600080fd5b80639652b121146104065780639ebea88c1461040f578063aa8c532414610422578063ab2e58dd1461042b57600080fd5b8063485cc955116101b35780636696f3ff116101825780636696f3ff146103b45780637b0472f0146103bd5780637fe91239146103d0578063817b1cd2146103d85780638da5cb5b146103e157600080fd5b8063485cc9551461031b5780634b0bddd21461032e57806354a02f9e146103415780635c141991146103a157600080fd5b806320114ac2116101fa57806320114ac21461029c57806328a6a2dd146102af578063333271d0146102c257806334553147146102d5578063429b62e5146102e857600080fd5b806305e30f511461022c57806312b583491461025f57806313c02846146102675780631e0927e81461027c575b600080fd5b61024c61023a366004612d43565b60056020526000908152604090205481565b6040519081526020015b60405180910390f35b61024c610521565b61027a610275366004612d43565b6105e2565b005b61028f61028a366004612d43565b6107c4565b6040516102569190612e25565b61027a6102aa366004612d43565b6108ab565b61028f6102bd366004612bf7565b610ac6565b61027a6102d0366004612d9a565b610b9d565b61027a6102e3366004612dbc565b610c2c565b61030b6102f6366004612bf7565b60126020526000908152604090205460ff1681565b6040519015158152602001610256565b61027a610329366004612c19565b610e8b565b61027a61033c366004612c4c565b610fc6565b61035461034f366004612c83565b61105b565b6040805198895260208901979097529587019490945260608601929092526001600160401b03908116608086015290811660a08501521660c083015260ff1660e082015261010001610256565b61027a6103af366004612d43565b6110d2565b61024c60105481565b61027a6103cb366004612d9a565b611110565b61024c6111e1565b61024c60095481565b6000546001600160a01b03165b6040516001600160a01b039091168152602001610256565b61024c600d5481565b61027a61041d366004612d75565b6111f1565b61024c60075481565b61024c60115481565b61024c60085481565b61027a61044b366004612ced565b61127e565b61024c600a5481565b61024c60065481565b61024c600f5481565b61027a610479366004612d43565b611325565b61024c600e5481565b61027a610495366004612cad565b6118b6565b61027a6104a8366004612d43565b611d58565b61024c600c5481565b61027a6104c4366004612d43565b611d96565b61027a6104d7366004612bf7565b611dd4565b61024c600b5481565b6001546103ee906001600160a01b031681565b61024c610506366004612bf7565b6001600160a01b031660009081526004602052604090205490565b60008061052d60025490565b905060005b818110156105dd576000610547600283611ecd565b6001600160a01b0381166000908152600460205260408120549192505b818110156105c7576001600160a01b038316600090815260046020526040902080548290811061059657610596613129565b906000526020600020906005020160000154866105b39190612f3e565b9550806105bf816130b8565b915050610564565b50505080806105d5906130b8565b915050610532565b505090565b336105f56000546001600160a01b031690565b6001600160a01b0316146106245760405162461bcd60e51b815260040161061b90612ec8565b60405180910390fd5b600e541561067e5760405162461bcd60e51b815260206004820152602160248201527f50726576696f757320726573756c7420776173206e6f742070726f63657373656044820152601960fa1b606482015260840161061b565b610686611f5e565b50600061069242611fab565b509150508060105414156106f85760405162461bcd60e51b815260206004820152602760248201527f526573756c74206d6179206265206164646564206f6e6c79206f6e63652070656044820152660e440dadedce8d60cb1b606482015260840161061b565b6010819055600d829055600954600090610713908490612efd565b12156107615760405162461bcd60e51b815260206004820152601c60248201527f746f74616c5374616b6564206c657373207468656e20616d6f756e7400000000604482015260640161061b565b600082131561078257600154610782906001600160a01b0316333085611fd1565b6001600e5560006011556040518281527f7e378eda7a53c9c96fb609c656ea4cddfd3f364b2fd5a0338fed559471da4fbe906020015b60405180910390a15050565b606060006107d3600284611ecd565b6001600160a01b0381166000908152600460209081526040808320805482518185028101850190935280835294955090939092909184015b8282101561089f576000848152602090819020604080516101008101825260058602909201805483526001808201548486015260028201549284019290925260038101546060840152600401546001600160401b038082166080850152600160401b8204811660a0850152600160801b82041660c0840152600160c01b900460ff1660e0830152908352909201910161080b565b50505050915050919050565b3360009081526012602052604090205460ff16806108e25750336108d76000546001600160a01b031690565b6001600160a01b0316145b6109245760405162461bcd60e51b815260206004820152601360248201527221b0b63632b91034b9903737ba1030b236b4b760691b604482015260640161061b565b600e546001146109635760405162461bcd60e51b815260206004820152600a602482015269057726f6e6720737465760b41b604482015260640161061b565b60006109726201518042612f84565b601154909150600061098360025490565b90505b80821015610a8257600061099b600284611ecd565b6001600160a01b0381166000908152600460205260409020549091508086106109cf576109c881876130a1565b9550610a0d565b6011849055600e546040805186815260208101869052808201929092525160008051602061314e8339815191529181900360600190a1505050505050565b60005b81811015610a6d576001600160a01b03831660009081526004602052604090208054610a5b91889184908110610a4857610a48613129565b9060005260206000209060050201612101565b80610a65816130b8565b915050610a10565b5083610a78816130b8565b9450505050610986565b6002600e556000601155604080518381526020810183905260019181019190915260008051602061314e833981519152906060015b60405180910390a15050505b50565b6001600160a01b0381166000908152600460209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610b92576000848152602090819020604080516101008101825260058602909201805483526001808201548486015260028201549284019290925260038101546060840152600401546001600160401b038082166080850152600160401b8204811660a0850152600160801b82041660c0840152600160c01b900460ff1660e08301529083529092019101610afe565b505050509050919050565b33610bb06000546001600160a01b031690565b6001600160a01b031614610bd65760405162461bcd60e51b815260040161061b90612ec8565b6064811115610c1a5760405162461bcd60e51b815260206004820152601060248201526f2bb937b7339036bab63a34b83634b2b960811b604482015260640161061b565b60009182526005602052604090912055565b336000908152600460205260408120805485908110610c4d57610c4d613129565b6000918252602090912060059091020160048101549091506001600160401b031642811115610e79576000610c8242836130a1565b905060075481610c9291906130d3565b9050600654600754610ca491906130a1565b811180610caf575080155b610cf45760405162461bcd60e51b81526020600482015260166024820152754f7574206f662077697468647261772077696e646f7760501b604482015260640161061b565b6003830154808611801590610d0a575083548611155b610d4b5760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f756768207265776172647360701b604482015260640161061b565b6000610d55611f5e565b9050610d618186612101565b610d6b87836130a1565b6003860155845487908690600090610d849084906130a1565b90915550506004850154600160c01b900460ff16610db4578660096000828254610dae91906130a1565b90915550505b8515610e2057600154610de2906001600160a01b0316610ddc6000546001600160a01b031690565b8961235f565b60408051338152602081018990527fa859066e89895ffb9f2cdf2af7e7e84061fcb7ddd8657877c264737f25f8b655910160405180910390a1610e71565b600154610e37906001600160a01b0316338961235f565b60408051338152602081018990527f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd910160405180910390a15b505050610e84565b610e84338685612473565b5050505050565b6001600160a01b03821615801590610eac57506000546001600160a01b0316155b610eb557600080fd5b600080546001600160a01b038085166001600160a01b031992831617835560018054918516919092161790556040513391907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350506206978060065562278d00600755680ad78ebc5ac6200000600855600560205260197faadf04b4a1bf84e121ab68e5c1cffab5aeb9be1a024ff9944a2a0bc1674866095560327fec79235ffe9302935718f9bddc23f2c5c6c950ae49f49d137c786213c361802755604b7fe78ea91a221fb67f10aba14ba22dc39f780130b5cf7d2295f57a7414e295968b5561016860005260647f5464d34515fb195718451914a9b5e2c4ac04dce5fd392ea5e3f190355ea2fb7e55565b33610fd96000546001600160a01b031690565b6001600160a01b031614610fff5760405162461bcd60e51b815260040161061b90612ec8565b6001600160a01b038216600081815260126020908152604091829020805460ff19168515159081179091558251938452908301527f55a5194bc0174fcaf12b2978bef43911466bf63b34db8d1dd1a0d5dcd5c41bea91016107b8565b6004602052816000526040600020818154811061107757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015492955090935091906001600160401b0380821691600160401b8104821691600160801b82041690600160c01b900460ff1688565b336110e56000546001600160a01b031690565b6001600160a01b03161461110b5760405162461bcd60e51b815260040161061b90612ec8565b600755565b60085482101561116d5760405162461bcd60e51b815260206004820152602260248201527f5374616b656420616d6f756e74206973206c657373207468656e206d696e696d604482015261756d60f01b606482015260840161061b565b600081815260056020526040902054806111b85760405162461bcd60e51b815260206004820152600c60248201526b15dc9bdb99c81c195c9a5bd960a21b604482015260640161061b565b6001546111d0906001600160a01b0316333086611fd1565b6111dc338484846125df565b505050565b60006111ec60025490565b905090565b33600090815260046020526040902080548390811061121257611212613129565b60009182526020909120600460059092020101546001600160401b031642101561126f5760405162461bcd60e51b815260206004820152600e60248201526d1058d8dbdd5b9d081b1bd8dad95960921b604482015260640161061b565b61127a338383612473565b5050565b336112916000546001600160a01b031690565b6001600160a01b0316146112b75760405162461bcd60e51b815260040161061b90612ec8565b60648111156112fb5760405162461bcd60e51b815260206004820152601060248201526f2bb937b7339036bab63a34b83634b2b960811b604482015260640161061b565b600154611313906001600160a01b0316333086611fd1565b61131f848484846125df565b50505050565b3360009081526012602052604090205460ff168061135c5750336113516000546001600160a01b031690565b6001600160a01b0316145b61139e5760405162461bcd60e51b815260206004820152601360248201527221b0b63632b91034b9903737ba1030b236b4b760691b604482015260640161061b565b600e546002146113dd5760405162461bcd60e51b815260206004820152600a602482015269057726f6e6720737465760b41b604482015260640161061b565b600d5460006113eb60025490565b90508161142a576000600e556040805182815260208101839052600281830152905160008051602061314e8339815191529181900360600190a1505050565b600b546011546000905b8381101561175d576000611449600283611ecd565b6001600160a01b03811660009081526004602052604090205490915080881061147d5761147681896130a1565b97506114d1565b6011839055600954611490908590612efd565b600955600e5460408051858152602081018990529081019190915260008051602061314e833981519152906060015b60405180910390a15050505050505050565b60005b81811015611748576001600160a01b038316600090815260046020526040812080548390811061150657611506613129565b906000526020600020906005020160020154905080600014611735576001600160a01b038416600090815260046020526040812080548490811061154c5761154c613129565b600091825260208220600590910201549150611569896064612fbe565b6001600160a01b038716600090815260046020526040902080548690811061159357611593613129565b6000918252602090912060059091020160040154600160801b90046001600160401b031660070b6115c4858e612fbe565b6115ce9190612fbe565b6115d89190612f56565b90506115e48189612efd565b97506000811315611642576001600160a01b038616600090815260046020526040902080548291908690811061161c5761161c613129565b9060005260206000209060050201600301600082825461163c9190612f3e565b90915550505b61164c8183612efd565b91506000821215611668576116618289613062565b9750600091505b6001600160a01b038616600090815260046020526040902080548391908690811061169557611695613129565b600091825260208083206005909202909101929092556001600160a01b03881681526004909152604081208054869081106116d2576116d2613129565b600091825260209182902060026005909202010191909155604080516001600160a01b038916815291820186905281018290527f4410f5289f71baff2baf30dad8844d6c4d5af1f55fd01dd890aec66584f1677c9060600160405180910390a150505b5080611740816130b8565b9150506114d4565b5082611753816130b8565b9350505050611434565b8160095461176b9190612efd565b6009556000600e81905560118190556001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b1580156117bd57600080fd5b505afa1580156117d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f59190612d5c565b90506000611801610521565b60095460408051918252602082018390529192507fd9cdec0295c8edc1c466e37dd37c5afeabaea2e083fe8aabc6b74cd6094182cb910160405180910390a1600954811015801561185157508082115b1561188757600154611887906001600160a01b03166118786000546001600160a01b031690565b61188284866130a1565b61235f565b604080518481526020810188905260029181019190915260008051602061314e833981519152906060016114bf565b336118c96000546001600160a01b031690565b6001600160a01b0316146118ef5760405162461bcd60e51b815260040161061b90612ec8565b60006118f9611f5e565b6001600160a01b0385166000908152600460205260408120805492935090918590811061192857611928613129565b906000526020600020906005020190506119428282612101565b80548015611a195783156119bf57600154611978906001600160a01b03166119726000546001600160a01b031690565b8361235f565b604080516001600160a01b0388168152602081018390527fa859066e89895ffb9f2cdf2af7e7e84061fcb7ddd8657877c264737f25f8b655910160405180910390a1611a19565b6001546119d6906001600160a01b0316878361235f565b604080516001600160a01b0388168152602081018390527f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd910160405180910390a15b6004820154600160c01b900460ff16611a44578060096000828254611a3e91906130a1565b90915550505b8160010154600a6000828254611a5a91906130a1565b90915550506002820154600b8054600090611a769084906130a1565b90915550506001600160a01b038616600090815260046020526040812054611aa0906001906130a1565b905080611b5c576001600160a01b0387166000908152600460205260409020805480611ace57611ace613113565b600082815260208120600560001990930192830201818155600181018290556002808201839055600382019290925560040180546001600160c81b03191690559155611b1a9088612815565b506040516001600160a01b03881681527f0ad8e54ac59bf2d8a7a1474c1af503b593553cf4fcaaffdef04ab5249f89762b9060200160405180910390a1611d4f565b808614611ca1576001600160a01b0387166000908152600460205260409020805482908110611b8d57611b8d613129565b906000526020600020906005020160046000896001600160a01b03166001600160a01b031681526020019081526020016000208781548110611bd157611bd1613129565b6000918252602090912082546005909202019081556001808301549082015560028083015490820155600380830154908201556004918201805492909101805467ffffffffffffffff1981166001600160401b0394851690811783558354600160401b908190048616026001600160801b031990921617178082558254600160801b9081900490941690930267ffffffffffffffff60801b19841681178255915460ff600160c01b91829004160260ff60c01b1990921668ffffffffffffffffff60801b19909316929092171790555b6001600160a01b0387166000908152600460205260409020805480611cc857611cc8613113565b600082815260208082206005600019949094019384020182815560018101839055600281018390556003810192909255600490910180546001600160c81b03191690559155604080516001600160a01b038a1681529182018890527f52da67f845146a7b07a837a7e32b5b74f6d3fafb17ec6c04f23acfc9e1aa9d1f910160405180910390a15b50505050505050565b33611d6b6000546001600160a01b031690565b6001600160a01b031614611d915760405162461bcd60e51b815260040161061b90612ec8565b600655565b33611da96000546001600160a01b031690565b6001600160a01b031614611dcf5760405162461bcd60e51b815260040161061b90612ec8565b600855565b33611de76000546001600160a01b031690565b6001600160a01b031614611e0d5760405162461bcd60e51b815260040161061b90612ec8565b6001600160a01b038116611e725760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161061b565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b81546000908210611f2b5760405162461bcd60e51b815260206004820152602260248201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604482015261647360f01b606482015260840161061b565b826000018281548110611f4057611f40613129565b6000918252602090912001546001600160a01b031690505b92915050565b6000611f6d6201518042612f84565b9050600f54811115611fa857600080611f8e83600f54600954600a54612957565b600f859055600a819055909250905081156105dd5750600b555b90565b60008080611fc4611fbf6201518086612f84565b6129f6565b9196909550909350915050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916120359190612dea565b6000604051808303816000865af19150503d8060008114612072576040519150601f19603f3d011682016040523d82523d6000602084013e612077565b606091505b50915091508180156120a15750805115806120a15750808060200190518101906120a19190612d26565b6120f95760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b606482015260840161061b565b505050505050565b6004810154600160c01b900460ff16806122df5781546001830154600484015460009061213b9062015180906001600160401b0316612f98565b6001600160401b0316905085811161226d5760008061215c88848787612957565b9150915080600a600082825461217291906130a1565b909155505081156121955781600b600082825461218f91906130a1565b90915550505b60048701546121b7908490600160401b90046001600160401b03168787612957565b60048901805467ffffffffffffffff60401b1916600160401b6001600160401b038d160217905560018901819055909250905081156121f857600287018290555b80156122185760048701805460ff60c01b1916600160c01b17905561224e565b81156122385760048701805460ff60c01b1916600160c11b17905561224e565b60048701805460ff60c01b1916600360c01b1790555b846009600082825461226091906130a1565b909155506120f992505050565b60048501546000908190612294908990600160401b90046001600160401b03168787612957565b60048901805467ffffffffffffffff60401b1916600160401b6001600160401b038d160217905560018901819055909250905081156122d557600287018290555b5050505050505050565b8060ff16600114801561230557506004820154600160401b90046001600160401b031683115b801561231357506002820154155b156111dc57600182018054600284018190556000909155156123475750600401805460ff60c01b1916600160c11b17905550565b50600401805460ff60c01b1916600360c01b17905550565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916123bb9190612dea565b6000604051808303816000865af19150503d80600081146123f8576040519150601f19603f3d011682016040523d82523d6000602084013e6123fd565b606091505b50915091508180156124275750805115806124275750808060200190518101906124279190612d26565b610e845760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c454400604482015260640161061b565b600061247d611f5e565b6001600160a01b038516600090815260046020526040812080549293509091859081106124ac576124ac613129565b906000526020600020906005020190506124c68282612101565b80546000808355600383015580156125a157831561254757600154612500906001600160a01b03166119726000546001600160a01b031690565b604080516001600160a01b0388168152602081018390527fa859066e89895ffb9f2cdf2af7e7e84061fcb7ddd8657877c264737f25f8b655910160405180910390a16125a1565b60015461255e906001600160a01b0316878361235f565b604080516001600160a01b0388168152602081018390527f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd910160405180910390a15b60028201541580156125b557506001820154155b156120f9576001600160a01b038616600090815260046020526040812054611aa0906001906130a1565b6125e7611f5e565b506001600160a01b038416600090815260046020526040902054600a116126505760405162461bcd60e51b815260206004820152601e60248201527f416c6c6f776564203130206465706f73697473207065722077616c6c65740000604482015260640161061b565b82600960008282546126629190612f3e565b909155506126739050600285612b69565b5060046000856001600160a01b03166001600160a01b0316815260200190815260200160002060405180610100016040528085815260200160008152602001600081526020016000815260200184620151806126cf9190613043565b6126d99042612f3e565b6001600160401b031681526020016126f46201518042612f84565b6001600160401b0390811682528481166020808401919091526000604093840181905285546001818101885596825290829020855160059092020190815590840151948101949094558282015160028501556060830151600385015560808301516004909401805460a085015160c086015160e09096015160ff16600160c01b0260ff60c01b19968516600160801b029690961668ffffffffffffffffff60801b19918516600160401b026001600160801b0319909316979094169690961717949094161791909117909155517ff556991011e831bcfac4f406d547e5e32cdd98267efab83935230d5f8d02c44690610ab79086908690869086906001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b0381166000908152600183016020526040812054801561294d5760006128436001836130a1565b8554909150600090612857906001906130a1565b9050600086600001828154811061287057612870613129565b60009182526020909120015487546001600160a01b039091169150819088908590811061289f5761289f613129565b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790556128d3836001612f3e565b6001600160a01b038216600090815260018901602052604090205586548790806128ff576128ff613113565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220919091559450611f589350505050565b6000915050611f58565b600081848611156129ed57600061296e86886130a1565b9050600061297b886129f6565b925050508181116129d357600061299282846130a1565b61299d906001612f3e565b90506129a98188613043565b6129b39087612f3e565b94506129bf81846130a1565b92506129cb8388613043565b9350506129ea565b6129dd8287613043565b6129e79086612f3e565b92505b50505b94509492505050565b600080808381612a098262010bd9612efd565b612a169062253d8c612efd565b9050600062023ab1612a29836004612fbe565b612a339190612f56565b90506004612a448262023ab1612fbe565b612a4f906003612efd565b612a599190612f56565b612a639083613062565b9150600062164b09612a76846001612efd565b612a8290610fa0612fbe565b612a8c9190612f56565b90506004612a9c826105b5612fbe565b612aa69190612f56565b612ab09084613062565b612abb90601f612efd565b9250600061098f612acd856050612fbe565b612ad79190612f56565b905060006050612ae98361098f612fbe565b612af39190612f56565b612afd9086613062565b9050612b0a600b83612f56565b9450612b1785600c612fbe565b612b22836002612efd565b612b2c9190613062565b91508483612b3b603187613062565b612b46906064612fbe565b612b509190612efd565b612b5a9190612efd565b9a919950975095505050505050565b6001600160a01b0381166000908152600183016020526040812054612bd357508154600180820184556000848152602080822090930180546001600160a01b0319166001600160a01b03861690811790915585549082528286019093526040902091909155611f58565b506000611f58565b80356001600160a01b0381168114612bf257600080fd5b919050565b600060208284031215612c0957600080fd5b612c1282612bdb565b9392505050565b60008060408385031215612c2c57600080fd5b612c3583612bdb565b9150612c4360208401612bdb565b90509250929050565b60008060408385031215612c5f57600080fd5b612c6883612bdb565b91506020830135612c788161313f565b809150509250929050565b60008060408385031215612c9657600080fd5b612c9f83612bdb565b946020939093013593505050565b600080600060608486031215612cc257600080fd5b612ccb84612bdb565b9250602084013591506040840135612ce28161313f565b809150509250925092565b60008060008060808587031215612d0357600080fd5b612d0c85612bdb565b966020860135965060408601359560600135945092505050565b600060208284031215612d3857600080fd5b8151612c128161313f565b600060208284031215612d5557600080fd5b5035919050565b600060208284031215612d6e57600080fd5b5051919050565b60008060408385031215612d8857600080fd5b823591506020830135612c788161313f565b60008060408385031215612dad57600080fd5b50508035926020909101359150565b600080600060608486031215612dd157600080fd5b83359250602084013591506040840135612ce28161313f565b6000825160005b81811015612e0b5760208186018101518583015201612df1565b81811115612e1a576000828501525b509190910192915050565b602080825282518282018190526000919060409081850190868401855b82811015612ebb5781518051855286810151878601528581015186860152606080820151908601526080808201516001600160401b039081169187019190915260a08083015182169087015260c0808301519091169086015260e09081015160ff16908501526101009093019290850190600101612e42565b5091979650505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600080821280156001600160ff1b0384900385131615612f1f57612f1f6130e7565b600160ff1b8390038412811615612f3857612f386130e7565b50500190565b60008219821115612f5157612f516130e7565b500190565b600082612f6557612f656130fd565b600160ff1b821460001984141615612f7f57612f7f6130e7565b500590565b600082612f9357612f936130fd565b500490565b60006001600160401b0380841680612fb257612fb26130fd565b92169190910492915050565b60006001600160ff1b0381841382841380821686840486111615612fe457612fe46130e7565b600160ff1b6000871282811687830589121615613003576130036130e7565b6000871292508782058712848416161561301f5761301f6130e7565b87850587128184161615613035576130356130e7565b505050929093029392505050565b600081600019048311821515161561305d5761305d6130e7565b500290565b60008083128015600160ff1b850184121615613080576130806130e7565b6001600160ff1b038401831381161561309b5761309b6130e7565b50500390565b6000828210156130b3576130b36130e7565b500390565b60006000198214156130cc576130cc6130e7565b5060010190565b6000826130e2576130e26130fd565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b8015158114610ac357600080fdfec534675d962a9c4b4a6eef4e934d46b14162000192fa31cf0c29cd81fdb8c2eea26469706673582212204c204c8cd7d2ba6046672effa6399deabc37b731022d25dd151d6c57e159ca6764736f6c63430008060033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106102275760003560e01c80639652b12111610130578063e6fc015e116100b8578063eeb4a9c81161007c578063eeb4a9c8146104b6578063f2fde38b146104c9578063f7cb8124146104dc578063fc0c546a146104e5578063ff293df3146104f857600080fd5b8063e6fc015e1461046b578063ebda3b051461047e578063ed47ab5b14610487578063edcb208b1461049a578063ee79da19146104ad57600080fd5b8063bb0c8298116100ff578063bb0c829814610434578063bbe0d9f61461043d578063bc10b17214610450578063cb028a8314610459578063e03aabe61461046257600080fd5b80639652b121146104065780639ebea88c1461040f578063aa8c532414610422578063ab2e58dd1461042b57600080fd5b8063485cc955116101b35780636696f3ff116101825780636696f3ff146103b45780637b0472f0146103bd5780637fe91239146103d0578063817b1cd2146103d85780638da5cb5b146103e157600080fd5b8063485cc9551461031b5780634b0bddd21461032e57806354a02f9e146103415780635c141991146103a157600080fd5b806320114ac2116101fa57806320114ac21461029c57806328a6a2dd146102af578063333271d0146102c257806334553147146102d5578063429b62e5146102e857600080fd5b806305e30f511461022c57806312b583491461025f57806313c02846146102675780631e0927e81461027c575b600080fd5b61024c61023a366004612d43565b60056020526000908152604090205481565b6040519081526020015b60405180910390f35b61024c610521565b61027a610275366004612d43565b6105e2565b005b61028f61028a366004612d43565b6107c4565b6040516102569190612e25565b61027a6102aa366004612d43565b6108ab565b61028f6102bd366004612bf7565b610ac6565b61027a6102d0366004612d9a565b610b9d565b61027a6102e3366004612dbc565b610c2c565b61030b6102f6366004612bf7565b60126020526000908152604090205460ff1681565b6040519015158152602001610256565b61027a610329366004612c19565b610e8b565b61027a61033c366004612c4c565b610fc6565b61035461034f366004612c83565b61105b565b6040805198895260208901979097529587019490945260608601929092526001600160401b03908116608086015290811660a08501521660c083015260ff1660e082015261010001610256565b61027a6103af366004612d43565b6110d2565b61024c60105481565b61027a6103cb366004612d9a565b611110565b61024c6111e1565b61024c60095481565b6000546001600160a01b03165b6040516001600160a01b039091168152602001610256565b61024c600d5481565b61027a61041d366004612d75565b6111f1565b61024c60075481565b61024c60115481565b61024c60085481565b61027a61044b366004612ced565b61127e565b61024c600a5481565b61024c60065481565b61024c600f5481565b61027a610479366004612d43565b611325565b61024c600e5481565b61027a610495366004612cad565b6118b6565b61027a6104a8366004612d43565b611d58565b61024c600c5481565b61027a6104c4366004612d43565b611d96565b61027a6104d7366004612bf7565b611dd4565b61024c600b5481565b6001546103ee906001600160a01b031681565b61024c610506366004612bf7565b6001600160a01b031660009081526004602052604090205490565b60008061052d60025490565b905060005b818110156105dd576000610547600283611ecd565b6001600160a01b0381166000908152600460205260408120549192505b818110156105c7576001600160a01b038316600090815260046020526040902080548290811061059657610596613129565b906000526020600020906005020160000154866105b39190612f3e565b9550806105bf816130b8565b915050610564565b50505080806105d5906130b8565b915050610532565b505090565b336105f56000546001600160a01b031690565b6001600160a01b0316146106245760405162461bcd60e51b815260040161061b90612ec8565b60405180910390fd5b600e541561067e5760405162461bcd60e51b815260206004820152602160248201527f50726576696f757320726573756c7420776173206e6f742070726f63657373656044820152601960fa1b606482015260840161061b565b610686611f5e565b50600061069242611fab565b509150508060105414156106f85760405162461bcd60e51b815260206004820152602760248201527f526573756c74206d6179206265206164646564206f6e6c79206f6e63652070656044820152660e440dadedce8d60cb1b606482015260840161061b565b6010819055600d829055600954600090610713908490612efd565b12156107615760405162461bcd60e51b815260206004820152601c60248201527f746f74616c5374616b6564206c657373207468656e20616d6f756e7400000000604482015260640161061b565b600082131561078257600154610782906001600160a01b0316333085611fd1565b6001600e5560006011556040518281527f7e378eda7a53c9c96fb609c656ea4cddfd3f364b2fd5a0338fed559471da4fbe906020015b60405180910390a15050565b606060006107d3600284611ecd565b6001600160a01b0381166000908152600460209081526040808320805482518185028101850190935280835294955090939092909184015b8282101561089f576000848152602090819020604080516101008101825260058602909201805483526001808201548486015260028201549284019290925260038101546060840152600401546001600160401b038082166080850152600160401b8204811660a0850152600160801b82041660c0840152600160c01b900460ff1660e0830152908352909201910161080b565b50505050915050919050565b3360009081526012602052604090205460ff16806108e25750336108d76000546001600160a01b031690565b6001600160a01b0316145b6109245760405162461bcd60e51b815260206004820152601360248201527221b0b63632b91034b9903737ba1030b236b4b760691b604482015260640161061b565b600e546001146109635760405162461bcd60e51b815260206004820152600a602482015269057726f6e6720737465760b41b604482015260640161061b565b60006109726201518042612f84565b601154909150600061098360025490565b90505b80821015610a8257600061099b600284611ecd565b6001600160a01b0381166000908152600460205260409020549091508086106109cf576109c881876130a1565b9550610a0d565b6011849055600e546040805186815260208101869052808201929092525160008051602061314e8339815191529181900360600190a1505050505050565b60005b81811015610a6d576001600160a01b03831660009081526004602052604090208054610a5b91889184908110610a4857610a48613129565b9060005260206000209060050201612101565b80610a65816130b8565b915050610a10565b5083610a78816130b8565b9450505050610986565b6002600e556000601155604080518381526020810183905260019181019190915260008051602061314e833981519152906060015b60405180910390a15050505b50565b6001600160a01b0381166000908152600460209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610b92576000848152602090819020604080516101008101825260058602909201805483526001808201548486015260028201549284019290925260038101546060840152600401546001600160401b038082166080850152600160401b8204811660a0850152600160801b82041660c0840152600160c01b900460ff1660e08301529083529092019101610afe565b505050509050919050565b33610bb06000546001600160a01b031690565b6001600160a01b031614610bd65760405162461bcd60e51b815260040161061b90612ec8565b6064811115610c1a5760405162461bcd60e51b815260206004820152601060248201526f2bb937b7339036bab63a34b83634b2b960811b604482015260640161061b565b60009182526005602052604090912055565b336000908152600460205260408120805485908110610c4d57610c4d613129565b6000918252602090912060059091020160048101549091506001600160401b031642811115610e79576000610c8242836130a1565b905060075481610c9291906130d3565b9050600654600754610ca491906130a1565b811180610caf575080155b610cf45760405162461bcd60e51b81526020600482015260166024820152754f7574206f662077697468647261772077696e646f7760501b604482015260640161061b565b6003830154808611801590610d0a575083548611155b610d4b5760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f756768207265776172647360701b604482015260640161061b565b6000610d55611f5e565b9050610d618186612101565b610d6b87836130a1565b6003860155845487908690600090610d849084906130a1565b90915550506004850154600160c01b900460ff16610db4578660096000828254610dae91906130a1565b90915550505b8515610e2057600154610de2906001600160a01b0316610ddc6000546001600160a01b031690565b8961235f565b60408051338152602081018990527fa859066e89895ffb9f2cdf2af7e7e84061fcb7ddd8657877c264737f25f8b655910160405180910390a1610e71565b600154610e37906001600160a01b0316338961235f565b60408051338152602081018990527f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd910160405180910390a15b505050610e84565b610e84338685612473565b5050505050565b6001600160a01b03821615801590610eac57506000546001600160a01b0316155b610eb557600080fd5b600080546001600160a01b038085166001600160a01b031992831617835560018054918516919092161790556040513391907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350506206978060065562278d00600755680ad78ebc5ac6200000600855600560205260197faadf04b4a1bf84e121ab68e5c1cffab5aeb9be1a024ff9944a2a0bc1674866095560327fec79235ffe9302935718f9bddc23f2c5c6c950ae49f49d137c786213c361802755604b7fe78ea91a221fb67f10aba14ba22dc39f780130b5cf7d2295f57a7414e295968b5561016860005260647f5464d34515fb195718451914a9b5e2c4ac04dce5fd392ea5e3f190355ea2fb7e55565b33610fd96000546001600160a01b031690565b6001600160a01b031614610fff5760405162461bcd60e51b815260040161061b90612ec8565b6001600160a01b038216600081815260126020908152604091829020805460ff19168515159081179091558251938452908301527f55a5194bc0174fcaf12b2978bef43911466bf63b34db8d1dd1a0d5dcd5c41bea91016107b8565b6004602052816000526040600020818154811061107757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015492955090935091906001600160401b0380821691600160401b8104821691600160801b82041690600160c01b900460ff1688565b336110e56000546001600160a01b031690565b6001600160a01b03161461110b5760405162461bcd60e51b815260040161061b90612ec8565b600755565b60085482101561116d5760405162461bcd60e51b815260206004820152602260248201527f5374616b656420616d6f756e74206973206c657373207468656e206d696e696d604482015261756d60f01b606482015260840161061b565b600081815260056020526040902054806111b85760405162461bcd60e51b815260206004820152600c60248201526b15dc9bdb99c81c195c9a5bd960a21b604482015260640161061b565b6001546111d0906001600160a01b0316333086611fd1565b6111dc338484846125df565b505050565b60006111ec60025490565b905090565b33600090815260046020526040902080548390811061121257611212613129565b60009182526020909120600460059092020101546001600160401b031642101561126f5760405162461bcd60e51b815260206004820152600e60248201526d1058d8dbdd5b9d081b1bd8dad95960921b604482015260640161061b565b61127a338383612473565b5050565b336112916000546001600160a01b031690565b6001600160a01b0316146112b75760405162461bcd60e51b815260040161061b90612ec8565b60648111156112fb5760405162461bcd60e51b815260206004820152601060248201526f2bb937b7339036bab63a34b83634b2b960811b604482015260640161061b565b600154611313906001600160a01b0316333086611fd1565b61131f848484846125df565b50505050565b3360009081526012602052604090205460ff168061135c5750336113516000546001600160a01b031690565b6001600160a01b0316145b61139e5760405162461bcd60e51b815260206004820152601360248201527221b0b63632b91034b9903737ba1030b236b4b760691b604482015260640161061b565b600e546002146113dd5760405162461bcd60e51b815260206004820152600a602482015269057726f6e6720737465760b41b604482015260640161061b565b600d5460006113eb60025490565b90508161142a576000600e556040805182815260208101839052600281830152905160008051602061314e8339815191529181900360600190a1505050565b600b546011546000905b8381101561175d576000611449600283611ecd565b6001600160a01b03811660009081526004602052604090205490915080881061147d5761147681896130a1565b97506114d1565b6011839055600954611490908590612efd565b600955600e5460408051858152602081018990529081019190915260008051602061314e833981519152906060015b60405180910390a15050505050505050565b60005b81811015611748576001600160a01b038316600090815260046020526040812080548390811061150657611506613129565b906000526020600020906005020160020154905080600014611735576001600160a01b038416600090815260046020526040812080548490811061154c5761154c613129565b600091825260208220600590910201549150611569896064612fbe565b6001600160a01b038716600090815260046020526040902080548690811061159357611593613129565b6000918252602090912060059091020160040154600160801b90046001600160401b031660070b6115c4858e612fbe565b6115ce9190612fbe565b6115d89190612f56565b90506115e48189612efd565b97506000811315611642576001600160a01b038616600090815260046020526040902080548291908690811061161c5761161c613129565b9060005260206000209060050201600301600082825461163c9190612f3e565b90915550505b61164c8183612efd565b91506000821215611668576116618289613062565b9750600091505b6001600160a01b038616600090815260046020526040902080548391908690811061169557611695613129565b600091825260208083206005909202909101929092556001600160a01b03881681526004909152604081208054869081106116d2576116d2613129565b600091825260209182902060026005909202010191909155604080516001600160a01b038916815291820186905281018290527f4410f5289f71baff2baf30dad8844d6c4d5af1f55fd01dd890aec66584f1677c9060600160405180910390a150505b5080611740816130b8565b9150506114d4565b5082611753816130b8565b9350505050611434565b8160095461176b9190612efd565b6009556000600e81905560118190556001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b1580156117bd57600080fd5b505afa1580156117d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f59190612d5c565b90506000611801610521565b60095460408051918252602082018390529192507fd9cdec0295c8edc1c466e37dd37c5afeabaea2e083fe8aabc6b74cd6094182cb910160405180910390a1600954811015801561185157508082115b1561188757600154611887906001600160a01b03166118786000546001600160a01b031690565b61188284866130a1565b61235f565b604080518481526020810188905260029181019190915260008051602061314e833981519152906060016114bf565b336118c96000546001600160a01b031690565b6001600160a01b0316146118ef5760405162461bcd60e51b815260040161061b90612ec8565b60006118f9611f5e565b6001600160a01b0385166000908152600460205260408120805492935090918590811061192857611928613129565b906000526020600020906005020190506119428282612101565b80548015611a195783156119bf57600154611978906001600160a01b03166119726000546001600160a01b031690565b8361235f565b604080516001600160a01b0388168152602081018390527fa859066e89895ffb9f2cdf2af7e7e84061fcb7ddd8657877c264737f25f8b655910160405180910390a1611a19565b6001546119d6906001600160a01b0316878361235f565b604080516001600160a01b0388168152602081018390527f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd910160405180910390a15b6004820154600160c01b900460ff16611a44578060096000828254611a3e91906130a1565b90915550505b8160010154600a6000828254611a5a91906130a1565b90915550506002820154600b8054600090611a769084906130a1565b90915550506001600160a01b038616600090815260046020526040812054611aa0906001906130a1565b905080611b5c576001600160a01b0387166000908152600460205260409020805480611ace57611ace613113565b600082815260208120600560001990930192830201818155600181018290556002808201839055600382019290925560040180546001600160c81b03191690559155611b1a9088612815565b506040516001600160a01b03881681527f0ad8e54ac59bf2d8a7a1474c1af503b593553cf4fcaaffdef04ab5249f89762b9060200160405180910390a1611d4f565b808614611ca1576001600160a01b0387166000908152600460205260409020805482908110611b8d57611b8d613129565b906000526020600020906005020160046000896001600160a01b03166001600160a01b031681526020019081526020016000208781548110611bd157611bd1613129565b6000918252602090912082546005909202019081556001808301549082015560028083015490820155600380830154908201556004918201805492909101805467ffffffffffffffff1981166001600160401b0394851690811783558354600160401b908190048616026001600160801b031990921617178082558254600160801b9081900490941690930267ffffffffffffffff60801b19841681178255915460ff600160c01b91829004160260ff60c01b1990921668ffffffffffffffffff60801b19909316929092171790555b6001600160a01b0387166000908152600460205260409020805480611cc857611cc8613113565b600082815260208082206005600019949094019384020182815560018101839055600281018390556003810192909255600490910180546001600160c81b03191690559155604080516001600160a01b038a1681529182018890527f52da67f845146a7b07a837a7e32b5b74f6d3fafb17ec6c04f23acfc9e1aa9d1f910160405180910390a15b50505050505050565b33611d6b6000546001600160a01b031690565b6001600160a01b031614611d915760405162461bcd60e51b815260040161061b90612ec8565b600655565b33611da96000546001600160a01b031690565b6001600160a01b031614611dcf5760405162461bcd60e51b815260040161061b90612ec8565b600855565b33611de76000546001600160a01b031690565b6001600160a01b031614611e0d5760405162461bcd60e51b815260040161061b90612ec8565b6001600160a01b038116611e725760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161061b565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b81546000908210611f2b5760405162461bcd60e51b815260206004820152602260248201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604482015261647360f01b606482015260840161061b565b826000018281548110611f4057611f40613129565b6000918252602090912001546001600160a01b031690505b92915050565b6000611f6d6201518042612f84565b9050600f54811115611fa857600080611f8e83600f54600954600a54612957565b600f859055600a819055909250905081156105dd5750600b555b90565b60008080611fc4611fbf6201518086612f84565b6129f6565b9196909550909350915050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916120359190612dea565b6000604051808303816000865af19150503d8060008114612072576040519150601f19603f3d011682016040523d82523d6000602084013e612077565b606091505b50915091508180156120a15750805115806120a15750808060200190518101906120a19190612d26565b6120f95760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b606482015260840161061b565b505050505050565b6004810154600160c01b900460ff16806122df5781546001830154600484015460009061213b9062015180906001600160401b0316612f98565b6001600160401b0316905085811161226d5760008061215c88848787612957565b9150915080600a600082825461217291906130a1565b909155505081156121955781600b600082825461218f91906130a1565b90915550505b60048701546121b7908490600160401b90046001600160401b03168787612957565b60048901805467ffffffffffffffff60401b1916600160401b6001600160401b038d160217905560018901819055909250905081156121f857600287018290555b80156122185760048701805460ff60c01b1916600160c01b17905561224e565b81156122385760048701805460ff60c01b1916600160c11b17905561224e565b60048701805460ff60c01b1916600360c01b1790555b846009600082825461226091906130a1565b909155506120f992505050565b60048501546000908190612294908990600160401b90046001600160401b03168787612957565b60048901805467ffffffffffffffff60401b1916600160401b6001600160401b038d160217905560018901819055909250905081156122d557600287018290555b5050505050505050565b8060ff16600114801561230557506004820154600160401b90046001600160401b031683115b801561231357506002820154155b156111dc57600182018054600284018190556000909155156123475750600401805460ff60c01b1916600160c11b17905550565b50600401805460ff60c01b1916600360c01b17905550565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916123bb9190612dea565b6000604051808303816000865af19150503d80600081146123f8576040519150601f19603f3d011682016040523d82523d6000602084013e6123fd565b606091505b50915091508180156124275750805115806124275750808060200190518101906124279190612d26565b610e845760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c454400604482015260640161061b565b600061247d611f5e565b6001600160a01b038516600090815260046020526040812080549293509091859081106124ac576124ac613129565b906000526020600020906005020190506124c68282612101565b80546000808355600383015580156125a157831561254757600154612500906001600160a01b03166119726000546001600160a01b031690565b604080516001600160a01b0388168152602081018390527fa859066e89895ffb9f2cdf2af7e7e84061fcb7ddd8657877c264737f25f8b655910160405180910390a16125a1565b60015461255e906001600160a01b0316878361235f565b604080516001600160a01b0388168152602081018390527f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd910160405180910390a15b60028201541580156125b557506001820154155b156120f9576001600160a01b038616600090815260046020526040812054611aa0906001906130a1565b6125e7611f5e565b506001600160a01b038416600090815260046020526040902054600a116126505760405162461bcd60e51b815260206004820152601e60248201527f416c6c6f776564203130206465706f73697473207065722077616c6c65740000604482015260640161061b565b82600960008282546126629190612f3e565b909155506126739050600285612b69565b5060046000856001600160a01b03166001600160a01b0316815260200190815260200160002060405180610100016040528085815260200160008152602001600081526020016000815260200184620151806126cf9190613043565b6126d99042612f3e565b6001600160401b031681526020016126f46201518042612f84565b6001600160401b0390811682528481166020808401919091526000604093840181905285546001818101885596825290829020855160059092020190815590840151948101949094558282015160028501556060830151600385015560808301516004909401805460a085015160c086015160e09096015160ff16600160c01b0260ff60c01b19968516600160801b029690961668ffffffffffffffffff60801b19918516600160401b026001600160801b0319909316979094169690961717949094161791909117909155517ff556991011e831bcfac4f406d547e5e32cdd98267efab83935230d5f8d02c44690610ab79086908690869086906001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b0381166000908152600183016020526040812054801561294d5760006128436001836130a1565b8554909150600090612857906001906130a1565b9050600086600001828154811061287057612870613129565b60009182526020909120015487546001600160a01b039091169150819088908590811061289f5761289f613129565b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790556128d3836001612f3e565b6001600160a01b038216600090815260018901602052604090205586548790806128ff576128ff613113565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220919091559450611f589350505050565b6000915050611f58565b600081848611156129ed57600061296e86886130a1565b9050600061297b886129f6565b925050508181116129d357600061299282846130a1565b61299d906001612f3e565b90506129a98188613043565b6129b39087612f3e565b94506129bf81846130a1565b92506129cb8388613043565b9350506129ea565b6129dd8287613043565b6129e79086612f3e565b92505b50505b94509492505050565b600080808381612a098262010bd9612efd565b612a169062253d8c612efd565b9050600062023ab1612a29836004612fbe565b612a339190612f56565b90506004612a448262023ab1612fbe565b612a4f906003612efd565b612a599190612f56565b612a639083613062565b9150600062164b09612a76846001612efd565b612a8290610fa0612fbe565b612a8c9190612f56565b90506004612a9c826105b5612fbe565b612aa69190612f56565b612ab09084613062565b612abb90601f612efd565b9250600061098f612acd856050612fbe565b612ad79190612f56565b905060006050612ae98361098f612fbe565b612af39190612f56565b612afd9086613062565b9050612b0a600b83612f56565b9450612b1785600c612fbe565b612b22836002612efd565b612b2c9190613062565b91508483612b3b603187613062565b612b46906064612fbe565b612b509190612efd565b612b5a9190612efd565b9a919950975095505050505050565b6001600160a01b0381166000908152600183016020526040812054612bd357508154600180820184556000848152602080822090930180546001600160a01b0319166001600160a01b03861690811790915585549082528286019093526040902091909155611f58565b506000611f58565b80356001600160a01b0381168114612bf257600080fd5b919050565b600060208284031215612c0957600080fd5b612c1282612bdb565b9392505050565b60008060408385031215612c2c57600080fd5b612c3583612bdb565b9150612c4360208401612bdb565b90509250929050565b60008060408385031215612c5f57600080fd5b612c6883612bdb565b91506020830135612c788161313f565b809150509250929050565b60008060408385031215612c9657600080fd5b612c9f83612bdb565b946020939093013593505050565b600080600060608486031215612cc257600080fd5b612ccb84612bdb565b9250602084013591506040840135612ce28161313f565b809150509250925092565b60008060008060808587031215612d0357600080fd5b612d0c85612bdb565b966020860135965060408601359560600135945092505050565b600060208284031215612d3857600080fd5b8151612c128161313f565b600060208284031215612d5557600080fd5b5035919050565b600060208284031215612d6e57600080fd5b5051919050565b60008060408385031215612d8857600080fd5b823591506020830135612c788161313f565b60008060408385031215612dad57600080fd5b50508035926020909101359150565b600080600060608486031215612dd157600080fd5b83359250602084013591506040840135612ce28161313f565b6000825160005b81811015612e0b5760208186018101518583015201612df1565b81811115612e1a576000828501525b509190910192915050565b602080825282518282018190526000919060409081850190868401855b82811015612ebb5781518051855286810151878601528581015186860152606080820151908601526080808201516001600160401b039081169187019190915260a08083015182169087015260c0808301519091169086015260e09081015160ff16908501526101009093019290850190600101612e42565b5091979650505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600080821280156001600160ff1b0384900385131615612f1f57612f1f6130e7565b600160ff1b8390038412811615612f3857612f386130e7565b50500190565b60008219821115612f5157612f516130e7565b500190565b600082612f6557612f656130fd565b600160ff1b821460001984141615612f7f57612f7f6130e7565b500590565b600082612f9357612f936130fd565b500490565b60006001600160401b0380841680612fb257612fb26130fd565b92169190910492915050565b60006001600160ff1b0381841382841380821686840486111615612fe457612fe46130e7565b600160ff1b6000871282811687830589121615613003576130036130e7565b6000871292508782058712848416161561301f5761301f6130e7565b87850587128184161615613035576130356130e7565b505050929093029392505050565b600081600019048311821515161561305d5761305d6130e7565b500290565b60008083128015600160ff1b850184121615613080576130806130e7565b6001600160ff1b038401831381161561309b5761309b6130e7565b50500390565b6000828210156130b3576130b36130e7565b500390565b60006000198214156130cc576130cc6130e7565b5060010190565b6000826130e2576130e26130fd565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b8015158114610ac357600080fdfec534675d962a9c4b4a6eef4e934d46b14162000192fa31cf0c29cd81fdb8c2eea26469706673582212204c204c8cd7d2ba6046672effa6399deabc37b731022d25dd151d6c57e159ca6764736f6c63430008060033