Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- MoniesTree
- Optimization enabled
- true
- Compiler version
- v0.8.20+commit.a1b79de6
- Optimization runs
- 200
- EVM Version
- shanghai
- Verified at
- 2026-01-18T07:38:52.408074Z
src/constants/contracts/test10min.sol
// SPDX-License-Identifier: UNLICENSED
// DEV-Telegram: @DevOctahedron
pragma solidity ^0.8.0;
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function allowance(
address owner,
address spender
) external view returns (uint256);
function decimals() external view returns (uint8);
function burn(uint256 amount) external;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
interface IPancakeRouter01 {
function factory() external pure returns (address);
function WPLS() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
)
external
payable
returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable returns (uint[] memory amounts);
function swapTokensForExactETH(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactTokensForETH(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapETHForExactTokens(
uint amountOut,
address[] calldata path,
address to,
uint deadline
) external payable returns (uint[] memory amounts);
function quote(
uint amountA,
uint reserveA,
uint reserveB
) external pure returns (uint amountB);
function getAmountOut(
uint amountIn,
uint reserveIn,
uint reserveOut
) external pure returns (uint amountOut);
function getAmountIn(
uint amountOut,
uint reserveIn,
uint reserveOut
) external pure returns (uint amountIn);
function getAmountsOut(
uint amountIn,
address[] calldata path
) external view returns (uint[] memory amounts);
function getAmountsIn(
uint amountOut,
address[] calldata path
) external view returns (uint[] memory amounts);
}
pragma solidity >=0.6.2;
interface IRouter is IPancakeRouter01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
pragma solidity >=0.6.2;
interface IFactory {
function getPair(
address token1,
address token2
) external pure returns (address);
}
interface IReserveContract {
function updateReserveStake(bool isAdd, uint256 amount) external;
function updateReserveAuction(bool isAdd, uint256 amount) external;
function daysRewardReserved(uint256 day) external view returns (bool);
function reserveDaysReward(uint256 day) external;
function readDaysReservedReward(
uint256 day
) external view returns (uint256);
function currentReserveForReward() external view returns (uint256);
function stakeRewardFactor() external view returns (uint256);
function auctionReserve() external view returns (uint256);
function auctionTokenFactor() external view returns (uint256);
function sendStakeRewardToUser(address user, uint256 amount) external;
function sendAuctionTokenToUser(address user, uint256 amount) external;
function reserveDaysAuctionToken(uint256 day) external;
}
interface IStakeContract {
function rewardsActive() external view returns (bool);
function updateRewards() external;
}
interface IAuctionContract {
function thisDay() external view returns (uint256);
function readCurrentDay() external view returns (uint256);
function _admin() external view returns (address payable);
function TeamAddr(address account) external view returns (bool);
}
contract StakeContract is IStakeContract {
using SafeMath for uint256;
string public constant name = "Stake and Earn Contract";
IAuctionContract public _auction; // the auction contract
IReserveContract public _reserve; // the reserve contract
uint256 public stakeLockTime = 7 days; // TODO change to 7 days
mapping(address => uint256) public userAmount; // User's staked amount
mapping(address => uint256) public userRewardDebt; // Reward debt to track claimed rewards
mapping(address => uint256) public userClaimTime; // users Last Claim TS
mapping(uint256 => uint256) public daysTotalStake; // stores Total staked per day
mapping(address => uint256) public pendingRewards; // Accumulated rewards for users
address[] public allStakers; // Array of all unique users
mapping(address => bool) public userExists; // Tracks if user was added to allStakers
uint256 public totalCurrentStake; // tracks the current amount of staked tokens
uint256 public accRewardPerStake; // Accumulated reward per stake (scaled by 1e18)
uint256 public lastRewardDay = 2; // Last day when rewards were calculated // starting with 2, before there are no Auction token available to users
bool public rewardsActive = true; // true if reward earning started // TODO change to false if you dont want to activate Rewards immediately
bool public rewardsPaused; // true if reward earning is paused
modifier onlySystem() {
require(msg.sender == address(_auction));
_;
}
modifier onlyTeam() {
require(
_auction.TeamAddr(msg.sender) ||
msg.sender == (_auction._admin).address
);
_;
}
event DepositToStakeContract(
address indexed user,
uint256 depositTimeStamp,
uint256 stakeAmount
);
event WithdrawFromStakeContract(
address indexed user,
uint256 withdrawTimeStamp,
uint256 withdrawAmount
);
event ClaimRewardsFromStaking(
address indexed user,
uint256 auctionDay,
uint256 claimTimeStamp,
uint256 rewardAmount
);
event CompoundRewardsFromStaking(
address indexed user,
uint256 auctionDay,
uint256 claimTimeStamp,
uint256 newUserAmount,
uint256 compoundedAmount
);
event UpdateRewardsStakeContract(
uint256 currentDay,
uint256 accRewardPerStake
);
// event AdminClaimedUnclaimableRewards (address indexed user, uint256 claimDay, uint256 reservedRewardSentToAdmin);
constructor() {
_auction = IAuctionContract(msg.sender);
}
// function for the auction contract to set the right reserve contract address
function setReserveContract(address reserve) public onlySystem {
_reserve = IReserveContract(reserve);
}
// update an indivitual uers Reward
function updateUserRewards(address user) public {
if (userAmount[user] == 0) return; // Skip if user has no stake
uint256 pending = userAmount[user].mul(accRewardPerStake).div(1e18).sub(
userRewardDebt[user]
); // calculate pending
pendingRewards[user] += pending; // Accumulate pending rewards before updating debt
userRewardDebt[user] = userAmount[user].mul(accRewardPerStake).div(
1e18
); // Update debt to latest
}
// function to store the right amount of rewars available per stake per day
function updateRewards() public {
uint256 currentDay = _auction.readCurrentDay();
// If rewards are not active, skip the entire function
if (!rewardsActive) {
return;
}
// ensure we are not updating rewards on ongling days
// we initially start with day (lastRewardDay) 2 as before thisDay() = 3 & currentDay = 3 there wont be any reserved rewards anyways
if (lastRewardDay >= currentDay) {
return;
}
// Ensure we skip reward accrual for paused days
if (rewardsPaused) {
lastRewardDay = currentDay;
return;
}
// Ensure current day's stake is properly set
if (daysTotalStake[currentDay] == 0 && totalCurrentStake > 0) {
daysTotalStake[currentDay] = totalCurrentStake;
}
for (uint256 day = lastRewardDay; day < currentDay; day++) {
// make sure we are only processing passed days!
if (!_reserve.daysRewardReserved(day)) {
_reserve.reserveDaysReward(day); // will be 0 if there are no rewards reserved in the reserve contract
}
uint256 daysReward = _reserve.readDaysReservedReward(day);
uint256 stakeAmountForDay = daysTotalStake[day];
// update days current stake amount
if (stakeAmountForDay == 0) {
daysTotalStake[day] = daysTotalStake[day - 1]; // if stakeAmountForDay is zero, the actual stake it the stake of the last finished day
stakeAmountForDay = daysTotalStake[day - 1];
}
if (stakeAmountForDay > 0) {
accRewardPerStake += (
daysReward.mul(1e18).div(stakeAmountForDay)
);
}
}
// Loop through all users and update their pending rewards
for (uint256 i = 0; i < allStakers.length; i++) {
updateUserRewards(allStakers[i]);
}
lastRewardDay = currentDay;
emit UpdateRewardsStakeContract(currentDay, accRewardPerStake);
}
// function for users to deposit token to be staked and eligible for earning
function deposit(uint256 amount) public {
updateRewards(); // Ensure rewards are updated before modifying stakes
updateUserRewards(msg.sender); // Update user's pending rewards
IERC20(address(_auction)).transferFrom(
msg.sender,
address(this),
amount
); // transfer tokens from user to contract
if (!userExists[msg.sender]) {
userExists[msg.sender] = true;
allStakers.push(msg.sender); // Track new staker
}
// update User state, staked amount and reward Dept
userAmount[msg.sender] += amount;
userRewardDebt[msg.sender] = userAmount[msg.sender]
.mul(accRewardPerStake)
.div(1e18); // store the debt like as if it was already all paid out for all stake amount
// update (daily) stake amount and user claim time
totalCurrentStake += amount;
daysTotalStake[_auction.readCurrentDay()] += amount;
userClaimTime[msg.sender] = block.timestamp;
emit DepositToStakeContract(msg.sender, block.timestamp, amount);
}
// function for users to withdraw their staking (if not locked)
function withdraw(uint256 amount) public {
require(readSecondsToUnlock(msg.sender) == 0, "Stake is still locked!");
require(
userAmount[msg.sender] >= amount,
"Withdraw amount exceeds staked balance!"
);
updateRewards(); // Ensure rewards are updated before modifying stakes
updateUserRewards(msg.sender); // Update user's pending rewards before modifying stake
// update User state, staked amount and reward Dept
userAmount[msg.sender] -= amount;
userRewardDebt[msg.sender] = userAmount[msg.sender]
.mul(accRewardPerStake)
.div(1e18);
// update (daily) stake amount
totalCurrentStake -= amount;
daysTotalStake[_auction.readCurrentDay()] -= amount;
// transfer amout to user
bool transfer = IERC20(address(_auction)).transfer(msg.sender, amount);
require(transfer, "Token transfer failed");
emit WithdrawFromStakeContract(msg.sender, block.timestamp, amount);
}
function calculatePending(address user) public view returns (uint256) {
return pendingRewards[user];
}
// function for users to claim their rewards of past days
function claimRewards() public {
updateRewards(); // Update global rewards
updateUserRewards(msg.sender); // Update user-specific pending rewards
uint256 totalRewards = pendingRewards[msg.sender]; // Get pending rewards
require(totalRewards > 0, "No rewards to claim!");
// Reset pending rewards and update user reward debt to current stake
pendingRewards[msg.sender] = 0;
userRewardDebt[msg.sender] = userAmount[msg.sender]
.mul(accRewardPerStake)
.div(1e18);
_reserve.sendStakeRewardToUser(msg.sender, totalRewards);
userClaimTime[msg.sender] = block.timestamp;
emit ClaimRewardsFromStaking(
msg.sender,
_auction.readCurrentDay(),
block.timestamp,
totalRewards
);
}
// function for users to compound their rewards of past days
function compoundRewards() public {
updateRewards(); // Update global rewards
updateUserRewards(msg.sender); // Update user-specific pending rewards
uint256 totalRewards = pendingRewards[msg.sender]; // Get pending rewards
require(totalRewards > 0, "No rewards to claim!");
pendingRewards[msg.sender] = 0; // set pending to 0
// update User state, staked amount and reward Dept, Compound the rewards by adding them to the user's stake
userAmount[msg.sender] += totalRewards;
userRewardDebt[msg.sender] = userAmount[msg.sender]
.mul(accRewardPerStake)
.div(1e18); // update dept for new amount
// transfer pending to stake contract
_reserve.sendStakeRewardToUser(address(this), totalRewards);
// update (daily) stake amount and user claim time
totalCurrentStake += totalRewards;
daysTotalStake[_auction.readCurrentDay()] += totalRewards;
userClaimTime[msg.sender] = block.timestamp;
emit CompoundRewardsFromStaking(
msg.sender,
_auction.readCurrentDay(),
block.timestamp,
userAmount[msg.sender],
totalRewards
);
}
// function to read the seconds until the user can withdraw his stake
// returns the seconds until unlock, or 0 when the user can withdraw
function readSecondsToUnlock(address user) public view returns (uint256) {
if (userClaimTime[user] + stakeLockTime <= block.timestamp) return 0;
else return (userClaimTime[user] + stakeLockTime - block.timestamp);
}
// admin function to set earning start / activate reward earning period ( admin calls once to activate permanently)
function activateRewards() external onlyTeam {
rewardsActive = true;
}
// admin function to pause and unpause reward earning
function pauseRewards(bool state) external onlyTeam {
updateRewards(); // Ensure rewards are up to date before changing the state
rewardsPaused = state;
}
}
contract ReserveContract is IReserveContract {
using SafeMath for uint256;
string public constant name = "Tax and Buy Back Reserve Contract";
IAuctionContract public _auction; // the auction contract
IStakeContract public _userStakeAndEarnContract; // the user stake and earn contract
uint256 public stakeRewardReserve; // stores total token amount reserved for staking rewards
uint256 public stakeRewardFactor = 10; // dafault 10 = 10%, how much of the total Stake reward amount is taken daily to reward stakers
uint256 public overallRewardsReservedForStakers;
uint256 public overallUserRewardsClaimed;
uint256 public auctionReserve; // stores total token amount reserved for auctions
uint256 public auctionTokenFactor = 50; // dafault 50 = 50%, how much of the complete auction Reserve is for daily additional auctions
uint256 public overallAuctionTokenReserved;
uint256 public overallAddVestEmissionsDistributed;
mapping(uint256 => bool) isDaysRewardReserved; // day "on" bool // bool for day
mapping(uint256 => uint256) daysReservedReward; // day "on" amount // amount PER day
mapping(uint256 => bool) isDaysAuctionTokenReserved;
mapping(uint256 => uint256) daysReservedAuctionToken;
modifier onlySystem() {
require(
msg.sender == address(_auction) ||
msg.sender == address(_userStakeAndEarnContract)
);
_;
}
modifier onlyTeam() {
require(_auction.TeamAddr(msg.sender));
_;
}
event UpdateReserve(string infoMessage, bool isAdd, uint256 amount);
event ReserveDaysRewardToken(
uint256 reservedForDay,
uint256 reservedRewardTokenAmount
);
event ReserveDaysAuctionToken(
uint256 reservedForDay,
uint256 reservedAuctionTokenAmount
);
event SendStakeRewards(address recipient, uint256 amount);
event SendAddAuctionVestEmissions(address recipient, uint256 amount);
constructor(address userStakeAndEarnContract) {
_auction = IAuctionContract(msg.sender);
_userStakeAndEarnContract = IStakeContract(userStakeAndEarnContract);
}
// Team fuctions:
// set percentage of Reward Reserve to be distributed per day to stakers
function setStakeRewardFactor(
uint256 newStakeRewardFactor
) public onlyTeam {
require(
newStakeRewardFactor >= 1 && newStakeRewardFactor <= 100,
"New Value is not in the range between 1 and 100!"
);
stakeRewardFactor = newStakeRewardFactor;
}
// set percentage of Auction Reserve to be distributed per on additional auction days
function setAuctionTokenFactor(
uint256 newAuctionTokenFactor
) public onlyTeam {
require(
newAuctionTokenFactor >= 1 && newAuctionTokenFactor <= 100,
"New Value is not in the range between 1 and 100!"
);
auctionTokenFactor = newAuctionTokenFactor;
}
// deposit token into the reserve, which is only used for stakers rewards
function depositStakeBonus(uint256 amount) public onlyTeam {
IERC20(address(_auction)).transferFrom(
msg.sender,
address(this),
amount
); // transfer tokens from user to reserve contract
stakeRewardReserve += amount;
}
// START ########## Functions for Stake Contract ########## //
// add or take to/from token amount accounted to Staking Reserve
function updateReserveStake(
bool isAdd,
uint256 amount
) external override onlySystem {
if (isAdd) {
stakeRewardReserve += amount;
} else {
stakeRewardReserve -= amount;
}
emit UpdateReserve("Stake Reserve", isAdd, amount);
}
// function to read the amount of rewards reserved for a certain day
function readDaysReservedReward(uint day) public view returns (uint256) {
return daysReservedReward[day];
}
// function to read if the reward for this day was reserved
function daysRewardReserved(uint256 day) external view returns (bool) {
return isDaysRewardReserved[day];
}
// function to read the current reward amount for an ongoing day ( for UI to show est. current ROI)
function currentReserveForReward() public view returns (uint256) {
return ((stakeRewardReserve * stakeRewardFactor) / 100);
}
// function to SET the Reward for DAY and update available token amount of reserve
function reserveDaysReward(uint256 day) public onlySystem {
uint256 reservedAmountDay = (stakeRewardReserve * stakeRewardFactor) /
100;
stakeRewardReserve -= reservedAmountDay;
daysReservedReward[day] = reservedAmountDay;
overallRewardsReservedForStakers += reservedAmountDay;
isDaysRewardReserved[day] = true;
emit ReserveDaysRewardToken(day, reservedAmountDay);
}
// fuction to send the rewards earned by stakers, called by the stake contract
function sendStakeRewardToUser(
address user,
uint256 amount
) public onlySystem {
IERC20(address(_auction)).transfer(user, amount);
overallUserRewardsClaimed += amount;
emit SendStakeRewards(user, amount);
}
// End ########## Functions for Stake Contract ########## //
// START ########## Functions for Auction/Main Contract ########## //
// add or take to/from token amount accounted to Auction Reserve
function updateReserveAuction(
bool isAdd,
uint256 amount
) external override onlySystem {
if (isAdd) {
auctionReserve += amount;
} else {
auctionReserve -= amount;
}
emit UpdateReserve("Auction Reserve", isAdd, amount);
}
// function to read the amount of token that have been reserved for a passed auction day
function readDaysReservedAuctionToken(
uint256 day
) public view returns (uint256) {
return daysReservedAuctionToken[day];
}
// function to view if the auction token fr a certain day were already reserved
function daysAuctionTokenReserved(
uint256 day
) external view returns (bool) {
return isDaysAuctionTokenReserved[day];
}
// function to reserve the auction token for the additional auction days
function reserveDaysAuctionToken(uint256 day) public onlySystem {
uint256 reservedAmountDay = (auctionReserve * auctionTokenFactor) / 100;
auctionReserve -= reservedAmountDay;
daysReservedAuctionToken[day] = reservedAmountDay;
overallAuctionTokenReserved += reservedAmountDay;
isDaysAuctionTokenReserved[day] = true;
emit ReserveDaysAuctionToken(day, reservedAmountDay);
}
// function to send vesting emissions of additional auction days to users calles by auction/main contract
function sendAuctionTokenToUser(
address user,
uint256 amount
) public onlySystem {
IERC20(address(_auction)).transfer(user, amount);
overallAddVestEmissionsDistributed += amount;
emit SendAddAuctionVestEmissions(user, amount);
}
// END ########## Functions for Auction Contract ########## //
}
// DEV-Telegram: @DevOctahedron
// contract for a 35 day auction with:
// - users take part in current and comming days by depositing ETH
// - users acution token are vested after the claim of auction shares
// - users vested auction token + 11% profit will be clamable during an emission period of 37 days
contract MoniesTree is IAuctionContract {
using SafeMath for uint256;
string public constant name = "MoniesTree";
string public constant symbol = "MT";
uint256 public constant decimals = 18;
address payable public _admin =
payable(0xe9CC2C44BB625789ED90CCdB9891f24D3Ee656c6); // receives shares of ETH and can set all the onlyAdmin functions
address payable public _feeRecipient =
payable(0x74dEfD2d030b2eCf1409B7cDbD6c3a3Baa498fD7); // receives the Transfer Tax
// address public _routerAddr = 0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02; // on Base univ2 // 0xD99D1c33F9fC3444f8101754aBC46c52416550D1; // on BNB testnet // 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; // ETH uniswap V2 on mainnet
address public _routerAddr = 0x165C3410fC91EF562C50559f7d2289fEbed552d9;
address public liquidityPoolAddress;
IRouter public _router = IRouter(_routerAddr);
StakeContract public userStakeAndEarnContract;
ReserveContract public taxBuyBackReserveContract;
uint256 public buyTaxPercent = 100; // 1 = 0.01%, 10 = 0.1%, 100 = 1%
uint256 public sellTaxPercent = 100; // 1 = 0.01% 10 = 0.1% 350 = 3.50%
address public contrAddr;
uint256 public buyBackSlippage = 9900; // 9000 = 90.00%, 9900 = 99.00%, 9999 = 99.99%
uint256 public overallVestedToken;
uint256 public overallCollectedEarnings;
/* Auction specifics - TEST VERSION: 4 min days, 3 days total */
uint256 public LAUNCH_TIME = block.timestamp + 5 minutes; // Day 1 begins 5 minutes after deployment
uint256 public currentDay;
uint256 public oneDay = 4 minutes; // TEST: 4 min per day
uint256 public auctionPeriod = 3 * oneDay; // TEST: 3 days auction period (12 min total)
uint32 public offDays; // stored as "real" days, not seconds, ( 1 = 1 day)
bool public isAuctionActive = true;
uint256 public lastAuctionPauseTime = 0;
uint256 public lastAuctionUnpauseTime = 0;
uint256 public totalPauseTimeCounter;
bool public pausabilityPermanentlyDisabled = false;
// this token/wei amount need to be accounted per second to have 1 ETH per day
uint256 private weiPerSfor1perDay = 11574074074074;
// Token available per auction day // TODO
uint256 public dayliAvailableToken = 7777777 ether; // 7.777 Million
uint256 public lastMintTimestamp;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
event LiqAdded(
uint256 transferredToken,
uint256 transferredETH,
uint256 timestamp
);
event BuybackAndBuild(
uint256 day,
uint256 collectedETHtoBuyback,
uint256 boughtTokens,
uint256 timestamp
);
event EnterAuction(
address indexed user,
uint256 rawAmount,
uint256 auctionEntryDay,
uint256 currentDay,
uint256 entryTime
);
event ChangeSharesToToken(
address indexed user,
uint256 amountShares,
uint256 amountToken
);
event Vest(
address indexed user,
uint256 vestAmount,
uint256 _vestIndex,
uint256 vestTime
);
event ClaimVesting(
address indexed user,
uint256 rewardAmount,
uint256 claimTime
);
mapping(address => bool) public TeamAddr;
modifier onlyAdmin() {
require(_admin == msg.sender, "Ownable: caller is not the admin");
_;
}
modifier onlyTeam() {
require(
_admin == msg.sender || TeamAddr[msg.sender],
"Ownable: caller is not from the team"
);
_;
}
uint256 private _totalSupply;
mapping(address => uint256) private _Balances;
struct VestData {
uint256 vestTime;
uint256 amount;
uint256 claimed;
uint256 lastUpdate;
uint256 collected;
}
mapping(address => mapping(uint256 => VestData)) public vesting;
/* a certain days total auction entry in ETH */
mapping(uint256 => uint256) public auctionEntry_thatDay;
// total auction entry in ETH of all auction days together
uint256 public auctionEntry_allDays;
// counting unique (unique for every day only) Auction enteries for each day
mapping(uint256 => uint256) public usersCountDaily;
// counting total unique (unique for every day only) users (if same user enters another day, it counts!)
uint256 public usersCount = 0;
// mapping for allowance
mapping(address => mapping(address => uint256)) private _allowance;
// Auction memebrs overall data
struct memberAuction_overallData {
uint256 overall_collectedTokens;
uint256 total_auctionEnteries;
}
// map for every user's overall data
mapping(address => memberAuction_overallData)
public mapMemberAuction_overallData;
/* Auction memebrs data */
struct memberAuction {
uint256 memberAuctionValue;
bool hasChangedShareToToken;
}
/* new map for every entry (users are allowed to enter multiple times a day) */
mapping(address => mapping(uint256 => memberAuction))
public mapMemberAuction;
// Addresses that excluded from transferTax when
mapping(address => bool) public _excludedFromTransferTax;
// mapping so see if buybacl and liq for a cerrtain day was already done
mapping(uint256 => bool) public buyBackAndBuildDone;
// ######################################################################
// ######################################################################
// ######################################################################
// ######################################################################
// ######################################################################
constructor() {
userStakeAndEarnContract = new StakeContract(); // create stake contract
taxBuyBackReserveContract = new ReserveContract(
address(userStakeAndEarnContract)
); // create Token reserve, as Tax and Buyback Recipient
userStakeAndEarnContract.setReserveContract(
address(taxBuyBackReserveContract)
); // set reserve contract in stake contract
contrAddr = address(this);
_excludedFromTransferTax[msg.sender] = true;
_excludedFromTransferTax[contrAddr] = true;
_excludedFromTransferTax[_admin] = true;
_excludedFromTransferTax[_feeRecipient] = true;
_excludedFromTransferTax[address(userStakeAndEarnContract)] = true;
_excludedFromTransferTax[address(taxBuyBackReserveContract)] = true;
TeamAddr[_admin] = true;
TeamAddr[msg.sender] = true;
_mint(contrAddr, 1 ether);
}
function totalSupply() external view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) external view returns (uint256) {
return _Balances[account];
}
function allowance(
address owner_,
address spender
) external view returns (uint256) {
return _allowance[owner_][spender];
}
function approve(address spender, uint256 value) public returns (bool) {
_allowance[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
function increaseAllowance(
address spender,
uint256 addedValue
) external returns (bool) {
_allowance[msg.sender][spender] = _allowance[msg.sender][spender].add(
addedValue
);
emit Approval(msg.sender, spender, _allowance[msg.sender][spender]);
return true;
}
function decreaseAllowance(
address spender,
uint256 subtractedValue
) external returns (bool) {
uint256 oldValue = _allowance[msg.sender][spender];
if (subtractedValue >= oldValue) {
_allowance[msg.sender][spender] = 0;
} else {
_allowance[msg.sender][spender] = oldValue.sub(subtractedValue);
}
emit Approval(msg.sender, spender, _allowance[msg.sender][spender]);
return true;
}
// function to set Buy and Sell tax, max buy tax is 10% and max sell tax is 20%
function setBuyAndSellTax(
uint256 newBuyTax,
uint256 newSellTax
) external onlyTeam {
require(newBuyTax < 1001, " Buy Tax Value not in allowed range!");
require(newSellTax < 1501, "Sell Tax Value not in allowed range!");
buyTaxPercent = newBuyTax;
sellTaxPercent = newSellTax;
}
// Set addresses of dev, fee recipient and adminHelper
function setAdminAddresses(
address payable admin,
address payable feeRecipient
) external onlyAdmin {
_admin = admin;
_feeRecipient = feeRecipient;
}
// add or remove address to admin helper list
function setAdminHelpers(
address newAdminHelper,
bool state
) external onlyAdmin {
TeamAddr[newAdminHelper] = state;
}
// Set address to be in- or excluded from Tax
function setExcludedFromTax(
address _account,
bool _excluded
) external onlyTeam {
_excludedFromTransferTax[_account] = _excluded;
}
// deposit into reserve to increase reserve amount
function depositIntoReserve(uint256 tokenAmount) external {
IERC20(contrAddr).transferFrom(
msg.sender,
address(taxBuyBackReserveContract),
tokenAmount
); // transfer tokens from user to reserve contract
// account the right amounts in the reserve contract
taxBuyBackReserveContract.updateReserveAuction(true, tokenAmount / 2); // 50% accounted to Auction reserve
taxBuyBackReserveContract.updateReserveStake(true, tokenAmount / 2); // 50% accounted to Stake reward reserve
}
// Returns if the address is excluded from Tax or not.
function isExcludedFromTax(address _account) public view returns (bool) {
return _excludedFromTransferTax[_account];
}
function transferToZero(uint256 amount) internal returns (bool) {
_Balances[contrAddr] = _Balances[contrAddr].sub(
amount,
"Token: transfer amount exceeds balance"
);
_Balances[address(0)] = _Balances[address(0)].add(amount);
emit Transfer(contrAddr, address(0), amount);
return true;
}
function transfer(address to, uint256 amount) public returns (bool) {
_transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public returns (bool) {
if (msg.sender != contrAddr) {
_allowance[from][msg.sender] = _allowance[from][msg.sender].sub(
amount
);
}
_transfer(from, to, amount);
return true;
}
// internal transfer function to apply the transfer tax and tax handling
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
bool isBuy = (from == liquidityPoolAddress); // Buying from LP
bool isSell = (to == liquidityPoolAddress); // Selling to LP
bool isTaxedTransfer = (isBuy || isSell) &&
(!isExcludedFromTax(from) && !isExcludedFromTax(to));
if (isTaxedTransfer) {
uint256 taxPercent = isBuy ? buyTaxPercent : sellTaxPercent; // Select tax rate
uint256 taxAmount = amount.mul(taxPercent).div(10000);
uint256 taxedAmount = amount.sub(taxAmount);
// Transfer taxed amount to recipient
_Balances[from] = _Balances[from].sub(
amount,
"transfer amount exceeds balance"
);
_Balances[to] += taxedAmount;
emit Transfer(from, to, taxedAmount);
// Tax handling: Split tax into Auction and Stake reserves
_Balances[address(taxBuyBackReserveContract)] += taxAmount;
taxBuyBackReserveContract.updateReserveAuction(true, taxAmount / 2);
taxBuyBackReserveContract.updateReserveStake(true, taxAmount / 2);
emit Transfer(from, address(taxBuyBackReserveContract), taxAmount);
} else {
// Normal untaxed transfer
_Balances[from] = _Balances[from].sub(
amount,
"transfer amount exceeds balance"
);
_Balances[to] += amount;
emit Transfer(from, to, amount);
}
}
function _mint(address _user, uint256 _amount) internal {
_Balances[_user] = _Balances[_user].add(_amount);
_totalSupply = _totalSupply.add(_amount);
emit Transfer(address(0), _user, _amount);
}
function _burn(address _user, uint256 _amount) internal {
_Balances[_user] = _Balances[_user].sub(_amount);
_totalSupply = _totalSupply.sub(_amount);
emit Transfer(_user, address(0), _amount);
}
// internal function to vest user Token
function vestInt(uint256 _amount, uint256 _vestIndex) internal {
vesting[msg.sender][_vestIndex].amount = _amount;
vesting[msg.sender][_vestIndex].vestTime = block.timestamp;
vesting[msg.sender][_vestIndex].lastUpdate = block.timestamp;
overallVestedToken += _amount;
emit Vest(msg.sender, _amount, _vestIndex, block.timestamp);
}
function setLaunchTime(uint256 newTime) external onlyTeam {
require(
LAUNCH_TIME + (offDays * oneDay) > block.timestamp,
"Auctions have already started!"
); // assure auctions have not already started
require(
newTime + (offDays * oneDay) > block.timestamp,
"New Launchtime + offDays must be in the future!"
); // assure new launctime is in the future
LAUNCH_TIME = newTime; // set Launchtime to the new time
}
function setOffDays(uint32 _offDays) external onlyTeam {
require(
LAUNCH_TIME + (offDays * oneDay) > block.timestamp,
"Auctions have already started!"
); // assure auctions have not already started
require(
LAUNCH_TIME + (_offDays * oneDay) > block.timestamp,
"Number for offDays too small!"
); // assure new offDays will start auctions in the future
offDays = _offDays; // set offDays to new offDays
}
function readCurrentDay() public view returns (uint256) {
return currentDay;
}
// function to see which is the actual auction day
function thisDay() public view returns (uint256) {
if (
(LAUNCH_TIME + (offDays * oneDay) + totalPauseTimeCounter) >
block.timestamp
) {
return 0;
} else {
return
1 +
(
((block.timestamp -
(LAUNCH_TIME +
(offDays * oneDay) +
totalPauseTimeCounter)) / oneDay)
);
}
}
// to make the contract being able to receive ETH from Router
receive() external payable {}
// permanemtly disallow pausability of auctions
function permanentlyDisableAuctionPause() external onlyTeam {
require(
isAuctionActive,
"Auctions are Paused! Unpause Auctions first!"
);
pausabilityPermanentlyDisabled = true;
}
// switch pause and unpause Auction
function pauseUnpauseAuctions() external onlyTeam {
require(
!pausabilityPermanentlyDisabled,
"Pausing Auctions was permanently disabled!"
);
if (isAuctionActive) {
// if auction is running
isAuctionActive = false; // PAUSE it!
lastAuctionPauseTime = block.timestamp; // store timestamp of last pause start
} else {
// if auction is paused
isAuctionActive = true; // UNPAUSE it!
lastAuctionUnpauseTime = block.timestamp; // set switch ON time to NOW
totalPauseTimeCounter +=
lastAuctionUnpauseTime -
lastAuctionPauseTime; // update total pause time
}
}
// function to add first days token to liquitidy
function addFirstDaysLiq() internal {
// calc the amount of token that should be added to preserve a 10% higher price than frist days auction Price!
uint256 amountAuctionTokenToAdd = (dayliAvailableToken * 765) / 1000;
// mint the tokens into the contract to have them available for liq
_mint(contrAddr, amountAuctionTokenToAdd);
// calc the amount of the deposit token to be added to liq
uint256 collectedETHtoLiq = (auctionEntry_thatDay[1] * 85) / 100;
// get real balance and require balance
uint256 collectedETHBalance = (contrAddr).balance;
require(
collectedETHBalance >= collectedETHtoLiq,
"addFirstDaysLiq: not enough ETH in contract"
);
IERC20(contrAddr).approve(_routerAddr, type(uint256).max);
// actual Liq adding to v2 Router:
(, , uint256 amtLiquidity) = _router.addLiquidityETH{
value: collectedETHtoLiq
}(
contrAddr, // address token
amountAuctionTokenToAdd, // amount token to add to Liq
0, // amount Token minimum
0, // amount ETH minimum
contrAddr, // LP recipient
block.timestamp + 100
);
address factory = _router.factory();
liquidityPoolAddress = IFactory(factory).getPair(
_router.WPLS(),
contrAddr
);
IERC20(liquidityPoolAddress).transfer(address(0), amtLiquidity);
// transfer remaining ETH to fee addr (15%)
_feeRecipient.transfer(auctionEntry_thatDay[1] - collectedETHtoLiq);
emit LiqAdded(
amountAuctionTokenToAdd,
collectedETHtoLiq,
block.timestamp
);
}
// function to view an days current amountOut
// BEFORE calling the buybackandbuild function, read this value of a PASSED auction day
// this was added to prevent the MEV bot from manipulating the price before the buyback tx!
function viewAmountOutOfDay(uint256 day) public view returns (uint256) {
uint256 collectedETHtoBuyBack = (auctionEntry_thatDay[day] * 85) / 100;
if (collectedETHtoBuyBack == 0) {
return 0;
}
// Define the path for swapping
address[] memory path = new address[](2);
path[0] = _router.WPLS();
path[1] = contrAddr;
// Get expected output amounts
uint256[] memory amountsOut = _router.getAmountsOut(
collectedETHtoBuyBack,
path
);
return amountsOut[1];
}
// function to view available token especially for additional aution days
function viewAvailableAuctionTokenForDay(
uint256 day
) public view returns (uint256) {
if (day > (auctionPeriod / oneDay)) {
// when we are in the additional auction period
if (!taxBuyBackReserveContract.daysRewardReserved(day)) {
// if we are in additional period AND the rewards have not been reserved for that day
uint256 partFromBnBforReserve = (viewAmountOutOfDay(day) / 2);
uint256 reserveForAuctions = taxBuyBackReserveContract
.auctionReserve();
return (((partFromBnBforReserve + reserveForAuctions) *
taxBuyBackReserveContract.auctionTokenFactor()) / 100);
} else {
return taxBuyBackReserveContract.readDaysReservedReward(day);
} // if rewards have already been resereved
} else {
return dayliAvailableToken;
} // when we are still in the regual auction Period!
}
// set slippage max slippage for buyback to adopt to bot behaviour
function setBuyBackSlippage(uint256 _slippage) public onlyTeam {
require(_slippage > 5000 && _slippage < 10001, "not a valid slippage");
buyBackSlippage = _slippage;
}
// function for the third and the following days, to buy back token with ETH and send to the reserve
function buybackAndBuild(
uint256 amountOutMin,
uint256 day
) public onlyTeam {
require(thisDay() >= 3, "invalid time for buyback and burn!");
require(
thisDay() > day,
"the day you want to buyback for is not finished!"
);
require(
!buyBackAndBuildDone[day],
"buyback and build already done for this day!"
);
uint256 collectedETHtoBuyBack = (auctionEntry_thatDay[day] * 85) / 100; // 85% of collected eth used for buyback
// Check contract's balance of ETH
uint256 contractBalance = (contrAddr).balance;
require(
contractBalance >= collectedETHtoBuyBack,
"Insufficient ETH balance"
);
// Define the path for swapping
address[] memory path = new address[](2);
path[0] = _router.WPLS();
path[1] = contrAddr;
// Calculate minimum expected amount (90% (default) of expectedAmountOut to allow slippage, settable)
uint256 amountOut = (amountOutMin * buyBackSlippage) / 10000;
// Check the actual balance of the recipient wallet.
uint256 tokenBalanceReserveBefore = IERC20(contrAddr).balanceOf(
address(taxBuyBackReserveContract)
);
// Swap to taxBuyBackReserve address
_router.swapExactETHForTokensSupportingFeeOnTransferTokens{
value: collectedETHtoBuyBack
}(
amountOut, // amount out min
path,
address(taxBuyBackReserveContract),
block.timestamp + 100
);
// Check the actual received amount after swap
uint256 receivedAmount = IERC20(contrAddr).balanceOf(
address(taxBuyBackReserveContract)
) - tokenBalanceReserveBefore;
// require received amount of contract token of taxBuyBackReserve is bigger than zero.
require(receivedAmount > 0, "No tokens received from buyback swap");
// account the right amounts in the reserve contract
taxBuyBackReserveContract.updateReserveAuction(
true,
receivedAmount / 2
); // 50% accounted to Auction reserve
taxBuyBackReserveContract.updateReserveStake(true, receivedAmount / 2); // 50% accounted to Stake reward reserve
buyBackAndBuildDone[day] = true;
// transfer remaining ETH of day to _feeRecipient (15%)
_feeRecipient.transfer(
auctionEntry_thatDay[day] - collectedETHtoBuyBack
);
if (userStakeAndEarnContract.rewardsActive()) {
userStakeAndEarnContract.updateRewards();
}
currentDay = thisDay(); // update currentDay
emit BuybackAndBuild(
day,
collectedETHtoBuyBack,
receivedAmount,
block.timestamp
);
}
function dailyUpdate() public {
if (thisDay() == 2 && currentDay == 1) {
addFirstDaysLiq();
}
if (
thisDay() >= (auctionPeriod / oneDay) + 2 &&
!taxBuyBackReserveContract.daysAuctionTokenReserved(thisDay() - 1)
) {
taxBuyBackReserveContract.reserveDaysAuctionToken(thisDay() - 1);
}
if (
currentDay < thisDay() && userStakeAndEarnContract.rewardsActive()
) {
userStakeAndEarnContract.updateRewards();
}
// update current day to assure that liq adding and buyback happens only once per day!
currentDay = thisDay();
}
// function that allows users to enter into all available auction days with the same amount of ETH
// allows only to enter regular auction days
function batchAuctionEntry() public payable {
uint256 rawETHamt = msg.value;
require(rawETHamt > 0, "batchAuctionEntry: no ETH sent!");
uint256 numberOfDays = (auctionPeriod / oneDay); // Total number of auction days
uint256 today = thisDay();
// Ensure `thisDay()` is within valid range
require(
today <= numberOfDays,
"batchAuctionEntry: invalid current day"
);
uint256 amountOfDays = numberOfDays - today + 1; // Total number of available auction days
uint256 dailyETHamt = rawETHamt / amountOfDays; // Divide ETH equally across all days
require(
dailyETHamt > 0,
"batchAuctionEntry: insufficient ETH for all days"
);
for (uint256 i = today; i <= numberOfDays; i++) {
_buyShareFromAuction(i, dailyETHamt); // Internal function
}
}
// function for users to participate in one day of the daily auctions
// also allows to enter the additional auction days
function buyShareFromAuction(
uint256 auctionDay
) public payable returns (bool) {
uint256 rawETHamt = msg.value;
require(rawETHamt > 0, "buyShareFromAuction: no ETH sent");
_buyShareFromAuction(auctionDay, rawETHamt); // Delegate logic to internal function
return true;
}
// Internal buy Share From Auction function
function _buyShareFromAuction(
uint256 auctionDay,
uint256 amount
) internal returns (bool) {
require(isAuctionActive, "Auctions are currently paused!"); // check if auctions are active
require(
block.timestamp >=
LAUNCH_TIME + (offDays * oneDay) + totalPauseTimeCounter,
"Auctions have not started yet!"
); // check if auctions have started
// require(auctionDay >= thisDay() && (auctionDay * oneDay) <= auctionPeriod,"buyShareFromAuction: invalid auction day"); // validate auction day
require(
auctionDay >= thisDay(),
"buyShareFromAuction: invalid auction day"
); // validate auction day
// Record the entry
auctionEntry_thatDay[auctionDay] += amount; // update deposit amount for the specified day
auctionEntry_allDays += amount; // update total deposits
if (mapMemberAuction[msg.sender][auctionDay].memberAuctionValue == 0) {
// check if user already made a depoist on that auction day
usersCount++; // UNIQUE users per day for ALL days
usersCountDaily[auctionDay]++; // UNIQUE users per day for the ENTRANCE day
}
mapMemberAuction_overallData[msg.sender]
.total_auctionEnteries += amount; // update total ETH amount used for auction entries of the USER
mapMemberAuction[msg.sender][auctionDay].memberAuctionValue += amount; // total ETH amount entries of the USER on THAT DAY
dailyUpdate();
emit EnterAuction(
msg.sender,
amount,
auctionDay,
currentDay,
block.timestamp
);
return true;
}
function calculateTokenPerShareOnDay(
uint256 _day
) public view returns (uint256) {
uint256 collectedThatDay = auctionEntry_thatDay[_day];
uint256 tokenPerShare;
if (collectedThatDay == 0) {
// avoid division by 0
return 0;
} else {
// so if there was ETH collected on _day
if (_day > (auctionPeriod / oneDay)) {
// if there was ETH collected AFTER regular auction period (i.e. day 31)
// if the auction token were not reserved it returns the theoretical amount
// if the day would have already ended with the current amount of token
if (!taxBuyBackReserveContract.daysAuctionTokenReserved(_day)) {
uint256 reserveAmount = taxBuyBackReserveContract
.auctionReserve();
uint256 reserveFactor = taxBuyBackReserveContract
.auctionTokenFactor();
return
(reserveAmount.mul(reserveFactor).div(100)).div(
collectedThatDay
);
} else {
// so if we are past day 30 AND have ETH deposits for _day AND the token are reserved in the reserve Contract
tokenPerShare = taxBuyBackReserveContract
.readDaysReservedAuctionToken(_day)
.mul(1e18)
.div(collectedThatDay);
return tokenPerShare;
}
}
// so IF we are still in the regular auction period time AND have ETH deposits that day
tokenPerShare = dayliAvailableToken.mul(1e18).div(collectedThatDay);
return tokenPerShare;
}
}
// function for users to change their shares from ALL auction days into vested tokens
function claimTokenFromSharesAndVest(
uint256 auctionDay
) external returns (bool) {
require(
thisDay() > auctionDay,
"Token of this auction day are not ready to be accounted to users vesting!"
);
if (auctionDay > 1) {
// all days biger than day 1 need the BnB to be done before the claim of auction Shares
require(
buyBackAndBuildDone[auctionDay],
"BuyBack and build for this day was not done so far!"
);
}
uint256 userShares = mapMemberAuction[msg.sender][auctionDay]
.memberAuctionValue; // get amount of shares for the requested auction day
require(
userShares > 0,
"User has never deposited ETH to this auctionDay!"
);
require(
mapMemberAuction[msg.sender][auctionDay].hasChangedShareToToken ==
false,
"User has already Changed his Shares to Token"
);
if (
(thisDay() >= (auctionPeriod / oneDay) + 2) &&
!taxBuyBackReserveContract.daysAuctionTokenReserved(auctionDay)
) {
taxBuyBackReserveContract.reserveDaysAuctionToken(auctionDay);
}
uint256 amountUserTokens = calculateTokenPerShareOnDay(auctionDay)
.mul(userShares)
.div(1e18);
vestInt(amountUserTokens, auctionDay); // create Vesting data for the USER // auctionDay = _vestIndex !
mapMemberAuction[msg.sender][auctionDay].hasChangedShareToToken = true;
dailyUpdate();
emit ChangeSharesToToken(msg.sender, userShares, amountUserTokens);
return true;
}
// Only called when claim (collect) is called
// Calculates the earned rewards since LAST UPDATE
// Earning is 3% per day and lasts until 111% is reached (effectively 37 days)
function calcVestingEmission(
address _user,
uint256 _vestIndex
) public view returns (uint256) {
if (vesting[_user][_vestIndex].vestTime == 0) {
return 0; // No vest, no reward
}
// Multiplier that represents the amount earned per second
// value 11574074074074 gives 1 ether per day as multiplier!
// Factor 3 for 3% per day
uint256 multiplier = (block.timestamp -
vesting[_user][_vestIndex].lastUpdate).mul(weiPerSfor1perDay).mul(
3
);
// Calculate the maximum reward (111% of the vesting amount for regular auction vesting)
uint256 maxReward;
if (_vestIndex <= auctionPeriod / oneDay) {
maxReward = vesting[_user][_vestIndex].amount.mul(111).div(100);
} else {
maxReward = vesting[_user][_vestIndex].amount;
}
// Check if the total earned (including previously collected) exceeds the maximum reward
if (
vesting[_user][_vestIndex]
.amount
.mul(multiplier)
.div(100 ether)
.add(vesting[_user][_vestIndex].collected) > maxReward
) {
return maxReward.sub(vesting[_user][_vestIndex].collected);
}
// Otherwise, return the calculated reward for this period
return vesting[_user][_vestIndex].amount.mul(multiplier).div(100 ether);
}
// Calculates claimable rewards for UI display
function readVestingEmission(
address _user,
uint256 _vestIndex
) public view returns (uint256) {
if (vesting[_user][_vestIndex].vestTime == 0) {
return 0;
}
uint256 multiplier = (block.timestamp -
vesting[_user][_vestIndex].lastUpdate).mul(weiPerSfor1perDay).mul(
3
);
uint256 maxReward;
if (_vestIndex <= auctionPeriod / oneDay) {
maxReward = vesting[_user][_vestIndex].amount.mul(111).div(100);
} else {
maxReward = vesting[_user][_vestIndex].amount;
}
if (
multiplier
.mul(vesting[_user][_vestIndex].amount)
.div(100 ether)
.add(vesting[_user][_vestIndex].collected) > maxReward
) {
return maxReward.sub(vesting[_user][_vestIndex].claimed);
}
return
vesting[_user][_vestIndex]
.amount
.mul(multiplier)
.div(100 ether)
.add(vesting[_user][_vestIndex].collected)
.sub(vesting[_user][_vestIndex].claimed);
}
// function to update the collected vesting emissions to user vestInt collected value and update the last updated value
function _collect(address _user, uint256 _vestIndex) internal {
vesting[_user][_vestIndex].collected = vesting[_user][_vestIndex]
.collected
.add(calcVestingEmission(_user, _vestIndex)); // Add new rewards to the collected amount
vesting[_user][_vestIndex].lastUpdate = block.timestamp; // Update the last time rewards were collected
}
// function to claim all user vests in one tx
function batchClaimVestingEmissions() external {
for (
uint256 i = 1;
i <= thisDay() && i <= (auctionPeriod / oneDay);
i++
) {
if (vesting[msg.sender][i].amount > 0) {
claimVestingEmissions(i);
}
}
}
// function for users to claim the vesting emissions
// new minting only during regular auction period
function claimVestingEmissions(uint256 _vestIndex) public {
//
_collect(msg.sender, _vestIndex); // call collect to update users vest data by addind the newly earned rewards
uint256 reward = vesting[msg.sender][_vestIndex].collected.sub(
vesting[msg.sender][_vestIndex].claimed
); // Calculate the unclaimed rewards
vesting[msg.sender][_vestIndex].claimed = vesting[msg.sender][
_vestIndex
].collected; // Update the claimed amount to match collected
if (_vestIndex > auctionPeriod / oneDay) {
taxBuyBackReserveContract.sendAuctionTokenToUser(
msg.sender,
reward
);
} else {
_mint(msg.sender, reward); // Mint new tokens to reward the user
}
mapMemberAuction_overallData[msg.sender]
.overall_collectedTokens += reward; // update total amount of claimed vesting emissions
overallCollectedEarnings += reward; // Increase overall dividends
dailyUpdate();
emit ClaimVesting(msg.sender, reward, block.timestamp); // Emit an event for transparency
}
}
Compiler Settings
{"viaIR":true,"remappings":["forge-std/=lib/forge-std/src/"],"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"libraries":{},"evmVersion":"shanghai"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"BuybackAndBuild","inputs":[{"type":"uint256","name":"day","internalType":"uint256","indexed":false},{"type":"uint256","name":"collectedETHtoBuyback","internalType":"uint256","indexed":false},{"type":"uint256","name":"boughtTokens","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ChangeSharesToToken","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amountShares","internalType":"uint256","indexed":false},{"type":"uint256","name":"amountToken","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ClaimVesting","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"rewardAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"claimTime","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"EnterAuction","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"rawAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"auctionEntryDay","internalType":"uint256","indexed":false},{"type":"uint256","name":"currentDay","internalType":"uint256","indexed":false},{"type":"uint256","name":"entryTime","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"LiqAdded","inputs":[{"type":"uint256","name":"transferredToken","internalType":"uint256","indexed":false},{"type":"uint256","name":"transferredETH","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Vest","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"vestAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"_vestIndex","internalType":"uint256","indexed":false},{"type":"uint256","name":"vestTime","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"LAUNCH_TIME","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"TeamAddr","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address payable"}],"name":"_admin","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"_excludedFromTransferTax","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address payable"}],"name":"_feeRecipient","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IRouter"}],"name":"_router","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"_routerAddr","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner_","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"auctionEntry_allDays","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"auctionEntry_thatDay","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"auctionPeriod","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"batchAuctionEntry","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"batchClaimVestingEmissions","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"buyBackAndBuildDone","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"buyBackSlippage","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"buyShareFromAuction","inputs":[{"type":"uint256","name":"auctionDay","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"buyTaxPercent","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"buybackAndBuild","inputs":[{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"uint256","name":"day","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"calcVestingEmission","inputs":[{"type":"address","name":"_user","internalType":"address"},{"type":"uint256","name":"_vestIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"calculateTokenPerShareOnDay","inputs":[{"type":"uint256","name":"_day","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"claimTokenFromSharesAndVest","inputs":[{"type":"uint256","name":"auctionDay","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimVestingEmissions","inputs":[{"type":"uint256","name":"_vestIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"contrAddr","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"currentDay","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"dailyUpdate","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dayliAvailableToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"decreaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"subtractedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"depositIntoReserve","inputs":[{"type":"uint256","name":"tokenAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"increaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"addedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isAuctionActive","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExcludedFromTax","inputs":[{"type":"address","name":"_account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastAuctionPauseTime","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastAuctionUnpauseTime","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastMintTimestamp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"liquidityPoolAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"memberAuctionValue","internalType":"uint256"},{"type":"bool","name":"hasChangedShareToToken","internalType":"bool"}],"name":"mapMemberAuction","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"overall_collectedTokens","internalType":"uint256"},{"type":"uint256","name":"total_auctionEnteries","internalType":"uint256"}],"name":"mapMemberAuction_overallData","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"offDays","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"oneDay","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"overallCollectedEarnings","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"overallVestedToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"pausabilityPermanentlyDisabled","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pauseUnpauseAuctions","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"permanentlyDisableAuctionPause","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"readCurrentDay","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"readVestingEmission","inputs":[{"type":"address","name":"_user","internalType":"address"},{"type":"uint256","name":"_vestIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"sellTaxPercent","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAdminAddresses","inputs":[{"type":"address","name":"admin","internalType":"address payable"},{"type":"address","name":"feeRecipient","internalType":"address payable"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAdminHelpers","inputs":[{"type":"address","name":"newAdminHelper","internalType":"address"},{"type":"bool","name":"state","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBuyAndSellTax","inputs":[{"type":"uint256","name":"newBuyTax","internalType":"uint256"},{"type":"uint256","name":"newSellTax","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBuyBackSlippage","inputs":[{"type":"uint256","name":"_slippage","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setExcludedFromTax","inputs":[{"type":"address","name":"_account","internalType":"address"},{"type":"bool","name":"_excluded","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setLaunchTime","inputs":[{"type":"uint256","name":"newTime","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setOffDays","inputs":[{"type":"uint32","name":"_offDays","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract ReserveContract"}],"name":"taxBuyBackReserveContract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"thisDay","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalPauseTimeCounter","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract StakeContract"}],"name":"userStakeAndEarnContract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"usersCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"usersCountDaily","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"vestTime","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"claimed","internalType":"uint256"},{"type":"uint256","name":"lastUpdate","internalType":"uint256"},{"type":"uint256","name":"collected","internalType":"uint256"}],"name":"vesting","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"viewAmountOutOfDay","inputs":[{"type":"uint256","name":"day","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"viewAvailableAuctionTokenForDay","inputs":[{"type":"uint256","name":"day","internalType":"uint256"}]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x6080604081815234620002f2575f9160018060a01b03199073e9cc2c44bb625789ed90ccdb9891f24d3ee656c6828554161784556001907374defd2d030b2ecf1409b7cdbd6c3a3baa498fd78383541617825573165c3410fc91ef562c50559f7d2289febed552d9948584600254161760025560049584875416178655606460075560646008556126ac600a5561012c42018042116200033057600d5560f0600f55916102d060105564010000000064ff000000001960115416176011555f6012555f60135560ff19908160155416601555650a86cc92e3da6016556a066f0222d28f57292400006017556020945f86556116f59384810160018060401b0395828210878311176200031d57908291620042d7833903905ff093841562000313576005805483166001600160a01b03968716908117909155885190610d4780830191908483118484101762000300579183918b93620059cc843981520301905ff08015620002f65785169081836006541617600655856005541691823b15620002f2575f9060248c838d519687948593630a4f4a5960e31b85528401525af18015620002e857620002b9575b5050907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9392913090600954161760095533855260248652868520818382541617905582600954168552868520818382541617905582855416855286852081838254161790558281541685528685208183825416179055826005541685528685208183825416179055826006541685528685208183825416179055828554168552601986528685208183825416179055338552868520918254161790556009541692838352601b8152620002828584205462000343565b848452601b8252858420556200029a601a5462000343565b601a558451670de0b6b3a76400008152a351613f1c9081620003bb8239f35b908092965011620002d557865294955085945f938480620001ab565b604188634e487b7160e01b5f525260245ffd5b89513d5f823e3d90fd5b5f80fd5b88513d5f823e3d90fd5b60418d634e487b7160e01b5f525260245ffd5b87513d5f823e3d90fd5b60418b634e487b7160e01b5f525260245ffd5b634e487b7160e01b825260118752602482fd5b670de0b6b3a7640000810190818111620003a6578110620003615790565b60405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606490fd5b634e487b7160e01b5f52601160045260245ffdfe6080604081815260049182361015610021575b505050361561001f575f80fd5b005b5f90813560e01c9081630177672e1461229f5750806301bc45c914612277578063022466b51461225857806306fdde031461221657806307283166146121ee57806308649840146121c9578063095ea7b3146121585780630cccfc5814612139578063108b90a414611cfa578063123e73c214611cd1578063143ee5b914611c645780631585119914611c3757806318160ddd14611c185780631822153214611bf95780632018907e14611bda5780632281b57514611bb157806323b872dd14611b2f57806325e10205146114bc578063313ce567146114a057806339509351146114055780633a52bedd146113e6578063429fed0d1461130357806345fd7df2146112e45780634bd9351b146112c55780634c59ffde146112745780634fe1c3531461125b578063504de2b01461123257806350ef22511461113057806352d63d491461110c57806355b35da3146110c257806358d26b6e146110535780635c9302c914610ca557806362244b3414610efd5780636ba13a8214610edf5780636f7806de1461065f5780636fb1896c14610ec05780637012e44c14610d3a57806370a0823114610d025780637194ae3a14610cc457806373701e1914610ca557806379e10daa14610c7c5780637df405a414610c5d578063834368ae14610c3e57806385c1a33c14610c1f5780638e80ff5d14610c005780638f10aca714610bd757806390f6c87214610b3357806395d89b4114610af55780639aa4611014610ad65780639ff46e74146109e5578063a342f238146109bc578063a457c2d7146108b6578063a9059cbb14610885578063aebc463b14610843578063b997fe821461081b578063bf627bf5146107fe578063c2ed286b14610798578063c843bae614610778578063c8a3fe8114610759578063c9b542ac1461069d578063cb4ca6311461065f578063cc1348391461055f578063d1b4b9a31461053a578063d25b17b614610511578063d7abc59b146104e8578063dd62ed3e1461049b578063edae876f1461046f578063f22fc41314610450578063f7a6b2f9146103c5578063f85bd4f11461035e5763fdd5eaeb03610012573461035b57602036600319011261035b575061035460209235612b54565b9051908152f35b80fd5b5090346103c15736600319011261035b57610377612384565b61037f61239a565b82546001600160a01b03928392919061039b8483163314612547565b6bffffffffffffffffffffffff60a01b9485911691161784551690600154161760015580f35b5080fd5b5090346103c157816003193601126103c15760018091815b6103e5578380f35b6103ed612a57565b82111580610438575b156104345761042083923386526020601c8152838720908288525283838720015461042657613531565b916103dd565b61042f81613d02565b613531565b8380f35b50610448601054600f54906125aa565b8211156103f6565b5090346103c157816003193601126103c1576020906013549051908152f35b5091346104975782600319360112610497575490516001600160a01b03909116815260209150f35b8280fd5b5090346103c157806003193601126103c1576020916104b8612384565b826104c161239a565b6001600160a01b03928316845260218652922091165f908152908352819020549051908152f35b5090346103c157806003193601126103c157602090610354610508612384565b60243590613b31565b5090346103c157816003193601126103c15760035490516001600160a01b039091168152602090f35b5090346103c157816003193601126103c1576011549051602091821c60ff1615158152f35b5091903461049757826003193601126104975782546001600160a01b03163314801561064a575b61058f906124ef565b60ff601554166105f4578260115460ff8160201c165f146105c0575064ff0000000019601154166011554260125580f35b6401000000009064ff00000000191617601155426013556105ee6105e6601254426124e2565b6014546123f5565b60145580f35b906020608492519162461bcd60e51b8352820152602a60248201527f50617573696e672041756374696f6e7320776173207065726d616e656e746c796044820152692064697361626c65642160b01b6064820152fd5b5033835260196020528083205460ff16610586565b5090346103c15760203660031901126103c15760209160ff9082906001600160a01b0361068a612384565b1681526024855220541690519015158152f35b5091903461049757826003193601126104975782546001600160a01b031633148015610744575b6106cd906124ef565b60ff60115460201c16156106ec5782600160ff19601554161760155580f35b906020608492519162461bcd60e51b8352820152602c60248201527f41756374696f6e7320617265205061757365642120556e70617573652041756360448201526b74696f6e732066697273742160a01b6064820152fd5b5033835260196020528083205460ff166106c4565b5090346103c157816003193601126103c1576020906014549051908152f35b5082346103c15760203660031901126103c1576107959035613d02565b80f35b5090346103c157610795906107ac366123c6565b84549092916001600160a01b03918216331480156107e9575b6107ce906124ef565b168452602460205283209060ff801983541691151516179055565b5033865260196020528286205460ff166107c5565b5090346103c157816003193601126103c157602090610354612a57565b509134610497576020366003190112610497576020928291358152601d845220549051908152f35b5090346103c15760203660031901126103c1579081906001600160a01b03610869612384565b1681526022602052206001815491015482519182526020820152f35b5090346103c157806003193601126103c1576020906108af6108a5612384565b60243590336125c8565b5160018152f35b5090346103c157806003193601126103c1576108d0612384565b338352602160209081528284206001600160a01b039092165f81815292825291839020549093839160243581811061095b57505033815260218552818120835f52855280825f20555b3381526021855220815f528352815f205482519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b6109a49161099f855161096d816122e3565b601e81527f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008a820152828411156124ba565b6124e2565b33825260218652828220845f528652825f2055610919565b5090346103c157816003193601126103c15760015490516001600160a01b039091168152602090f35b5091346104975760203660031901126104975780359160018060a01b0384541633148015610ac1575b610a17906124ef565b600d54610a58610a5263ffffffff6011541692610a4b610a44600f5492610a3e84886128db565b906123f5565b4210612a0b565b42936128db565b856123f5565b1115610a66575050600d5580f35b906020608492519162461bcd60e51b8352820152602f60248201527f4e6577204c61756e636874696d65202b206f666644617973206d75737420626560448201526e20696e20746865206675747572652160881b6064820152fd5b5033845260196020528084205460ff16610a0e565b5090346103c157816003193601126103c157602090600c549051908152f35b5090346103c157816003193601126103c1578051610b2f91610b16826122e3565b6002825261135560f21b6020830152519182918261233d565b0390f35b5091346104975760203660031901126104975780359160018060a01b0384541633148015610bc2575b610b65906124ef565b611388831180610bb7575b15610b7d575050600a5580f35b906020606492519162461bcd60e51b835282015260146024820152736e6f7420612076616c696420736c69707061676560601b6044820152fd5b506127118310610b70565b5033845260196020528084205460ff16610b5c565b5090346103c157806003193601126103c157602090610354610bf7612384565b6024359061398f565b5090346103c157816003193601126103c1576020906018549051908152f35b5090346103c157816003193601126103c157602090600b549051908152f35b5090346103c157816003193601126103c157602090601e549051908152f35b5090346103c157816003193601126103c1576020906007549051908152f35b5090346103c157816003193601126103c15760095490516001600160a01b039091168152602090f35b5090346103c157816003193601126103c157602090600e549051908152f35b5090346103c15760203660031901126103c15760209160ff9082906001600160a01b03610cef612384565b1681526019855220541690519015158152f35b5090346103c15760203660031901126103c15760209181906001600160a01b03610d2a612384565b168152601b845220549051908152f35b50919082600319360112610497573415610e7d57610d5d601054600f54906125aa565b91610d66612a57565b90838211610e2b57610d7882856124e2565b60018101809111610e1857610d8d90346125aa565b928315610dbc5750505b82811115610da3578380f35b80610db183610db79361353f565b50613531565b610d97565b906020608492519162461bcd60e51b8352820152603060248201527f626174636841756374696f6e456e7472793a20696e73756666696369656e742060448201526f45544820666f7220616c6c206461797360801b6064820152fd5b634e487b7160e01b865260118252602486fd5b608490602084519162461bcd60e51b8352820152602660248201527f626174636841756374696f6e456e7472793a20696e76616c69642063757272656044820152656e742064617960d01b6064820152fd5b906020606492519162461bcd60e51b8352820152601f60248201527f626174636841756374696f6e456e7472793a206e6f204554482073656e7421006044820152fd5b5090346103c157816003193601126103c1576020906008549051908152f35b5090346103c157816003193601126103c15760209081549051908152f35b509182913461104f57602036600319011261104f5760095460065482516323b872dd60e01b815233818601526001600160a01b0391821660248201528435604482018190529492602090829060649082908a9087165af1801561101357611021575b5080600654169360011c93803b1561101d578580916044865180948193630b39c79b60e21b83526001898401528a60248401525af1801561101357908691610fff575b50506006541690813b15610ffb57604460019186809486519788958694636d80f47f60e11b865285015260248401525af1908115610ff25750610fe25750f35b610feb906122bb565b61035b5780f35b513d84823e3d90fd5b8480fd5b611008906122bb565b610ffb57845f610fa2565b84513d88823e3d90fd5b8580fd5b6110419060203d8111611048575b611039818361231b565b810190612592565b505f610f5f565b503d61102f565b5050fd5b508290602036600319011261035b57503415611080579061107860209234903561353f565b505160018152f35b6020606492519162461bcd60e51b8352820152602060248201527f627579536861726546726f6d41756374696f6e3a206e6f204554482073656e746044820152fd5b5090346103c157610795906110d6366123c6565b84549092916001600160a01b03916110f19083163314612547565b168452601960205283209060ff801983541691151516179055565b5090346103c157816003193601126103c15760209060ff6015541690519015158152f35b5091903461049757611141366123b0565b92909160018060a01b038554163314801561121d575b611160906124ef565b6103e98310156111ce576105dd84101561117f57505060075560085580f35b906020608492519162461bcd60e51b83528201526024808201527f53656c6c205461782056616c7565206e6f7420696e20616c6c6f7765642072616044820152636e67652160e01b6064820152fd5b906020608492519162461bcd60e51b83528201526024808201527f20427579205461782056616c7565206e6f7420696e20616c6c6f7765642072616044820152636e67652160e01b6064820152fd5b5033855260196020528085205460ff16611157565b5090346103c157816003193601126103c15760025490516001600160a01b039091168152602090f35b503461035b578060031936011261035b57610795612ef9565b5090346103c157806003193601126103c1579081906001600160a01b03611299612384565b168152602360205281812060243582526020522060ff6001825492015416825191825215156020820152f35b5090346103c157816003193601126103c157602090600f549051908152f35b503461035b57602036600319011261035b575061035460209235612d34565b509190346104975760203660031901126104975781359163ffffffff91828416809403610ffb5784546001600160a01b0316331480156113d1575b611347906124ef565b600d54926113786011549461136d610a44611367600f5480968a166128db565b836123f5565b610a3e4293886128db565b111561138e57505063ffffffff19161760115580f35b906020606492519162461bcd60e51b8352820152601d60248201527f4e756d62657220666f72206f66664461797320746f6f20736d616c6c210000006044820152fd5b5033855260196020528085205460ff1661133e565b503461035b57602036600319011261035b575061035460209235613760565b5090346103c157806003193601126103c15761141f612384565b33835281602093602185528181209260018060a01b031692835f52855261144b602435835f2054612416565b33825260218652828220845f528652825f20553381526021855220815f528352815f205482519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b5090346103c157816003193601126103c1576020905160128152f35b50919034610497576114cd366123b0565b92909160018060a01b03918286541633148015611b1a575b6114ee906124ef565b60036114f8612a57565b10611acd5784611506612a57565b1115611a72578486526020906025825260ff8388205416611a1c57858752601d825282872054605581029080820460551490151715611a09576064900493806009541695858731106119c657845161155d816122ff565b600281528536868301378284541691865163ef8ef56f60e01b815286818781875afa908c82156119bb579161271093916115ba939161198e575b50866115a286612ae7565b911690528a6115b085612b08565b52600a54906128db565b0483600654169187519387856024816370a0823160e01b9e8f8252888c8301525afa948515611984578d95611955575b50606442019283421161194257908d94939291813b1561101d578b896116339688968e519889978896879563b6f9de9560e01b8752860152608060248601526084850190612b18565b916044840152606483015203925af1801561193857611920575b505081600954169084836006541698602488518095819382528c898301525afa8015611916578a906118e3575b61168492506124e2565b9586156118945790889392918760011c90803b1561101d578580916044895180948193630b39c79b60e21b835260018a8401528760248401525af1801561188a57908691611876575b5050816006541690813b1561101d5785916044839289519485938492636d80f47f60e11b845260018a85015260248401525af180156118415790859161185e575b5088905260258352848420600160ff19825416179055838080808460015416601d885261173e8b8b8420546124e2565b90828215611855575bf11561184b576005541691845163528c890d60e11b815281818481875afa918215611841578592611824575b50506117d7575b5050507f1c047191e91ffa3e968d6304deca41a64944ccb1ae9116b3f331197d920e5a70936117d1916117ab612a57565b600e55519384934292859094939260609260808301968352602083015260408201520152565b0390a180f35b813b15610497578351630f8562c360e21b81529183918391829084905af1801561181a57611806575b8061177a565b61180f906122bb565b610ffb57845f611800565b83513d84823e3d90fd5b61183a9250803d1061104857611039818361231b565b5f80611773565b86513d87823e3d90fd5b84513d85823e3d90fd5b506108fc611747565b611867906122bb565b61187257835f61170e565b8380fd5b61187f906122bb565b610ffb57845f6116cd565b87513d88823e3d90fd5b845162461bcd60e51b81528084018590526024808201527f4e6f20746f6b656e732072656365697665642066726f6d206275796261636b206044820152630737761760e41b6064820152608490fd5b508482813d831161190f575b6118f9818361231b565b8101031261190b57611684915161167a565b5f80fd5b503d6118ef565b86513d8c823e3d90fd5b611929906122bb565b61193457885f61164d565b8880fd5b87513d84823e3d90fd5b634e487b7160e01b8e526011885260248efd5b9094508781813d831161197d575b61196d818361231b565b8101031261190b5751935f6115ea565b503d611963565b89513d8f823e3d90fd5b6119ae9150893d8b116119b4575b6119a6818361231b565b810190612ac8565b5f611597565b503d61199c565b8951903d90823e3d90fd5b845162461bcd60e51b8152808401859052601860248201527f496e73756666696369656e74204554482062616c616e636500000000000000006044820152606490fd5b634e487b7160e01b885260118252602488fd5b915162461bcd60e51b815291820152602c60248201527f6275796261636b20616e64206275696c6420616c726561647920646f6e65206660448201526b6f722074686973206461792160a01b6064820152608490fd5b6020608492519162461bcd60e51b8352820152603060248201527f7468652064617920796f752077616e7420746f206275796261636b20666f722060448201526f6973206e6f742066696e69736865642160801b6064820152fd5b6020608492519162461bcd60e51b8352820152602260248201527f696e76616c69642074696d6520666f72206275796261636b20616e64206275726044820152616e2160f01b6064820152fd5b5033865260196020528186205460ff166114e5565b5090346103c15760603660031901126103c1576108af602092611b50612384565b611b5861239a565b90604435928560018060a01b0380600954163303611b79575b5050506125c8565b83169182815260218952818120335f528952611b9886835f2054612470565b9281526021895220335f528752855f2055868581611b71565b5090346103c157816003193601126103c15760065490516001600160a01b039091168152602090f35b5090346103c157816003193601126103c1576020906012549051908152f35b5090346103c157816003193601126103c157602090600a549051908152f35b5090346103c157816003193601126103c157602090601a549051908152f35b509134610497576020366003190112610497578160209360ff923581526025855220541690519015158152f35b5091903461049757806003193601126104975760a09281906001600160a01b03611c8c612384565b168152601c6020528181206024358252602052208054926001820154926002830154916003840154930154938151958652602086015284015260608301526080820152f35b5090346103c157816003193601126103c15760055490516001600160a01b039091168152602090f35b5090346103c1576020928360031936011261049757803580611d1a612a57565b11156120bf5760019384821161204e575b33815260238652838120828252865283812054928315611ff25733825260238752848220838352875260ff86868420015416611f9a57611d69612a57565b611d78601054600f54906125aa565b9060028201809211611f8757918793918793101580611f15575b611eb6575b50670de0b6b3a7640000611db386611dae87613760565b6129b2565b5f80516020613ec78339815191528a8551611dcd816122e3565b601a815201520493338252601c8952828220818352895284848484200155338252601c895282822081835289524283832055338252601c895282822081835289524260038484200155611e2285600b546123f5565b600b5582518581526020810182905242604082015233907f830e279449af3d754a4667acaa6e90dedd7a8b466dd3f232bd2db88e6e77693a90606090a23382526023895282822090825288522001805460ff191685179055611e82612ef9565b8251918252848201527fe3e10b6a13fa59fdab56800bb8942e886fa0b6ffccb5a9e062d968c05becdd71823392a251908152f35b6006549193506001600160a01b039091169150813b156104975783602484928389519586948593637a0ae01f60e11b85528401525af18015611f0b57918591879315611d9757611f05906122bb565b5f611d97565b85513d84823e3d90fd5b5060065487516389a88c6f60e01b81528083018790529294509092508890829060249082906001600160a01b03165afa908115611f7d579183918793899591611f60575b5015611d92565b611f7791508a3d8c1161104857611039818361231b565b5f611f59565b86513d85823e3d90fd5b634e487b7160e01b845260118352602484fd5b845162461bcd60e51b8152908101879052602c60248201527f557365722068617320616c7265616479204368616e676564206869732053686160448201526b3932b9903a37902a37b5b2b760a11b6064820152608490fd5b845162461bcd60e51b8152908101879052603060248201527f5573657220686173206e65766572206465706f73697465642045544820746f2060448201526f746869732061756374696f6e4461792160801b6064820152608490fd5b8181526025865260ff8482205416611d2b57835162461bcd60e51b8152808401879052603360248201527f4275794261636b20616e64206275696c6420666f7220746869732064617920776044820152726173206e6f7420646f6e6520736f206661722160681b6064820152608490fd5b508360a492519162461bcd60e51b8352820152604960248201527f546f6b656e206f6620746869732061756374696f6e2064617920617265206e6f60448201527f7420726561647920746f206265206163636f756e74656420746f2075736572736064820152682076657374696e672160b81b6084820152fd5b5090346103c157816003193601126103c1576020906010549051908152f35b5090346103c157806003193601126103c15760209181612176612384565b91602435918291338152602187528181209460018060a01b0316948582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b5090346103c157816003193601126103c15760209063ffffffff601154169051908152f35b509134610497576020366003190112610497576020928291358152601f845220549051908152f35b5090346103c157816003193601126103c1578051610b2f91612237826122e3565b600a8252694d6f6e6965735472656560b01b6020830152519182918261233d565b5090346103c157816003193601126103c157602090600d549051908152f35b5090346103c157816003193601126103c157905490516001600160a01b039091168152602090f35b9050346103c157816003193601126103c1576020906017548152f35b67ffffffffffffffff81116122cf57604052565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176122cf57604052565b6060810190811067ffffffffffffffff8211176122cf57604052565b90601f8019910116810190811067ffffffffffffffff8211176122cf57604052565b602080825282518183018190529093925f5b82811061237057505060409293505f838284010152601f8019910116010190565b81810186015184820160400152850161234f565b600435906001600160a01b038216820361190b57565b602435906001600160a01b038216820361190b57565b604090600319011261190b576004359060243590565b604090600319011261190b576004356001600160a01b038116810361190b5790602435801515810361190b5790565b9190820180921161240257565b634e487b7160e01b5f52601160045260245ffd5b9061242190826123f5565b90811061242b5790565b60405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606490fd5b906124b79161099f604051612484816122e3565b601e81527f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006020820152828411156124ba565b90565b156124c25750565b60405162461bcd60e51b81529081906124de906004830161233d565b0390fd5b9190820391821161240257565b156124f657565b60405162461bcd60e51b8152602060048201526024808201527f4f776e61626c653a2063616c6c6572206973206e6f742066726f6d20746865206044820152637465616d60e01b6064820152608490fd5b1561254e57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e6044820152fd5b9081602091031261190b5751801515810361190b5790565b81156125b4570490565b634e487b7160e01b5f52601260045260245ffd5b6003546001600160a01b039283169391831692908116838114925f929091849081156128d1575b50806128a7575b1561280a575f80516020613ec783398151915293156127ff5761261c6007545b836129b2565b9260409686612710895196612630886122e3565b601a88526020988980990152049461267e8a5161264c816122e3565b601e81527f536166654d6174683a207375627472616374696f6e206f766572666c6f77000089820152828811156124ba565b6126d761268b87836124e2565b91838652601b89528b86205461099f8d516126a5816122e3565b601f81527f7472616e7366657220616d6f756e7420657863656564732062616c616e6365008c820152828411156124ba565b828552601b88528a8520558284528984206126f38282546123f5565b905589519081527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef978891a381600654168152601b84528681206127388482546123f5565b90558160065416908360011c91803b156103c15781809160448b5180948193630b39c79b60e21b8352600160048401528860248401525af180156127f5576127e6575b5090826006541690813b15610497578291604483928b519485938492636d80f47f60e11b84526001600485015260248401525af180156127dc576127c8575b5050600654169451908152a3565b6127d282916122bb565b61035b57806127ba565b88513d84823e3d90fd5b6127ef906122bb565b5f61277b565b89513d84823e3d90fd5b61261c600854612616565b507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92506040828560209452601b8452612882838383205461099f8551612850816122e3565b601f81527f7472616e7366657220616d6f756e7420657863656564732062616c616e63650089820152828411156124ba565b868252601b8552828220558681522061289c8282546123f5565b9055604051908152a3565b50848352602460205260ff6040842054161580156125f6575085835260ff604084205416156125f6565b905086145f6125ef565b8181029291811591840414171561240257565b801561296b57670de0b6b3a76400008082029180830482036124025761291490836125aa565b0361291c5790565b60405162461bcd60e51b815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6044820152607760f81b6064820152608490fd5b505f90565b801561296b57600381029080820460030361240257612914600391836125aa565b801561296b57606f810290808204606f0361240257612914606f91836125aa565b9081156129cd576129146129c682846128db565b92836125aa565b50505f90565b906124b791612a066040516129e7816122e3565b601a81525f80516020613ec783398151915260208201528315156124ba565b6125aa565b15612a1257565b60405162461bcd60e51b815260206004820152601e60248201527f41756374696f6e73206861766520616c726561647920737461727465642100006044820152606490fd5b600d5463ffffffff60115416600f5490612a7a612a7483836128db565b846123f5565b92612a8860145480956123f5565b421015612a9757505050505f90565b612aba93612aaf612ab492610a3e86612a06966128db565b6123f5565b426124e2565b600101806001116124025790565b9081602091031261190b57516001600160a01b038116810361190b5790565b805115612af45760200190565b634e487b7160e01b5f52603260045260245ffd5b805160011015612af45760400190565b9081518082526020808093019301915f5b828110612b37575050505090565b83516001600160a01b031685529381019392810192600101612b29565b905f9182526020601d815260409081842054605581029080820460551490151715612d2057606490048015612d1b57825190612b8f826122ff565b6002825283368484013760048054855163ef8ef56f60e01b81526001600160a01b0391821693928690829081875afa908115612d11579189959391869593612c1c9a9b91612cf4575b5081612be386612ae7565b9116905260095416612bf484612b08565b52865180988194829363d06ca61f60e01b845260048401528960248401526044830190612b18565b03915afa928315612cea578193612c3f575b505050612c3b9150612b08565b5190565b909192503d8083863e612c52818661231b565b840191838584031261035b57845167ffffffffffffffff9586821161049757019083601f8301121561035b578151958611612cd6578560051b925195612c9a8685018861231b565b8652848087019383010193841161035b57508301905b828210612cc75750505050612c3b905f8080612c2e565b81518152908301908301612cb0565b634e487b7160e01b81526041600452602490fd5b51903d90823e3d90fd5b612d0b9150883d8a116119b4576119a6818361231b565b5f612bd8565b87513d8b823e3d90fd5b505050565b634e487b7160e01b85526011600452602485fd5b612d43601054600f54906125aa565b811115612ef257600654604080516318bad88b60e11b8152600481018490526001600160a01b03909216929091602091908281602481885afa908115612e7157908392915f91612ed5575b50612e7b57612d9d9150612b54565b825163a515a5bd60e01b81529060011c8282600481885afa918215612e71575f92612e40575b5091612dd281926004946123f5565b948451938480926333b5f0b560e01b82525afa928315612e3757505f92612e06575b5050612e02906064926128db565b0490565b81819392933d8311612e30575b612e1d818361231b565b8101031261035b57505181612e02612df4565b503d612e13565b513d5f823e3d90fd5b90918382813d8311612e6a575b612e57818361231b565b8101031261035b57505190612dd2612dc3565b503d612e4d565b84513d5f823e3d90fd5b60248451809681936377238c7760e01b835260048301525afa918215612e3757505f91612ea9575b50905090565b82813d8311612ece575b612ebd818361231b565b8101031261035b575051805f612ea3565b503d612eb3565b612eec9150833d851161104857611039818361231b565b5f612d8e565b5060175490565b6002612f03612a57565b14806134be575b613104575b612f17612a57565b60105490612f295f92600f54906125aa565b906002820180921161308057101580613094575b61301b575b600e54612f4d612a57565b1180612fc2575b612f67575b50612f62612a57565b600e55565b6005546001600160a01b0316803b156103c157818091600460405180948193630f8562c360e21b83525af18015612fb757612fa3575b50612f59565b612fad82916122bb565b61035b5780612f9d565b6040513d84823e3d90fd5b5060055460405163528c890d60e11b815290602090829060049082906001600160a01b03165afa908115612fb7578291612ffd575b50612f54565b613015915060203d811161104857611039818361231b565b5f612ff7565b6006546001600160a01b031661302f612a57565b5f19810190811161308057813b15610497578291602483926040519485938492637a0ae01f60e11b845260048401525af18015612fb757613071575b50612f42565b61307a906122bb565b5f61306b565b634e487b7160e01b83526011600452602483fd5b506006546001600160a01b03166130a9612a57565b5f198101908111613080576020906024604051809481936389a88c6f60e01b835260048301525afa908115612fb75782916130e6575b5015612f3d565b6130fe915060203d811161104857611039818361231b565b5f6130df565b6017546102fd90818102918183041490151715612402576009546001600160a01b0392916103e890049061313b90829085166134ca565b5f9260018452602093601d85526040948582205460558102908082046055149015171561308057606490049280600954168481311061346657838383600254169260448b518094819363095ea7b360e01b8352600497888401525f1960248401525af1801561342c57613449575b50818154169082600954166064420192834211613436579060c489896060948e51978895869463f305d71960e01b8652818a87015260248601528c60448601528c6064860152608485015260a48401525af191821561342c5785926133f7575b508054895163c45a015560e01b815290841685828481845afa9182156133ce57839291879189936133d8575b508c5163ef8ef56f60e01b815293849182905afa9182156133ce5760448c9387899481948c936133af575b5081600954169651968795869463e6a4390560e01b865216898501526024840152165afa9081156133a5578592878681946044948391613388575b5016806bffffffffffffffffffffffff60a01b60035416176003558d51968795869463a9059cbb60e01b865285015260248401525af1801561337e578493601d859485948594613361575b50600154169160018452526132fe878b8420546124e2565b90828215613358575bf11561334d575092519081526020810192909252426040830152907fa9632746d1a957634e707ce9a2abb47f8431306c20c70876bf17212eddd388f090606090a1612f0f565b8451903d90823e3d90fd5b506108fc613307565b61337790843d861161104857611039818361231b565b505f6132e6565b88513d86823e3d90fd5b61339f9150873d89116119b4576119a6818361231b565b5f61329b565b8a513d88823e3d90fd5b6133c7919350863d88116119b4576119a6818361231b565b915f613260565b8b513d89823e3d90fd5b6133f0919350823d84116119b4576119a6818361231b565b915f613235565b9091506060813d8211613424575b816134126060938361231b565b81010312610ffb57880151905f613209565b3d9150613405565b89513d87823e3d90fd5b634e487b7160e01b875260118352602487fd5b61345f90843d861161104857611039818361231b565b505f6131a9565b875162461bcd60e51b815260048101849052602b60248201527f6164644669727374446179734c69713a206e6f7420656e6f756768204554482060448201526a1a5b8818dbdb9d1c9858dd60aa1b6064820152608490fd5b506001600e5414612f0a565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60205f9260018060a01b031693848452601b825261350d816040862054612416565b858552601b8352604085205561352581601a54612416565b601a55604051908152a3565b5f1981146124025760010190565b9060115460209060ff81831c161561371b5761356e61357791610a3e600d549163ffffffff600f5491166128db565b601454906123f5565b42106136d757613585612a57565b831061368257907ec639b627799a5a1755e1d6b1557ddc43a507ee06867a140a2e082ca142cd0f915f90848252601d815260409182918282206135c98682546123f5565b90556135d785601e546123f5565b601e55338252602381528282208783528152828220541561365b575b3382526022815260018383200161360b8682546123f5565b9055338252602381528282209087835252206136288382546123f5565b9055613632612ef9565b600e549051918252602082019390935260408101929092524260608301523391608090a2600190565b6136658154613531565b8155868252601f815282822061367b8154613531565b90556135f3565b6084906040519062461bcd60e51b82526004820152602860248201527f627579536861726546726f6d41756374696f6e3a20696e76616c69642061756360448201526774696f6e2064617960c01b6064820152fd5b6064906040519062461bcd60e51b82526004820152601e60248201527f41756374696f6e732068617665206e6f742073746172746564207965742100006044820152fd5b60405162461bcd60e51b815260048101839052601e60248201527f41756374696f6e73206172652063757272656e746c79207061757365642100006044820152606490fd5b5f908082526020601d8152604090818420549283155f14613782575050505090565b6137966010959293949554600f54906125aa565b81116137b457505050506124b7906137af6017546128ee565b6129d3565b60065484516389a88c6f60e01b8152600481018390526001600160a01b0390911691908481602481865afa908115613985578491613968575b506138ed5750835163a515a5bd60e01b81528381600481855afa9081156138e357849084926138b5575b5085516333b5f0b560e01b81529192829060049082905afa9283156138aa578093613876575b505060649261385f6124b79695935f80516020613ec7833981519152936129b2565b925161386a816122e3565b601a81520152046129d3565b909192508382813d83116138a3575b61388f818361231b565b8101031261035b575051908261385f61383d565b503d613885565b8551903d90823e3d90fd5b809250813d83116138dc575b6138cb818361231b565b810103126104975751836004613817565b503d6138c1565b85513d85823e3d90fd5b928091936024865180968193621614f960e81b835260048301525afa93841561395d57508193613928575b505050906137af6124b7926128ee565b9091809350813d8311613956575b613940818361231b565b8101031261035b5750516137af6124b75f613918565b503d613936565b51913d9150823e3d90fd5b61397f9150853d871161104857611039818361231b565b5f6137ed565b86513d86823e3d90fd5b60018060a01b0316905f828152601c60209181835260409384822081835284528482205415613b28579083929186825282845285822081835284526139ee6139e96139e060038986200154426124e2565b601654906129b2565b612970565b926139fe601054600f54906125aa565b8211613b0d5787835280855286832082845285526064613a2360018986200154612991565b5f80516020613ec7833981519152878a51613a3d816122e3565b601a8152015204975b8084528186528784208385528652613a648560018a872001546129b2565b988851613a70816122e3565b601a81525f80516020613ec78339815191529889910152818552828752888520848652875280613ab260048b8820015468056bc75e2d63100000809d04612416565b11613aea575083528452858220908252835284902060010154613ad591906129b2565b9251613ae0816122e3565b601a815201520490565b979592936124b79950600497508095505281528383209183525220015490612470565b87835280855286832082845285526001878420015497613a46565b50935050505090565b60018060a01b03165f91818352601c9260209184835260409283832082845281528383205415613cf9578483528581528383208284528152613b7f6139e96139e060038787200154426124e2565b95613b8f601054600f54906125aa565b8311613cdd578584528082528484208385528252816064613bb560018888200154612991565b5f80516020613ec7833981519152838951613bcf816122e3565b601a8152015204975b8786528282528686208587528252613bf660018888200154826129b2565b908751613c02816122e3565b601a81525f80516020613ec78339815191529384910152888752838552878720868852855289613c4460048a8a20015468056bc75e2d63100000809504612416565b11613cbc576124b7995091613ca791613c7888979695948b60029b9a52858752898920888a52875260018a8a2001546129b2565b91858951613c85816122e3565b601a815201528987528385528787208688528552600488882001549104612416565b96845281528383209183525220015490612470565b5050509483529384528282209082529092529020600201546124b791612470565b8584528082528484208385528252816001868620015497613bd8565b50509250505090565b905f91338352601c9060208281526040918286208187528252613d3560048488200154613d2f833361398f565b90612416565b338752848352838720828852835260048488200155338652838252828620818752825242600384882001553386528382528286208187528252613d936004848820015433885285845284882083895284526002858920015490612470565b93338752808352838720828852835260048488200154903388528352838720828852835260028488200155613dcd601054600f54906125aa565b1015613e925760065485906001600160a01b0316803b156103c15781906044855180948193630138792d60e51b83523360048401528960248401525af18015613e88579583917f93b2b5baeb90867d00d09e02023eed58ae019d05b1c254578512984cc85e5ba6959697613e79575b505b3381526022835220613e518582546123f5565b9055613e5f84600c546123f5565b600c55613e6a612ef9565b815193845242908401523392a2565b613e82906122bb565b5f613e3c565b83513d88823e3d90fd5b81839495613ec17f93b2b5baeb90867d00d09e02023eed58ae019d05b1c254578512984cc85e5ba695336134ca565b613e3e56fe536166654d6174683a206469766973696f6e206279207a65726f000000000000a26469706673582212200d28c028060f251b43ab1327e6b68c7f4c909f7702c53e6d56e61eda20f8332664736f6c63430008140033608080604052346100405762093a806002908155600c55600d805460ff191660011790555f80546001600160a01b031916331790556116b090816100458239f35b5f80fdfe608060409080825260049081361015610016575f80fd5b5f92833560e01c91826306fdde0314610efc575081630e666e4914610ebc57816314c7c64914610e20578163246a1a4514610e015781632e1a7d4d14610b6757816331b7558b14610aae57816331d7a2621461079e578163339a055114610a87578163372500ab146108fb5781633e158b0c146108e2578163413ab4a8146108b95781634bf6f9e71461087e578163527a52c814610833578163634ebd27146107f85781637f0e5463146107d95781638051d7dd1461079e5781638330b5b514610775578163a519121a14610751578163b6b55f25146104f1578163b7aab50f146104b8578163c00c9f7f14610268578163c3214d6c14610223578163db56a6d614610204578163dbc588d4146101e5578163e1ad418e146101a6578163e53b78801461017e575063f31878ae1461014c575f80fd5b3461017a57602036600319011261017a57356001600160a01b038116810361017a576101779061106b565b80f35b5080fd5b83903461017a578160031936011261017a57905490516001600160a01b039091168152602090f35b919050346101e15760203660031901126101e157356001600160a01b038116908190036101e157828291602094526003845220549051908152f35b8280fd5b83903461017a578160031936011261017a57602090600b549051908152f35b83903461017a578160031936011261017a57602090600c549051908152f35b919050346101e15760203660031901126101e1573591600854831015610265575061024f602092611001565b905491519160018060a01b039160031b1c168152f35b80fd5b9050346101e157826003193601126101e15761028261128e565b61028b3361106b565b33835260206007815281842054916102a48315156115c8565b338552600782528481812055600382528085206102c284825461104a565b905533855260038252670de0b6b3a76400006102e482872054600b5490611244565b5f8051602061165b8339815191528484516102fe81610f7c565b601a81520152338752858452048186205560018060a01b03858160015416803b1561017a5783516303b3990960e21b815230818901908152602081018890529091839183919082908490829060400103925af180156104ae57610496575b505061036a84600a5461104a565b600a5580865416908251848188816373701e1960e01b968782525afa90811561048c579085939291899161045d575b508852600683528388206103ae87825461104a565b90553388526005835242848920558754169583518097819382525afa938415610453578594610420575b503385526003825280852054918151948552429085015283015260608201527f9d9bcddfe8d49f23f1d54f0cd96a8eb8801b41a362bab4e61910b2b34b8f33e460803392a280f35b9093508181813d831161044c575b6104388183610f98565b810103126104485751925f6103d8565b5f80fd5b503d61042e565b81513d87823e3d90fd5b84819592503d8311610485575b6104748183610f98565b81010312610448578492515f610399565b503d61046a565b84513d8a823e3d90fd5b61049f90610f54565b6104aa57855f61035c565b8580fd5b84513d84823e3d90fd5b919050346101e15760203660031901126101e15735916001600160a01b038316830361026557506104ea60209261160b565b9051908152f35b919050346101e1576020918260031936011261074d57813561051161128e565b61051a3361106b565b845482516323b872dd60e01b81523385820152306024820152604481018390526001600160a01b03918690829060649082908b9087165af180156107435790869291610716575b5033875260098252838720805460ff8116156106b8575b50503387526003825283872061058f84825461104a565b905533875260038252670de0b6b3a76400006105b185892054600b5490611244565b5f8051602061165b8339815191528487516105cb81610f7c565b601a8152015233895286845204848820556105e883600a5461104a565b600a558654168351948580926373701e1960e01b82525afa80156106ae578590610661575b7f024a51579966a3ad01a4d870ecb6e03ebff42e00474a444a97ee3e5fa1fad071935085526006845281852061064482825461104a565b90553385526005845242828620558151934285528401523392a280f35b508383813d83116106a7575b6106778183610f98565b81010312610448577f024a51579966a3ad01a4d870ecb6e03ebff42e00474a444a97ee3e5fa1fad071925161060d565b503d61066d565b82513d87823e3d90fd5b60ff191660011790556008549091506801000000000000000081101561070357906106ea826001889401600855611001565b81549060031b908333831b921b19161790555f80610578565b634e487b7160e01b875260418552602487fd5b61073590833d851161073c575b61072d8183610f98565b810190611276565b505f610561565b503d610723565b84513d89823e3d90fd5b8380fd5b83903461017a578160031936011261017a5760209060ff600d541690519015158152f35b919050346101e15760203660031901126101e15760209282913581526006845220549051908152f35b919050346101e15760203660031901126101e157356001600160a01b038116908190036101e157828291602094526007845220549051908152f35b83903461017a578160031936011261017a57602090600a549051908152f35b919050346101e15760203660031901126101e157356001600160a01b038116908190036101e157828291602094526005845220549051908152f35b50503461017a57602036600319011261017a57356001600160a01b03818116918290036101e157825416330361017a576bffffffffffffffffffffffff60a01b600154161760015580f35b919050346101e15760203660031901126101e15780356001600160a01b0381169081900361074d579282916020948252845220549051908152f35b83903461017a578160031936011261017a5760015490516001600160a01b039091168152602090f35b833461026557806003193601126102655761017761128e565b9050346101e157826003193601126101e15761091561128e565b61091e3361106b565b3383526020906007825280842054916109388315156115c8565b33855260078152848281205560038152670de0b6b3a764000061096183872054600b5490611244565b5f8051602061165b83398151915283855161097b81610f7c565b601a81520152338752858352048286205560018060a01b038060015416803b15610a835783516303b3990960e21b815233878201908152602081018790529091889183919082908490829060400103925af1801561074357610a70575b5081903387526005825242848820558654168351958680926373701e1960e01b82525afa9384156106ae578594610a41575b50815193845242908401528201527f7528a4fb347cbaa8b6bc7e4af2d66d9907225b4a4e5863287bdbbf5aaed62ab260603392a280f35b9080945081813d8311610a69575b610a598183610f98565b810103126104485751925f610a0a565b503d610a4f565b95610a7c839297610f54565b95906109d8565b8680fd5b83903461017a578160031936011261017a5760209060ff600d5460081c1690519015158152f35b9050346101e15760203660031901126101e15781359182151580930361074d57835482516338ca571d60e11b815233928101929092526001600160a01b031690602081602481855afa928315610b5e57508492610b3e575b508115610b34575b501561017a57610b1c61128e565b61ff00600d549160081b169061ff00191617600d5580f35b905033145f610b0e565b610b5791925060203d811161073c5761072d8183610f98565b905f610b06565b513d86823e3d90fd5b8391503461017a57602090816003193601126101e157833593610b893361160b565b610dc75733845260038352848285205410610d7657610ba661128e565b610baf3361106b565b33845260038352818420610bc4868254611197565b905533845260038352670de0b6b3a7640000610be683862054600b5490611244565b5f8051602061165b833981519152858551610c0081610f7c565b601a815201523386528285520482852055610c1d85600a54611197565b600a55835482516373701e1960e01b81526001600160a01b0391859082908590829086165afa908115610d6c578691610d3f575b50855260068452828520610c66878254611197565b90558454835163a9059cbb60e01b815233848201908152602081018990529092869284928390036040019183918a91165af1908115610d35578591610d18575b5015610cdf575080847fce55fb2734b82a39f039ae72ac899be08fca1bfd9b8f56c3122ac8616efe1b419251934285528401523392a280f35b82606492519162461bcd60e51b83528201526015602482015274151bdad95b881d1c985b9cd9995c8819985a5b1959605a1b6044820152fd5b610d2f9150843d861161073c5761072d8183610f98565b86610ca6565b83513d87823e3d90fd5b90508481813d8311610d65575b610d568183610f98565b810103126104aa575187610c51565b503d610d4c565b84513d88823e3d90fd5b82608492519162461bcd60e51b8352820152602760248201527f576974686472617720616d6f756e742065786365656473207374616b65642062604482015266616c616e63652160c81b6064820152fd5b82606492519162461bcd60e51b835282015260166024820152755374616b65206973207374696c6c206c6f636b65642160501b6044820152fd5b83903461017a578160031936011261017a576020906002549051908152f35b919050346101e157826003193601126101e157825482516338ca571d60e11b815233928101929092526001600160a01b031690602081602481855afa928315610eb357508392610e93575b508115610e89575b501561026557600160ff19600d541617600d5580f35b905033145f610e73565b610eac91925060203d811161073c5761072d8183610f98565b905f610e6b565b513d85823e3d90fd5b919050346101e15760203660031901126101e157356001600160a01b038116908190036101e157818360ff92602095526009855220541690519015158152f35b8491346101e157826003193601126101e157610f509250610f1c82610f7c565b601782527f5374616b6520616e64204561726e20436f6e747261637400000000000000000060208301525191829182610fba565b0390f35b67ffffffffffffffff8111610f6857604052565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff821117610f6857604052565b90601f8019910116810190811067ffffffffffffffff821117610f6857604052565b602080825282518183018190529093925f5b828110610fed57505060409293505f838284010152601f8019910116010190565b818101860151848201604001528501610fcc565b6008548110156110365760085f527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee301905f90565b634e487b7160e01b5f52603260045260245ffd5b9190820180921161105757565b634e487b7160e01b5f52601160045260245ffd5b60018060a01b03165f9080825260209060038252604091828420548015611168578161109c600492600b5490611244565b9385516110a881610f7c565b601a81525f8051602061165b833981519152948591015261111e670de0b6b3a7640000809604828952848452878920549061111989516110e781610f7c565b601e81527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000878201528284111561116f565b611197565b8188526007835261113387892091825461104a565b90558087526003825261114c86882054600b5490611244565b9382875161115981610f7c565b601a8152015286525204912055565b5050505050565b156111775750565b60405162461bcd60e51b81529081906111939060048301610fba565b0390fd5b9190820391821161105757565b81156111ae570490565b634e487b7160e01b5f52601260045260245ffd5b801561123f57670de0b6b3a7640000808202918083048203611057576111e890836111a4565b036111f05790565b60405162461bcd60e51b815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6044820152607760f81b6064820152608490fd5b505f90565b90811561126257808202918083048203611057576111e890836111a4565b50505f90565b5f1981146110575760010190565b90816020910312610448575180151581036104485790565b5f8054604080516373701e1960e01b81526001600160a01b039460049490936020919082908490889082908b165afa9283156115bc57819361158d575b50600d549560ff8716156115835783600c5410156115835760ff600897881c16611577578382526006908184528583208054158061156c575b611561575b50600c545b858110611386575050505b855481101561134a57806113408861133361134594611001565b90549060031b1c1661106b565b611268565b611319565b5090919294507f77de657bed0b46fc066982877c0c58de0dd2f56632a65a2c925dc6196b51af2f935081600c55600b54908351928352820152a1565b6001805488516318bad88b60e11b815284810184905260249392918d169088818681855afa908115611557579289928f9287958b9161153a575b50156114e9575b5054168a51928380926377238c7760e01b825286898301525afa9081156114df5786916114b2575b5081865284875288862054801561146f575b61141793508015158061141c575b505050611268565b61130e565b61145361142b611458946111c2565b918c519061143882610f7c565b601a82525f8051602061165b8339815191528c83015261116f565b6111a4565b611465600b91825461104a565b90555f808061140f565b5090915f198301908382116114a15750908161141793928752858852898720548388528a882055865288862054611401565b634e487b7160e01b87526011855286fd5b90508681813d83116114d8575b6114c98183610f98565b810103126104aa57515f6113ef565b503d6114bf565b89513d88823e3d90fd5b9250925050803b15610a8357868091858c518094819363347bd69d60e21b8352888b8401525af1801561153057849289928f92156113c75761152a90610f54565b5f6113c7565b8a513d89823e3d90fd5b6115519150853d871161073c5761072d8183610f98565b5f6113c0565b8b513d8a823e3d90fd5b600a5490555f611309565b50600a541515611304565b505050600c5550915050565b5050505050915050565b9092508181813d83116115b5575b6115a58183610f98565b810103126101e15751915f6112cb565b503d61159b565b508351903d90823e3d90fd5b156115cf57565b60405162461bcd60e51b81526020600482015260146024820152734e6f207265776172647320746f20636c61696d2160601b6044820152606490fd5b6001600160a01b03165f818152600560205260409020546002549061163190829061104a565b421061163d5750505f90565b611657915f526005602052611119429160405f205461104a565b9056fe536166654d6174683a206469766973696f6e206279207a65726f000000000000a2646970667358221220baf93e6d92a82029b8f5011155ef63bfbba1536aaf08719dc4c08df9f375756564736f6c6343000814003360803461008257601f610d4738819003918201601f19168301916001600160401b038311848410176100865780849260209460405283398101031261008257516001600160a01b0381169081900361008257600a600355603260075560018060a01b031933815f5416175f556001541617600155604051610cac908161009b8239f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040818152600480361015610014575f80fd5b5f92833560e01c90816306fdde0314610a7d575080630ece6424146109885780630fffde38146109695780631614f90014610942578063270f25a0146108445780632ce71e6c146107825780633175b1161461075657806333b5f0b514610737578063448972601461071a5780635fbec760146106fb5780636ae594441461066457806377238c771461063d578063878493c51461061e5780638799dbce146105f057806387f075d9146105d157806389a88c6f146105a55780638e7e2449146104c05780638efb31c71461041057806390239739146103f1578063a515a5bd146103d2578063b7258a78146103a9578063d1ef5a74146102e8578063db01e8fe14610224578063e53b7880146101f85763f415c03e14610133575f80fd5b346101e65760203660031901126101e657825490359190336001600160a01b03918216149081156101ea575b50156101e6577ffc27af1225a3a689115d8d8e0a25a292847f8ddf6647cc335f537e3c5c10db57916006546101a3606461019b60075484610c63565b048092610c56565b600655818552600d60205280838620556101bf81600854610c35565b600855818552600c602052828520600160ff1982541617905582519182526020820152a180f35b8280fd5b90506001541633145f61015f565b505034610220578160031936011261022057905490516001600160a01b039091168152602090f35b5080fd5b5050346102205761023436610b99565b835490929190336001600160a01b03918216149081156102da575b50156102d6577f68f567dab8c491c8f7b458d154ea75a5728045b122e67ee1b377adc502fa0a8c9260a09282156102c25761028c82600254610c35565b6002555b80519260608452600d60608501526c5374616b65205265736572766560981b608085015215156020840152820152a180f35b6102ce82600254610c56565b600255610290565b8380fd5b90506001541633145f61024f565b5090346101e65760203660031901126101e6578254823590336001600160a01b039182161490811561039b575b50156102d6577fdd946c37ff600aa10dae3920e9583253c63eb9b353cc349d0a37f723a72f671b926002549061035a606461035260035485610c63565b048093610c56565b600255828652600b6020528184872055610375828254610c35565b9055818552600a602052828520600160ff1982541617905582519182526020820152a180f35b90506001541633145f610315565b50503461022057816003193601126102205760015490516001600160a01b039091168152602090f35b5050346102205781600319360112610220576020906006549051908152f35b5050346102205781600319360112610220576020906002549051908152f35b5090346101e65760203660031901126101e657825481516338ca571d60e11b8152338185015292359290602090829060249082906001600160a01b03165afa9182156104b757508391610489575b50156102205760018110158061047e575b61047890610bd0565b60035580f35b50606481111561046f565b6104aa915060203d81116104b0575b6104a28183610b39565b810190610bb8565b5f61045e565b503d610498565b513d85823e3d90fd5b50346101e6576020806003193601126102d6578382359260018060a01b0382541685516338ca571d60e11b815233838201528481602481855afa90811561059b57849161057e575b50156101e65760648492875194859384926323b872dd60e01b845233908401523060248401528860448401525af18015610574576105509450610556575b5050600254610c35565b60025580f35b8161056c92903d106104b0576104a28183610b39565b505f80610546565b84513d87823e3d90fd5b6105959150853d87116104b0576104a28183610b39565b5f610508565b87513d86823e3d90fd5b50346101e65760203660031901126101e6578160209360ff92358152600c855220541690519015158152f35b5050346102205781600319360112610220576020906003549051908152f35b505034610220578160031936011261022057602090606461061660025460035490610c63565b049051908152f35b5050346102205781600319360112610220576020906009549051908152f35b50346101e65760203660031901126101e6576020928291358152600b845220549051908152f35b5090346101e65760203660031901126101e657825481516338ca571d60e11b8152338185015292359290602090829060249082906001600160a01b03165afa9182156104b7575083916106dd575b5015610220576001811015806106d2575b6106cc90610bd0565b60075580f35b5060648111156106c3565b6106f5915060203d81116104b0576104a28183610b39565b5f6106b2565b5050346102205781600319360112610220576020906005549051908152f35b50346101e657826003193601126101e65760209250549051908152f35b5050346102205781600319360112610220576020906007549051908152f35b50346101e65760203660031901126101e6578160209360ff92358152600a855220541690519015158152f35b5050346102205761079236610b99565b835490929190336001600160a01b0391821614908115610836575b50156102d6577f68f567dab8c491c8f7b458d154ea75a5728045b122e67ee1b377adc502fa0a8c9260a0928215610822576107ea82600654610c35565b6006555b80519260608452600f60608501526e41756374696f6e205265736572766560881b608085015215156020840152820152a180f35b61082e82600654610c56565b6006556107ee565b90506001541633145f6107ad565b50346101e65761085336610b6f565b845490926001600160a01b03918216918690338414908115610934575b501561093157855163a9059cbb60e01b81526001600160a01b03851692810192835260208381018790529093909284928391829060400103925af18015610574579361090d917fe57c1894aae7c0e57d9375b5be68aaea74652be1d22c145c9266d65fa1ef741795610913575b506108ea84600954610c35565b600955516001600160a01b03909216825260208201929092529081906040820190565b0390a180f35b61092a9060203d81116104b0576104a28183610b39565b505f6108dd565b80fd5b90506001541633145f610870565b50346101e65760203660031901126101e6576020928291358152600d845220549051908152f35b5050346102205781600319360112610220576020906008549051908152f35b50346101e65761099736610b6f565b845490926001600160a01b03918216918690338414908115610a6f575b501561093157855163a9059cbb60e01b81526001600160a01b03851692810192835260208381018790529093909284928391829060400103925af18015610574579361090d917f8d0a72843f40bd8772e61bbbff6d33b86a4ff3ba86116b3a9e5019839046073395610a51575b50610a2e84600554610c35565b600555516001600160a01b03909216825260208201929092529081906040820190565b610a689060203d81116104b0576104a28183610b39565b505f610a21565b90506001541633145f6109b4565b919050346102d657836003193601126102d657606082019082821067ffffffffffffffff831117610b2657508252602181526020907f54617820616e6420427579204261636b205265736572766520436f6e7472616382820152601d60fa1b8382015282519382859384528251928382860152825b848110610b1057505050828201840152601f01601f19168101030190f35b8181018301518882018801528795508201610af2565b634e487b7160e01b855260419052602484fd5b90601f8019910116810190811067ffffffffffffffff821117610b5b57604052565b634e487b7160e01b5f52604160045260245ffd5b6040906003190112610b95576004356001600160a01b0381168103610b95579060243590565b5f80fd5b6040906003190112610b95576004358015158103610b95579060243590565b90816020910312610b9557518015158103610b955790565b15610bd757565b60405162461bcd60e51b815260206004820152603060248201527f4e65772056616c7565206973206e6f7420696e207468652072616e676520626560448201526f747765656e203120616e64203130302160801b6064820152608490fd5b91908201809211610c4257565b634e487b7160e01b5f52601160045260245ffd5b91908203918211610c4257565b81810292918115918404141715610c425756fea2646970667358221220579240900845f334e6a6d6ae6c2f3d994a6b780aedfee3673ac77e372c4035da64736f6c63430008140033
Deployed ByteCode
0x6080604081815260049182361015610021575b505050361561001f575f80fd5b005b5f90813560e01c9081630177672e1461229f5750806301bc45c914612277578063022466b51461225857806306fdde031461221657806307283166146121ee57806308649840146121c9578063095ea7b3146121585780630cccfc5814612139578063108b90a414611cfa578063123e73c214611cd1578063143ee5b914611c645780631585119914611c3757806318160ddd14611c185780631822153214611bf95780632018907e14611bda5780632281b57514611bb157806323b872dd14611b2f57806325e10205146114bc578063313ce567146114a057806339509351146114055780633a52bedd146113e6578063429fed0d1461130357806345fd7df2146112e45780634bd9351b146112c55780634c59ffde146112745780634fe1c3531461125b578063504de2b01461123257806350ef22511461113057806352d63d491461110c57806355b35da3146110c257806358d26b6e146110535780635c9302c914610ca557806362244b3414610efd5780636ba13a8214610edf5780636f7806de1461065f5780636fb1896c14610ec05780637012e44c14610d3a57806370a0823114610d025780637194ae3a14610cc457806373701e1914610ca557806379e10daa14610c7c5780637df405a414610c5d578063834368ae14610c3e57806385c1a33c14610c1f5780638e80ff5d14610c005780638f10aca714610bd757806390f6c87214610b3357806395d89b4114610af55780639aa4611014610ad65780639ff46e74146109e5578063a342f238146109bc578063a457c2d7146108b6578063a9059cbb14610885578063aebc463b14610843578063b997fe821461081b578063bf627bf5146107fe578063c2ed286b14610798578063c843bae614610778578063c8a3fe8114610759578063c9b542ac1461069d578063cb4ca6311461065f578063cc1348391461055f578063d1b4b9a31461053a578063d25b17b614610511578063d7abc59b146104e8578063dd62ed3e1461049b578063edae876f1461046f578063f22fc41314610450578063f7a6b2f9146103c5578063f85bd4f11461035e5763fdd5eaeb03610012573461035b57602036600319011261035b575061035460209235612b54565b9051908152f35b80fd5b5090346103c15736600319011261035b57610377612384565b61037f61239a565b82546001600160a01b03928392919061039b8483163314612547565b6bffffffffffffffffffffffff60a01b9485911691161784551690600154161760015580f35b5080fd5b5090346103c157816003193601126103c15760018091815b6103e5578380f35b6103ed612a57565b82111580610438575b156104345761042083923386526020601c8152838720908288525283838720015461042657613531565b916103dd565b61042f81613d02565b613531565b8380f35b50610448601054600f54906125aa565b8211156103f6565b5090346103c157816003193601126103c1576020906013549051908152f35b5091346104975782600319360112610497575490516001600160a01b03909116815260209150f35b8280fd5b5090346103c157806003193601126103c1576020916104b8612384565b826104c161239a565b6001600160a01b03928316845260218652922091165f908152908352819020549051908152f35b5090346103c157806003193601126103c157602090610354610508612384565b60243590613b31565b5090346103c157816003193601126103c15760035490516001600160a01b039091168152602090f35b5090346103c157816003193601126103c1576011549051602091821c60ff1615158152f35b5091903461049757826003193601126104975782546001600160a01b03163314801561064a575b61058f906124ef565b60ff601554166105f4578260115460ff8160201c165f146105c0575064ff0000000019601154166011554260125580f35b6401000000009064ff00000000191617601155426013556105ee6105e6601254426124e2565b6014546123f5565b60145580f35b906020608492519162461bcd60e51b8352820152602a60248201527f50617573696e672041756374696f6e7320776173207065726d616e656e746c796044820152692064697361626c65642160b01b6064820152fd5b5033835260196020528083205460ff16610586565b5090346103c15760203660031901126103c15760209160ff9082906001600160a01b0361068a612384565b1681526024855220541690519015158152f35b5091903461049757826003193601126104975782546001600160a01b031633148015610744575b6106cd906124ef565b60ff60115460201c16156106ec5782600160ff19601554161760155580f35b906020608492519162461bcd60e51b8352820152602c60248201527f41756374696f6e7320617265205061757365642120556e70617573652041756360448201526b74696f6e732066697273742160a01b6064820152fd5b5033835260196020528083205460ff166106c4565b5090346103c157816003193601126103c1576020906014549051908152f35b5082346103c15760203660031901126103c1576107959035613d02565b80f35b5090346103c157610795906107ac366123c6565b84549092916001600160a01b03918216331480156107e9575b6107ce906124ef565b168452602460205283209060ff801983541691151516179055565b5033865260196020528286205460ff166107c5565b5090346103c157816003193601126103c157602090610354612a57565b509134610497576020366003190112610497576020928291358152601d845220549051908152f35b5090346103c15760203660031901126103c1579081906001600160a01b03610869612384565b1681526022602052206001815491015482519182526020820152f35b5090346103c157806003193601126103c1576020906108af6108a5612384565b60243590336125c8565b5160018152f35b5090346103c157806003193601126103c1576108d0612384565b338352602160209081528284206001600160a01b039092165f81815292825291839020549093839160243581811061095b57505033815260218552818120835f52855280825f20555b3381526021855220815f528352815f205482519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b6109a49161099f855161096d816122e3565b601e81527f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008a820152828411156124ba565b6124e2565b33825260218652828220845f528652825f2055610919565b5090346103c157816003193601126103c15760015490516001600160a01b039091168152602090f35b5091346104975760203660031901126104975780359160018060a01b0384541633148015610ac1575b610a17906124ef565b600d54610a58610a5263ffffffff6011541692610a4b610a44600f5492610a3e84886128db565b906123f5565b4210612a0b565b42936128db565b856123f5565b1115610a66575050600d5580f35b906020608492519162461bcd60e51b8352820152602f60248201527f4e6577204c61756e636874696d65202b206f666644617973206d75737420626560448201526e20696e20746865206675747572652160881b6064820152fd5b5033845260196020528084205460ff16610a0e565b5090346103c157816003193601126103c157602090600c549051908152f35b5090346103c157816003193601126103c1578051610b2f91610b16826122e3565b6002825261135560f21b6020830152519182918261233d565b0390f35b5091346104975760203660031901126104975780359160018060a01b0384541633148015610bc2575b610b65906124ef565b611388831180610bb7575b15610b7d575050600a5580f35b906020606492519162461bcd60e51b835282015260146024820152736e6f7420612076616c696420736c69707061676560601b6044820152fd5b506127118310610b70565b5033845260196020528084205460ff16610b5c565b5090346103c157806003193601126103c157602090610354610bf7612384565b6024359061398f565b5090346103c157816003193601126103c1576020906018549051908152f35b5090346103c157816003193601126103c157602090600b549051908152f35b5090346103c157816003193601126103c157602090601e549051908152f35b5090346103c157816003193601126103c1576020906007549051908152f35b5090346103c157816003193601126103c15760095490516001600160a01b039091168152602090f35b5090346103c157816003193601126103c157602090600e549051908152f35b5090346103c15760203660031901126103c15760209160ff9082906001600160a01b03610cef612384565b1681526019855220541690519015158152f35b5090346103c15760203660031901126103c15760209181906001600160a01b03610d2a612384565b168152601b845220549051908152f35b50919082600319360112610497573415610e7d57610d5d601054600f54906125aa565b91610d66612a57565b90838211610e2b57610d7882856124e2565b60018101809111610e1857610d8d90346125aa565b928315610dbc5750505b82811115610da3578380f35b80610db183610db79361353f565b50613531565b610d97565b906020608492519162461bcd60e51b8352820152603060248201527f626174636841756374696f6e456e7472793a20696e73756666696369656e742060448201526f45544820666f7220616c6c206461797360801b6064820152fd5b634e487b7160e01b865260118252602486fd5b608490602084519162461bcd60e51b8352820152602660248201527f626174636841756374696f6e456e7472793a20696e76616c69642063757272656044820152656e742064617960d01b6064820152fd5b906020606492519162461bcd60e51b8352820152601f60248201527f626174636841756374696f6e456e7472793a206e6f204554482073656e7421006044820152fd5b5090346103c157816003193601126103c1576020906008549051908152f35b5090346103c157816003193601126103c15760209081549051908152f35b509182913461104f57602036600319011261104f5760095460065482516323b872dd60e01b815233818601526001600160a01b0391821660248201528435604482018190529492602090829060649082908a9087165af1801561101357611021575b5080600654169360011c93803b1561101d578580916044865180948193630b39c79b60e21b83526001898401528a60248401525af1801561101357908691610fff575b50506006541690813b15610ffb57604460019186809486519788958694636d80f47f60e11b865285015260248401525af1908115610ff25750610fe25750f35b610feb906122bb565b61035b5780f35b513d84823e3d90fd5b8480fd5b611008906122bb565b610ffb57845f610fa2565b84513d88823e3d90fd5b8580fd5b6110419060203d8111611048575b611039818361231b565b810190612592565b505f610f5f565b503d61102f565b5050fd5b508290602036600319011261035b57503415611080579061107860209234903561353f565b505160018152f35b6020606492519162461bcd60e51b8352820152602060248201527f627579536861726546726f6d41756374696f6e3a206e6f204554482073656e746044820152fd5b5090346103c157610795906110d6366123c6565b84549092916001600160a01b03916110f19083163314612547565b168452601960205283209060ff801983541691151516179055565b5090346103c157816003193601126103c15760209060ff6015541690519015158152f35b5091903461049757611141366123b0565b92909160018060a01b038554163314801561121d575b611160906124ef565b6103e98310156111ce576105dd84101561117f57505060075560085580f35b906020608492519162461bcd60e51b83528201526024808201527f53656c6c205461782056616c7565206e6f7420696e20616c6c6f7765642072616044820152636e67652160e01b6064820152fd5b906020608492519162461bcd60e51b83528201526024808201527f20427579205461782056616c7565206e6f7420696e20616c6c6f7765642072616044820152636e67652160e01b6064820152fd5b5033855260196020528085205460ff16611157565b5090346103c157816003193601126103c15760025490516001600160a01b039091168152602090f35b503461035b578060031936011261035b57610795612ef9565b5090346103c157806003193601126103c1579081906001600160a01b03611299612384565b168152602360205281812060243582526020522060ff6001825492015416825191825215156020820152f35b5090346103c157816003193601126103c157602090600f549051908152f35b503461035b57602036600319011261035b575061035460209235612d34565b509190346104975760203660031901126104975781359163ffffffff91828416809403610ffb5784546001600160a01b0316331480156113d1575b611347906124ef565b600d54926113786011549461136d610a44611367600f5480968a166128db565b836123f5565b610a3e4293886128db565b111561138e57505063ffffffff19161760115580f35b906020606492519162461bcd60e51b8352820152601d60248201527f4e756d62657220666f72206f66664461797320746f6f20736d616c6c210000006044820152fd5b5033855260196020528085205460ff1661133e565b503461035b57602036600319011261035b575061035460209235613760565b5090346103c157806003193601126103c15761141f612384565b33835281602093602185528181209260018060a01b031692835f52855261144b602435835f2054612416565b33825260218652828220845f528652825f20553381526021855220815f528352815f205482519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b5090346103c157816003193601126103c1576020905160128152f35b50919034610497576114cd366123b0565b92909160018060a01b03918286541633148015611b1a575b6114ee906124ef565b60036114f8612a57565b10611acd5784611506612a57565b1115611a72578486526020906025825260ff8388205416611a1c57858752601d825282872054605581029080820460551490151715611a09576064900493806009541695858731106119c657845161155d816122ff565b600281528536868301378284541691865163ef8ef56f60e01b815286818781875afa908c82156119bb579161271093916115ba939161198e575b50866115a286612ae7565b911690528a6115b085612b08565b52600a54906128db565b0483600654169187519387856024816370a0823160e01b9e8f8252888c8301525afa948515611984578d95611955575b50606442019283421161194257908d94939291813b1561101d578b896116339688968e519889978896879563b6f9de9560e01b8752860152608060248601526084850190612b18565b916044840152606483015203925af1801561193857611920575b505081600954169084836006541698602488518095819382528c898301525afa8015611916578a906118e3575b61168492506124e2565b9586156118945790889392918760011c90803b1561101d578580916044895180948193630b39c79b60e21b835260018a8401528760248401525af1801561188a57908691611876575b5050816006541690813b1561101d5785916044839289519485938492636d80f47f60e11b845260018a85015260248401525af180156118415790859161185e575b5088905260258352848420600160ff19825416179055838080808460015416601d885261173e8b8b8420546124e2565b90828215611855575bf11561184b576005541691845163528c890d60e11b815281818481875afa918215611841578592611824575b50506117d7575b5050507f1c047191e91ffa3e968d6304deca41a64944ccb1ae9116b3f331197d920e5a70936117d1916117ab612a57565b600e55519384934292859094939260609260808301968352602083015260408201520152565b0390a180f35b813b15610497578351630f8562c360e21b81529183918391829084905af1801561181a57611806575b8061177a565b61180f906122bb565b610ffb57845f611800565b83513d84823e3d90fd5b61183a9250803d1061104857611039818361231b565b5f80611773565b86513d87823e3d90fd5b84513d85823e3d90fd5b506108fc611747565b611867906122bb565b61187257835f61170e565b8380fd5b61187f906122bb565b610ffb57845f6116cd565b87513d88823e3d90fd5b845162461bcd60e51b81528084018590526024808201527f4e6f20746f6b656e732072656365697665642066726f6d206275796261636b206044820152630737761760e41b6064820152608490fd5b508482813d831161190f575b6118f9818361231b565b8101031261190b57611684915161167a565b5f80fd5b503d6118ef565b86513d8c823e3d90fd5b611929906122bb565b61193457885f61164d565b8880fd5b87513d84823e3d90fd5b634e487b7160e01b8e526011885260248efd5b9094508781813d831161197d575b61196d818361231b565b8101031261190b5751935f6115ea565b503d611963565b89513d8f823e3d90fd5b6119ae9150893d8b116119b4575b6119a6818361231b565b810190612ac8565b5f611597565b503d61199c565b8951903d90823e3d90fd5b845162461bcd60e51b8152808401859052601860248201527f496e73756666696369656e74204554482062616c616e636500000000000000006044820152606490fd5b634e487b7160e01b885260118252602488fd5b915162461bcd60e51b815291820152602c60248201527f6275796261636b20616e64206275696c6420616c726561647920646f6e65206660448201526b6f722074686973206461792160a01b6064820152608490fd5b6020608492519162461bcd60e51b8352820152603060248201527f7468652064617920796f752077616e7420746f206275796261636b20666f722060448201526f6973206e6f742066696e69736865642160801b6064820152fd5b6020608492519162461bcd60e51b8352820152602260248201527f696e76616c69642074696d6520666f72206275796261636b20616e64206275726044820152616e2160f01b6064820152fd5b5033865260196020528186205460ff166114e5565b5090346103c15760603660031901126103c1576108af602092611b50612384565b611b5861239a565b90604435928560018060a01b0380600954163303611b79575b5050506125c8565b83169182815260218952818120335f528952611b9886835f2054612470565b9281526021895220335f528752855f2055868581611b71565b5090346103c157816003193601126103c15760065490516001600160a01b039091168152602090f35b5090346103c157816003193601126103c1576020906012549051908152f35b5090346103c157816003193601126103c157602090600a549051908152f35b5090346103c157816003193601126103c157602090601a549051908152f35b509134610497576020366003190112610497578160209360ff923581526025855220541690519015158152f35b5091903461049757806003193601126104975760a09281906001600160a01b03611c8c612384565b168152601c6020528181206024358252602052208054926001820154926002830154916003840154930154938151958652602086015284015260608301526080820152f35b5090346103c157816003193601126103c15760055490516001600160a01b039091168152602090f35b5090346103c1576020928360031936011261049757803580611d1a612a57565b11156120bf5760019384821161204e575b33815260238652838120828252865283812054928315611ff25733825260238752848220838352875260ff86868420015416611f9a57611d69612a57565b611d78601054600f54906125aa565b9060028201809211611f8757918793918793101580611f15575b611eb6575b50670de0b6b3a7640000611db386611dae87613760565b6129b2565b5f80516020613ec78339815191528a8551611dcd816122e3565b601a815201520493338252601c8952828220818352895284848484200155338252601c895282822081835289524283832055338252601c895282822081835289524260038484200155611e2285600b546123f5565b600b5582518581526020810182905242604082015233907f830e279449af3d754a4667acaa6e90dedd7a8b466dd3f232bd2db88e6e77693a90606090a23382526023895282822090825288522001805460ff191685179055611e82612ef9565b8251918252848201527fe3e10b6a13fa59fdab56800bb8942e886fa0b6ffccb5a9e062d968c05becdd71823392a251908152f35b6006549193506001600160a01b039091169150813b156104975783602484928389519586948593637a0ae01f60e11b85528401525af18015611f0b57918591879315611d9757611f05906122bb565b5f611d97565b85513d84823e3d90fd5b5060065487516389a88c6f60e01b81528083018790529294509092508890829060249082906001600160a01b03165afa908115611f7d579183918793899591611f60575b5015611d92565b611f7791508a3d8c1161104857611039818361231b565b5f611f59565b86513d85823e3d90fd5b634e487b7160e01b845260118352602484fd5b845162461bcd60e51b8152908101879052602c60248201527f557365722068617320616c7265616479204368616e676564206869732053686160448201526b3932b9903a37902a37b5b2b760a11b6064820152608490fd5b845162461bcd60e51b8152908101879052603060248201527f5573657220686173206e65766572206465706f73697465642045544820746f2060448201526f746869732061756374696f6e4461792160801b6064820152608490fd5b8181526025865260ff8482205416611d2b57835162461bcd60e51b8152808401879052603360248201527f4275794261636b20616e64206275696c6420666f7220746869732064617920776044820152726173206e6f7420646f6e6520736f206661722160681b6064820152608490fd5b508360a492519162461bcd60e51b8352820152604960248201527f546f6b656e206f6620746869732061756374696f6e2064617920617265206e6f60448201527f7420726561647920746f206265206163636f756e74656420746f2075736572736064820152682076657374696e672160b81b6084820152fd5b5090346103c157816003193601126103c1576020906010549051908152f35b5090346103c157806003193601126103c15760209181612176612384565b91602435918291338152602187528181209460018060a01b0316948582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b5090346103c157816003193601126103c15760209063ffffffff601154169051908152f35b509134610497576020366003190112610497576020928291358152601f845220549051908152f35b5090346103c157816003193601126103c1578051610b2f91612237826122e3565b600a8252694d6f6e6965735472656560b01b6020830152519182918261233d565b5090346103c157816003193601126103c157602090600d549051908152f35b5090346103c157816003193601126103c157905490516001600160a01b039091168152602090f35b9050346103c157816003193601126103c1576020906017548152f35b67ffffffffffffffff81116122cf57604052565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176122cf57604052565b6060810190811067ffffffffffffffff8211176122cf57604052565b90601f8019910116810190811067ffffffffffffffff8211176122cf57604052565b602080825282518183018190529093925f5b82811061237057505060409293505f838284010152601f8019910116010190565b81810186015184820160400152850161234f565b600435906001600160a01b038216820361190b57565b602435906001600160a01b038216820361190b57565b604090600319011261190b576004359060243590565b604090600319011261190b576004356001600160a01b038116810361190b5790602435801515810361190b5790565b9190820180921161240257565b634e487b7160e01b5f52601160045260245ffd5b9061242190826123f5565b90811061242b5790565b60405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606490fd5b906124b79161099f604051612484816122e3565b601e81527f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006020820152828411156124ba565b90565b156124c25750565b60405162461bcd60e51b81529081906124de906004830161233d565b0390fd5b9190820391821161240257565b156124f657565b60405162461bcd60e51b8152602060048201526024808201527f4f776e61626c653a2063616c6c6572206973206e6f742066726f6d20746865206044820152637465616d60e01b6064820152608490fd5b1561254e57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f74207468652061646d696e6044820152fd5b9081602091031261190b5751801515810361190b5790565b81156125b4570490565b634e487b7160e01b5f52601260045260245ffd5b6003546001600160a01b039283169391831692908116838114925f929091849081156128d1575b50806128a7575b1561280a575f80516020613ec783398151915293156127ff5761261c6007545b836129b2565b9260409686612710895196612630886122e3565b601a88526020988980990152049461267e8a5161264c816122e3565b601e81527f536166654d6174683a207375627472616374696f6e206f766572666c6f77000089820152828811156124ba565b6126d761268b87836124e2565b91838652601b89528b86205461099f8d516126a5816122e3565b601f81527f7472616e7366657220616d6f756e7420657863656564732062616c616e6365008c820152828411156124ba565b828552601b88528a8520558284528984206126f38282546123f5565b905589519081527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef978891a381600654168152601b84528681206127388482546123f5565b90558160065416908360011c91803b156103c15781809160448b5180948193630b39c79b60e21b8352600160048401528860248401525af180156127f5576127e6575b5090826006541690813b15610497578291604483928b519485938492636d80f47f60e11b84526001600485015260248401525af180156127dc576127c8575b5050600654169451908152a3565b6127d282916122bb565b61035b57806127ba565b88513d84823e3d90fd5b6127ef906122bb565b5f61277b565b89513d84823e3d90fd5b61261c600854612616565b507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92506040828560209452601b8452612882838383205461099f8551612850816122e3565b601f81527f7472616e7366657220616d6f756e7420657863656564732062616c616e63650089820152828411156124ba565b868252601b8552828220558681522061289c8282546123f5565b9055604051908152a3565b50848352602460205260ff6040842054161580156125f6575085835260ff604084205416156125f6565b905086145f6125ef565b8181029291811591840414171561240257565b801561296b57670de0b6b3a76400008082029180830482036124025761291490836125aa565b0361291c5790565b60405162461bcd60e51b815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6044820152607760f81b6064820152608490fd5b505f90565b801561296b57600381029080820460030361240257612914600391836125aa565b801561296b57606f810290808204606f0361240257612914606f91836125aa565b9081156129cd576129146129c682846128db565b92836125aa565b50505f90565b906124b791612a066040516129e7816122e3565b601a81525f80516020613ec783398151915260208201528315156124ba565b6125aa565b15612a1257565b60405162461bcd60e51b815260206004820152601e60248201527f41756374696f6e73206861766520616c726561647920737461727465642100006044820152606490fd5b600d5463ffffffff60115416600f5490612a7a612a7483836128db565b846123f5565b92612a8860145480956123f5565b421015612a9757505050505f90565b612aba93612aaf612ab492610a3e86612a06966128db565b6123f5565b426124e2565b600101806001116124025790565b9081602091031261190b57516001600160a01b038116810361190b5790565b805115612af45760200190565b634e487b7160e01b5f52603260045260245ffd5b805160011015612af45760400190565b9081518082526020808093019301915f5b828110612b37575050505090565b83516001600160a01b031685529381019392810192600101612b29565b905f9182526020601d815260409081842054605581029080820460551490151715612d2057606490048015612d1b57825190612b8f826122ff565b6002825283368484013760048054855163ef8ef56f60e01b81526001600160a01b0391821693928690829081875afa908115612d11579189959391869593612c1c9a9b91612cf4575b5081612be386612ae7565b9116905260095416612bf484612b08565b52865180988194829363d06ca61f60e01b845260048401528960248401526044830190612b18565b03915afa928315612cea578193612c3f575b505050612c3b9150612b08565b5190565b909192503d8083863e612c52818661231b565b840191838584031261035b57845167ffffffffffffffff9586821161049757019083601f8301121561035b578151958611612cd6578560051b925195612c9a8685018861231b565b8652848087019383010193841161035b57508301905b828210612cc75750505050612c3b905f8080612c2e565b81518152908301908301612cb0565b634e487b7160e01b81526041600452602490fd5b51903d90823e3d90fd5b612d0b9150883d8a116119b4576119a6818361231b565b5f612bd8565b87513d8b823e3d90fd5b505050565b634e487b7160e01b85526011600452602485fd5b612d43601054600f54906125aa565b811115612ef257600654604080516318bad88b60e11b8152600481018490526001600160a01b03909216929091602091908281602481885afa908115612e7157908392915f91612ed5575b50612e7b57612d9d9150612b54565b825163a515a5bd60e01b81529060011c8282600481885afa918215612e71575f92612e40575b5091612dd281926004946123f5565b948451938480926333b5f0b560e01b82525afa928315612e3757505f92612e06575b5050612e02906064926128db565b0490565b81819392933d8311612e30575b612e1d818361231b565b8101031261035b57505181612e02612df4565b503d612e13565b513d5f823e3d90fd5b90918382813d8311612e6a575b612e57818361231b565b8101031261035b57505190612dd2612dc3565b503d612e4d565b84513d5f823e3d90fd5b60248451809681936377238c7760e01b835260048301525afa918215612e3757505f91612ea9575b50905090565b82813d8311612ece575b612ebd818361231b565b8101031261035b575051805f612ea3565b503d612eb3565b612eec9150833d851161104857611039818361231b565b5f612d8e565b5060175490565b6002612f03612a57565b14806134be575b613104575b612f17612a57565b60105490612f295f92600f54906125aa565b906002820180921161308057101580613094575b61301b575b600e54612f4d612a57565b1180612fc2575b612f67575b50612f62612a57565b600e55565b6005546001600160a01b0316803b156103c157818091600460405180948193630f8562c360e21b83525af18015612fb757612fa3575b50612f59565b612fad82916122bb565b61035b5780612f9d565b6040513d84823e3d90fd5b5060055460405163528c890d60e11b815290602090829060049082906001600160a01b03165afa908115612fb7578291612ffd575b50612f54565b613015915060203d811161104857611039818361231b565b5f612ff7565b6006546001600160a01b031661302f612a57565b5f19810190811161308057813b15610497578291602483926040519485938492637a0ae01f60e11b845260048401525af18015612fb757613071575b50612f42565b61307a906122bb565b5f61306b565b634e487b7160e01b83526011600452602483fd5b506006546001600160a01b03166130a9612a57565b5f198101908111613080576020906024604051809481936389a88c6f60e01b835260048301525afa908115612fb75782916130e6575b5015612f3d565b6130fe915060203d811161104857611039818361231b565b5f6130df565b6017546102fd90818102918183041490151715612402576009546001600160a01b0392916103e890049061313b90829085166134ca565b5f9260018452602093601d85526040948582205460558102908082046055149015171561308057606490049280600954168481311061346657838383600254169260448b518094819363095ea7b360e01b8352600497888401525f1960248401525af1801561342c57613449575b50818154169082600954166064420192834211613436579060c489896060948e51978895869463f305d71960e01b8652818a87015260248601528c60448601528c6064860152608485015260a48401525af191821561342c5785926133f7575b508054895163c45a015560e01b815290841685828481845afa9182156133ce57839291879189936133d8575b508c5163ef8ef56f60e01b815293849182905afa9182156133ce5760448c9387899481948c936133af575b5081600954169651968795869463e6a4390560e01b865216898501526024840152165afa9081156133a5578592878681946044948391613388575b5016806bffffffffffffffffffffffff60a01b60035416176003558d51968795869463a9059cbb60e01b865285015260248401525af1801561337e578493601d859485948594613361575b50600154169160018452526132fe878b8420546124e2565b90828215613358575bf11561334d575092519081526020810192909252426040830152907fa9632746d1a957634e707ce9a2abb47f8431306c20c70876bf17212eddd388f090606090a1612f0f565b8451903d90823e3d90fd5b506108fc613307565b61337790843d861161104857611039818361231b565b505f6132e6565b88513d86823e3d90fd5b61339f9150873d89116119b4576119a6818361231b565b5f61329b565b8a513d88823e3d90fd5b6133c7919350863d88116119b4576119a6818361231b565b915f613260565b8b513d89823e3d90fd5b6133f0919350823d84116119b4576119a6818361231b565b915f613235565b9091506060813d8211613424575b816134126060938361231b565b81010312610ffb57880151905f613209565b3d9150613405565b89513d87823e3d90fd5b634e487b7160e01b875260118352602487fd5b61345f90843d861161104857611039818361231b565b505f6131a9565b875162461bcd60e51b815260048101849052602b60248201527f6164644669727374446179734c69713a206e6f7420656e6f756768204554482060448201526a1a5b8818dbdb9d1c9858dd60aa1b6064820152608490fd5b506001600e5414612f0a565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60205f9260018060a01b031693848452601b825261350d816040862054612416565b858552601b8352604085205561352581601a54612416565b601a55604051908152a3565b5f1981146124025760010190565b9060115460209060ff81831c161561371b5761356e61357791610a3e600d549163ffffffff600f5491166128db565b601454906123f5565b42106136d757613585612a57565b831061368257907ec639b627799a5a1755e1d6b1557ddc43a507ee06867a140a2e082ca142cd0f915f90848252601d815260409182918282206135c98682546123f5565b90556135d785601e546123f5565b601e55338252602381528282208783528152828220541561365b575b3382526022815260018383200161360b8682546123f5565b9055338252602381528282209087835252206136288382546123f5565b9055613632612ef9565b600e549051918252602082019390935260408101929092524260608301523391608090a2600190565b6136658154613531565b8155868252601f815282822061367b8154613531565b90556135f3565b6084906040519062461bcd60e51b82526004820152602860248201527f627579536861726546726f6d41756374696f6e3a20696e76616c69642061756360448201526774696f6e2064617960c01b6064820152fd5b6064906040519062461bcd60e51b82526004820152601e60248201527f41756374696f6e732068617665206e6f742073746172746564207965742100006044820152fd5b60405162461bcd60e51b815260048101839052601e60248201527f41756374696f6e73206172652063757272656e746c79207061757365642100006044820152606490fd5b5f908082526020601d8152604090818420549283155f14613782575050505090565b6137966010959293949554600f54906125aa565b81116137b457505050506124b7906137af6017546128ee565b6129d3565b60065484516389a88c6f60e01b8152600481018390526001600160a01b0390911691908481602481865afa908115613985578491613968575b506138ed5750835163a515a5bd60e01b81528381600481855afa9081156138e357849084926138b5575b5085516333b5f0b560e01b81529192829060049082905afa9283156138aa578093613876575b505060649261385f6124b79695935f80516020613ec7833981519152936129b2565b925161386a816122e3565b601a81520152046129d3565b909192508382813d83116138a3575b61388f818361231b565b8101031261035b575051908261385f61383d565b503d613885565b8551903d90823e3d90fd5b809250813d83116138dc575b6138cb818361231b565b810103126104975751836004613817565b503d6138c1565b85513d85823e3d90fd5b928091936024865180968193621614f960e81b835260048301525afa93841561395d57508193613928575b505050906137af6124b7926128ee565b9091809350813d8311613956575b613940818361231b565b8101031261035b5750516137af6124b75f613918565b503d613936565b51913d9150823e3d90fd5b61397f9150853d871161104857611039818361231b565b5f6137ed565b86513d86823e3d90fd5b60018060a01b0316905f828152601c60209181835260409384822081835284528482205415613b28579083929186825282845285822081835284526139ee6139e96139e060038986200154426124e2565b601654906129b2565b612970565b926139fe601054600f54906125aa565b8211613b0d5787835280855286832082845285526064613a2360018986200154612991565b5f80516020613ec7833981519152878a51613a3d816122e3565b601a8152015204975b8084528186528784208385528652613a648560018a872001546129b2565b988851613a70816122e3565b601a81525f80516020613ec78339815191529889910152818552828752888520848652875280613ab260048b8820015468056bc75e2d63100000809d04612416565b11613aea575083528452858220908252835284902060010154613ad591906129b2565b9251613ae0816122e3565b601a815201520490565b979592936124b79950600497508095505281528383209183525220015490612470565b87835280855286832082845285526001878420015497613a46565b50935050505090565b60018060a01b03165f91818352601c9260209184835260409283832082845281528383205415613cf9578483528581528383208284528152613b7f6139e96139e060038787200154426124e2565b95613b8f601054600f54906125aa565b8311613cdd578584528082528484208385528252816064613bb560018888200154612991565b5f80516020613ec7833981519152838951613bcf816122e3565b601a8152015204975b8786528282528686208587528252613bf660018888200154826129b2565b908751613c02816122e3565b601a81525f80516020613ec78339815191529384910152888752838552878720868852855289613c4460048a8a20015468056bc75e2d63100000809504612416565b11613cbc576124b7995091613ca791613c7888979695948b60029b9a52858752898920888a52875260018a8a2001546129b2565b91858951613c85816122e3565b601a815201528987528385528787208688528552600488882001549104612416565b96845281528383209183525220015490612470565b5050509483529384528282209082529092529020600201546124b791612470565b8584528082528484208385528252816001868620015497613bd8565b50509250505090565b905f91338352601c9060208281526040918286208187528252613d3560048488200154613d2f833361398f565b90612416565b338752848352838720828852835260048488200155338652838252828620818752825242600384882001553386528382528286208187528252613d936004848820015433885285845284882083895284526002858920015490612470565b93338752808352838720828852835260048488200154903388528352838720828852835260028488200155613dcd601054600f54906125aa565b1015613e925760065485906001600160a01b0316803b156103c15781906044855180948193630138792d60e51b83523360048401528960248401525af18015613e88579583917f93b2b5baeb90867d00d09e02023eed58ae019d05b1c254578512984cc85e5ba6959697613e79575b505b3381526022835220613e518582546123f5565b9055613e5f84600c546123f5565b600c55613e6a612ef9565b815193845242908401523392a2565b613e82906122bb565b5f613e3c565b83513d88823e3d90fd5b81839495613ec17f93b2b5baeb90867d00d09e02023eed58ae019d05b1c254578512984cc85e5ba695336134ca565b613e3e56fe536166654d6174683a206469766973696f6e206279207a65726f000000000000a26469706673582212200d28c028060f251b43ab1327e6b68c7f4c909f7702c53e6d56e61eda20f8332664736f6c63430008140033