Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
Latest 25 from a total of 2,808 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw | 20634328 | 15 hrs ago | IN | 0 ETH | 0.00040535 | ||||
Withdraw Request | 20632876 | 20 hrs ago | IN | 0 ETH | 0.00006977 | ||||
Withdraw Request | 20595488 | 6 days ago | IN | 0 ETH | 0.00006013 | ||||
Withdraw | 20585939 | 7 days ago | IN | 0 ETH | 0.00021356 | ||||
Withdraw Request | 20583506 | 7 days ago | IN | 0 ETH | 0.00007876 | ||||
Claim | 20563031 | 10 days ago | IN | 0 ETH | 0.00010409 | ||||
Claim | 20562816 | 10 days ago | IN | 0 ETH | 0.0001246 | ||||
Claim | 20562682 | 10 days ago | IN | 0 ETH | 0.00006871 | ||||
Withdraw Request | 20546284 | 12 days ago | IN | 0 ETH | 0.00003527 | ||||
Withdraw Request | 20535904 | 14 days ago | IN | 0 ETH | 0.0002362 | ||||
Withdraw Request | 20522810 | 16 days ago | IN | 0 ETH | 0.00005017 | ||||
Withdraw Request | 20507007 | 18 days ago | IN | 0 ETH | 0.00009912 | ||||
Withdraw | 20506197 | 18 days ago | IN | 0 ETH | 0.0002363 | ||||
Withdraw | 20463986 | 24 days ago | IN | 0 ETH | 0.00271119 | ||||
Withdraw | 20462795 | 24 days ago | IN | 0 ETH | 0.00778258 | ||||
Withdraw Request | 20455826 | 25 days ago | IN | 0 ETH | 0.0001344 | ||||
Withdraw | 20455823 | 25 days ago | IN | 0 ETH | 0.00045643 | ||||
Withdraw Request | 20452990 | 25 days ago | IN | 0 ETH | 0.00006133 | ||||
Withdraw | 20451985 | 26 days ago | IN | 0 ETH | 0.00025689 | ||||
Claim | 20433230 | 28 days ago | IN | 0 ETH | 0.00014889 | ||||
Withdraw | 20432360 | 28 days ago | IN | 0 ETH | 0.0005083 | ||||
Withdraw | 20430733 | 29 days ago | IN | 0 ETH | 0.0214862 | ||||
Withdraw Request | 20422865 | 30 days ago | IN | 0 ETH | 0.00011447 | ||||
Withdraw Request | 20422659 | 30 days ago | IN | 0 ETH | 0.00011708 | ||||
Claim | 20418361 | 30 days ago | IN | 0 ETH | 0.00012054 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
HATVaults
Compiler Version
v0.8.6+commit.11564f7e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // Disclaimer https://github.com/hats-finance/hats-contracts/blob/main/DISCLAIMER.md pragma solidity 0.8.6; import "./interfaces/ISwapRouter.sol"; import "openzeppelin-solidity/contracts/token/ERC20/utils/SafeERC20.sol"; import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; import "./HATMaster.sol"; import "./tokenlock/ITokenLockFactory.sol"; import "./Governable.sol"; contract HATVaults is Governable, HATMaster { using SafeMath for uint256; using SafeERC20 for IERC20; struct PendingApproval { address beneficiary; uint256 severity; address approver; } struct ClaimReward { uint256 hackerVestedReward; uint256 hackerReward; uint256 committeeReward; uint256 swapAndBurn; uint256 governanceHatReward; uint256 hackerHatReward; } struct PendingRewardsLevels { uint256 timestamp; uint256[] rewardsLevels; } struct GeneralParameters { uint256 hatVestingDuration; uint256 hatVestingPeriods; uint256 withdrawPeriod; uint256 safetyPeriod; //withdraw disable period in seconds uint256 setRewardsLevelsDelay; uint256 withdrawRequestEnablePeriod; uint256 withdrawRequestPendingPeriod; uint256 claimFee; //claim fee in ETH } //pid -> committee address mapping(uint256=>address) public committees; mapping(address => uint256) public swapAndBurns; //hackerAddress ->(token->amount) mapping(address => mapping(address => uint256)) public hackersHatRewards; //token -> amount mapping(address => uint256) public governanceHatRewards; //pid -> PendingApproval mapping(uint256 => PendingApproval) public pendingApprovals; //poolId -> (address -> requestTime) mapping(uint256 => mapping(address => uint256)) public withdrawRequests; //poolId -> PendingRewardsLevels mapping(uint256 => PendingRewardsLevels) public pendingRewardsLevels; mapping(uint256 => bool) public poolDepositPause; GeneralParameters public generalParameters; uint256 internal constant REWARDS_LEVEL_DENOMINATOR = 10000; ITokenLockFactory public immutable tokenLockFactory; ISwapRouter public immutable uniSwapRouter; uint256 public constant MINIMUM_DEPOSIT = 1e6; modifier onlyCommittee(uint256 _pid) { require(committees[_pid] == msg.sender, "only committee"); _; } modifier noPendingApproval(uint256 _pid) { require(pendingApprovals[_pid].beneficiary == address(0), "pending approval exist"); _; } modifier noSafetyPeriod() { //disable withdraw for safetyPeriod (e.g 1 hour) each withdrawPeriod(e.g 11 hours) // solhint-disable-next-line not-rely-on-time require(block.timestamp % (generalParameters.withdrawPeriod + generalParameters.safetyPeriod) < generalParameters.withdrawPeriod, "safety period"); _; } event SetCommittee(uint256 indexed _pid, address indexed _committee); event AddPool(uint256 indexed _pid, uint256 indexed _allocPoint, address indexed _lpToken, address _committee, string _descriptionHash, uint256[] _rewardsLevels, RewardsSplit _rewardsSplit, uint256 _rewardVestingDuration, uint256 _rewardVestingPeriods); event SetPool(uint256 indexed _pid, uint256 indexed _allocPoint, bool indexed _registered, string _descriptionHash); event Claim(address indexed _claimer, string _descriptionHash); event SetRewardsSplit(uint256 indexed _pid, RewardsSplit _rewardsSplit); event SetRewardsLevels(uint256 indexed _pid, uint256[] _rewardsLevels); event PendingRewardsLevelsLog(uint256 indexed _pid, uint256[] _rewardsLevels, uint256 _timeStamp); event SwapAndSend(uint256 indexed _pid, address indexed _beneficiary, uint256 indexed _amountSwaped, uint256 _amountReceived, address _tokenLock); event SwapAndBurn(uint256 indexed _pid, uint256 indexed _amountSwaped, uint256 indexed _amountBurned); event SetVestingParams(uint256 indexed _pid, uint256 indexed _duration, uint256 indexed _periods); event SetHatVestingParams(uint256 indexed _duration, uint256 indexed _periods); event ClaimApprove(address indexed _approver, uint256 indexed _pid, address indexed _beneficiary, uint256 _severity, address _tokenLock, ClaimReward _claimReward); event PendingApprovalLog(uint256 indexed _pid, address indexed _beneficiary, uint256 indexed _severity, address _approver); event WithdrawRequest(uint256 indexed _pid, address indexed _beneficiary, uint256 indexed _withdrawEnableTime); event SetWithdrawSafetyPeriod(uint256 indexed _withdrawPeriod, uint256 indexed _safetyPeriod); event RewardDepositors(uint256 indexed _pid, uint256 indexed _amount); /** * @dev constructor - * @param _rewardsToken the reward token address (HAT) * @param _rewardPerBlock the reward amount per block the contract will reward pools * @param _startBlock start block of of which the contract will start rewarding from. * @param _multiplierPeriod a fix period value. each period will have its own multiplier value. * which set the reward for each period. e.g a value of 100000 means that each such period is 100000 blocks. * @param _hatGovernance the governance address. * Some of the contracts functions are limited only to governance : * addPool,setPool,dismissPendingApprovalClaim,approveClaim, * setHatVestingParams,setVestingParams,setRewardsSplit * @param _uniSwapRouter uni swap v3 router to be used to swap tokens for HAT token. * @param _tokenLockFactory address of the token lock factory to be used * to create a vesting contract for the approved claim reporter. */ constructor( address _rewardsToken, uint256 _rewardPerBlock, uint256 _startBlock, uint256 _multiplierPeriod, address _hatGovernance, ISwapRouter _uniSwapRouter, ITokenLockFactory _tokenLockFactory // solhint-disable-next-line func-visibility ) HATMaster(HATToken(_rewardsToken), _rewardPerBlock, _startBlock, _multiplierPeriod) { Governable.initialize(_hatGovernance); uniSwapRouter = _uniSwapRouter; tokenLockFactory = _tokenLockFactory; generalParameters = GeneralParameters({ hatVestingDuration: 90 days, hatVestingPeriods:90, withdrawPeriod: 11 hours, safetyPeriod: 1 hours, setRewardsLevelsDelay: 2 days, withdrawRequestEnablePeriod: 7 days, withdrawRequestPendingPeriod: 7 days, claimFee: 0 }); } /** * @dev pendingApprovalClaim - called by a committee to set a pending approval claim. * The pending approval need to be approved or dismissed by the hats governance. * This function should be called only on a safety period, where withdrawn is disable. * Upon a call to this function by the committee the pool withdrawn will be disable * till governance will approve or dismiss this pending approval. * @param _pid pool id * @param _beneficiary the approval claim beneficiary * @param _severity approval claim severity */ function pendingApprovalClaim(uint256 _pid, address _beneficiary, uint256 _severity) external onlyCommittee(_pid) noPendingApproval(_pid) { require(_beneficiary != address(0), "beneficiary is zero"); // solhint-disable-next-line not-rely-on-time require(block.timestamp % (generalParameters.withdrawPeriod + generalParameters.safetyPeriod) >= generalParameters.withdrawPeriod, "none safety period"); require(_severity < poolsRewards[_pid].rewardsLevels.length, "_severity is not in the range"); pendingApprovals[_pid] = PendingApproval({ beneficiary: _beneficiary, severity: _severity, approver: msg.sender }); emit PendingApprovalLog(_pid, _beneficiary, _severity, msg.sender); } /** * @dev setWithdrawRequestParams - called by hats governance to set withdraw request params * @param _withdrawRequestPendingPeriod - the time period where the withdraw request is pending. * @param _withdrawRequestEnablePeriod - the time period where the withdraw is enable for a withdraw request. */ function setWithdrawRequestParams(uint256 _withdrawRequestPendingPeriod, uint256 _withdrawRequestEnablePeriod) external onlyGovernance { generalParameters.withdrawRequestPendingPeriod = _withdrawRequestPendingPeriod; generalParameters.withdrawRequestEnablePeriod = _withdrawRequestEnablePeriod; } /** * @dev dismissPendingApprovalClaim - called by hats governance to dismiss a pending approval claim. * @param _pid pool id */ function dismissPendingApprovalClaim(uint256 _pid) external onlyGovernance { delete pendingApprovals[_pid]; } /** * @dev approveClaim - called by hats governance to approve a pending approval claim. * @param _pid pool id */ function approveClaim(uint256 _pid) external onlyGovernance nonReentrant { require(pendingApprovals[_pid].beneficiary != address(0), "no pending approval"); PoolReward storage poolReward = poolsRewards[_pid]; PendingApproval memory pendingApproval = pendingApprovals[_pid]; delete pendingApprovals[_pid]; IERC20 lpToken = poolInfo[_pid].lpToken; ClaimReward memory claimRewards = calcClaimRewards(_pid, pendingApproval.severity); poolInfo[_pid].balance = poolInfo[_pid].balance.sub( claimRewards.hackerReward .add(claimRewards.hackerVestedReward) .add(claimRewards.committeeReward) .add(claimRewards.swapAndBurn) .add(claimRewards.hackerHatReward) .add(claimRewards.governanceHatReward)); address tokenLock; if (claimRewards.hackerVestedReward > 0) { //hacker get its reward to a vesting contract tokenLock = tokenLockFactory.createTokenLock( address(lpToken), 0x000000000000000000000000000000000000dEaD, //this address as owner, so it can do nothing. pendingApproval.beneficiary, claimRewards.hackerVestedReward, // solhint-disable-next-line not-rely-on-time block.timestamp, //start // solhint-disable-next-line not-rely-on-time block.timestamp + poolReward.vestingDuration, //end poolReward.vestingPeriods, 0, //no release start 0, //no cliff ITokenLock.Revocability.Disabled, false ); lpToken.safeTransfer(tokenLock, claimRewards.hackerVestedReward); } lpToken.safeTransfer(pendingApproval.beneficiary, claimRewards.hackerReward); lpToken.safeTransfer(pendingApproval.approver, claimRewards.committeeReward); //storing the amount of token which can be swap and burned so it could be swapAndBurn in a seperate tx. swapAndBurns[address(lpToken)] = swapAndBurns[address(lpToken)].add(claimRewards.swapAndBurn); governanceHatRewards[address(lpToken)] = governanceHatRewards[address(lpToken)].add(claimRewards.governanceHatReward); hackersHatRewards[pendingApproval.beneficiary][address(lpToken)] = hackersHatRewards[pendingApproval.beneficiary][address(lpToken)].add(claimRewards.hackerHatReward); emit ClaimApprove(msg.sender, _pid, pendingApproval.beneficiary, pendingApproval.severity, tokenLock, claimRewards); assert(poolInfo[_pid].balance > 0); } /** * @dev rewardDepositors - add funds to pool to reward depositors. * The funds will be given to depositors pro rata upon withdraw * @param _pid pool id * @param _amount amount to add */ function rewardDepositors(uint256 _pid, uint256 _amount) external { require(poolInfo[_pid].balance.add(_amount).div(MINIMUM_DEPOSIT) < poolInfo[_pid].totalUsersAmount, "amount to reward is too big"); poolInfo[_pid].lpToken.safeTransferFrom(msg.sender, address(this), _amount); poolInfo[_pid].balance = poolInfo[_pid].balance.add(_amount); emit RewardDepositors(_pid, _amount); } /** * @dev setClaimFee - called by hats governance to set claim fee * @param _fee claim fee in ETH */ function setClaimFee(uint256 _fee) external onlyGovernance { generalParameters.claimFee = _fee; } /** * @dev setWithdrawSafetyPeriod - called by hats governance to set Withdraw Period * @param _withdrawPeriod withdraw enable period * @param _safetyPeriod withdraw disable period */ function setWithdrawSafetyPeriod(uint256 _withdrawPeriod, uint256 _safetyPeriod) external onlyGovernance { generalParameters.withdrawPeriod = _withdrawPeriod; generalParameters.safetyPeriod = _safetyPeriod; emit SetWithdrawSafetyPeriod(generalParameters.withdrawPeriod, generalParameters.safetyPeriod); } //_descriptionHash - a hash of an ipfs encrypted file which describe the claim. // this can be use later on by the claimer to prove her claim function claim(string memory _descriptionHash) external payable { if (generalParameters.claimFee > 0) { require(msg.value >= generalParameters.claimFee, "not enough fee payed"); // solhint-disable-next-line indent payable(governance()).transfer(msg.value); } emit Claim(msg.sender, _descriptionHash); } /** * @dev setVestingParams - set pool vesting params for rewarding claim reporter with the pool token * @param _pid pool id * @param _duration duration of the vesting period * @param _periods the vesting periods */ function setVestingParams(uint256 _pid, uint256 _duration, uint256 _periods) external onlyGovernance { require(_duration < 120 days, "vesting duration is too long"); require(_periods > 0, "vesting periods cannot be zero"); require(_duration >= _periods, "vesting duration smaller than periods"); poolsRewards[_pid].vestingDuration = _duration; poolsRewards[_pid].vestingPeriods = _periods; emit SetVestingParams(_pid, _duration, _periods); } /** * @dev setHatVestingParams - set HAT vesting params for rewarding claim reporter with HAT token * the function can be called only by governance. * @param _duration duration of the vesting period * @param _periods the vesting periods */ function setHatVestingParams(uint256 _duration, uint256 _periods) external onlyGovernance { require(_duration < 180 days, "vesting duration is too long"); require(_periods > 0, "vesting periods cannot be zero"); require(_duration >= _periods, "vesting duration smaller than periods"); generalParameters.hatVestingDuration = _duration; generalParameters.hatVestingPeriods = _periods; emit SetHatVestingParams(_duration, _periods); } /** * @dev setRewardsSplit - set the pool token rewards split upon an approval * the function can be called only by governance. * the sum of the rewards split should be less than 10000 (less than 100%) * @param _pid pool id * @param _rewardsSplit split * and sent to the hacker(claim reported) */ function setRewardsSplit(uint256 _pid, RewardsSplit memory _rewardsSplit) external onlyGovernance noPendingApproval(_pid) noSafetyPeriod { validateSplit(_rewardsSplit); poolsRewards[_pid].rewardsSplit = _rewardsSplit; emit SetRewardsSplit(_pid, _rewardsSplit); } /** * @dev setRewardsLevelsDelay - set the timelock delay for setting rewars level * @param _delay time delay */ function setRewardsLevelsDelay(uint256 _delay) external onlyGovernance { require(_delay >= 2 days, "delay is too short"); generalParameters.setRewardsLevelsDelay = _delay; } /** * @dev setPendingRewardsLevels - set pending request to set pool token rewards level. * the reward level represent the percentage of the pool's token which will be split as a reward. * the function can be called only by the pool committee. * cannot be called if there already pending approval. * each level should be less than 10000 * @param _pid pool id * @param _rewardsLevels the reward levels array */ function setPendingRewardsLevels(uint256 _pid, uint256[] memory _rewardsLevels) external onlyCommittee(_pid) noPendingApproval(_pid) { pendingRewardsLevels[_pid].rewardsLevels = checkRewardsLevels(_rewardsLevels); // solhint-disable-next-line not-rely-on-time pendingRewardsLevels[_pid].timestamp = block.timestamp; emit PendingRewardsLevelsLog(_pid, _rewardsLevels, pendingRewardsLevels[_pid].timestamp); } /** * @dev setRewardsLevels - set the pool token rewards level of already pending set rewards level. * see pendingRewardsLevels * the reward level represent the percentage of the pool's token which will be split as a reward. * the function can be called only by the pool committee. * cannot be called if there already pending approval. * each level should be less than 10000 * @param _pid pool id */ function setRewardsLevels(uint256 _pid) external onlyCommittee(_pid) noPendingApproval(_pid) { require(pendingRewardsLevels[_pid].timestamp > 0, "no pending set rewards levels"); // solhint-disable-next-line not-rely-on-time require(block.timestamp - pendingRewardsLevels[_pid].timestamp > generalParameters.setRewardsLevelsDelay, "cannot confirm setRewardsLevels at this time"); poolsRewards[_pid].rewardsLevels = pendingRewardsLevels[_pid].rewardsLevels; delete pendingRewardsLevels[_pid]; emit SetRewardsLevels(_pid, poolsRewards[_pid].rewardsLevels); } /** * @dev committeeCheckIn - committee check in. * deposit is enable only after committee check in * @param _pid pool id */ function committeeCheckIn(uint256 _pid) external onlyCommittee(_pid) { poolsRewards[_pid].committeeCheckIn = true; } /** * @dev setCommittee - set new committee address. * @param _pid pool id * @param _committee new committee address */ function setCommittee(uint256 _pid, address _committee) external { require(_committee != address(0), "committee is zero"); //governance can update committee only if committee was not checked in yet. if (msg.sender == governance() && committees[_pid] != msg.sender) { require(!poolsRewards[_pid].committeeCheckIn, "Committee already checked in"); } else { require(committees[_pid] == msg.sender, "Only committee"); } committees[_pid] = _committee; emit SetCommittee(_pid, _committee); } /** * @dev addPool - only Governance * @param _allocPoint the pool allocation point * @param _lpToken pool token * @param _committee pool committee address * @param _rewardsLevels pool reward levels(sevirities) each level is a number between 0 and 10000. * @param _rewardsSplit pool reward split. each entry is a number between 0 and 10000. total splits should be equal to 10000 * @param _descriptionHash the hash of the pool description. * @param _rewardVestingParams vesting params * _rewardVestingParams[0] - vesting duration * _rewardVestingParams[1] - vesting periods */ function addPool(uint256 _allocPoint, address _lpToken, address _committee, uint256[] memory _rewardsLevels, RewardsSplit memory _rewardsSplit, string memory _descriptionHash, uint256[2] memory _rewardVestingParams) external onlyGovernance { require(_rewardVestingParams[0] < 120 days, "vesting duration is too long"); require(_rewardVestingParams[1] > 0, "vesting periods cannot be zero"); require(_rewardVestingParams[0] >= _rewardVestingParams[1], "vesting duration smaller than periods"); require(_committee != address(0), "committee is zero"); add(_allocPoint, IERC20(_lpToken)); uint256 poolId = poolInfo.length-1; committees[poolId] = _committee; uint256[] memory rewardsLevels = checkRewardsLevels(_rewardsLevels); RewardsSplit memory rewardsSplit = (_rewardsSplit.hackerVestedReward == 0 && _rewardsSplit.hackerReward == 0) ? getDefaultRewardsSplit() : _rewardsSplit; validateSplit(rewardsSplit); poolsRewards[poolId] = PoolReward({ rewardsLevels: rewardsLevels, rewardsSplit: rewardsSplit, committeeCheckIn: false, vestingDuration: _rewardVestingParams[0], vestingPeriods: _rewardVestingParams[1] }); emit AddPool(poolId, _allocPoint, address(_lpToken), _committee, _descriptionHash, rewardsLevels, rewardsSplit, _rewardVestingParams[0], _rewardVestingParams[1]); } /** * @dev setPool * @param _pid the pool id * @param _allocPoint the pool allocation point * @param _registered does this pool is registered (default true). * @param _depositPause pause pool deposit (default false). * This parameter can be used by the UI to include or exclude the pool * @param _descriptionHash the hash of the pool description. */ function setPool(uint256 _pid, uint256 _allocPoint, bool _registered, bool _depositPause, string memory _descriptionHash) external onlyGovernance { require(poolInfo[_pid].lpToken != IERC20(address(0)), "pool does not exist"); set(_pid, _allocPoint); poolDepositPause[_pid] = _depositPause; emit SetPool(_pid, _allocPoint, _registered, _descriptionHash); } /** * @dev swapBurnSend swap lptoken to HAT. * send to beneficiary and governance its hats rewards . * burn the rest of HAT. * only governance are authorized to call this function. * @param _pid the pool id * @param _beneficiary beneficiary * @param _amountOutMinimum minimum output of HATs at swap * @param _fees the fees for the multi path swap **/ function swapBurnSend(uint256 _pid, address _beneficiary, uint256 _amountOutMinimum, uint24[2] memory _fees) external onlyGovernance { IERC20 token = poolInfo[_pid].lpToken; uint256 amountToSwapAndBurn = swapAndBurns[address(token)]; uint256 amountForHackersHatRewards = hackersHatRewards[_beneficiary][address(token)]; uint256 amount = amountToSwapAndBurn.add(amountForHackersHatRewards).add(governanceHatRewards[address(token)]); require(amount > 0, "amount is zero"); swapAndBurns[address(token)] = 0; governanceHatRewards[address(token)] = 0; hackersHatRewards[_beneficiary][address(token)] = 0; uint256 hatsReceived = swapTokenForHAT(amount, token, _fees, _amountOutMinimum); uint256 burntHats = hatsReceived.mul(amountToSwapAndBurn).div(amount); if (burntHats > 0) { HAT.burn(burntHats); } emit SwapAndBurn(_pid, amount, burntHats); address tokenLock; uint256 hackerReward = hatsReceived.mul(amountForHackersHatRewards).div(amount); if (hackerReward > 0) { //hacker get its reward via vesting contract tokenLock = tokenLockFactory.createTokenLock( address(HAT), 0x000000000000000000000000000000000000dEaD, //this address as owner, so it can do nothing. _beneficiary, hackerReward, // solhint-disable-next-line not-rely-on-time block.timestamp, //start // solhint-disable-next-line not-rely-on-time block.timestamp + generalParameters.hatVestingDuration, //end generalParameters.hatVestingPeriods, 0, //no release start 0, //no cliff ITokenLock.Revocability.Disabled, true ); HAT.transfer(tokenLock, hackerReward); } emit SwapAndSend(_pid, _beneficiary, amount, hackerReward, tokenLock); HAT.transfer(governance(), hatsReceived.sub(hackerReward).sub(burntHats)); } /** * @dev withdrawRequest submit a withdraw request * @param _pid the pool id **/ function withdrawRequest(uint256 _pid) external { // solhint-disable-next-line not-rely-on-time require(block.timestamp > withdrawRequests[_pid][msg.sender] + generalParameters.withdrawRequestEnablePeriod, "pending withdraw request exist"); // solhint-disable-next-line not-rely-on-time withdrawRequests[_pid][msg.sender] = block.timestamp + generalParameters.withdrawRequestPendingPeriod; emit WithdrawRequest(_pid, msg.sender, withdrawRequests[_pid][msg.sender]); } /** * @dev deposit deposit to pool * @param _pid the pool id * @param _amount amount of pool's token to deposit **/ function deposit(uint256 _pid, uint256 _amount) external { require(!poolDepositPause[_pid], "deposit paused"); require(_amount >= MINIMUM_DEPOSIT, "amount less than 1e6"); //clear withdraw request withdrawRequests[_pid][msg.sender] = 0; _deposit(_pid, _amount); } /** * @dev withdraw - withdraw user's pool share. * user need first to submit a withdraw request. * @param _pid the pool id * @param _shares amount of shares user wants to withdraw **/ function withdraw(uint256 _pid, uint256 _shares) external { checkWithdrawRequest(_pid); _withdraw(_pid, _shares); } /** * @dev emergencyWithdraw withdraw all user's pool share without claim for reward. * user need first to submit a withdraw request. * @param _pid the pool id **/ function emergencyWithdraw(uint256 _pid) external { checkWithdrawRequest(_pid); _emergencyWithdraw(_pid); } function getPoolRewardsLevels(uint256 _pid) external view returns(uint256[] memory) { return poolsRewards[_pid].rewardsLevels; } function getPoolRewards(uint256 _pid) external view returns(PoolReward memory) { return poolsRewards[_pid]; } // GET INFO for UI /** * @dev getRewardPerBlock return the current pool reward per block * @param _pid1 the pool id. * if _pid1 = 0 , it return the current block reward for whole pools. * otherwise it return the current block reward for _pid1-1. * @return rewardPerBlock **/ function getRewardPerBlock(uint256 _pid1) external view returns (uint256) { if (_pid1 == 0) { return getRewardForBlocksRange(block.number-1, block.number, 1, 1); } else { return getRewardForBlocksRange(block.number-1, block.number, poolInfo[_pid1 - 1].allocPoint, globalPoolUpdates[globalPoolUpdates.length-1].totalAllocPoint); } } function pendingReward(uint256 _pid, address _user) external view returns (uint256) { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_user]; uint256 rewardPerShare = pool.rewardPerShare; if (block.number > pool.lastRewardBlock && pool.totalUsersAmount > 0) { uint256 reward = calcPoolReward(_pid, pool.lastRewardBlock, globalPoolUpdates.length-1); rewardPerShare = rewardPerShare.add(reward.mul(1e12).div(pool.totalUsersAmount)); } return user.amount.mul(rewardPerShare).div(1e12).sub(user.rewardDebt); } function getGlobalPoolUpdatesLength() external view returns (uint256) { return globalPoolUpdates.length; } function getStakedAmount(uint _pid, address _user) external view returns (uint256) { UserInfo storage user = userInfo[_pid][_user]; return user.amount; } function poolLength() external view returns (uint256) { return poolInfo.length; } function calcClaimRewards(uint256 _pid, uint256 _severity) public view returns(ClaimReward memory claimRewards) { uint256 totalSupply = poolInfo[_pid].balance; require(totalSupply > 0, "totalSupply is zero"); require(_severity < poolsRewards[_pid].rewardsLevels.length, "_severity is not in the range"); //hackingRewardAmount uint256 claimRewardAmount = totalSupply.mul(poolsRewards[_pid].rewardsLevels[_severity]); claimRewards.hackerVestedReward = claimRewardAmount.mul(poolsRewards[_pid].rewardsSplit.hackerVestedReward) .div(REWARDS_LEVEL_DENOMINATOR*REWARDS_LEVEL_DENOMINATOR); claimRewards.hackerReward = claimRewardAmount.mul(poolsRewards[_pid].rewardsSplit.hackerReward) .div(REWARDS_LEVEL_DENOMINATOR*REWARDS_LEVEL_DENOMINATOR); claimRewards.committeeReward = claimRewardAmount.mul(poolsRewards[_pid].rewardsSplit.committeeReward) .div(REWARDS_LEVEL_DENOMINATOR*REWARDS_LEVEL_DENOMINATOR); claimRewards.swapAndBurn = claimRewardAmount.mul(poolsRewards[_pid].rewardsSplit.swapAndBurn) .div(REWARDS_LEVEL_DENOMINATOR*REWARDS_LEVEL_DENOMINATOR); claimRewards.governanceHatReward = claimRewardAmount.mul(poolsRewards[_pid].rewardsSplit.governanceHatReward) .div(REWARDS_LEVEL_DENOMINATOR*REWARDS_LEVEL_DENOMINATOR); claimRewards.hackerHatReward = claimRewardAmount.mul(poolsRewards[_pid].rewardsSplit.hackerHatReward) .div(REWARDS_LEVEL_DENOMINATOR*REWARDS_LEVEL_DENOMINATOR); } function getDefaultRewardsSplit() public pure returns (RewardsSplit memory) { return RewardsSplit({ hackerVestedReward: 6000, hackerReward: 2000, committeeReward: 500, swapAndBurn: 0, governanceHatReward: 1000, hackerHatReward: 500 }); } function validateSplit(RewardsSplit memory _rewardsSplit) internal pure { require(_rewardsSplit.hackerVestedReward .add(_rewardsSplit.hackerReward) .add(_rewardsSplit.committeeReward) .add(_rewardsSplit.swapAndBurn) .add(_rewardsSplit.governanceHatReward) .add(_rewardsSplit.hackerHatReward) == REWARDS_LEVEL_DENOMINATOR, "total split % should be 10000"); } function checkWithdrawRequest(uint256 _pid) internal noPendingApproval(_pid) noSafetyPeriod { // solhint-disable-next-line not-rely-on-time require(block.timestamp > withdrawRequests[_pid][msg.sender] && // solhint-disable-next-line not-rely-on-time block.timestamp < withdrawRequests[_pid][msg.sender] + generalParameters.withdrawRequestEnablePeriod, "withdraw request not valid"); withdrawRequests[_pid][msg.sender] = 0; } function swapTokenForHAT(uint256 _amount, IERC20 _token, uint24[2] memory _fees, uint256 _amountOutMinimum) internal returns (uint256 hatsReceived) { if (address(_token) == address(HAT)) { return _amount; } require(_token.approve(address(uniSwapRouter), _amount), "token approve failed"); uint256 hatBalanceBefore = HAT.balanceOf(address(this)); address weth = uniSwapRouter.WETH9(); bytes memory path; if (address(_token) == weth) { path = abi.encodePacked(address(_token), _fees[0], address(HAT)); } else { path = abi.encodePacked(address(_token), _fees[0], weth, _fees[1], address(HAT)); } hatsReceived = uniSwapRouter.exactInput(ISwapRouter.ExactInputParams({ path: path, recipient: address(this), // solhint-disable-next-line not-rely-on-time deadline: block.timestamp, amountIn: _amount, amountOutMinimum: _amountOutMinimum })); require(HAT.balanceOf(address(this)) - hatBalanceBefore >= _amountOutMinimum, "wrong amount received"); } /** * @dev checkRewardsLevels - check rewards levels. * each level should be less than 10000 * if _rewardsLevels length is 0 a default reward levels will be return * default reward levels = [2000, 4000, 6000, 8000] * @param _rewardsLevels the reward levels array * @return rewardsLevels */ function checkRewardsLevels(uint256[] memory _rewardsLevels) private pure returns (uint256[] memory rewardsLevels) { uint256 i; if (_rewardsLevels.length == 0) { rewardsLevels = new uint256[](4); for (i; i < 4; i++) { //defaultRewardLevels = [2000, 4000, 6000, 8000]; rewardsLevels[i] = 2000*(i+1); } } else { for (i; i < _rewardsLevels.length; i++) { require(_rewardsLevels[i] < REWARDS_LEVEL_DENOMINATOR, "reward level can not be more than 10000"); } rewardsLevels = _rewardsLevels; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.6; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface ISwapRouter { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); // solhint-disable-next-line func-name-mixedcase function WETH9() external pure returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The defaut value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor (string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); _approve(sender, _msgSender(), currentAllowance - amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); _approve(_msgSender(), spender, currentAllowance - subtractedValue); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); _balances[sender] = senderBalance - amount; _balances[recipient] += amount; emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); _balances[account] = accountBalance - amount; _totalSupply -= amount; emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } }
// SPDX-License-Identifier: MIT // Disclaimer https://github.com/hats-finance/hats-contracts/blob/main/DISCLAIMER.md pragma solidity 0.8.6; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "openzeppelin-solidity/contracts/token/ERC20/utils/SafeERC20.sol"; import "openzeppelin-solidity/contracts/utils/math/SafeMath.sol"; import "./HATToken.sol"; import "openzeppelin-solidity/contracts/security/ReentrancyGuard.sol"; contract HATMaster is ReentrancyGuard { using SafeMath for uint256; using SafeERC20 for IERC20; struct UserInfo { uint256 amount; // The user share of the pool based on the amount of lpToken the user has provided. uint256 rewardDebt; // Reward debt. See explanation below. // // We do some fancy math here. Basically, any point in time, the amount of HATs // entitled to a user but is pending to be distributed is: // // pending reward = (user.amount * pool.rewardPerShare) - user.rewardDebt // // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: // 1. The pool's `rewardPerShare` (and `lastRewardBlock`) gets updated. // 2. User receives the pending reward sent to his/her address. // 3. User's `amount` gets updated. // 4. User's `rewardDebt` gets updated. } struct PoolUpdate { uint256 blockNumber;// update blocknumber uint256 totalAllocPoint; //totalAllocPoint } struct RewardsSplit { //the percentage of the total reward to reward the hacker via vesting contract(claim reported) uint256 hackerVestedReward; //the percentage of the total reward to reward the hacker(claim reported) uint256 hackerReward; // the percentage of the total reward to be sent to the committee uint256 committeeReward; // the percentage of the total reward to be swap to HAT and to be burned uint256 swapAndBurn; // the percentage of the total reward to be swap to HAT and sent to governance uint256 governanceHatReward; // the percentage of the total reward to be swap to HAT and sent to the hacker uint256 hackerHatReward; } // Info of each pool. struct PoolInfo { IERC20 lpToken; uint256 allocPoint; uint256 lastRewardBlock; uint256 rewardPerShare; uint256 totalUsersAmount; uint256 lastProcessedTotalAllocPoint; uint256 balance; } // Info of each pool. struct PoolReward { RewardsSplit rewardsSplit; uint256[] rewardsLevels; bool committeeCheckIn; uint256 vestingDuration; uint256 vestingPeriods; } HATToken public immutable HAT; uint256 public immutable REWARD_PER_BLOCK; uint256 public immutable START_BLOCK; uint256 public immutable MULTIPLIER_PERIOD; // Info of each pool. PoolInfo[] public poolInfo; PoolUpdate[] public globalPoolUpdates; mapping(address => uint256) public poolId1; // poolId1 count from 1, subtraction 1 before using with poolInfo // Info of each user that stakes LP tokens. pid => user address => info mapping (uint256 => mapping (address => UserInfo)) public userInfo; //pid -> PoolReward mapping (uint256=>PoolReward) internal poolsRewards; event Deposit(address indexed user, uint256 indexed pid, uint256 amount); event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount); event SendReward(address indexed user, uint256 indexed pid, uint256 amount, uint256 requestedAmount); event MassUpdatePools(uint256 _fromPid, uint256 _toPid); constructor( HATToken _hat, uint256 _rewardPerBlock, uint256 _startBlock, uint256 _multiplierPeriod // solhint-disable-next-line func-visibility ) { HAT = _hat; REWARD_PER_BLOCK = _rewardPerBlock; START_BLOCK = _startBlock; MULTIPLIER_PERIOD = _multiplierPeriod; } /** * @dev massUpdatePools - Update reward variables for all pools * Be careful of gas spending! * @param _fromPid update pools range from this pool id * @param _toPid update pools range to this pool id */ function massUpdatePools(uint256 _fromPid, uint256 _toPid) external { require(_toPid <= poolInfo.length, "pool range is too big"); require(_fromPid <= _toPid, "invalid pool range"); for (uint256 pid = _fromPid; pid < _toPid; ++pid) { updatePool(pid); } emit MassUpdatePools(_fromPid, _toPid); } function claimReward(uint256 _pid) external { _deposit(_pid, 0); } function updatePool(uint256 _pid) public { PoolInfo storage pool = poolInfo[_pid]; uint256 lastRewardBlock = pool.lastRewardBlock; if (block.number <= lastRewardBlock) { return; } uint256 totalUsersAmount = pool.totalUsersAmount; uint256 lastPoolUpdate = globalPoolUpdates.length-1; if (totalUsersAmount == 0) { pool.lastRewardBlock = block.number; pool.lastProcessedTotalAllocPoint = lastPoolUpdate; return; } uint256 reward = calcPoolReward(_pid, lastRewardBlock, lastPoolUpdate); uint256 amountCanMint = HAT.minters(address(this)); reward = amountCanMint < reward ? amountCanMint : reward; if (reward > 0) { HAT.mint(address(this), reward); } pool.rewardPerShare = pool.rewardPerShare.add(reward.mul(1e12).div(totalUsersAmount)); pool.lastRewardBlock = block.number; pool.lastProcessedTotalAllocPoint = lastPoolUpdate; } /** * @dev getMultiplier - multiply blocks with relevant multiplier for specific range * @param _from range's from block * @param _to range's to block * will revert if from < START_BLOCK or _to < _from */ function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256 result) { uint256[25] memory rewardMultipliers = [uint256(4413), 4413, 8825, 7788, 6873, 6065, 5353, 4724, 4169, 3679, 3247, 2865, 2528, 2231, 1969, 1738, 1534, 1353, 1194, 1054, 930, 821, 724, 639, 0]; uint256 max = rewardMultipliers.length; uint256 i = (_from - START_BLOCK) / MULTIPLIER_PERIOD + 1; for (; i < max; i++) { uint256 endBlock = MULTIPLIER_PERIOD * i + START_BLOCK; if (_to <= endBlock) { break; } result += (endBlock - _from) * rewardMultipliers[i-1]; _from = endBlock; } result += (_to - _from) * rewardMultipliers[i > max ? (max-1) : (i-1)]; } function getRewardForBlocksRange(uint256 _from, uint256 _to, uint256 _allocPoint, uint256 _totalAllocPoint) public view returns (uint256 reward) { if (_totalAllocPoint > 0) { reward = getMultiplier(_from, _to).mul(REWARD_PER_BLOCK).mul(_allocPoint).div(_totalAllocPoint).div(100); } } /** * @dev calcPoolReward - * calculate rewards for a pool by iterating over the history of totalAllocPoints updates. * and sum up all rewards periods from pool.lastRewardBlock till current block number. * @param _pid pool id * @param _from block starting calculation * @param _lastPoolUpdate lastPoolUpdate * @return reward */ function calcPoolReward(uint256 _pid, uint256 _from, uint256 _lastPoolUpdate) public view returns(uint256 reward) { uint256 poolAllocPoint = poolInfo[_pid].allocPoint; uint256 i = poolInfo[_pid].lastProcessedTotalAllocPoint; for (; i < _lastPoolUpdate; i++) { uint256 nextUpdateBlock = globalPoolUpdates[i+1].blockNumber; reward = reward.add(getRewardForBlocksRange(_from, nextUpdateBlock, poolAllocPoint, globalPoolUpdates[i].totalAllocPoint)); _from = nextUpdateBlock; } return reward.add(getRewardForBlocksRange(_from, block.number, poolAllocPoint, globalPoolUpdates[i].totalAllocPoint)); } function _deposit(uint256 _pid, uint256 _amount) internal nonReentrant { require(poolsRewards[_pid].committeeCheckIn, "committee not checked in yet"); PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; updatePool(_pid); if (user.amount > 0) { uint256 pending = user.amount.mul(pool.rewardPerShare).div(1e12).sub(user.rewardDebt); if (pending > 0) { safeTransferReward(msg.sender, pending, _pid); } } if (_amount > 0) { uint256 lpSupply = pool.balance; pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount); pool.balance = pool.balance.add(_amount); uint256 factoredAmount = _amount; if (pool.totalUsersAmount > 0) { factoredAmount = pool.totalUsersAmount.mul(_amount).div(lpSupply); } user.amount = user.amount.add(factoredAmount); pool.totalUsersAmount = pool.totalUsersAmount.add(factoredAmount); } user.rewardDebt = user.amount.mul(pool.rewardPerShare).div(1e12); emit Deposit(msg.sender, _pid, _amount); } function _withdraw(uint256 _pid, uint256 _amount) internal nonReentrant { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; require(user.amount >= _amount, "withdraw: not enough user balance"); updatePool(_pid); uint256 pending = user.amount.mul(pool.rewardPerShare).div(1e12).sub(user.rewardDebt); if (pending > 0) { safeTransferReward(msg.sender, pending, _pid); } if (_amount > 0) { user.amount = user.amount.sub(_amount); uint256 amountToWithdraw = _amount.mul(pool.balance).div(pool.totalUsersAmount); pool.balance = pool.balance.sub(amountToWithdraw); pool.lpToken.safeTransfer(msg.sender, amountToWithdraw); pool.totalUsersAmount = pool.totalUsersAmount.sub(_amount); } user.rewardDebt = user.amount.mul(pool.rewardPerShare).div(1e12); emit Withdraw(msg.sender, _pid, _amount); } // Withdraw without caring about rewards. EMERGENCY ONLY. function _emergencyWithdraw(uint256 _pid) internal { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; require(user.amount > 0, "user.amount = 0"); uint256 factoredBalance = user.amount.mul(pool.balance).div(pool.totalUsersAmount); pool.totalUsersAmount = pool.totalUsersAmount.sub(user.amount); user.amount = 0; user.rewardDebt = 0; pool.balance = pool.balance.sub(factoredBalance); pool.lpToken.safeTransfer(msg.sender, factoredBalance); emit EmergencyWithdraw(msg.sender, _pid, factoredBalance); } // -------- For manage pool --------- function add(uint256 _allocPoint, IERC20 _lpToken) internal { require(poolId1[address(_lpToken)] == 0, "HATMaster::add: lpToken is already in pool"); poolId1[address(_lpToken)] = poolInfo.length + 1; uint256 lastRewardBlock = block.number > START_BLOCK ? block.number : START_BLOCK; uint256 totalAllocPoint = (globalPoolUpdates.length == 0) ? _allocPoint : globalPoolUpdates[globalPoolUpdates.length-1].totalAllocPoint.add(_allocPoint); if (globalPoolUpdates.length > 0 && globalPoolUpdates[globalPoolUpdates.length-1].blockNumber == block.number) { //already update in this block globalPoolUpdates[globalPoolUpdates.length-1].totalAllocPoint = totalAllocPoint; } else { globalPoolUpdates.push(PoolUpdate({ blockNumber: block.number, totalAllocPoint: totalAllocPoint })); } poolInfo.push(PoolInfo({ lpToken: _lpToken, allocPoint: _allocPoint, lastRewardBlock: lastRewardBlock, rewardPerShare: 0, totalUsersAmount: 0, lastProcessedTotalAllocPoint: globalPoolUpdates.length-1, balance: 0 })); } function set(uint256 _pid, uint256 _allocPoint) internal { updatePool(_pid); uint256 totalAllocPoint = globalPoolUpdates[globalPoolUpdates.length-1].totalAllocPoint .sub(poolInfo[_pid].allocPoint).add(_allocPoint); if (globalPoolUpdates[globalPoolUpdates.length-1].blockNumber == block.number) { //already update in this block globalPoolUpdates[globalPoolUpdates.length-1].totalAllocPoint = totalAllocPoint; } else { globalPoolUpdates.push(PoolUpdate({ blockNumber: block.number, totalAllocPoint: totalAllocPoint })); } poolInfo[_pid].allocPoint = _allocPoint; } // Safe HAT transfer function, just in case if rounding error causes pool to not have enough HATs. function safeTransferReward(address _to, uint256 _amount, uint256 _pid) internal { uint256 hatBalance = HAT.balanceOf(address(this)); if (_amount > hatBalance) { HAT.transfer(_to, hatBalance); emit SendReward(_to, _pid, hatBalance, _amount); } else { HAT.transfer(_to, _amount); emit SendReward(_to, _pid, _amount, _amount); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.6; import "./ITokenLock.sol"; interface ITokenLockFactory { // -- Factory -- function setMasterCopy(address _masterCopy) external; function createTokenLock( address _token, address _owner, address _beneficiary, uint256 _managedAmount, uint256 _startTime, uint256 _endTime, uint256 _periods, uint256 _releaseStartTime, uint256 _vestingCliffTime, ITokenLock.Revocability _revocable, bool _canDelegate ) external returns(address contractAddress); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.6; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an governance) that can be granted exclusive access to * specific functions. * * The governance account will be passed on initialization of the contract. This * can later be changed with {setPendingGovernance and then transferGovernorship after 2 days}. * * This module is used through inheritance. It will make available the modifier * `onlyGovernance`, which can be applied to your functions to restrict their use to * the governance. */ contract Governable { address private _governance; address public governancePending; uint256 public setGovernancePendingAt; uint256 public constant TIME_LOCK_DELAY = 2 days; /// @notice An event thats emitted when a new governance address is set event GovernorshipTransferred(address indexed _previousGovernance, address indexed _newGovernance); /// @notice An event thats emitted when a new governance address is pending event GovernancePending(address indexed _previousGovernance, address indexed _newGovernance, uint256 _at); /** * @dev Throws if called by any account other than the governance. */ modifier onlyGovernance() { require(msg.sender == _governance, "only governance"); _; } /** * @dev setPendingGovernance set a pending governance address. * NOTE: transferGovernorship can be called after a time delay of 2 days. */ function setPendingGovernance(address _newGovernance) external onlyGovernance { require(_newGovernance != address(0), "Governable:new governance is the zero address"); governancePending = _newGovernance; // solhint-disable-next-line not-rely-on-time setGovernancePendingAt = block.timestamp; emit GovernancePending(_governance, _newGovernance, setGovernancePendingAt); } /** * @dev transferGovernorship transfer governorship to the pending governance address. * NOTE: transferGovernorship can be called after a time delay of 2 days from the latest setPendingGovernance. */ function transferGovernorship() external onlyGovernance { require(setGovernancePendingAt > 0, "Governable: no pending governance"); // solhint-disable-next-line not-rely-on-time require(block.timestamp - setGovernancePendingAt > TIME_LOCK_DELAY, "Governable: cannot confirm governance at this time"); emit GovernorshipTransferred(_governance, governancePending); _governance = governancePending; setGovernancePendingAt = 0; } /** * @dev Returns the address of the current governance. */ function governance() public view returns (address) { return _governance; } /** * @dev Initializes the contract setting the initial governance. */ function initialize(address _initialGovernance) internal { _governance = _initialGovernance; emit GovernorshipTransferred(address(0), _initialGovernance); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount) external returns (bool); /** * @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); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT 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) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.6; import "openzeppelin-solidity/contracts/utils/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; contract HATToken is IERC20 { struct PendingMinter { uint256 seedAmount; uint256 setMinterPendingAt; } /// @notice A checkpoint for marking number of votes from a given block struct Checkpoint { uint32 fromBlock; uint96 votes; } /// @notice EIP-20 token name for this token // solhint-disable-next-line const-name-snakecase string public constant name = "hats.finance"; /// @notice EIP-20 token symbol for this token // solhint-disable-next-line const-name-snakecase string public constant symbol = "HAT"; /// @notice EIP-20 token decimals for this token // solhint-disable-next-line const-name-snakecase uint8 public constant decimals = 18; /// @notice Total number of tokens in circulation uint public override totalSupply; address public governance; address public governancePending; uint256 public setGovernancePendingAt; uint256 public immutable timeLockDelay; uint256 public constant CAP = 10000000e18; /// @notice Address which may mint new tokens /// minter -> minting seedAmount mapping (address => uint256) public minters; /// @notice Address which may mint new tokens /// minter -> minting seedAmount mapping (address => PendingMinter) public pendingMinters; // @notice Allowance amounts on behalf of others mapping (address => mapping (address => uint96)) internal allowances; // @notice Official record of token balances for each account mapping (address => uint96) internal balances; /// @notice A record of each accounts delegate mapping (address => address) public delegates; /// @notice A record of votes checkpoints for each account, by index mapping (address => mapping (uint32 => Checkpoint)) public checkpoints; /// @notice The number of checkpoints for each account mapping (address => uint32) public numCheckpoints; /// @notice A record of states for signing / validating signatures mapping (address => uint) public nonces; /// @notice The EIP-712 typehash for the contract's domain bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); /// @notice The EIP-712 typehash for the delegation struct used by the contract bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); /// @notice The EIP-712 typehash for the permit struct used by the contract bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); /// @notice An event thats emitted when a new minter address is pending event MinterPending(address indexed minter, uint256 seedAmount, uint256 at); /// @notice An event thats emitted when the minter address is changed event MinterChanged(address indexed minter, uint256 seedAmount); /// @notice An event thats emitted when a new governance address is pending event GovernancePending(address indexed oldGovernance, address indexed newGovernance, uint256 at); /// @notice An event thats emitted when a new governance address is set event GovernanceChanged(address indexed oldGovernance, address indexed newGovernance); /// @notice An event thats emitted when an account changes its delegate event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); /// @notice An event thats emitted when a delegate account's vote balance changes event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance); /** * @notice Construct a new HAT token */ // solhint-disable-next-line func-visibility constructor(address _governance, uint256 _timeLockDelay) { governance = _governance; timeLockDelay = _timeLockDelay; } function setPendingGovernance(address _governance) external { require(msg.sender == governance, "HAT:!governance"); require(_governance != address(0), "HAT:!_governance"); governancePending = _governance; // solhint-disable-next-line not-rely-on-time setGovernancePendingAt = block.timestamp; emit GovernancePending(governance, _governance, setGovernancePendingAt); } function confirmGovernance() external { require(msg.sender == governance, "HAT:!governance"); require(setGovernancePendingAt > 0, "HAT:!governancePending"); // solhint-disable-next-line not-rely-on-time require(block.timestamp - setGovernancePendingAt > timeLockDelay, "HAT: cannot confirm governance at this time"); emit GovernanceChanged(governance, governancePending); governance = governancePending; setGovernancePendingAt = 0; } function setPendingMinter(address _minter, uint256 _cap) external { require(msg.sender == governance, "HAT::!governance"); pendingMinters[_minter].seedAmount = _cap; // solhint-disable-next-line not-rely-on-time pendingMinters[_minter].setMinterPendingAt = block.timestamp; emit MinterPending(_minter, _cap, pendingMinters[_minter].setMinterPendingAt); } function confirmMinter(address _minter) external { require(msg.sender == governance, "HAT::mint: only the governance can confirm minter"); require(pendingMinters[_minter].setMinterPendingAt > 0, "HAT:: no pending minter was set"); // solhint-disable-next-line not-rely-on-time require(block.timestamp - pendingMinters[_minter].setMinterPendingAt > timeLockDelay, "HATToken: cannot confirm at this time"); minters[_minter] = pendingMinters[_minter].seedAmount; pendingMinters[_minter].setMinterPendingAt = 0; emit MinterChanged(_minter, pendingMinters[_minter].seedAmount); } function burn(uint256 _amount) external { return _burn(msg.sender, _amount); } function mint(address _account, uint _amount) external { require(minters[msg.sender] >= _amount, "HATToken: amount greater than limitation"); minters[msg.sender] = SafeMath.sub(minters[msg.sender], _amount); _mint(_account, _amount); } /** * @notice Get the number of tokens `spender` is approved to spend on behalf of `account` * @param account The address of the account holding the funds * @param spender The address of the account spending the funds * @return The number of tokens approved */ function allowance(address account, address spender) external override view returns (uint) { return allowances[account][spender]; } /** * @notice Approve `spender` to transfer up to `amount` from `src` * @dev This will overwrite the approval amount for `spender` * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) * @param spender The address of the account which may transfer tokens * @param rawAmount The number of tokens that are approved (2^256-1 means infinite) * @return Whether or not the approval succeeded */ function approve(address spender, uint rawAmount) external override returns (bool) { uint96 amount; if (rawAmount == type(uint256).max) { amount = type(uint96).max; } else { amount = safe96(rawAmount, "HAT::approve: amount exceeds 96 bits"); } allowances[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint addedValue) external virtual returns (bool) { require(spender != address(0), "HAT: increaseAllowance to the zero address"); uint96 valueToAdd = safe96(addedValue, "HAT::increaseAllowance: addedValue exceeds 96 bits"); allowances[msg.sender][spender] = add96(allowances[msg.sender][spender], valueToAdd, "HAT::increaseAllowance: overflows"); emit Approval(msg.sender, spender, allowances[msg.sender][spender]); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint subtractedValue) external virtual returns (bool) { require(spender != address(0), "HAT: decreaseAllowance to the zero address"); uint96 valueTosubtract = safe96(subtractedValue, "HAT::decreaseAllowance: subtractedValue exceeds 96 bits"); allowances[msg.sender][spender] = sub96(allowances[msg.sender][spender], valueTosubtract, "HAT::decreaseAllowance: spender allowance is less than subtractedValue"); emit Approval(msg.sender, spender, allowances[msg.sender][spender]); return true; } /** * @notice Triggers an approval from owner to spends * @param owner The address to approve from * @param spender The address to be approved * @param rawAmount The number of tokens that are approved (2^256-1 means infinite) * @param deadline The time at which to expire the signature * @param v The recovery byte of the signature * @param r Half of the ECDSA signature pair * @param s Half of the ECDSA signature pair */ function permit(address owner, address spender, uint rawAmount, uint deadline, uint8 v, bytes32 r, bytes32 s) external { uint96 amount; if (rawAmount == type(uint256).max) { amount = type(uint96).max; } else { amount = safe96(rawAmount, "HAT::permit: amount exceeds 96 bits"); } bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this))); bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, rawAmount, nonces[owner]++, deadline)); bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); address signatory = ecrecover(digest, v, r, s); require(signatory != address(0), "HAT::permit: invalid signature"); require(signatory == owner, "HAT::permit: unauthorized"); // solhint-disable-next-line not-rely-on-time require(block.timestamp <= deadline, "HAT::permit: signature expired"); allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @notice Get the number of tokens held by the `account` * @param account The address of the account to get the balance of * @return The number of tokens held */ function balanceOf(address account) external view override returns (uint) { return balances[account]; } /** * @notice Transfer `amount` tokens from `msg.sender` to `dst` * @param dst The address of the destination account * @param rawAmount The number of tokens to transfer * @return Whether or not the transfer succeeded */ function transfer(address dst, uint rawAmount) external override returns (bool) { uint96 amount = safe96(rawAmount, "HAT::transfer: amount exceeds 96 bits"); _transferTokens(msg.sender, dst, amount); return true; } /** * @notice Transfer `amount` tokens from `src` to `dst` * @param src The address of the source account * @param dst The address of the destination account * @param rawAmount The number of tokens to transfer * @return Whether or not the transfer succeeded */ function transferFrom(address src, address dst, uint rawAmount) external override returns (bool) { address spender = msg.sender; uint96 spenderAllowance = allowances[src][spender]; uint96 amount = safe96(rawAmount, "HAT::approve: amount exceeds 96 bits"); if (spender != src && spenderAllowance != type(uint96).max) { uint96 newAllowance = sub96(spenderAllowance, amount, "HAT::transferFrom: transfer amount exceeds spender allowance"); allowances[src][spender] = newAllowance; emit Approval(src, spender, newAllowance); } _transferTokens(src, dst, amount); return true; } /** * @notice Delegate votes from `msg.sender` to `delegatee` * @param delegatee The address to delegate votes to */ function delegate(address delegatee) external { return _delegate(msg.sender, delegatee); } /** * @notice Delegates votes from signatory to `delegatee` * @param delegatee The address to delegate votes to * @param nonce The contract state required to match the signature * @param expiry The time at which to expire the signature * @param v The recovery byte of the signature * @param r Half of the ECDSA signature pair * @param s Half of the ECDSA signature pair */ function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) external { bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this))); bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)); bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); address signatory = ecrecover(digest, v, r, s); require(signatory != address(0), "HAT::delegateBySig: invalid signature"); require(nonce == nonces[signatory]++, "HAT::delegateBySig: invalid nonce"); // solhint-disable-next-line not-rely-on-time require(block.timestamp <= expiry, "HAT::delegateBySig: signature expired"); return _delegate(signatory, delegatee); } /** * @notice Gets the current votes balance for `account` * @param account The address to get votes balance * @return The number of current votes for `account` */ function getCurrentVotes(address account) external view returns (uint96) { uint32 nCheckpoints = numCheckpoints[account]; return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0; } /** * @notice Determine the prior number of votes for an account as of a block number * @dev Block number must be a finalized block or else this function will revert to prevent misinformation. * @param account The address of the account to check * @param blockNumber The block number to get the vote balance at * @return The number of votes the account had as of the given block */ function getPriorVotes(address account, uint blockNumber) external view returns (uint96) { require(blockNumber < block.number, "HAT::getPriorVotes: not yet determined"); uint32 nCheckpoints = numCheckpoints[account]; if (nCheckpoints == 0) { return 0; } // First check most recent balance if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { return checkpoints[account][nCheckpoints - 1].votes; } // Next check implicit zero balance if (checkpoints[account][0].fromBlock > blockNumber) { return 0; } uint32 lower = 0; uint32 upper = nCheckpoints - 1; while (upper > lower) { uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow Checkpoint memory cp = checkpoints[account][center]; if (cp.fromBlock == blockNumber) { return cp.votes; } else if (cp.fromBlock < blockNumber) { lower = center; } else { upper = center - 1; } } return checkpoints[account][lower].votes; } /** * @notice Mint new tokens * @param dst The address of the destination account * @param rawAmount The number of tokens to be minted */ function _mint(address dst, uint rawAmount) internal { require(dst != address(0), "HAT::mint: cannot transfer to the zero address"); require(SafeMath.add(totalSupply, rawAmount) <= CAP, "ERC20Capped: CAP exceeded"); // mint the amount uint96 amount = safe96(rawAmount, "HAT::mint: amount exceeds 96 bits"); totalSupply = safe96(SafeMath.add(totalSupply, amount), "HAT::mint: totalSupply exceeds 96 bits"); // transfer the amount to the recipient balances[dst] = add96(balances[dst], amount, "HAT::mint: transfer amount overflows"); emit Transfer(address(0), dst, amount); // move delegates _moveDelegates(address(0), delegates[dst], amount); } /** * Burn tokens * @param src The address of the source account * @param rawAmount The number of tokens to be burned */ function _burn(address src, uint rawAmount) internal { require(src != address(0), "HAT::burn: cannot burn to the zero address"); // burn the amount uint96 amount = safe96(rawAmount, "HAT::burn: amount exceeds 96 bits"); totalSupply = safe96(SafeMath.sub(totalSupply, amount), "HAT::mint: totalSupply exceeds 96 bits"); // reduce the amount from src address balances[src] = sub96(balances[src], amount, "HAT::burn: burn amount exceeds balance"); emit Transfer(src, address(0), amount); // move delegates _moveDelegates(delegates[src], address(0), amount); } function _delegate(address delegator, address delegatee) internal { address currentDelegate = delegates[delegator]; uint96 delegatorBalance = balances[delegator]; delegates[delegator] = delegatee; emit DelegateChanged(delegator, currentDelegate, delegatee); _moveDelegates(currentDelegate, delegatee, delegatorBalance); } function _transferTokens(address src, address dst, uint96 amount) internal { require(src != address(0), "HAT::_transferTokens: cannot transfer from the zero address"); require(dst != address(0), "HAT::_transferTokens: cannot transfer to the zero address"); balances[src] = sub96(balances[src], amount, "HAT::_transferTokens: transfer amount exceeds balance"); balances[dst] = add96(balances[dst], amount, "HAT::_transferTokens: transfer amount overflows"); emit Transfer(src, dst, amount); _moveDelegates(delegates[src], delegates[dst], amount); } function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal { if (srcRep != dstRep && amount > 0) { if (srcRep != address(0)) { uint32 srcRepNum = numCheckpoints[srcRep]; uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0; uint96 srcRepNew = sub96(srcRepOld, amount, "HAT::_moveVotes: vote amount underflows"); _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew); } if (dstRep != address(0)) { uint32 dstRepNum = numCheckpoints[dstRep]; uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0; uint96 dstRepNew = add96(dstRepOld, amount, "HAT::_moveVotes: vote amount overflows"); _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew); } } } function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal { uint32 blockNumber = safe32(block.number, "HAT::_writeCheckpoint: block number exceeds 32 bits"); if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) { checkpoints[delegatee][nCheckpoints - 1].votes = newVotes; } else { checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes); numCheckpoints[delegatee] = nCheckpoints + 1; } emit DelegateVotesChanged(delegatee, oldVotes, newVotes); } function safe32(uint n, string memory errorMessage) internal pure returns (uint32) { require(n < 2**32, errorMessage); return uint32(n); } function safe96(uint n, string memory errorMessage) internal pure returns (uint96) { require(n < 2**96, errorMessage); return uint96(n); } function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) { uint96 c = a + b; require(c >= a, errorMessage); return c; } function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) { require(b <= a, errorMessage); return a - b; } function getChainId() internal view returns (uint) { uint256 chainId; // solhint-disable-next-line no-inline-assembly assembly { chainId := chainid() } return chainId; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.6; pragma experimental ABIEncoderV2; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; interface ITokenLock { enum Revocability { NotSet, Enabled, Disabled } // -- Balances -- function currentBalance() external view returns (uint256); // -- Time & Periods -- function currentTime() external view returns (uint256); function duration() external view returns (uint256); function sinceStartTime() external view returns (uint256); function amountPerPeriod() external view returns (uint256); function periodDuration() external view returns (uint256); function currentPeriod() external view returns (uint256); function passedPeriods() external view returns (uint256); // -- Locking & Release Schedule -- function availableAmount() external view returns (uint256); function vestedAmount() external view returns (uint256); function releasableAmount() external view returns (uint256); function totalOutstandingAmount() external view returns (uint256); function surplusAmount() external view returns (uint256); // -- Value Transfer -- function release() external; function withdrawSurplus(uint256 _amount) external; function revoke() external; }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_rewardsToken","type":"address"},{"internalType":"uint256","name":"_rewardPerBlock","type":"uint256"},{"internalType":"uint256","name":"_startBlock","type":"uint256"},{"internalType":"uint256","name":"_multiplierPeriod","type":"uint256"},{"internalType":"address","name":"_hatGovernance","type":"address"},{"internalType":"contract ISwapRouter","name":"_uniSwapRouter","type":"address"},{"internalType":"contract ITokenLockFactory","name":"_tokenLockFactory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"indexed":true,"internalType":"address","name":"_lpToken","type":"address"},{"indexed":false,"internalType":"address","name":"_committee","type":"address"},{"indexed":false,"internalType":"string","name":"_descriptionHash","type":"string"},{"indexed":false,"internalType":"uint256[]","name":"_rewardsLevels","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"hackerVestedReward","type":"uint256"},{"internalType":"uint256","name":"hackerReward","type":"uint256"},{"internalType":"uint256","name":"committeeReward","type":"uint256"},{"internalType":"uint256","name":"swapAndBurn","type":"uint256"},{"internalType":"uint256","name":"governanceHatReward","type":"uint256"},{"internalType":"uint256","name":"hackerHatReward","type":"uint256"}],"indexed":false,"internalType":"struct HATMaster.RewardsSplit","name":"_rewardsSplit","type":"tuple"},{"indexed":false,"internalType":"uint256","name":"_rewardVestingDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_rewardVestingPeriods","type":"uint256"}],"name":"AddPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_claimer","type":"address"},{"indexed":false,"internalType":"string","name":"_descriptionHash","type":"string"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_approver","type":"address"},{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"indexed":true,"internalType":"address","name":"_beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"_severity","type":"uint256"},{"indexed":false,"internalType":"address","name":"_tokenLock","type":"address"},{"components":[{"internalType":"uint256","name":"hackerVestedReward","type":"uint256"},{"internalType":"uint256","name":"hackerReward","type":"uint256"},{"internalType":"uint256","name":"committeeReward","type":"uint256"},{"internalType":"uint256","name":"swapAndBurn","type":"uint256"},{"internalType":"uint256","name":"governanceHatReward","type":"uint256"},{"internalType":"uint256","name":"hackerHatReward","type":"uint256"}],"indexed":false,"internalType":"struct HATVaults.ClaimReward","name":"_claimReward","type":"tuple"}],"name":"ClaimApprove","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_previousGovernance","type":"address"},{"indexed":true,"internalType":"address","name":"_newGovernance","type":"address"},{"indexed":false,"internalType":"uint256","name":"_at","type":"uint256"}],"name":"GovernancePending","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_previousGovernance","type":"address"},{"indexed":true,"internalType":"address","name":"_newGovernance","type":"address"}],"name":"GovernorshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_fromPid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toPid","type":"uint256"}],"name":"MassUpdatePools","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"indexed":true,"internalType":"address","name":"_beneficiary","type":"address"},{"indexed":true,"internalType":"uint256","name":"_severity","type":"uint256"},{"indexed":false,"internalType":"address","name":"_approver","type":"address"}],"name":"PendingApprovalLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"_rewardsLevels","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"_timeStamp","type":"uint256"}],"name":"PendingRewardsLevelsLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"RewardDepositors","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"name":"SendReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"indexed":true,"internalType":"address","name":"_committee","type":"address"}],"name":"SetCommittee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_duration","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_periods","type":"uint256"}],"name":"SetHatVestingParams","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"indexed":true,"internalType":"bool","name":"_registered","type":"bool"},{"indexed":false,"internalType":"string","name":"_descriptionHash","type":"string"}],"name":"SetPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"_rewardsLevels","type":"uint256[]"}],"name":"SetRewardsLevels","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"components":[{"internalType":"uint256","name":"hackerVestedReward","type":"uint256"},{"internalType":"uint256","name":"hackerReward","type":"uint256"},{"internalType":"uint256","name":"committeeReward","type":"uint256"},{"internalType":"uint256","name":"swapAndBurn","type":"uint256"},{"internalType":"uint256","name":"governanceHatReward","type":"uint256"},{"internalType":"uint256","name":"hackerHatReward","type":"uint256"}],"indexed":false,"internalType":"struct HATMaster.RewardsSplit","name":"_rewardsSplit","type":"tuple"}],"name":"SetRewardsSplit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_duration","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_periods","type":"uint256"}],"name":"SetVestingParams","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_withdrawPeriod","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_safetyPeriod","type":"uint256"}],"name":"SetWithdrawSafetyPeriod","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_amountSwaped","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_amountBurned","type":"uint256"}],"name":"SwapAndBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"indexed":true,"internalType":"address","name":"_beneficiary","type":"address"},{"indexed":true,"internalType":"uint256","name":"_amountSwaped","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_amountReceived","type":"uint256"},{"indexed":false,"internalType":"address","name":"_tokenLock","type":"address"}],"name":"SwapAndSend","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_pid","type":"uint256"},{"indexed":true,"internalType":"address","name":"_beneficiary","type":"address"},{"indexed":true,"internalType":"uint256","name":"_withdrawEnableTime","type":"uint256"}],"name":"WithdrawRequest","type":"event"},{"inputs":[],"name":"HAT","outputs":[{"internalType":"contract HATToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINIMUM_DEPOSIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MULTIPLIER_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_PER_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"START_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIME_LOCK_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"address","name":"_lpToken","type":"address"},{"internalType":"address","name":"_committee","type":"address"},{"internalType":"uint256[]","name":"_rewardsLevels","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"hackerVestedReward","type":"uint256"},{"internalType":"uint256","name":"hackerReward","type":"uint256"},{"internalType":"uint256","name":"committeeReward","type":"uint256"},{"internalType":"uint256","name":"swapAndBurn","type":"uint256"},{"internalType":"uint256","name":"governanceHatReward","type":"uint256"},{"internalType":"uint256","name":"hackerHatReward","type":"uint256"}],"internalType":"struct HATMaster.RewardsSplit","name":"_rewardsSplit","type":"tuple"},{"internalType":"string","name":"_descriptionHash","type":"string"},{"internalType":"uint256[2]","name":"_rewardVestingParams","type":"uint256[2]"}],"name":"addPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"approveClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_severity","type":"uint256"}],"name":"calcClaimRewards","outputs":[{"components":[{"internalType":"uint256","name":"hackerVestedReward","type":"uint256"},{"internalType":"uint256","name":"hackerReward","type":"uint256"},{"internalType":"uint256","name":"committeeReward","type":"uint256"},{"internalType":"uint256","name":"swapAndBurn","type":"uint256"},{"internalType":"uint256","name":"governanceHatReward","type":"uint256"},{"internalType":"uint256","name":"hackerHatReward","type":"uint256"}],"internalType":"struct HATVaults.ClaimReward","name":"claimRewards","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_from","type":"uint256"},{"internalType":"uint256","name":"_lastPoolUpdate","type":"uint256"}],"name":"calcPoolReward","outputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_descriptionHash","type":"string"}],"name":"claim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"committeeCheckIn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"committees","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"dismissPendingApprovalClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"generalParameters","outputs":[{"internalType":"uint256","name":"hatVestingDuration","type":"uint256"},{"internalType":"uint256","name":"hatVestingPeriods","type":"uint256"},{"internalType":"uint256","name":"withdrawPeriod","type":"uint256"},{"internalType":"uint256","name":"safetyPeriod","type":"uint256"},{"internalType":"uint256","name":"setRewardsLevelsDelay","type":"uint256"},{"internalType":"uint256","name":"withdrawRequestEnablePeriod","type":"uint256"},{"internalType":"uint256","name":"withdrawRequestPendingPeriod","type":"uint256"},{"internalType":"uint256","name":"claimFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDefaultRewardsSplit","outputs":[{"components":[{"internalType":"uint256","name":"hackerVestedReward","type":"uint256"},{"internalType":"uint256","name":"hackerReward","type":"uint256"},{"internalType":"uint256","name":"committeeReward","type":"uint256"},{"internalType":"uint256","name":"swapAndBurn","type":"uint256"},{"internalType":"uint256","name":"governanceHatReward","type":"uint256"},{"internalType":"uint256","name":"hackerHatReward","type":"uint256"}],"internalType":"struct HATMaster.RewardsSplit","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getGlobalPoolUpdatesLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_from","type":"uint256"},{"internalType":"uint256","name":"_to","type":"uint256"}],"name":"getMultiplier","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"getPoolRewards","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"hackerVestedReward","type":"uint256"},{"internalType":"uint256","name":"hackerReward","type":"uint256"},{"internalType":"uint256","name":"committeeReward","type":"uint256"},{"internalType":"uint256","name":"swapAndBurn","type":"uint256"},{"internalType":"uint256","name":"governanceHatReward","type":"uint256"},{"internalType":"uint256","name":"hackerHatReward","type":"uint256"}],"internalType":"struct HATMaster.RewardsSplit","name":"rewardsSplit","type":"tuple"},{"internalType":"uint256[]","name":"rewardsLevels","type":"uint256[]"},{"internalType":"bool","name":"committeeCheckIn","type":"bool"},{"internalType":"uint256","name":"vestingDuration","type":"uint256"},{"internalType":"uint256","name":"vestingPeriods","type":"uint256"}],"internalType":"struct HATMaster.PoolReward","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"getPoolRewardsLevels","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_from","type":"uint256"},{"internalType":"uint256","name":"_to","type":"uint256"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"uint256","name":"_totalAllocPoint","type":"uint256"}],"name":"getRewardForBlocksRange","outputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid1","type":"uint256"}],"name":"getRewardPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"getStakedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"globalPoolUpdates","outputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"totalAllocPoint","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"governanceHatRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governancePending","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"hackersHatRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fromPid","type":"uint256"},{"internalType":"uint256","name":"_toPid","type":"uint256"}],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_beneficiary","type":"address"},{"internalType":"uint256","name":"_severity","type":"uint256"}],"name":"pendingApprovalClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pendingApprovals","outputs":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"severity","type":"uint256"},{"internalType":"address","name":"approver","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pendingRewardsLevels","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolDepositPause","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolId1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"contract IERC20","name":"lpToken","type":"address"},{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"internalType":"uint256","name":"rewardPerShare","type":"uint256"},{"internalType":"uint256","name":"totalUsersAmount","type":"uint256"},{"internalType":"uint256","name":"lastProcessedTotalAllocPoint","type":"uint256"},{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"rewardDepositors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setClaimFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_committee","type":"address"}],"name":"setCommittee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setGovernancePendingAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"},{"internalType":"uint256","name":"_periods","type":"uint256"}],"name":"setHatVestingParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernance","type":"address"}],"name":"setPendingGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256[]","name":"_rewardsLevels","type":"uint256[]"}],"name":"setPendingRewardsLevels","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"bool","name":"_registered","type":"bool"},{"internalType":"bool","name":"_depositPause","type":"bool"},{"internalType":"string","name":"_descriptionHash","type":"string"}],"name":"setPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"setRewardsLevels","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setRewardsLevelsDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"components":[{"internalType":"uint256","name":"hackerVestedReward","type":"uint256"},{"internalType":"uint256","name":"hackerReward","type":"uint256"},{"internalType":"uint256","name":"committeeReward","type":"uint256"},{"internalType":"uint256","name":"swapAndBurn","type":"uint256"},{"internalType":"uint256","name":"governanceHatReward","type":"uint256"},{"internalType":"uint256","name":"hackerHatReward","type":"uint256"}],"internalType":"struct HATMaster.RewardsSplit","name":"_rewardsSplit","type":"tuple"}],"name":"setRewardsSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_duration","type":"uint256"},{"internalType":"uint256","name":"_periods","type":"uint256"}],"name":"setVestingParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_withdrawRequestPendingPeriod","type":"uint256"},{"internalType":"uint256","name":"_withdrawRequestEnablePeriod","type":"uint256"}],"name":"setWithdrawRequestParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_withdrawPeriod","type":"uint256"},{"internalType":"uint256","name":"_safetyPeriod","type":"uint256"}],"name":"setWithdrawSafetyPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"swapAndBurns","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_beneficiary","type":"address"},{"internalType":"uint256","name":"_amountOutMinimum","type":"uint256"},{"internalType":"uint24[2]","name":"_fees","type":"uint24[2]"}],"name":"swapBurnSend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenLockFactory","outputs":[{"internalType":"contract ITokenLockFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferGovernorship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniSwapRouter","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"withdrawRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"withdrawRequests","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101406040523480156200001257600080fd5b506040516200618538038062006185833981016040819052620000359162000162565b6001600355606087901b6001600160601b03191660805260a086905260c085905260e0849052620000728362000117602090811b620039a817901c565b6001600160601b0319606092831b81166101205290821b166101009081526040805191820181526276a700808352605a60208401819052619ab0928401839052610e109484018590526202a3006080850181905262093a8060a0860181905260c08601819052600060e0909601869052601193909355601291909155601392909255601493909355601555601682905560179190915560185550620002039350505050565b600080546001600160a01b0319166001600160a01b03831690811782556040519091907fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a908290a350565b600080600080600080600060e0888a0312156200017e57600080fd5b87516200018b81620001ea565b809750506020880151955060408801519450606088015193506080880151620001b481620001ea565b60a0890151909350620001c781620001ea565b60c0890151909250620001da81620001ea565b8091505092959891949750929550565b6001600160a01b03811681146200020057600080fd5b50565b60805160601c60a05160c05160e0516101005160601c6101205160601c615e73620003126000396000818161080f015281816147db015281816149490152614b3e01526000818161048a01528181611b170152612fb6015260008181610dac0152818161288601526129180152600081816106bd015281816128aa015281816128f301528181613e590152613e80015260008181610a22015261372e01526000818161063c015281816120e50152818161219401528181612f0701528181612fe5015281816130cb015281816131a401528181614785015281816148c101528181614a2d01528181614ac501528181614be801528181614cd501528181614d870152614e750152615e736000f3fe6080604052600436106103c35760003560e01c806382b0617d116101f2578063cbd42a701161010d578063eabcff2c116100a0578063f3fe12c91161006f578063f3fe12c914610d51578063f5e820fd14610d64578063f7cd531914610d9a578063fcecc73814610dce57600080fd5b8063eabcff2c14610cda578063ebb6bc7214610cfa578063f19451d814610d1a578063f26ae82714610d3157600080fd5b8063dd072f03116100dc578063dd072f0314610bf4578063df1b1ebe14610c14578063e02ff8f214610c82578063e2bbb15814610cba57600080fd5b8063cbd42a7014610b71578063ce2529c914610b91578063d2369c6514610bbe578063da42757814610bd457600080fd5b806399f9b05a11610185578063b2e629c711610154578063b2e629c714610af1578063b9a4bdb414610b11578063be75e74f14610b31578063c7b5184a14610b5157600080fd5b806399f9b05a14610a645780639c2a7a6d14610a9c578063aa0cd25c14610abc578063ae169a5014610ad157600080fd5b806393f1a40b116101c157806393f1a40b1461098f57806395fec613146109e3578063975532dc14610a1057806398969e8214610a4457600080fd5b806382b0617d1461090257806383867c1b1461092f57806384fcf8e51461094f5780638dbb1e3a1461096f57600080fd5b8063398488eb116102e2578063520a924d11610275578063686b656e11610244578063686b656e146108315780636e419506146108a257806374899a7e146108c25780637b550bc9146108e257600080fd5b8063520a924d1461079f5780635312ea8e146107bf5780635aa6e675146107df5780635d01ff3d146107fd57600080fd5b8063441a3e70116102b1578063441a3e701461071f57806346e301351461073f5780634f8d45ee1461075f57806351eb05a61461077f57600080fd5b8063398488eb1461068b57806339b3e826146106ab5780633a71ede8146106df5780633d8a0906146106ff57600080fd5b80631d46446a1161035a5780633207b103116103295780633207b103146105d057806334333058146105fd5780633449a8651461062a57806335bbf3161461065e57600080fd5b80631d46446a146105435780632a5ad7d0146105635780632b2f4d84146105905780632e75ab50146105b057600080fd5b80630d2edde2116103965780630d2edde21461046357806311c2aae31461047857806313401551146104c45780631526fe27146104e457600080fd5b8063081e3eda146103c85780630abb6035146103ec5780630af937f21461040e5780630b346a9e1461044e575b600080fd5b3480156103d457600080fd5b506004545b6040519081526020015b60405180910390f35b3480156103f857600080fd5b5061040c6104073660046153a8565b610de5565b005b34801561041a57600080fd5b5061043e61042936600461546d565b60106020526000908152604090205460ff1681565b60405190151581526020016103e3565b34801561045a57600080fd5b506005546103d9565b34801561046f57600080fd5b5061040c610eee565b34801561048457600080fd5b506104ac7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103e3565b3480156104d057600080fd5b506001546104ac906001600160a01b031681565b3480156104f057600080fd5b506105046104ff36600461546d565b611052565b604080516001600160a01b0390981688526020880196909652948601939093526060850191909152608084015260a083015260c082015260e0016103e3565b34801561054f57600080fd5b5061040c61055e3660046155c8565b6110ab565b34801561056f57600080fd5b506103d961057e3660046153a8565b600c6020526000908152604090205481565b34801561059c57600080fd5b5061040c6105ab3660046157ac565b6112c7565b3480156105bc57600080fd5b5061040c6105cb36600461546d565b6113a1565b3480156105dc57600080fd5b506105f06105eb36600461546d565b6113d0565b6040516103e391906159b6565b34801561060957600080fd5b5061061d610618366004615714565b611435565b6040516103e39190615bb0565b34801561063657600080fd5b506104ac7f000000000000000000000000000000000000000000000000000000000000000081565b34801561066a57600080fd5b506103d961067936600461546d565b600f6020526000908152604090205481565b34801561069757600080fd5b5061040c6106a6366004615714565b6116b0565b3480156106b757600080fd5b506103d97f000000000000000000000000000000000000000000000000000000000000000081565b3480156106eb57600080fd5b506103d96106fa36600461549f565b6116e5565b34801561070b57600080fd5b5061040c61071a36600461546d565b61170f565b34801561072b57600080fd5b5061040c61073a366004615714565b6118f9565b34801561074b57600080fd5b5061040c61075a36600461546d565b611910565b34801561076b57600080fd5b5061040c61077a3660046154c4565b611d96565b34801561078b57600080fd5b5061040c61079a36600461546d565b612049565b3480156107ab57600080fd5b5061040c6107ba366004615714565b612235565b3480156107cb57600080fd5b5061040c6107da36600461546d565b61229a565b3480156107eb57600080fd5b506000546001600160a01b03166104ac565b34801561080957600080fd5b506104ac7f000000000000000000000000000000000000000000000000000000000000000081565b34801561083d57600080fd5b5061087861084c36600461546d565b600d602052600090815260409020805460018201546002909201546001600160a01b0391821692911683565b604080516001600160a01b03948516815260208101939093529216918101919091526060016103e3565b3480156108ae57600080fd5b5061040c6108bd366004615714565b6122af565b3480156108ce57600080fd5b5061040c6108dd36600461546d565b61240b565b3480156108ee57600080fd5b506103d96108fd36600461546d565b6124d6565b34801561090e57600080fd5b5061092261091d36600461546d565b61256d565b6040516103e39190615c16565b34801561093b57600080fd5b5061040c61094a36600461546d565b612651565b34801561095b57600080fd5b5061040c61096a3660046156a0565b6126a8565b34801561097b57600080fd5b506103d961098a366004615714565b61279e565b34801561099b57600080fd5b506109ce6109aa36600461549f565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016103e3565b3480156109ef57600080fd5b506103d96109fe3660046153a8565b600a6020526000908152604090205481565b348015610a1c57600080fd5b506103d97f000000000000000000000000000000000000000000000000000000000000000081565b348015610a5057600080fd5b506103d9610a5f36600461549f565b612a0b565b348015610a7057600080fd5b506103d9610a7f3660046153e2565b600b60209081526000928352604080842090915290825290205481565b348015610aa857600080fd5b5061040c610ab73660046156e7565b612af0565b348015610ac857600080fd5b5061061d612c28565b348015610add57600080fd5b5061040c610aec36600461546d565b612c9e565b348015610afd57600080fd5b5061040c610b0c366004615736565b612ca9565b348015610b1d57600080fd5b5061040c610b2c366004615600565b612dab565b348015610b3d57600080fd5b5061040c610b4c36600461549f565b61327e565b348015610b5d57600080fd5b5061040c610b6c36600461546d565b613415565b348015610b7d57600080fd5b506109ce610b8c36600461546d565b613471565b348015610b9d57600080fd5b506103d9610bac3660046153a8565b60066020526000908152604090205481565b348015610bca57600080fd5b506103d960025481565b348015610be057600080fd5b5061040c610bef366004615714565b61349f565b348015610c0057600080fd5b5061040c610c0f366004615714565b61358f565b348015610c2057600080fd5b50601154601254601354601454601554601654601754601854610c47979695949392919088565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c083015260e0820152610100016103e3565b348015610c8e57600080fd5b506103d9610c9d36600461549f565b600e60209081526000928352604080842090915290825290205481565b348015610cc657600080fd5b5061040c610cd5366004615714565b613656565b348015610ce657600080fd5b506103d9610cf53660046157d8565b613714565b348015610d0657600080fd5b5061040c610d1536600461546d565b613768565b348015610d2657600080fd5b506103d9620f424081565b348015610d3d57600080fd5b506103d9610d4c3660046157ac565b6137df565b61040c610d5f366004615438565b6138d7565b348015610d7057600080fd5b506104ac610d7f36600461546d565b6009602052600090815260409020546001600160a01b031681565b348015610da657600080fd5b506103d97f000000000000000000000000000000000000000000000000000000000000000081565b348015610dda57600080fd5b506103d96202a30081565b6000546001600160a01b03163314610e185760405162461bcd60e51b8152600401610e0f90615aa4565b60405180910390fd5b6001600160a01b038116610e845760405162461bcd60e51b815260206004820152602d60248201527f476f7665726e61626c653a6e657720676f7665726e616e63652069732074686560448201526c207a65726f206164647265737360981b6064820152608401610e0f565b600180546001600160a01b038084166001600160a01b03199092168217909255426002819055600054604051929316917f6dedeac5137d4e7301332bf2cbe80d9997406cff0e2b3634c9f8c47a49989ba991610ee39190815260200190565b60405180910390a350565b6000546001600160a01b03163314610f185760405162461bcd60e51b8152600401610e0f90615aa4565b600060025411610f745760405162461bcd60e51b815260206004820152602160248201527f476f7665726e61626c653a206e6f2070656e64696e6720676f7665726e616e636044820152606560f81b6064820152608401610e0f565b6202a30060025442610f869190615d3a565b11610fee5760405162461bcd60e51b815260206004820152603260248201527f476f7665726e61626c653a2063616e6e6f7420636f6e6669726d20676f7665726044820152716e616e636520617420746869732074696d6560701b6064820152608401610e0f565b600154600080546040516001600160a01b0393841693909116917fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a91a3600154600080546001600160a01b0319166001600160a01b03909216919091178155600255565b6004818154811061106257600080fd5b600091825260209091206007909102018054600182015460028301546003840154600485015460058601546006909601546001600160a01b039095169650929491939092919087565b60008381526009602052604090205483906001600160a01b031633146110e35760405162461bcd60e51b8152600401610e0f90615a45565b6000848152600d602052604090205484906001600160a01b03161561111a5760405162461bcd60e51b8152600401610e0f90615acd565b6001600160a01b0384166111665760405162461bcd60e51b815260206004820152601360248201527262656e6566696369617279206973207a65726f60681b6044820152606401610e0f565b6013546014546111769082615cef565b6111809042615d98565b10156111c35760405162461bcd60e51b81526020600482015260126024820152711b9bdb99481cd859995d1e481c195c9a5bd960721b6044820152606401610e0f565b60008581526008602052604090206006015483106112235760405162461bcd60e51b815260206004820152601d60248201527f5f7365766572697479206973206e6f7420696e207468652072616e67650000006044820152606401610e0f565b604080516060810182526001600160a01b0386811680835260208084018881523385870181815260008d8152600d8552889020965187549087166001600160a01b0319918216178855925160018801555160029096018054969095169590911694909417909255925191825285929188917fd878c70cbed9605353e23b13b6475a2e1ef3c7d976f8495f233a1a7f4bc6811c91015b60405180910390a45050505050565b6000546001600160a01b031633146112f15760405162461bcd60e51b8152600401610e0f90615aa4565b629e340082106113135760405162461bcd60e51b8152600401610e0f90615afd565b600081116113335760405162461bcd60e51b8152600401610e0f90615a6d565b808210156113535760405162461bcd60e51b8152600401610e0f90615b34565b60008381526008602081905260408083209182018590556009909101839055518291849186917fb2c473651bf0d98b7935f0a45d2e04d804b1d00c3131bf824fb1944ff9ae8e3c91a4505050565b6000546001600160a01b031633146113cb5760405162461bcd60e51b8152600401610e0f90615aa4565b601855565b60008181526008602090815260409182902060060180548351818402810184019094528084526060939283018282801561142957602002820191906000526020600020905b815481526020019060010190808311611415575b50505050509050919050565b61146e6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60006004848154811061148357611483615dee565b9060005260206000209060070201600601549050600081116114dd5760405162461bcd60e51b8152602060048201526013602482015272746f74616c537570706c79206973207a65726f60681b6044820152606401610e0f565b600084815260086020526040902060060154831061153d5760405162461bcd60e51b815260206004820152601d60248201527f5f7365766572697479206973206e6f7420696e207468652072616e67650000006044820152606401610e0f565b6000848152600860205260408120600601805461157f91908690811061156557611565615dee565b9060005260206000200154836139f390919063ffffffff16565b90506115b061159061271080615d1b565b6000878152600860205260409020546115aa9084906139f3565b906139ff565b83526115de6115c161271080615d1b565b6000878152600860205260409020600101546115aa9084906139f3565b602084015261160f6115f261271080615d1b565b6000878152600860205260409020600201546115aa9084906139f3565b604084015261164061162361271080615d1b565b6000878152600860205260409020600301546115aa9084906139f3565b606084015261167161165461271080615d1b565b6000878152600860205260409020600401546115aa9084906139f3565b60808401526116a261168561271080615d1b565b6000878152600860205260409020600501546115aa9084906139f3565b60a084015250909392505050565b6000546001600160a01b031633146116da5760405162461bcd60e51b8152600401610e0f90615aa4565b601791909155601655565b60008281526007602090815260408083206001600160a01b03851684529091529020545b92915050565b60008181526009602052604090205481906001600160a01b031633146117475760405162461bcd60e51b8152600401610e0f90615a45565b6000828152600d602052604090205482906001600160a01b03161561177e5760405162461bcd60e51b8152600401610e0f90615acd565b6000838152600f60205260409020546117d95760405162461bcd60e51b815260206004820152601d60248201527f6e6f2070656e64696e67207365742072657761726473206c6576656c730000006044820152606401610e0f565b6015546000848152600f60205260409020546117f59042615d3a565b116118575760405162461bcd60e51b815260206004820152602c60248201527f63616e6e6f7420636f6e6669726d20736574526577617264734c6576656c732060448201526b617420746869732074696d6560a01b6064820152608401610e0f565b6000838152600f60209081526040808320600890925290912060019091018054611885926006019190615112565b506000838152600f60205260408120818155906118a56001830182615162565b5050827f37234a2297757e81787ddd776e23606f74b9ecc8562ba691b9dde3adef5089cd600860008681526020019081526020016000206006016040516118ec91906159eb565b60405180910390a2505050565b61190282613a0b565b61190c8282613b4f565b5050565b6000546001600160a01b0316331461193a5760405162461bcd60e51b8152600401610e0f90615aa4565b6002600354141561195d5760405162461bcd60e51b8152600401610e0f90615b79565b60026003556000818152600d60205260409020546001600160a01b03166119bc5760405162461bcd60e51b81526020600482015260136024820152721b9bc81c195b991a5b99c8185c1c1c9bdd985b606a1b6044820152606401610e0f565b6000818152600860209081526040808320600d808452828520835160608101855281546001600160a01b038082168352600184018054848a0152600285018054928316988501989098528a8a52949097526001600160a01b0319908116909255918690559093169091556004805491939185908110611a3d57611a3d615dee565b60009182526020808320600790920290910154908401516001600160a01b039091169250611a6c908690611435565b9050611ae5611ab28260800151611aac8460a00151611aac8660600151611aac8860400151611aac8a600001518b60200151613d3490919063ffffffff16565b90613d34565b60048781548110611ac557611ac5615dee565b906000526020600020906007020160060154613d4090919063ffffffff16565b60048681548110611af857611af8615dee565b60009182526020822060066007909202010191909155815115611c02577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e95cd0518461dead87600001518660000151428b6008015442611b639190615cef565b8c60090154600080600260006040518c63ffffffff1660e01b8152600401611b959b9a999897969594939291906158c7565b602060405180830381600087803b158015611baf57600080fd5b505af1158015611bc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be791906153c5565b8251909150611c02906001600160a01b038516908390613d4c565b83516020830151611c1d916001600160a01b03861691613d4c565b60408085015190830151611c3b916001600160a01b03861691613d4c565b60608201516001600160a01b0384166000908152600a6020526040902054611c6291613d34565b6001600160a01b0384166000908152600a60209081526040808320939093556080850151600c90915291902054611c9891613d34565b6001600160a01b038085166000818152600c602090815260408083209590955560a087015189519094168252600b8152848220928252919091529190912054611ce091613d34565b84516001600160a01b039081166000908152600b6020908152604080832088851684528252918290209390935586519287015190519290911691889133917fb34d89b43b53d2ebac4aa01c9ab4b64aca3ca9612c3f79a58c6d2528e414775291611d4d9187908990615c71565b60405180910390a4600060048781548110611d6a57611d6a615dee565b90600052602060002090600702016006015411611d8957611d89615dac565b5050600160035550505050565b6000546001600160a01b03163314611dc05760405162461bcd60e51b8152600401610e0f90615aa4565b8051629e340011611de35760405162461bcd60e51b8152600401610e0f90615afd565b6020810151611e045760405162461bcd60e51b8152600401610e0f90615a6d565b602081015181511015611e295760405162461bcd60e51b8152600401610e0f90615b34565b6001600160a01b038516611e735760405162461bcd60e51b8152602060048201526011602482015270636f6d6d6974746565206973207a65726f60781b6044820152606401610e0f565b611e7d8787613db4565b600454600090611e8f90600190615d3a565b600081815260096020526040812080546001600160a01b0319166001600160a01b038a16179055909150611ec2866140cc565b8551909150600090158015611ed957506020860151155b611ee35785611eeb565b611eeb612c28565b9050611ef6816141ef565b6040518060a0016040528082815260200183815260200160001515815260200185600060028110611f2957611f29615dee565b6020020151815260200185600160028110611f4657611f46615dee565b60209081029190910151909152600085815260088252604090819020835180518255808401516001830155918201516002820155606082015160038201556080820151600482015560a09091015160058201558282015180519192611fb392600685019290910190615180565b50604082015160078201805460ff1916911515919091179055606082015160088201556080909101516009909101556001600160a01b0389168a847f101333dd96212851804793a854aef45352029659781cb05bddccb6815bd86dc78b8987878b600060200201518c6001602002015160405161203596959493929190615957565b60405180910390a450505050505050505050565b60006004828154811061205e5761205e615dee565b9060005260206000209060070201905060008160020154905080431161208357505050565b600482015460055460009061209a90600190615d3a565b9050816120b557436002850155600590930192909255505050565b60006120c28685846137df565b604051633d1bb33160e21b81523060048201529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f46eccc49060240160206040518083038186803b15801561212757600080fd5b505afa15801561213b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215f9190615486565b905081811061216e5781612170565b805b915081156121f9576040516340c10f1960e01b8152306004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f1990604401600060405180830381600087803b1580156121e057600080fd5b505af11580156121f4573d6000803e3d6000fd5b505050505b61221a61220f856115aa8564e8d4a510006139f3565b600388015490613d34565b60038701555050436002850155600590930192909255505050565b6000546001600160a01b0316331461225f5760405162461bcd60e51b8152600401610e0f90615aa4565b60138290556014819055604051819083907f47c8a5b15f6172a5053bfac488642484dd38e9c0f3073c23c5d822c4cbab530990600090a35050565b6122a381613a0b565b6122ac8161427a565b50565b600482815481106122c2576122c2615dee565b906000526020600020906007020160040154612312620f42406115aa84600487815481106122f2576122f2615dee565b906000526020600020906007020160060154613d3490919063ffffffff16565b1061235f5760405162461bcd60e51b815260206004820152601b60248201527f616d6f756e7420746f2072657761726420697320746f6f2062696700000000006044820152606401610e0f565b61239a3330836004868154811061237857612378615dee565b60009182526020909120600790910201546001600160a01b03169291906143a9565b6123b181600484815481106122f2576122f2615dee565b600483815481106123c4576123c4615dee565b90600052602060002090600702016006018190555080827f66a9deaf092dcf4f0e1ca57edbef82d4eb4df8fdd6501dc30018338a4b8f625a60405160405180910390a35050565b6016546000828152600e602090815260408083203384529091529020546124329190615cef565b42116124805760405162461bcd60e51b815260206004820152601e60248201527f70656e64696e67207769746864726177207265717565737420657869737400006044820152606401610e0f565b60175461248d9042615cef565b6000828152600e6020908152604080832033808552925280832084905551909184917f13be99dfb4b71705ce15b8b7b83d0b8aa95b5ffb84bb2830a7e2b6b858c7218e9190a450565b6000816124f4576117096124eb600143615d3a565b43600180613714565b611709612502600143615d3a565b436004612510600187615d3a565b8154811061252057612520615dee565b906000526020600020906007020160010154600560016005805490506125469190615d3a565b8154811061255657612556615dee565b906000526020600020906002020160010154613714565b6125756151bb565b600082815260086020908152604091829020825161016081018452815460a08201908152600183015460c0830152600283015460e083015260038301546101008301526004830154610120830152600583015461014083015281526006820180548551818602810186019096528086529194929385810193929083018282801561261e57602002820191906000526020600020905b81548152602001906001019080831161260a575b5050509183525050600782015460ff16151560208201526008820154604082015260099091015460609091015292915050565b60008181526009602052604090205481906001600160a01b031633146126895760405162461bcd60e51b8152600401610e0f90615a45565b506000908152600860205260409020600701805460ff19166001179055565b60008281526009602052604090205482906001600160a01b031633146126e05760405162461bcd60e51b8152600401610e0f90615a45565b6000838152600d602052604090205483906001600160a01b0316156127175760405162461bcd60e51b8152600401610e0f90615acd565b612720836140cc565b600f60008681526020019081526020016000206001019080519060200190612749929190615180565b506000848152600f6020526040908190204290819055905185917f58f0d300eb5324931fe020560b51830bc4ead10b19467f5d56af8083eed98d48916127909187916159c9565b60405180910390a250505050565b604080516103208101825261113d808252602082015261227991810191909152611e6c6060820152611ad960808201526117b160a08201526114e960c082015261127460e0820152611049610100820152610e5f610120820152610caf610140820152610b316101608201526109e06101808201526108b76101a08201526107b16101c08201526106ca6101e08201526105fe6102008201526105496102208201526104aa61024082015261041e6102608201526103a26102808201526103356102a08201526102d46102c082015261027f6102e082015260006103008201819052906019827f00000000000000000000000000000000000000000000000000000000000000006128cf7f000000000000000000000000000000000000000000000000000000000000000088615d3a565b6128d99190615d07565b6128e4906001615cef565b90505b818110156129ab5760007f000000000000000000000000000000000000000000000000000000000000000061293c837f0000000000000000000000000000000000000000000000000000000000000000615d1b565b6129469190615cef565b905080861161295557506129ab565b83612961600184615d3a565b6019811061297157612971615dee565b60200201516129808883615d3a565b61298a9190615d1b565b6129949086615cef565b9096509350806129a381615d7d565b9150506128e7565b828282116129c3576129be600183615d3a565b6129ce565b6129ce600184615d3a565b601981106129de576129de615dee565b60200201516129ed8787615d3a565b6129f79190615d1b565b612a019085615cef565b9695505050505050565b60008060048481548110612a2157612a21615dee565b60009182526020808320878452600780835260408086206001600160a01b038a168752909352919093209102909101600381015460028201549193509043118015612a70575060008360040154115b15612ac2576000612a928785600201546001600580549050610d4c9190615d3a565b9050612abe612ab785600401546115aa64e8d4a51000856139f390919063ffffffff16565b8390613d34565b9150505b612a018260010154612aea64e8d4a510006115aa8587600001546139f390919063ffffffff16565b90613d40565b6000546001600160a01b03163314612b1a5760405162461bcd60e51b8152600401610e0f90615aa4565b6000828152600d602052604090205482906001600160a01b031615612b515760405162461bcd60e51b8152600401610e0f90615acd565b601354601454612b619082615cef565b612b6b9042615d98565b10612ba85760405162461bcd60e51b815260206004820152600d60248201526c1cd859995d1e481c195c9a5bd9609a1b6044820152606401610e0f565b612bb1826141ef565b60008381526008602090815260409182902084518155908401516001820155818401516002820155606084015160038201556080840151600482015560a08401516005909101555183907fe0fe09d9a25d5360154efb63f8f8c43a9cf25b0e4715d7f9ee42b362d99c941f906118ec908590615bb0565b612c616040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060c0016040528061177081526020016107d081526020016101f48152602001600081526020016103e881526020016101f4815250905090565b6122ac8160006143e7565b6000546001600160a01b03163314612cd35760405162461bcd60e51b8152600401610e0f90615aa4565b60006001600160a01b031660048681548110612cf157612cf1615dee565b60009182526020909120600790910201546001600160a01b03161415612d4f5760405162461bcd60e51b81526020600482015260136024820152721c1bdbdb08191bd95cc81b9bdd08195e1a5cdd606a1b6044820152606401610e0f565b612d5985856145e7565b60008581526010602052604090819020805460ff19168415151790555183151590859087907fd01a08be7ba6451f751cf523b54675f30a2c5ea6fa6bd909c2fd57f296fef0b5906112b8908690615a32565b6000546001600160a01b03163314612dd55760405162461bcd60e51b8152600401610e0f90615aa4565b600060048581548110612dea57612dea615dee565b600091825260208083206007909202909101546001600160a01b03908116808452600a83526040808520549289168552600b8452808520828652845280852054600c909452842054909450909290612e4690611aac8585613d34565b905060008111612e895760405162461bcd60e51b815260206004820152600e60248201526d616d6f756e74206973207a65726f60901b6044820152606401610e0f565b6001600160a01b038085166000818152600a60209081526040808320839055600c8252808320839055938b168252600b815283822092825291909152908120819055612ed78286888a614781565b90506000612ee9836115aa84886139f3565b90508015612f6c57604051630852cd8d60e31b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342966c6890602401600060405180830381600087803b158015612f5357600080fd5b505af1158015612f67573d6000803e3d6000fd5b505050505b80838b7f4f255c8cf5a84786ddc35d528b4df336f3aad1b61d63615fd8b228a39548cc9360405160405180910390a4600080612fac856115aa86896139f3565b9050801561314b577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e95cd0517f000000000000000000000000000000000000000000000000000000000000000061dead8e85426011600001544261301b9190615cef565b6012546040516001600160e01b031960e08a901b168152613050979695949392919060009081906002906001906004016158c7565b602060405180830381600087803b15801561306a57600080fd5b505af115801561307e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a291906153c5565b60405163a9059cbb60e01b81526001600160a01b038083166004830152602482018490529193507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb90604401602060405180830381600087803b15801561311157600080fd5b505af1158015613125573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613149919061541b565b505b848b6001600160a01b03168d7f5130497d6ba2833abd6dbfb4eb1a4bfa30540ea493ee0f3c811e44ff829697dc848660405161319a9291909182526001600160a01b0316602082015260400190565b60405180910390a47f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6131e36000546001600160a01b031690565b6131f186612aea8987613d40565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b15801561323757600080fd5b505af115801561324b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061326f919061541b565b50505050505050505050505050565b6001600160a01b0381166132c85760405162461bcd60e51b8152602060048201526011602482015270636f6d6d6974746565206973207a65726f60781b6044820152606401610e0f565b6000546001600160a01b0316331480156132f957506000828152600960205260409020546001600160a01b03163314155b156133655760008281526008602052604090206007015460ff16156133605760405162461bcd60e51b815260206004820152601c60248201527f436f6d6d697474656520616c726561647920636865636b656420696e000000006044820152606401610e0f565b6133bc565b6000828152600960205260409020546001600160a01b031633146133bc5760405162461bcd60e51b815260206004820152600e60248201526d4f6e6c7920636f6d6d697474656560901b6044820152606401610e0f565b60008281526009602052604080822080546001600160a01b0319166001600160a01b0385169081179091559051909184917f2d56897538f0fc982e13469f511616bed63e0c8f65a75270ba4346266b50f2a59190a35050565b6000546001600160a01b0316331461343f5760405162461bcd60e51b8152600401610e0f90615aa4565b6000908152600d6020526040812080546001600160a01b03199081168255600182019290925560020180549091169055565b6005818154811061348157600080fd5b60009182526020909120600290910201805460019091015490915082565b6004548111156134e95760405162461bcd60e51b8152602060048201526015602482015274706f6f6c2072616e676520697320746f6f2062696760581b6044820152606401610e0f565b8082111561352e5760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420706f6f6c2072616e676560701b6044820152606401610e0f565b815b818110156135515761354181612049565b61354a81615d7d565b9050613530565b5060408051838152602081018390527fd3f7645e6170879584cabe5bb42b1c424830ab0646a05d1d90bf6f641dc2e3d8910160405180910390a15050565b6000546001600160a01b031633146135b95760405162461bcd60e51b8152600401610e0f90615aa4565b62ed4e0082106135db5760405162461bcd60e51b8152600401610e0f90615afd565b600081116135fb5760405162461bcd60e51b8152600401610e0f90615a6d565b8082101561361b5760405162461bcd60e51b8152600401610e0f90615b34565b60118290556012819055604051819083907fa3d5527033c65a7e5eda0ffec2fe75b8bfc358a419914452e5e29993f531136d90600090a35050565b60008281526010602052604090205460ff16156136a65760405162461bcd60e51b815260206004820152600e60248201526d19195c1bdcda5d081c185d5cd95960921b6044820152606401610e0f565b620f42408110156136f05760405162461bcd60e51b815260206004820152601460248201527330b6b7bab73a103632b9b9903a3430b71018b29b60611b6044820152606401610e0f565b6000828152600e6020908152604080832033845290915281205561190c82826143e7565b600081156137605761375d60646115aa846115aa876137577f00000000000000000000000000000000000000000000000000000000000000006137578d8d61279e565b906139f3565b90505b949350505050565b6000546001600160a01b031633146137925760405162461bcd60e51b8152600401610e0f90615aa4565b6202a3008110156137da5760405162461bcd60e51b815260206004820152601260248201527119195b185e481a5cc81d1bdbc81cda1bdc9d60721b6044820152606401610e0f565b601555565b600080600485815481106137f5576137f5615dee565b906000526020600020906007020160010154905060006004868154811061381e5761381e615dee565b90600052602060002090600702016005015490505b838110156138a8576000600561384a836001615cef565b8154811061385a5761385a615dee565b906000526020600020906002020160000154905061389161388a8783866005878154811061255657612556615dee565b8590613d34565b9095509250806138a081615d7d565b915050613833565b6138cb6138c48643856005868154811061255657612556615dee565b8490613d34565b925050505b9392505050565b60185415613964576018543410156139285760405162461bcd60e51b81526020600482015260146024820152731b9bdd08195b9bdd59da08199959481c185e595960621b6044820152606401610e0f565b600080546040516001600160a01b03909116913480156108fc02929091818181858888f19350505050158015613962573d6000803e3d6000fd5b505b336001600160a01b03167fc8fdf13a4b928b8811a082d6f49538b13d9279cc130d1312406e8fa8742997358260405161399d9190615a32565b60405180910390a250565b600080546001600160a01b0319166001600160a01b03831690811782556040519091907fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a908290a350565b60006138d08284615d1b565b60006138d08284615d07565b6000818152600d602052604090205481906001600160a01b031615613a425760405162461bcd60e51b8152600401610e0f90615acd565b601354601454613a529082615cef565b613a5c9042615d98565b10613a995760405162461bcd60e51b815260206004820152600d60248201526c1cd859995d1e481c195c9a5bd9609a1b6044820152606401610e0f565b6000828152600e6020908152604080832033845290915290205442118015613ae657506016546000838152600e60209081526040808320338452909152902054613ae39190615cef565b42105b613b325760405162461bcd60e51b815260206004820152601a60248201527f77697468647261772072657175657374206e6f742076616c69640000000000006044820152606401610e0f565b506000908152600e60209081526040808320338452909152812055565b60026003541415613b725760405162461bcd60e51b8152600401610e0f90615b79565b6002600381905550600060048381548110613b8f57613b8f615dee565b6000918252602080832086845260078083526040808620338752909352919093208054929091029092019250831115613c145760405162461bcd60e51b815260206004820152602160248201527f77697468647261773a206e6f7420656e6f75676820757365722062616c616e636044820152606560f81b6064820152608401610e0f565b613c1d84612049565b6000613c4b8260010154612aea64e8d4a510006115aa876003015487600001546139f390919063ffffffff16565b90508015613c5e57613c5e338287614cbd565b8315613cd1578154613c709085613d40565b825560048301546006840154600091613c8e916115aa9088906139f3565b6006850154909150613ca09082613d40565b60068501558354613cbb906001600160a01b03163383613d4c565b6004840154613cca9086613d40565b6004850155505b60038301548254613cec9164e8d4a51000916115aa916139f3565b6001830155604051848152859033907ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5689060200160405180910390a350506001600355505050565b60006138d08284615cef565b60006138d08284615d3a565b6040516001600160a01b038316602482015260448101829052613daf90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614f35565b505050565b6001600160a01b03811660009081526006602052604090205415613e2d5760405162461bcd60e51b815260206004820152602a60248201527f4841544d61737465723a3a6164643a206c70546f6b656e20697320616c726561604482015269191e481a5b881c1bdbdb60b21b6064820152608401610e0f565b600454613e3b906001615cef565b6001600160a01b0382166000908152600660205260408120919091557f00000000000000000000000000000000000000000000000000000000000000004311613ea4577f0000000000000000000000000000000000000000000000000000000000000000613ea6565b435b60055490915060009015613eff5760058054613efa918691613eca90600190615d3a565b81548110613eda57613eda615dee565b906000526020600020906002020160010154613d3490919063ffffffff16565b613f01565b835b60055490915015801590613f47575060058054439190613f2390600190615d3a565b81548110613f3357613f33615dee565b906000526020600020906002020160000154145b15613f895760058054829190613f5f90600190615d3a565b81548110613f6f57613f6f615dee565b906000526020600020906002020160010181905550614000565b60408051808201909152438152602081018281526005805460018101825560009190915291517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0600290930292830155517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db1909101555b60046040518060e00160405280856001600160a01b03168152602001868152602001848152602001600081526020016000815260200160016005805490506140489190615d3a565b81526000602091820181905283546001808201865594825290829020835160079092020180546001600160a01b0319166001600160a01b03909216919091178155908201519281019290925560408101516002830155606081015160038301556080810151600483015560a0810151600583015560c0015160069091015550505050565b606060008251600014156141505760408051600480825260a0820190925290602082016080803683370190505091505b600481101561414b57614110816001615cef565b61411c906107d0615d1b565b82828151811061412e5761412e615dee565b60209081029190910101528061414381615d7d565b9150506140fc565b6141e9565b82518110156141e55761271083828151811061416e5761416e615dee565b6020026020010151106141d35760405162461bcd60e51b815260206004820152602760248201527f726577617264206c6576656c2063616e206e6f74206265206d6f72652074686160448201526606e2031303030360cc1b6064820152608401610e0f565b806141dd81615d7d565b915050614150565b8291505b50919050565b61271061422d8260a00151611aac8460800151611aac8660600151611aac8860400151611aac8a602001518b60000151613d3490919063ffffffff16565b146122ac5760405162461bcd60e51b815260206004820152601d60248201527f746f74616c2073706c697420252073686f756c642062652031303030300000006044820152606401610e0f565b60006004828154811061428f5761428f615dee565b60009182526020808320858452600780835260408086203387529093529190932080549290910290920192506142f95760405162461bcd60e51b815260206004820152600f60248201526e0757365722e616d6f756e74203d203608c1b6044820152606401610e0f565b600061431e83600401546115aa856006015485600001546139f390919063ffffffff16565b825460048501549192506143329190613d40565b60048401556000808355600183015560068301546143509082613d40565b6006840155825461436b906001600160a01b03163383613d4c565b604051818152849033907fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae0595906020015b60405180910390a350505050565b6040516001600160a01b03808516602483015283166044820152606481018290526143e19085906323b872dd60e01b90608401613d78565b50505050565b6002600354141561440a5760405162461bcd60e51b8152600401610e0f90615b79565b600260035560008281526008602052604090206007015460ff166144705760405162461bcd60e51b815260206004820152601c60248201527f636f6d6d6974746565206e6f7420636865636b656420696e20796574000000006044820152606401610e0f565b60006004838154811061448557614485615dee565b600091825260208083208684526007808352604080862033875290935291909320910290910191506144b684612049565b8054156145005760006144eb8260010154612aea64e8d4a510006115aa876003015487600001546139f390919063ffffffff16565b905080156144fe576144fe338287614cbd565b505b82156145855760068201548254614522906001600160a01b03163330876143a9565b60068301546145319085613d34565b600684015560048301548490156145605761455d826115aa8787600401546139f390919063ffffffff16565b90505b825461456c9082613d34565b8355600484015461457d9082613d34565b600485015550505b600382015481546145a09164e8d4a51000916115aa916139f3565b6001820155604051838152849033907f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159060200160405180910390a3505060016003555050565b6145f082612049565b600061466282611aac6004868154811061460c5761460c615dee565b906000526020600020906007020160010154600560016005805490506146329190615d3a565b8154811061464257614642615dee565b906000526020600020906002020160010154613d4090919063ffffffff16565b60058054919250439161467790600190615d3a565b8154811061468757614687615dee565b90600052602060002090600202016000015414156146dc57600580548291906146b290600190615d3a565b815481106146c2576146c2615dee565b906000526020600020906002020160010181905550614753565b60408051808201909152438152602081018281526005805460018101825560009190915291517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0600290930292830155517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db1909101555b816004848154811061476757614767615dee565b906000526020600020906007020160010181905550505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614156147c4575083613760565b60405163095ea7b360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820187905285169063095ea7b390604401602060405180830381600087803b15801561482e57600080fd5b505af1158015614842573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614866919061541b565b6148a95760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b88185c1c1c9bdd994819985a5b195960621b6044820152606401610e0f565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561490b57600080fd5b505afa15801561491f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149439190615486565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634aa4a4fc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156149a057600080fd5b505afa1580156149b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149d891906153c5565b90506060816001600160a01b0316876001600160a01b03161415614a6f578551604051606089811b6bffffffffffffffffffffffff19908116602084015260e89390931b6001600160e81b03191660348301527f0000000000000000000000000000000000000000000000000000000000000000901b9091166037820152604b016040516020818303038152906040529050614b02565b855160208088015160405160608b811b6bffffffffffffffffffffffff199081169483019490945260e894851b6001600160e81b0319908116603484015287821b851660378401529290941b909116604b8201527f000000000000000000000000000000000000000000000000000000000000000090921b16604e82015260620160405160208183030381529060405290505b6040805160a0810182528281523060208201524281830152606081018a905260808101879052905163c04b8d5960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163c04b8d5991614b729190600401615bbe565b602060405180830381600087803b158015614b8c57600080fd5b505af1158015614ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614bc49190615486565b6040516370a0823160e01b8152306004820152909450859084906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b158015614c2a57600080fd5b505afa158015614c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c629190615486565b614c6c9190615d3a565b1015614cb25760405162461bcd60e51b81526020600482015260156024820152741ddc9bdb99c8185b5bdd5b9d081c9958d95a5d9959605a1b6044820152606401610e0f565b505050949350505050565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b158015614d1f57600080fd5b505afa158015614d33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d579190615486565b905080831115614e4f5760405163a9059cbb60e01b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90604401602060405180830381600087803b158015614dcb57600080fd5b505af1158015614ddf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e03919061541b565b50604080518281526020810185905283916001600160a01b038716917fee9cbb749817d7aa2d7b761a12c7789e3f9ac46e77f63c47e4f5f21da5e7cf0b910160405180910390a36143e1565b60405163a9059cbb60e01b81526001600160a01b038581166004830152602482018590527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90604401602060405180830381600087803b158015614eb957600080fd5b505af1158015614ecd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ef1919061541b565b50604080518481526020810185905283916001600160a01b038716917fee9cbb749817d7aa2d7b761a12c7789e3f9ac46e77f63c47e4f5f21da5e7cf0b910161439b565b6000614f8a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166150079092919063ffffffff16565b805190915015613daf5780806020019051810190614fa8919061541b565b613daf5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e0f565b6060613760848460008585843b6150605760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e0f565b600080866001600160a01b0316858760405161507c91906158ab565b60006040518083038185875af1925050503d80600081146150b9576040519150601f19603f3d011682016040523d82523d6000602084013e6150be565b606091505b50915091506150ce8282866150d9565b979650505050505050565b606083156150e85750816138d0565b8251156150f85782518084602001fd5b8160405162461bcd60e51b8152600401610e0f9190615a32565b8280548282559060005260206000209081019282156151525760005260206000209182015b82811115615152578254825591600101919060010190615137565b5061515e929150615223565b5090565b50805460008255906000526020600020908101906122ac9190615223565b828054828255906000526020600020908101928215615152579160200282015b828111156151525782518255916020019190600101906151a0565b6040518060a001604052806151ff6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b81526020016060815260200160001515815260200160008152602001600081525090565b5b8082111561515e5760008155600101615224565b600082601f83011261524957600080fd5b8135602067ffffffffffffffff82111561526557615265615e04565b8160051b615274828201615cbe565b83815282810190868401838801850189101561528f57600080fd5b600093505b858410156152b2578035835260019390930192918401918401615294565b50979650505050505050565b600082601f8301126152cf57600080fd5b813567ffffffffffffffff8111156152e9576152e9615e04565b6152fc601f8201601f1916602001615cbe565b81815284602083860101111561531157600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561534057600080fd5b60405160c0810181811067ffffffffffffffff8211171561536357615363615e04565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a08201525092915050565b6000602082840312156153ba57600080fd5b81356138d081615e1a565b6000602082840312156153d757600080fd5b81516138d081615e1a565b600080604083850312156153f557600080fd5b823561540081615e1a565b9150602083013561541081615e1a565b809150509250929050565b60006020828403121561542d57600080fd5b81516138d081615e2f565b60006020828403121561544a57600080fd5b813567ffffffffffffffff81111561546157600080fd5b613760848285016152be565b60006020828403121561547f57600080fd5b5035919050565b60006020828403121561549857600080fd5b5051919050565b600080604083850312156154b257600080fd5b82359150602083013561541081615e1a565b60008060008060008060006101a080898b0312156154e157600080fd5b883597506020808a01356154f481615e1a565b975060408a013561550481615e1a565b965060608a013567ffffffffffffffff8082111561552157600080fd5b61552d8d838e01615238565b975061553c8d60808e0161532e565b96506101408c013591508082111561555357600080fd5b506155608c828d016152be565b9450508a61017f8b011261557357600080fd5b61557b615c95565b806101608c018d858e01111561559057600080fd5b600094505b60028510156155b4578035835260019490940193918301918301615595565b508094505050505092959891949750929550565b6000806000606084860312156155dd57600080fd5b8335925060208401356155ef81615e1a565b929592945050506040919091013590565b60008060008060a0858703121561561657600080fd5b8435935060208086013561562981615e1a565b935060408601359250607f8601871361564157600080fd5b615649615c95565b80606088018960a08a01111561565e57600080fd5b6000805b600281101561568f57823562ffffff8116811461567d578283fd5b85529385019391850191600101615662565b50979a969950949750955050505050565b600080604083850312156156b357600080fd5b82359150602083013567ffffffffffffffff8111156156d157600080fd5b6156dd85828601615238565b9150509250929050565b60008060e083850312156156fa57600080fd5b8235915061570b846020850161532e565b90509250929050565b6000806040838503121561572757600080fd5b50508035926020909101359150565b600080600080600060a0868803121561574e57600080fd5b8535945060208601359350604086013561576781615e2f565b9250606086013561577781615e2f565b9150608086013567ffffffffffffffff81111561579357600080fd5b61579f888289016152be565b9150509295509295909350565b6000806000606084860312156157c157600080fd5b505081359360208301359350604090920135919050565b600080600080608085870312156157ee57600080fd5b5050823594602084013594506040840135936060013592509050565b600081518084526020808501945080840160005b8381101561583a5781518752958201959082019060010161581e565b509495945050505050565b6000815180845261585d816020860160208601615d51565b601f01601f19169290920160200192915050565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b600082516158bd818460208701615d51565b9190910192915050565b6001600160a01b038c811682528b811660208301528a166040820152606081018990526080810188905260a0810187905260c0810186905260e08101859052610100810184905261016081016003841061593157634e487b7160e01b600052602160045260246000fd5b8361012083015261594761014083018415159052565b9c9b505050505050505050505050565b6001600160a01b03871681526101606020820181905260009061597c83820189615845565b90508281036040840152615990818861580a565b9150506159a06060830186615871565b6101208201939093526101400152949350505050565b6020815260006138d0602083018461580a565b6040815260006159dc604083018561580a565b90508260208301529392505050565b6020808252825482820181905260008481528281209092916040850190845b81811015615a2657835483526001938401939285019201615a0a565b50909695505050505050565b6020815260006138d06020830184615845565b6020808252600e908201526d6f6e6c7920636f6d6d697474656560901b604082015260600190565b6020808252601e908201527f76657374696e6720706572696f64732063616e6e6f74206265207a65726f0000604082015260600190565b6020808252600f908201526e6f6e6c7920676f7665726e616e636560881b604082015260600190565b6020808252601690820152751c195b991a5b99c8185c1c1c9bdd985b08195e1a5cdd60521b604082015260600190565b6020808252601c908201527f76657374696e67206475726174696f6e20697320746f6f206c6f6e6700000000604082015260600190565b60208082526025908201527f76657374696e67206475726174696f6e20736d616c6c6572207468616e20706560408201526472696f647360d81b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60c081016117098284615871565b602081526000825160a06020840152615bda60c0840182615845565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b60208152615c28602082018351615871565b600060208301516101408060e0850152615c4661016085018361580a565b6040860151151561010086015260608601516101208601526080909501519301929092525090919050565b8381526001600160a01b038316602082015261010081016137606040830184615871565b6040805190810167ffffffffffffffff81118282101715615cb857615cb8615e04565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715615ce757615ce7615e04565b604052919050565b60008219821115615d0257615d02615dc2565b500190565b600082615d1657615d16615dd8565b500490565b6000816000190483118215151615615d3557615d35615dc2565b500290565b600082821015615d4c57615d4c615dc2565b500390565b60005b83811015615d6c578181015183820152602001615d54565b838111156143e15750506000910152565b6000600019821415615d9157615d91615dc2565b5060010190565b600082615da757615da7615dd8565b500690565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146122ac57600080fd5b80151581146122ac57600080fdfea264697066735822122079009a8ae3b9731756933a98158ca9c0485be9ead682ff201ad5eb91827e847764736f6c63430008060033000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c000000000000000000000000000000000000000000000000003980c218c3c0000000000000000000000000000000000000000000000000000000000000c52b10000000000000000000000000000000000000000000000000000000000002fa80000000000000000000000000a13ddfa63774c5b982d2c3e92fde3b660616ffcd000000000000000000000000e592427a0aece92de3edee1f18e0157c058615640000000000000000000000002c7daec5b1c6157c2b37b2505d5d57d6d075e39e
Deployed Bytecode
0x6080604052600436106103c35760003560e01c806382b0617d116101f2578063cbd42a701161010d578063eabcff2c116100a0578063f3fe12c91161006f578063f3fe12c914610d51578063f5e820fd14610d64578063f7cd531914610d9a578063fcecc73814610dce57600080fd5b8063eabcff2c14610cda578063ebb6bc7214610cfa578063f19451d814610d1a578063f26ae82714610d3157600080fd5b8063dd072f03116100dc578063dd072f0314610bf4578063df1b1ebe14610c14578063e02ff8f214610c82578063e2bbb15814610cba57600080fd5b8063cbd42a7014610b71578063ce2529c914610b91578063d2369c6514610bbe578063da42757814610bd457600080fd5b806399f9b05a11610185578063b2e629c711610154578063b2e629c714610af1578063b9a4bdb414610b11578063be75e74f14610b31578063c7b5184a14610b5157600080fd5b806399f9b05a14610a645780639c2a7a6d14610a9c578063aa0cd25c14610abc578063ae169a5014610ad157600080fd5b806393f1a40b116101c157806393f1a40b1461098f57806395fec613146109e3578063975532dc14610a1057806398969e8214610a4457600080fd5b806382b0617d1461090257806383867c1b1461092f57806384fcf8e51461094f5780638dbb1e3a1461096f57600080fd5b8063398488eb116102e2578063520a924d11610275578063686b656e11610244578063686b656e146108315780636e419506146108a257806374899a7e146108c25780637b550bc9146108e257600080fd5b8063520a924d1461079f5780635312ea8e146107bf5780635aa6e675146107df5780635d01ff3d146107fd57600080fd5b8063441a3e70116102b1578063441a3e701461071f57806346e301351461073f5780634f8d45ee1461075f57806351eb05a61461077f57600080fd5b8063398488eb1461068b57806339b3e826146106ab5780633a71ede8146106df5780633d8a0906146106ff57600080fd5b80631d46446a1161035a5780633207b103116103295780633207b103146105d057806334333058146105fd5780633449a8651461062a57806335bbf3161461065e57600080fd5b80631d46446a146105435780632a5ad7d0146105635780632b2f4d84146105905780632e75ab50146105b057600080fd5b80630d2edde2116103965780630d2edde21461046357806311c2aae31461047857806313401551146104c45780631526fe27146104e457600080fd5b8063081e3eda146103c85780630abb6035146103ec5780630af937f21461040e5780630b346a9e1461044e575b600080fd5b3480156103d457600080fd5b506004545b6040519081526020015b60405180910390f35b3480156103f857600080fd5b5061040c6104073660046153a8565b610de5565b005b34801561041a57600080fd5b5061043e61042936600461546d565b60106020526000908152604090205460ff1681565b60405190151581526020016103e3565b34801561045a57600080fd5b506005546103d9565b34801561046f57600080fd5b5061040c610eee565b34801561048457600080fd5b506104ac7f0000000000000000000000002c7daec5b1c6157c2b37b2505d5d57d6d075e39e81565b6040516001600160a01b0390911681526020016103e3565b3480156104d057600080fd5b506001546104ac906001600160a01b031681565b3480156104f057600080fd5b506105046104ff36600461546d565b611052565b604080516001600160a01b0390981688526020880196909652948601939093526060850191909152608084015260a083015260c082015260e0016103e3565b34801561054f57600080fd5b5061040c61055e3660046155c8565b6110ab565b34801561056f57600080fd5b506103d961057e3660046153a8565b600c6020526000908152604090205481565b34801561059c57600080fd5b5061040c6105ab3660046157ac565b6112c7565b3480156105bc57600080fd5b5061040c6105cb36600461546d565b6113a1565b3480156105dc57600080fd5b506105f06105eb36600461546d565b6113d0565b6040516103e391906159b6565b34801561060957600080fd5b5061061d610618366004615714565b611435565b6040516103e39190615bb0565b34801561063657600080fd5b506104ac7f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c81565b34801561066a57600080fd5b506103d961067936600461546d565b600f6020526000908152604090205481565b34801561069757600080fd5b5061040c6106a6366004615714565b6116b0565b3480156106b757600080fd5b506103d97f0000000000000000000000000000000000000000000000000000000000c52b1081565b3480156106eb57600080fd5b506103d96106fa36600461549f565b6116e5565b34801561070b57600080fd5b5061040c61071a36600461546d565b61170f565b34801561072b57600080fd5b5061040c61073a366004615714565b6118f9565b34801561074b57600080fd5b5061040c61075a36600461546d565b611910565b34801561076b57600080fd5b5061040c61077a3660046154c4565b611d96565b34801561078b57600080fd5b5061040c61079a36600461546d565b612049565b3480156107ab57600080fd5b5061040c6107ba366004615714565b612235565b3480156107cb57600080fd5b5061040c6107da36600461546d565b61229a565b3480156107eb57600080fd5b506000546001600160a01b03166104ac565b34801561080957600080fd5b506104ac7f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156481565b34801561083d57600080fd5b5061087861084c36600461546d565b600d602052600090815260409020805460018201546002909201546001600160a01b0391821692911683565b604080516001600160a01b03948516815260208101939093529216918101919091526060016103e3565b3480156108ae57600080fd5b5061040c6108bd366004615714565b6122af565b3480156108ce57600080fd5b5061040c6108dd36600461546d565b61240b565b3480156108ee57600080fd5b506103d96108fd36600461546d565b6124d6565b34801561090e57600080fd5b5061092261091d36600461546d565b61256d565b6040516103e39190615c16565b34801561093b57600080fd5b5061040c61094a36600461546d565b612651565b34801561095b57600080fd5b5061040c61096a3660046156a0565b6126a8565b34801561097b57600080fd5b506103d961098a366004615714565b61279e565b34801561099b57600080fd5b506109ce6109aa36600461549f565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016103e3565b3480156109ef57600080fd5b506103d96109fe3660046153a8565b600a6020526000908152604090205481565b348015610a1c57600080fd5b506103d97f000000000000000000000000000000000000000000000000003980c218c3c00081565b348015610a5057600080fd5b506103d9610a5f36600461549f565b612a0b565b348015610a7057600080fd5b506103d9610a7f3660046153e2565b600b60209081526000928352604080842090915290825290205481565b348015610aa857600080fd5b5061040c610ab73660046156e7565b612af0565b348015610ac857600080fd5b5061061d612c28565b348015610add57600080fd5b5061040c610aec36600461546d565b612c9e565b348015610afd57600080fd5b5061040c610b0c366004615736565b612ca9565b348015610b1d57600080fd5b5061040c610b2c366004615600565b612dab565b348015610b3d57600080fd5b5061040c610b4c36600461549f565b61327e565b348015610b5d57600080fd5b5061040c610b6c36600461546d565b613415565b348015610b7d57600080fd5b506109ce610b8c36600461546d565b613471565b348015610b9d57600080fd5b506103d9610bac3660046153a8565b60066020526000908152604090205481565b348015610bca57600080fd5b506103d960025481565b348015610be057600080fd5b5061040c610bef366004615714565b61349f565b348015610c0057600080fd5b5061040c610c0f366004615714565b61358f565b348015610c2057600080fd5b50601154601254601354601454601554601654601754601854610c47979695949392919088565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c083015260e0820152610100016103e3565b348015610c8e57600080fd5b506103d9610c9d36600461549f565b600e60209081526000928352604080842090915290825290205481565b348015610cc657600080fd5b5061040c610cd5366004615714565b613656565b348015610ce657600080fd5b506103d9610cf53660046157d8565b613714565b348015610d0657600080fd5b5061040c610d1536600461546d565b613768565b348015610d2657600080fd5b506103d9620f424081565b348015610d3d57600080fd5b506103d9610d4c3660046157ac565b6137df565b61040c610d5f366004615438565b6138d7565b348015610d7057600080fd5b506104ac610d7f36600461546d565b6009602052600090815260409020546001600160a01b031681565b348015610da657600080fd5b506103d97f000000000000000000000000000000000000000000000000000000000002fa8081565b348015610dda57600080fd5b506103d96202a30081565b6000546001600160a01b03163314610e185760405162461bcd60e51b8152600401610e0f90615aa4565b60405180910390fd5b6001600160a01b038116610e845760405162461bcd60e51b815260206004820152602d60248201527f476f7665726e61626c653a6e657720676f7665726e616e63652069732074686560448201526c207a65726f206164647265737360981b6064820152608401610e0f565b600180546001600160a01b038084166001600160a01b03199092168217909255426002819055600054604051929316917f6dedeac5137d4e7301332bf2cbe80d9997406cff0e2b3634c9f8c47a49989ba991610ee39190815260200190565b60405180910390a350565b6000546001600160a01b03163314610f185760405162461bcd60e51b8152600401610e0f90615aa4565b600060025411610f745760405162461bcd60e51b815260206004820152602160248201527f476f7665726e61626c653a206e6f2070656e64696e6720676f7665726e616e636044820152606560f81b6064820152608401610e0f565b6202a30060025442610f869190615d3a565b11610fee5760405162461bcd60e51b815260206004820152603260248201527f476f7665726e61626c653a2063616e6e6f7420636f6e6669726d20676f7665726044820152716e616e636520617420746869732074696d6560701b6064820152608401610e0f565b600154600080546040516001600160a01b0393841693909116917fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a91a3600154600080546001600160a01b0319166001600160a01b03909216919091178155600255565b6004818154811061106257600080fd5b600091825260209091206007909102018054600182015460028301546003840154600485015460058601546006909601546001600160a01b039095169650929491939092919087565b60008381526009602052604090205483906001600160a01b031633146110e35760405162461bcd60e51b8152600401610e0f90615a45565b6000848152600d602052604090205484906001600160a01b03161561111a5760405162461bcd60e51b8152600401610e0f90615acd565b6001600160a01b0384166111665760405162461bcd60e51b815260206004820152601360248201527262656e6566696369617279206973207a65726f60681b6044820152606401610e0f565b6013546014546111769082615cef565b6111809042615d98565b10156111c35760405162461bcd60e51b81526020600482015260126024820152711b9bdb99481cd859995d1e481c195c9a5bd960721b6044820152606401610e0f565b60008581526008602052604090206006015483106112235760405162461bcd60e51b815260206004820152601d60248201527f5f7365766572697479206973206e6f7420696e207468652072616e67650000006044820152606401610e0f565b604080516060810182526001600160a01b0386811680835260208084018881523385870181815260008d8152600d8552889020965187549087166001600160a01b0319918216178855925160018801555160029096018054969095169590911694909417909255925191825285929188917fd878c70cbed9605353e23b13b6475a2e1ef3c7d976f8495f233a1a7f4bc6811c91015b60405180910390a45050505050565b6000546001600160a01b031633146112f15760405162461bcd60e51b8152600401610e0f90615aa4565b629e340082106113135760405162461bcd60e51b8152600401610e0f90615afd565b600081116113335760405162461bcd60e51b8152600401610e0f90615a6d565b808210156113535760405162461bcd60e51b8152600401610e0f90615b34565b60008381526008602081905260408083209182018590556009909101839055518291849186917fb2c473651bf0d98b7935f0a45d2e04d804b1d00c3131bf824fb1944ff9ae8e3c91a4505050565b6000546001600160a01b031633146113cb5760405162461bcd60e51b8152600401610e0f90615aa4565b601855565b60008181526008602090815260409182902060060180548351818402810184019094528084526060939283018282801561142957602002820191906000526020600020905b815481526020019060010190808311611415575b50505050509050919050565b61146e6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60006004848154811061148357611483615dee565b9060005260206000209060070201600601549050600081116114dd5760405162461bcd60e51b8152602060048201526013602482015272746f74616c537570706c79206973207a65726f60681b6044820152606401610e0f565b600084815260086020526040902060060154831061153d5760405162461bcd60e51b815260206004820152601d60248201527f5f7365766572697479206973206e6f7420696e207468652072616e67650000006044820152606401610e0f565b6000848152600860205260408120600601805461157f91908690811061156557611565615dee565b9060005260206000200154836139f390919063ffffffff16565b90506115b061159061271080615d1b565b6000878152600860205260409020546115aa9084906139f3565b906139ff565b83526115de6115c161271080615d1b565b6000878152600860205260409020600101546115aa9084906139f3565b602084015261160f6115f261271080615d1b565b6000878152600860205260409020600201546115aa9084906139f3565b604084015261164061162361271080615d1b565b6000878152600860205260409020600301546115aa9084906139f3565b606084015261167161165461271080615d1b565b6000878152600860205260409020600401546115aa9084906139f3565b60808401526116a261168561271080615d1b565b6000878152600860205260409020600501546115aa9084906139f3565b60a084015250909392505050565b6000546001600160a01b031633146116da5760405162461bcd60e51b8152600401610e0f90615aa4565b601791909155601655565b60008281526007602090815260408083206001600160a01b03851684529091529020545b92915050565b60008181526009602052604090205481906001600160a01b031633146117475760405162461bcd60e51b8152600401610e0f90615a45565b6000828152600d602052604090205482906001600160a01b03161561177e5760405162461bcd60e51b8152600401610e0f90615acd565b6000838152600f60205260409020546117d95760405162461bcd60e51b815260206004820152601d60248201527f6e6f2070656e64696e67207365742072657761726473206c6576656c730000006044820152606401610e0f565b6015546000848152600f60205260409020546117f59042615d3a565b116118575760405162461bcd60e51b815260206004820152602c60248201527f63616e6e6f7420636f6e6669726d20736574526577617264734c6576656c732060448201526b617420746869732074696d6560a01b6064820152608401610e0f565b6000838152600f60209081526040808320600890925290912060019091018054611885926006019190615112565b506000838152600f60205260408120818155906118a56001830182615162565b5050827f37234a2297757e81787ddd776e23606f74b9ecc8562ba691b9dde3adef5089cd600860008681526020019081526020016000206006016040516118ec91906159eb565b60405180910390a2505050565b61190282613a0b565b61190c8282613b4f565b5050565b6000546001600160a01b0316331461193a5760405162461bcd60e51b8152600401610e0f90615aa4565b6002600354141561195d5760405162461bcd60e51b8152600401610e0f90615b79565b60026003556000818152600d60205260409020546001600160a01b03166119bc5760405162461bcd60e51b81526020600482015260136024820152721b9bc81c195b991a5b99c8185c1c1c9bdd985b606a1b6044820152606401610e0f565b6000818152600860209081526040808320600d808452828520835160608101855281546001600160a01b038082168352600184018054848a0152600285018054928316988501989098528a8a52949097526001600160a01b0319908116909255918690559093169091556004805491939185908110611a3d57611a3d615dee565b60009182526020808320600790920290910154908401516001600160a01b039091169250611a6c908690611435565b9050611ae5611ab28260800151611aac8460a00151611aac8660600151611aac8860400151611aac8a600001518b60200151613d3490919063ffffffff16565b90613d34565b60048781548110611ac557611ac5615dee565b906000526020600020906007020160060154613d4090919063ffffffff16565b60048681548110611af857611af8615dee565b60009182526020822060066007909202010191909155815115611c02577f0000000000000000000000002c7daec5b1c6157c2b37b2505d5d57d6d075e39e6001600160a01b031663e95cd0518461dead87600001518660000151428b6008015442611b639190615cef565b8c60090154600080600260006040518c63ffffffff1660e01b8152600401611b959b9a999897969594939291906158c7565b602060405180830381600087803b158015611baf57600080fd5b505af1158015611bc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be791906153c5565b8251909150611c02906001600160a01b038516908390613d4c565b83516020830151611c1d916001600160a01b03861691613d4c565b60408085015190830151611c3b916001600160a01b03861691613d4c565b60608201516001600160a01b0384166000908152600a6020526040902054611c6291613d34565b6001600160a01b0384166000908152600a60209081526040808320939093556080850151600c90915291902054611c9891613d34565b6001600160a01b038085166000818152600c602090815260408083209590955560a087015189519094168252600b8152848220928252919091529190912054611ce091613d34565b84516001600160a01b039081166000908152600b6020908152604080832088851684528252918290209390935586519287015190519290911691889133917fb34d89b43b53d2ebac4aa01c9ab4b64aca3ca9612c3f79a58c6d2528e414775291611d4d9187908990615c71565b60405180910390a4600060048781548110611d6a57611d6a615dee565b90600052602060002090600702016006015411611d8957611d89615dac565b5050600160035550505050565b6000546001600160a01b03163314611dc05760405162461bcd60e51b8152600401610e0f90615aa4565b8051629e340011611de35760405162461bcd60e51b8152600401610e0f90615afd565b6020810151611e045760405162461bcd60e51b8152600401610e0f90615a6d565b602081015181511015611e295760405162461bcd60e51b8152600401610e0f90615b34565b6001600160a01b038516611e735760405162461bcd60e51b8152602060048201526011602482015270636f6d6d6974746565206973207a65726f60781b6044820152606401610e0f565b611e7d8787613db4565b600454600090611e8f90600190615d3a565b600081815260096020526040812080546001600160a01b0319166001600160a01b038a16179055909150611ec2866140cc565b8551909150600090158015611ed957506020860151155b611ee35785611eeb565b611eeb612c28565b9050611ef6816141ef565b6040518060a0016040528082815260200183815260200160001515815260200185600060028110611f2957611f29615dee565b6020020151815260200185600160028110611f4657611f46615dee565b60209081029190910151909152600085815260088252604090819020835180518255808401516001830155918201516002820155606082015160038201556080820151600482015560a09091015160058201558282015180519192611fb392600685019290910190615180565b50604082015160078201805460ff1916911515919091179055606082015160088201556080909101516009909101556001600160a01b0389168a847f101333dd96212851804793a854aef45352029659781cb05bddccb6815bd86dc78b8987878b600060200201518c6001602002015160405161203596959493929190615957565b60405180910390a450505050505050505050565b60006004828154811061205e5761205e615dee565b9060005260206000209060070201905060008160020154905080431161208357505050565b600482015460055460009061209a90600190615d3a565b9050816120b557436002850155600590930192909255505050565b60006120c28685846137df565b604051633d1bb33160e21b81523060048201529091506000906001600160a01b037f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c169063f46eccc49060240160206040518083038186803b15801561212757600080fd5b505afa15801561213b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215f9190615486565b905081811061216e5781612170565b805b915081156121f9576040516340c10f1960e01b8152306004820152602481018390527f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c6001600160a01b0316906340c10f1990604401600060405180830381600087803b1580156121e057600080fd5b505af11580156121f4573d6000803e3d6000fd5b505050505b61221a61220f856115aa8564e8d4a510006139f3565b600388015490613d34565b60038701555050436002850155600590930192909255505050565b6000546001600160a01b0316331461225f5760405162461bcd60e51b8152600401610e0f90615aa4565b60138290556014819055604051819083907f47c8a5b15f6172a5053bfac488642484dd38e9c0f3073c23c5d822c4cbab530990600090a35050565b6122a381613a0b565b6122ac8161427a565b50565b600482815481106122c2576122c2615dee565b906000526020600020906007020160040154612312620f42406115aa84600487815481106122f2576122f2615dee565b906000526020600020906007020160060154613d3490919063ffffffff16565b1061235f5760405162461bcd60e51b815260206004820152601b60248201527f616d6f756e7420746f2072657761726420697320746f6f2062696700000000006044820152606401610e0f565b61239a3330836004868154811061237857612378615dee565b60009182526020909120600790910201546001600160a01b03169291906143a9565b6123b181600484815481106122f2576122f2615dee565b600483815481106123c4576123c4615dee565b90600052602060002090600702016006018190555080827f66a9deaf092dcf4f0e1ca57edbef82d4eb4df8fdd6501dc30018338a4b8f625a60405160405180910390a35050565b6016546000828152600e602090815260408083203384529091529020546124329190615cef565b42116124805760405162461bcd60e51b815260206004820152601e60248201527f70656e64696e67207769746864726177207265717565737420657869737400006044820152606401610e0f565b60175461248d9042615cef565b6000828152600e6020908152604080832033808552925280832084905551909184917f13be99dfb4b71705ce15b8b7b83d0b8aa95b5ffb84bb2830a7e2b6b858c7218e9190a450565b6000816124f4576117096124eb600143615d3a565b43600180613714565b611709612502600143615d3a565b436004612510600187615d3a565b8154811061252057612520615dee565b906000526020600020906007020160010154600560016005805490506125469190615d3a565b8154811061255657612556615dee565b906000526020600020906002020160010154613714565b6125756151bb565b600082815260086020908152604091829020825161016081018452815460a08201908152600183015460c0830152600283015460e083015260038301546101008301526004830154610120830152600583015461014083015281526006820180548551818602810186019096528086529194929385810193929083018282801561261e57602002820191906000526020600020905b81548152602001906001019080831161260a575b5050509183525050600782015460ff16151560208201526008820154604082015260099091015460609091015292915050565b60008181526009602052604090205481906001600160a01b031633146126895760405162461bcd60e51b8152600401610e0f90615a45565b506000908152600860205260409020600701805460ff19166001179055565b60008281526009602052604090205482906001600160a01b031633146126e05760405162461bcd60e51b8152600401610e0f90615a45565b6000838152600d602052604090205483906001600160a01b0316156127175760405162461bcd60e51b8152600401610e0f90615acd565b612720836140cc565b600f60008681526020019081526020016000206001019080519060200190612749929190615180565b506000848152600f6020526040908190204290819055905185917f58f0d300eb5324931fe020560b51830bc4ead10b19467f5d56af8083eed98d48916127909187916159c9565b60405180910390a250505050565b604080516103208101825261113d808252602082015261227991810191909152611e6c6060820152611ad960808201526117b160a08201526114e960c082015261127460e0820152611049610100820152610e5f610120820152610caf610140820152610b316101608201526109e06101808201526108b76101a08201526107b16101c08201526106ca6101e08201526105fe6102008201526105496102208201526104aa61024082015261041e6102608201526103a26102808201526103356102a08201526102d46102c082015261027f6102e082015260006103008201819052906019827f000000000000000000000000000000000000000000000000000000000002fa806128cf7f0000000000000000000000000000000000000000000000000000000000c52b1088615d3a565b6128d99190615d07565b6128e4906001615cef565b90505b818110156129ab5760007f0000000000000000000000000000000000000000000000000000000000c52b1061293c837f000000000000000000000000000000000000000000000000000000000002fa80615d1b565b6129469190615cef565b905080861161295557506129ab565b83612961600184615d3a565b6019811061297157612971615dee565b60200201516129808883615d3a565b61298a9190615d1b565b6129949086615cef565b9096509350806129a381615d7d565b9150506128e7565b828282116129c3576129be600183615d3a565b6129ce565b6129ce600184615d3a565b601981106129de576129de615dee565b60200201516129ed8787615d3a565b6129f79190615d1b565b612a019085615cef565b9695505050505050565b60008060048481548110612a2157612a21615dee565b60009182526020808320878452600780835260408086206001600160a01b038a168752909352919093209102909101600381015460028201549193509043118015612a70575060008360040154115b15612ac2576000612a928785600201546001600580549050610d4c9190615d3a565b9050612abe612ab785600401546115aa64e8d4a51000856139f390919063ffffffff16565b8390613d34565b9150505b612a018260010154612aea64e8d4a510006115aa8587600001546139f390919063ffffffff16565b90613d40565b6000546001600160a01b03163314612b1a5760405162461bcd60e51b8152600401610e0f90615aa4565b6000828152600d602052604090205482906001600160a01b031615612b515760405162461bcd60e51b8152600401610e0f90615acd565b601354601454612b619082615cef565b612b6b9042615d98565b10612ba85760405162461bcd60e51b815260206004820152600d60248201526c1cd859995d1e481c195c9a5bd9609a1b6044820152606401610e0f565b612bb1826141ef565b60008381526008602090815260409182902084518155908401516001820155818401516002820155606084015160038201556080840151600482015560a08401516005909101555183907fe0fe09d9a25d5360154efb63f8f8c43a9cf25b0e4715d7f9ee42b362d99c941f906118ec908590615bb0565b612c616040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060c0016040528061177081526020016107d081526020016101f48152602001600081526020016103e881526020016101f4815250905090565b6122ac8160006143e7565b6000546001600160a01b03163314612cd35760405162461bcd60e51b8152600401610e0f90615aa4565b60006001600160a01b031660048681548110612cf157612cf1615dee565b60009182526020909120600790910201546001600160a01b03161415612d4f5760405162461bcd60e51b81526020600482015260136024820152721c1bdbdb08191bd95cc81b9bdd08195e1a5cdd606a1b6044820152606401610e0f565b612d5985856145e7565b60008581526010602052604090819020805460ff19168415151790555183151590859087907fd01a08be7ba6451f751cf523b54675f30a2c5ea6fa6bd909c2fd57f296fef0b5906112b8908690615a32565b6000546001600160a01b03163314612dd55760405162461bcd60e51b8152600401610e0f90615aa4565b600060048581548110612dea57612dea615dee565b600091825260208083206007909202909101546001600160a01b03908116808452600a83526040808520549289168552600b8452808520828652845280852054600c909452842054909450909290612e4690611aac8585613d34565b905060008111612e895760405162461bcd60e51b815260206004820152600e60248201526d616d6f756e74206973207a65726f60901b6044820152606401610e0f565b6001600160a01b038085166000818152600a60209081526040808320839055600c8252808320839055938b168252600b815283822092825291909152908120819055612ed78286888a614781565b90506000612ee9836115aa84886139f3565b90508015612f6c57604051630852cd8d60e31b8152600481018290527f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c6001600160a01b0316906342966c6890602401600060405180830381600087803b158015612f5357600080fd5b505af1158015612f67573d6000803e3d6000fd5b505050505b80838b7f4f255c8cf5a84786ddc35d528b4df336f3aad1b61d63615fd8b228a39548cc9360405160405180910390a4600080612fac856115aa86896139f3565b9050801561314b577f0000000000000000000000002c7daec5b1c6157c2b37b2505d5d57d6d075e39e6001600160a01b031663e95cd0517f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c61dead8e85426011600001544261301b9190615cef565b6012546040516001600160e01b031960e08a901b168152613050979695949392919060009081906002906001906004016158c7565b602060405180830381600087803b15801561306a57600080fd5b505af115801561307e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a291906153c5565b60405163a9059cbb60e01b81526001600160a01b038083166004830152602482018490529193507f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c9091169063a9059cbb90604401602060405180830381600087803b15801561311157600080fd5b505af1158015613125573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613149919061541b565b505b848b6001600160a01b03168d7f5130497d6ba2833abd6dbfb4eb1a4bfa30540ea493ee0f3c811e44ff829697dc848660405161319a9291909182526001600160a01b0316602082015260400190565b60405180910390a47f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c6001600160a01b031663a9059cbb6131e36000546001600160a01b031690565b6131f186612aea8987613d40565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b15801561323757600080fd5b505af115801561324b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061326f919061541b565b50505050505050505050505050565b6001600160a01b0381166132c85760405162461bcd60e51b8152602060048201526011602482015270636f6d6d6974746565206973207a65726f60781b6044820152606401610e0f565b6000546001600160a01b0316331480156132f957506000828152600960205260409020546001600160a01b03163314155b156133655760008281526008602052604090206007015460ff16156133605760405162461bcd60e51b815260206004820152601c60248201527f436f6d6d697474656520616c726561647920636865636b656420696e000000006044820152606401610e0f565b6133bc565b6000828152600960205260409020546001600160a01b031633146133bc5760405162461bcd60e51b815260206004820152600e60248201526d4f6e6c7920636f6d6d697474656560901b6044820152606401610e0f565b60008281526009602052604080822080546001600160a01b0319166001600160a01b0385169081179091559051909184917f2d56897538f0fc982e13469f511616bed63e0c8f65a75270ba4346266b50f2a59190a35050565b6000546001600160a01b0316331461343f5760405162461bcd60e51b8152600401610e0f90615aa4565b6000908152600d6020526040812080546001600160a01b03199081168255600182019290925560020180549091169055565b6005818154811061348157600080fd5b60009182526020909120600290910201805460019091015490915082565b6004548111156134e95760405162461bcd60e51b8152602060048201526015602482015274706f6f6c2072616e676520697320746f6f2062696760581b6044820152606401610e0f565b8082111561352e5760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420706f6f6c2072616e676560701b6044820152606401610e0f565b815b818110156135515761354181612049565b61354a81615d7d565b9050613530565b5060408051838152602081018390527fd3f7645e6170879584cabe5bb42b1c424830ab0646a05d1d90bf6f641dc2e3d8910160405180910390a15050565b6000546001600160a01b031633146135b95760405162461bcd60e51b8152600401610e0f90615aa4565b62ed4e0082106135db5760405162461bcd60e51b8152600401610e0f90615afd565b600081116135fb5760405162461bcd60e51b8152600401610e0f90615a6d565b8082101561361b5760405162461bcd60e51b8152600401610e0f90615b34565b60118290556012819055604051819083907fa3d5527033c65a7e5eda0ffec2fe75b8bfc358a419914452e5e29993f531136d90600090a35050565b60008281526010602052604090205460ff16156136a65760405162461bcd60e51b815260206004820152600e60248201526d19195c1bdcda5d081c185d5cd95960921b6044820152606401610e0f565b620f42408110156136f05760405162461bcd60e51b815260206004820152601460248201527330b6b7bab73a103632b9b9903a3430b71018b29b60611b6044820152606401610e0f565b6000828152600e6020908152604080832033845290915281205561190c82826143e7565b600081156137605761375d60646115aa846115aa876137577f000000000000000000000000000000000000000000000000003980c218c3c0006137578d8d61279e565b906139f3565b90505b949350505050565b6000546001600160a01b031633146137925760405162461bcd60e51b8152600401610e0f90615aa4565b6202a3008110156137da5760405162461bcd60e51b815260206004820152601260248201527119195b185e481a5cc81d1bdbc81cda1bdc9d60721b6044820152606401610e0f565b601555565b600080600485815481106137f5576137f5615dee565b906000526020600020906007020160010154905060006004868154811061381e5761381e615dee565b90600052602060002090600702016005015490505b838110156138a8576000600561384a836001615cef565b8154811061385a5761385a615dee565b906000526020600020906002020160000154905061389161388a8783866005878154811061255657612556615dee565b8590613d34565b9095509250806138a081615d7d565b915050613833565b6138cb6138c48643856005868154811061255657612556615dee565b8490613d34565b925050505b9392505050565b60185415613964576018543410156139285760405162461bcd60e51b81526020600482015260146024820152731b9bdd08195b9bdd59da08199959481c185e595960621b6044820152606401610e0f565b600080546040516001600160a01b03909116913480156108fc02929091818181858888f19350505050158015613962573d6000803e3d6000fd5b505b336001600160a01b03167fc8fdf13a4b928b8811a082d6f49538b13d9279cc130d1312406e8fa8742997358260405161399d9190615a32565b60405180910390a250565b600080546001600160a01b0319166001600160a01b03831690811782556040519091907fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a908290a350565b60006138d08284615d1b565b60006138d08284615d07565b6000818152600d602052604090205481906001600160a01b031615613a425760405162461bcd60e51b8152600401610e0f90615acd565b601354601454613a529082615cef565b613a5c9042615d98565b10613a995760405162461bcd60e51b815260206004820152600d60248201526c1cd859995d1e481c195c9a5bd9609a1b6044820152606401610e0f565b6000828152600e6020908152604080832033845290915290205442118015613ae657506016546000838152600e60209081526040808320338452909152902054613ae39190615cef565b42105b613b325760405162461bcd60e51b815260206004820152601a60248201527f77697468647261772072657175657374206e6f742076616c69640000000000006044820152606401610e0f565b506000908152600e60209081526040808320338452909152812055565b60026003541415613b725760405162461bcd60e51b8152600401610e0f90615b79565b6002600381905550600060048381548110613b8f57613b8f615dee565b6000918252602080832086845260078083526040808620338752909352919093208054929091029092019250831115613c145760405162461bcd60e51b815260206004820152602160248201527f77697468647261773a206e6f7420656e6f75676820757365722062616c616e636044820152606560f81b6064820152608401610e0f565b613c1d84612049565b6000613c4b8260010154612aea64e8d4a510006115aa876003015487600001546139f390919063ffffffff16565b90508015613c5e57613c5e338287614cbd565b8315613cd1578154613c709085613d40565b825560048301546006840154600091613c8e916115aa9088906139f3565b6006850154909150613ca09082613d40565b60068501558354613cbb906001600160a01b03163383613d4c565b6004840154613cca9086613d40565b6004850155505b60038301548254613cec9164e8d4a51000916115aa916139f3565b6001830155604051848152859033907ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5689060200160405180910390a350506001600355505050565b60006138d08284615cef565b60006138d08284615d3a565b6040516001600160a01b038316602482015260448101829052613daf90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614f35565b505050565b6001600160a01b03811660009081526006602052604090205415613e2d5760405162461bcd60e51b815260206004820152602a60248201527f4841544d61737465723a3a6164643a206c70546f6b656e20697320616c726561604482015269191e481a5b881c1bdbdb60b21b6064820152608401610e0f565b600454613e3b906001615cef565b6001600160a01b0382166000908152600660205260408120919091557f0000000000000000000000000000000000000000000000000000000000c52b104311613ea4577f0000000000000000000000000000000000000000000000000000000000c52b10613ea6565b435b60055490915060009015613eff5760058054613efa918691613eca90600190615d3a565b81548110613eda57613eda615dee565b906000526020600020906002020160010154613d3490919063ffffffff16565b613f01565b835b60055490915015801590613f47575060058054439190613f2390600190615d3a565b81548110613f3357613f33615dee565b906000526020600020906002020160000154145b15613f895760058054829190613f5f90600190615d3a565b81548110613f6f57613f6f615dee565b906000526020600020906002020160010181905550614000565b60408051808201909152438152602081018281526005805460018101825560009190915291517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0600290930292830155517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db1909101555b60046040518060e00160405280856001600160a01b03168152602001868152602001848152602001600081526020016000815260200160016005805490506140489190615d3a565b81526000602091820181905283546001808201865594825290829020835160079092020180546001600160a01b0319166001600160a01b03909216919091178155908201519281019290925560408101516002830155606081015160038301556080810151600483015560a0810151600583015560c0015160069091015550505050565b606060008251600014156141505760408051600480825260a0820190925290602082016080803683370190505091505b600481101561414b57614110816001615cef565b61411c906107d0615d1b565b82828151811061412e5761412e615dee565b60209081029190910101528061414381615d7d565b9150506140fc565b6141e9565b82518110156141e55761271083828151811061416e5761416e615dee565b6020026020010151106141d35760405162461bcd60e51b815260206004820152602760248201527f726577617264206c6576656c2063616e206e6f74206265206d6f72652074686160448201526606e2031303030360cc1b6064820152608401610e0f565b806141dd81615d7d565b915050614150565b8291505b50919050565b61271061422d8260a00151611aac8460800151611aac8660600151611aac8860400151611aac8a602001518b60000151613d3490919063ffffffff16565b146122ac5760405162461bcd60e51b815260206004820152601d60248201527f746f74616c2073706c697420252073686f756c642062652031303030300000006044820152606401610e0f565b60006004828154811061428f5761428f615dee565b60009182526020808320858452600780835260408086203387529093529190932080549290910290920192506142f95760405162461bcd60e51b815260206004820152600f60248201526e0757365722e616d6f756e74203d203608c1b6044820152606401610e0f565b600061431e83600401546115aa856006015485600001546139f390919063ffffffff16565b825460048501549192506143329190613d40565b60048401556000808355600183015560068301546143509082613d40565b6006840155825461436b906001600160a01b03163383613d4c565b604051818152849033907fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae0595906020015b60405180910390a350505050565b6040516001600160a01b03808516602483015283166044820152606481018290526143e19085906323b872dd60e01b90608401613d78565b50505050565b6002600354141561440a5760405162461bcd60e51b8152600401610e0f90615b79565b600260035560008281526008602052604090206007015460ff166144705760405162461bcd60e51b815260206004820152601c60248201527f636f6d6d6974746565206e6f7420636865636b656420696e20796574000000006044820152606401610e0f565b60006004838154811061448557614485615dee565b600091825260208083208684526007808352604080862033875290935291909320910290910191506144b684612049565b8054156145005760006144eb8260010154612aea64e8d4a510006115aa876003015487600001546139f390919063ffffffff16565b905080156144fe576144fe338287614cbd565b505b82156145855760068201548254614522906001600160a01b03163330876143a9565b60068301546145319085613d34565b600684015560048301548490156145605761455d826115aa8787600401546139f390919063ffffffff16565b90505b825461456c9082613d34565b8355600484015461457d9082613d34565b600485015550505b600382015481546145a09164e8d4a51000916115aa916139f3565b6001820155604051838152849033907f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159060200160405180910390a3505060016003555050565b6145f082612049565b600061466282611aac6004868154811061460c5761460c615dee565b906000526020600020906007020160010154600560016005805490506146329190615d3a565b8154811061464257614642615dee565b906000526020600020906002020160010154613d4090919063ffffffff16565b60058054919250439161467790600190615d3a565b8154811061468757614687615dee565b90600052602060002090600202016000015414156146dc57600580548291906146b290600190615d3a565b815481106146c2576146c2615dee565b906000526020600020906002020160010181905550614753565b60408051808201909152438152602081018281526005805460018101825560009190915291517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0600290930292830155517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db1909101555b816004848154811061476757614767615dee565b906000526020600020906007020160010181905550505050565b60007f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c6001600160a01b0316846001600160a01b031614156147c4575083613760565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564811660048301526024820187905285169063095ea7b390604401602060405180830381600087803b15801561482e57600080fd5b505af1158015614842573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614866919061541b565b6148a95760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b88185c1c1c9bdd994819985a5b195960621b6044820152606401610e0f565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c6001600160a01b0316906370a082319060240160206040518083038186803b15801561490b57600080fd5b505afa15801561491f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149439190615486565b905060007f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615646001600160a01b0316634aa4a4fc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156149a057600080fd5b505afa1580156149b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149d891906153c5565b90506060816001600160a01b0316876001600160a01b03161415614a6f578551604051606089811b6bffffffffffffffffffffffff19908116602084015260e89390931b6001600160e81b03191660348301527f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c901b9091166037820152604b016040516020818303038152906040529050614b02565b855160208088015160405160608b811b6bffffffffffffffffffffffff199081169483019490945260e894851b6001600160e81b0319908116603484015287821b851660378401529290941b909116604b8201527f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c90921b16604e82015260620160405160208183030381529060405290505b6040805160a0810182528281523060208201524281830152606081018a905260808101879052905163c04b8d5960e01b81526001600160a01b037f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564169163c04b8d5991614b729190600401615bbe565b602060405180830381600087803b158015614b8c57600080fd5b505af1158015614ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614bc49190615486565b6040516370a0823160e01b8152306004820152909450859084906001600160a01b037f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c16906370a082319060240160206040518083038186803b158015614c2a57600080fd5b505afa158015614c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c629190615486565b614c6c9190615d3a565b1015614cb25760405162461bcd60e51b81526020600482015260156024820152741ddc9bdb99c8185b5bdd5b9d081c9958d95a5d9959605a1b6044820152606401610e0f565b505050949350505050565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c6001600160a01b0316906370a082319060240160206040518083038186803b158015614d1f57600080fd5b505afa158015614d33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d579190615486565b905080831115614e4f5760405163a9059cbb60e01b81526001600160a01b038581166004830152602482018390527f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c169063a9059cbb90604401602060405180830381600087803b158015614dcb57600080fd5b505af1158015614ddf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e03919061541b565b50604080518281526020810185905283916001600160a01b038716917fee9cbb749817d7aa2d7b761a12c7789e3f9ac46e77f63c47e4f5f21da5e7cf0b910160405180910390a36143e1565b60405163a9059cbb60e01b81526001600160a01b038581166004830152602482018590527f000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c169063a9059cbb90604401602060405180830381600087803b158015614eb957600080fd5b505af1158015614ecd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ef1919061541b565b50604080518481526020810185905283916001600160a01b038716917fee9cbb749817d7aa2d7b761a12c7789e3f9ac46e77f63c47e4f5f21da5e7cf0b910161439b565b6000614f8a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166150079092919063ffffffff16565b805190915015613daf5780806020019051810190614fa8919061541b565b613daf5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e0f565b6060613760848460008585843b6150605760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e0f565b600080866001600160a01b0316858760405161507c91906158ab565b60006040518083038185875af1925050503d80600081146150b9576040519150601f19603f3d011682016040523d82523d6000602084013e6150be565b606091505b50915091506150ce8282866150d9565b979650505050505050565b606083156150e85750816138d0565b8251156150f85782518084602001fd5b8160405162461bcd60e51b8152600401610e0f9190615a32565b8280548282559060005260206000209081019282156151525760005260206000209182015b82811115615152578254825591600101919060010190615137565b5061515e929150615223565b5090565b50805460008255906000526020600020908101906122ac9190615223565b828054828255906000526020600020908101928215615152579160200282015b828111156151525782518255916020019190600101906151a0565b6040518060a001604052806151ff6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b81526020016060815260200160001515815260200160008152602001600081525090565b5b8082111561515e5760008155600101615224565b600082601f83011261524957600080fd5b8135602067ffffffffffffffff82111561526557615265615e04565b8160051b615274828201615cbe565b83815282810190868401838801850189101561528f57600080fd5b600093505b858410156152b2578035835260019390930192918401918401615294565b50979650505050505050565b600082601f8301126152cf57600080fd5b813567ffffffffffffffff8111156152e9576152e9615e04565b6152fc601f8201601f1916602001615cbe565b81815284602083860101111561531157600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561534057600080fd5b60405160c0810181811067ffffffffffffffff8211171561536357615363615e04565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a08201525092915050565b6000602082840312156153ba57600080fd5b81356138d081615e1a565b6000602082840312156153d757600080fd5b81516138d081615e1a565b600080604083850312156153f557600080fd5b823561540081615e1a565b9150602083013561541081615e1a565b809150509250929050565b60006020828403121561542d57600080fd5b81516138d081615e2f565b60006020828403121561544a57600080fd5b813567ffffffffffffffff81111561546157600080fd5b613760848285016152be565b60006020828403121561547f57600080fd5b5035919050565b60006020828403121561549857600080fd5b5051919050565b600080604083850312156154b257600080fd5b82359150602083013561541081615e1a565b60008060008060008060006101a080898b0312156154e157600080fd5b883597506020808a01356154f481615e1a565b975060408a013561550481615e1a565b965060608a013567ffffffffffffffff8082111561552157600080fd5b61552d8d838e01615238565b975061553c8d60808e0161532e565b96506101408c013591508082111561555357600080fd5b506155608c828d016152be565b9450508a61017f8b011261557357600080fd5b61557b615c95565b806101608c018d858e01111561559057600080fd5b600094505b60028510156155b4578035835260019490940193918301918301615595565b508094505050505092959891949750929550565b6000806000606084860312156155dd57600080fd5b8335925060208401356155ef81615e1a565b929592945050506040919091013590565b60008060008060a0858703121561561657600080fd5b8435935060208086013561562981615e1a565b935060408601359250607f8601871361564157600080fd5b615649615c95565b80606088018960a08a01111561565e57600080fd5b6000805b600281101561568f57823562ffffff8116811461567d578283fd5b85529385019391850191600101615662565b50979a969950949750955050505050565b600080604083850312156156b357600080fd5b82359150602083013567ffffffffffffffff8111156156d157600080fd5b6156dd85828601615238565b9150509250929050565b60008060e083850312156156fa57600080fd5b8235915061570b846020850161532e565b90509250929050565b6000806040838503121561572757600080fd5b50508035926020909101359150565b600080600080600060a0868803121561574e57600080fd5b8535945060208601359350604086013561576781615e2f565b9250606086013561577781615e2f565b9150608086013567ffffffffffffffff81111561579357600080fd5b61579f888289016152be565b9150509295509295909350565b6000806000606084860312156157c157600080fd5b505081359360208301359350604090920135919050565b600080600080608085870312156157ee57600080fd5b5050823594602084013594506040840135936060013592509050565b600081518084526020808501945080840160005b8381101561583a5781518752958201959082019060010161581e565b509495945050505050565b6000815180845261585d816020860160208601615d51565b601f01601f19169290920160200192915050565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b600082516158bd818460208701615d51565b9190910192915050565b6001600160a01b038c811682528b811660208301528a166040820152606081018990526080810188905260a0810187905260c0810186905260e08101859052610100810184905261016081016003841061593157634e487b7160e01b600052602160045260246000fd5b8361012083015261594761014083018415159052565b9c9b505050505050505050505050565b6001600160a01b03871681526101606020820181905260009061597c83820189615845565b90508281036040840152615990818861580a565b9150506159a06060830186615871565b6101208201939093526101400152949350505050565b6020815260006138d0602083018461580a565b6040815260006159dc604083018561580a565b90508260208301529392505050565b6020808252825482820181905260008481528281209092916040850190845b81811015615a2657835483526001938401939285019201615a0a565b50909695505050505050565b6020815260006138d06020830184615845565b6020808252600e908201526d6f6e6c7920636f6d6d697474656560901b604082015260600190565b6020808252601e908201527f76657374696e6720706572696f64732063616e6e6f74206265207a65726f0000604082015260600190565b6020808252600f908201526e6f6e6c7920676f7665726e616e636560881b604082015260600190565b6020808252601690820152751c195b991a5b99c8185c1c1c9bdd985b08195e1a5cdd60521b604082015260600190565b6020808252601c908201527f76657374696e67206475726174696f6e20697320746f6f206c6f6e6700000000604082015260600190565b60208082526025908201527f76657374696e67206475726174696f6e20736d616c6c6572207468616e20706560408201526472696f647360d81b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60c081016117098284615871565b602081526000825160a06020840152615bda60c0840182615845565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b60208152615c28602082018351615871565b600060208301516101408060e0850152615c4661016085018361580a565b6040860151151561010086015260608601516101208601526080909501519301929092525090919050565b8381526001600160a01b038316602082015261010081016137606040830184615871565b6040805190810167ffffffffffffffff81118282101715615cb857615cb8615e04565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715615ce757615ce7615e04565b604052919050565b60008219821115615d0257615d02615dc2565b500190565b600082615d1657615d16615dd8565b500490565b6000816000190483118215151615615d3557615d35615dc2565b500290565b600082821015615d4c57615d4c615dc2565b500390565b60005b83811015615d6c578181015183820152602001615d54565b838111156143e15750506000910152565b6000600019821415615d9157615d91615dc2565b5060010190565b600082615da757615da7615dd8565b500690565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146122ac57600080fd5b80151581146122ac57600080fdfea264697066735822122079009a8ae3b9731756933a98158ca9c0485be9ead682ff201ad5eb91827e847764736f6c63430008060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c000000000000000000000000000000000000000000000000003980c218c3c0000000000000000000000000000000000000000000000000000000000000c52b10000000000000000000000000000000000000000000000000000000000002fa80000000000000000000000000a13ddfa63774c5b982d2c3e92fde3b660616ffcd000000000000000000000000e592427a0aece92de3edee1f18e0157c058615640000000000000000000000002c7daec5b1c6157c2b37b2505d5d57d6d075e39e
-----Decoded View---------------
Arg [0] : _rewardsToken (address): 0x685D939C8FE6CCe02f3C7Cbc37d024E99570812c
Arg [1] : _rewardPerBlock (uint256): 16185644800000000
Arg [2] : _startBlock (uint256): 12921616
Arg [3] : _multiplierPeriod (uint256): 195200
Arg [4] : _hatGovernance (address): 0xa13DDFA63774C5b982d2C3E92fDe3b660616FfCd
Arg [5] : _uniSwapRouter (address): 0xE592427A0AEce92De3Edee1F18E0157C05861564
Arg [6] : _tokenLockFactory (address): 0x2c7dAec5B1C6157C2b37B2505d5D57d6D075E39E
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000685d939c8fe6cce02f3c7cbc37d024e99570812c
Arg [1] : 000000000000000000000000000000000000000000000000003980c218c3c000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000c52b10
Arg [3] : 000000000000000000000000000000000000000000000000000000000002fa80
Arg [4] : 000000000000000000000000a13ddfa63774c5b982d2c3e92fde3b660616ffcd
Arg [5] : 000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Arg [6] : 0000000000000000000000002c7daec5b1c6157c2b37b2505d5d57d6d075e39e
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 23.77% | $0.999336 | 23,704.4509 | $23,688.71 | |
ETH | 22.89% | $0.02269 | 1,005,024.5267 | $22,803.69 | |
ETH | 17.40% | $0.635512 | 27,287.6198 | $17,341.61 | |
ETH | 15.86% | $1.58 | 10,000 | $15,800 | |
ETH | 11.62% | $0.046332 | 250,000 | $11,582.89 | |
ETH | 3.17% | $0.062983 | 50,100 | $3,155.45 | |
ETH | 1.81% | $0.014781 | 121,793.2029 | $1,800.23 | |
ETH | 1.36% | $1 | 1,351.0649 | $1,351.12 | |
ETH | 0.87% | $1.35 | 641.3408 | $865.81 | |
ETH | 0.52% | $0.999385 | 518.4435 | $518.12 | |
ETH | 0.34% | $0.015705 | 21,639.1315 | $339.85 | |
ETH | 0.26% | $0.000149 | 1,755,000 | $260.97 | |
ETH | 0.10% | $1.11 | 88.8 | $98.57 | |
ETH | 0.02% | $0.000592 | 33,837.368 | $20.02 | |
ETH | 0.01% | $0.28167 | 45 | $12.68 | |
ETH | <0.01% | $0.999476 | 3.0004 | $3 | |
MATIC | <0.01% | $0.425882 | 0.0001 | $0.000043 |
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.