More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 73 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw | 18838623 | 401 days ago | IN | 0.00089 ETH | 0.00520596 | ||||
Withdraw | 18406645 | 462 days ago | IN | 0.00089 ETH | 0.00281414 | ||||
Compound Reward | 17958982 | 524 days ago | IN | 0.00089 ETH | 0.00222 | ||||
Claim Reward | 17731881 | 556 days ago | IN | 0.00089 ETH | 0.00244946 | ||||
Compound Reward | 17706669 | 560 days ago | IN | 0.00089 ETH | 0.00283388 | ||||
Compound Reward | 17421595 | 600 days ago | IN | 0.00089 ETH | 0.00327766 | ||||
Withdraw | 17310887 | 615 days ago | IN | 0.00089 ETH | 0.01016587 | ||||
Compound Reward | 17310879 | 615 days ago | IN | 0.00089 ETH | 0.0051222 | ||||
Withdraw | 17159885 | 636 days ago | IN | 0.00089 ETH | 0.01067554 | ||||
Claim Reward | 17159882 | 636 days ago | IN | 0.00089 ETH | 0.00842658 | ||||
Deposit | 17132611 | 640 days ago | IN | 0.00089 ETH | 0.01160306 | ||||
Withdraw | 17113507 | 643 days ago | IN | 0.00089 ETH | 0.00716341 | ||||
Withdraw | 17111883 | 643 days ago | IN | 0.00089 ETH | 0.0072943 | ||||
Claim Reward | 17111880 | 643 days ago | IN | 0.00089 ETH | 0.00508013 | ||||
Withdraw | 17092677 | 646 days ago | IN | 0.00089 ETH | 0.0071745 | ||||
Deposit | 17092419 | 646 days ago | IN | 0.00089 ETH | 0.00697664 | ||||
Deposit | 17052714 | 652 days ago | IN | 0.00089 ETH | 0.00559271 | ||||
Withdraw | 17017417 | 657 days ago | IN | 0.00089 ETH | 0.00402105 | ||||
Compound Reward | 17015130 | 657 days ago | IN | 0.00089 ETH | 0.00285529 | ||||
Deposit | 17014994 | 657 days ago | IN | 0.00089 ETH | 0.00476186 | ||||
Compound Reward | 17014895 | 657 days ago | IN | 0.00089 ETH | 0.00286141 | ||||
Compound Reward | 16961538 | 665 days ago | IN | 0.00089 ETH | 0.00260914 | ||||
Compound Reward | 16961532 | 665 days ago | IN | 0.00089 ETH | 0.0028119 | ||||
Withdraw | 16960503 | 665 days ago | IN | 0.00089 ETH | 0.0042748 | ||||
Withdraw | 16958977 | 665 days ago | IN | 0.00089 ETH | 0.0044892 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
18838623 | 401 days ago | 0.00089 ETH | ||||
18406645 | 462 days ago | 0.00089 ETH | ||||
17958982 | 524 days ago | 0.00089 ETH | ||||
17731881 | 556 days ago | 0.00089 ETH | ||||
17706669 | 560 days ago | 0.00089 ETH | ||||
17421595 | 600 days ago | 0.00089 ETH | ||||
17310887 | 615 days ago | 0.00089 ETH | ||||
17310879 | 615 days ago | 0.00089 ETH | ||||
17159885 | 636 days ago | 0.00089 ETH | ||||
17159882 | 636 days ago | 0.00089 ETH | ||||
17132611 | 640 days ago | 0.00089 ETH | ||||
17113507 | 643 days ago | 0.00089 ETH | ||||
17111883 | 643 days ago | 0.00089 ETH | ||||
17111880 | 643 days ago | 0.00089 ETH | ||||
17092677 | 646 days ago | 0.00089 ETH | ||||
17092419 | 646 days ago | 0.00089 ETH | ||||
17052714 | 652 days ago | 0.00089 ETH | ||||
17017417 | 657 days ago | 0.00089 ETH | ||||
17015130 | 657 days ago | 0.00089 ETH | ||||
17014994 | 657 days ago | 0.00089 ETH | ||||
17014895 | 657 days ago | 0.00089 ETH | ||||
16961538 | 665 days ago | 0.00089 ETH | ||||
16961532 | 665 days ago | 0.00089 ETH | ||||
16960503 | 665 days ago | 0.00089 ETH | ||||
16958977 | 665 days ago | 0.00089 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
BrewlabsStaking
Compiler Version
v0.8.14+commit.80d49f37
Optimization Enabled:
Yes with 100 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./libs/IUniRouter02.sol"; import "./libs/IWETH.sol"; interface WhiteList { function whitelisted(address _address) external view returns (bool); } contract BrewlabsStaking is Ownable, ReentrancyGuard { using SafeERC20 for IERC20; uint256 private constant PERCENT_PRECISION = 10000; uint256 private constant BLOCKS_PER_DAY = 6426; // Whether it is initialized bool public isInitialized; uint256 public duration = 365; // 365 days // Whether a limit is set for users bool public hasUserLimit; // The pool limit (0 if none) uint256 public poolLimitPerUser; address public whiteList; // The block number when staking starts. uint256 public startBlock; // The block number when staking ends. uint256 public bonusEndBlock; // tokens created per block. uint256 public rewardPerBlock; // The block number of the last pool update uint256 public lastRewardBlock; // swap router and path, slipPage uint256 public slippageFactor = 8000; // 20% default slippage tolerance uint256 public constant slippageFactorUL = 9950; address public uniRouterAddress; address[] public reflectionToStakedPath; address[] public earnedToStakedPath; // The deposit & withdraw fee uint256 public constant MAX_FEE = 2000; uint256 public depositFee; uint256 public withdrawFee; address public walletA; address public treasury = 0x64961Ffd0d84b2355eC2B5d35B0d8D8825A774dc; uint256 public performanceFee = 0.00089 ether; // The precision factor uint256 public PRECISION_FACTOR; uint256 public PRECISION_FACTOR_REFLECTION; // The staked token IERC20 public stakingToken; // The earned token IERC20 public earnedToken; // The dividend token of staking token address public dividendToken; bool public hasDividend; bool public autoAdjustableForRewardRate = false; // Accrued token per share uint256 public accTokenPerShare; uint256 public accDividendPerShare; uint256 public totalStaked; uint256 private totalEarned; uint256 private totalReflections; uint256 private reflections; uint256 private paidRewards; uint256 private shouldTotalPaid; // Info of each user that stakes tokens (stakingToken) mapping(address => UserInfo) public userInfo; struct UserInfo { uint256 amount; // How many staked tokens the user has provided uint256 rewardDebt; // Reward debt uint256 reflectionDebt; // Reflection debt } event Deposit(address indexed user, uint256 amount); event Withdraw(address indexed user, uint256 amount); event EmergencyWithdraw(address indexed user, uint256 amount); event AdminTokenRecovered(address tokenRecovered, uint256 amount); event NewStartAndEndBlocks(uint256 startBlock, uint256 endBlock); event NewRewardPerBlock(uint256 rewardPerBlock); event RewardsStop(uint256 blockNumber); event EndBlockUpdated(uint256 blockNumber); event UpdatePoolLimit(uint256 poolLimitPerUser, bool hasLimit); event ServiceInfoUpadted(address _addr, uint256 _fee); event WalletAUpdated(address _addr); event DurationUpdated(uint256 _duration); event SetAutoAdjustableForRewardRate(bool status); event SetWhiteList(address _whitelist); event SetSettings( uint256 _depositFee, uint256 _withdrawFee, uint256 _slippageFactor, address _uniRouter, address[] _path0, address[] _path1 ); constructor() {} /** * @notice Initialize the contract * @param _stakingToken: staked token address * @param _earnedToken: earned token address * @param _dividendToken: reflection token address * @param _rewardPerBlock: reward per block (in earnedToken) * @param _depositFee: deposit fee * @param _withdrawFee: withdraw fee * @param _uniRouter: uniswap router address for swap tokens * @param _earnedToStakedPath: swap path to compound (earned -> staking path) * @param _reflectionToStakedPath: swap path to compound (reflection -> staking path) * @param _whiteList: whitelist contract address * @param _hasDividend: reflection available flag */ function initialize( IERC20 _stakingToken, IERC20 _earnedToken, address _dividendToken, uint256 _rewardPerBlock, uint256 _depositFee, uint256 _withdrawFee, address _uniRouter, address[] memory _earnedToStakedPath, address[] memory _reflectionToStakedPath, address _whiteList, bool _hasDividend ) external onlyOwner { require(!isInitialized, "Already initialized"); // Make this contract initialized isInitialized = true; stakingToken = _stakingToken; earnedToken = _earnedToken; dividendToken = _dividendToken; hasDividend = _hasDividend; rewardPerBlock = _rewardPerBlock; require(_depositFee < MAX_FEE, "Invalid deposit fee"); require(_withdrawFee < MAX_FEE, "Invalid withdraw fee"); depositFee = _depositFee; withdrawFee = _withdrawFee; walletA = msg.sender; uint256 decimalsRewardToken = uint256(IERC20Metadata(address(earnedToken)).decimals()); require(decimalsRewardToken < 30, "Must be inferior to 30"); PRECISION_FACTOR = uint256(10 ** (40 - decimalsRewardToken)); uint256 decimalsdividendToken = 18; if (address(dividendToken) != address(0x0)) { decimalsdividendToken = uint256(IERC20Metadata(address(dividendToken)).decimals()); require(decimalsdividendToken < 30, "Must be inferior to 30"); } PRECISION_FACTOR_REFLECTION = uint256(10 ** (40 - decimalsdividendToken)); uniRouterAddress = _uniRouter; earnedToStakedPath = _earnedToStakedPath; reflectionToStakedPath = _reflectionToStakedPath; whiteList = _whiteList; } /** * @notice Deposit staked tokens and collect reward tokens (if any) * @param _amount: amount to withdraw (in earnedToken) */ function deposit(uint256 _amount) external payable nonReentrant { require(startBlock > 0 && startBlock < block.number, "Staking hasn't started yet"); require(_amount > 0, "Amount should be greator than 0"); if (whiteList != address(0x0)) { require(WhiteList(whiteList).whitelisted(msg.sender), "not whitelisted"); } UserInfo storage user = userInfo[msg.sender]; if (hasUserLimit) { require(_amount + user.amount <= poolLimitPerUser, "User amount above limit"); } _transferPerformanceFee(); _updatePool(); if (user.amount > 0) { uint256 pending = user.amount * accTokenPerShare / PRECISION_FACTOR - user.rewardDebt; if (pending > 0) { require(availableRewardTokens() >= pending, "Insufficient reward tokens"); earnedToken.safeTransfer(address(msg.sender), pending); if (totalEarned > pending) { totalEarned = totalEarned - pending; } else { totalEarned = 0; } paidRewards = paidRewards + pending; } uint256 pendingReflection = user.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION - user.reflectionDebt; if (pendingReflection > 0 && hasDividend) { if (address(dividendToken) == address(0x0)) { payable(msg.sender).transfer(estimateDividendAmount(pendingReflection)); } else { IERC20(dividendToken).safeTransfer(address(msg.sender), estimateDividendAmount(pendingReflection)); } totalReflections = totalReflections - pendingReflection; } } uint256 beforeAmount = stakingToken.balanceOf(address(this)); stakingToken.safeTransferFrom(address(msg.sender), address(this), _amount); uint256 afterAmount = stakingToken.balanceOf(address(this)); uint256 realAmount = afterAmount - beforeAmount; if (realAmount > _amount) realAmount = _amount; if (depositFee > 0) { uint256 fee = realAmount * depositFee / PERCENT_PRECISION; stakingToken.safeTransfer(walletA, fee); realAmount = realAmount - fee; } user.amount = user.amount + realAmount; user.rewardDebt = user.amount * accTokenPerShare / PRECISION_FACTOR; user.reflectionDebt = user.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION; totalStaked = totalStaked + realAmount; emit Deposit(msg.sender, realAmount); if (autoAdjustableForRewardRate) _updateRewardRate(); } /** * @notice Withdraw staked tokens and collect reward tokens * @param _amount: amount to withdraw (in earnedToken) */ function withdraw(uint256 _amount) external payable nonReentrant { require(_amount > 0, "Amount should be greator than 0"); UserInfo storage user = userInfo[msg.sender]; require(user.amount >= _amount, "Amount to withdraw too high"); _transferPerformanceFee(); _updatePool(); if (user.amount > 0) { uint256 pending = user.amount * accTokenPerShare / PRECISION_FACTOR - user.rewardDebt; if (pending > 0) { require(availableRewardTokens() >= pending, "Insufficient reward tokens"); earnedToken.safeTransfer(address(msg.sender), pending); if (totalEarned > pending) { totalEarned = totalEarned - pending; } else { totalEarned = 0; } paidRewards = paidRewards + pending; } uint256 pendingReflection = user.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION - user.reflectionDebt; if (pendingReflection > 0 && hasDividend) { if (address(dividendToken) == address(0x0)) { payable(msg.sender).transfer(estimateDividendAmount(pendingReflection)); } else { IERC20(dividendToken).safeTransfer(address(msg.sender), estimateDividendAmount(pendingReflection)); } totalReflections = totalReflections - pendingReflection; } } uint256 realAmount = _amount; if (user.amount < _amount) { realAmount = user.amount; } user.amount = user.amount - realAmount; totalStaked = totalStaked - realAmount; emit Withdraw(msg.sender, realAmount); if (withdrawFee > 0) { uint256 fee = realAmount * withdrawFee / PERCENT_PRECISION; stakingToken.safeTransfer(walletA, fee); realAmount = realAmount - fee; } stakingToken.safeTransfer(address(msg.sender), realAmount); user.rewardDebt = user.amount * accTokenPerShare / PRECISION_FACTOR; user.reflectionDebt = user.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION; if (autoAdjustableForRewardRate) _updateRewardRate(); } function claimReward() external payable nonReentrant { UserInfo storage user = userInfo[msg.sender]; _transferPerformanceFee(); _updatePool(); if (user.amount == 0) return; uint256 pending = user.amount * accTokenPerShare / PRECISION_FACTOR - user.rewardDebt; if (pending > 0) { require(availableRewardTokens() >= pending, "Insufficient reward tokens"); earnedToken.safeTransfer(address(msg.sender), pending); if (totalEarned > pending) { totalEarned = totalEarned - pending; } else { totalEarned = 0; } paidRewards = paidRewards + pending; } user.rewardDebt = user.amount * accTokenPerShare / PRECISION_FACTOR; } function claimDividend() external payable nonReentrant { require(hasDividend == true, "No reflections"); UserInfo storage user = userInfo[msg.sender]; _transferPerformanceFee(); _updatePool(); if (user.amount == 0) return; uint256 pendingReflection = user.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION - user.reflectionDebt; if (pendingReflection > 0) { if (address(dividendToken) == address(0x0)) { payable(msg.sender).transfer(estimateDividendAmount(pendingReflection)); } else { IERC20(dividendToken).safeTransfer(address(msg.sender), estimateDividendAmount(pendingReflection)); } totalReflections = totalReflections - pendingReflection; } user.reflectionDebt = user.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION; } function compoundReward() external payable nonReentrant { UserInfo storage user = userInfo[msg.sender]; _transferPerformanceFee(); _updatePool(); if (user.amount == 0) return; uint256 pending = user.amount * accTokenPerShare / PRECISION_FACTOR - user.rewardDebt; if (pending > 0) { require(availableRewardTokens() >= pending, "Insufficient reward tokens"); if (totalEarned > pending) { totalEarned = totalEarned - pending; } else { totalEarned = 0; } paidRewards = paidRewards + pending; if (address(stakingToken) != address(earnedToken)) { uint256 beforeAmount = stakingToken.balanceOf(address(this)); _safeSwap(pending, earnedToStakedPath, address(this)); uint256 afterAmount = stakingToken.balanceOf(address(this)); pending = afterAmount - beforeAmount; } if (hasUserLimit) { require(pending + user.amount <= poolLimitPerUser, "User amount above limit"); } totalStaked = totalStaked + pending; user.amount = user.amount + pending; user.reflectionDebt = user.reflectionDebt + pending * accDividendPerShare / PRECISION_FACTOR_REFLECTION; emit Deposit(msg.sender, pending); } user.rewardDebt = user.amount * accTokenPerShare / PRECISION_FACTOR; } function compoundDividend() external payable nonReentrant { require(hasDividend == true, "No reflections"); UserInfo storage user = userInfo[msg.sender]; _transferPerformanceFee(); _updatePool(); if (user.amount == 0) return; uint256 _pending = (user.amount * accDividendPerShare) / PRECISION_FACTOR_REFLECTION - user.reflectionDebt; uint256 pending = estimateDividendAmount(_pending); totalReflections = totalReflections - _pending; if (pending > 0) { if (address(stakingToken) != address(dividendToken)) { if (address(dividendToken) == address(0x0)) { address wethAddress = IUniRouter02(uniRouterAddress).WETH(); IWETH(wethAddress).deposit{value: pending}(); } uint256 beforeAmount = stakingToken.balanceOf(address(this)); _safeSwap(pending, reflectionToStakedPath, address(this)); uint256 afterAmount = stakingToken.balanceOf(address(this)); pending = afterAmount - beforeAmount; } if (hasUserLimit) { require(pending + user.amount <= poolLimitPerUser, "User amount above limit"); } totalStaked = totalStaked + pending; user.amount = user.amount + pending; user.rewardDebt = user.rewardDebt + pending * accTokenPerShare / PRECISION_FACTOR; emit Deposit(msg.sender, pending); } user.reflectionDebt = user.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION; } function _transferPerformanceFee() internal { require(msg.value >= performanceFee, "should pay small gas to compound or harvest"); payable(treasury).transfer(performanceFee); if (msg.value > performanceFee) { payable(msg.sender).transfer(msg.value - performanceFee); } } /** * @notice Withdraw staked tokens without caring about rewards * @dev Needs to be for emergency. */ function emergencyWithdraw() external nonReentrant { UserInfo storage user = userInfo[msg.sender]; uint256 amountToTransfer = user.amount; user.amount = 0; user.rewardDebt = 0; user.reflectionDebt = 0; if (amountToTransfer > 0) { stakingToken.safeTransfer(address(msg.sender), amountToTransfer); totalStaked = totalStaked - amountToTransfer; } emit EmergencyWithdraw(msg.sender, amountToTransfer); } /** * @notice Available amount of reward token */ function availableRewardTokens() public view returns (uint256) { if (address(earnedToken) == address(dividendToken)) return totalEarned; uint256 _amount = earnedToken.balanceOf(address(this)); if (address(earnedToken) == address(stakingToken)) { if (_amount < totalStaked) return 0; return _amount - totalStaked; } return _amount; } /** * @notice Available amount of reflection token */ function availableDividendTokens() public view returns (uint256) { if (address(dividendToken) == address(0x0)) { return address(this).balance; } uint256 _amount = IERC20(dividendToken).balanceOf(address(this)); if (address(dividendToken) == address(earnedToken)) { if (_amount < totalEarned) return 0; _amount = _amount - totalEarned; } if (address(dividendToken) == address(stakingToken)) { if (_amount < totalStaked) return 0; _amount = _amount - totalStaked; } return _amount; } function insufficientRewards() external view returns (uint256) { uint256 adjustedShouldTotalPaid = shouldTotalPaid; uint256 remainRewards = availableRewardTokens() + paidRewards; if (startBlock == 0) { adjustedShouldTotalPaid = adjustedShouldTotalPaid + rewardPerBlock * duration * BLOCKS_PER_DAY; } else { uint256 remainBlocks = _getMultiplier(lastRewardBlock, bonusEndBlock); adjustedShouldTotalPaid = adjustedShouldTotalPaid + rewardPerBlock * remainBlocks; } if (remainRewards >= adjustedShouldTotalPaid) return 0; return adjustedShouldTotalPaid - remainRewards; } /** * @notice View function to see pending reward on frontend. * @param _user: user address * @return Pending reward for a given user */ function pendingReward(address _user) external view returns (uint256) { UserInfo memory user = userInfo[_user]; uint256 adjustedTokenPerShare = accTokenPerShare; if (block.number > lastRewardBlock && totalStaked != 0 && lastRewardBlock > 0) { uint256 multiplier = _getMultiplier(lastRewardBlock, block.number); uint256 rewards = multiplier * rewardPerBlock; adjustedTokenPerShare = accTokenPerShare + (rewards * PRECISION_FACTOR / totalStaked); } return user.amount * adjustedTokenPerShare / PRECISION_FACTOR - user.rewardDebt; } function pendingDividends(address _user) external view returns (uint256) { if (totalStaked == 0) return 0; UserInfo memory user = userInfo[_user]; uint256 reflectionAmount = availableDividendTokens(); if (reflectionAmount > totalReflections) { reflectionAmount -= totalReflections; } else { reflectionAmount = 0; } uint256 sTokenBal = totalStaked; uint256 eTokenBal = availableRewardTokens(); if (address(stakingToken) == address(earnedToken)) { sTokenBal = sTokenBal + eTokenBal; } uint256 adjustedReflectionPerShare = accDividendPerShare + (reflectionAmount * PRECISION_FACTOR_REFLECTION / sTokenBal); uint256 pendingReflection = user.amount * adjustedReflectionPerShare / PRECISION_FACTOR_REFLECTION - user.reflectionDebt; return pendingReflection; } /** * Admin Methods */ function harvestTo(address _treasury) external onlyOwner { _updatePool(); if (reflections > 0) { if (address(dividendToken) == address(0x0)) { payable(_treasury).transfer(estimateDividendAmount(reflections)); } else { IERC20(dividendToken).safeTransfer(_treasury, estimateDividendAmount(reflections)); } totalReflections = totalReflections - reflections; reflections = 0; } } /** * @notice Deposit reward token * @dev Only call by owner. Needs to be for deposit of reward token when reflection token is same with reward token. */ function depositRewards(uint256 _amount) external onlyOwner nonReentrant { require(_amount > 0, "invalid amount"); uint256 beforeAmt = earnedToken.balanceOf(address(this)); earnedToken.safeTransferFrom(msg.sender, address(this), _amount); uint256 afterAmt = earnedToken.balanceOf(address(this)); totalEarned = totalEarned + afterAmt - beforeAmt; } function increaseEmissionRate(uint256 _amount) external onlyOwner { require(startBlock > 0, "pool is not started"); require(bonusEndBlock > block.number, "pool was already finished"); require(_amount > 0, "invalid amount"); _updatePool(); uint256 beforeAmt = earnedToken.balanceOf(address(this)); earnedToken.safeTransferFrom(msg.sender, address(this), _amount); uint256 afterAmt = earnedToken.balanceOf(address(this)); totalEarned = totalEarned + afterAmt - beforeAmt; _updateRewardRate(); } function _updateRewardRate() internal { if (bonusEndBlock <= block.number) return; uint256 remainRewards = availableRewardTokens() + paidRewards; if (remainRewards > shouldTotalPaid) { remainRewards = remainRewards - shouldTotalPaid; uint256 remainBlocks = bonusEndBlock - block.number; rewardPerBlock = remainRewards / remainBlocks; emit NewRewardPerBlock(rewardPerBlock); } } /** * @notice Withdraw reward token * @dev Only callable by owner. Needs to be for emergency. */ function emergencyRewardWithdraw(uint256 _amount) external onlyOwner { require(block.number > bonusEndBlock, "Pool is running"); require(availableRewardTokens() >= _amount, "Insufficient reward tokens"); if (_amount == 0) _amount = availableRewardTokens(); earnedToken.safeTransfer(address(msg.sender), _amount); if (totalEarned > 0) { if (_amount > totalEarned) { totalEarned = 0; } else { totalEarned = totalEarned - _amount; } } } /** * @notice It allows the admin to recover wrong tokens sent to the contract * @param _tokenAddress: the address of the token to withdraw * @param _tokenAmount: the number of tokens to withdraw * @dev This function is only callable by admin. */ function recoverWrongTokens(address _tokenAddress, uint256 _tokenAmount) external onlyOwner { require(_tokenAddress != address(earnedToken) || _tokenAddress == dividendToken, "Cannot be reward token"); if (_tokenAddress == address(stakingToken)) { uint256 tokenBal = stakingToken.balanceOf(address(this)); require(_tokenAmount <= tokenBal - totalStaked, "Insufficient balance"); } if (_tokenAddress == address(0x0)) { payable(msg.sender).transfer(_tokenAmount); } else { IERC20(_tokenAddress).safeTransfer(address(msg.sender), _tokenAmount); } emit AdminTokenRecovered(_tokenAddress, _tokenAmount); } function startReward() external onlyOwner { require(startBlock == 0, "Pool was already started"); startBlock = block.number + 100; bonusEndBlock = startBlock + duration * BLOCKS_PER_DAY; lastRewardBlock = startBlock; emit NewStartAndEndBlocks(startBlock, bonusEndBlock); } function stopReward() external onlyOwner { _updatePool(); uint256 remainRewards = availableRewardTokens() + paidRewards; if (remainRewards > shouldTotalPaid) { remainRewards = remainRewards - shouldTotalPaid; earnedToken.transfer(msg.sender, remainRewards); if (totalEarned > remainRewards) { totalEarned = totalEarned - remainRewards; } else { totalEarned = 0; } } bonusEndBlock = block.number; emit RewardsStop(bonusEndBlock); } function updateEndBlock(uint256 _endBlock) external onlyOwner { require(startBlock > 0, "Pool is not started"); require(bonusEndBlock > block.number, "Pool was already finished"); require(_endBlock > block.number && _endBlock > startBlock, "Invalid end block"); bonusEndBlock = _endBlock; emit EndBlockUpdated(_endBlock); } /** * @notice Update pool limit per user * @dev Only callable by owner. * @param _hasUserLimit: whether the limit remains forced * @param _poolLimitPerUser: new pool limit per user */ function updatePoolLimitPerUser(bool _hasUserLimit, uint256 _poolLimitPerUser) external onlyOwner { if (_hasUserLimit) { require(_poolLimitPerUser > poolLimitPerUser, "New limit must be higher"); poolLimitPerUser = _poolLimitPerUser; } else { poolLimitPerUser = 0; } hasUserLimit = _hasUserLimit; emit UpdatePoolLimit(poolLimitPerUser, hasUserLimit); } /** * @notice Update reward per block * @dev Only callable by owner. * @param _rewardPerBlock: the reward per block */ function updateRewardPerBlock(uint256 _rewardPerBlock) external onlyOwner { // require(block.number < startBlock, "Pool was already started"); rewardPerBlock = _rewardPerBlock; emit NewRewardPerBlock(_rewardPerBlock); } function setServiceInfo(address _treasury, uint256 _fee) external { require(msg.sender == treasury, "setServiceInfo: FORBIDDEN"); require(_treasury != address(0x0), "Invalid address"); treasury = _treasury; performanceFee = _fee; emit ServiceInfoUpadted(_treasury, _fee); } function updateWalletA(address _walletA) external onlyOwner { require(_walletA != address(0x0) || _walletA != walletA, "Invalid address"); walletA = _walletA; emit WalletAUpdated(_walletA); } function setDuration(uint256 _duration) external onlyOwner { require(_duration >= 30, "lower limit reached"); duration = _duration; if (startBlock > 0) { bonusEndBlock = startBlock + duration * BLOCKS_PER_DAY; require(bonusEndBlock > block.number, "invalid duration"); } emit DurationUpdated(_duration); } function setAutoAdjustableForRewardRate(bool _status) external onlyOwner { autoAdjustableForRewardRate = _status; emit SetAutoAdjustableForRewardRate(_status); } function setSettings( uint256 _depositFee, uint256 _withdrawFee, uint256 _slippageFactor, address _uniRouter, address[] memory _earnedToStakedPath, address[] memory _reflectionToStakedPath ) external onlyOwner { require(_depositFee < MAX_FEE, "Invalid deposit fee"); require(_withdrawFee < MAX_FEE, "Invalid withdraw fee"); require(_slippageFactor <= slippageFactorUL, "_slippageFactor too high"); depositFee = _depositFee; withdrawFee = _withdrawFee; slippageFactor = _slippageFactor; uniRouterAddress = _uniRouter; reflectionToStakedPath = _reflectionToStakedPath; earnedToStakedPath = _earnedToStakedPath; emit SetSettings( _depositFee, _withdrawFee, _slippageFactor, _uniRouter, _earnedToStakedPath, _reflectionToStakedPath ); } function setWhitelist(address _whitelist) external onlyOwner { whiteList = _whitelist; emit SetWhiteList(_whitelist); } /** * @notice Update reward variables of the given pool to be up-to-date. */ function _updatePool() internal { // calc reflection rate if (totalStaked > 0 && hasDividend) { uint256 reflectionAmount = availableDividendTokens(); if (reflectionAmount > totalReflections) { reflectionAmount -= totalReflections; } else { reflectionAmount = 0; } uint256 sTokenBal = totalStaked; uint256 eTokenBal = availableRewardTokens(); if (address(stakingToken) == address(earnedToken)) { sTokenBal = sTokenBal + eTokenBal; } accDividendPerShare += reflectionAmount * PRECISION_FACTOR_REFLECTION / sTokenBal; reflections += reflectionAmount * eTokenBal / sTokenBal; totalReflections += reflectionAmount; } if (block.number <= lastRewardBlock || lastRewardBlock == 0) return; if (totalStaked == 0) { lastRewardBlock = block.number; return; } uint256 multiplier = _getMultiplier(lastRewardBlock, block.number); uint256 _reward = multiplier * rewardPerBlock; accTokenPerShare += _reward * PRECISION_FACTOR / totalStaked; lastRewardBlock = block.number; shouldTotalPaid = shouldTotalPaid + _reward; } function estimateDividendAmount(uint256 amount) internal view returns (uint256) { uint256 dTokenBal = availableDividendTokens(); if (amount > totalReflections) amount = totalReflections; if (amount > dTokenBal) amount = dTokenBal; return amount; } /** * @notice Return reward multiplier over the given _from to _to block. * @param _from: block to start * @param _to: block to finish */ function _getMultiplier(uint256 _from, uint256 _to) internal view returns (uint256) { if (_to <= bonusEndBlock) { return _to - _from; } else if (_from >= bonusEndBlock) { return 0; } else { return bonusEndBlock - _from; } } function _safeSwap(uint256 _amountIn, address[] memory _path, address _to) internal { uint256[] memory amounts = IUniRouter02(uniRouterAddress).getAmountsOut(_amountIn, _path); uint256 amountOut = amounts[amounts.length - 1]; IERC20(_path[0]).safeApprove(uniRouterAddress, _amountIn); IUniRouter02(uniRouterAddress).swapExactTokensForTokensSupportingFeeOnTransferTokens( _amountIn, amountOut * slippageFactor / PERCENT_PRECISION, _path, _to, block.timestamp + 600 ); } receive() external payable {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) 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 making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // 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 // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) 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 // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.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' 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)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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 require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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"); (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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IUniRouter01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity); function addLiquidityETH( address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external payable returns (uint256 amountToken, uint256 amountETH, uint256 liquidity); function removeLiquidity( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityETH( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external returns (uint256 amountToken, uint256 amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityETHWithPermit( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountToken, uint256 amountETH); function swapExactTokensForTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapTokensForExactTokens( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactETHForTokens(uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) external payable returns (uint256[] memory amounts); function swapTokensForExactETH( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactTokensForETH( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapETHForExactTokens(uint256 amountOut, address[] calldata path, address to, uint256 deadline) external payable returns (uint256[] memory amounts); function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) external pure returns (uint256 amountB); function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut) external pure returns (uint256 amountOut); function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut) external pure returns (uint256 amountIn); function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts); function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IUniRouter01.sol"; interface IUniRouter02 is IUniRouter01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external returns (uint256 amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; }
{ "optimizer": { "enabled": true, "runs": 100 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenRecovered","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AdminTokenRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"DurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"EndBlockUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"rewardPerBlock","type":"uint256"}],"name":"NewRewardPerBlock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endBlock","type":"uint256"}],"name":"NewStartAndEndBlocks","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"RewardsStop","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"ServiceInfoUpadted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"SetAutoAdjustableForRewardRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_depositFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_withdrawFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_slippageFactor","type":"uint256"},{"indexed":false,"internalType":"address","name":"_uniRouter","type":"address"},{"indexed":false,"internalType":"address[]","name":"_path0","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"_path1","type":"address[]"}],"name":"SetSettings","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_whitelist","type":"address"}],"name":"SetWhiteList","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"poolLimitPerUser","type":"uint256"},{"indexed":false,"internalType":"bool","name":"hasLimit","type":"bool"}],"name":"UpdatePoolLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_addr","type":"address"}],"name":"WalletAUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION_FACTOR_REFLECTION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accDividendPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accTokenPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"autoAdjustableForRewardRate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"availableDividendTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"availableRewardTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bonusEndBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimDividend","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"claimReward","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"compoundDividend","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"compoundReward","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"depositFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dividendToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"duration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"earnedToStakedPath","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"earnedToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"emergencyRewardWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"harvestTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hasDividend","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasUserLimit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"increaseEmissionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_stakingToken","type":"address"},{"internalType":"contract IERC20","name":"_earnedToken","type":"address"},{"internalType":"address","name":"_dividendToken","type":"address"},{"internalType":"uint256","name":"_rewardPerBlock","type":"uint256"},{"internalType":"uint256","name":"_depositFee","type":"uint256"},{"internalType":"uint256","name":"_withdrawFee","type":"uint256"},{"internalType":"address","name":"_uniRouter","type":"address"},{"internalType":"address[]","name":"_earnedToStakedPath","type":"address[]"},{"internalType":"address[]","name":"_reflectionToStakedPath","type":"address[]"},{"internalType":"address","name":"_whiteList","type":"address"},{"internalType":"bool","name":"_hasDividend","type":"bool"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"insufficientRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRewardBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"pendingDividends","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"pendingReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"performanceFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLimitPerUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"recoverWrongTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"reflectionToStakedPath","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_status","type":"bool"}],"name":"setAutoAdjustableForRewardRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"setDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setServiceInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_depositFee","type":"uint256"},{"internalType":"uint256","name":"_withdrawFee","type":"uint256"},{"internalType":"uint256","name":"_slippageFactor","type":"uint256"},{"internalType":"address","name":"_uniRouter","type":"address"},{"internalType":"address[]","name":"_earnedToStakedPath","type":"address[]"},{"internalType":"address[]","name":"_reflectionToStakedPath","type":"address[]"}],"name":"setSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_whitelist","type":"address"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slippageFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"slippageFactorUL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniRouterAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_endBlock","type":"uint256"}],"name":"updateEndBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_hasUserLimit","type":"bool"},{"internalType":"uint256","name":"_poolLimitPerUser","type":"uint256"}],"name":"updatePoolLimitPerUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_rewardPerBlock","type":"uint256"}],"name":"updateRewardPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_walletA","type":"address"}],"name":"updateWalletA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"},{"internalType":"uint256","name":"reflectionDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"walletA","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whiteList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdrawFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405261016d600355611f40600b55601280546001600160a01b0319167364961ffd0d84b2355ec2b5d35b0d8d8825a774dc1790556603297345d9a0006013556018805460ff60a81b191690553480156200005b57600080fd5b50620000673362000071565b60018055620000c1565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61469580620000d16000396000f3fe60806040526004361061033b5760003560e01c806387788782116101b2578063b88a802f116100ed578063e941fa7811610090578063e941fa781461094a578063f0fc6bca14610960578063f2fde38b14610968578063f3aeb31d14610988578063f40f0f521461099d578063f4ef5ed5146109bd578063f6be71d1146109dd578063ffbd3b1f146109fd57600080fd5b8063b88a802f14610881578063bc063e1a14610889578063c1e22a651461089f578063c7926458146108bf578063ccd34cd5146108df578063cd635cce146108f5578063d5f0ca9414610915578063db2e21bc1461093557600080fd5b806396c5f9801161015557806396c5f980146107ac5780639f94e272146107cc578063a0b40905146107e1578063a5bfd0f214610801578063a9f8d18114610822578063b6b55f2514610838578063b74cd2421461084b578063b77e7da01461086157600080fd5b806387788782146106e657806388bbb0c1146106fc5780638ae39cac146107125780638bdf67f2146107285780638da5cb5b146107485780638f6629151461076657806392b46e5b1461077c57806392e8990e1461079257600080fd5b80634de8ff2111610282578063715018a611610225578063715018a61461061157806372f702f314610626578063746c8ae1146106465780637972271b1461065b57806380dc06721461067b578063817b1cd21461069057806381b61948146106a6578063854cff2f146106c657600080fd5b80634de8ff21146105605780635dde4a911461056857806361d027b31461057d57806366fe9f8a1461059d57806367a52793146105b3578063693a090b146105c95780636d971a10146105e95780636e707b73146105f157600080fd5b806324937567116102ea578063249375671461046c5780632e1a7d4d1461049d5780633279beab146104b05780633544a864146104d057806338411f21146104f0578063392e53cd146105105780633f138d4b1461052a57806348cd4cb11461054a57600080fd5b80626f02311461034757806301f8a976146103695780630fb5a6b4146103895780631582358e146103b2578063167d2dbe146103df5780631959a002146103ff5780631aed65531461045657600080fd5b3661034257005b600080fd5b34801561035357600080fd5b50610367610362366004613d47565b610a13565b005b34801561037557600080fd5b50610367610384366004613d47565b610b41565b34801561039557600080fd5b5061039f60035481565b6040519081526020015b60405180910390f35b3480156103be57600080fd5b506018546103d2906001600160a01b031681565b6040516103a99190613d60565b3480156103eb57600080fd5b506103d26103fa366004613d47565b610b7e565b34801561040b57600080fd5b5061043b61041a366004613d94565b60216020526000908152604090208054600182015460029092015490919083565b604080519384526020840192909252908201526060016103a9565b34801561046257600080fd5b5061039f60085481565b34801561047857600080fd5b5060185461048d90600160a81b900460ff1681565b60405190151581526020016103a9565b6103676104ab366004613d47565b610ba8565b3480156104bc57600080fd5b506103676104cb366004613d47565b610efd565b3480156104dc57600080fd5b506006546103d2906001600160a01b031681565b3480156104fc57600080fd5b5061036761050b366004613eb0565b610fc7565b34801561051c57600080fd5b5060025461048d9060ff1681565b34801561053657600080fd5b50610367610545366004613f9c565b6112c3565b34801561055657600080fd5b5061039f60075481565b6103676114ac565b34801561057457600080fd5b5061039f61188d565b34801561058957600080fd5b506012546103d2906001600160a01b031681565b3480156105a957600080fd5b5061039f60055481565b3480156105bf57600080fd5b5061039f600f5481565b3480156105d557600080fd5b50600c546103d2906001600160a01b031681565b610367611993565b3480156105fd57600080fd5b506017546103d2906001600160a01b031681565b34801561061d57600080fd5b50610367611ca2565b34801561063257600080fd5b506016546103d2906001600160a01b031681565b34801561065257600080fd5b50610367611cb4565b34801561066757600080fd5b50610367610676366004613d94565b611d7f565b34801561068757600080fd5b50610367611e13565b34801561069c57600080fd5b5061039f601b5481565b3480156106b257600080fd5b506103676106c1366004613f9c565b611f26565b3480156106d257600080fd5b506103676106e1366004613d94565b611ff4565b3480156106f257600080fd5b5061039f60135481565b34801561070857600080fd5b5061039f60155481565b34801561071e57600080fd5b5061039f60095481565b34801561073457600080fd5b50610367610743366004613d47565b612047565b34801561075457600080fd5b506000546001600160a01b03166103d2565b34801561077257600080fd5b5061039f60195481565b34801561078857600080fd5b5061039f601a5481565b34801561079e57600080fd5b5060045461048d9060ff1681565b3480156107b857600080fd5b506103676107c7366004613d94565b61219d565b3480156107d857600080fd5b5061039f612235565b3480156107ed57600080fd5b506103676107fc366004613fc8565b612309565b34801561080d57600080fd5b5060185461048d90600160a01b900460ff1681565b34801561082e57600080fd5b5061039f600a5481565b610367610846366004613d47565b6123c2565b34801561085757600080fd5b5061039f6126de81565b34801561086d57600080fd5b506011546103d2906001600160a01b031681565b6103676128ec565b34801561089557600080fd5b5061039f6107d081565b3480156108ab57600080fd5b506103d26108ba366004613d47565b6129e1565b3480156108cb57600080fd5b5061039f6108da366004613d94565b6129f1565b3480156108eb57600080fd5b5061039f60145481565b34801561090157600080fd5b50610367610910366004613fe6565b612b06565b34801561092157600080fd5b50610367610930366004614003565b612b5b565b34801561094157600080fd5b50610367612c8d565b34801561095657600080fd5b5061039f60105481565b610367612d28565b34801561097457600080fd5b50610367610983366004613d94565b612e5d565b34801561099457600080fd5b5061039f612ed3565b3480156109a957600080fd5b5061039f6109b8366004613d94565b612f7b565b3480156109c957600080fd5b506103676109d8366004613d47565b61305e565b3480156109e957600080fd5b506103676109f8366004613d47565b61324d565b348015610a0957600080fd5b5061039f600b5481565b610a1b61333c565b600060075411610a685760405162461bcd60e51b8152602060048201526013602482015272141bdbdb081a5cc81b9bdd081cdd185c9d1959606a1b60448201526064015b60405180910390fd5b4360085411610ab55760405162461bcd60e51b8152602060048201526019602482015278141bdbdb081dd85cc8185b1c9958591e48199a5b9a5cda1959603a1b6044820152606401610a5f565b4381118015610ac5575060075481115b610b055760405162461bcd60e51b8152602060048201526011602482015270496e76616c696420656e6420626c6f636b60781b6044820152606401610a5f565b60088190556040518181527f0972575658363b3e7c472ab3a6a918726742c853b732f6a4a2763e2e3a94c977906020015b60405180910390a150565b610b4961333c565b60098190556040518181527f0c4d677eef92893ac7ec52faf8140fc6c851ab4736302b4f3a89dfb20696a0df90602001610b36565b600d8181548110610b8e57600080fd5b6000918252602090912001546001600160a01b0316905081565b610bb0613396565b60008111610bd05760405162461bcd60e51b8152600401610a5f90614095565b3360009081526021602052604090208054821115610c305760405162461bcd60e51b815260206004820152601b60248201527f416d6f756e7420746f20776974686472617720746f6f206869676800000000006044820152606401610a5f565b610c386133ef565b610c406134d7565b805415610dc557600081600101546014546019548460000154610c6391906140e2565b610c6d9190614101565b610c779190614123565b90508015610cf55780610c88612235565b1015610ca65760405162461bcd60e51b8152600401610a5f9061413a565b601754610cbd906001600160a01b03163383613666565b80601c541115610cdd5780601c54610cd59190614123565b601c55610ce3565b6000601c555b80601f54610cf19190614171565b601f555b60008260020154601554601a548560000154610d1191906140e2565b610d1b9190614101565b610d259190614123565b9050600081118015610d405750601854600160a01b900460ff165b15610dc2576018546001600160a01b0316610d9057336108fc610d62836136bc565b6040518115909202916000818181858888f19350505050158015610d8a573d6000803e3d6000fd5b50610db0565b610db033610d9d836136bc565b6018546001600160a01b03169190613666565b80601d54610dbe9190614123565b601d555b50505b80548290811115610dd4575080545b8154610de1908290614123565b8255601b54610df1908290614123565b601b5560405181815233907f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243649060200160405180910390a260105415610e7c57600061271060105483610e4491906140e2565b610e4e9190614101565b601154601654919250610e6e916001600160a01b03908116911683613666565b610e788183614123565b9150505b601654610e93906001600160a01b03163383613666565b6014546019548354610ea591906140e2565b610eaf9190614101565b6001830155601554601a548354610ec691906140e2565b610ed09190614101565b6002830155601854600160a81b900460ff1615610eef57610eef6136ec565b5050610efa60018055565b50565b610f0561333c565b6008544311610f485760405162461bcd60e51b815260206004820152600f60248201526e506f6f6c2069732072756e6e696e6760881b6044820152606401610a5f565b80610f51612235565b1015610f6f5760405162461bcd60e51b8152600401610a5f9061413a565b80600003610f8257610f7f612235565b90505b601754610f99906001600160a01b03163383613666565b601c5415610efa57601c54811115610fb3576000601c5550565b80601c54610fc19190614123565b601c5550565b610fcf61333c565b60025460ff16156110185760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610a5f565b6002805460ff19166001179055601680546001600160a01b03808e166001600160a01b031992831617909255601780548d8416921691909117905560188054831515600160a01b026001600160a81b0319909116928c169290921791909117905560098890556107d0871061109f5760405162461bcd60e51b8152600401610a5f90614189565b6107d086106110c05760405162461bcd60e51b8152600401610a5f906141b6565b600f8790556010869055601180546001600160a01b031916331790556017546040805163313ce56760e01b815290516000926001600160a01b03169163313ce5679160048083019260209291908290030181865afa158015611126573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114a91906141e4565b60ff169050601e811061116f5760405162461bcd60e51b8152600401610a5f90614207565b61117a816028614123565b61118590600a61431b565b6014556018546012906001600160a01b03161561123857601860009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111ef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121391906141e4565b60ff169050601e81106112385760405162461bcd60e51b8152600401610a5f90614207565b611243816028614123565b61124e90600a61431b565b601555600c80546001600160a01b0319166001600160a01b038916179055855161127f90600e906020890190613ccd565b50845161129390600d906020880190613ccd565b5050600680546001600160a01b0319166001600160a01b0394909416939093179092555050505050505050505050565b6112cb61333c565b6017546001600160a01b0383811691161415806112f557506018546001600160a01b038381169116145b61133a5760405162461bcd60e51b815260206004820152601660248201527521b0b73737ba103132903932bbb0b932103a37b5b2b760511b6044820152606401610a5f565b6016546001600160a01b039081169083160361141a576016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611381903090600401613d60565b602060405180830381865afa15801561139e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c29190614327565b9050601b54816113d29190614123565b8211156114185760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610a5f565b505b6001600160a01b03821661145b57604051339082156108fc029083906000818181858888f19350505050158015611455573d6000803e3d6000fd5b5061146f565b61146f6001600160a01b0383163383613666565b7f74f5dcd55c394cb1c6d3b9da22c2464bcc46c38cc3865bd629ed75823249b40b82826040516114a0929190614340565b60405180910390a15050565b6114b4613396565b601854600160a01b900460ff1615156001146114e25760405162461bcd60e51b8152600401610a5f90614359565b3360009081526021602052604090206114f96133ef565b6115016134d7565b80546000036115105750611882565b60008160020154601554601a54846000015461152c91906140e2565b6115369190614101565b6115409190614123565b9050600061154d826136bc565b905081601d5461155d9190614123565b601d55801561185a576018546016546001600160a01b039081169116146117b0576018546001600160a01b031661165457600c54604080516315ab88c960e31b815290516000926001600160a01b03169163ad5c46489160048083019260209291908290030181865afa1580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190614381565b9050806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b15801561163957600080fd5b505af115801561164d573d6000803e3d6000fd5b5050505050505b6016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611685903090600401613d60565b602060405180830381865afa1580156116a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116c69190614327565b905061172d82600d80548060200260200160405190810160405280929190818152602001828054801561172257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611704575b50505050503061377a565b6016546040516370a0823160e01b81526000916001600160a01b0316906370a082319061175e903090600401613d60565b602060405180830381865afa15801561177b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179f9190614327565b90506117ab8282614123565b925050505b60045460ff16156117e85760055483546117ca9083614171565b11156117e85760405162461bcd60e51b8152600401610a5f9061439e565b80601b546117f69190614171565b601b558254611806908290614171565b835560145460195461181890836140e2565b6118229190614101565b83600101546118319190614171565b600184015560405181815233906000805160206146408339815191529060200160405180910390a25b601554601a54845461186c91906140e2565b6118769190614101565b83600201819055505050505b61188b60018055565b565b6018546000906001600160a01b03166118a557504790565b6018546040516370a0823160e01b81526000916001600160a01b0316906370a08231906118d6903090600401613d60565b602060405180830381865afa1580156118f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119179190614327565b6017546018549192506001600160a01b0390811691160361195457601c5481101561194457600091505090565b601c546119519082614123565b90505b6016546018546001600160a01b0391821691160361198e57601b5481101561197e57600091505090565b601b5461198b9082614123565b90505b919050565b61199b613396565b3360009081526021602052604090206119b26133ef565b6119ba6134d7565b80546000036119c95750611882565b6000816001015460145460195484600001546119e591906140e2565b6119ef9190614101565b6119f99190614123565b90508015611c7b5780611a0a612235565b1015611a285760405162461bcd60e51b8152600401610a5f9061413a565b80601c541115611a485780601c54611a409190614123565b601c55611a4e565b6000601c555b80601f54611a5c9190614171565b601f556017546016546001600160a01b03908116911614611bd1576016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611aa8903090600401613d60565b602060405180830381865afa158015611ac5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae99190614327565b9050611b4e82600e805480602002602001604051908101604052809291908181526020018280548015611722576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116117045750505050503061377a565b6016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611b7f903090600401613d60565b602060405180830381865afa158015611b9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc09190614327565b9050611bcc8282614123565b925050505b60045460ff1615611c09576005548254611beb9083614171565b1115611c095760405162461bcd60e51b8152600401610a5f9061439e565b80601b54611c179190614171565b601b558154611c27908290614171565b8255601554601a54611c3990836140e2565b611c439190614101565b8260020154611c529190614171565b600283015560405181815233906000805160206146408339815191529060200160405180910390a25b6014546019548354611c8d91906140e2565b611c979190614101565b600192830155508055565b611caa61333c565b61188b6000613905565b611cbc61333c565b60075415611d075760405162461bcd60e51b8152602060048201526018602482015277141bdbdb081dd85cc8185b1c9958591e481cdd185c9d195960421b6044820152606401610a5f565b611d12436064614171565b600755600354611d259061191a906140e2565b600754611d329190614171565b6008819055600754600a8190556040517f7cd0ab87d19036f3dfadadb232c78aa4879dda3f0c994a9d637532410ee2ce0692611d75928252602082015260400190565b60405180910390a1565b611d8761333c565b6001600160a01b038116151580611dac57506011546001600160a01b03828116911614155b611dc85760405162461bcd60e51b8152600401610a5f906143cf565b601180546001600160a01b0319166001600160a01b0383161790556040517f6de6ddf87fbce1f42220b349684d9b952eac9bffd639fd2093096032cb1d4d4e90610b36908390613d60565b611e1b61333c565b611e236134d7565b6000601f54611e30612235565b611e3a9190614171565b9050602054811115611ef057602054611e539082614123565b60175460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb90611e869033908590600401614340565b6020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec991906143f8565b5080601c541115611eea5780601c54611ee29190614123565b601c55611ef0565b6000601c555b4360088190556040519081527ffed9fcb0ca3d1e761a4b929792bb24082fba92dca81252646ad306d30680656690602001610b36565b6012546001600160a01b03163314611f7c5760405162461bcd60e51b815260206004820152601960248201527839b2ba29b2b93b34b1b2a4b733379d102327a92124a22222a760391b6044820152606401610a5f565b6001600160a01b038216611fa25760405162461bcd60e51b8152600401610a5f906143cf565b601280546001600160a01b0319166001600160a01b03841617905560138190556040517f232f2e6280d2064b1e439bf40ecdada042d84eefbb55039e4c49e8dc4f4c90c9906114a09084908490614340565b611ffc61333c565b600680546001600160a01b0319166001600160a01b0383161790556040517f3990e3e141b903f4f5602428874be692206642a653b416f336d965e2f04813ce90610b36908390613d60565b61204f61333c565b612057613396565b600081116120775760405162461bcd60e51b8152600401610a5f90614415565b6017546040516370a0823160e01b81526000916001600160a01b0316906370a08231906120a8903090600401613d60565b602060405180830381865afa1580156120c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e99190614327565b601754909150612104906001600160a01b0316333085613955565b6017546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612135903090600401613d60565b602060405180830381865afa158015612152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121769190614327565b90508181601c546121879190614171565b6121919190614123565b601c5550506001805550565b6121a561333c565b6121ad6134d7565b601e5415610efa576018546001600160a01b031661220b57806001600160a01b03166108fc6121dd601e546136bc565b6040518115909202916000818181858888f19350505050158015612205573d6000803e3d6000fd5b5061221a565b61221a81610d9d601e546136bc565b601e54601d5461222a9190614123565b601d556000601e5550565b6018546017546000916001600160a01b039081169116036122575750601c5490565b6017546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612288903090600401613d60565b602060405180830381865afa1580156122a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c99190614327565b6016546017549192506001600160a01b0390811691160361198e57601b548110156122f657600091505090565b601b546123039082614123565b91505090565b61231161333c565b811561236d5760055481116123635760405162461bcd60e51b81526020600482015260186024820152772732bb903634b6b4ba1036bab9ba103132903434b3b432b960411b6044820152606401610a5f565b6005819055612373565b60006005555b6004805460ff19168315159081179091556005546040805191825260ff909216151560208201527f19a6e21b354f2502655dd03f5ac08375f296d713847fbfbf7eec539cd22c443991016114a0565b6123ca613396565b60006007541180156123dd575043600754105b6124295760405162461bcd60e51b815260206004820152601a60248201527f5374616b696e67206861736e27742073746172746564207965740000000000006044820152606401610a5f565b600081116124495760405162461bcd60e51b8152600401610a5f90614095565b6006546001600160a01b03161561250957600654604051636c9b2a3f60e11b81526001600160a01b039091169063d936547e9061248a903390600401613d60565b602060405180830381865afa1580156124a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124cb91906143f8565b6125095760405162461bcd60e51b815260206004820152600f60248201526e1b9bdd081dda1a5d195b1a5cdd1959608a1b6044820152606401610a5f565b33600090815260216020526040902060045460ff16156125505760055481546125329084614171565b11156125505760405162461bcd60e51b8152600401610a5f9061439e565b6125586133ef565b6125606134d7565b8054156126d25760008160010154601454601954846000015461258391906140e2565b61258d9190614101565b6125979190614123565b9050801561261557806125a8612235565b10156125c65760405162461bcd60e51b8152600401610a5f9061413a565b6017546125dd906001600160a01b03163383613666565b80601c5411156125fd5780601c546125f59190614123565b601c55612603565b6000601c555b80601f546126119190614171565b601f555b60008260020154601554601a54856000015461263191906140e2565b61263b9190614101565b6126459190614123565b90506000811180156126605750601854600160a01b900460ff165b156126cf576018546001600160a01b03166126b057336108fc612682836136bc565b6040518115909202916000818181858888f193505050501580156126aa573d6000803e3d6000fd5b506126bd565b6126bd33610d9d836136bc565b80601d546126cb9190614123565b601d555b50505b6016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612703903090600401613d60565b602060405180830381865afa158015612720573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127449190614327565b60165490915061275f906001600160a01b0316333086613955565b6016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612790903090600401613d60565b602060405180830381865afa1580156127ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127d19190614327565b905060006127df8383614123565b9050848111156127ec5750835b600f541561283f576000612710600f548361280791906140e2565b6128119190614101565b601154601654919250612831916001600160a01b03908116911683613666565b61283b8183614123565b9150505b835461284c908290614171565b808555601454601954909161286191906140e2565b61286b9190614101565b6001850155601554601a54855461288291906140e2565b61288c9190614101565b6002850155601b5461289f908290614171565b601b5560405181815233906000805160206146408339815191529060200160405180910390a2601854600160a81b900460ff16156128df576128df6136ec565b50505050610efa60018055565b6128f4613396565b33600090815260216020526040902061290b6133ef565b6129136134d7565b80546000036129225750611882565b60008160010154601454601954846000015461293e91906140e2565b6129489190614101565b6129529190614123565b90508015611c7b5780612963612235565b10156129815760405162461bcd60e51b8152600401610a5f9061413a565b601754612998906001600160a01b03163383613666565b80601c5411156129b85780601c546129b09190614123565b601c556129be565b6000601c555b80601f546129cc9190614171565b601f556014546019548354611c8d91906140e2565b600e8181548110610b8e57600080fd5b6000601b54600003612a0557506000919050565b6001600160a01b0382166000908152602160209081526040808320815160608101835281548152600182015493810193909352600201549082015290612a4961188d565b9050601d54811115612a6957601d54612a629082614123565b9050612a6d565b5060005b601b546000612a7a612235565b6017546016549192506001600160a01b03908116911603612aa257612a9f8183614171565b91505b60008260155485612ab391906140e2565b612abd9190614101565b601a54612aca9190614171565b905060008560400151601554838860000151612ae691906140e2565b612af09190614101565b612afa9190614123565b98975050505050505050565b612b0e61333c565b60188054821515600160a81b0260ff60a81b199091161790556040517f6c55f8d24f45456d49b15692f6cd375689cbbc2cc46a33366288f1061229c1d390610b3690831515815260200190565b612b6361333c565b6107d08610612b845760405162461bcd60e51b8152600401610a5f90614189565b6107d08510612ba55760405162461bcd60e51b8152600401610a5f906141b6565b6126de841115612bf25760405162461bcd60e51b81526020600482015260186024820152770bee6d8d2e0e0c2ceca8cc2c6e8dee440e8dede40d0d2ced60431b6044820152606401610a5f565b600f8690556010859055600b849055600c80546001600160a01b0319166001600160a01b0385161790558051612c2f90600d906020840190613ccd565b508151612c4390600e906020850190613ccd565b507fe4ca6c7437a74a9ccfa4c03f7fadad98aa07cae9f4e4f35d7e294f87e4e81e33868686868686604051612c7d96959493929190614481565b60405180910390a1505050505050565b612c95613396565b3360009081526021602052604081208054828255600182018390556002820192909255908015612ce857601654612cd6906001600160a01b03163383613666565b80601b54612ce49190614123565b601b555b60405181815233907f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd96959060200160405180910390a2505061188b60018055565b612d30613396565b601854600160a01b900460ff161515600114612d5e5760405162461bcd60e51b8152600401610a5f90614359565b336000908152602160205260409020612d756133ef565b612d7d6134d7565b8054600003612d8c5750611882565b60008160020154601554601a548460000154612da891906140e2565b612db29190614101565b612dbc9190614123565b90508015612e2e576018546001600160a01b0316612e0f57336108fc612de1836136bc565b6040518115909202916000818181858888f19350505050158015612e09573d6000803e3d6000fd5b50612e1c565b612e1c33610d9d836136bc565b80601d54612e2a9190614123565b601d555b601554601a548354612e4091906140e2565b612e4a9190614101565b8260020181905550505061188b60018055565b612e6561333c565b6001600160a01b038116612eca5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a5f565b610efa81613905565b60008060205490506000601f54612ee8612235565b612ef29190614171565b9050600754600003612f2c5761191a600354600954612f1191906140e2565b612f1b91906140e2565b612f259083614171565b9150612f5a565b6000612f3c600a54600854613993565b905080600954612f4c91906140e2565b612f569084614171565b9250505b818110612f6a5760009250505090565b612f748183614123565b9250505090565b6001600160a01b03811660009081526021602090815260408083208151606081018352815481526001820154938101939093526002015490820152601954600a5443118015612fcb5750601b5415155b8015612fd957506000600a54115b1561302d576000612fec600a5443613993565b9050600060095482612ffe91906140e2565b9050601b546014548261301191906140e2565b61301b9190614101565b6019546130289190614171565b925050505b602082015160145483516130429084906140e2565b61304c9190614101565b6130569190614123565b949350505050565b61306661333c565b6000600754116130ae5760405162461bcd60e51b81526020600482015260136024820152721c1bdbdb081a5cc81b9bdd081cdd185c9d1959606a1b6044820152606401610a5f565b43600854116130fb5760405162461bcd60e51b81526020600482015260196024820152781c1bdbdb081dd85cc8185b1c9958591e48199a5b9a5cda1959603a1b6044820152606401610a5f565b6000811161311b5760405162461bcd60e51b8152600401610a5f90614415565b6131236134d7565b6017546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613154903090600401613d60565b602060405180830381865afa158015613171573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131959190614327565b6017549091506131b0906001600160a01b0316333085613955565b6017546040516370a0823160e01b81526000916001600160a01b0316906370a08231906131e1903090600401613d60565b602060405180830381865afa1580156131fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132229190614327565b90508181601c546132339190614171565b61323d9190614123565b601c556132486136ec565b505050565b61325561333c565b601e81101561329c5760405162461bcd60e51b81526020600482015260136024820152721b1bddd95c881b1a5b5a5d081c995858da1959606a1b6044820152606401610a5f565b60038190556007541561330c5761191a6003546132b991906140e2565b6007546132c69190614171565b6008819055431061330c5760405162461bcd60e51b815260206004820152601060248201526f34b73b30b634b210323ab930ba34b7b760811b6044820152606401610a5f565b6040518181527f91abcc2d6823e3a3f11d31b208dd3065d2c6a791f1c7c9fe96a42ce12897eac590602001610b36565b6000546001600160a01b0316331461188b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a5f565b6002600154036133e85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a5f565b6002600155565b6013543410156134555760405162461bcd60e51b815260206004820152602b60248201527f73686f756c642070617920736d616c6c2067617320746f20636f6d706f756e6460448201526a081bdc881a185c9d995cdd60aa1b6064820152608401610a5f565b6012546013546040516001600160a01b039092169181156108fc0291906000818181858888f19350505050158015613491573d6000803e3d6000fd5b5060135434111561188b5760135433906108fc906134af9034614123565b6040518115909202916000818181858888f19350505050158015610efa573d6000803e3d6000fd5b6000601b541180156134f25750601854600160a01b900460ff165b156135d257600061350161188d565b9050601d5481111561352157601d5461351a9082614123565b9050613525565b5060005b601b546000613532612235565b6017546016549192506001600160a01b0390811691160361355a576135578183614171565b91505b816015548461356991906140e2565b6135739190614101565b601a60008282546135849190614171565b9091555082905061359582856140e2565b61359f9190614101565b601e60008282546135b09190614171565b9250508190555082601d60008282546135c99190614171565b90915550505050505b600a54431115806135e35750600a54155b156135ea57565b601b546000036135fa5743600a55565b6000613608600a5443613993565b905060006009548261361a91906140e2565b9050601b546014548261362d91906140e2565b6136379190614101565b601960008282546136489190614171565b909155505043600a5560205461365f908290614171565b6020555050565b6132488363a9059cbb60e01b8484604051602401613685929190614340565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526139d4565b6000806136c761188d565b9050601d548311156136d957601d5492505b808311156136e5578092505b5090919050565b43600854116136f757565b6000601f54613704612235565b61370e9190614171565b9050602054811115610efa576020546137279082614123565b90506000436008546137399190614123565b90506137458183614101565b60098190556040519081527f0c4d677eef92893ac7ec52faf8140fc6c851ab4736302b4f3a89dfb20696a0df906020016114a0565b600c5460405163d06ca61f60e01b81526000916001600160a01b03169063d06ca61f906137ad90879087906004016144d3565b600060405180830381865afa1580156137ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526137f291908101906144ec565b9050600081600183516138059190614123565b8151811061381557613815614572565b6020026020010151905061386c600c60009054906101000a90046001600160a01b0316868660008151811061384c5761384c614572565b60200260200101516001600160a01b0316613aa69092919063ffffffff16565b600c54600b546001600160a01b0390911690635c11d7959087906127109061389490866140e2565b61389e9190614101565b87876138ac42610258614171565b6040518663ffffffff1660e01b81526004016138cc959493929190614588565b600060405180830381600087803b1580156138e657600080fd5b505af11580156138fa573d6000803e3d6000fd5b505050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b038085166024830152831660448201526064810182905261398d9085906323b872dd60e01b90608401613685565b50505050565b600060085482116139af576139a88383614123565b90506139ce565b60085483106139c0575060006139ce565b826008546139a89190614123565b92915050565b6000613a29826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613baa9092919063ffffffff16565b8051909150156132485780806020019051810190613a4791906143f8565b6132485760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610a5f565b801580613b205750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015613afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1e9190614327565b155b613b8b5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610a5f565b6132488363095ea7b360e01b8484604051602401613685929190614340565b6060613056848460008585600080866001600160a01b03168587604051613bd191906145f0565b60006040518083038185875af1925050503d8060008114613c0e576040519150601f19603f3d011682016040523d82523d6000602084013e613c13565b606091505b5091509150613c2487838387613c2f565b979650505050505050565b60608315613c9e578251600003613c97576001600160a01b0385163b613c975760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a5f565b5081613056565b6130568383815115613cb35781518083602001fd5b8060405162461bcd60e51b8152600401610a5f919061460c565b828054828255906000526020600020908101928215613d22579160200282015b82811115613d2257825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613ced565b50613d2e929150613d32565b5090565b5b80821115613d2e5760008155600101613d33565b600060208284031215613d5957600080fd5b5035919050565b6001600160a01b0391909116815260200190565b6001600160a01b0381168114610efa57600080fd5b803561198e81613d74565b600060208284031215613da657600080fd5b8135613db181613d74565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613df757613df7613db8565b604052919050565b600067ffffffffffffffff821115613e1957613e19613db8565b5060051b60200190565b600082601f830112613e3457600080fd5b81356020613e49613e4483613dff565b613dce565b82815260059290921b84018101918181019086841115613e6857600080fd5b8286015b84811015613e8c578035613e7f81613d74565b8352918301918301613e6c565b509695505050505050565b8015158114610efa57600080fd5b803561198e81613e97565b60008060008060008060008060008060006101608c8e031215613ed257600080fd5b613edb8c613d89565b9a50613ee960208d01613d89565b9950613ef760408d01613d89565b985060608c0135975060808c0135965060a08c01359550613f1a60c08d01613d89565b945067ffffffffffffffff8060e08e01351115613f3657600080fd5b613f468e60e08f01358f01613e23565b9450806101008e01351115613f5a57600080fd5b50613f6c8d6101008e01358e01613e23565b9250613f7b6101208d01613d89565b9150613f8a6101408d01613ea5565b90509295989b509295989b9093969950565b60008060408385031215613faf57600080fd5b8235613fba81613d74565b946020939093013593505050565b60008060408385031215613fdb57600080fd5b8235613fba81613e97565b600060208284031215613ff857600080fd5b8135613db181613e97565b60008060008060008060c0878903121561401c57600080fd5b863595506020870135945060408701359350606087013561403c81613d74565b9250608087013567ffffffffffffffff8082111561405957600080fd5b6140658a838b01613e23565b935060a089013591508082111561407b57600080fd5b5061408889828a01613e23565b9150509295509295509295565b6020808252601f908201527f416d6f756e742073686f756c642062652067726561746f72207468616e203000604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156140fc576140fc6140cc565b500290565b60008261411e57634e487b7160e01b600052601260045260246000fd5b500490565b600082821015614135576141356140cc565b500390565b6020808252601a908201527f496e73756666696369656e742072657761726420746f6b656e73000000000000604082015260600190565b60008219821115614184576141846140cc565b500190565b602080825260139082015272496e76616c6964206465706f7369742066656560681b604082015260600190565b602080825260149082015273496e76616c69642077697468647261772066656560601b604082015260600190565b6000602082840312156141f657600080fd5b815160ff81168114613db157600080fd5b60208082526016908201527504d75737420626520696e666572696f7220746f2033360541b604082015260600190565b600181815b80851115614272578160001904821115614258576142586140cc565b8085161561426557918102915b93841c939080029061423c565b509250929050565b600082614289575060016139ce565b81614296575060006139ce565b81600181146142ac57600281146142b6576142d2565b60019150506139ce565b60ff8411156142c7576142c76140cc565b50506001821b6139ce565b5060208310610133831016604e8410600b84101617156142f5575081810a6139ce565b6142ff8383614237565b8060001904821115614313576143136140cc565b029392505050565b6000613db1838361427a565b60006020828403121561433957600080fd5b5051919050565b6001600160a01b03929092168252602082015260400190565b6020808252600e908201526d4e6f207265666c656374696f6e7360901b604082015260600190565b60006020828403121561439357600080fd5b8151613db181613d74565b602080825260179082015276155cd95c88185b5bdd5b9d0818589bdd99481b1a5b5a5d604a1b604082015260600190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b60006020828403121561440a57600080fd5b8151613db181613e97565b6020808252600e908201526d1a5b9d985b1a5908185b5bdd5b9d60921b604082015260600190565b600081518084526020808501945080840160005b838110156144765781516001600160a01b031687529582019590820190600101614451565b509495945050505050565b86815285602082015284604082015260018060a01b038416606082015260c0608082015260006144b460c083018561443d565b82810360a08401526144c6818561443d565b9998505050505050505050565b828152604060208201526000613056604083018461443d565b600060208083850312156144ff57600080fd5b825167ffffffffffffffff81111561451657600080fd5b8301601f8101851361452757600080fd5b8051614535613e4482613dff565b81815260059190911b8201830190838101908783111561455457600080fd5b928401925b82841015613c2457835182529284019290840190614559565b634e487b7160e01b600052603260045260246000fd5b85815284602082015260a0604082015260006145a760a083018661443d565b6001600160a01b0394909416606083015250608001529392505050565b60005b838110156145df5781810151838201526020016145c7565b8381111561398d5750506000910152565b600082516146028184602087016145c4565b9190910192915050565b602081526000825180602084015261462b8160408501602087016145c4565b601f01601f1916919091016040019291505056fee1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109ca2646970667358221220a7940b66c263a113f921847e7fc0d140ed65337736ef5a2dd96e38b838cf9a0f64736f6c634300080e0033
Deployed Bytecode
0x60806040526004361061033b5760003560e01c806387788782116101b2578063b88a802f116100ed578063e941fa7811610090578063e941fa781461094a578063f0fc6bca14610960578063f2fde38b14610968578063f3aeb31d14610988578063f40f0f521461099d578063f4ef5ed5146109bd578063f6be71d1146109dd578063ffbd3b1f146109fd57600080fd5b8063b88a802f14610881578063bc063e1a14610889578063c1e22a651461089f578063c7926458146108bf578063ccd34cd5146108df578063cd635cce146108f5578063d5f0ca9414610915578063db2e21bc1461093557600080fd5b806396c5f9801161015557806396c5f980146107ac5780639f94e272146107cc578063a0b40905146107e1578063a5bfd0f214610801578063a9f8d18114610822578063b6b55f2514610838578063b74cd2421461084b578063b77e7da01461086157600080fd5b806387788782146106e657806388bbb0c1146106fc5780638ae39cac146107125780638bdf67f2146107285780638da5cb5b146107485780638f6629151461076657806392b46e5b1461077c57806392e8990e1461079257600080fd5b80634de8ff2111610282578063715018a611610225578063715018a61461061157806372f702f314610626578063746c8ae1146106465780637972271b1461065b57806380dc06721461067b578063817b1cd21461069057806381b61948146106a6578063854cff2f146106c657600080fd5b80634de8ff21146105605780635dde4a911461056857806361d027b31461057d57806366fe9f8a1461059d57806367a52793146105b3578063693a090b146105c95780636d971a10146105e95780636e707b73146105f157600080fd5b806324937567116102ea578063249375671461046c5780632e1a7d4d1461049d5780633279beab146104b05780633544a864146104d057806338411f21146104f0578063392e53cd146105105780633f138d4b1461052a57806348cd4cb11461054a57600080fd5b80626f02311461034757806301f8a976146103695780630fb5a6b4146103895780631582358e146103b2578063167d2dbe146103df5780631959a002146103ff5780631aed65531461045657600080fd5b3661034257005b600080fd5b34801561035357600080fd5b50610367610362366004613d47565b610a13565b005b34801561037557600080fd5b50610367610384366004613d47565b610b41565b34801561039557600080fd5b5061039f60035481565b6040519081526020015b60405180910390f35b3480156103be57600080fd5b506018546103d2906001600160a01b031681565b6040516103a99190613d60565b3480156103eb57600080fd5b506103d26103fa366004613d47565b610b7e565b34801561040b57600080fd5b5061043b61041a366004613d94565b60216020526000908152604090208054600182015460029092015490919083565b604080519384526020840192909252908201526060016103a9565b34801561046257600080fd5b5061039f60085481565b34801561047857600080fd5b5060185461048d90600160a81b900460ff1681565b60405190151581526020016103a9565b6103676104ab366004613d47565b610ba8565b3480156104bc57600080fd5b506103676104cb366004613d47565b610efd565b3480156104dc57600080fd5b506006546103d2906001600160a01b031681565b3480156104fc57600080fd5b5061036761050b366004613eb0565b610fc7565b34801561051c57600080fd5b5060025461048d9060ff1681565b34801561053657600080fd5b50610367610545366004613f9c565b6112c3565b34801561055657600080fd5b5061039f60075481565b6103676114ac565b34801561057457600080fd5b5061039f61188d565b34801561058957600080fd5b506012546103d2906001600160a01b031681565b3480156105a957600080fd5b5061039f60055481565b3480156105bf57600080fd5b5061039f600f5481565b3480156105d557600080fd5b50600c546103d2906001600160a01b031681565b610367611993565b3480156105fd57600080fd5b506017546103d2906001600160a01b031681565b34801561061d57600080fd5b50610367611ca2565b34801561063257600080fd5b506016546103d2906001600160a01b031681565b34801561065257600080fd5b50610367611cb4565b34801561066757600080fd5b50610367610676366004613d94565b611d7f565b34801561068757600080fd5b50610367611e13565b34801561069c57600080fd5b5061039f601b5481565b3480156106b257600080fd5b506103676106c1366004613f9c565b611f26565b3480156106d257600080fd5b506103676106e1366004613d94565b611ff4565b3480156106f257600080fd5b5061039f60135481565b34801561070857600080fd5b5061039f60155481565b34801561071e57600080fd5b5061039f60095481565b34801561073457600080fd5b50610367610743366004613d47565b612047565b34801561075457600080fd5b506000546001600160a01b03166103d2565b34801561077257600080fd5b5061039f60195481565b34801561078857600080fd5b5061039f601a5481565b34801561079e57600080fd5b5060045461048d9060ff1681565b3480156107b857600080fd5b506103676107c7366004613d94565b61219d565b3480156107d857600080fd5b5061039f612235565b3480156107ed57600080fd5b506103676107fc366004613fc8565b612309565b34801561080d57600080fd5b5060185461048d90600160a01b900460ff1681565b34801561082e57600080fd5b5061039f600a5481565b610367610846366004613d47565b6123c2565b34801561085757600080fd5b5061039f6126de81565b34801561086d57600080fd5b506011546103d2906001600160a01b031681565b6103676128ec565b34801561089557600080fd5b5061039f6107d081565b3480156108ab57600080fd5b506103d26108ba366004613d47565b6129e1565b3480156108cb57600080fd5b5061039f6108da366004613d94565b6129f1565b3480156108eb57600080fd5b5061039f60145481565b34801561090157600080fd5b50610367610910366004613fe6565b612b06565b34801561092157600080fd5b50610367610930366004614003565b612b5b565b34801561094157600080fd5b50610367612c8d565b34801561095657600080fd5b5061039f60105481565b610367612d28565b34801561097457600080fd5b50610367610983366004613d94565b612e5d565b34801561099457600080fd5b5061039f612ed3565b3480156109a957600080fd5b5061039f6109b8366004613d94565b612f7b565b3480156109c957600080fd5b506103676109d8366004613d47565b61305e565b3480156109e957600080fd5b506103676109f8366004613d47565b61324d565b348015610a0957600080fd5b5061039f600b5481565b610a1b61333c565b600060075411610a685760405162461bcd60e51b8152602060048201526013602482015272141bdbdb081a5cc81b9bdd081cdd185c9d1959606a1b60448201526064015b60405180910390fd5b4360085411610ab55760405162461bcd60e51b8152602060048201526019602482015278141bdbdb081dd85cc8185b1c9958591e48199a5b9a5cda1959603a1b6044820152606401610a5f565b4381118015610ac5575060075481115b610b055760405162461bcd60e51b8152602060048201526011602482015270496e76616c696420656e6420626c6f636b60781b6044820152606401610a5f565b60088190556040518181527f0972575658363b3e7c472ab3a6a918726742c853b732f6a4a2763e2e3a94c977906020015b60405180910390a150565b610b4961333c565b60098190556040518181527f0c4d677eef92893ac7ec52faf8140fc6c851ab4736302b4f3a89dfb20696a0df90602001610b36565b600d8181548110610b8e57600080fd5b6000918252602090912001546001600160a01b0316905081565b610bb0613396565b60008111610bd05760405162461bcd60e51b8152600401610a5f90614095565b3360009081526021602052604090208054821115610c305760405162461bcd60e51b815260206004820152601b60248201527f416d6f756e7420746f20776974686472617720746f6f206869676800000000006044820152606401610a5f565b610c386133ef565b610c406134d7565b805415610dc557600081600101546014546019548460000154610c6391906140e2565b610c6d9190614101565b610c779190614123565b90508015610cf55780610c88612235565b1015610ca65760405162461bcd60e51b8152600401610a5f9061413a565b601754610cbd906001600160a01b03163383613666565b80601c541115610cdd5780601c54610cd59190614123565b601c55610ce3565b6000601c555b80601f54610cf19190614171565b601f555b60008260020154601554601a548560000154610d1191906140e2565b610d1b9190614101565b610d259190614123565b9050600081118015610d405750601854600160a01b900460ff165b15610dc2576018546001600160a01b0316610d9057336108fc610d62836136bc565b6040518115909202916000818181858888f19350505050158015610d8a573d6000803e3d6000fd5b50610db0565b610db033610d9d836136bc565b6018546001600160a01b03169190613666565b80601d54610dbe9190614123565b601d555b50505b80548290811115610dd4575080545b8154610de1908290614123565b8255601b54610df1908290614123565b601b5560405181815233907f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243649060200160405180910390a260105415610e7c57600061271060105483610e4491906140e2565b610e4e9190614101565b601154601654919250610e6e916001600160a01b03908116911683613666565b610e788183614123565b9150505b601654610e93906001600160a01b03163383613666565b6014546019548354610ea591906140e2565b610eaf9190614101565b6001830155601554601a548354610ec691906140e2565b610ed09190614101565b6002830155601854600160a81b900460ff1615610eef57610eef6136ec565b5050610efa60018055565b50565b610f0561333c565b6008544311610f485760405162461bcd60e51b815260206004820152600f60248201526e506f6f6c2069732072756e6e696e6760881b6044820152606401610a5f565b80610f51612235565b1015610f6f5760405162461bcd60e51b8152600401610a5f9061413a565b80600003610f8257610f7f612235565b90505b601754610f99906001600160a01b03163383613666565b601c5415610efa57601c54811115610fb3576000601c5550565b80601c54610fc19190614123565b601c5550565b610fcf61333c565b60025460ff16156110185760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610a5f565b6002805460ff19166001179055601680546001600160a01b03808e166001600160a01b031992831617909255601780548d8416921691909117905560188054831515600160a01b026001600160a81b0319909116928c169290921791909117905560098890556107d0871061109f5760405162461bcd60e51b8152600401610a5f90614189565b6107d086106110c05760405162461bcd60e51b8152600401610a5f906141b6565b600f8790556010869055601180546001600160a01b031916331790556017546040805163313ce56760e01b815290516000926001600160a01b03169163313ce5679160048083019260209291908290030181865afa158015611126573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114a91906141e4565b60ff169050601e811061116f5760405162461bcd60e51b8152600401610a5f90614207565b61117a816028614123565b61118590600a61431b565b6014556018546012906001600160a01b03161561123857601860009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111ef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121391906141e4565b60ff169050601e81106112385760405162461bcd60e51b8152600401610a5f90614207565b611243816028614123565b61124e90600a61431b565b601555600c80546001600160a01b0319166001600160a01b038916179055855161127f90600e906020890190613ccd565b50845161129390600d906020880190613ccd565b5050600680546001600160a01b0319166001600160a01b0394909416939093179092555050505050505050505050565b6112cb61333c565b6017546001600160a01b0383811691161415806112f557506018546001600160a01b038381169116145b61133a5760405162461bcd60e51b815260206004820152601660248201527521b0b73737ba103132903932bbb0b932103a37b5b2b760511b6044820152606401610a5f565b6016546001600160a01b039081169083160361141a576016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611381903090600401613d60565b602060405180830381865afa15801561139e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c29190614327565b9050601b54816113d29190614123565b8211156114185760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610a5f565b505b6001600160a01b03821661145b57604051339082156108fc029083906000818181858888f19350505050158015611455573d6000803e3d6000fd5b5061146f565b61146f6001600160a01b0383163383613666565b7f74f5dcd55c394cb1c6d3b9da22c2464bcc46c38cc3865bd629ed75823249b40b82826040516114a0929190614340565b60405180910390a15050565b6114b4613396565b601854600160a01b900460ff1615156001146114e25760405162461bcd60e51b8152600401610a5f90614359565b3360009081526021602052604090206114f96133ef565b6115016134d7565b80546000036115105750611882565b60008160020154601554601a54846000015461152c91906140e2565b6115369190614101565b6115409190614123565b9050600061154d826136bc565b905081601d5461155d9190614123565b601d55801561185a576018546016546001600160a01b039081169116146117b0576018546001600160a01b031661165457600c54604080516315ab88c960e31b815290516000926001600160a01b03169163ad5c46489160048083019260209291908290030181865afa1580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190614381565b9050806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b15801561163957600080fd5b505af115801561164d573d6000803e3d6000fd5b5050505050505b6016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611685903090600401613d60565b602060405180830381865afa1580156116a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116c69190614327565b905061172d82600d80548060200260200160405190810160405280929190818152602001828054801561172257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611704575b50505050503061377a565b6016546040516370a0823160e01b81526000916001600160a01b0316906370a082319061175e903090600401613d60565b602060405180830381865afa15801561177b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179f9190614327565b90506117ab8282614123565b925050505b60045460ff16156117e85760055483546117ca9083614171565b11156117e85760405162461bcd60e51b8152600401610a5f9061439e565b80601b546117f69190614171565b601b558254611806908290614171565b835560145460195461181890836140e2565b6118229190614101565b83600101546118319190614171565b600184015560405181815233906000805160206146408339815191529060200160405180910390a25b601554601a54845461186c91906140e2565b6118769190614101565b83600201819055505050505b61188b60018055565b565b6018546000906001600160a01b03166118a557504790565b6018546040516370a0823160e01b81526000916001600160a01b0316906370a08231906118d6903090600401613d60565b602060405180830381865afa1580156118f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119179190614327565b6017546018549192506001600160a01b0390811691160361195457601c5481101561194457600091505090565b601c546119519082614123565b90505b6016546018546001600160a01b0391821691160361198e57601b5481101561197e57600091505090565b601b5461198b9082614123565b90505b919050565b61199b613396565b3360009081526021602052604090206119b26133ef565b6119ba6134d7565b80546000036119c95750611882565b6000816001015460145460195484600001546119e591906140e2565b6119ef9190614101565b6119f99190614123565b90508015611c7b5780611a0a612235565b1015611a285760405162461bcd60e51b8152600401610a5f9061413a565b80601c541115611a485780601c54611a409190614123565b601c55611a4e565b6000601c555b80601f54611a5c9190614171565b601f556017546016546001600160a01b03908116911614611bd1576016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611aa8903090600401613d60565b602060405180830381865afa158015611ac5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae99190614327565b9050611b4e82600e805480602002602001604051908101604052809291908181526020018280548015611722576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116117045750505050503061377a565b6016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611b7f903090600401613d60565b602060405180830381865afa158015611b9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc09190614327565b9050611bcc8282614123565b925050505b60045460ff1615611c09576005548254611beb9083614171565b1115611c095760405162461bcd60e51b8152600401610a5f9061439e565b80601b54611c179190614171565b601b558154611c27908290614171565b8255601554601a54611c3990836140e2565b611c439190614101565b8260020154611c529190614171565b600283015560405181815233906000805160206146408339815191529060200160405180910390a25b6014546019548354611c8d91906140e2565b611c979190614101565b600192830155508055565b611caa61333c565b61188b6000613905565b611cbc61333c565b60075415611d075760405162461bcd60e51b8152602060048201526018602482015277141bdbdb081dd85cc8185b1c9958591e481cdd185c9d195960421b6044820152606401610a5f565b611d12436064614171565b600755600354611d259061191a906140e2565b600754611d329190614171565b6008819055600754600a8190556040517f7cd0ab87d19036f3dfadadb232c78aa4879dda3f0c994a9d637532410ee2ce0692611d75928252602082015260400190565b60405180910390a1565b611d8761333c565b6001600160a01b038116151580611dac57506011546001600160a01b03828116911614155b611dc85760405162461bcd60e51b8152600401610a5f906143cf565b601180546001600160a01b0319166001600160a01b0383161790556040517f6de6ddf87fbce1f42220b349684d9b952eac9bffd639fd2093096032cb1d4d4e90610b36908390613d60565b611e1b61333c565b611e236134d7565b6000601f54611e30612235565b611e3a9190614171565b9050602054811115611ef057602054611e539082614123565b60175460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb90611e869033908590600401614340565b6020604051808303816000875af1158015611ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec991906143f8565b5080601c541115611eea5780601c54611ee29190614123565b601c55611ef0565b6000601c555b4360088190556040519081527ffed9fcb0ca3d1e761a4b929792bb24082fba92dca81252646ad306d30680656690602001610b36565b6012546001600160a01b03163314611f7c5760405162461bcd60e51b815260206004820152601960248201527839b2ba29b2b93b34b1b2a4b733379d102327a92124a22222a760391b6044820152606401610a5f565b6001600160a01b038216611fa25760405162461bcd60e51b8152600401610a5f906143cf565b601280546001600160a01b0319166001600160a01b03841617905560138190556040517f232f2e6280d2064b1e439bf40ecdada042d84eefbb55039e4c49e8dc4f4c90c9906114a09084908490614340565b611ffc61333c565b600680546001600160a01b0319166001600160a01b0383161790556040517f3990e3e141b903f4f5602428874be692206642a653b416f336d965e2f04813ce90610b36908390613d60565b61204f61333c565b612057613396565b600081116120775760405162461bcd60e51b8152600401610a5f90614415565b6017546040516370a0823160e01b81526000916001600160a01b0316906370a08231906120a8903090600401613d60565b602060405180830381865afa1580156120c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e99190614327565b601754909150612104906001600160a01b0316333085613955565b6017546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612135903090600401613d60565b602060405180830381865afa158015612152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121769190614327565b90508181601c546121879190614171565b6121919190614123565b601c5550506001805550565b6121a561333c565b6121ad6134d7565b601e5415610efa576018546001600160a01b031661220b57806001600160a01b03166108fc6121dd601e546136bc565b6040518115909202916000818181858888f19350505050158015612205573d6000803e3d6000fd5b5061221a565b61221a81610d9d601e546136bc565b601e54601d5461222a9190614123565b601d556000601e5550565b6018546017546000916001600160a01b039081169116036122575750601c5490565b6017546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612288903090600401613d60565b602060405180830381865afa1580156122a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c99190614327565b6016546017549192506001600160a01b0390811691160361198e57601b548110156122f657600091505090565b601b546123039082614123565b91505090565b61231161333c565b811561236d5760055481116123635760405162461bcd60e51b81526020600482015260186024820152772732bb903634b6b4ba1036bab9ba103132903434b3b432b960411b6044820152606401610a5f565b6005819055612373565b60006005555b6004805460ff19168315159081179091556005546040805191825260ff909216151560208201527f19a6e21b354f2502655dd03f5ac08375f296d713847fbfbf7eec539cd22c443991016114a0565b6123ca613396565b60006007541180156123dd575043600754105b6124295760405162461bcd60e51b815260206004820152601a60248201527f5374616b696e67206861736e27742073746172746564207965740000000000006044820152606401610a5f565b600081116124495760405162461bcd60e51b8152600401610a5f90614095565b6006546001600160a01b03161561250957600654604051636c9b2a3f60e11b81526001600160a01b039091169063d936547e9061248a903390600401613d60565b602060405180830381865afa1580156124a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124cb91906143f8565b6125095760405162461bcd60e51b815260206004820152600f60248201526e1b9bdd081dda1a5d195b1a5cdd1959608a1b6044820152606401610a5f565b33600090815260216020526040902060045460ff16156125505760055481546125329084614171565b11156125505760405162461bcd60e51b8152600401610a5f9061439e565b6125586133ef565b6125606134d7565b8054156126d25760008160010154601454601954846000015461258391906140e2565b61258d9190614101565b6125979190614123565b9050801561261557806125a8612235565b10156125c65760405162461bcd60e51b8152600401610a5f9061413a565b6017546125dd906001600160a01b03163383613666565b80601c5411156125fd5780601c546125f59190614123565b601c55612603565b6000601c555b80601f546126119190614171565b601f555b60008260020154601554601a54856000015461263191906140e2565b61263b9190614101565b6126459190614123565b90506000811180156126605750601854600160a01b900460ff165b156126cf576018546001600160a01b03166126b057336108fc612682836136bc565b6040518115909202916000818181858888f193505050501580156126aa573d6000803e3d6000fd5b506126bd565b6126bd33610d9d836136bc565b80601d546126cb9190614123565b601d555b50505b6016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612703903090600401613d60565b602060405180830381865afa158015612720573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127449190614327565b60165490915061275f906001600160a01b0316333086613955565b6016546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612790903090600401613d60565b602060405180830381865afa1580156127ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127d19190614327565b905060006127df8383614123565b9050848111156127ec5750835b600f541561283f576000612710600f548361280791906140e2565b6128119190614101565b601154601654919250612831916001600160a01b03908116911683613666565b61283b8183614123565b9150505b835461284c908290614171565b808555601454601954909161286191906140e2565b61286b9190614101565b6001850155601554601a54855461288291906140e2565b61288c9190614101565b6002850155601b5461289f908290614171565b601b5560405181815233906000805160206146408339815191529060200160405180910390a2601854600160a81b900460ff16156128df576128df6136ec565b50505050610efa60018055565b6128f4613396565b33600090815260216020526040902061290b6133ef565b6129136134d7565b80546000036129225750611882565b60008160010154601454601954846000015461293e91906140e2565b6129489190614101565b6129529190614123565b90508015611c7b5780612963612235565b10156129815760405162461bcd60e51b8152600401610a5f9061413a565b601754612998906001600160a01b03163383613666565b80601c5411156129b85780601c546129b09190614123565b601c556129be565b6000601c555b80601f546129cc9190614171565b601f556014546019548354611c8d91906140e2565b600e8181548110610b8e57600080fd5b6000601b54600003612a0557506000919050565b6001600160a01b0382166000908152602160209081526040808320815160608101835281548152600182015493810193909352600201549082015290612a4961188d565b9050601d54811115612a6957601d54612a629082614123565b9050612a6d565b5060005b601b546000612a7a612235565b6017546016549192506001600160a01b03908116911603612aa257612a9f8183614171565b91505b60008260155485612ab391906140e2565b612abd9190614101565b601a54612aca9190614171565b905060008560400151601554838860000151612ae691906140e2565b612af09190614101565b612afa9190614123565b98975050505050505050565b612b0e61333c565b60188054821515600160a81b0260ff60a81b199091161790556040517f6c55f8d24f45456d49b15692f6cd375689cbbc2cc46a33366288f1061229c1d390610b3690831515815260200190565b612b6361333c565b6107d08610612b845760405162461bcd60e51b8152600401610a5f90614189565b6107d08510612ba55760405162461bcd60e51b8152600401610a5f906141b6565b6126de841115612bf25760405162461bcd60e51b81526020600482015260186024820152770bee6d8d2e0e0c2ceca8cc2c6e8dee440e8dede40d0d2ced60431b6044820152606401610a5f565b600f8690556010859055600b849055600c80546001600160a01b0319166001600160a01b0385161790558051612c2f90600d906020840190613ccd565b508151612c4390600e906020850190613ccd565b507fe4ca6c7437a74a9ccfa4c03f7fadad98aa07cae9f4e4f35d7e294f87e4e81e33868686868686604051612c7d96959493929190614481565b60405180910390a1505050505050565b612c95613396565b3360009081526021602052604081208054828255600182018390556002820192909255908015612ce857601654612cd6906001600160a01b03163383613666565b80601b54612ce49190614123565b601b555b60405181815233907f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd96959060200160405180910390a2505061188b60018055565b612d30613396565b601854600160a01b900460ff161515600114612d5e5760405162461bcd60e51b8152600401610a5f90614359565b336000908152602160205260409020612d756133ef565b612d7d6134d7565b8054600003612d8c5750611882565b60008160020154601554601a548460000154612da891906140e2565b612db29190614101565b612dbc9190614123565b90508015612e2e576018546001600160a01b0316612e0f57336108fc612de1836136bc565b6040518115909202916000818181858888f19350505050158015612e09573d6000803e3d6000fd5b50612e1c565b612e1c33610d9d836136bc565b80601d54612e2a9190614123565b601d555b601554601a548354612e4091906140e2565b612e4a9190614101565b8260020181905550505061188b60018055565b612e6561333c565b6001600160a01b038116612eca5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a5f565b610efa81613905565b60008060205490506000601f54612ee8612235565b612ef29190614171565b9050600754600003612f2c5761191a600354600954612f1191906140e2565b612f1b91906140e2565b612f259083614171565b9150612f5a565b6000612f3c600a54600854613993565b905080600954612f4c91906140e2565b612f569084614171565b9250505b818110612f6a5760009250505090565b612f748183614123565b9250505090565b6001600160a01b03811660009081526021602090815260408083208151606081018352815481526001820154938101939093526002015490820152601954600a5443118015612fcb5750601b5415155b8015612fd957506000600a54115b1561302d576000612fec600a5443613993565b9050600060095482612ffe91906140e2565b9050601b546014548261301191906140e2565b61301b9190614101565b6019546130289190614171565b925050505b602082015160145483516130429084906140e2565b61304c9190614101565b6130569190614123565b949350505050565b61306661333c565b6000600754116130ae5760405162461bcd60e51b81526020600482015260136024820152721c1bdbdb081a5cc81b9bdd081cdd185c9d1959606a1b6044820152606401610a5f565b43600854116130fb5760405162461bcd60e51b81526020600482015260196024820152781c1bdbdb081dd85cc8185b1c9958591e48199a5b9a5cda1959603a1b6044820152606401610a5f565b6000811161311b5760405162461bcd60e51b8152600401610a5f90614415565b6131236134d7565b6017546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613154903090600401613d60565b602060405180830381865afa158015613171573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131959190614327565b6017549091506131b0906001600160a01b0316333085613955565b6017546040516370a0823160e01b81526000916001600160a01b0316906370a08231906131e1903090600401613d60565b602060405180830381865afa1580156131fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132229190614327565b90508181601c546132339190614171565b61323d9190614123565b601c556132486136ec565b505050565b61325561333c565b601e81101561329c5760405162461bcd60e51b81526020600482015260136024820152721b1bddd95c881b1a5b5a5d081c995858da1959606a1b6044820152606401610a5f565b60038190556007541561330c5761191a6003546132b991906140e2565b6007546132c69190614171565b6008819055431061330c5760405162461bcd60e51b815260206004820152601060248201526f34b73b30b634b210323ab930ba34b7b760811b6044820152606401610a5f565b6040518181527f91abcc2d6823e3a3f11d31b208dd3065d2c6a791f1c7c9fe96a42ce12897eac590602001610b36565b6000546001600160a01b0316331461188b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a5f565b6002600154036133e85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a5f565b6002600155565b6013543410156134555760405162461bcd60e51b815260206004820152602b60248201527f73686f756c642070617920736d616c6c2067617320746f20636f6d706f756e6460448201526a081bdc881a185c9d995cdd60aa1b6064820152608401610a5f565b6012546013546040516001600160a01b039092169181156108fc0291906000818181858888f19350505050158015613491573d6000803e3d6000fd5b5060135434111561188b5760135433906108fc906134af9034614123565b6040518115909202916000818181858888f19350505050158015610efa573d6000803e3d6000fd5b6000601b541180156134f25750601854600160a01b900460ff165b156135d257600061350161188d565b9050601d5481111561352157601d5461351a9082614123565b9050613525565b5060005b601b546000613532612235565b6017546016549192506001600160a01b0390811691160361355a576135578183614171565b91505b816015548461356991906140e2565b6135739190614101565b601a60008282546135849190614171565b9091555082905061359582856140e2565b61359f9190614101565b601e60008282546135b09190614171565b9250508190555082601d60008282546135c99190614171565b90915550505050505b600a54431115806135e35750600a54155b156135ea57565b601b546000036135fa5743600a55565b6000613608600a5443613993565b905060006009548261361a91906140e2565b9050601b546014548261362d91906140e2565b6136379190614101565b601960008282546136489190614171565b909155505043600a5560205461365f908290614171565b6020555050565b6132488363a9059cbb60e01b8484604051602401613685929190614340565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526139d4565b6000806136c761188d565b9050601d548311156136d957601d5492505b808311156136e5578092505b5090919050565b43600854116136f757565b6000601f54613704612235565b61370e9190614171565b9050602054811115610efa576020546137279082614123565b90506000436008546137399190614123565b90506137458183614101565b60098190556040519081527f0c4d677eef92893ac7ec52faf8140fc6c851ab4736302b4f3a89dfb20696a0df906020016114a0565b600c5460405163d06ca61f60e01b81526000916001600160a01b03169063d06ca61f906137ad90879087906004016144d3565b600060405180830381865afa1580156137ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526137f291908101906144ec565b9050600081600183516138059190614123565b8151811061381557613815614572565b6020026020010151905061386c600c60009054906101000a90046001600160a01b0316868660008151811061384c5761384c614572565b60200260200101516001600160a01b0316613aa69092919063ffffffff16565b600c54600b546001600160a01b0390911690635c11d7959087906127109061389490866140e2565b61389e9190614101565b87876138ac42610258614171565b6040518663ffffffff1660e01b81526004016138cc959493929190614588565b600060405180830381600087803b1580156138e657600080fd5b505af11580156138fa573d6000803e3d6000fd5b505050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b038085166024830152831660448201526064810182905261398d9085906323b872dd60e01b90608401613685565b50505050565b600060085482116139af576139a88383614123565b90506139ce565b60085483106139c0575060006139ce565b826008546139a89190614123565b92915050565b6000613a29826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613baa9092919063ffffffff16565b8051909150156132485780806020019051810190613a4791906143f8565b6132485760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610a5f565b801580613b205750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015613afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1e9190614327565b155b613b8b5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610a5f565b6132488363095ea7b360e01b8484604051602401613685929190614340565b6060613056848460008585600080866001600160a01b03168587604051613bd191906145f0565b60006040518083038185875af1925050503d8060008114613c0e576040519150601f19603f3d011682016040523d82523d6000602084013e613c13565b606091505b5091509150613c2487838387613c2f565b979650505050505050565b60608315613c9e578251600003613c97576001600160a01b0385163b613c975760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a5f565b5081613056565b6130568383815115613cb35781518083602001fd5b8060405162461bcd60e51b8152600401610a5f919061460c565b828054828255906000526020600020908101928215613d22579160200282015b82811115613d2257825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613ced565b50613d2e929150613d32565b5090565b5b80821115613d2e5760008155600101613d33565b600060208284031215613d5957600080fd5b5035919050565b6001600160a01b0391909116815260200190565b6001600160a01b0381168114610efa57600080fd5b803561198e81613d74565b600060208284031215613da657600080fd5b8135613db181613d74565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613df757613df7613db8565b604052919050565b600067ffffffffffffffff821115613e1957613e19613db8565b5060051b60200190565b600082601f830112613e3457600080fd5b81356020613e49613e4483613dff565b613dce565b82815260059290921b84018101918181019086841115613e6857600080fd5b8286015b84811015613e8c578035613e7f81613d74565b8352918301918301613e6c565b509695505050505050565b8015158114610efa57600080fd5b803561198e81613e97565b60008060008060008060008060008060006101608c8e031215613ed257600080fd5b613edb8c613d89565b9a50613ee960208d01613d89565b9950613ef760408d01613d89565b985060608c0135975060808c0135965060a08c01359550613f1a60c08d01613d89565b945067ffffffffffffffff8060e08e01351115613f3657600080fd5b613f468e60e08f01358f01613e23565b9450806101008e01351115613f5a57600080fd5b50613f6c8d6101008e01358e01613e23565b9250613f7b6101208d01613d89565b9150613f8a6101408d01613ea5565b90509295989b509295989b9093969950565b60008060408385031215613faf57600080fd5b8235613fba81613d74565b946020939093013593505050565b60008060408385031215613fdb57600080fd5b8235613fba81613e97565b600060208284031215613ff857600080fd5b8135613db181613e97565b60008060008060008060c0878903121561401c57600080fd5b863595506020870135945060408701359350606087013561403c81613d74565b9250608087013567ffffffffffffffff8082111561405957600080fd5b6140658a838b01613e23565b935060a089013591508082111561407b57600080fd5b5061408889828a01613e23565b9150509295509295509295565b6020808252601f908201527f416d6f756e742073686f756c642062652067726561746f72207468616e203000604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156140fc576140fc6140cc565b500290565b60008261411e57634e487b7160e01b600052601260045260246000fd5b500490565b600082821015614135576141356140cc565b500390565b6020808252601a908201527f496e73756666696369656e742072657761726420746f6b656e73000000000000604082015260600190565b60008219821115614184576141846140cc565b500190565b602080825260139082015272496e76616c6964206465706f7369742066656560681b604082015260600190565b602080825260149082015273496e76616c69642077697468647261772066656560601b604082015260600190565b6000602082840312156141f657600080fd5b815160ff81168114613db157600080fd5b60208082526016908201527504d75737420626520696e666572696f7220746f2033360541b604082015260600190565b600181815b80851115614272578160001904821115614258576142586140cc565b8085161561426557918102915b93841c939080029061423c565b509250929050565b600082614289575060016139ce565b81614296575060006139ce565b81600181146142ac57600281146142b6576142d2565b60019150506139ce565b60ff8411156142c7576142c76140cc565b50506001821b6139ce565b5060208310610133831016604e8410600b84101617156142f5575081810a6139ce565b6142ff8383614237565b8060001904821115614313576143136140cc565b029392505050565b6000613db1838361427a565b60006020828403121561433957600080fd5b5051919050565b6001600160a01b03929092168252602082015260400190565b6020808252600e908201526d4e6f207265666c656374696f6e7360901b604082015260600190565b60006020828403121561439357600080fd5b8151613db181613d74565b602080825260179082015276155cd95c88185b5bdd5b9d0818589bdd99481b1a5b5a5d604a1b604082015260600190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b60006020828403121561440a57600080fd5b8151613db181613e97565b6020808252600e908201526d1a5b9d985b1a5908185b5bdd5b9d60921b604082015260600190565b600081518084526020808501945080840160005b838110156144765781516001600160a01b031687529582019590820190600101614451565b509495945050505050565b86815285602082015284604082015260018060a01b038416606082015260c0608082015260006144b460c083018561443d565b82810360a08401526144c6818561443d565b9998505050505050505050565b828152604060208201526000613056604083018461443d565b600060208083850312156144ff57600080fd5b825167ffffffffffffffff81111561451657600080fd5b8301601f8101851361452757600080fd5b8051614535613e4482613dff565b81815260059190911b8201830190838101908783111561455457600080fd5b928401925b82841015613c2457835182529284019290840190614559565b634e487b7160e01b600052603260045260246000fd5b85815284602082015260a0604082015260006145a760a083018661443d565b6001600160a01b0394909416606083015250608001529392505050565b60005b838110156145df5781810151838201526020016145c7565b8381111561398d5750506000910152565b600082516146028184602087016145c4565b9190910192915050565b602081526000825180602084015261462b8160408501602087016145c4565b601f01601f1916919091016040019291505056fee1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109ca2646970667358221220a7940b66c263a113f921847e7fc0d140ed65337736ef5a2dd96e38b838cf9a0f64736f6c634300080e0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BSC | 100.00% | $685.01 | 0.00356 | $2.44 |
Loading...
Loading
[ Download: CSV Export ]
[ 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.