Contract 0xddaecf4b02a3e45b96fc2d7339c997e072b0d034 19

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xe4f18f3fe737a8b430312ffb68341052bc61c9ad6d6fe46f79260400ebbb7ed7Claim Dividend1855456702024-02-29 3:21:5458 mins ago0xe72ce8ca4b344ab1fbc5a3f554ae8836ac84ab57 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00006758 0.1
0x16a134880bf9b5cd93581675b6acf0b5db601b91dfbb8e5553a534e0f6008155Deposit Vesting1855447642024-02-29 3:18:051 hr 2 mins ago0x8deb68528151896e1e1b82d994be2ec000d06717 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00010894 0.1
0x36747c9a824053f8124b16364855b8246c40649e2885a570f0fcad6896abeaf0Deposit Vesting1855415412024-02-29 3:04:291 hr 16 mins ago0xfaf09c4d3213fb8d0ee7f8cc6f11c6248a213993 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00011294 0.1
0x65ac8ebd46832b7d2e606e22998ab3a6b6d76a7ad678bcf85076dcc22a90300cWithdraw Vesting1855410282024-02-29 3:02:161 hr 18 mins ago0xfaf09c4d3213fb8d0ee7f8cc6f11c6248a213993 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00009459 0.1
0x4d667cd0a1d664eff2784f162d07ffba815d186554d5993c9e9b72a17005aca4Claim Vesting1855391232024-02-29 2:54:151 hr 26 mins ago0x20216577f78ee7d6d5b2b962c744a950efc77437 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.000087660.1
0x0dd9f9d28ec2a63646ccdf34ca8d09b57803e59369827e736f1f58b64f509fb7Deposit Vesting1855376972024-02-29 2:48:161 hr 32 mins ago0xe29be695f9716add4ee6d51c94c3aafd6e89eed4 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00009284 0.1
0x83c490ae08ef5a81566c4f48e4877d80a882bc9f18178ac12d0155a1b72e2e4fDeposit Vesting1855376182024-02-29 2:47:591 hr 32 mins ago0x99526eb2c443302042ea8a45688d0b7574a29dd3 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00008886 0.1
0xe3cb7350254acfab9871281e31b0ca8d01b2e6be7418bea74ed536884341694eDeposit Vesting1855307392024-02-29 2:18:532 hrs 1 min ago0x965594b1752ff9ce863806c39ef4598e7970421e IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00012073 0.1
0x7927e613df9bf83f35cb6ef8f107a36544dfe6e962548d8ae7db4f789f2f5f0eDeposit Vesting1855209042024-02-29 1:36:362 hrs 43 mins ago0xaf79312eb821871208ac76a80c8e282f8796964e IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.000144610.1
0x74dc44308bab518147db8c15e8e83c44a2acfdfa477e9eb6cca489d8e1ec3e6aUnstake1855207872024-02-29 1:36:052 hrs 44 mins ago0xaf79312eb821871208ac76a80c8e282f8796964e IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.000131810.1
0xaf990bf2d9856d24dc63f2c1e622a0bfcf7a034695eb05d52d0e30ff9136817fDeposit Dividend1855187452024-02-29 1:27:042 hrs 53 mins ago0xecc3eb1df1781c09564e17c515514edcf2bb1695 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00012807 0.1
0x99ed6785de506a04fde3dcc9a46e4a8976e9a5269e38bc08005985c8f0acb2fbDeposit Vesting1855184222024-02-29 1:25:422 hrs 54 mins ago0x22c3272a6a371a1e7e98a0669ae785c86a2dfa0c IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.0001390.1
0x44396276cf2f2d8b4a8bcbe5be9727c0ea92c55cb19cac1f77fccc27edcf9c97Unstake1855170492024-02-29 1:19:393 hrs ago0x22c3272a6a371a1e7e98a0669ae785c86a2dfa0c IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00011730.1
0xeb52e0d47ca4a4dda7992207f5dc18ff004cb0befd65f06754e6affec7682764Claim Dividend1855169042024-02-29 1:19:003 hrs 1 min ago0x22c3272a6a371a1e7e98a0669ae785c86a2dfa0c IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.000079790.1
0x5249e04738ca56fc7dd0953ce91a467d826441996770894068502232191bb6a1Claim Dividend1855030992024-02-29 0:20:593 hrs 59 mins ago0x6ba9d0c502127fa27964ecc61f9021f4e2066abd IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00006406 0.1
0xadd8bff45a4f790a54c5854dd9678a9d82704e9dc835c66b62b02eaae1086871Unstake1855030372024-02-29 0:20:443 hrs 59 mins ago0x6ba9d0c502127fa27964ecc61f9021f4e2066abd IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00011025 0.1
0x5573f550cb3817e0487ad5e0ac2638172ea2c0430ec803945fcf4c85de7c3acfDeposit Dividend1854892362024-02-28 23:21:094 hrs 59 mins ago0x17a29971dd4fc0afbd21d5d8c1aa359c67e99389 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.000086820.1
0x5c31d20eb96f7717605b08b4818732588644e561170269171bd833869988db86Deposit Dividend1854882642024-02-28 23:17:015 hrs 3 mins ago0xe1a49616b0b18ac9c647225262ea996b68f3b337 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00008202 0.1
0x9b34d9102b1db44e6a9c7c594b2b8d2f4222cc6ff43b7d89880ec6078fce8c87Withdraw Vesting1854852092024-02-28 23:04:065 hrs 16 mins ago0xd64724f4f02e4b5e838b3a7b3193d785a8d7c1f7 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00008868 0.1
0xc8f2efee5439ee34d8f874e7974d02365cd2aa9d5d8a913bb2ce1ae35fa9f3dbClaim Vesting1854851122024-02-28 23:03:425 hrs 16 mins ago0xd64724f4f02e4b5e838b3a7b3193d785a8d7c1f7 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00011756 0.1
0xd174cc3ee46ae16f1befc3b242322f4ad22981109ad813d1536a90570f7a8b90Withdraw Vesting1854768752024-02-28 22:27:395 hrs 52 mins ago0xa34369c8e3265dff5b1fe5a231061828058ccbee IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00009737 0.1
0x92039c1d4bb114e002aec506a1ef3778c314a25aa7b09d27b942fea098b0e3dfClaim Vesting1854716182024-02-28 22:05:066 hrs 15 mins ago0x38e76e6d3024475e2d39deb94b2797ce801381c0 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00011659 0.1
0x688b7016f027b46ff51333747b7e07e73a68e4e9c4aa505a2f2c220f1e6f0343Claim Dividend1854715182024-02-28 22:04:416 hrs 15 mins ago0x38e76e6d3024475e2d39deb94b2797ce801381c0 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00006937 0.1
0x35d0b04dbda51403738223530f766695df8115ac6bc8dc42e03934cfefdf01e1Claim Dividend1854658162024-02-28 21:39:416 hrs 40 mins ago0x0c830a9806af3ef3762b21e98ca6818e373cf985 IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.000075120.1
0x225b93721237ff05f4f36f81a98816d5513d2383b4ffbf6cedb9fe8b75a2dd6cClaim Dividend1854622402024-02-28 21:23:516 hrs 56 mins ago0x078b3f76e120a1f70491375fb33e289ecff9bd8a IN  0xddaecf4b02a3e45b96fc2d7339c997e072b0d0340 ETH0.00007142 0.1
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
WINRStaking

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 12 : WINRStaking.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "./WINRVesting.sol";

contract WINRStaking is WINRVesting {
	/*==================================================== State Variables ========================================================*/
	mapping(address => StakeDividend) public dividendWINRStakes;
	mapping(address => StakeDividend) public dividendVestedWINRStakes;

	/*==================================================== Constructor ===========================================================*/
	constructor(
		address _vaultRegistry,
		address _timelock
	) WINRVesting(_vaultRegistry, _timelock) {}

	/*===================================================== FUNCTIONS ============================================================*/
	/*=================================================== View Functions =========================================================*/

	/**
	 *
	 * @dev Retrieves the staked amount of dividend WINR tokens for a specified account and stake type.
	 * @param _account The address of the account to retrieve the staked amount for.
	 * @param _isVested A boolean flag indicating whether to retrieve the vested WINR or WINR dividend stake.
	 * @return _amount The staked amount of dividend WINR/vWINR tokens for the specified account and stake type.
	 * @dev The function retrieves the staked amount of dividend WINR/vWINR tokens for the specified account and stake type from the dividendWINRStakes or dividenVestedWINRdStakes mapping,
	 *      depending on the value of the isVested parameter.
	 */
	function dividendStakedAmount(
		address _account,
		bool _isVested
	) external view returns (uint256) {
		return
			_isVested
				? dividendVestedWINRStakes[_account].amount
				: dividendWINRStakes[_account].amount;
	}

	/**
	 *
	 * @dev Retrieves the dividend stake for a specified account and stake type.
	 * @param _account The address of the account to retrieve the dividend stake for.
	 * @param _isVested A boolean flag indicating whether to retrieve the vested or non-vested dividend stake.
	 * @return stake A Stake struct representing the dividend stake for the specified account and stake type.
	 * @dev The function retrieves the dividend stake for the specified account and stake type from the dividendWINRStakes or dividenVestedWINRdStakes mapping, depending on the value of the isVested parameter.
	 */
	function getDividendStake(
		address _account,
		bool _isVested
	) external view returns (StakeDividend memory) {
		return
			_isVested
				? dividendVestedWINRStakes[_account]
				: dividendWINRStakes[_account];
	}

	/**
	 *
	 * @param _account The address of the account to retrieve the pending rewards data.
	 */
	function pendingDividendRewards(address _account) external view returns (uint256 pending_) {
		// Calculate the pending reward based on the dividend vested WINR stake of the given account
		pending_ += _pendingByDividendStake(dividendVestedWINRStakes[_account]);
		// Calculate the pending reward based on the dividend WINR stake of the given account
		pending_ += _pendingByDividendStake(dividendWINRStakes[_account]);
	}

	/*================================================= External Functions =======================================================*/
	/**
	 *
	 * @dev Fallback function that handles incoming Ether transfers to the contract.
	 * @dev The function emits a Donation event with the sender's address and the amount of Ether transferred.
	 * @dev The function can receive Ether and can be called by anyone, but does not modify the state of the contract.
	 */
	fallback() external payable {
		emit Donation(msg.sender, msg.value);
	}

	/**
	 *
	 * @dev Receive function that handles incoming Ether transfers to the contract.
	 * @dev The function emits a Donation event with the sender's address and the amount of Ether transferred.
	 * @dev The function can receive Ether and can be called by anyone, but does not modify the state of the contract.
	 */
	receive() external payable {
		emit Donation(msg.sender, msg.value);
	}

	/**
	 *
	 * @dev Distributes a share of profits to all stakers based on their stake weight.
	 * @param _amount The amount of profits to distribute among stakers.
	 * @notice The function can only be called by an address with the PROTOCOL_ROLE.
	 * @notice The total weight of all staked tokens must be greater than zero for profits to be distributed.
	 * @dev If the total weight of all staked tokens is greater than zero,
	 *      the function adds the specified amount of profits to the total profit pool
	 *      and updates the accumulated profit per weight value accordingly.
	 * @dev The function emits a Share event to notify external systems about the distribution of profits.
	 */
	function share(uint256 _amount) external override isAmountNonZero(_amount) onlyProtocol {
		if (totalWeight > 0) {
			totalProfit += _amount;
			totalEarned += _amount;
			accumProfitPerWeight += (_amount * PRECISION) / totalWeight;

			emit Share(_amount, totalWeight, totalStakedVestedWINR, totalStakedWINR);
		}
	}

	/**
	 *
	 *  @dev Function to claim dividends for the caller.
	 *  @notice The function can only be called when the contract is not paused and is non-reentrant.
	 *  @notice The function calls the internal function '_claimDividend' passing the caller's address and 'isVested' boolean as parameters.
	 */
	function claimDividend() external whenNotPaused nonReentrant {
		_claimDividendBatch(msg.sender);
	}

	/**
	 * @notice Pauses the contract. Only the governance address can call this function.
	 * @dev While the contract is paused, some functions may be disabled to prevent unexpected behavior.
	 */
	function pause() public onlyTeam {
		_pause();
	}

	/**
	 * @notice Unpauses the contract. Only the governance address can call this function.
	 * @dev Once the contract is unpaused, all functions should be enabled again.
	 */
	function unpause() public onlyTeam {
		_unpause();
	}

	/**
	 * @notice Allows the governance to withdraw a certain amount of donations and transfer them to a specified address
	 * @param to The address to transfer the donations to
	 * @param amount The amount of donations to withdraw
	 */
	function withdrawDonations(address payable to, uint256 amount) external onlyGovernance {
		require(address(this).balance >= amount, "Insufficient balance");
		(bool sent, ) = to.call{value: amount}("");
		require(sent, "Withdraw failed");
	}

	/**
	 * @dev Updates the vesting period configuration.
	 * @param duration Total vesting duration in seconds.
	 * @param minDuration Minimum vesting duration in seconds.
	 * @param claimDuration Duration in seconds during which rewards can be claimed.
	 * @param minPercent Minimum percentage of the total stake that must be vested.
	 */
	function updatePeriod(
		uint256 duration,
		uint256 minDuration,
		uint256 claimDuration,
		uint256 minPercent
	) external onlyGovernance {
		require(
			duration >= minDuration,
			"Duration must be greater than or equal to minimum duration"
		);
		require(
			claimDuration <= duration,
			"Claim duration must be less than or equal to duration"
		);

		period.duration = duration;
		period.minDuration = minDuration;
		period.claimDuration = claimDuration;
		period.minPercent = minPercent;
	}

	/**
	 *
	 * @dev Internal function to deposit WINR/vWINR as dividends.
	 * @param _amount The amount of WINR/vWINR to be deposited.
	 * @param _isVested Boolean flag indicating if tokens are vWINR.
	 * @dev This function performs the following steps:
	 *     Get the address of the stake owner.
	 *     Determine the stake details based on the boolean flag isVested.
	 *     Take the tokens from the stake owner and update the stake amount.
	 *     If the stake amount is greater than 0, claim dividends for the stake owner.
	 *     Calculate the stake weight based on the updated stake amount and isVested flag.
	 *     Update the stake with the new stake amount, start time, weight and profit debt.
	 *     Emit a Deposit event with the details of the deposited tokens.
	 */
	function depositDividend(
		uint256 _amount,
		bool _isVested
	) external isAmountNonZero(_amount) nonReentrant whenNotPaused {
		// Get the address of the stake owner.
		address sender_ = msg.sender;
		// Determine the stake details based on the boolean flag isVested.
		StakeDividend storage stake_;

		if (_isVested) {
			tokenManager.takeVestedWINR(sender_, _amount);
			stake_ = dividendVestedWINRStakes[sender_];
			totalStakedVestedWINR += _amount;
		} else {
			tokenManager.takeWINR(sender_, _amount);
			stake_ = dividendWINRStakes[sender_];
			totalStakedWINR += _amount;
		}

		// If the stake amount is greater than 0, claim dividends for the stake owner.
		if (stake_.amount > 0) {
			_claimDividend(sender_, _isVested);
		}

		// Calculate the stake weight
		uint256 weight_ = _calculateWeight(stake_.amount + _amount, _isVested, false);
		// increase the total staked weight
		totalWeight += (weight_ - stake_.weight);
		// Update the stake with the new stake amount, start time, weight and profit debt.
		stake_.amount += _amount;
		stake_.depositTime = uint128(block.timestamp);
		stake_.weight = weight_;
		stake_.profitDebt = _calcDebt(weight_);

		// Emit a DepositDividend event with the details of the deposited tokens.
		emit DepositDividend(sender_, stake_.amount, stake_.profitDebt, _isVested);
	}

	/**
	 *
	 * @dev Internal function to unstake tokens.
	 * @param _amount The amount of tokens to be unstaked.
	 * @param _isVested Boolean flag indicating if stake is Vested WINR.
	 * @notice This function also claims rewards.
	 * @dev This function performs the following steps:
	 *    Check that the staker has sufficient stake amount.
	 *    Claim dividends for the staker.
	 *    Compute the weight of the unstaked tokens and update the total staked amount and weight.
	 *    Compute the debt for the stake after unstaking tokens.
	 *    Burn the necessary amount of tokens and send the remaining unstaked tokens to the staker.
	 *    Emit an Unstake event with the details of the unstaked tokens.
	 */
	function unstake(uint256 _amount, bool _isVested) external nonReentrant whenNotPaused {
		address sender_ = msg.sender;
		StakeDividend storage stake_ = _isVested
			? dividendVestedWINRStakes[sender_]
			: dividendWINRStakes[sender_];
		require(stake_.amount >= _amount, "Insufficient stake amount");
		ITokenManager tokenManager_ = tokenManager;

		// Compute the amount of tokens to be burned and sent to the staker.
		uint256 burnAmount_ = _computeBurnAmount(_amount);
		uint256 sendAmount_ = _amount - burnAmount_;
		// Compute the weight of the unstaked tokens and update the total staked amount and weight.
		uint256 unstakedWeight_;

		// Claim dividends for the staker.
		_claimDividend(sender_, _isVested);

		// Burn the necessary amount of tokens and send the remaining unstaked tokens to the staker.
		if (_isVested) {
			tokenManager_.burnVestedWINR(burnAmount_);
			tokenManager_.sendVestedWINR(sender_, sendAmount_);
			unstakedWeight_ = _amount * weightMultipliers.vWinr;
			totalStakedVestedWINR -= _amount;
		} else {
			tokenManager_.burnWINR(burnAmount_);
			tokenManager_.sendWINR(sender_, sendAmount_);
			unstakedWeight_ = _amount * weightMultipliers.winr;
			totalStakedWINR -= _amount;
		}

		totalWeight -= unstakedWeight_;

		// Update the stake details after unstaking tokens.
		stake_.amount -= _amount;
		stake_.weight -= unstakedWeight_;
		stake_.profitDebt = _calcDebt(stake_.weight);

		// Emit an Unstake event with the details of the unstaked tokens.
		emit Unstake(sender_, block.timestamp, sendAmount_, burnAmount_, _isVested);
	}

	/*================================================= Internal Functions =======================================================*/
	/**
	 *
	 * @dev Internal function to claim dividends for a stake.
	 * @param _account The address of the stake owner.
	 * @param _isVested Boolean flag indicating if stake is Vested WINR.
	 * @return reward_ The amount of dividends claimed.
	 * @dev This function performs the following steps:
	 *     Determine the stake details based on the boolean flag isVested.
	 *     Calculate the pending rewards for the stake.
	 *     Send the rewards to the stake owner.
	 *     Update the profit debt for the stake.
	 *     Update the total profit and total claimed for the stake owner.
	 *     Emit a Claim event with the details of the claimed rewards.
	 */
	function _claimDividend(
		address _account,
		bool _isVested
	) internal returns (uint256 reward_) {
		// Determine the stake details based on the boolean flag isVested.
		StakeDividend storage stake_ = _isVested
			? dividendVestedWINRStakes[_account]
			: dividendWINRStakes[_account];

		// Calculate the pending rewards for the stake.
		reward_ = _pendingByDividendStake(stake_);

		if (reward_ == 0) {
			return 0;
		}

		// Send the rewards to the stake owner.
		tokenManager.sendWLP(_account, reward_);

		// Update the profit debt for the stake.
		stake_.profitDebt = _calcDebt(stake_.weight);

		// Update the total profit and total claimed for the stake owner.
		// totalProfit -= _reward;
		totalClaimed[_account] += reward_;

		// Emit a Claim event with the details of the claimed rewards.
		emit ClaimDividend(_account, reward_, _isVested);
	}

	/**
	 *
	 * @dev Internal function to claim dividends for all stake.
	 * @param _account The address of the stake owner.
	 * @return reward_ The amount of dividends claimed.
	 */
	function _claimDividendBatch(address _account) internal returns (uint256 reward_) {
		// Determine the stake details based on the boolean flag isVested.
		StakeDividend storage stakeVWINR_ = dividendVestedWINRStakes[_account];
		StakeDividend storage stakeWINR_ = dividendWINRStakes[_account];

		// Calculate the pending rewards for the stake.
		reward_ = _pendingByDividendStake(stakeVWINR_);
		reward_ += _pendingByDividendStake(stakeWINR_);

		if (reward_ == 0) {
			return 0;
		}

		// Send the rewards to the stake owner.
		tokenManager.sendWLP(_account, reward_);

		// Update the profit debt for the stake.
		stakeVWINR_.profitDebt = _calcDebt(stakeVWINR_.weight);
		stakeWINR_.profitDebt = _calcDebt(stakeWINR_.weight);

		// Update the total profit and total claimed for the stake owner.
		totalClaimed[_account] += reward_;

		// Emit a Claim event with the details of the claimed rewards.
		emit ClaimDividendBatch(_account, reward_);
	}

	/**
	 * @notice Computes the pending WLP amount of the stake.
	 * @param _stake The stake for which to compute the pending amount.
	 * @return holderProfit_ The pending WLP amount.
	 */
	function _pendingByDividendStake(
		StakeDividend memory _stake
	) internal view returns (uint256 holderProfit_) {
		// Compute the holder's profit as the product of their stake's weight and the accumulated profit per weight.
		holderProfit_ = ((_stake.weight * accumProfitPerWeight) / PRECISION);
		// If the holder's profit is less than their profit debt, return zero.
		if (holderProfit_ < _stake.profitDebt) {
			return 0;
		} else {
			// Otherwise, subtract their profit debt from their total profit and return the result.
			holderProfit_ -= _stake.profitDebt;
		}
	}
}

File 2 of 12 : WINRVesting.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "solmate/src/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "../../core/AccessControlBase.sol";
import "../../interfaces/core/ITokenManager.sol";
import "../../interfaces/tokens/IWINR.sol";
import "../../interfaces/stakings/IWINRStaking.sol";

abstract contract WINRVesting is IWINRStaking, Pausable, ReentrancyGuard, AccessControlBase {
	/*====================================================== Modifiers ===========================================================*/
	/**
	 * @notice Throws if the amount is not greater than zero
	 */
	modifier isAmountNonZero(uint256 amount) {
		require(amount > 0, "amount must be greater than zero");
		_;
	}

	/*====================================================== State Variables =====================================================*/

	// 18 decimal precision
	uint256 internal constant PRECISION = 1e18;
	//The total profit earned by all staked tokens in the contract
	uint256 public totalProfit;
	//The total weight of all stakes in the contract
	uint256 public totalWeight;
	//The total amount of WINR tokens staked in the contract
	uint256 public totalStakedWINR;
	//The total amount of vWINR tokens staked in the contract
	uint256 public totalStakedVestedWINR;
	//The accumulated profit per weight of all stakes in the contract. It is used in the calculation of rewards earned by each stakeholder
	uint256 public accumProfitPerWeight;
	//The percentage of staked tokens that will be burned when a stake is withdrawn
	uint256 public unstakeBurnPercentage;
	//The total profit history earned by all staked tokens in the contract
	uint256 public totalEarned;
	//Interface of Token Manager contract
	ITokenManager public tokenManager;
	//This mapping stores an array of StakeVesting structures for each address that has staked tokens in the contract
	mapping(address => StakeVesting[]) public stakes;
	//This mapping stores an array of indexes into the stakes array for each address that has active vesting stakes in the contract
	mapping(address => uint256[]) public activeVestingIndexes;
	//This mapping stores the total amount of tokens claimed by each address that has staked tokens in the contract
	mapping(address => uint256) public totalClaimed;
	//Initializes default vesting period
	Period public period = Period(180 days, 15 days, 165, 5e17);
	//Initializes default reward multipliers
	WeightMultipliers public weightMultipliers = WeightMultipliers(1, 2, 1);

	/*==================================================== Constructor ===========================================================*/
	constructor(
		address _vaultRegistry,
		address _timelock
	) AccessControlBase(_vaultRegistry, _timelock) {
		unstakeBurnPercentage = 5e15; // 0.5% default
	}

	/*===================================================== FUNCTIONS ============================================================*/
	/*=================================================== View Functions =========================================================*/
	/**
	 *
	 * @dev Calculates the pending reward for a given staker.
	 * @param account The address of the staker for whom to calculate the pending reward.
	 * @return pending The amount of pending WLP tokens that the staker is eligible to receive.
	 * @dev The function iterates over all active stakes for the given staker and calculates the pending rewards for each stake using the _pendingWLPOfStake() internal function.
	 * @dev The function is view-only and does not modify the state of the contract.
	 */
	function pendingVestingRewards(address account) external view returns (uint256 pending) {
		uint256[] memory activeIndexes = getActiveIndexes(account);

		for (uint256 i = 0; i < activeIndexes.length; i++) {
			StakeVesting memory stake = stakes[account][activeIndexes[i]];
			pending += _pendingWLPOfStake(stake);
		}
	}

	/**
	 *
	 * @dev Calculates the pending reward for a given staker with given index.
	 * @param account The address of the staker for whom to calculate the pending reward.
	 * @return pending The amount of pending WLP tokens that the staker is eligible to receive.
	 * @dev The function calculates the pending rewards for the stake using the _pendingWLPOfStake() internal function.
	 * @dev The function is view-only and does not modify the state of the contract.
	 */
	function pendingVestingByIndex(
		address account,
		uint256 index
	) external view returns (uint256 pending) {
		// Get the stake from the stakes mapping
		StakeVesting memory stake = stakes[account][index];
		if(stake.withdrawn || stake.cancelled) return 0;
		// Calculate the pending reward for the stake
		pending = _pendingWLPOfStake(stake);
	}

	/**
	 *
	 * @param _account Address of staker
	 * @param _index index to calculate the withdrawable amount
	 * @return _withdrawable  withdrawable amount of WINR/vWINR
	 */
	function withdrawableTokens(
		address _account,
		uint256 _index
	) external view returns (uint256 _withdrawable) {
		// Get the stake from the stakes mapping
		StakeVesting memory _stake = stakes[_account][_index];
		// Calculate the withdrawable amount for the stake
		_withdrawable = _withdrawableByVesting(_stake);

		// Check if the vesting period has passed
		if (_stake.startTime + _stake.vestingDuration > block.timestamp) {
			_withdrawable = 0;
		}
	}

	/**
	 * @notice This function returns an array of indexes representing the active vesting stakes indexes for a given staker.
	 * @param staker The address of the staker
	 */
	function getActiveIndexes(address staker) public view returns (uint[] memory indexes) {
		indexes = activeVestingIndexes[staker];
	}

	/**
	 *
	 * @param _account Address of the staker
	 * @param _indexes Indexes of the vesting stakes to calculate the total staked amount
	 * @return _totalStaked The total amount of staked tokens across the specified vesting stakes
	 */
	function vestingStakedAmount(
		address _account,
		uint256[] calldata _indexes
	) external view returns (uint256 _totalStaked) {
		for (uint256 i = 0; i < _indexes.length; i++) {
			StakeVesting memory _stake = stakes[_account][_indexes[i]];
			_totalStaked += _stake.amount;
		}
	}

	/**
	 * @return _totalStakedVWINR The total amount of vWINR tokens staked in the contract
	 * @return _totalStakedWINR The total amount of WINR tokens staked in the contract
	 * @return _totalEarned The total profit earned
	 */
	function globalData()
		external
		view
		returns (uint256 _totalStakedVWINR, uint256 _totalStakedWINR, uint256 _totalEarned)
	{
		_totalStakedVWINR = totalStakedVestedWINR;
		_totalStakedWINR = totalStakedWINR;
		_totalEarned = totalEarned;
	}

	/**
	 *
	 * @param _account Address of staker
	 * @param _index Index of stake
	 * @return _stake Data of the stake
	 */
	function getVestingStake(
		address _account,
		uint256 _index
	) public view returns (StakeVesting memory _stake) {
		_stake = stakes[_account][_index];
	}

	/**
	 *
	 * @param _account Address of staker
	 * @return _length total stake count of the _account
	 */
	function getVestingStakeLength(address _account) external view returns (uint256 _length) {
		_length = stakes[_account].length;
	}

	function _calcDebt(uint256 _weight) internal view returns (uint256 debt) {
		debt = (_weight * accumProfitPerWeight) / PRECISION;
	}

	/**
	 *
	 * @dev Computes the weight of a specified amount of tokens based on its type and vesting status.
	 * @param amount The amount of tokens to compute the weight for.
	 * @param vested A boolean flag indicating whether the tokens are vested or not.
	 * @param vesting A boolean flag indicating whether the tokens are vesting or not, applicable only if the tokens are vested.
	 * @return The weight of the specified amount of tokens.
	 * @dev The function computes the weight of the specified amount of tokens based on its type and vesting status, using the weightMultipliers mapping.
	 * @dev The function does not modify the state of the contract and can only be called internally.
	 */
	function _calculateWeight(
		uint256 amount,
		bool vested,
		bool vesting
	) internal view returns (uint256) {
		return
			!vested ? amount * weightMultipliers.winr : vesting
				? amount * weightMultipliers.vWinrVesting
				: amount * weightMultipliers.vWinr;
	}

	/**
	 * @notice Computes the pending WLP amount of the stake.
	 * @param stake The stake for which to compute the pending amount.
	 * @return holderProfit The pending WLP amount.
	 */
	function _pendingWLPOfStake(StakeVesting memory stake) internal view returns (uint256) {
	// Compute the holder's profit as the product of their stake's weight and the accumulated profit per weight.
		uint256 holderProfit = ((stake.weight * accumProfitPerWeight) / PRECISION);
		// If the holder's profit is less than their profit debt, return zero.
		return holderProfit < stake.profitDebt ? 0 : holderProfit - stake.profitDebt;
	}

	/**
	 * @notice Calculates the amount of WINR/vWINR that should be burned upon unstaking.
	 * @param amount The amount of WINR/vWINR being unstaked.
	 * @return _burnAmount The amount of WINR/vWINR to be burned.
	 */
	function _computeBurnAmount(uint256 amount) internal view returns (uint256 _burnAmount) {
		// Calculate the burn amount as the product of the unstake burn percentage and the amount being unstaked.
		_burnAmount = (amount * unstakeBurnPercentage) / PRECISION;
	}

	/**
	 * @notice Computes the withdrawable amount of WINR for the stake.
	 * @param stake The stake for which to compute the withdrawable amount.
	 * @return withdrawable_ The withdrawable amount of WINR.
	 */
	function _withdrawableByVesting(
		StakeVesting memory stake
	) internal view returns (uint256 withdrawable_) {
		// Compute the total amount of time that the stake has been staked, in days.
		uint256 totalStakedDuration_ = (block.timestamp - stake.startTime) / 1 days;
		// Compute the minimum number of days required for staking in order to be eligible for a reward.
		uint256 _minDays = period.minDuration / 1 days;

		// If the stake duration is less than the minimum number of days, the holder cannot withdraw any tokens.
		if (totalStakedDuration_ < _minDays) {
			return 0;
		}

		// Otherwise, calculate the holder's profit as follows:
		if (block.timestamp > stake.startTime + stake.vestingDuration) {
			// If the vesting period has expired, then the holder can withdraw their full stake amount.
			totalStakedDuration_ = stake.vestingDuration / 1 days;
		}

		// Calculate the profit for the holder as the sum of the tokens earned on the first day and the additional tokens earned over time.
		withdrawable_ =
			stake.accTokenFirstDay +
			((stake.amount - stake.accTokenFirstDay) *
				(totalStakedDuration_ - _minDays)) /
			period.claimDuration;
	}

	/*================================================= External Functions =======================================================*/

	/**
	 * @dev This function cancels vesting stakes without penalty and reward.
	 * It sends the staked amount to the staker.
	 * @param _index index to cancel vesting for
	 * @notice Throws an error if the stake has already been withdrawn
	 * @notice Emits a Cancel event upon successful execution
	 */
	function cancel(uint256 _index) external {
		// Get the address of the caller
		address sender_ = msg.sender;
		// Declare local variables for stake and bool values
		StakeVesting memory stake;
		

		// Retrieve the stake and bool values for the given index and staker
		(stake) = getVestingStake(sender_, _index);

		// Check if the stake has already been withdrawn
		require(!stake.withdrawn, "stake has withdrawn");
		// Check if the stake has already been cancelled
		require(!stake.cancelled, "stake has cancelled");

		// Remove the index from the staker's active stakes list
		_removeActiveIndex(sender_, _index);

		uint256 amount_ = stake.amount;


		// Calculate the amount of tokens to burn and the amount of tokens to send to the staker
		uint256 burnAmount_ = _computeBurnAmount(amount_);
		uint256 sendAmount_ = amount_ - burnAmount_;
		totalStakedVestedWINR -= amount_;
		totalWeight -= stake.weight;
		// claim rewards
		uint256 reward_ = _pendingWLPOfStake(stake);

		// share rewards with the pool
		if(reward_ > 0) {
			// Update the accumulated profit per weight
			accumProfitPerWeight += (reward_ * PRECISION) / totalWeight;
			// Update the holder's profit debt
			stakes[sender_][_index].profitDebt += reward_;
		}
		// Mark the stake as cancelled in the mapping
		stakes[sender_][_index].cancelled = true;
		stakes[sender_][_index].amount = 0;

		// Send the staked tokens to the staker
		tokenManager.sendVestedWINR(sender_, sendAmount_);

		// Burn the remaining vesting tokens
		tokenManager.burnVestedWINR(burnAmount_);

		// Emit a Cancel event to notify listeners of the cancellation
		emit Cancel(sender_, block.timestamp, _index, burnAmount_, sendAmount_);
	}


	/**
	 * @dev Set the percentage of tokens to burn upon unstaking. Only callable by the governance address.
	 * @param _unstakeBurnPercentage The percentage of tokens to burn upon unstaking
	 * @notice Emits an UnstakeBurnPercentageUpdate event upon successful execution
	 */
	function setUnstakeBurnPercentage(uint256 _unstakeBurnPercentage) external onlyGovernance {
		// Set the unstake burn percentage to the provided value
		unstakeBurnPercentage = _unstakeBurnPercentage;

		// Emit an event to notify listeners of the update
		emit UnstakeBurnPercentageUpdate(_unstakeBurnPercentage);
	}

	/**
	 * @dev Set the address of the token manager contract. Only callable by the governance address.
	 * @param _tokenManager The address of the token manager contract
	 */
	function setTokenManager(ITokenManager _tokenManager) external onlyGovernance {
		require(
			address(_tokenManager) != address(0),
			"token manager address can not be zero"
		);
		// Set the token manager to the provided address
		tokenManager = _tokenManager;
	}

	/**
	 * @dev Deposit vWINR tokens into the contract and create a vesting stake with the specified parameters
	 * @param amount The amount of vWINR tokens to deposit
	 * @param vestingDuration The duration of the vesting period in seconds
	 */
	function depositVesting(
		uint256 amount,
		uint256 vestingDuration
	) external isAmountNonZero(amount) nonReentrant whenNotPaused {
		uint256 vestingDurationInSeconds = vestingDuration * 1 days;
		require(
			vestingDurationInSeconds >= period.minDuration &&
				vestingDuration <= period.duration,
			"duration must be in period"
		);
		// Get the address of the caller
		address sender = msg.sender;
		uint256 weight = _calculateWeight(amount, true, true);
		// Calculate the profit debt for the stake based on its weight
		uint256 profitDebt = _calcDebt(weight);
		// Get the current timestamp as the start time for the stake
		uint256 startTime = block.timestamp;
		// Calculate the accumulated token value for the first day of the claim period
		uint256 accTokenFirstDay = (amount * period.minPercent) / PRECISION;
		// Calculate the daily accumulation rate for the claim period
		uint256 accTokenPerDay = (amount - accTokenFirstDay) / period.claimDuration;

		// Transfer the vWINR tokens from the sender to the token manager contract
		tokenManager.takeVestedWINR(sender, amount);

		totalWeight += weight;
		totalStakedVestedWINR += amount;

		// Create a new stake with the specified parameters and add it to the list of stakes for the sender
		stakes[sender].push(
			StakeVesting(
				amount,
				weight,
				vestingDurationInSeconds,
				profitDebt,
				startTime,
				accTokenFirstDay,
				accTokenPerDay,
				false,
				false
			)
		);

		// Get the index of the newly added stake and add it to the list of active stakes for the sender
		uint256 _index = stakes[msg.sender].length - 1;
		_addActiveIndex(msg.sender, _index);

		// Emit a Deposit event to notify listeners of the new stake
		emit DepositVesting(
			sender,
			_index,
			startTime,
			vestingDurationInSeconds,
			amount,
			profitDebt,
			true,
			true
		);
	}

	/**
	 *
	 *  @dev Function to claim rewards for a specified array of indexes.
	 *  @param indexes The array of indexes to claim rewards for.
	 *  @notice The function can only be called when the contract is not paused and is non-reentrant.
	 *  @notice The function throws an error if the array of indexes is empty.
	 */
	function claimVesting(uint256[] calldata indexes) external whenNotPaused nonReentrant {
		require(indexes.length > 0, "empty indexes");
		_claim(indexes, true);
	}

	/**
	 * @dev Withdraws staked tokens and claims rewards
	 * @param _index Index to withdraw
	 */
	function withdrawVesting(uint256 _index) external whenNotPaused nonReentrant {
		address sender_ = msg.sender;
		// Initialize an array of size 4 to store the amounts
		StakeVesting storage stake_ = stakes[sender_][_index];

		// Check that the withdrawal period for this stake has passed
		require(
			block.timestamp >= stake_.startTime + stake_.vestingDuration,
			"You can't withdraw the stake yet"
		);
		// Check that this stake has not already been withdrawn
		require(!stake_.withdrawn, "already withdrawn");
		// Check that this stake has not been cancelled
		require(!stake_.cancelled, "stake cancelled");

		// Redeemable WINR amount by stake
		uint256 redeemable_ = _withdrawableByVesting(stake_);
		// Redeemable WLP amount by stake
		uint256 reward_ = _pendingWLPOfStake(stake_);
		
		// Interact with external contracts to complete the withdrawal process
		if (redeemable_ > 0) {
			// Mint reward tokens if necessary
			tokenManager.mintOrTransferByPool(sender_, redeemable_);
		}

		uint256 amountToBurn = stake_.amount - redeemable_;

		// Mint WINR tokens to decrease MAX_SUPPLY
		if (amountToBurn > 0) {
			// this code piece is used to decrease burn amount from WINR total supply
			tokenManager.mintWINR(address(tokenManager), amountToBurn);
			tokenManager.burnWINR(amountToBurn);
		}

		// Burn vested WINR tokens
		tokenManager.burnVestedWINR(stake_.amount);

		// Interactions
		if (reward_ > 0) {
			tokenManager.sendWLP(sender_, reward_);

			stakes[sender_][_index].profitDebt += reward_;
			totalProfit -= reward_;
			totalClaimed[sender_] += reward_;

			emit ClaimVesting(sender_, reward_, _index);
		}

		// Calculate the total amounts to be withdrawn
		// Mark this stake as withdrawn and remove its index from the active list
		stake_.withdrawn = true;
		_removeActiveIndex(sender_, _index);

		// Update the total weight and total staked amount
		totalWeight -= stake_.weight;
		totalStakedVestedWINR -= stake_.amount;

		// Emit an event to log the withdrawal
		emit Withdraw(
			sender_,
			block.timestamp,
			_index,
			stake_.weight,
			stake_.weight,
			stake_.amount
		);
	}

	/**
	 * @dev Withdraws staked tokens and claims rewards
	 * @param indexes Indexes to withdraw
	 */
	function withdrawVestingBatch(
		uint256[] calldata indexes
	) external whenNotPaused nonReentrant {
		address sender = msg.sender;
		// Initialize an array of size 4 to store the amounts
		uint256[4] memory _amounts;

		// Check effects for each stake to be withdrawn
		for (uint256 i = 0; i < indexes.length; i++) {
			// Get the stake and boolean values for this index
			uint256 index = indexes[i];
			StakeVesting storage stake = stakes[sender][index];

			// Check that the withdrawal period for this stake has passed
			require(
				block.timestamp >= stake.startTime + stake.vestingDuration,
				"You can't withdraw the stake yet"
			);

			// Check that this stake has not already been withdrawn
			require(!stake.withdrawn, "already withdrawn");

			// Check that this stake has not been cancelled
			require(!stake.cancelled, "stake cancelled");

			// Calculate the total amounts to be withdrawn
			_amounts[0] += stake.weight;
			_amounts[1] += _withdrawableByVesting(stake);
			_amounts[2] += _pendingWLPOfStake(stake);
			_amounts[3] += stake.amount;

			// Mark this stake as withdrawn and remove its index from the active list
			stake.withdrawn = true;
			_removeActiveIndex(sender, index);
		}

		// Interact with external contracts to complete the withdrawal process
		if (_amounts[1] > 0) {
			// Mint rewards tokens if necessary
			tokenManager.mintOrTransferByPool(sender, _amounts[1]);
		}

		// the calculation is amountToBurn = total withdraw weight - total withdraw amount;
		uint256 amountToBurn = _amounts[3] - _amounts[1];

		// Mint WINR tokens to decrease total supply
		if (amountToBurn > 0) {
			// this code piece is used to decrease burn amount from WINR total supply
			// Mint WINR tokens to the tokenManager contract
			tokenManager.mintWINR(address(tokenManager), amountToBurn);
			tokenManager.burnWINR(amountToBurn);
		}

		// Burn total vested WINR tokens
		tokenManager.burnVestedWINR(_amounts[3]);

		// Update the total weight and total staked amount
		totalWeight -= _amounts[0];
		totalStakedVestedWINR -= _amounts[3];

		// Claim rewards for remaining stakes
		_claim(indexes, false);

		// Emit an event to log the withdrawal
		emit WithdrawBatch(
			sender,
			block.timestamp,
			indexes,
			_amounts[1],
			_amounts[1],
			_amounts[3]
		);
	}

	/*================================================= Internal Functions =======================================================*/
	/**
	 * @dev Claims the reward for the specified stakes
	 * @param indexes Array of the indexes to claim
	 * @param isClaim Checks if the caller is the claim function
	 */
	function _claim(uint256[] memory indexes, bool isClaim) internal {
		address sender_ = msg.sender;
		uint256 totalFee_;

		// Check
		for (uint256 i = 0; i < indexes.length; i++) {
			uint256 index_ = indexes[i];

			StakeVesting storage stake_ = stakes[sender_][index_];

			// Check that the stake has not been withdrawn
			if (isClaim) {
				require(!stake_.withdrawn, "Stake has already been withdrawn");
			}

			// Check that the stake has not been cancelled
			require(!stake_.cancelled, "Stake has been cancelled");

			 uint256 fee_ = _pendingWLPOfStake(stake_);
			 stake_.profitDebt += fee_;
			totalFee_ += fee_;
			 
		}
		// Effects


		totalProfit -= totalFee_;
		totalClaimed[sender_] += totalFee_;
		// Interactions
		if (totalFee_ > 0) {
			
			tokenManager.sendWLP(sender_, totalFee_);
		}

		// Emit event
		emit ClaimVestingBatch(sender_, totalFee_, indexes);
	}

	/**
	 *
	 *  @dev Internal function to remove an active vesting index for a staker.
	 *  @param staker The address of the staker.
	 *  @param index The index of the vesting schedule to remove.
	 */
	function _removeActiveIndex(address staker, uint index) internal {
		uint[] storage indexes = activeVestingIndexes[staker];

    	uint length = indexes.length;

    	// Find the index to remove
    	for (uint i = 0; i < length; i++) {
        	if (indexes[i] == index) {
            	// Swap with the last element
            	indexes[i] = indexes[length - 1];
            
            	// Remove the last element
            	indexes.pop();
            	return;
        	}
    	}
	}

	function _addActiveIndex(address staker, uint256 index) internal {
		uint[] storage indexes;

		indexes = activeVestingIndexes[staker];
		indexes.push(index);
	}

	function share(uint256 amount) external virtual override {}
}

File 3 of 12 : ReentrancyGuard.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Gas optimized reentrancy protection for smart contracts.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
    uint256 private locked = 1;

    modifier nonReentrant() virtual {
        require(locked == 1, "REENTRANCY");

        locked = 2;

        _;

        locked = 1;
    }
}

File 4 of 12 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 5 of 12 : AccessControlBase.sol
// SPDX-License-Identifier: MIT

import "@openzeppelin/contracts/utils/Context.sol";
import "../interfaces/core/IVaultAccessControlRegistry.sol";

pragma solidity 0.8.19;

contract AccessControlBase is Context {
	IVaultAccessControlRegistry public immutable registry;
	address public immutable timelockAddressImmutable;

	constructor(address _vaultRegistry, address _timelock) {
		registry = IVaultAccessControlRegistry(_vaultRegistry);
		timelockAddressImmutable = _timelock;
	}

	/*==================== Managed in VaultAccessControlRegistry *====================*/

	modifier onlyGovernance() {
		require(registry.isCallerGovernance(_msgSender()), "Forbidden: Only Governance");
		_;
	}

	modifier onlyEmergency() {
		require(registry.isCallerEmergency(_msgSender()), "Forbidden: Only Emergency");
		_;
	}

	modifier onlySupport() {
		require(registry.isCallerSupport(_msgSender()), "Forbidden: Only Support");
		_;
	}

	modifier onlyTeam() {
		require(registry.isCallerTeam(_msgSender()), "Forbidden: Only Team");
		_;
	}

	modifier onlyProtocol() {
		require(registry.isCallerProtocol(_msgSender()), "Forbidden: Only Protocol");
		_;
	}

	modifier protocolNotPaused() {
		require(!registry.isProtocolPaused(), "Forbidden: Protocol Paused");
		_;
	}

	/*==================== Managed in WINRTimelock *====================*/

	modifier onlyTimelockGovernance() {
		address timelockActive_;
		if (!registry.timelockActivated()) {
			// the flip is not switched yet, so this means that the governance address can still pass the onlyTimelockGoverance modifier
			timelockActive_ = registry.governanceAddress();
		} else {
			// the flip is switched, the immutable timelock is now locked in as the only adddress that can pass this modifier (and nothing can undo that)
			timelockActive_ = timelockAddressImmutable;
		}
		require(_msgSender() == timelockActive_, "Forbidden: Only TimelockGovernance");
		_;
	}
}

File 6 of 12 : ITokenManager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface ITokenManager {
	function takeVestedWINR(address _from, uint256 _amount) external;

	function takeWINR(address _from, uint256 _amount) external;

	function sendVestedWINR(address _to, uint256 _amount) external;

	function sendWINR(address _to, uint256 _amount) external;

	function burnVestedWINR(uint256 _amount) external;

	function burnWINR(uint256 _amount) external;

	function mintWINR(address _to, uint256 _amount) external;

	function sendWLP(address _to, uint256 _amount) external;

	function mintOrTransferByPool(address _to, uint256 _amount) external;

	function mintVestedWINR(address _input, uint256 _amount, address _recipient) external returns(uint256 _mintAmount);

	function mintedByGames() external returns (uint256);

	function MAX_MINT() external returns (uint256);

	function share(uint256 amount) external;
}

File 7 of 12 : IWINR.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IWINR is IERC20 {
	function mint(address account, uint256 amount) external returns (uint256, uint256);

	function burn(uint256 amount) external;

	function MAX_SUPPLY() external view returns (uint256);
}

File 8 of 12 : IWINRStaking.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface IWINRStaking {
	function share(uint256 amount) external;

	function totalWeight() external view returns (uint256);

	struct StakeDividend {
		uint256 amount;
		uint256 profitDebt;
		uint256 weight;
		uint128 depositTime;
	}

	struct StakeVesting {
		uint256 amount; // The amount of tokens being staked
		uint256 weight; // The weight of the stake, used for calculating rewards
		uint256 vestingDuration; // The duration of the vesting period in seconds
		uint256 profitDebt; // The amount of profit earned by the stake, used for calculating rewards
		uint256 startTime; // The timestamp at which the stake was created
		uint256 accTokenFirstDay; // The accumulated  WINR tokens earned on the first day of the stake
		uint256 accTokenPerDay; // The rate at which WINR tokens are accumulated per day
		bool withdrawn; // Indicates whether the stake has been withdrawn or not
		bool cancelled; // Indicates whether the stake has been cancelled or not
	}

	struct Period {
		uint256 duration;
		uint256 minDuration;
		uint256 claimDuration;
		uint256 minPercent;
	}

	struct WeightMultipliers {
		uint256 winr;
		uint256 vWinr;
		uint256 vWinrVesting;
	}

	/*==================================================== Events =============================================================*/

	event Donation(address indexed player, uint amount);
	event Share(uint256 amount, uint256 totalWeight, uint256 totalStakedVWINR, uint256 totalStakedWINR);
	event DepositVesting(
		address indexed user,
		uint256 index,
		uint256 startTime,
		uint256 endTime,
		uint256 amount,
		uint256 profitDebt,
		bool isVested,
		bool isVesting
	);

	event DepositDividend(
		address indexed user,
		uint256 amount,
		uint256 profitDebt,
		bool isVested
	);
	event Withdraw(
		address indexed user,
		uint256 withdrawTime,
		uint256 index,
		uint256 amount,
		uint256 redeem,
		uint256 vestedBurn
	);
	event WithdrawBatch(
		address indexed user,
		uint256 withdrawTime,
		uint256[] indexes,
		uint256 amount,
		uint256 redeem,
		uint256 vestedBurn
	);

	event Unstake(
		address indexed user,
		uint256 unstakeTime,
		uint256 amount,
		uint256 burnedAmount,
		bool isVested
	);
	event Cancel(
		address indexed user,
		uint256 cancelTime,
		uint256 index,
		uint256 burnedAmount,
		uint256 sentAmount
	);
	event ClaimVesting(address indexed user, uint256 reward, uint256 index);
	event ClaimVestingBatch(address indexed user, uint256 reward, uint256[] indexes);
	event ClaimDividend(address indexed user, uint256 reward, bool isVested);
	event ClaimDividendBatch(address indexed user, uint256 reward);
	event WeightMultipliersUpdate(WeightMultipliers _weightMultipliers);
	event UnstakeBurnPercentageUpdate(uint256 _unstakeBurnPercentage);
}

File 9 of 12 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 10 of 12 : IVaultAccessControlRegistry.sol
// SPDX-License-Identifier: MIT

import "@openzeppelin/contracts/access/IAccessControl.sol";

pragma solidity >=0.6.0 <0.9.0;

interface IVaultAccessControlRegistry is IAccessControl {
	function timelockActivated() external view returns (bool);

	function governanceAddress() external view returns (address);

	function pauseProtocol() external;

	function unpauseProtocol() external;

	function isCallerGovernance(address _account) external view returns (bool);

	function isCallerEmergency(address _account) external view returns (bool);

	function isCallerProtocol(address _account) external view returns (bool);

	function isCallerTeam(address _account) external view returns (bool);

	function isCallerSupport(address _account) external view returns (bool);

	function isProtocolPaused() external view returns (bool);

	function changeGovernanceAddress(address _governanceAddress) external;

	/*==================== Events *====================*/

	event DeadmanSwitchFlipped();
	event GovernanceChange(address newGovernanceAddress);
}

File 11 of 12 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 12 of 12 : IAccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

Settings
{
  "remappings": [
    "@ensdomains/=node_modules/@ensdomains/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@uniswap/=node_modules/@uniswap/",
    "base64-sol/=node_modules/base64-sol/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "eth-gas-reporter/=node_modules/eth-gas-reporter/",
    "forge-std/=lib/forge-std/src/",
    "hardhat/=node_modules/hardhat/",
    "solmate/=node_modules/solmate/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_vaultRegistry","type":"address"},{"internalType":"address","name":"_timelock","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"cancelTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burnedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sentAmount","type":"uint256"}],"name":"Cancel","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isVested","type":"bool"}],"name":"ClaimDividend","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"ClaimDividendBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"ClaimVesting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"indexes","type":"uint256[]"}],"name":"ClaimVestingBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"profitDebt","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isVested","type":"bool"}],"name":"DepositDividend","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"profitDebt","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isVested","type":"bool"},{"indexed":false,"internalType":"bool","name":"isVesting","type":"bool"}],"name":"DepositVesting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Donation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalWeight","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalStakedVWINR","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalStakedWINR","type":"uint256"}],"name":"Share","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"unstakeTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burnedAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isVested","type":"bool"}],"name":"Unstake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_unstakeBurnPercentage","type":"uint256"}],"name":"UnstakeBurnPercentageUpdate","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"winr","type":"uint256"},{"internalType":"uint256","name":"vWinr","type":"uint256"},{"internalType":"uint256","name":"vWinrVesting","type":"uint256"}],"indexed":false,"internalType":"struct IWINRStaking.WeightMultipliers","name":"_weightMultipliers","type":"tuple"}],"name":"WeightMultipliersUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"withdrawTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redeem","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vestedBurn","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"withdrawTime","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"indexes","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redeem","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vestedBurn","type":"uint256"}],"name":"WithdrawBatch","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"accumProfitPerWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"activeVestingIndexes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimDividend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"indexes","type":"uint256[]"}],"name":"claimVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_isVested","type":"bool"}],"name":"depositDividend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"vestingDuration","type":"uint256"}],"name":"depositVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_isVested","type":"bool"}],"name":"dividendStakedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"dividendVestedWINRStakes","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"profitDebt","type":"uint256"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint128","name":"depositTime","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"dividendWINRStakes","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"profitDebt","type":"uint256"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint128","name":"depositTime","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"getActiveIndexes","outputs":[{"internalType":"uint256[]","name":"indexes","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_isVested","type":"bool"}],"name":"getDividendStake","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"profitDebt","type":"uint256"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint128","name":"depositTime","type":"uint128"}],"internalType":"struct IWINRStaking.StakeDividend","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getVestingStake","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint256","name":"vestingDuration","type":"uint256"},{"internalType":"uint256","name":"profitDebt","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"accTokenFirstDay","type":"uint256"},{"internalType":"uint256","name":"accTokenPerDay","type":"uint256"},{"internalType":"bool","name":"withdrawn","type":"bool"},{"internalType":"bool","name":"cancelled","type":"bool"}],"internalType":"struct IWINRStaking.StakeVesting","name":"_stake","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getVestingStakeLength","outputs":[{"internalType":"uint256","name":"_length","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalData","outputs":[{"internalType":"uint256","name":"_totalStakedVWINR","type":"uint256"},{"internalType":"uint256","name":"_totalStakedWINR","type":"uint256"},{"internalType":"uint256","name":"_totalEarned","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"pendingDividendRewards","outputs":[{"internalType":"uint256","name":"pending_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"pendingVestingByIndex","outputs":[{"internalType":"uint256","name":"pending","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"pendingVestingRewards","outputs":[{"internalType":"uint256","name":"pending","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"minDuration","type":"uint256"},{"internalType":"uint256","name":"claimDuration","type":"uint256"},{"internalType":"uint256","name":"minPercent","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IVaultAccessControlRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ITokenManager","name":"_tokenManager","type":"address"}],"name":"setTokenManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_unstakeBurnPercentage","type":"uint256"}],"name":"setUnstakeBurnPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"share","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakes","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint256","name":"vestingDuration","type":"uint256"},{"internalType":"uint256","name":"profitDebt","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"accTokenFirstDay","type":"uint256"},{"internalType":"uint256","name":"accTokenPerDay","type":"uint256"},{"internalType":"bool","name":"withdrawn","type":"bool"},{"internalType":"bool","name":"cancelled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timelockAddressImmutable","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenManager","outputs":[{"internalType":"contract ITokenManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalEarned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalProfit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakedVestedWINR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakedWINR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_isVested","type":"bool"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unstakeBurnPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"minDuration","type":"uint256"},{"internalType":"uint256","name":"claimDuration","type":"uint256"},{"internalType":"uint256","name":"minPercent","type":"uint256"}],"name":"updatePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256[]","name":"_indexes","type":"uint256[]"}],"name":"vestingStakedAmount","outputs":[{"internalType":"uint256","name":"_totalStaked","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weightMultipliers","outputs":[{"internalType":"uint256","name":"winr","type":"uint256"},{"internalType":"uint256","name":"vWinr","type":"uint256"},{"internalType":"uint256","name":"vWinrVesting","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawDonations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"withdrawVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"indexes","type":"uint256[]"}],"name":"withdrawVestingBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"withdrawableTokens","outputs":[{"internalType":"uint256","name":"_withdrawable","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

600180805562ed4e0060c08190526213c68060e081905260a56101008190526706f05b59d3b20000610120819052600d93909355600e91909155600f556010556101a0604052610140819052600261016081905261018082905260118290556012556013553480156200007157600080fd5b5060405162004464380380620044648339810160408190526200009491620000de565b6000805460ff191690556001600160a01b039182166080521660a0526611c37937e0800060075562000116565b80516001600160a01b0381168114620000d957600080fd5b919050565b60008060408385031215620000f257600080fd5b620000fd83620000c1565b91506200010d60208401620000c1565b90509250929050565b60805160a0516142f76200016d600039600061086201526000818161063201528181610e5201528181610ffe015281816112af01528181611d4b015281816120d8015281816122120152612e2301526142f76000f3fe60806040526004361061026b5760003560e01c80637cb2b79c11610144578063b9e8346d116100b6578063ef5d9ae81161007a578063ef5d9ae81461091a578063ef78d4fd14610947578063f0fc6bca1461098a578063f520c87f1461099f578063f79d032d146109b5578063fe9b050e146109cb576102a8565b8063b9e8346d14610850578063c3d9c4b414610884578063dba41cbf146108a4578063e4aff9c4146108c4578063e982a482146108fa576102a8565b806396c82e571161010857806396c82e571461076f5780639def0543146107855780639ebea88c146107a5578063a9c26186146107c5578063ae03119314610810578063b1945e5a14610830576102a8565b80637cb2b79c146106e55780638456cb5914610705578063860015191461071a578063947a56cd14610730578063961072021461074f576102a8565b8063581b593e116101dd578063613ce410116101a1578063613ce410146105a25780636230b83d146105d45780636cc0bd24146105ea5780636dfa8d991461060a5780637b103999146106205780637be25ba214610654576102a8565b8063581b593e14610463578063584b62a1146104d75780635ab08f001461053f5780635c975abb1461055f57806360d3bdfe14610582576102a8565b80632a709b141161022f5780632a709b14146103965780632ef73e88146103ce578063374756f5146103ee5780633f4ba83a1461040e57806340e58ee5146104235780634178ec2814610443576102a8565b80630210290f146102da5780631df0af3f1461031057806324d17fa11461033257806327f00c251461035257806329f0db2214610376576102a8565b366102a85760405134815233907f5d8bc849764969eb1bcc6d0a2f55999d0167c1ccec240a4f39cf664ca9c4148e906020015b60405180910390a2005b60405134815233907f5d8bc849764969eb1bcc6d0a2f55999d0167c1ccec240a4f39cf664ca9c4148e9060200161029e565b3480156102e657600080fd5b506102fa6102f5366004613e82565b610a27565b6040516103079190613eda565b60405180910390f35b34801561031c57600080fd5b5061033061032b366004613eed565b610a93565b005b34801561033e57600080fd5b5061033061034d366004613f0f565b610e48565b34801561035e57600080fd5b5061036860055481565b604051908152602001610307565b34801561038257600080fd5b50610330610391366004613f41565b610ff4565b3480156103a257600080fd5b506009546103b6906001600160a01b031681565b6040516001600160a01b039091168152602001610307565b3480156103da57600080fd5b506103686103e9366004613e82565b6110e3565b3480156103fa57600080fd5b50610330610409366004613fa6565b6111f2565b34801561041a57600080fd5b506103306112a5565b34801561042f57600080fd5b5061033061043e366004613f41565b61138a565b34801561044f57600080fd5b5061033061045e366004613f41565b6116d7565b34801561046f57600080fd5b506104ae61047e366004613e82565b6014602052600090815260409020805460018201546002830154600390930154919290916001600160801b031684565b604080519485526020850193909352918301526001600160801b03166060820152608001610307565b3480156104e357600080fd5b506104f76104f2366004613fe8565b611cd3565b60408051998a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c0840152151560e0830152151561010082015261012001610307565b34801561054b57600080fd5b5061033061055a366004613fe8565b611d41565b34801561056b57600080fd5b5060005460ff166040519015158152602001610307565b34801561058e57600080fd5b5061036861059d366004614022565b611ed6565b3480156105ae57600080fd5b506005546004546008545b60408051938452602084019290925290820152606001610307565b3480156105e057600080fd5b5061036860075481565b3480156105f657600080fd5b5061036861060536600461405b565b611f1e565b34801561061657600080fd5b5061036860085481565b34801561062c57600080fd5b506103b67f000000000000000000000000000000000000000000000000000000000000000081565b34801561066057600080fd5b5061067461066f366004613fe8565b612016565b6040516103079190600061012082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e0830151151560e0830152610100808401511515818401525092915050565b3480156106f157600080fd5b50610330610700366004613e82565b6120ce565b34801561071157600080fd5b50610330612208565b34801561072657600080fd5b5061036860025481565b34801561073c57600080fd5b506011546012546013546105b992919083565b34801561075b57600080fd5b5061036861076a366004613e82565b6122eb565b34801561077b57600080fd5b5061036860035481565b34801561079157600080fd5b506103686107a0366004613fe8565b6123b9565b3480156107b157600080fd5b506103306107c03660046140b0565b6123ea565b3480156107d157600080fd5b506104ae6107e0366004613e82565b6015602052600090815260409020805460018201546002830154600390930154919290916001600160801b031684565b34801561081c57600080fd5b5061033061082b366004613fa6565b612770565b34801561083c57600080fd5b5061036861084b366004613fe8565b612d18565b34801561085c57600080fd5b506103b67f000000000000000000000000000000000000000000000000000000000000000081565b34801561089057600080fd5b5061033061089f366004613f41565b612df8565b3480156108b057600080fd5b506103686108bf366004613fe8565b612fbf565b3480156108d057600080fd5b506103686108df366004613e82565b6001600160a01b03166000908152600a602052604090205490565b34801561090657600080fd5b506103306109153660046140b0565b6130a2565b34801561092657600080fd5b50610368610935366004613e82565b600c6020526000908152604090205481565b34801561095357600080fd5b50600d54600e54600f5460105461096a9392919084565b604080519485526020850193909352918301526060820152608001610307565b34801561099657600080fd5b5061033061332e565b3480156109ab57600080fd5b5061036860065481565b3480156109c157600080fd5b5061036860045481565b3480156109d757600080fd5b506109eb6109e6366004614022565b61336d565b60405161030791908151815260208083015190820152604080830151908201526060918201516001600160801b03169181019190915260800190565b6001600160a01b0381166000908152600b6020908152604091829020805483518184028101840190945280845260609392830182828015610a8757602002820191906000526020600020905b815481526020019060010190808311610a73575b50505050509050919050565b8160008111610abd5760405162461bcd60e51b8152600401610ab4906140d5565b60405180910390fd5b600154600114610adf5760405162461bcd60e51b8152600401610ab49061410a565b6002600155610aec61341b565b6000610afb8362015180614144565b600e549091508110801590610b125750600d548311155b610b5e5760405162461bcd60e51b815260206004820152601a60248201527f6475726174696f6e206d75737420626520696e20706572696f640000000000006044820152606401610ab4565b336000610b6d86600180613461565b90506000610b7a8261349a565b6010549091504290600090670de0b6b3a764000090610b99908b614144565b610ba3919061415b565b600f54909150600090610bb6838c61417d565b610bc0919061415b565b60095460405163079b9d7760e21b81529192506001600160a01b031690631e6e75dc90610bf39089908e90600401614190565b600060405180830381600087803b158015610c0d57600080fd5b505af1158015610c21573d6000803e3d6000fd5b505050508460036000828254610c3791906141a9565b925050819055508960056000828254610c5091906141a9565b92505081905550600a6000876001600160a01b03166001600160a01b031681526020019081526020016000206040518061012001604052808c8152602001878152602001898152602001868152602001858152602001848152602001838152602001600015158152602001600015158152509080600181540180825580915050600190039060005260206000209060080201600090919091909150600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e08201518160070160006101000a81548160ff0219169083151502179055506101008201518160070160016101000a81548160ff021916908315150217905550505060006001600a6000336001600160a01b03166001600160a01b0316815260200190815260200160002080549050610dab919061417d565b336000908152600b602090815260408220805460018101825590835291200181905590506040805182815260208101869052908101899052606081018c905260808101869052600160a0820181905260c08201526001600160a01b038816907feb7bdad6029ad027c77906ce1960c5ac2111bf37b5a7bb7b63068aa4f25256179060e00160405180910390a2505060018055505050505050505050565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016637d075595336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ebc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee091906141bc565b610efc5760405162461bcd60e51b8152600401610ab4906141d9565b82841015610f725760405162461bcd60e51b815260206004820152603a60248201527f4475726174696f6e206d7573742062652067726561746572207468616e206f7260448201527f20657175616c20746f206d696e696d756d206475726174696f6e0000000000006064820152608401610ab4565b83821115610fe05760405162461bcd60e51b815260206004820152603560248201527f436c61696d206475726174696f6e206d757374206265206c657373207468616e6044820152741037b91032b8bab0b6103a3790323ab930ba34b7b760591b6064820152608401610ab4565b600d93909355600e91909155600f55601055565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016637d075595336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611068573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108c91906141bc565b6110a85760405162461bcd60e51b8152600401610ab4906141d9565b60078190556040518181527fc6723167dfc6a0204d07a4d7c81104295b948a8fac5769b1576c202032cf8ef39060200160405180910390a150565b6000806110ef83610a27565b905060005b81518110156111eb576001600160a01b0384166000908152600a60205260408120835184908490811061112957611129614210565b60200260200101518154811061114157611141614210565b600091825260209182902060408051610120810182526008909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460ff808216151560e0840152610100918290041615159082015290506111cb816134bd565b6111d590856141a9565b93505080806111e390614226565b9150506110f4565b5050919050565b6111fa61341b565b60015460011461121c5760405162461bcd60e51b8152600401610ab49061410a565b60026001558061125e5760405162461bcd60e51b815260206004820152600d60248201526c656d70747920696e646578657360981b6044820152606401610ab4565b61129d82828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525060019250613510915050565b505060018055565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663784cbca2336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611319573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133d91906141bc565b6113805760405162461bcd60e51b8152602060048201526014602482015273466f7262696464656e3a204f6e6c79205465616d60601b6044820152606401610ab4565b6113886137e8565b565b33611393613dfc565b61139d8284612016565b90508060e00151156113e75760405162461bcd60e51b815260206004820152601360248201527239ba30b5b2903430b9903bb4ba34323930bbb760691b6044820152606401610ab4565b806101000151156114305760405162461bcd60e51b81526020600482015260136024820152721cdd185ad9481a185cc818d85b98d95b1b1959606a1b6044820152606401610ab4565b61143a828461383a565b805160006114478261390f565b90506000611455828461417d565b90508260056000828254611469919061417d565b909155505060208401516003805460009061148590849061417d565b9091555060009050611496856134bd565b90508015611526576003546114b3670de0b6b3a764000083614144565b6114bd919061415b565b600660008282546114ce91906141a9565b90915550506001600160a01b0386166000908152600a6020526040902080548291908990811061150057611500614210565b9060005260206000209060080201600301600082825461152091906141a9565b90915550505b6001600160a01b0386166000908152600a602052604090208054600191908990811061155457611554614210565b6000918252602080832060076008909302019190910180549315156101000261ff0019909416939093179092556001600160a01b0388168152600a909152604081208054899081106115a8576115a8614210565b600091825260209091206008909102015560095460405163d3e96ed360e01b81526001600160a01b039091169063d3e96ed3906115eb9089908690600401614190565b600060405180830381600087803b15801561160557600080fd5b505af1158015611619573d6000803e3d6000fd5b50506009546040516376555fed60e11b8152600481018790526001600160a01b03909116925063ecaabfda9150602401600060405180830381600087803b15801561166357600080fd5b505af1158015611677573d6000803e3d6000fd5b505060408051428152602081018b9052908101869052606081018590526001600160a01b03891692507f10de281942f9db9a7f40110d5f1d818f2ab6f7e182a6d5c0727c6804c17b84bf915060800160405180910390a250505050505050565b6116df61341b565b6001546001146117015760405162461bcd60e51b8152600401610ab49061410a565b6002600155336000818152600a6020526040812080548490811061172757611727614210565b906000526020600020906008020190508060020154816004015461174b91906141a9565b42101561179a5760405162461bcd60e51b815260206004820181905260248201527f596f752063616e277420776974686472617720746865207374616b65207965746044820152606401610ab4565b600781015460ff16156117e35760405162461bcd60e51b815260206004820152601160248201527030b63932b0b23c903bb4ba34323930bbb760791b6044820152606401610ab4565b6007810154610100900460ff161561182f5760405162461bcd60e51b815260206004820152600f60248201526e1cdd185ad94818d85b98d95b1b1959608a1b6044820152606401610ab4565b604080516101208101825282548152600183015460208201526002830154918101919091526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460ff808216151560e084015261010091829004161515908201526000906118a790613928565b604080516101208101825284548152600185015460208201526002850154918101919091526003840154606082015260048401546080820152600584015460a0820152600684015460c0820152600784015460ff808216151560e08401526101009182900416151590820152909150600090611922906134bd565b9050811561198f5760095460405163e24acd4b60e01b81526001600160a01b039091169063e24acd4b9061195c9087908690600401614190565b600060405180830381600087803b15801561197657600080fd5b505af115801561198a573d6000803e3d6000fd5b505050505b825460009061199f90849061417d565b90508015611a6a57600954604051633802f5af60e11b81526001600160a01b0390911690637005eb5e906119d99083908590600401614190565b600060405180830381600087803b1580156119f357600080fd5b505af1158015611a07573d6000803e3d6000fd5b505060095460405163673b31a760e01b8152600481018590526001600160a01b03909116925063673b31a79150602401600060405180830381600087803b158015611a5157600080fd5b505af1158015611a65573d6000803e3d6000fd5b505050505b60095484546040516376555fed60e11b81526001600160a01b039092169163ecaabfda91611a9e9160040190815260200190565b600060405180830381600087803b158015611ab857600080fd5b505af1158015611acc573d6000803e3d6000fd5b505050506000821115611c19576009546040516301e2206160e11b81526001600160a01b03909116906303c440c290611b0b9088908690600401614190565b600060405180830381600087803b158015611b2557600080fd5b505af1158015611b39573d6000803e3d6000fd5b5050506001600160a01b0386166000908152600a60205260409020805484925088908110611b6957611b69614210565b90600052602060002090600802016003016000828254611b8991906141a9565b925050819055508160026000828254611ba2919061417d565b90915550506001600160a01b0385166000908152600c602052604081208054849290611bcf9084906141a9565b909155505060408051838152602081018890526001600160a01b038716917f93b2b5baeb90867d00d09e02023eed58ae019d05b1c254578512984cc85e5ba6910160405180910390a25b60078401805460ff19166001179055611c32858761383a565b836001015460036000828254611c48919061417d565b9091555050835460058054600090611c6190849061417d565b90915550506001840154845460408051428152602081018a9052908101839052606081019290925260808201526001600160a01b038616907fb7ee00edafdb5db3a1b52a5789a6b562eb48268842d113dbfe860b6f86e5f5959060a0015b60405180910390a250506001805550505050565b600a6020528160005260406000208181548110611cef57600080fd5b6000918252602090912060089091020180546001820154600283015460038401546004850154600586015460068701546007909701549598509396509194909391929160ff8082169161010090041689565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016637d075595336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611db5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd991906141bc565b611df55760405162461bcd60e51b8152600401610ab4906141d9565b80471015611e3c5760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610ab4565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611e89576040519150601f19603f3d011682016040523d82523d6000602084013e611e8e565b606091505b5050905080611ed15760405162461bcd60e51b815260206004820152600f60248201526e15da5d1a191c985dc819985a5b1959608a1b6044820152606401610ab4565b505050565b600081611efb576001600160a01b038316600090815260146020526040902054611f15565b6001600160a01b0383166000908152601560205260409020545b90505b92915050565b6000805b8281101561200e576001600160a01b0385166000908152600a60205260408120858584818110611f5457611f54614210565b9050602002013581548110611f6b57611f6b614210565b60009182526020918290206040805161012081018252600890930290910180548084526001820154948401949094526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c08301526007015460ff808216151560e084015261010091829004161515908201529150611ff890846141a9565b925050808061200690614226565b915050611f22565b509392505050565b61201e613dfc565b6001600160a01b0383166000908152600a6020526040902080548390811061204857612048614210565b600091825260209182902060408051610120810182526008909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460ff808216151560e084015261010091829004161515908201529392505050565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016637d075595336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612142573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216691906141bc565b6121825760405162461bcd60e51b8152600401610ab4906141d9565b6001600160a01b0381166121e65760405162461bcd60e51b815260206004820152602560248201527f746f6b656e206d616e6167657220616464726573732063616e206e6f74206265604482015264207a65726f60d81b6064820152608401610ab4565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663784cbca2336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561227c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a091906141bc565b6122e35760405162461bcd60e51b8152602060048201526014602482015273466f7262696464656e3a204f6e6c79205465616d60601b6044820152606401610ab4565b6113886139e7565b6001600160a01b0381166000908152601560209081526040808320815160808101835281548152600182015493810193909352600281015491830191909152600301546001600160801b0316606082015261234590613a24565b61234f90826141a9565b6001600160a01b0383166000908152601460209081526040918290208251608081018452815481526001820154928101929092526002810154928201929092526003909101546001600160801b031660608201529091506123af90613a24565b611f1890826141a9565b600b60205281600052604060002081815481106123d557600080fd5b90600052602060002001600091509150505481565b60015460011461240c5760405162461bcd60e51b8152600401610ab49061410a565b600260015561241961341b565b3360008261243e576001600160a01b0382166000908152601460205260409020612457565b6001600160a01b03821660009081526015602052604090205b905083816000015410156124ad5760405162461bcd60e51b815260206004820152601960248201527f496e73756666696369656e74207374616b6520616d6f756e74000000000000006044820152606401610ab4565b6009546001600160a01b031660006124c48661390f565b905060006124d2828861417d565b905060006124e08688613a70565b5086156125ce576040516376555fed60e11b8152600481018490526001600160a01b0385169063ecaabfda90602401600060405180830381600087803b15801561252957600080fd5b505af115801561253d573d6000803e3d6000fd5b505060405163d3e96ed360e01b81526001600160a01b038716925063d3e96ed3915061256f9089908690600401614190565b600060405180830381600087803b15801561258957600080fd5b505af115801561259d573d6000803e3d6000fd5b50506012546125af9250905089614144565b905087600560008282546125c3919061417d565b909155506126b09050565b60405163673b31a760e01b8152600481018490526001600160a01b0385169063673b31a790602401600060405180830381600087803b15801561261057600080fd5b505af1158015612624573d6000803e3d6000fd5b505060405163562084bd60e11b81526001600160a01b038716925063ac41097a91506126569089908690600401614190565b600060405180830381600087803b15801561267057600080fd5b505af1158015612684573d6000803e3d6000fd5b50506011546126969250905089614144565b905087600460008282546126aa919061417d565b90915550505b80600360008282546126c2919061417d565b90915550508454889086906000906126db90849061417d565b92505081905550808560020160008282546126f6919061417d565b909155505060028501546127099061349a565b6001860155604080514281526020810184905290810184905287151560608201526001600160a01b038716907fc7ccdcb2d25f572c6814e377dbb34ea4318a4b7d3cd890f5cfad699d75327c7c9060800160405180910390a2505060018055505050505050565b61277861341b565b60015460011461279a5760405162461bcd60e51b8152600401610ab49061410a565b6002600155336127a8613e4c565b60005b83811015612a7d5760008585838181106127c7576127c7614210565b9050602002013590506000600a6000866001600160a01b03166001600160a01b03168152602001908152602001600020828154811061280857612808614210565b906000526020600020906008020190508060020154816004015461282c91906141a9565b42101561287b5760405162461bcd60e51b815260206004820181905260248201527f596f752063616e277420776974686472617720746865207374616b65207965746044820152606401610ab4565b600781015460ff16156128c45760405162461bcd60e51b815260206004820152601160248201527030b63932b0b23c903bb4ba34323930bbb760791b6044820152606401610ab4565b6007810154610100900460ff16156129105760405162461bcd60e51b815260206004820152600f60248201526e1cdd185ad94818d85b98d95b1b1959608a1b6044820152606401610ab4565b6001810154845185906129249083906141a9565b905250604080516101208101825282548152600183015460208201526002830154918101919091526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460ff808216151560e0840152610100918290041615159082015261299c90613928565b6020850180516129ad9083906141a9565b905250604080516101208101825282548152600183015460208201526002830154918101919091526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460ff808216151560e08401526101009182900416151590820152612a25906134bd565b604085018051612a369083906141a9565b9052508054606085018051612a4c9083906141a9565b90525060078101805460ff19166001179055612a68858361383a565b50508080612a7590614226565b9150506127ab565b50602081015115612af157600954602082015160405163e24acd4b60e01b81526001600160a01b039092169163e24acd4b91612abe91869190600401614190565b600060405180830381600087803b158015612ad857600080fd5b505af1158015612aec573d6000803e3d6000fd5b505050505b60208101516060820151600091612b079161417d565b90508015612bd257600954604051633802f5af60e11b81526001600160a01b0390911690637005eb5e90612b419083908590600401614190565b600060405180830381600087803b158015612b5b57600080fd5b505af1158015612b6f573d6000803e3d6000fd5b505060095460405163673b31a760e01b8152600481018590526001600160a01b03909116925063673b31a79150602401600060405180830381600087803b158015612bb957600080fd5b505af1158015612bcd573d6000803e3d6000fd5b505050505b60095460608301516040516376555fed60e11b815260048101919091526001600160a01b039091169063ecaabfda90602401600060405180830381600087803b158015612c1e57600080fd5b505af1158015612c32573d6000803e3d6000fd5b5050505081600060048110612c4957612c49614210565b602002015160036000828254612c5f919061417d565b9091555050606082015160058054600090612c7b90849061417d565b90915550506040805160208087028281018201909352868252612cb99288918891829185019084908082843760009201829052509250613510915050565b602082015160608301516040516001600160a01b038616927f670058fd657dd0cbca748af3a687a4d5b441b61753a2ccbea58894eac13d559992612d059242928b928b9282919061423f565b60405180910390a2505060018055505050565b6001600160a01b0382166000908152600a60205260408120805482919084908110612d4557612d45614210565b600091825260209182902060408051610120810182526008909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460ff808216151560e084015261010091829004161515908201529050612dcf81613928565b91504281604001518260800151612de691906141a9565b1115612df157600091505b5092915050565b8060008111612e195760405162461bcd60e51b8152600401610ab4906140d5565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663b3296422336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612e8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eb191906141bc565b612efd5760405162461bcd60e51b815260206004820152601860248201527f466f7262696464656e3a204f6e6c792050726f746f636f6c00000000000000006044820152606401610ab4565b60035415612fbb578160026000828254612f1791906141a9565b925050819055508160086000828254612f3091906141a9565b9091555050600354612f4a670de0b6b3a764000084614144565b612f54919061415b565b60066000828254612f6591906141a9565b909155505060035460055460045460408051868152602081019490945283019190915260608201527fb2de7f58fce4830ac7100b13cdb8d26966c919277b33ed122a362543a7addf369060800160405180910390a15b5050565b6001600160a01b0382166000908152600a60205260408120805482919084908110612fec57612fec614210565b600091825260209182902060408051610120810182526008909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460ff808216151560e08401819052610100928390049091161515918301919091529091508061308257508061010001515b15613091576000915050611f18565b61309a816134bd565b949350505050565b81600081116130c35760405162461bcd60e51b8152600401610ab4906140d5565b6001546001146130e55760405162461bcd60e51b8152600401610ab49061410a565b60026001556130f261341b565b33600083156131985760095460405163079b9d7760e21b81526001600160a01b0390911690631e6e75dc9061312d9085908990600401614190565b600060405180830381600087803b15801561314757600080fd5b505af115801561315b573d6000803e3d6000fd5b5050506001600160a01b038316600090815260156020526040812060058054919450889350919061318d9084906141a9565b909155506132309050565b600954604051631095e8b160e31b81526001600160a01b03909116906384af4588906131ca9085908990600401614190565b600060405180830381600087803b1580156131e457600080fd5b505af11580156131f8573d6000803e3d6000fd5b5050506001600160a01b038316600090815260146020526040812060048054919450889350919061322a9084906141a9565b90915550505b805415613243576132418285613a70565b505b600061326086836000015461325891906141a9565b866000613461565b9050816002015481613272919061417d565b6003600082825461328391906141a9565b909155505081548690839060009061329c9084906141a9565b90915550506003820180546fffffffffffffffffffffffffffffffff1916426001600160801b0316179055600282018190556132d78161349a565b600183018190558254604080519182526020820192909252861515918101919091526001600160a01b038416907fd0f836e593c496b2857b30a01b4268b1ae280ad2545285f4cadf3fe26c00763b90606001611cbf565b61333661341b565b6001546001146133585760405162461bcd60e51b8152600401610ab49061410a565b600260015561336633613bf4565b5060018055565b6133a1604051806080016040528060008152602001600081526020016000815260200160006001600160801b031681525090565b816133c3576001600160a01b03831660009081526014602052604090206133dc565b6001600160a01b03831660009081526015602052604090205b6040805160808101825282548152600183015460208201526002830154918101919091526003909101546001600160801b031660608201529392505050565b60005460ff16156113885760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ab4565b6000821561348d57816134805760125461347b9085614144565b61309a565b60135461347b9085614144565b60115461309a9085614144565b6000670de0b6b3a7640000600654836134b39190614144565b611f18919061415b565b600080670de0b6b3a764000060065484602001516134db9190614144565b6134e5919061415b565b905082606001518110613506576060830151613501908261417d565b613509565b60005b9392505050565b336000805b84518110156136ef57600085828151811061353257613532614210565b602002602001015190506000600a6000866001600160a01b03166001600160a01b03168152602001908152602001600020828154811061357457613574614210565b9060005260206000209060080201905085156135df57600781015460ff16156135df5760405162461bcd60e51b815260206004820181905260248201527f5374616b652068617320616c7265616479206265656e2077697468647261776e6044820152606401610ab4565b6007810154610100900460ff16156136395760405162461bcd60e51b815260206004820152601860248201527f5374616b6520686173206265656e2063616e63656c6c656400000000000000006044820152606401610ab4565b604080516101208101825282548152600183015460208201526002830154918101919091526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460ff808216151560e084015261010091829004161515908201526000906136b1906134bd565b9050808260030160008282546136c791906141a9565b909155506136d7905081866141a9565b945050505080806136e790614226565b915050613515565b508060026000828254613702919061417d565b90915550506001600160a01b0382166000908152600c60205260408120805483929061372f9084906141a9565b9091555050801561379f576009546040516301e2206160e11b81526001600160a01b03909116906303c440c29061376c9085908590600401614190565b600060405180830381600087803b15801561378657600080fd5b505af115801561379a573d6000803e3d6000fd5b505050505b816001600160a01b03167f94dcc76e9211fa75425c6978d70f34a2182dee339d4aa4f9d0a0351f62c769e382866040516137da929190614292565b60405180910390a250505050565b6137f0613db3565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382166000908152600b60205260408120805490915b81811015613908578383828154811061387257613872614210565b9060005260206000200154036138f6578261388e60018461417d565b8154811061389e5761389e614210565b90600052602060002001548382815481106138bb576138bb614210565b9060005260206000200181905550828054806138d9576138d96142ab565b600190038181906000526020600020016000905590555050505050565b8061390081614226565b915050613857565b5050505050565b6000670de0b6b3a7640000600754836134b39190614144565b6000806201518083608001514261393f919061417d565b613949919061415b565b9050600062015180600d60010154613961919061415b565b905080821015613975575060009392505050565b8360400151846080015161398991906141a9565b4211156139a6576201518084604001516139a3919061415b565b91505b600f546139b3828461417d565b60a086015186516139c4919061417d565b6139ce9190614144565b6139d8919061415b565b8460a0015161309a91906141a9565b6139ef61341b565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861381d3390565b6000670de0b6b3a76400006006548360400151613a419190614144565b613a4b919061415b565b90508160200151811015613a6157506000919050565b6020820151611f18908261417d565b60008082613a95576001600160a01b0384166000908152601460205260409020613aae565b6001600160a01b03841660009081526015602052604090205b60408051608081018252825481526001830154602082015260028301549181019190915260038201546001600160801b03166060820152909150613af190613a24565b915081600003613b05576000915050611f18565b6009546040516301e2206160e11b81526001600160a01b03909116906303c440c290613b379087908690600401614190565b600060405180830381600087803b158015613b5157600080fd5b505af1158015613b65573d6000803e3d6000fd5b50505050613b76816002015461349a565b60018201556001600160a01b0384166000908152600c602052604081208054849290613ba39084906141a9565b90915550506040805183815284151560208201526001600160a01b038616917feafb3ef7cb9229547fa473df9e43073744d337e19e2e548fa289a2747abeddc7910160405180910390a25092915050565b6001600160a01b03811660009081526015602090815260408083206014835281842082516080810184528254815260018301549481019490945260028201549284019290925260038101546001600160801b0316606084015291613c5790613a24565b60408051608081018252835481526001840154602082015260028401549181019190915260038301546001600160801b03166060820152909350613c9a90613a24565b613ca490846141a9565b925082600003613cb8575060009392505050565b6009546040516301e2206160e11b81526001600160a01b03909116906303c440c290613cea9087908790600401614190565b600060405180830381600087803b158015613d0457600080fd5b505af1158015613d18573d6000803e3d6000fd5b50505050613d29826002015461349a565b60018301556002810154613d3c9061349a565b60018201556001600160a01b0384166000908152600c602052604081208054859290613d699084906141a9565b90915550506040518381526001600160a01b038516907f39f1bc8a3004d8c2a2e71c312c419cafba6747f8552f82ba2c5fb5cc92d263189060200160405180910390a25050919050565b60005460ff166113885760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610ab4565b604051806101200160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b60405180608001604052806004906020820280368337509192915050565b6001600160a01b0381168114613e7f57600080fd5b50565b600060208284031215613e9457600080fd5b813561350981613e6a565b600081518084526020808501945080840160005b83811015613ecf57815187529582019590820190600101613eb3565b509495945050505050565b602081526000611f156020830184613e9f565b60008060408385031215613f0057600080fd5b50508035926020909101359150565b60008060008060808587031215613f2557600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215613f5357600080fd5b5035919050565b60008083601f840112613f6c57600080fd5b50813567ffffffffffffffff811115613f8457600080fd5b6020830191508360208260051b8501011115613f9f57600080fd5b9250929050565b60008060208385031215613fb957600080fd5b823567ffffffffffffffff811115613fd057600080fd5b613fdc85828601613f5a565b90969095509350505050565b60008060408385031215613ffb57600080fd5b823561400681613e6a565b946020939093013593505050565b8015158114613e7f57600080fd5b6000806040838503121561403557600080fd5b823561404081613e6a565b9150602083013561405081614014565b809150509250929050565b60008060006040848603121561407057600080fd5b833561407b81613e6a565b9250602084013567ffffffffffffffff81111561409757600080fd5b6140a386828701613f5a565b9497909650939450505050565b600080604083850312156140c357600080fd5b82359150602083013561405081614014565b6020808252818101527f616d6f756e74206d7573742062652067726561746572207468616e207a65726f604082015260600190565b6020808252600a90820152695245454e5452414e435960b01b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417611f1857611f1861412e565b60008261417857634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115611f1857611f1861412e565b6001600160a01b03929092168252602082015260400190565b80820180821115611f1857611f1861412e565b6000602082840312156141ce57600080fd5b815161350981614014565b6020808252601a908201527f466f7262696464656e3a204f6e6c7920476f7665726e616e6365000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6000600182016142385761423861412e565b5060010190565b86815260a060208201819052810185905260006001600160fb1b0386111561426657600080fd5b8560051b808860c0850137604083019590955250606081019290925260808201520160c0019392505050565b82815260406020820152600061309a6040830184613e9f565b634e487b7160e01b600052603160045260246000fdfea26469706673582212209db504b7d6c99067ebeb7f431e241e251bb0af51bbc6b0ab5b2163104376fe7064736f6c634300081300330000000000000000000000008cca793d0ec8c61f156cd4738455ab682554f4180000000000000000000000009ad41cd4f7434d33c30062301a303a9b42111d45

Deployed Bytecode

0x60806040526004361061026b5760003560e01c80637cb2b79c11610144578063b9e8346d116100b6578063ef5d9ae81161007a578063ef5d9ae81461091a578063ef78d4fd14610947578063f0fc6bca1461098a578063f520c87f1461099f578063f79d032d146109b5578063fe9b050e146109cb576102a8565b8063b9e8346d14610850578063c3d9c4b414610884578063dba41cbf146108a4578063e4aff9c4146108c4578063e982a482146108fa576102a8565b806396c82e571161010857806396c82e571461076f5780639def0543146107855780639ebea88c146107a5578063a9c26186146107c5578063ae03119314610810578063b1945e5a14610830576102a8565b80637cb2b79c146106e55780638456cb5914610705578063860015191461071a578063947a56cd14610730578063961072021461074f576102a8565b8063581b593e116101dd578063613ce410116101a1578063613ce410146105a25780636230b83d146105d45780636cc0bd24146105ea5780636dfa8d991461060a5780637b103999146106205780637be25ba214610654576102a8565b8063581b593e14610463578063584b62a1146104d75780635ab08f001461053f5780635c975abb1461055f57806360d3bdfe14610582576102a8565b80632a709b141161022f5780632a709b14146103965780632ef73e88146103ce578063374756f5146103ee5780633f4ba83a1461040e57806340e58ee5146104235780634178ec2814610443576102a8565b80630210290f146102da5780631df0af3f1461031057806324d17fa11461033257806327f00c251461035257806329f0db2214610376576102a8565b366102a85760405134815233907f5d8bc849764969eb1bcc6d0a2f55999d0167c1ccec240a4f39cf664ca9c4148e906020015b60405180910390a2005b60405134815233907f5d8bc849764969eb1bcc6d0a2f55999d0167c1ccec240a4f39cf664ca9c4148e9060200161029e565b3480156102e657600080fd5b506102fa6102f5366004613e82565b610a27565b6040516103079190613eda565b60405180910390f35b34801561031c57600080fd5b5061033061032b366004613eed565b610a93565b005b34801561033e57600080fd5b5061033061034d366004613f0f565b610e48565b34801561035e57600080fd5b5061036860055481565b604051908152602001610307565b34801561038257600080fd5b50610330610391366004613f41565b610ff4565b3480156103a257600080fd5b506009546103b6906001600160a01b031681565b6040516001600160a01b039091168152602001610307565b3480156103da57600080fd5b506103686103e9366004613e82565b6110e3565b3480156103fa57600080fd5b50610330610409366004613fa6565b6111f2565b34801561041a57600080fd5b506103306112a5565b34801561042f57600080fd5b5061033061043e366004613f41565b61138a565b34801561044f57600080fd5b5061033061045e366004613f41565b6116d7565b34801561046f57600080fd5b506104ae61047e366004613e82565b6014602052600090815260409020805460018201546002830154600390930154919290916001600160801b031684565b604080519485526020850193909352918301526001600160801b03166060820152608001610307565b3480156104e357600080fd5b506104f76104f2366004613fe8565b611cd3565b60408051998a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c0840152151560e0830152151561010082015261012001610307565b34801561054b57600080fd5b5061033061055a366004613fe8565b611d41565b34801561056b57600080fd5b5060005460ff166040519015158152602001610307565b34801561058e57600080fd5b5061036861059d366004614022565b611ed6565b3480156105ae57600080fd5b506005546004546008545b60408051938452602084019290925290820152606001610307565b3480156105e057600080fd5b5061036860075481565b3480156105f657600080fd5b5061036861060536600461405b565b611f1e565b34801561061657600080fd5b5061036860085481565b34801561062c57600080fd5b506103b67f0000000000000000000000008cca793d0ec8c61f156cd4738455ab682554f41881565b34801561066057600080fd5b5061067461066f366004613fe8565b612016565b6040516103079190600061012082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e0830151151560e0830152610100808401511515818401525092915050565b3480156106f157600080fd5b50610330610700366004613e82565b6120ce565b34801561071157600080fd5b50610330612208565b34801561072657600080fd5b5061036860025481565b34801561073c57600080fd5b506011546012546013546105b992919083565b34801561075b57600080fd5b5061036861076a366004613e82565b6122eb565b34801561077b57600080fd5b5061036860035481565b34801561079157600080fd5b506103686107a0366004613fe8565b6123b9565b3480156107b157600080fd5b506103306107c03660046140b0565b6123ea565b3480156107d157600080fd5b506104ae6107e0366004613e82565b6015602052600090815260409020805460018201546002830154600390930154919290916001600160801b031684565b34801561081c57600080fd5b5061033061082b366004613fa6565b612770565b34801561083c57600080fd5b5061036861084b366004613fe8565b612d18565b34801561085c57600080fd5b506103b67f0000000000000000000000009ad41cd4f7434d33c30062301a303a9b42111d4581565b34801561089057600080fd5b5061033061089f366004613f41565b612df8565b3480156108b057600080fd5b506103686108bf366004613fe8565b612fbf565b3480156108d057600080fd5b506103686108df366004613e82565b6001600160a01b03166000908152600a602052604090205490565b34801561090657600080fd5b506103306109153660046140b0565b6130a2565b34801561092657600080fd5b50610368610935366004613e82565b600c6020526000908152604090205481565b34801561095357600080fd5b50600d54600e54600f5460105461096a9392919084565b604080519485526020850193909352918301526060820152608001610307565b34801561099657600080fd5b5061033061332e565b3480156109ab57600080fd5b5061036860065481565b3480156109c157600080fd5b5061036860045481565b3480156109d757600080fd5b506109eb6109e6366004614022565b61336d565b60405161030791908151815260208083015190820152604080830151908201526060918201516001600160801b03169181019190915260800190565b6001600160a01b0381166000908152600b6020908152604091829020805483518184028101840190945280845260609392830182828015610a8757602002820191906000526020600020905b815481526020019060010190808311610a73575b50505050509050919050565b8160008111610abd5760405162461bcd60e51b8152600401610ab4906140d5565b60405180910390fd5b600154600114610adf5760405162461bcd60e51b8152600401610ab49061410a565b6002600155610aec61341b565b6000610afb8362015180614144565b600e549091508110801590610b125750600d548311155b610b5e5760405162461bcd60e51b815260206004820152601a60248201527f6475726174696f6e206d75737420626520696e20706572696f640000000000006044820152606401610ab4565b336000610b6d86600180613461565b90506000610b7a8261349a565b6010549091504290600090670de0b6b3a764000090610b99908b614144565b610ba3919061415b565b600f54909150600090610bb6838c61417d565b610bc0919061415b565b60095460405163079b9d7760e21b81529192506001600160a01b031690631e6e75dc90610bf39089908e90600401614190565b600060405180830381600087803b158015610c0d57600080fd5b505af1158015610c21573d6000803e3d6000fd5b505050508460036000828254610c3791906141a9565b925050819055508960056000828254610c5091906141a9565b92505081905550600a6000876001600160a01b03166001600160a01b031681526020019081526020016000206040518061012001604052808c8152602001878152602001898152602001868152602001858152602001848152602001838152602001600015158152602001600015158152509080600181540180825580915050600190039060005260206000209060080201600090919091909150600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e08201518160070160006101000a81548160ff0219169083151502179055506101008201518160070160016101000a81548160ff021916908315150217905550505060006001600a6000336001600160a01b03166001600160a01b0316815260200190815260200160002080549050610dab919061417d565b336000908152600b602090815260408220805460018101825590835291200181905590506040805182815260208101869052908101899052606081018c905260808101869052600160a0820181905260c08201526001600160a01b038816907feb7bdad6029ad027c77906ce1960c5ac2111bf37b5a7bb7b63068aa4f25256179060e00160405180910390a2505060018055505050505050505050565b6001600160a01b037f0000000000000000000000008cca793d0ec8c61f156cd4738455ab682554f41816637d075595336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ebc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee091906141bc565b610efc5760405162461bcd60e51b8152600401610ab4906141d9565b82841015610f725760405162461bcd60e51b815260206004820152603a60248201527f4475726174696f6e206d7573742062652067726561746572207468616e206f7260448201527f20657175616c20746f206d696e696d756d206475726174696f6e0000000000006064820152608401610ab4565b83821115610fe05760405162461bcd60e51b815260206004820152603560248201527f436c61696d206475726174696f6e206d757374206265206c657373207468616e6044820152741037b91032b8bab0b6103a3790323ab930ba34b7b760591b6064820152608401610ab4565b600d93909355600e91909155600f55601055565b6001600160a01b037f0000000000000000000000008cca793d0ec8c61f156cd4738455ab682554f41816637d075595336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611068573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108c91906141bc565b6110a85760405162461bcd60e51b8152600401610ab4906141d9565b60078190556040518181527fc6723167dfc6a0204d07a4d7c81104295b948a8fac5769b1576c202032cf8ef39060200160405180910390a150565b6000806110ef83610a27565b905060005b81518110156111eb576001600160a01b0384166000908152600a60205260408120835184908490811061112957611129614210565b60200260200101518154811061114157611141614210565b600091825260209182902060408051610120810182526008909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460ff808216151560e0840152610100918290041615159082015290506111cb816134bd565b6111d590856141a9565b93505080806111e390614226565b9150506110f4565b5050919050565b6111fa61341b565b60015460011461121c5760405162461bcd60e51b8152600401610ab49061410a565b60026001558061125e5760405162461bcd60e51b815260206004820152600d60248201526c656d70747920696e646578657360981b6044820152606401610ab4565b61129d82828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525060019250613510915050565b505060018055565b6001600160a01b037f0000000000000000000000008cca793d0ec8c61f156cd4738455ab682554f4181663784cbca2336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611319573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133d91906141bc565b6113805760405162461bcd60e51b8152602060048201526014602482015273466f7262696464656e3a204f6e6c79205465616d60601b6044820152606401610ab4565b6113886137e8565b565b33611393613dfc565b61139d8284612016565b90508060e00151156113e75760405162461bcd60e51b815260206004820152601360248201527239ba30b5b2903430b9903bb4ba34323930bbb760691b6044820152606401610ab4565b806101000151156114305760405162461bcd60e51b81526020600482015260136024820152721cdd185ad9481a185cc818d85b98d95b1b1959606a1b6044820152606401610ab4565b61143a828461383a565b805160006114478261390f565b90506000611455828461417d565b90508260056000828254611469919061417d565b909155505060208401516003805460009061148590849061417d565b9091555060009050611496856134bd565b90508015611526576003546114b3670de0b6b3a764000083614144565b6114bd919061415b565b600660008282546114ce91906141a9565b90915550506001600160a01b0386166000908152600a6020526040902080548291908990811061150057611500614210565b9060005260206000209060080201600301600082825461152091906141a9565b90915550505b6001600160a01b0386166000908152600a602052604090208054600191908990811061155457611554614210565b6000918252602080832060076008909302019190910180549315156101000261ff0019909416939093179092556001600160a01b0388168152600a909152604081208054899081106115a8576115a8614210565b600091825260209091206008909102015560095460405163d3e96ed360e01b81526001600160a01b039091169063d3e96ed3906115eb9089908690600401614190565b600060405180830381600087803b15801561160557600080fd5b505af1158015611619573d6000803e3d6000fd5b50506009546040516376555fed60e11b8152600481018790526001600160a01b03909116925063ecaabfda9150602401600060405180830381600087803b15801561166357600080fd5b505af1158015611677573d6000803e3d6000fd5b505060408051428152602081018b9052908101869052606081018590526001600160a01b03891692507f10de281942f9db9a7f40110d5f1d818f2ab6f7e182a6d5c0727c6804c17b84bf915060800160405180910390a250505050505050565b6116df61341b565b6001546001146117015760405162461bcd60e51b8152600401610ab49061410a565b6002600155336000818152600a6020526040812080548490811061172757611727614210565b906000526020600020906008020190508060020154816004015461174b91906141a9565b42101561179a5760405162461bcd60e51b815260206004820181905260248201527f596f752063616e277420776974686472617720746865207374616b65207965746044820152606401610ab4565b600781015460ff16156117e35760405162461bcd60e51b815260206004820152601160248201527030b63932b0b23c903bb4ba34323930bbb760791b6044820152606401610ab4565b6007810154610100900460ff161561182f5760405162461bcd60e51b815260206004820152600f60248201526e1cdd185ad94818d85b98d95b1b1959608a1b6044820152606401610ab4565b604080516101208101825282548152600183015460208201526002830154918101919091526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460ff808216151560e084015261010091829004161515908201526000906118a790613928565b604080516101208101825284548152600185015460208201526002850154918101919091526003840154606082015260048401546080820152600584015460a0820152600684015460c0820152600784015460ff808216151560e08401526101009182900416151590820152909150600090611922906134bd565b9050811561198f5760095460405163e24acd4b60e01b81526001600160a01b039091169063e24acd4b9061195c9087908690600401614190565b600060405180830381600087803b15801561197657600080fd5b505af115801561198a573d6000803e3d6000fd5b505050505b825460009061199f90849061417d565b90508015611a6a57600954604051633802f5af60e11b81526001600160a01b0390911690637005eb5e906119d99083908590600401614190565b600060405180830381600087803b1580156119f357600080fd5b505af1158015611a07573d6000803e3d6000fd5b505060095460405163673b31a760e01b8152600481018590526001600160a01b03909116925063673b31a79150602401600060405180830381600087803b158015611a5157600080fd5b505af1158015611a65573d6000803e3d6000fd5b505050505b60095484546040516376555fed60e11b81526001600160a01b039092169163ecaabfda91611a9e9160040190815260200190565b600060405180830381600087803b158015611ab857600080fd5b505af1158015611acc573d6000803e3d6000fd5b505050506000821115611c19576009546040516301e2206160e11b81526001600160a01b03909116906303c440c290611b0b9088908690600401614190565b600060405180830381600087803b158015611b2557600080fd5b505af1158015611b39573d6000803e3d6000fd5b5050506001600160a01b0386166000908152600a60205260409020805484925088908110611b6957611b69614210565b90600052602060002090600802016003016000828254611b8991906141a9565b925050819055508160026000828254611ba2919061417d565b90915550506001600160a01b0385166000908152600c602052604081208054849290611bcf9084906141a9565b909155505060408051838152602081018890526001600160a01b038716917f93b2b5baeb90867d00d09e02023eed58ae019d05b1c254578512984cc85e5ba6910160405180910390a25b60078401805460ff19166001179055611c32858761383a565b836001015460036000828254611c48919061417d565b9091555050835460058054600090611c6190849061417d565b90915550506001840154845460408051428152602081018a9052908101839052606081019290925260808201526001600160a01b038616907fb7ee00edafdb5db3a1b52a5789a6b562eb48268842d113dbfe860b6f86e5f5959060a0015b60405180910390a250506001805550505050565b600a6020528160005260406000208181548110611cef57600080fd5b6000918252602090912060089091020180546001820154600283015460038401546004850154600586015460068701546007909701549598509396509194909391929160ff8082169161010090041689565b6001600160a01b037f0000000000000000000000008cca793d0ec8c61f156cd4738455ab682554f41816637d075595336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611db5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd991906141bc565b611df55760405162461bcd60e51b8152600401610ab4906141d9565b80471015611e3c5760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610ab4565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611e89576040519150601f19603f3d011682016040523d82523d6000602084013e611e8e565b606091505b5050905080611ed15760405162461bcd60e51b815260206004820152600f60248201526e15da5d1a191c985dc819985a5b1959608a1b6044820152606401610ab4565b505050565b600081611efb576001600160a01b038316600090815260146020526040902054611f15565b6001600160a01b0383166000908152601560205260409020545b90505b92915050565b6000805b8281101561200e576001600160a01b0385166000908152600a60205260408120858584818110611f5457611f54614210565b9050602002013581548110611f6b57611f6b614210565b60009182526020918290206040805161012081018252600890930290910180548084526001820154948401949094526002810154918301919091526003810154606083015260048101546080830152600581015460a0830152600681015460c08301526007015460ff808216151560e084015261010091829004161515908201529150611ff890846141a9565b925050808061200690614226565b915050611f22565b509392505050565b61201e613dfc565b6001600160a01b0383166000908152600a6020526040902080548390811061204857612048614210565b600091825260209182902060408051610120810182526008909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460ff808216151560e084015261010091829004161515908201529392505050565b6001600160a01b037f0000000000000000000000008cca793d0ec8c61f156cd4738455ab682554f41816637d075595336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612142573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216691906141bc565b6121825760405162461bcd60e51b8152600401610ab4906141d9565b6001600160a01b0381166121e65760405162461bcd60e51b815260206004820152602560248201527f746f6b656e206d616e6167657220616464726573732063616e206e6f74206265604482015264207a65726f60d81b6064820152608401610ab4565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b037f0000000000000000000000008cca793d0ec8c61f156cd4738455ab682554f4181663784cbca2336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561227c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a091906141bc565b6122e35760405162461bcd60e51b8152602060048201526014602482015273466f7262696464656e3a204f6e6c79205465616d60601b6044820152606401610ab4565b6113886139e7565b6001600160a01b0381166000908152601560209081526040808320815160808101835281548152600182015493810193909352600281015491830191909152600301546001600160801b0316606082015261234590613a24565b61234f90826141a9565b6001600160a01b0383166000908152601460209081526040918290208251608081018452815481526001820154928101929092526002810154928201929092526003909101546001600160801b031660608201529091506123af90613a24565b611f1890826141a9565b600b60205281600052604060002081815481106123d557600080fd5b90600052602060002001600091509150505481565b60015460011461240c5760405162461bcd60e51b8152600401610ab49061410a565b600260015561241961341b565b3360008261243e576001600160a01b0382166000908152601460205260409020612457565b6001600160a01b03821660009081526015602052604090205b905083816000015410156124ad5760405162461bcd60e51b815260206004820152601960248201527f496e73756666696369656e74207374616b6520616d6f756e74000000000000006044820152606401610ab4565b6009546001600160a01b031660006124c48661390f565b905060006124d2828861417d565b905060006124e08688613a70565b5086156125ce576040516376555fed60e11b8152600481018490526001600160a01b0385169063ecaabfda90602401600060405180830381600087803b15801561252957600080fd5b505af115801561253d573d6000803e3d6000fd5b505060405163d3e96ed360e01b81526001600160a01b038716925063d3e96ed3915061256f9089908690600401614190565b600060405180830381600087803b15801561258957600080fd5b505af115801561259d573d6000803e3d6000fd5b50506012546125af9250905089614144565b905087600560008282546125c3919061417d565b909155506126b09050565b60405163673b31a760e01b8152600481018490526001600160a01b0385169063673b31a790602401600060405180830381600087803b15801561261057600080fd5b505af1158015612624573d6000803e3d6000fd5b505060405163562084bd60e11b81526001600160a01b038716925063ac41097a91506126569089908690600401614190565b600060405180830381600087803b15801561267057600080fd5b505af1158015612684573d6000803e3d6000fd5b50506011546126969250905089614144565b905087600460008282546126aa919061417d565b90915550505b80600360008282546126c2919061417d565b90915550508454889086906000906126db90849061417d565b92505081905550808560020160008282546126f6919061417d565b909155505060028501546127099061349a565b6001860155604080514281526020810184905290810184905287151560608201526001600160a01b038716907fc7ccdcb2d25f572c6814e377dbb34ea4318a4b7d3cd890f5cfad699d75327c7c9060800160405180910390a2505060018055505050505050565b61277861341b565b60015460011461279a5760405162461bcd60e51b8152600401610ab49061410a565b6002600155336127a8613e4c565b60005b83811015612a7d5760008585838181106127c7576127c7614210565b9050602002013590506000600a6000866001600160a01b03166001600160a01b03168152602001908152602001600020828154811061280857612808614210565b906000526020600020906008020190508060020154816004015461282c91906141a9565b42101561287b5760405162461bcd60e51b815260206004820181905260248201527f596f752063616e277420776974686472617720746865207374616b65207965746044820152606401610ab4565b600781015460ff16156128c45760405162461bcd60e51b815260206004820152601160248201527030b63932b0b23c903bb4ba34323930bbb760791b6044820152606401610ab4565b6007810154610100900460ff16156129105760405162461bcd60e51b815260206004820152600f60248201526e1cdd185ad94818d85b98d95b1b1959608a1b6044820152606401610ab4565b6001810154845185906129249083906141a9565b905250604080516101208101825282548152600183015460208201526002830154918101919091526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460ff808216151560e0840152610100918290041615159082015261299c90613928565b6020850180516129ad9083906141a9565b905250604080516101208101825282548152600183015460208201526002830154918101919091526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460ff808216151560e08401526101009182900416151590820152612a25906134bd565b604085018051612a369083906141a9565b9052508054606085018051612a4c9083906141a9565b90525060078101805460ff19166001179055612a68858361383a565b50508080612a7590614226565b9150506127ab565b50602081015115612af157600954602082015160405163e24acd4b60e01b81526001600160a01b039092169163e24acd4b91612abe91869190600401614190565b600060405180830381600087803b158015612ad857600080fd5b505af1158015612aec573d6000803e3d6000fd5b505050505b60208101516060820151600091612b079161417d565b90508015612bd257600954604051633802f5af60e11b81526001600160a01b0390911690637005eb5e90612b419083908590600401614190565b600060405180830381600087803b158015612b5b57600080fd5b505af1158015612b6f573d6000803e3d6000fd5b505060095460405163673b31a760e01b8152600481018590526001600160a01b03909116925063673b31a79150602401600060405180830381600087803b158015612bb957600080fd5b505af1158015612bcd573d6000803e3d6000fd5b505050505b60095460608301516040516376555fed60e11b815260048101919091526001600160a01b039091169063ecaabfda90602401600060405180830381600087803b158015612c1e57600080fd5b505af1158015612c32573d6000803e3d6000fd5b5050505081600060048110612c4957612c49614210565b602002015160036000828254612c5f919061417d565b9091555050606082015160058054600090612c7b90849061417d565b90915550506040805160208087028281018201909352868252612cb99288918891829185019084908082843760009201829052509250613510915050565b602082015160608301516040516001600160a01b038616927f670058fd657dd0cbca748af3a687a4d5b441b61753a2ccbea58894eac13d559992612d059242928b928b9282919061423f565b60405180910390a2505060018055505050565b6001600160a01b0382166000908152600a60205260408120805482919084908110612d4557612d45614210565b600091825260209182902060408051610120810182526008909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460ff808216151560e084015261010091829004161515908201529050612dcf81613928565b91504281604001518260800151612de691906141a9565b1115612df157600091505b5092915050565b8060008111612e195760405162461bcd60e51b8152600401610ab4906140d5565b6001600160a01b037f0000000000000000000000008cca793d0ec8c61f156cd4738455ab682554f4181663b3296422336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612e8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eb191906141bc565b612efd5760405162461bcd60e51b815260206004820152601860248201527f466f7262696464656e3a204f6e6c792050726f746f636f6c00000000000000006044820152606401610ab4565b60035415612fbb578160026000828254612f1791906141a9565b925050819055508160086000828254612f3091906141a9565b9091555050600354612f4a670de0b6b3a764000084614144565b612f54919061415b565b60066000828254612f6591906141a9565b909155505060035460055460045460408051868152602081019490945283019190915260608201527fb2de7f58fce4830ac7100b13cdb8d26966c919277b33ed122a362543a7addf369060800160405180910390a15b5050565b6001600160a01b0382166000908152600a60205260408120805482919084908110612fec57612fec614210565b600091825260209182902060408051610120810182526008909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260079091015460ff808216151560e08401819052610100928390049091161515918301919091529091508061308257508061010001515b15613091576000915050611f18565b61309a816134bd565b949350505050565b81600081116130c35760405162461bcd60e51b8152600401610ab4906140d5565b6001546001146130e55760405162461bcd60e51b8152600401610ab49061410a565b60026001556130f261341b565b33600083156131985760095460405163079b9d7760e21b81526001600160a01b0390911690631e6e75dc9061312d9085908990600401614190565b600060405180830381600087803b15801561314757600080fd5b505af115801561315b573d6000803e3d6000fd5b5050506001600160a01b038316600090815260156020526040812060058054919450889350919061318d9084906141a9565b909155506132309050565b600954604051631095e8b160e31b81526001600160a01b03909116906384af4588906131ca9085908990600401614190565b600060405180830381600087803b1580156131e457600080fd5b505af11580156131f8573d6000803e3d6000fd5b5050506001600160a01b038316600090815260146020526040812060048054919450889350919061322a9084906141a9565b90915550505b805415613243576132418285613a70565b505b600061326086836000015461325891906141a9565b866000613461565b9050816002015481613272919061417d565b6003600082825461328391906141a9565b909155505081548690839060009061329c9084906141a9565b90915550506003820180546fffffffffffffffffffffffffffffffff1916426001600160801b0316179055600282018190556132d78161349a565b600183018190558254604080519182526020820192909252861515918101919091526001600160a01b038416907fd0f836e593c496b2857b30a01b4268b1ae280ad2545285f4cadf3fe26c00763b90606001611cbf565b61333661341b565b6001546001146133585760405162461bcd60e51b8152600401610ab49061410a565b600260015561336633613bf4565b5060018055565b6133a1604051806080016040528060008152602001600081526020016000815260200160006001600160801b031681525090565b816133c3576001600160a01b03831660009081526014602052604090206133dc565b6001600160a01b03831660009081526015602052604090205b6040805160808101825282548152600183015460208201526002830154918101919091526003909101546001600160801b031660608201529392505050565b60005460ff16156113885760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ab4565b6000821561348d57816134805760125461347b9085614144565b61309a565b60135461347b9085614144565b60115461309a9085614144565b6000670de0b6b3a7640000600654836134b39190614144565b611f18919061415b565b600080670de0b6b3a764000060065484602001516134db9190614144565b6134e5919061415b565b905082606001518110613506576060830151613501908261417d565b613509565b60005b9392505050565b336000805b84518110156136ef57600085828151811061353257613532614210565b602002602001015190506000600a6000866001600160a01b03166001600160a01b03168152602001908152602001600020828154811061357457613574614210565b9060005260206000209060080201905085156135df57600781015460ff16156135df5760405162461bcd60e51b815260206004820181905260248201527f5374616b652068617320616c7265616479206265656e2077697468647261776e6044820152606401610ab4565b6007810154610100900460ff16156136395760405162461bcd60e51b815260206004820152601860248201527f5374616b6520686173206265656e2063616e63656c6c656400000000000000006044820152606401610ab4565b604080516101208101825282548152600183015460208201526002830154918101919091526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460ff808216151560e084015261010091829004161515908201526000906136b1906134bd565b9050808260030160008282546136c791906141a9565b909155506136d7905081866141a9565b945050505080806136e790614226565b915050613515565b508060026000828254613702919061417d565b90915550506001600160a01b0382166000908152600c60205260408120805483929061372f9084906141a9565b9091555050801561379f576009546040516301e2206160e11b81526001600160a01b03909116906303c440c29061376c9085908590600401614190565b600060405180830381600087803b15801561378657600080fd5b505af115801561379a573d6000803e3d6000fd5b505050505b816001600160a01b03167f94dcc76e9211fa75425c6978d70f34a2182dee339d4aa4f9d0a0351f62c769e382866040516137da929190614292565b60405180910390a250505050565b6137f0613db3565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382166000908152600b60205260408120805490915b81811015613908578383828154811061387257613872614210565b9060005260206000200154036138f6578261388e60018461417d565b8154811061389e5761389e614210565b90600052602060002001548382815481106138bb576138bb614210565b9060005260206000200181905550828054806138d9576138d96142ab565b600190038181906000526020600020016000905590555050505050565b8061390081614226565b915050613857565b5050505050565b6000670de0b6b3a7640000600754836134b39190614144565b6000806201518083608001514261393f919061417d565b613949919061415b565b9050600062015180600d60010154613961919061415b565b905080821015613975575060009392505050565b8360400151846080015161398991906141a9565b4211156139a6576201518084604001516139a3919061415b565b91505b600f546139b3828461417d565b60a086015186516139c4919061417d565b6139ce9190614144565b6139d8919061415b565b8460a0015161309a91906141a9565b6139ef61341b565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861381d3390565b6000670de0b6b3a76400006006548360400151613a419190614144565b613a4b919061415b565b90508160200151811015613a6157506000919050565b6020820151611f18908261417d565b60008082613a95576001600160a01b0384166000908152601460205260409020613aae565b6001600160a01b03841660009081526015602052604090205b60408051608081018252825481526001830154602082015260028301549181019190915260038201546001600160801b03166060820152909150613af190613a24565b915081600003613b05576000915050611f18565b6009546040516301e2206160e11b81526001600160a01b03909116906303c440c290613b379087908690600401614190565b600060405180830381600087803b158015613b5157600080fd5b505af1158015613b65573d6000803e3d6000fd5b50505050613b76816002015461349a565b60018201556001600160a01b0384166000908152600c602052604081208054849290613ba39084906141a9565b90915550506040805183815284151560208201526001600160a01b038616917feafb3ef7cb9229547fa473df9e43073744d337e19e2e548fa289a2747abeddc7910160405180910390a25092915050565b6001600160a01b03811660009081526015602090815260408083206014835281842082516080810184528254815260018301549481019490945260028201549284019290925260038101546001600160801b0316606084015291613c5790613a24565b60408051608081018252835481526001840154602082015260028401549181019190915260038301546001600160801b03166060820152909350613c9a90613a24565b613ca490846141a9565b925082600003613cb8575060009392505050565b6009546040516301e2206160e11b81526001600160a01b03909116906303c440c290613cea9087908790600401614190565b600060405180830381600087803b158015613d0457600080fd5b505af1158015613d18573d6000803e3d6000fd5b50505050613d29826002015461349a565b60018301556002810154613d3c9061349a565b60018201556001600160a01b0384166000908152600c602052604081208054859290613d699084906141a9565b90915550506040518381526001600160a01b038516907f39f1bc8a3004d8c2a2e71c312c419cafba6747f8552f82ba2c5fb5cc92d263189060200160405180910390a25050919050565b60005460ff166113885760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610ab4565b604051806101200160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b60405180608001604052806004906020820280368337509192915050565b6001600160a01b0381168114613e7f57600080fd5b50565b600060208284031215613e9457600080fd5b813561350981613e6a565b600081518084526020808501945080840160005b83811015613ecf57815187529582019590820190600101613eb3565b509495945050505050565b602081526000611f156020830184613e9f565b60008060408385031215613f0057600080fd5b50508035926020909101359150565b60008060008060808587031215613f2557600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215613f5357600080fd5b5035919050565b60008083601f840112613f6c57600080fd5b50813567ffffffffffffffff811115613f8457600080fd5b6020830191508360208260051b8501011115613f9f57600080fd5b9250929050565b60008060208385031215613fb957600080fd5b823567ffffffffffffffff811115613fd057600080fd5b613fdc85828601613f5a565b90969095509350505050565b60008060408385031215613ffb57600080fd5b823561400681613e6a565b946020939093013593505050565b8015158114613e7f57600080fd5b6000806040838503121561403557600080fd5b823561404081613e6a565b9150602083013561405081614014565b809150509250929050565b60008060006040848603121561407057600080fd5b833561407b81613e6a565b9250602084013567ffffffffffffffff81111561409757600080fd5b6140a386828701613f5a565b9497909650939450505050565b600080604083850312156140c357600080fd5b82359150602083013561405081614014565b6020808252818101527f616d6f756e74206d7573742062652067726561746572207468616e207a65726f604082015260600190565b6020808252600a90820152695245454e5452414e435960b01b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417611f1857611f1861412e565b60008261417857634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115611f1857611f1861412e565b6001600160a01b03929092168252602082015260400190565b80820180821115611f1857611f1861412e565b6000602082840312156141ce57600080fd5b815161350981614014565b6020808252601a908201527f466f7262696464656e3a204f6e6c7920476f7665726e616e6365000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6000600182016142385761423861412e565b5060010190565b86815260a060208201819052810185905260006001600160fb1b0386111561426657600080fd5b8560051b808860c0850137604083019590955250606081019290925260808201520160c0019392505050565b82815260406020820152600061309a6040830184613e9f565b634e487b7160e01b600052603160045260246000fdfea26469706673582212209db504b7d6c99067ebeb7f431e241e251bb0af51bbc6b0ab5b2163104376fe7064736f6c63430008130033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000008cca793d0ec8c61f156cd4738455ab682554f4180000000000000000000000009ad41cd4f7434d33c30062301a303a9b42111d45

-----Decoded View---------------
Arg [0] : _vaultRegistry (address): 0x8Cca793D0ec8C61f156cD4738455ab682554f418
Arg [1] : _timelock (address): 0x9ad41cD4F7434D33C30062301a303A9b42111D45

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000008cca793d0ec8c61f156cd4738455ab682554f418
Arg [1] : 0000000000000000000000009ad41cd4f7434d33c30062301a303a9b42111d45


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.