Source Code
Latest 25 from a total of 463 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw | 19237521 | 740 days ago | IN | 0.00089 ETH | 0.01239161 | ||||
| Withdraw | 19237512 | 740 days ago | IN | 0.00089 ETH | 0.01314014 | ||||
| Withdraw | 17805980 | 941 days ago | IN | 0.00089 ETH | 0.0062914 | ||||
| Withdraw | 17599040 | 970 days ago | IN | 0.00089 ETH | 0.00508086 | ||||
| Withdraw | 17554751 | 976 days ago | IN | 0.00089 ETH | 0.00471547 | ||||
| Compound Reward | 17554749 | 976 days ago | IN | 0.00089 ETH | 0.00235668 | ||||
| Withdraw | 17554744 | 976 days ago | IN | 0.00089 ETH | 0.00508076 | ||||
| Compound Reward | 17554739 | 976 days ago | IN | 0.00089 ETH | 0.00234211 | ||||
| Compound Reward | 17554093 | 976 days ago | IN | 0.00089 ETH | 0.00241239 | ||||
| Withdraw | 17503614 | 983 days ago | IN | 0.00089 ETH | 0.00523113 | ||||
| Withdraw | 17497091 | 984 days ago | IN | 0.00089 ETH | 0.00540291 | ||||
| Withdraw | 17497050 | 984 days ago | IN | 0.00089 ETH | 0.00704964 | ||||
| Compound Reward | 17497044 | 984 days ago | IN | 0.00089 ETH | 0.0032215 | ||||
| Compound Reward | 17475802 | 987 days ago | IN | 0.00089 ETH | 0.0031752 | ||||
| Deposit | 17274969 | 1015 days ago | IN | 0.00089 ETH | 0.02870237 | ||||
| Withdraw | 17115884 | 1038 days ago | IN | 0.00089 ETH | 0.01573238 | ||||
| Withdraw | 17110475 | 1039 days ago | IN | 0.00089 ETH | 0.01886148 | ||||
| Withdraw | 17075673 | 1043 days ago | IN | 0.00089 ETH | 0.03079418 | ||||
| Withdraw | 17044781 | 1048 days ago | IN | 0.00089 ETH | 0.01221896 | ||||
| Deposit | 17035228 | 1049 days ago | IN | 0.00089 ETH | 0.01238903 | ||||
| Withdraw | 17020459 | 1051 days ago | IN | 0.00089 ETH | 0.01163229 | ||||
| Withdraw | 16978851 | 1057 days ago | IN | 0.00089 ETH | 0.01090184 | ||||
| Withdraw | 16965353 | 1059 days ago | IN | 0.00089 ETH | 0.0107131 | ||||
| Deposit | 16965309 | 1059 days ago | IN | 0.00089 ETH | 0.00792091 | ||||
| Withdraw | 16965306 | 1059 days ago | IN | 0.00089 ETH | 0.00817074 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 19237521 | 740 days ago | 0.00089 ETH | ||||
| Transfer | 19237512 | 740 days ago | 0.00089 ETH | ||||
| Transfer | 17805980 | 941 days ago | 0.00089 ETH | ||||
| Transfer | 17599040 | 970 days ago | 0.00089 ETH | ||||
| Transfer | 17554751 | 976 days ago | 0.00089 ETH | ||||
| Transfer | 17554749 | 976 days ago | 0.00089 ETH | ||||
| Transfer | 17554744 | 976 days ago | 0.00089 ETH | ||||
| Transfer | 17554739 | 976 days ago | 0.00089 ETH | ||||
| Transfer | 17554093 | 976 days ago | 0.00089 ETH | ||||
| Transfer | 17503614 | 983 days ago | 0.00089 ETH | ||||
| Transfer | 17497091 | 984 days ago | 0.00089 ETH | ||||
| Transfer | 17497050 | 984 days ago | 0.00089 ETH | ||||
| Transfer | 17497044 | 984 days ago | 0.00089 ETH | ||||
| Transfer | 17475802 | 987 days ago | 0.00089 ETH | ||||
| Transfer | 17274969 | 1015 days ago | 0.00089 ETH | ||||
| Transfer | 17115884 | 1038 days ago | 0.00089 ETH | ||||
| Transfer | 17110475 | 1039 days ago | 0.00089 ETH | ||||
| Transfer | 17075673 | 1043 days ago | 0.00089 ETH | ||||
| Transfer | 17044781 | 1048 days ago | 0.00089 ETH | ||||
| Transfer | 17035228 | 1049 days ago | 0.00089 ETH | ||||
| Transfer | 17020459 | 1051 days ago | 0.00089 ETH | ||||
| Transfer | 16978851 | 1057 days ago | 0.00089 ETH | ||||
| Transfer | 16965353 | 1059 days ago | 0.00089 ETH | ||||
| Transfer | 16965309 | 1059 days ago | 0.00089 ETH | ||||
| Transfer | 16965306 | 1059 days ago | 0.00089 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
BrewlabsLockup
Compiler Version
v0.8.4+commit.c7e474f2
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 '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '@openzeppelin/contracts/access/Ownable.sol';
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "./libs/IUniRouter02.sol";
import "./libs/IWETH.sol";
interface IToken {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the token decimals.
*/
function decimals() external view returns (uint8);
/**
* @dev Returns the token symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the token name.
*/
function name() external view returns (string memory);
}
contract BrewlabsLockup is Ownable, ReentrancyGuard {
using SafeERC20 for IERC20;
// 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;
// The block number when staking starts.
uint256 public startBlock;
// The block number when staking ends.
uint256 public bonusEndBlock;
// swap router and path, slipPage
uint256 public slippageFactor = 800; // 20% default slippage tolerance
uint256 public constant slippageFactorUL = 995;
address public uniRouterAddress;
address[] public reflectionToStakedPath;
address[] public earnedToStakedPath;
address public walletA;
address public buyBackWallet = 0xE1f1dd010BBC2860F81c8F90Ea4E38dB949BB16F;
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;
// Accrued token per share
uint256 public accDividendPerShare;
uint256 public totalStaked;
uint256 private totalEarned;
uint256 private totalReflections;
uint256 private reflections;
uint256 private paidRewards;
uint256 private shouldTotalPaid;
struct Lockup {
uint8 stakeType;
uint256 duration;
uint256 depositFee;
uint256 withdrawFee;
uint256 rate;
uint256 accTokenPerShare;
uint256 lastRewardBlock;
uint256 totalStaked;
uint256 totalStakedLimit;
}
struct UserInfo {
uint256 amount; // How many staked tokens the user has provided
uint256 locked;
uint256 available;
}
struct Stake {
uint8 stakeType;
uint256 amount; // amount to stake
uint256 duration; // the lockup duration of the stake
uint256 end; // when does the staking period end
uint256 rewardDebt; // Reward debt
uint256 reflectionDebt; // Reflection debt
}
uint256 constant MAX_STAKES = 256;
Lockup[] public lockups;
mapping(address => Stake[]) public userStakes;
mapping(address => UserInfo) public userStaked;
event Deposit(address indexed user, uint256 stakeType, uint256 amount);
event Withdraw(address indexed user, uint256 stakeType, uint256 amount);
event EmergencyWithdraw(address indexed user, uint256 amount);
event AdminTokenRecovered(address tokenRecovered, uint256 amount);
event NewStartAndEndBlocks(uint256 startBlock, uint256 endBlock);
event LockupUpdated(uint8 _type, uint256 _duration, uint256 _fee0, uint256 _fee1, uint256 _rate);
event RewardsStop(uint256 blockNumber);
event EndBlockUpdated(uint256 blockNumber);
event UpdatePoolLimit(uint256 poolLimitPerUser, bool hasLimit);
event ServiceInfoUpadted(address _addr, uint256 _fee);
event DurationUpdated(uint256 _duration);
event SetSettings(
uint256 _slippageFactor,
address _uniRouter,
address[] _path0,
address[] _path1,
address _walletA
);
constructor() {}
/*
* @notice Initialize the contract
* @param _stakingToken: staked token address
* @param _earnedToken: earned token address
* @param _dividendToken: reflection token address
* @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)
*/
function initialize(
IERC20 _stakingToken,
IERC20 _earnedToken,
address _dividendToken,
address _uniRouter,
address[] memory _earnedToStakedPath,
address[] memory _reflectionToStakedPath
) external onlyOwner {
require(!isInitialized, "Already initialized");
// Make this contract initialized
isInitialized = true;
stakingToken = _stakingToken;
earnedToken = _earnedToken;
dividendToken = _dividendToken;
walletA = msg.sender;
uint256 decimalsRewardToken = uint256(IToken(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(IToken(address(dividendToken)).decimals());
require(decimalsdividendToken < 30, "Must be inferior to 30");
}
PRECISION_FACTOR_REFLECTION = uint256(10**(40 - decimalsRewardToken));
uniRouterAddress = _uniRouter;
earnedToStakedPath = _earnedToStakedPath;
reflectionToStakedPath = _reflectionToStakedPath;
}
/*
* @notice Deposit staked tokens and collect reward tokens (if any)
* @param _amount: amount to withdraw (in earnedToken)
*/
function deposit(uint256 _amount, uint8 _stakeType) external payable nonReentrant {
require(startBlock > 0 && startBlock < block.number, "Staking hasn't started yet");
require(_amount > 0, "Amount should be greator than 0");
require(_stakeType < lockups.length, "Invalid stake type");
_transferPerformanceFee();
_updatePool(_stakeType);
UserInfo storage user = userStaked[msg.sender];
Stake[] storage stakes = userStakes[msg.sender];
Lockup storage lockup = lockups[_stakeType];
if(lockup.totalStakedLimit > 0) {
require(lockup.totalStaked < lockup.totalStakedLimit, "Total staked limit exceeded");
if(lockup.totalStaked + _amount > lockup.totalStakedLimit) {
_amount = lockup.totalStakedLimit - lockup.totalStaked;
}
}
uint256 pending = 0;
uint256 pendingReflection = 0;
for(uint256 j = 0; j < stakes.length; j++) {
Stake storage stake = stakes[j];
if(stake.stakeType != _stakeType) continue;
if(stake.amount == 0) continue;
pendingReflection = pendingReflection + (
stake.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION - stake.reflectionDebt
);
uint256 _pending = stake.amount * lockup.accTokenPerShare / PRECISION_FACTOR - stake.rewardDebt;
pending = pending + _pending;
stake.rewardDebt = stake.amount * lockup.accTokenPerShare / PRECISION_FACTOR;
stake.reflectionDebt = stake.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION;
}
if (pending > 0) {
require(availableRewardTokens() >= pending, "Insufficient reward tokens");
earnedToken.safeTransfer(address(msg.sender), pending);
_updateEarned(pending);
paidRewards = paidRewards + pending;
}
pendingReflection = estimateDividendAmount(pendingReflection);
if (pendingReflection > 0) {
_transferToken(dividendToken, msg.sender, 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 (hasUserLimit) {
require(
realAmount + user.amount <= poolLimitPerUser,
"User amount above limit"
);
}
if (lockup.depositFee > 0) {
uint256 fee = realAmount * lockup.depositFee / 10000;
if (fee > 0) {
stakingToken.safeTransfer(walletA, fee);
realAmount = realAmount - fee;
}
}
_addStake(_stakeType, msg.sender, lockup.duration, realAmount);
user.amount = user.amount + realAmount;
lockup.totalStaked = lockup.totalStaked + realAmount;
totalStaked = totalStaked + realAmount;
emit Deposit(msg.sender, _stakeType, realAmount);
}
function _addStake(uint8 _stakeType, address _account, uint256 _duration, uint256 _amount) internal {
Stake[] storage stakes = userStakes[_account];
uint256 end = block.timestamp + _duration * 1 days;
uint256 i = stakes.length;
require(i < MAX_STAKES, "Max stakes");
stakes.push(); // grow the array
// find the spot where we can insert the current stake
// this should make an increasing list sorted by end
while (i != 0 && stakes[i - 1].end > end) {
// shift it back one
stakes[i] = stakes[i - 1];
i -= 1;
}
Lockup storage lockup = lockups[_stakeType];
// insert the stake
Stake storage newStake = stakes[i];
newStake.stakeType = _stakeType;
newStake.duration = _duration;
newStake.end = end;
newStake.amount = _amount;
newStake.rewardDebt = newStake.amount * lockup.accTokenPerShare / PRECISION_FACTOR;
newStake.reflectionDebt = newStake.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION;
}
/*
* @notice Withdraw staked tokens and collect reward tokens
* @param _amount: amount to withdraw (in earnedToken)
*/
function withdraw(uint256 _amount, uint8 _stakeType) external payable nonReentrant {
require(_amount > 0, "Amount should be greator than 0");
require(_stakeType < lockups.length, "Invalid stake type");
_transferPerformanceFee();
_updatePool(_stakeType);
UserInfo storage user = userStaked[msg.sender];
Stake[] storage stakes = userStakes[msg.sender];
Lockup storage lockup = lockups[_stakeType];
uint256 pending = 0;
uint256 pendingReflection = 0;
uint256 remained = _amount;
for(uint256 j = 0; j < stakes.length; j++) {
Stake storage stake = stakes[j];
if(stake.stakeType != _stakeType) continue;
if(stake.amount == 0) continue;
if(remained == 0) break;
uint256 _pending = stake.amount * lockup.accTokenPerShare / PRECISION_FACTOR - stake.rewardDebt;
pendingReflection = pendingReflection + (
stake.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION - stake.reflectionDebt
);
pending = pending + _pending;
if(stake.end < block.timestamp || bonusEndBlock < block.number) {
if(stake.amount > remained) {
stake.amount = stake.amount - remained;
remained = 0;
} else {
remained = remained - stake.amount;
stake.amount = 0;
}
}
stake.rewardDebt = stake.amount * lockup.accTokenPerShare / PRECISION_FACTOR;
stake.reflectionDebt = stake.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION;
}
if (pending > 0) {
require(availableRewardTokens() >= pending, "Insufficient reward tokens");
earnedToken.safeTransfer(address(msg.sender), pending);
_updateEarned(pending);
paidRewards = paidRewards + pending;
}
if (pendingReflection > 0) {
pendingReflection = estimateDividendAmount(pendingReflection);
_transferToken(dividendToken, msg.sender, pendingReflection);
totalReflections = totalReflections - pendingReflection;
}
uint256 realAmount = _amount - remained;
user.amount = user.amount - realAmount;
lockup.totalStaked = lockup.totalStaked - realAmount;
totalStaked = totalStaked - realAmount;
if(realAmount > 0) {
if (lockup.withdrawFee > 0) {
uint256 fee = realAmount * lockup.withdrawFee / 10000;
stakingToken.safeTransfer(walletA, fee);
realAmount = realAmount - fee;
}
stakingToken.safeTransfer(address(msg.sender), realAmount);
}
emit Withdraw(msg.sender, _stakeType, realAmount);
}
function claimReward(uint8 _stakeType) external payable nonReentrant {
if(_stakeType >= lockups.length) return;
if(startBlock == 0) return;
_transferPerformanceFee();
_updatePool(_stakeType);
Stake[] storage stakes = userStakes[msg.sender];
Lockup storage lockup = lockups[_stakeType];
uint256 pending = 0;
for(uint256 j = 0; j < stakes.length; j++) {
Stake storage stake = stakes[j];
if(stake.stakeType != _stakeType) continue;
if(stake.amount == 0) continue;
uint256 _pending = stake.amount * lockup.accTokenPerShare / PRECISION_FACTOR - stake.rewardDebt;
pending = pending + _pending;
stake.rewardDebt = stake.amount * lockup.accTokenPerShare / PRECISION_FACTOR;
}
if (pending > 0) {
require(availableRewardTokens() >= pending, "Insufficient reward tokens");
earnedToken.safeTransfer(address(msg.sender), pending);
_updateEarned(pending);
paidRewards = paidRewards + pending;
}
}
function claimDividend(uint8 _stakeType) external payable nonReentrant {
if(_stakeType >= lockups.length) return;
if(startBlock == 0) return;
_transferPerformanceFee();
_updatePool(_stakeType);
Stake[] storage stakes = userStakes[msg.sender];
uint256 pendingReflection = 0;
for(uint256 j = 0; j < stakes.length; j++) {
Stake storage stake = stakes[j];
if(stake.stakeType != _stakeType) continue;
if(stake.amount == 0) continue;
pendingReflection = pendingReflection + (
stake.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION - stake.reflectionDebt
);
stake.reflectionDebt = stake.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION;
}
pendingReflection = estimateDividendAmount(pendingReflection);
if (pendingReflection > 0) {
_transferToken(dividendToken, msg.sender, pendingReflection);
totalReflections = totalReflections - pendingReflection;
}
}
function compoundReward(uint8 _stakeType) external payable nonReentrant {
if(_stakeType >= lockups.length) return;
if(startBlock == 0) return;
_transferPerformanceFee();
_updatePool(_stakeType);
UserInfo storage user = userStaked[msg.sender];
Stake[] storage stakes = userStakes[msg.sender];
Lockup storage lockup = lockups[_stakeType];
uint256 pending = 0;
uint256 compounded = 0;
for(uint256 j = 0; j < stakes.length; j++) {
Stake storage stake = stakes[j];
if(stake.stakeType != _stakeType) continue;
if(stake.amount == 0) continue;
uint256 _pending = stake.amount * lockup.accTokenPerShare / PRECISION_FACTOR - stake.rewardDebt;
pending = pending + _pending;
if(address(stakingToken) != address(earnedToken) && _pending > 0) {
uint256 _beforeAmount = stakingToken.balanceOf(address(this));
_safeSwap(_pending, earnedToStakedPath, address(this));
uint256 _afterAmount = stakingToken.balanceOf(address(this));
_pending = _afterAmount - _beforeAmount;
}
compounded = compounded + _pending;
stake.amount = stake.amount + _pending;
stake.rewardDebt = stake.amount * lockup.accTokenPerShare / PRECISION_FACTOR;
stake.reflectionDebt = stake.reflectionDebt + _pending * accDividendPerShare / PRECISION_FACTOR_REFLECTION;
}
if (pending > 0) {
require(availableRewardTokens() >= pending, "Insufficient reward tokens");
_updateEarned(pending);
paidRewards = paidRewards + pending;
user.amount = user.amount + compounded;
lockup.totalStaked = lockup.totalStaked + compounded;
totalStaked = totalStaked + compounded;
emit Deposit(msg.sender, _stakeType, compounded);
}
}
function compoundDividend(uint8 _stakeType) external payable nonReentrant {
if(_stakeType >= lockups.length) return;
if(startBlock == 0) return;
_transferPerformanceFee();
_updatePool(_stakeType);
UserInfo storage user = userStaked[msg.sender];
Stake[] storage stakes = userStakes[msg.sender];
Lockup storage lockup = lockups[_stakeType];
uint256 compounded = 0;
for(uint256 j = 0; j < stakes.length; j++) {
Stake storage stake = stakes[j];
if(stake.stakeType != _stakeType) continue;
if(stake.amount == 0) continue;
uint256 _pending = stake.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION - stake.reflectionDebt;
_pending = estimateDividendAmount(_pending);
totalReflections = totalReflections - _pending;
if(address(stakingToken) != address(dividendToken) && _pending > 0) {
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;
}
compounded = compounded + _pending;
stake.amount = stake.amount + _pending;
stake.rewardDebt = stake.rewardDebt + _pending * lockup.accTokenPerShare / PRECISION_FACTOR;
stake.reflectionDebt = stake.amount * accDividendPerShare / PRECISION_FACTOR_REFLECTION;
}
if (compounded > 0) {
user.amount = user.amount + compounded;
lockup.totalStaked = lockup.totalStaked + compounded;
totalStaked = totalStaked + compounded;
emit Deposit(msg.sender, _stakeType, compounded);
}
}
function _transferPerformanceFee() internal {
require(msg.value >= performanceFee, 'should pay small gas to compound or harvest');
payable(buyBackWallet).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(uint8 _stakeType) external nonReentrant {
if(_stakeType >= lockups.length) return;
UserInfo storage user = userStaked[msg.sender];
Stake[] storage stakes = userStakes[msg.sender];
Lockup storage lockup = lockups[_stakeType];
uint256 amountToTransfer = 0;
for(uint256 j = 0; j < stakes.length; j++) {
Stake storage stake = stakes[j];
if(stake.stakeType != _stakeType) continue;
if(stake.amount == 0) continue;
amountToTransfer = amountToTransfer + stake.amount;
stake.amount = 0;
stake.rewardDebt = 0;
stake.reflectionDebt = 0;
}
if (amountToTransfer > 0) {
stakingToken.safeTransfer(address(msg.sender), amountToTransfer);
user.amount = user.amount - amountToTransfer;
lockup.totalStaked = lockup.totalStaked - amountToTransfer;
totalStaked = totalStaked - amountToTransfer;
}
emit EmergencyWithdraw(msg.sender, amountToTransfer);
}
function rewardPerBlock(uint8 _stakeType) external view returns (uint256) {
if(_stakeType >= lockups.length) return 0;
return lockups[_stakeType].rate;
}
/**
* @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;
for(uint i = 0; i < lockups.length; i++) {
if(startBlock == 0) {
adjustedShouldTotalPaid = adjustedShouldTotalPaid + lockups[i].rate * duration * 6426;
} else {
uint256 remainBlocks = _getMultiplier(lockups[i].lastRewardBlock, bonusEndBlock);
adjustedShouldTotalPaid = adjustedShouldTotalPaid + lockups[i].rate * remainBlocks;
}
}
if(remainRewards >= adjustedShouldTotalPaid) return 0;
return adjustedShouldTotalPaid - remainRewards;
}
function userInfo(uint8 _stakeType, address _account) external view returns (uint256 amount, uint256 available, uint256 locked) {
Stake[] memory stakes = userStakes[_account];
for(uint256 i = 0; i < stakes.length; i++) {
Stake memory stake = stakes[i];
if(stake.stakeType != _stakeType) continue;
if(stake.amount == 0) continue;
amount = amount + stake.amount;
if(block.timestamp > stake.end || bonusEndBlock < block.number) {
available = available + stake.amount;
} else {
locked = locked + stake.amount;
}
}
}
/*
* @notice View function to see pending reward on frontend.
* @param _user: user address
* @return Pending reward for a given user
*/
function pendingReward(address _account, uint8 _stakeType) external view returns (uint256) {
if(_stakeType >= lockups.length || startBlock == 0) return 0;
Stake[] memory stakes = userStakes[_account];
Lockup memory lockup = lockups[_stakeType];
if(lockup.totalStaked == 0) return 0;
uint256 adjustedTokenPerShare = lockup.accTokenPerShare;
if (block.number > lockup.lastRewardBlock && lockup.totalStaked != 0 && lockup.lastRewardBlock > 0) {
uint256 multiplier = _getMultiplier(lockup.lastRewardBlock, block.number);
uint256 reward = multiplier * lockup.rate;
adjustedTokenPerShare = lockup.accTokenPerShare + reward * PRECISION_FACTOR / lockup.totalStaked;
}
uint256 pending = 0;
for(uint256 i = 0; i < stakes.length; i++) {
Stake memory stake = stakes[i];
if(stake.stakeType != _stakeType) continue;
if(stake.amount == 0) continue;
pending = pending + (
stake.amount * adjustedTokenPerShare / PRECISION_FACTOR - stake.rewardDebt
);
}
return pending;
}
function pendingDividends(address _account, uint8 _stakeType) external view returns (uint256) {
if(_stakeType >= lockups.length) return 0;
if(startBlock == 0 || totalStaked == 0) return 0;
Stake[] memory stakes = userStakes[_account];
uint256 reflectionAmount = availableDividendTokens();
if(reflectionAmount < totalReflections) {
reflectionAmount = totalReflections;
}
uint256 sTokenBal = totalStaked;
uint256 eTokenBal = availableRewardTokens();
if(address(stakingToken) == address(earnedToken)) {
sTokenBal = sTokenBal + eTokenBal;
}
uint256 adjustedReflectionPerShare = accDividendPerShare + (
(reflectionAmount - totalReflections) * PRECISION_FACTOR_REFLECTION / sTokenBal
);
uint256 pendingReflection = 0;
for(uint256 i = 0; i < stakes.length; i++) {
Stake memory stake = stakes[i];
if(stake.stakeType != _stakeType) continue;
if(stake.amount == 0) continue;
pendingReflection = pendingReflection + (
stake.amount * adjustedReflectionPerShare / PRECISION_FACTOR_REFLECTION - stake.reflectionDebt
);
}
return pendingReflection;
}
/************************
** Admin Methods
*************************/
function harvest() external onlyOwner {
_updatePool(0);
reflections = estimateDividendAmount(reflections);
if(reflections > 0) {
_transferToken(dividendToken, walletA, 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(uint _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(uint8 _stakeType, 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(_stakeType);
uint256 beforeAmt = earnedToken.balanceOf(address(this));
earnedToken.safeTransferFrom(msg.sender, address(this), _amount);
uint256 afterAmt = earnedToken.balanceOf(address(this));
totalEarned = totalEarned + afterAmt - beforeAmt;
uint256 remainRewards = availableRewardTokens() + paidRewards;
uint256 adjustedShouldTotalPaid = shouldTotalPaid;
for(uint i = 0; i < lockups.length; i++) {
if(i == _stakeType) continue;
if(startBlock == 0) {
adjustedShouldTotalPaid = adjustedShouldTotalPaid + lockups[i].rate * duration * 6426;
} else {
uint256 remainBlocks = _getMultiplier(lockups[i].lastRewardBlock, bonusEndBlock);
adjustedShouldTotalPaid = adjustedShouldTotalPaid + lockups[i].rate * remainBlocks;
}
}
if(remainRewards > shouldTotalPaid) {
remainRewards = remainRewards - adjustedShouldTotalPaid;
uint256 remainBlocks = bonusEndBlock - block.number;
lockups[_stakeType].rate = remainRewards / remainBlocks;
emit LockupUpdated(_stakeType, lockups[_stakeType].duration, lockups[_stakeType].depositFee, lockups[_stakeType].withdrawFee, lockups[_stakeType].rate);
}
}
/*
* @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");
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),
"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 * 6426;
for(uint256 i = 0; i < lockups.length; i++) {
lockups[i].lastRewardBlock = startBlock;
}
emit NewStartAndEndBlocks(startBlock, bonusEndBlock);
}
function stopReward() external onlyOwner {
for(uint8 i = 0; i < lockups.length; i++) {
_updatePool(i);
}
uint256 remainRewards = availableRewardTokens() + paidRewards;
if(remainRewards > shouldTotalPaid) {
remainRewards = remainRewards - shouldTotalPaid;
earnedToken.transfer(msg.sender, remainRewards);
_updateEarned(remainRewards);
}
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);
}
function updateLockup(uint8 _stakeType, uint256 _duration, uint256 _depositFee, uint256 _withdrawFee, uint256 _rate, uint256 _totalStakedLimit) external onlyOwner {
// require(block.number < startBlock, "Pool was already started");
require(_stakeType < lockups.length, "Lockup Not found");
require(_depositFee < 2000, "Invalid deposit fee");
require(_withdrawFee < 2000, "Invalid withdraw fee");
_updatePool(_stakeType);
Lockup storage _lockup = lockups[_stakeType];
_lockup.duration = _duration;
_lockup.depositFee = _depositFee;
_lockup.withdrawFee = _withdrawFee;
_lockup.rate = _rate;
_lockup.totalStakedLimit = _totalStakedLimit;
emit LockupUpdated(_stakeType, _duration, _depositFee, _withdrawFee, _rate);
}
function addLockup(uint256 _duration, uint256 _depositFee, uint256 _withdrawFee, uint256 _rate, uint256 _totalStakedLimit) external onlyOwner {
require(_depositFee < 2000, "Invalid deposit fee");
require(_withdrawFee < 2000, "Invalid withdraw fee");
lockups.push();
Lockup storage _lockup = lockups[lockups.length - 1];
_lockup.duration = _duration;
_lockup.depositFee = _depositFee;
_lockup.withdrawFee = _withdrawFee;
_lockup.rate = _rate;
_lockup.lastRewardBlock = block.number;
_lockup.totalStakedLimit = _totalStakedLimit;
emit LockupUpdated(uint8(lockups.length - 1), _duration, _depositFee, _withdrawFee, _rate);
}
function setServiceInfo(address _addr, uint256 _fee) external {
require(msg.sender == buyBackWallet, "setServiceInfo: FORBIDDEN");
require(_addr != address(0x0), "Invalid address");
require(_fee < 0.05 ether, "fee cannot exceed 0.05 ether");
buyBackWallet = _addr;
performanceFee = _fee;
emit ServiceInfoUpadted(_addr, _fee);
}
function setDuration(uint256 _duration) external onlyOwner {
require(startBlock == 0, "Pool was already started");
require(_duration >= 30, "lower limit reached");
duration = _duration;
emit DurationUpdated(_duration);
}
function setSettings(
uint256 _slippageFactor,
address _uniRouter,
address[] memory _earnedToStakedPath,
address[] memory _reflectionToStakedPath,
address _feeAddr
) external onlyOwner {
require(_slippageFactor <= slippageFactorUL, "_slippageFactor too high");
require(_feeAddr != address(0x0), "Invalid Address");
slippageFactor = _slippageFactor;
uniRouterAddress = _uniRouter;
reflectionToStakedPath = _reflectionToStakedPath;
earnedToStakedPath = _earnedToStakedPath;
walletA = _feeAddr;
emit SetSettings(_slippageFactor, _uniRouter, _earnedToStakedPath, _reflectionToStakedPath, _feeAddr);
}
/************************
** Internal Methods
*************************/
/*
* @notice Update reward variables of the given pool to be up-to-date.
*/
function _updatePool(uint8 _stakeType) internal {
// calc reflection rate
if(totalStaked > 0) {
uint256 reflectionAmount = availableDividendTokens();
if(reflectionAmount < totalReflections) {
reflectionAmount = totalReflections;
}
uint256 sTokenBal = totalStaked;
uint256 eTokenBal = availableRewardTokens();
if(address(stakingToken) == address(earnedToken)) {
sTokenBal = sTokenBal + eTokenBal;
}
accDividendPerShare = accDividendPerShare + (
(reflectionAmount - totalReflections) * PRECISION_FACTOR_REFLECTION / sTokenBal
);
if(address(stakingToken) == address(earnedToken)) {
reflections = reflections + (reflectionAmount - totalReflections) * eTokenBal / sTokenBal;
}
totalReflections = reflectionAmount;
}
Lockup storage lockup = lockups[_stakeType];
if (block.number <= lockup.lastRewardBlock || lockup.lastRewardBlock == 0) return;
if (lockup.totalStaked == 0) {
lockup.lastRewardBlock = block.number;
return;
}
uint256 multiplier = _getMultiplier(lockup.lastRewardBlock, block.number);
uint256 _reward = multiplier * lockup.rate;
lockup.accTokenPerShare = lockup.accTokenPerShare + (
_reward * PRECISION_FACTOR / lockup.totalStaked
);
lockup.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 _transferToken(address _token, address _to, uint256 _amount) internal {
if(_token == address(0x0)) {
payable(_to).transfer(_amount);
} else {
IERC20(_token).transfer(_to, _amount);
}
}
function _updateEarned(uint256 _amount) internal {
if(totalEarned > _amount) {
totalEarned = totalEarned - _amount;
} else {
totalEarned = 0;
}
}
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 / 1000,
_path,
_to,
block.timestamp + 600
);
}
receive() external payable {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _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 v4.4.1 (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() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.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, uint value) external returns (bool);
function withdraw(uint) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason 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 {
// 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
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);
}{
"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
Contract ABI
API[{"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":"stakeType","type":"uint256"},{"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":"uint8","name":"_type","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"_duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_fee0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_fee1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_rate","type":"uint256"}],"name":"LockupUpdated","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":"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[]"},{"indexed":false,"internalType":"address","name":"_walletA","type":"address"}],"name":"SetSettings","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":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"stakeType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"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":[{"internalType":"uint256","name":"_duration","type":"uint256"},{"internalType":"uint256","name":"_depositFee","type":"uint256"},{"internalType":"uint256","name":"_withdrawFee","type":"uint256"},{"internalType":"uint256","name":"_rate","type":"uint256"},{"internalType":"uint256","name":"_totalStakedLimit","type":"uint256"}],"name":"addLockup","outputs":[],"stateMutability":"nonpayable","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":"buyBackWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_stakeType","type":"uint8"}],"name":"claimDividend","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_stakeType","type":"uint8"}],"name":"claimReward","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_stakeType","type":"uint8"}],"name":"compoundDividend","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_stakeType","type":"uint8"}],"name":"compoundReward","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint8","name":"_stakeType","type":"uint8"}],"name":"deposit","outputs":[],"stateMutability":"payable","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":[{"internalType":"uint8","name":"_stakeType","type":"uint8"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hasUserLimit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_stakeType","type":"uint8"},{"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":"address","name":"_uniRouter","type":"address"},{"internalType":"address[]","name":"_earnedToStakedPath","type":"address[]"},{"internalType":"address[]","name":"_reflectionToStakedPath","type":"address[]"}],"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":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lockups","outputs":[{"internalType":"uint8","name":"stakeType","type":"uint8"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"depositFee","type":"uint256"},{"internalType":"uint256","name":"withdrawFee","type":"uint256"},{"internalType":"uint256","name":"rate","type":"uint256"},{"internalType":"uint256","name":"accTokenPerShare","type":"uint256"},{"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"internalType":"uint256","name":"totalStaked","type":"uint256"},{"internalType":"uint256","name":"totalStakedLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint8","name":"_stakeType","type":"uint8"}],"name":"pendingDividends","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint8","name":"_stakeType","type":"uint8"}],"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":[{"internalType":"uint8","name":"_stakeType","type":"uint8"}],"name":"rewardPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"setDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setServiceInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_slippageFactor","type":"uint256"},{"internalType":"address","name":"_uniRouter","type":"address"},{"internalType":"address[]","name":"_earnedToStakedPath","type":"address[]"},{"internalType":"address[]","name":"_reflectionToStakedPath","type":"address[]"},{"internalType":"address","name":"_feeAddr","type":"address"}],"name":"setSettings","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":"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":"uint8","name":"_stakeType","type":"uint8"},{"internalType":"uint256","name":"_duration","type":"uint256"},{"internalType":"uint256","name":"_depositFee","type":"uint256"},{"internalType":"uint256","name":"_withdrawFee","type":"uint256"},{"internalType":"uint256","name":"_rate","type":"uint256"},{"internalType":"uint256","name":"_totalStakedLimit","type":"uint256"}],"name":"updateLockup","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":"uint8","name":"_stakeType","type":"uint8"},{"internalType":"address","name":"_account","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"locked","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userStaked","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"locked","type":"uint256"},{"internalType":"uint256","name":"available","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userStakes","outputs":[{"internalType":"uint8","name":"stakeType","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"end","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":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint8","name":"_stakeType","type":"uint8"}],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405261016d600355610320600855600d80546001600160a01b03191673e1f1dd010bbc2860f81c8f90ea4e38db949bb16f1790556603297345d9a000600e553480156200004e57600080fd5b506200005a3362000064565b60018055620000b4565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b615cb580620000c46000396000f3fe6080604052600436106102ee5760003560e01c806376fa17d211610186578063a0b40905116100d7578063e7a2fed711610085578063e7a2fed7146108f1578063f2fde38b14610911578063f3aeb31d14610931578063f6be71d114610946578063f8920ee714610966578063fbe32b3514610986578063ffbd3b1f146109a657600080fd5b8063a0b40905146107d8578063acc3a939146107f8578063b5d5b5fa14610834578063b74cd24214610885578063b77e7da01461089b578063c1e22a65146108bb578063ccd34cd5146108db57600080fd5b80638bdf67f2116101345780638bdf67f2146106e35780638da5cb5b146107035780638e6f4fb714610718578063903d42961461078057806392b46e5b1461079357806392e8990e146107a95780639f94e272146107c357600080fd5b806376fa17d21461061e57806378d57eea1461065957806380dc06721461066c578063817b1cd21461068157806381b619481461069757806387788782146106b757806388bbb0c1146106cd57600080fd5b806348cd4cb111610240578063689f1623116101ee578063689f162314610561578063693a090b146105745780636becd657146105945780636e707b73146105b4578063715018a6146105d457806372f702f3146105e9578063746c8ae11461060957600080fd5b806348cd4cb1146104ad578063515bbf2c146104c357806353314fae146104e3578063595e173a146105035780635dde4a9114610523578063654cfdff1461053857806366fe9f8a1461054b57600080fd5b80631aed65531161029d5780631aed6553146103e55780631cd348c0146103fb578063304f807c1461041b5780633279beab1461042e578063392e53cd1461044e5780633f138d4b146104785780634641257d1461049857600080fd5b80626f0231146102fa5780630bf8a6a41461031c5780630fb5a6b41461033c57806313c68f9014610365578063155622a4146103785780631582358e14610398578063167d2dbe146103c557600080fd5b366102f557005b600080fd5b34801561030657600080fd5b5061031a610315366004615468565b6109bc565b005b34801561032857600080fd5b5061031a61033736600461552a565b610b15565b34801561034857600080fd5b5061035260035481565b6040519081526020015b60405180910390f35b61031a610373366004615588565b610c3e565b34801561038457600080fd5b5061031a610393366004615588565b610dbe565b3480156103a457600080fd5b506013546103b8906001600160a01b031681565b60405161035c91906156b4565b3480156103d157600080fd5b506103b86103e0366004615468565b610f80565b3480156103f157600080fd5b5061035260075481565b34801561040757600080fd5b50600d546103b8906001600160a01b031681565b61031a610429366004615588565b610faa565b34801561043a57600080fd5b5061031a610449366004615468565b611487565b34801561045a57600080fd5b506002546104689060ff1681565b604051901515815260200161035c565b34801561048457600080fd5b5061031a61049336600461528f565b611566565b3480156104a457600080fd5b5061031a61176d565b3480156104b957600080fd5b5061035260065481565b3480156104cf57600080fd5b5061031a6104de3660046153be565b6117f6565b3480156104ef57600080fd5b5061031a6104fe36600461560a565b611a99565b34801561050f57600080fd5b5061031a61051e3660046155ed565b611bed565b34801561052f57600080fd5b506103526120c1565b61031a610546366004615564565b6121d8565b34801561055757600080fd5b5061035260055481565b61031a61056f366004615588565b6127e6565b34801561058057600080fd5b506009546103b8906001600160a01b031681565b3480156105a057600080fd5b506103526105af3660046152ba565b6129d0565b3480156105c057600080fd5b506012546103b8906001600160a01b031681565b3480156105e057600080fd5b5061031a612bec565b3480156105f557600080fd5b506011546103b8906001600160a01b031681565b34801561061557600080fd5b5061031a612c25565b34801561062a57600080fd5b5061063e6106393660046155c0565b612d41565b6040805193845260208401929092529082015260600161035c565b61031a610667366004615588565b612ec9565b34801561067857600080fd5b5061031a6132f9565b34801561068d57600080fd5b5061035260155481565b3480156106a357600080fd5b5061031a6106b236600461528f565b613449565b3480156106c357600080fd5b50610352600e5481565b3480156106d957600080fd5b5061035260105481565b3480156106ef57600080fd5b5061031a6106fe366004615468565b61358f565b34801561070f57600080fd5b506103b8613747565b34801561072457600080fd5b50610738610733366004615468565b613756565b6040805160ff909a168a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c084015260e08301526101008201526101200161035c565b61031a61078e366004615564565b6137b5565b34801561079f57600080fd5b5061035260145481565b3480156107b557600080fd5b506004546104689060ff1681565b3480156107cf57600080fd5b50610352613bc9565b3480156107e457600080fd5b5061031a6107f33660046153a1565b613cae565b34801561080457600080fd5b5061063e610813366004615257565b601d6020526000908152604090208054600182015460029092015490919083565b34801561084057600080fd5b5061085461084f36600461528f565b613d8a565b6040805160ff90971687526020870195909552938501929092526060840152608083015260a082015260c00161035c565b34801561089157600080fd5b506103526103e381565b3480156108a757600080fd5b50600c546103b8906001600160a01b031681565b3480156108c757600080fd5b506103b86108d6366004615468565b613de2565b3480156108e757600080fd5b50610352600f5481565b3480156108fd57600080fd5b5061031a61090c366004615498565b613df2565b34801561091d57600080fd5b5061031a61092c366004615257565b613f60565b34801561093d57600080fd5b50610352613ffd565b34801561095257600080fd5b5061031a610961366004615468565b614137565b34801561097257600080fd5b50610352610981366004615588565b614202565b34801561099257600080fd5b506103526109a13660046152ba565b614256565b3480156109b257600080fd5b5061035260085481565b336109c5613747565b6001600160a01b0316146109f45760405162461bcd60e51b81526004016109eb906157c9565b60405180910390fd5b600060065411610a3c5760405162461bcd60e51b8152602060048201526013602482015272141bdbdb081a5cc81b9bdd081cdd185c9d1959606a1b60448201526064016109eb565b4360075411610a895760405162461bcd60e51b8152602060048201526019602482015278141bdbdb081dd85cc8185b1c9958591e48199a5b9a5cda1959603a1b60448201526064016109eb565b4381118015610a99575060065481115b610ad95760405162461bcd60e51b8152602060048201526011602482015270496e76616c696420656e6420626c6f636b60781b60448201526064016109eb565b60078190556040518181527f0972575658363b3e7c472ab3a6a918726742c853b732f6a4a2763e2e3a94c977906020015b60405180910390a150565b33610b1e613747565b6001600160a01b031614610b445760405162461bcd60e51b81526004016109eb906157c9565b6107d08410610b655760405162461bcd60e51b81526004016109eb90615746565b6107d08310610b865760405162461bcd60e51b81526004016109eb90615773565b601b8054600190810180835560008381529291610ba291615b63565b81548110610bc057634e487b7160e01b600052603260045260246000fd5b60009182526020909120600160099092020181810188905560028101879055600381018690556004810185905543600682015560088101849055601b54909250600080516020615c4083398151915291610c1991615b63565b87878787604051610c2e9594939291906159a4565b60405180910390a1505050505050565b60026001541415610c615760405162461bcd60e51b81526004016109eb90615835565b6002600155601b5460ff821610610c7757610db7565b600654610c8357610db7565b610c8b61450f565b610c94816145f7565b336000908152601c6020526040812090805b8254811015610d79576000838281548110610cd157634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff868116911614610cf85750610d67565b6001810154610d075750610d67565b80600501546010546014548360010154610d219190615b44565b610d2b9190615a39565b610d359190615b63565b610d3f9084615a21565b92506010546014548260010154610d569190615b44565b610d609190615a39565b6005909101555b80610d7181615ba6565b915050610ca6565b50610d83816147b5565b90508015610db457601354610da2906001600160a01b031633836147e5565b80601754610db09190615b63565b6017555b50505b5060018055565b60026001541415610de15760405162461bcd60e51b81526004016109eb90615835565b6002600155601b5460ff821610610df757610db7565b336000908152601d60209081526040808320601c9092528220601b80549293919260ff8616908110610e3957634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020190506000805b8354811015610eeb576000848281548110610e7857634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff888116911614610e9f5750610ed9565b6001810154610eae5750610ed9565b6001810154610ebd9084615a21565b6000600183018190556004830181905560059092019190915591505b80610ee381615ba6565b915050610e4d565b508015610f3f57601154610f09906001600160a01b031633836148b4565b8354610f16908290615b63565b84556007820154610f28908290615b63565b6007830155601554610f3b908290615b63565b6015555b60405181815233907f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd9695906020015b60405180910390a2505050505060018055565b600a8181548110610f9057600080fd5b6000918252602090912001546001600160a01b0316905081565b60026001541415610fcd5760405162461bcd60e51b81526004016109eb90615835565b6002600155601b5460ff821610610fe357610db7565b600654610fef57610db7565b610ff761450f565b611000816145f7565b336000908152601d60209081526040808320601c9092528220601b80549293919260ff861690811061104257634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020190506000805b835481101561141757600084828154811061108157634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff8881169116146110a85750611405565b60018101546110b75750611405565b6000816005015460105460145484600101546110d39190615b44565b6110dd9190615a39565b6110e79190615b63565b90506110f2816147b5565b9050806017546111029190615b63565b6017556013546011546001600160a01b039081169116148015906111265750600081115b1561138a576013546001600160a01b031661121057600954604080516315ab88c960e31b815290516000926001600160a01b03169163ad5c4648916004808301926020929190829003018186803b15801561118057600080fd5b505afa158015611194573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b89190615273565b9050806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b1580156111f557600080fd5b505af1158015611209573d6000803e3d6000fd5b5050505050505b6011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906112419030906004016156b4565b60206040518083038186803b15801561125957600080fd5b505afa15801561126d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112919190615480565b90506112f882600a8054806020026020016040519081016040528092919081815260200182805480156112ed57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112cf575b50505050503061490a565b6011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906113299030906004016156b4565b60206040518083038186803b15801561134157600080fd5b505afa158015611355573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113799190615480565b90506113858282615b63565b925050505b6113948185615a21565b93508082600101546113a69190615a21565b6001830155600f5460058601546113bd9083615b44565b6113c79190615a39565b82600401546113d69190615a21565b600483015560105460145460018401546113f09190615b44565b6113fa9190615a39565b826005018190555050505b8061140f81615ba6565b915050611056565b50801561147c57835461142b908290615a21565b8455600782015461143d908290615a21565b6007830155601554611450908290615a21565b6015556040805160ff87168152602081018390523391600080516020615c608339815191529101610f6d565b505050505060018055565b33611490613747565b6001600160a01b0316146114b65760405162461bcd60e51b81526004016109eb906157c9565b60075443116114f95760405162461bcd60e51b815260206004820152600f60248201526e506f6f6c2069732072756e6e696e6760881b60448201526064016109eb565b80611502613bc9565b10156115205760405162461bcd60e51b81526004016109eb906158c8565b601254611537906001600160a01b031633836148b4565b601654156115635760165481111561155157600060165550565b8060165461155f9190615b63565b6016555b50565b3361156f613747565b6001600160a01b0316146115955760405162461bcd60e51b81526004016109eb906157c9565b6012546001600160a01b03838116911614156115ec5760405162461bcd60e51b815260206004820152601660248201527521b0b73737ba103132903932bbb0b932103a37b5b2b760511b60448201526064016109eb565b6011546001600160a01b03838116911614156116db576011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906116339030906004016156b4565b60206040518083038186803b15801561164b57600080fd5b505afa15801561165f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116839190615480565b9050601554816116939190615b63565b8211156116d95760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b60448201526064016109eb565b505b6001600160a01b03821661171c57604051339082156108fc029083906000818181858888f19350505050158015611716573d6000803e3d6000fd5b50611730565b6117306001600160a01b03831633836148b4565b7f74f5dcd55c394cb1c6d3b9da22c2464bcc46c38cc3865bd629ed75823249b40b82826040516117619291906156c8565b60405180910390a15050565b33611776613747565b6001600160a01b03161461179c5760405162461bcd60e51b81526004016109eb906157c9565b6117a660006145f7565b6117b16018546147b5565b6018819055156117f457601354600c546018546117db926001600160a01b039081169216906147e5565b6018546017546117eb9190615b63565b60175560006018555b565b336117ff613747565b6001600160a01b0316146118255760405162461bcd60e51b81526004016109eb906157c9565b60025460ff161561186e5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b60448201526064016109eb565b6002805460ff19166001179055601180546001600160a01b038089166001600160a01b0319928316179092556012805488841690831681179091556013805493881693831693909317909255600c8054909116331790556040805163313ce56760e01b815290516000929163313ce567916004808301926020929190829003018186803b1580156118fe57600080fd5b505afa158015611912573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193691906155a4565b60ff169050601e811061195b5760405162461bcd60e51b81526004016109eb90615898565b611966816028615b63565b61197190600a615a9c565b600f556013546012906001600160a01b031615611a3357601360009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156119d657600080fd5b505afa1580156119ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0e91906155a4565b60ff169050601e8110611a335760405162461bcd60e51b81526004016109eb90615898565b611a3e826028615b63565b611a4990600a615a9c565b601055600980546001600160a01b0319166001600160a01b0387161790558351611a7a90600b906020870190615165565b508251611a8e90600a906020860190615165565b505050505050505050565b33611aa2613747565b6001600160a01b031614611ac85760405162461bcd60e51b81526004016109eb906157c9565b601b5460ff871610611b0f5760405162461bcd60e51b815260206004820152601060248201526f131bd8dadd5c08139bdd08199bdd5b9960821b60448201526064016109eb565b6107d08410611b305760405162461bcd60e51b81526004016109eb90615746565b6107d08310611b515760405162461bcd60e51b81526004016109eb90615773565b611b5a866145f7565b6000601b8760ff1681548110611b8057634e487b7160e01b600052603260045260246000fd5b600091825260209091206009909102016001810187905560028101869055600381018590556004810184905560088101839055604051909150600080516020615c4083398151915290611bdc90899089908990899089906159a4565b60405180910390a150505050505050565b33611bf6613747565b6001600160a01b031614611c1c5760405162461bcd60e51b81526004016109eb906157c9565b600060065411611c645760405162461bcd60e51b81526020600482015260136024820152721c1bdbdb081a5cc81b9bdd081cdd185c9d1959606a1b60448201526064016109eb565b4360075411611cb15760405162461bcd60e51b81526020600482015260196024820152781c1bdbdb081dd85cc8185b1c9958591e48199a5b9a5cda1959603a1b60448201526064016109eb565b60008111611cd15760405162461bcd60e51b81526004016109eb906157a1565b611cda826145f7565b6012546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611d0b9030906004016156b4565b60206040518083038186803b158015611d2357600080fd5b505afa158015611d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5b9190615480565b601254909150611d76906001600160a01b0316333085614ab5565b6012546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611da79030906004016156b4565b60206040518083038186803b158015611dbf57600080fd5b505afa158015611dd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df79190615480565b90508181601654611e089190615a21565b611e129190615b63565b601655601954600090611e23613bc9565b611e2d9190615a21565b601a5490915060005b601b54811015611f54578660ff16811415611e5057611f42565b600654611eb457600354601b8281548110611e7b57634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160040154611e979190615b44565b611ea39061191a615b44565b611ead9083615a21565b9150611f42565b6000611ef4601b8381548110611eda57634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160060154600754614aed565b905080601b8381548110611f1857634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160040154611f349190615b44565b611f3e9084615a21565b9250505b80611f4c81615ba6565b915050611e36565b50601a548211156120b957611f698183615b63565b9150600043600754611f7b9190615b63565b9050611f878184615a39565b601b8860ff1681548110611fab57634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160040181905550600080516020615c4083398151915287601b8960ff1681548110611ff457634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160010154601b8a60ff168154811061202a57634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160020154601b8b60ff168154811061206057634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160030154601b8c60ff168154811061209657634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160040154604051611bdc9594939291906159a4565b505050505050565b6013546000906001600160a01b03166120d957504790565b6013546040516370a0823160e01b81526000916001600160a01b0316906370a082319061210a9030906004016156b4565b60206040518083038186803b15801561212257600080fd5b505afa158015612136573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215a9190615480565b6012546013549192506001600160a01b03918216911614156121985760165481101561218857600091505090565b6016546121959082615b63565b90505b6011546013546001600160a01b03908116911614156121d3576015548110156121c357600091505090565b6015546121d09082615b63565b90505b919050565b600260015414156121fb5760405162461bcd60e51b81526004016109eb90615835565b600260015560065415801590612212575043600654105b61225e5760405162461bcd60e51b815260206004820152601a60248201527f5374616b696e67206861736e277420737461727465642079657400000000000060448201526064016109eb565b6000821161227e5760405162461bcd60e51b81526004016109eb906157fe565b601b5460ff8216106122a25760405162461bcd60e51b81526004016109eb9061586c565b6122aa61450f565b6122b3816145f7565b336000908152601d60209081526040808320601c9092528220601b80549293919260ff86169081106122f557634e487b7160e01b600052603260045260246000fd5b9060005260206000209060090201905060008160080154111561239b5780600801548160070154106123695760405162461bcd60e51b815260206004820152601b60248201527f546f74616c207374616b6564206c696d6974206578636565646564000000000060448201526064016109eb565b806008015485826007015461237e9190615a21565b111561239b57806007015481600801546123989190615b63565b94505b60008060005b84548110156124de5760008582815481106123cc57634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff8981169116146123f357506124cc565b600181015461240257506124cc565b8060050154601054601454836001015461241c9190615b44565b6124269190615a39565b6124309190615b63565b61243a9084615a21565b925060008160040154600f548760050154846001015461245a9190615b44565b6124649190615a39565b61246e9190615b63565b905061247a8186615a21565b9450600f54866005015483600101546124939190615b44565b61249d9190615a39565b600483015560105460145460018401546124b79190615b44565b6124c19190615a39565b826005018190555050505b806124d681615ba6565b9150506123a1565b50811561253e57816124ee613bc9565b101561250c5760405162461bcd60e51b81526004016109eb906158c8565b601254612523906001600160a01b031633846148b4565b61252c82614b28565b8160195461253a9190615a21565b6019555b612547816147b5565b9050801561257857601354612566906001600160a01b031633836147e5565b806017546125749190615b63565b6017555b6011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906125a99030906004016156b4565b60206040518083038186803b1580156125c157600080fd5b505afa1580156125d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f99190615480565b601154909150612614906001600160a01b031633308b614ab5565b6011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906126459030906004016156b4565b60206040518083038186803b15801561265d57600080fd5b505afa158015612671573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126959190615480565b905060006126a38383615b63565b60045490915060ff16156127085760055488546126c09083615a21565b11156127085760405162461bcd60e51b8152602060048201526017602482015276155cd95c88185b5bdd5b9d0818589bdd99481b1a5b5a5d604a1b60448201526064016109eb565b6002860154156127655760006127108760020154836127279190615b44565b6127319190615a39565b9050801561276357600c54601154612756916001600160a01b039182169116836148b4565b6127608183615b63565b91505b505b6127758933886001015484614b48565b8754612782908290615a21565b88556007860154612794908290615a21565b60078701556015546127a7908290615a21565b6015556040805160ff8b168152602081018390523391600080516020615c60833981519152910160405180910390a25050600180555050505050505050565b600260015414156128095760405162461bcd60e51b81526004016109eb90615835565b6002600155601b5460ff82161061281f57610db7565b60065461282b57610db7565b61283361450f565b61283c816145f7565b336000908152601c60205260408120601b805491929160ff851690811061287357634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020190506000805b83548110156129665760008482815481106128b257634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff8781169116146128d95750612954565b60018101546128e85750612954565b60008160040154600f54866005015484600101546129069190615b44565b6129109190615a39565b61291a9190615b63565b90506129268185615a21565b9350600f548560050154836001015461293f9190615b44565b6129499190615a39565b826004018190555050505b8061295e81615ba6565b915050612887565b5080156129c65780612976613bc9565b10156129945760405162461bcd60e51b81526004016109eb906158c8565b6012546129ab906001600160a01b031633836148b4565b6129b481614b28565b806019546129c29190615a21565b6019555b5050505060018055565b601b5460009060ff8316106129e757506000612be6565b60065415806129f65750601554155b15612a0357506000612be6565b6001600160a01b0383166000908152601c6020908152604080832080548251818502810185019093528083529192909190849084015b82821015612aa45760008481526020908190206040805160c08101825260068602909201805460ff1683526001808201548486015260028201549284019290925260038101546060840152600481015460808401526005015460a08301529083529092019101612a39565b5050505090506000612ab46120c1565b9050601754811015612ac557506017545b6015546000612ad2613bc9565b6012546011549192506001600160a01b0391821691161415612afb57612af88183615a21565b91505b60008260105460175486612b0f9190615b63565b612b199190615b44565b612b239190615a39565b601454612b309190615a21565b90506000805b8651811015612bdd576000878281518110612b6157634e487b7160e01b600052603260045260246000fd5b602002602001015190508960ff16816000015160ff1614612b825750612bcb565b6020810151612b915750612bcb565b8060a00151601054858360200151612ba99190615b44565b612bb39190615a39565b612bbd9190615b63565b612bc79084615a21565b9250505b80612bd581615ba6565b915050612b36565b50955050505050505b92915050565b33612bf5613747565b6001600160a01b031614612c1b5760405162461bcd60e51b81526004016109eb906157c9565b6117f46000614db6565b33612c2e613747565b6001600160a01b031614612c545760405162461bcd60e51b81526004016109eb906157c9565b60065415612c745760405162461bcd60e51b81526004016109eb90615714565b612c7f436064615a21565b600655600354612c919061191a615b44565b600654612c9e9190615a21565b60075560005b601b54811015612cf857600654601b8281548110612cd257634e487b7160e01b600052603260045260246000fd5b600091825260209091206006600990920201015580612cf081615ba6565b915050612ca4565b507f7cd0ab87d19036f3dfadadb232c78aa4879dda3f0c994a9d637532410ee2ce06600654600754604051612d37929190918252602082015260400190565b60405180910390a1565b600080600080601c6000866001600160a01b03166001600160a01b03168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015612df75760008481526020908190206040805160c08101825260068602909201805460ff1683526001808201548486015260028201549284019290925260038101546060840152600481015460808401526005015460a08301529083529092019101612d8c565b50505050905060005b8151811015612ec0576000828281518110612e2b57634e487b7160e01b600052603260045260246000fd5b602002602001015190508760ff16816000015160ff1614612e4c5750612eae565b6020810151612e5b5750612eae565b6020810151612e6a9087615a21565b95508060600151421180612e7f575043600754105b15612e9a576020810151612e939086615a21565b9450612eac565b6020810151612ea99085615a21565b93505b505b80612eb881615ba6565b915050612e00565b50509250925092565b60026001541415612eec5760405162461bcd60e51b81526004016109eb90615835565b6002600155601b5460ff821610612f0257610db7565b600654612f0e57610db7565b612f1661450f565b612f1f816145f7565b336000908152601d60209081526040808320601c9092528220601b80549293919260ff8616908110612f6157634e487b7160e01b600052603260045260246000fd5b9060005260206000209060090201905060008060005b8454811015613243576000858281548110612fa257634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff898116911614612fc95750613231565b6001810154612fd85750613231565b60008160040154600f5487600501548460010154612ff69190615b44565b6130009190615a39565b61300a9190615b63565b90506130168186615a21565b6012546011549196506001600160a01b0391821691161480159061303a5750600081115b156131b7576011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906130709030906004016156b4565b60206040518083038186803b15801561308857600080fd5b505afa15801561309c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130c09190615480565b905061312582600b8054806020026020016040519081016040528092919081815260200182805480156112ed576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116112cf5750505050503061490a565b6011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906131569030906004016156b4565b60206040518083038186803b15801561316e57600080fd5b505afa158015613182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131a69190615480565b90506131b28282615b63565b925050505b6131c18185615a21565b93508082600101546131d39190615a21565b60018301819055600f54600588015490916131ee9190615b44565b6131f89190615a39565b600483015560105460145461320d9083615b44565b6132179190615a39565b82600501546132269190615a21565b826005018190555050505b8061323b81615ba6565b915050612f77565b5081156132ed5781613253613bc9565b10156132715760405162461bcd60e51b81526004016109eb906158c8565b61327a82614b28565b816019546132889190615a21565b6019558454613298908290615a21565b855560078301546132aa908290615a21565b60078401556015546132bd908290615a21565b6015556040805160ff88168152602081018390523391600080516020615c60833981519152910160405180910390a25b50505050505060018055565b33613302613747565b6001600160a01b0316146133285760405162461bcd60e51b81526004016109eb906157c9565b60005b601b5460ff8216101561335357613341816145f7565b8061334b81615bc1565b91505061332b565b506000601954613361613bc9565b61336b9190615a21565b9050601a5481111561341357601a546133849082615b63565b60125460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb906133b790339085906004016156c8565b602060405180830381600087803b1580156133d157600080fd5b505af11580156133e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134099190615385565b5061341381614b28565b4360078190556040519081527ffed9fcb0ca3d1e761a4b929792bb24082fba92dca81252646ad306d30680656690602001610b0a565b600d546001600160a01b0316331461349f5760405162461bcd60e51b815260206004820152601960248201527839b2ba29b2b93b34b1b2a4b733379d102327a92124a22222a760391b60448201526064016109eb565b6001600160a01b0382166134e75760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b60448201526064016109eb565b66b1a2bc2ec50000811061353d5760405162461bcd60e51b815260206004820152601c60248201527f6665652063616e6e6f742065786365656420302e30352065746865720000000060448201526064016109eb565b600d80546001600160a01b0319166001600160a01b038416179055600e8190556040517f232f2e6280d2064b1e439bf40ecdada042d84eefbb55039e4c49e8dc4f4c90c99061176190849084906156c8565b33613598613747565b6001600160a01b0316146135be5760405162461bcd60e51b81526004016109eb906157c9565b600260015414156135e15760405162461bcd60e51b81526004016109eb90615835565b6002600155806136035760405162461bcd60e51b81526004016109eb906157a1565b6012546040516370a0823160e01b81526000916001600160a01b0316906370a08231906136349030906004016156b4565b60206040518083038186803b15801561364c57600080fd5b505afa158015613660573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136849190615480565b60125490915061369f906001600160a01b0316333085614ab5565b6012546040516370a0823160e01b81526000916001600160a01b0316906370a08231906136d09030906004016156b4565b60206040518083038186803b1580156136e857600080fd5b505afa1580156136fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137209190615480565b905081816016546137319190615a21565b61373b9190615b63565b60165550506001805550565b6000546001600160a01b031690565b601b818154811061376657600080fd5b600091825260209091206009909102018054600182015460028301546003840154600485015460058601546006870154600788015460089098015460ff90971698509496939592949193909289565b600260015414156137d85760405162461bcd60e51b81526004016109eb90615835565b6002600155816137fa5760405162461bcd60e51b81526004016109eb906157fe565b601b5460ff82161061381e5760405162461bcd60e51b81526004016109eb9061586c565b61382661450f565b61382f816145f7565b336000908152601d60209081526040808320601c9092528220601b80549293919260ff861690811061387157634e487b7160e01b600052603260045260246000fd5b60009182526020822060099091020191508086815b8554811015613a295760008682815481106138b157634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff8a81169116146138d85750613a17565b60018101546138e75750613a17565b826138f25750613a29565b60008160040154600f54886005015484600101546139109190615b44565b61391a9190615a39565b6139249190615b63565b9050816005015460105460145484600101546139409190615b44565b61394a9190615a39565b6139549190615b63565b61395e9086615a21565b945061396a8187615a21565b9550428260030154108061397f575043600754105b156139c75783826001015411156139ae578382600101546139a09190615b63565b6001830155600093506139c7565b60018201546139bd9085615b63565b6000600184015593505b600f54876005015483600101546139de9190615b44565b6139e89190615a39565b60048301556010546014546001840154613a029190615b44565b613a0c9190615a39565b826005018190555050505b80613a2181615ba6565b915050613886565b508215613a895782613a39613bc9565b1015613a575760405162461bcd60e51b81526004016109eb906158c8565b601254613a6e906001600160a01b031633856148b4565b613a7783614b28565b82601954613a859190615a21565b6019555b8115613ac457613a98826147b5565b601354909250613ab2906001600160a01b031633846147e5565b81601754613ac09190615b63565b6017555b6000613ad0828a615b63565b8754909150613ae0908290615b63565b87556007850154613af2908290615b63565b6007860155601554613b05908290615b63565b6015558015613b7c57600385015415613b65576000612710866003015483613b2d9190615b44565b613b379190615a39565b600c54601154919250613b57916001600160a01b039081169116836148b4565b613b618183615b63565b9150505b601154613b7c906001600160a01b031633836148b4565b6040805160ff8a1681526020810183905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a250506001805550505050505050565b6013546012546000916001600160a01b0391821691161415613bec575060165490565b6012546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613c1d9030906004016156b4565b60206040518083038186803b158015613c3557600080fd5b505afa158015613c49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c6d9190615480565b6011546012549192506001600160a01b03918216911614156121d357601554811015613c9b57600091505090565b601554613ca89082615b63565b91505090565b33613cb7613747565b6001600160a01b031614613cdd5760405162461bcd60e51b81526004016109eb906157c9565b8115613d39576005548111613d2f5760405162461bcd60e51b81526020600482015260186024820152772732bb903634b6b4ba1036bab9ba103132903434b3b432b960411b60448201526064016109eb565b6005819055613d3f565b60006005555b6004805460ff19168315159081179091556005546040805191825260208201929092527f19a6e21b354f2502655dd03f5ac08375f296d713847fbfbf7eec539cd22c44399101611761565b601c6020528160005260406000208181548110613da657600080fd5b600091825260209091206006909102018054600182015460028301546003840154600485015460059095015460ff909416965091945092909186565b600b8181548110610f9057600080fd5b33613dfb613747565b6001600160a01b031614613e215760405162461bcd60e51b81526004016109eb906157c9565b6103e3851115613e6e5760405162461bcd60e51b81526020600482015260186024820152770bee6d8d2e0e0c2ceca8cc2c6e8dee440e8dede40d0d2ced60431b60448201526064016109eb565b6001600160a01b038116613eb65760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964204164647265737360881b60448201526064016109eb565b6008859055600980546001600160a01b0319166001600160a01b0386161790558151613ee990600a906020850190615165565b508251613efd90600b906020860190615165565b50600c80546001600160a01b0319166001600160a01b0383161790556040517f0fae0d0e8768c1e54ef03d02ab9a3aea954cb05c643b8650d09b989b2cb27ac790613f5190879087908790879087906158ff565b60405180910390a15050505050565b33613f69613747565b6001600160a01b031614613f8f5760405162461bcd60e51b81526004016109eb906157c9565b6001600160a01b038116613ff45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109eb565b61156381614db6565b600080601a5490506000601954614012613bc9565b61401c9190615a21565b905060005b601b548110156141155760065461408f57600354601b828154811061405657634e487b7160e01b600052603260045260246000fd5b9060005260206000209060090201600401546140729190615b44565b61407e9061191a615b44565b6140889084615a21565b9250614103565b60006140b5601b8381548110611eda57634e487b7160e01b600052603260045260246000fd5b905080601b83815481106140d957634e487b7160e01b600052603260045260246000fd5b9060005260206000209060090201600401546140f59190615b44565b6140ff9085615a21565b9350505b8061410d81615ba6565b915050614021565b508181106141265760009250505090565b6141308183615b63565b9250505090565b33614140613747565b6001600160a01b0316146141665760405162461bcd60e51b81526004016109eb906157c9565b600654156141865760405162461bcd60e51b81526004016109eb90615714565b601e8110156141cd5760405162461bcd60e51b81526020600482015260136024820152721b1bddd95c881b1a5b5a5d081c995858da1959606a1b60448201526064016109eb565b60038190556040518181527f91abcc2d6823e3a3f11d31b208dd3065d2c6a791f1c7c9fe96a42ce12897eac590602001610b0a565b601b5460009060ff83161061421957506000919050565b601b8260ff168154811061423d57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060090201600401549050919050565b601b5460009060ff831610158061426d5750600654155b1561427a57506000612be6565b6001600160a01b0383166000908152601c6020908152604080832080548251818502810185019093528083529192909190849084015b8282101561431b5760008481526020908190206040805160c08101825260068602909201805460ff1683526001808201548486015260028201549284019290925260038101546060840152600481015460808401526005015460a083015290835290920191016142b0565b5050505090506000601b8460ff168154811061434757634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051610120810182526009909302909101805460ff1683526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460e0820181905260089092015461010082015291506143d257600092505050612be6565b60a081015160c0820151431180156143ed575060e082015115155b80156143fd575060008260c00151115b156144595760006144128360c0015143614aed565b905060008360800151826144269190615b44565b90508360e00151600f548261443b9190615b44565b6144459190615a39565b8460a001516144549190615a21565b925050505b6000805b845181101561450457600085828151811061448857634e487b7160e01b600052603260045260246000fd5b602002602001015190508760ff16816000015160ff16146144a957506144f2565b60208101516144b857506144f2565b8060800151600f548583602001516144d09190615b44565b6144da9190615a39565b6144e49190615b63565b6144ee9084615a21565b9250505b806144fc81615ba6565b91505061445d565b509695505050505050565b600e543410156145755760405162461bcd60e51b815260206004820152602b60248201527f73686f756c642070617920736d616c6c2067617320746f20636f6d706f756e6460448201526a081bdc881a185c9d995cdd60aa1b60648201526084016109eb565b600d54600e546040516001600160a01b039092169181156108fc0291906000818181858888f193505050501580156145b1573d6000803e3d6000fd5b50600e543411156117f457600e5433906108fc906145cf9034615b63565b6040518115909202916000818181858888f19350505050158015611563573d6000803e3d6000fd5b601554156146da5760006146096120c1565b905060175481101561461a57506017545b6015546000614627613bc9565b6012546011549192506001600160a01b03918216911614156146505761464d8183615a21565b91505b81601054601754856146629190615b63565b61466c9190615b44565b6146769190615a39565b6014546146839190615a21565b6014556012546011546001600160a01b03908116911614156146d4578181601754856146af9190615b63565b6146b99190615b44565b6146c39190615a39565b6018546146d09190615a21565b6018555b50506017555b6000601b8260ff168154811061470057634e487b7160e01b600052603260045260246000fd5b9060005260206000209060090201905080600601544311158061472557506006810154155b1561472e575050565b6007810154614741574360069091015550565b6000614751826006015443614aed565b905060008260040154826147659190615b44565b90508260070154600f548261477a9190615b44565b6147849190615a39565b83600501546147939190615a21565b6005840155436006840155601a546147ac908290615a21565b601a5550505050565b6000806147c06120c1565b90506017548311156147d25760175492505b808311156147de578092505b5090919050565b6001600160a01b03831661482f576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015614829573d6000803e3d6000fd5b50505050565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb9061485d90859085906004016156c8565b602060405180830381600087803b15801561487757600080fd5b505af115801561488b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148299190615385565b505050565b6148af8363a9059cbb60e01b84846040516024016148d39291906156c8565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614e06565b60095460405163d06ca61f60e01b81526000916001600160a01b03169063d06ca61f9061493d908790879060040161594f565b60006040518083038186803b15801561495557600080fd5b505afa158015614969573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261499191908101906152f2565b9050600081600183516149a49190615b63565b815181106149c257634e487b7160e01b600052603260045260246000fd5b60200260200101519050614a27600960009054906101000a90046001600160a01b03168686600081518110614a0757634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316614ed89092919063ffffffff16565b6009546008546001600160a01b0390911690635c11d7959087906103e890614a4f9086615b44565b614a599190615a39565b8787614a6742610258615a21565b6040518663ffffffff1660e01b8152600401614a87959493929190615968565b600060405180830381600087803b158015614aa157600080fd5b505af1158015611a8e573d6000803e3d6000fd5b6040516001600160a01b03808516602483015283166044820152606481018290526148299085906323b872dd60e01b906084016148d3565b60006007548211614b0957614b028383615b63565b9050612be6565b6007548310614b1a57506000612be6565b82600754614b029190615b63565b806016541115614b40578060165461155f9190615b63565b600060165550565b6001600160a01b0383166000908152601c6020526040812090614b6e8462015180615b44565b614b789042615a21565b82549091506101008110614bbb5760405162461bcd60e51b815260206004820152600a6024820152694d6178207374616b657360b01b60448201526064016109eb565b8254600101835560008390525b8015801590614c1157508183614bdf600184615b63565b81548110614bfd57634e487b7160e01b600052603260045260246000fd5b906000526020600020906006020160030154115b15614cd85782614c22600183615b63565b81548110614c4057634e487b7160e01b600052603260045260246000fd5b9060005260206000209060060201838281548110614c6e57634e487b7160e01b600052603260045260246000fd5b600091825260209091208254600690920201805460ff191660ff909216919091178155600180830154818301556002808401549083015560038084015490830155600480840154908301556005928301549290910191909155614cd19082615b63565b9050614bc8565b6000601b8860ff1681548110614cfe57634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020190506000848381548110614d3057634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805460ff191660ff8b16178155600281018890556003810185905560018101879055600f54600584015491925090614d789088615b44565b614d829190615a39565b60048201556010546014546001830154614d9c9190615b44565b614da69190615a39565b6005909101555050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000614e5b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614feb9092919063ffffffff16565b8051909150156148af5780806020019051810190614e799190615385565b6148af5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109eb565b801580614f615750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015614f2757600080fd5b505afa158015614f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f5f9190615480565b155b614fcc5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084016109eb565b6148af8363095ea7b360e01b84846040516024016148d39291906156c8565b6060614ffa8484600085615004565b90505b9392505050565b6060824710156150655760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109eb565b843b6150b35760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109eb565b600080866001600160a01b031685876040516150cf9190615698565b60006040518083038185875af1925050503d806000811461510c576040519150601f19603f3d011682016040523d82523d6000602084013e615111565b606091505b509150915061512182828661512c565b979650505050505050565b6060831561513b575081614ffd565b82511561514b5782518084602001fd5b8160405162461bcd60e51b81526004016109eb91906156e1565b8280548282559060005260206000209081019282156151ba579160200282015b828111156151ba57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615185565b506151c69291506151ca565b5090565b5b808211156151c657600081556001016151cb565b600082601f8301126151ef578081fd5b813560206152046151ff836159fd565b6159cc565b80838252828201915082860187848660051b8901011115615223578586fd5b855b8581101561524a57813561523881615c0d565b84529284019290840190600101615225565b5090979650505050505050565b600060208284031215615268578081fd5b8135614ffd81615c0d565b600060208284031215615284578081fd5b8151614ffd81615c0d565b600080604083850312156152a1578081fd5b82356152ac81615c0d565b946020939093013593505050565b600080604083850312156152cc578182fd5b82356152d781615c0d565b915060208301356152e781615c30565b809150509250929050565b60006020808385031215615304578182fd5b825167ffffffffffffffff81111561531a578283fd5b8301601f8101851361532a578283fd5b80516153386151ff826159fd565b80828252848201915084840188868560051b8701011115615357578687fd5b8694505b8385101561537957805183526001949094019391850191850161535b565b50979650505050505050565b600060208284031215615396578081fd5b8151614ffd81615c22565b600080604083850312156153b3578182fd5b82356152ac81615c22565b60008060008060008060c087890312156153d6578182fd5b86356153e181615c0d565b955060208701356153f181615c0d565b9450604087013561540181615c0d565b9350606087013561541181615c0d565b9250608087013567ffffffffffffffff8082111561542d578384fd5b6154398a838b016151df565b935060a089013591508082111561544e578283fd5b5061545b89828a016151df565b9150509295509295509295565b600060208284031215615479578081fd5b5035919050565b600060208284031215615491578081fd5b5051919050565b600080600080600060a086880312156154af578081fd5b8535945060208601356154c181615c0d565b9350604086013567ffffffffffffffff808211156154dd578283fd5b6154e989838a016151df565b945060608801359150808211156154fe578283fd5b5061550b888289016151df565b925050608086013561551c81615c0d565b809150509295509295909350565b600080600080600060a08688031215615541578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060408385031215615576578182fd5b8235915060208301356152e781615c30565b600060208284031215615599578081fd5b8135614ffd81615c30565b6000602082840312156155b5578081fd5b8151614ffd81615c30565b600080604083850312156155d2578182fd5b82356155dd81615c30565b915060208301356152e781615c0d565b600080604083850312156155ff578182fd5b82356152ac81615c30565b60008060008060008060c08789031215615622578384fd5b863561562d81615c30565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b6000815180845260208085019450808401835b8381101561568d5781516001600160a01b031687529582019590820190600101615668565b509495945050505050565b600082516156aa818460208701615b7a565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6020815260008251806020840152615700816040850160208701615b7a565b601f01601f19169190910160400192915050565b602080825260189082015277141bdbdb081dd85cc8185b1c9958591e481cdd185c9d195960421b604082015260600190565b602080825260139082015272496e76616c6964206465706f7369742066656560681b604082015260600190565b602080825260149082015273496e76616c69642077697468647261772066656560601b604082015260600190565b6020808252600e908201526d1a5b9d985b1a5908185b5bdd5b9d60921b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601f908201527f416d6f756e742073686f756c642062652067726561746f72207468616e203000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b602080825260129082015271496e76616c6964207374616b65207479706560701b604082015260600190565b60208082526016908201527504d75737420626520696e666572696f7220746f2033360541b604082015260600190565b6020808252601a908201527f496e73756666696369656e742072657761726420746f6b656e73000000000000604082015260600190565b858152600060018060a01b03808716602084015260a0604084015261592760a0840187615655565b83810360608501526159398187615655565b9250508084166080840152509695505050505050565b828152604060208201526000614ffa6040830184615655565b85815284602082015260a06040820152600061598760a0830186615655565b6001600160a01b0394909416606083015250608001529392505050565b60ff959095168552602085019390935260408401919091526060830152608082015260a00190565b604051601f8201601f1916810167ffffffffffffffff811182821017156159f5576159f5615bf7565b604052919050565b600067ffffffffffffffff821115615a1757615a17615bf7565b5060051b60200190565b60008219821115615a3457615a34615be1565b500190565b600082615a5457634e487b7160e01b81526012600452602481fd5b500490565b600181815b80851115615a94578160001904821115615a7a57615a7a615be1565b80851615615a8757918102915b93841c9390800290615a5e565b509250929050565b6000614ffd8383600082615ab257506001612be6565b81615abf57506000612be6565b8160018114615ad55760028114615adf57615afb565b6001915050612be6565b60ff841115615af057615af0615be1565b50506001821b612be6565b5060208310610133831016604e8410600b8410161715615b1e575081810a612be6565b615b288383615a59565b8060001904821115615b3c57615b3c615be1565b029392505050565b6000816000190483118215151615615b5e57615b5e615be1565b500290565b600082821015615b7557615b75615be1565b500390565b60005b83811015615b95578181015183820152602001615b7d565b838111156148295750506000910152565b6000600019821415615bba57615bba615be1565b5060010190565b600060ff821660ff811415615bd857615bd8615be1565b60010192915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461156357600080fd5b801515811461156357600080fd5b60ff8116811461156357600080fdfe2a9378497cb60e247e83eb6f2c7c371ba979e24ee25723c2e3275822b317175990890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15a26469706673582212204374d0f0e7f0d8406c5a91342522638e3c09082e5c00e413f888e6864e8f6c3d64736f6c63430008040033
Deployed Bytecode
0x6080604052600436106102ee5760003560e01c806376fa17d211610186578063a0b40905116100d7578063e7a2fed711610085578063e7a2fed7146108f1578063f2fde38b14610911578063f3aeb31d14610931578063f6be71d114610946578063f8920ee714610966578063fbe32b3514610986578063ffbd3b1f146109a657600080fd5b8063a0b40905146107d8578063acc3a939146107f8578063b5d5b5fa14610834578063b74cd24214610885578063b77e7da01461089b578063c1e22a65146108bb578063ccd34cd5146108db57600080fd5b80638bdf67f2116101345780638bdf67f2146106e35780638da5cb5b146107035780638e6f4fb714610718578063903d42961461078057806392b46e5b1461079357806392e8990e146107a95780639f94e272146107c357600080fd5b806376fa17d21461061e57806378d57eea1461065957806380dc06721461066c578063817b1cd21461068157806381b619481461069757806387788782146106b757806388bbb0c1146106cd57600080fd5b806348cd4cb111610240578063689f1623116101ee578063689f162314610561578063693a090b146105745780636becd657146105945780636e707b73146105b4578063715018a6146105d457806372f702f3146105e9578063746c8ae11461060957600080fd5b806348cd4cb1146104ad578063515bbf2c146104c357806353314fae146104e3578063595e173a146105035780635dde4a9114610523578063654cfdff1461053857806366fe9f8a1461054b57600080fd5b80631aed65531161029d5780631aed6553146103e55780631cd348c0146103fb578063304f807c1461041b5780633279beab1461042e578063392e53cd1461044e5780633f138d4b146104785780634641257d1461049857600080fd5b80626f0231146102fa5780630bf8a6a41461031c5780630fb5a6b41461033c57806313c68f9014610365578063155622a4146103785780631582358e14610398578063167d2dbe146103c557600080fd5b366102f557005b600080fd5b34801561030657600080fd5b5061031a610315366004615468565b6109bc565b005b34801561032857600080fd5b5061031a61033736600461552a565b610b15565b34801561034857600080fd5b5061035260035481565b6040519081526020015b60405180910390f35b61031a610373366004615588565b610c3e565b34801561038457600080fd5b5061031a610393366004615588565b610dbe565b3480156103a457600080fd5b506013546103b8906001600160a01b031681565b60405161035c91906156b4565b3480156103d157600080fd5b506103b86103e0366004615468565b610f80565b3480156103f157600080fd5b5061035260075481565b34801561040757600080fd5b50600d546103b8906001600160a01b031681565b61031a610429366004615588565b610faa565b34801561043a57600080fd5b5061031a610449366004615468565b611487565b34801561045a57600080fd5b506002546104689060ff1681565b604051901515815260200161035c565b34801561048457600080fd5b5061031a61049336600461528f565b611566565b3480156104a457600080fd5b5061031a61176d565b3480156104b957600080fd5b5061035260065481565b3480156104cf57600080fd5b5061031a6104de3660046153be565b6117f6565b3480156104ef57600080fd5b5061031a6104fe36600461560a565b611a99565b34801561050f57600080fd5b5061031a61051e3660046155ed565b611bed565b34801561052f57600080fd5b506103526120c1565b61031a610546366004615564565b6121d8565b34801561055757600080fd5b5061035260055481565b61031a61056f366004615588565b6127e6565b34801561058057600080fd5b506009546103b8906001600160a01b031681565b3480156105a057600080fd5b506103526105af3660046152ba565b6129d0565b3480156105c057600080fd5b506012546103b8906001600160a01b031681565b3480156105e057600080fd5b5061031a612bec565b3480156105f557600080fd5b506011546103b8906001600160a01b031681565b34801561061557600080fd5b5061031a612c25565b34801561062a57600080fd5b5061063e6106393660046155c0565b612d41565b6040805193845260208401929092529082015260600161035c565b61031a610667366004615588565b612ec9565b34801561067857600080fd5b5061031a6132f9565b34801561068d57600080fd5b5061035260155481565b3480156106a357600080fd5b5061031a6106b236600461528f565b613449565b3480156106c357600080fd5b50610352600e5481565b3480156106d957600080fd5b5061035260105481565b3480156106ef57600080fd5b5061031a6106fe366004615468565b61358f565b34801561070f57600080fd5b506103b8613747565b34801561072457600080fd5b50610738610733366004615468565b613756565b6040805160ff909a168a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c084015260e08301526101008201526101200161035c565b61031a61078e366004615564565b6137b5565b34801561079f57600080fd5b5061035260145481565b3480156107b557600080fd5b506004546104689060ff1681565b3480156107cf57600080fd5b50610352613bc9565b3480156107e457600080fd5b5061031a6107f33660046153a1565b613cae565b34801561080457600080fd5b5061063e610813366004615257565b601d6020526000908152604090208054600182015460029092015490919083565b34801561084057600080fd5b5061085461084f36600461528f565b613d8a565b6040805160ff90971687526020870195909552938501929092526060840152608083015260a082015260c00161035c565b34801561089157600080fd5b506103526103e381565b3480156108a757600080fd5b50600c546103b8906001600160a01b031681565b3480156108c757600080fd5b506103b86108d6366004615468565b613de2565b3480156108e757600080fd5b50610352600f5481565b3480156108fd57600080fd5b5061031a61090c366004615498565b613df2565b34801561091d57600080fd5b5061031a61092c366004615257565b613f60565b34801561093d57600080fd5b50610352613ffd565b34801561095257600080fd5b5061031a610961366004615468565b614137565b34801561097257600080fd5b50610352610981366004615588565b614202565b34801561099257600080fd5b506103526109a13660046152ba565b614256565b3480156109b257600080fd5b5061035260085481565b336109c5613747565b6001600160a01b0316146109f45760405162461bcd60e51b81526004016109eb906157c9565b60405180910390fd5b600060065411610a3c5760405162461bcd60e51b8152602060048201526013602482015272141bdbdb081a5cc81b9bdd081cdd185c9d1959606a1b60448201526064016109eb565b4360075411610a895760405162461bcd60e51b8152602060048201526019602482015278141bdbdb081dd85cc8185b1c9958591e48199a5b9a5cda1959603a1b60448201526064016109eb565b4381118015610a99575060065481115b610ad95760405162461bcd60e51b8152602060048201526011602482015270496e76616c696420656e6420626c6f636b60781b60448201526064016109eb565b60078190556040518181527f0972575658363b3e7c472ab3a6a918726742c853b732f6a4a2763e2e3a94c977906020015b60405180910390a150565b33610b1e613747565b6001600160a01b031614610b445760405162461bcd60e51b81526004016109eb906157c9565b6107d08410610b655760405162461bcd60e51b81526004016109eb90615746565b6107d08310610b865760405162461bcd60e51b81526004016109eb90615773565b601b8054600190810180835560008381529291610ba291615b63565b81548110610bc057634e487b7160e01b600052603260045260246000fd5b60009182526020909120600160099092020181810188905560028101879055600381018690556004810185905543600682015560088101849055601b54909250600080516020615c4083398151915291610c1991615b63565b87878787604051610c2e9594939291906159a4565b60405180910390a1505050505050565b60026001541415610c615760405162461bcd60e51b81526004016109eb90615835565b6002600155601b5460ff821610610c7757610db7565b600654610c8357610db7565b610c8b61450f565b610c94816145f7565b336000908152601c6020526040812090805b8254811015610d79576000838281548110610cd157634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff868116911614610cf85750610d67565b6001810154610d075750610d67565b80600501546010546014548360010154610d219190615b44565b610d2b9190615a39565b610d359190615b63565b610d3f9084615a21565b92506010546014548260010154610d569190615b44565b610d609190615a39565b6005909101555b80610d7181615ba6565b915050610ca6565b50610d83816147b5565b90508015610db457601354610da2906001600160a01b031633836147e5565b80601754610db09190615b63565b6017555b50505b5060018055565b60026001541415610de15760405162461bcd60e51b81526004016109eb90615835565b6002600155601b5460ff821610610df757610db7565b336000908152601d60209081526040808320601c9092528220601b80549293919260ff8616908110610e3957634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020190506000805b8354811015610eeb576000848281548110610e7857634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff888116911614610e9f5750610ed9565b6001810154610eae5750610ed9565b6001810154610ebd9084615a21565b6000600183018190556004830181905560059092019190915591505b80610ee381615ba6565b915050610e4d565b508015610f3f57601154610f09906001600160a01b031633836148b4565b8354610f16908290615b63565b84556007820154610f28908290615b63565b6007830155601554610f3b908290615b63565b6015555b60405181815233907f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd9695906020015b60405180910390a2505050505060018055565b600a8181548110610f9057600080fd5b6000918252602090912001546001600160a01b0316905081565b60026001541415610fcd5760405162461bcd60e51b81526004016109eb90615835565b6002600155601b5460ff821610610fe357610db7565b600654610fef57610db7565b610ff761450f565b611000816145f7565b336000908152601d60209081526040808320601c9092528220601b80549293919260ff861690811061104257634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020190506000805b835481101561141757600084828154811061108157634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff8881169116146110a85750611405565b60018101546110b75750611405565b6000816005015460105460145484600101546110d39190615b44565b6110dd9190615a39565b6110e79190615b63565b90506110f2816147b5565b9050806017546111029190615b63565b6017556013546011546001600160a01b039081169116148015906111265750600081115b1561138a576013546001600160a01b031661121057600954604080516315ab88c960e31b815290516000926001600160a01b03169163ad5c4648916004808301926020929190829003018186803b15801561118057600080fd5b505afa158015611194573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b89190615273565b9050806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b1580156111f557600080fd5b505af1158015611209573d6000803e3d6000fd5b5050505050505b6011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906112419030906004016156b4565b60206040518083038186803b15801561125957600080fd5b505afa15801561126d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112919190615480565b90506112f882600a8054806020026020016040519081016040528092919081815260200182805480156112ed57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112cf575b50505050503061490a565b6011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906113299030906004016156b4565b60206040518083038186803b15801561134157600080fd5b505afa158015611355573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113799190615480565b90506113858282615b63565b925050505b6113948185615a21565b93508082600101546113a69190615a21565b6001830155600f5460058601546113bd9083615b44565b6113c79190615a39565b82600401546113d69190615a21565b600483015560105460145460018401546113f09190615b44565b6113fa9190615a39565b826005018190555050505b8061140f81615ba6565b915050611056565b50801561147c57835461142b908290615a21565b8455600782015461143d908290615a21565b6007830155601554611450908290615a21565b6015556040805160ff87168152602081018390523391600080516020615c608339815191529101610f6d565b505050505060018055565b33611490613747565b6001600160a01b0316146114b65760405162461bcd60e51b81526004016109eb906157c9565b60075443116114f95760405162461bcd60e51b815260206004820152600f60248201526e506f6f6c2069732072756e6e696e6760881b60448201526064016109eb565b80611502613bc9565b10156115205760405162461bcd60e51b81526004016109eb906158c8565b601254611537906001600160a01b031633836148b4565b601654156115635760165481111561155157600060165550565b8060165461155f9190615b63565b6016555b50565b3361156f613747565b6001600160a01b0316146115955760405162461bcd60e51b81526004016109eb906157c9565b6012546001600160a01b03838116911614156115ec5760405162461bcd60e51b815260206004820152601660248201527521b0b73737ba103132903932bbb0b932103a37b5b2b760511b60448201526064016109eb565b6011546001600160a01b03838116911614156116db576011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906116339030906004016156b4565b60206040518083038186803b15801561164b57600080fd5b505afa15801561165f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116839190615480565b9050601554816116939190615b63565b8211156116d95760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b60448201526064016109eb565b505b6001600160a01b03821661171c57604051339082156108fc029083906000818181858888f19350505050158015611716573d6000803e3d6000fd5b50611730565b6117306001600160a01b03831633836148b4565b7f74f5dcd55c394cb1c6d3b9da22c2464bcc46c38cc3865bd629ed75823249b40b82826040516117619291906156c8565b60405180910390a15050565b33611776613747565b6001600160a01b03161461179c5760405162461bcd60e51b81526004016109eb906157c9565b6117a660006145f7565b6117b16018546147b5565b6018819055156117f457601354600c546018546117db926001600160a01b039081169216906147e5565b6018546017546117eb9190615b63565b60175560006018555b565b336117ff613747565b6001600160a01b0316146118255760405162461bcd60e51b81526004016109eb906157c9565b60025460ff161561186e5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b60448201526064016109eb565b6002805460ff19166001179055601180546001600160a01b038089166001600160a01b0319928316179092556012805488841690831681179091556013805493881693831693909317909255600c8054909116331790556040805163313ce56760e01b815290516000929163313ce567916004808301926020929190829003018186803b1580156118fe57600080fd5b505afa158015611912573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193691906155a4565b60ff169050601e811061195b5760405162461bcd60e51b81526004016109eb90615898565b611966816028615b63565b61197190600a615a9c565b600f556013546012906001600160a01b031615611a3357601360009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156119d657600080fd5b505afa1580156119ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0e91906155a4565b60ff169050601e8110611a335760405162461bcd60e51b81526004016109eb90615898565b611a3e826028615b63565b611a4990600a615a9c565b601055600980546001600160a01b0319166001600160a01b0387161790558351611a7a90600b906020870190615165565b508251611a8e90600a906020860190615165565b505050505050505050565b33611aa2613747565b6001600160a01b031614611ac85760405162461bcd60e51b81526004016109eb906157c9565b601b5460ff871610611b0f5760405162461bcd60e51b815260206004820152601060248201526f131bd8dadd5c08139bdd08199bdd5b9960821b60448201526064016109eb565b6107d08410611b305760405162461bcd60e51b81526004016109eb90615746565b6107d08310611b515760405162461bcd60e51b81526004016109eb90615773565b611b5a866145f7565b6000601b8760ff1681548110611b8057634e487b7160e01b600052603260045260246000fd5b600091825260209091206009909102016001810187905560028101869055600381018590556004810184905560088101839055604051909150600080516020615c4083398151915290611bdc90899089908990899089906159a4565b60405180910390a150505050505050565b33611bf6613747565b6001600160a01b031614611c1c5760405162461bcd60e51b81526004016109eb906157c9565b600060065411611c645760405162461bcd60e51b81526020600482015260136024820152721c1bdbdb081a5cc81b9bdd081cdd185c9d1959606a1b60448201526064016109eb565b4360075411611cb15760405162461bcd60e51b81526020600482015260196024820152781c1bdbdb081dd85cc8185b1c9958591e48199a5b9a5cda1959603a1b60448201526064016109eb565b60008111611cd15760405162461bcd60e51b81526004016109eb906157a1565b611cda826145f7565b6012546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611d0b9030906004016156b4565b60206040518083038186803b158015611d2357600080fd5b505afa158015611d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5b9190615480565b601254909150611d76906001600160a01b0316333085614ab5565b6012546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611da79030906004016156b4565b60206040518083038186803b158015611dbf57600080fd5b505afa158015611dd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df79190615480565b90508181601654611e089190615a21565b611e129190615b63565b601655601954600090611e23613bc9565b611e2d9190615a21565b601a5490915060005b601b54811015611f54578660ff16811415611e5057611f42565b600654611eb457600354601b8281548110611e7b57634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160040154611e979190615b44565b611ea39061191a615b44565b611ead9083615a21565b9150611f42565b6000611ef4601b8381548110611eda57634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160060154600754614aed565b905080601b8381548110611f1857634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160040154611f349190615b44565b611f3e9084615a21565b9250505b80611f4c81615ba6565b915050611e36565b50601a548211156120b957611f698183615b63565b9150600043600754611f7b9190615b63565b9050611f878184615a39565b601b8860ff1681548110611fab57634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160040181905550600080516020615c4083398151915287601b8960ff1681548110611ff457634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160010154601b8a60ff168154811061202a57634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160020154601b8b60ff168154811061206057634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160030154601b8c60ff168154811061209657634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020160040154604051611bdc9594939291906159a4565b505050505050565b6013546000906001600160a01b03166120d957504790565b6013546040516370a0823160e01b81526000916001600160a01b0316906370a082319061210a9030906004016156b4565b60206040518083038186803b15801561212257600080fd5b505afa158015612136573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215a9190615480565b6012546013549192506001600160a01b03918216911614156121985760165481101561218857600091505090565b6016546121959082615b63565b90505b6011546013546001600160a01b03908116911614156121d3576015548110156121c357600091505090565b6015546121d09082615b63565b90505b919050565b600260015414156121fb5760405162461bcd60e51b81526004016109eb90615835565b600260015560065415801590612212575043600654105b61225e5760405162461bcd60e51b815260206004820152601a60248201527f5374616b696e67206861736e277420737461727465642079657400000000000060448201526064016109eb565b6000821161227e5760405162461bcd60e51b81526004016109eb906157fe565b601b5460ff8216106122a25760405162461bcd60e51b81526004016109eb9061586c565b6122aa61450f565b6122b3816145f7565b336000908152601d60209081526040808320601c9092528220601b80549293919260ff86169081106122f557634e487b7160e01b600052603260045260246000fd5b9060005260206000209060090201905060008160080154111561239b5780600801548160070154106123695760405162461bcd60e51b815260206004820152601b60248201527f546f74616c207374616b6564206c696d6974206578636565646564000000000060448201526064016109eb565b806008015485826007015461237e9190615a21565b111561239b57806007015481600801546123989190615b63565b94505b60008060005b84548110156124de5760008582815481106123cc57634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff8981169116146123f357506124cc565b600181015461240257506124cc565b8060050154601054601454836001015461241c9190615b44565b6124269190615a39565b6124309190615b63565b61243a9084615a21565b925060008160040154600f548760050154846001015461245a9190615b44565b6124649190615a39565b61246e9190615b63565b905061247a8186615a21565b9450600f54866005015483600101546124939190615b44565b61249d9190615a39565b600483015560105460145460018401546124b79190615b44565b6124c19190615a39565b826005018190555050505b806124d681615ba6565b9150506123a1565b50811561253e57816124ee613bc9565b101561250c5760405162461bcd60e51b81526004016109eb906158c8565b601254612523906001600160a01b031633846148b4565b61252c82614b28565b8160195461253a9190615a21565b6019555b612547816147b5565b9050801561257857601354612566906001600160a01b031633836147e5565b806017546125749190615b63565b6017555b6011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906125a99030906004016156b4565b60206040518083038186803b1580156125c157600080fd5b505afa1580156125d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f99190615480565b601154909150612614906001600160a01b031633308b614ab5565b6011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906126459030906004016156b4565b60206040518083038186803b15801561265d57600080fd5b505afa158015612671573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126959190615480565b905060006126a38383615b63565b60045490915060ff16156127085760055488546126c09083615a21565b11156127085760405162461bcd60e51b8152602060048201526017602482015276155cd95c88185b5bdd5b9d0818589bdd99481b1a5b5a5d604a1b60448201526064016109eb565b6002860154156127655760006127108760020154836127279190615b44565b6127319190615a39565b9050801561276357600c54601154612756916001600160a01b039182169116836148b4565b6127608183615b63565b91505b505b6127758933886001015484614b48565b8754612782908290615a21565b88556007860154612794908290615a21565b60078701556015546127a7908290615a21565b6015556040805160ff8b168152602081018390523391600080516020615c60833981519152910160405180910390a25050600180555050505050505050565b600260015414156128095760405162461bcd60e51b81526004016109eb90615835565b6002600155601b5460ff82161061281f57610db7565b60065461282b57610db7565b61283361450f565b61283c816145f7565b336000908152601c60205260408120601b805491929160ff851690811061287357634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020190506000805b83548110156129665760008482815481106128b257634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff8781169116146128d95750612954565b60018101546128e85750612954565b60008160040154600f54866005015484600101546129069190615b44565b6129109190615a39565b61291a9190615b63565b90506129268185615a21565b9350600f548560050154836001015461293f9190615b44565b6129499190615a39565b826004018190555050505b8061295e81615ba6565b915050612887565b5080156129c65780612976613bc9565b10156129945760405162461bcd60e51b81526004016109eb906158c8565b6012546129ab906001600160a01b031633836148b4565b6129b481614b28565b806019546129c29190615a21565b6019555b5050505060018055565b601b5460009060ff8316106129e757506000612be6565b60065415806129f65750601554155b15612a0357506000612be6565b6001600160a01b0383166000908152601c6020908152604080832080548251818502810185019093528083529192909190849084015b82821015612aa45760008481526020908190206040805160c08101825260068602909201805460ff1683526001808201548486015260028201549284019290925260038101546060840152600481015460808401526005015460a08301529083529092019101612a39565b5050505090506000612ab46120c1565b9050601754811015612ac557506017545b6015546000612ad2613bc9565b6012546011549192506001600160a01b0391821691161415612afb57612af88183615a21565b91505b60008260105460175486612b0f9190615b63565b612b199190615b44565b612b239190615a39565b601454612b309190615a21565b90506000805b8651811015612bdd576000878281518110612b6157634e487b7160e01b600052603260045260246000fd5b602002602001015190508960ff16816000015160ff1614612b825750612bcb565b6020810151612b915750612bcb565b8060a00151601054858360200151612ba99190615b44565b612bb39190615a39565b612bbd9190615b63565b612bc79084615a21565b9250505b80612bd581615ba6565b915050612b36565b50955050505050505b92915050565b33612bf5613747565b6001600160a01b031614612c1b5760405162461bcd60e51b81526004016109eb906157c9565b6117f46000614db6565b33612c2e613747565b6001600160a01b031614612c545760405162461bcd60e51b81526004016109eb906157c9565b60065415612c745760405162461bcd60e51b81526004016109eb90615714565b612c7f436064615a21565b600655600354612c919061191a615b44565b600654612c9e9190615a21565b60075560005b601b54811015612cf857600654601b8281548110612cd257634e487b7160e01b600052603260045260246000fd5b600091825260209091206006600990920201015580612cf081615ba6565b915050612ca4565b507f7cd0ab87d19036f3dfadadb232c78aa4879dda3f0c994a9d637532410ee2ce06600654600754604051612d37929190918252602082015260400190565b60405180910390a1565b600080600080601c6000866001600160a01b03166001600160a01b03168152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015612df75760008481526020908190206040805160c08101825260068602909201805460ff1683526001808201548486015260028201549284019290925260038101546060840152600481015460808401526005015460a08301529083529092019101612d8c565b50505050905060005b8151811015612ec0576000828281518110612e2b57634e487b7160e01b600052603260045260246000fd5b602002602001015190508760ff16816000015160ff1614612e4c5750612eae565b6020810151612e5b5750612eae565b6020810151612e6a9087615a21565b95508060600151421180612e7f575043600754105b15612e9a576020810151612e939086615a21565b9450612eac565b6020810151612ea99085615a21565b93505b505b80612eb881615ba6565b915050612e00565b50509250925092565b60026001541415612eec5760405162461bcd60e51b81526004016109eb90615835565b6002600155601b5460ff821610612f0257610db7565b600654612f0e57610db7565b612f1661450f565b612f1f816145f7565b336000908152601d60209081526040808320601c9092528220601b80549293919260ff8616908110612f6157634e487b7160e01b600052603260045260246000fd5b9060005260206000209060090201905060008060005b8454811015613243576000858281548110612fa257634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff898116911614612fc95750613231565b6001810154612fd85750613231565b60008160040154600f5487600501548460010154612ff69190615b44565b6130009190615a39565b61300a9190615b63565b90506130168186615a21565b6012546011549196506001600160a01b0391821691161480159061303a5750600081115b156131b7576011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906130709030906004016156b4565b60206040518083038186803b15801561308857600080fd5b505afa15801561309c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130c09190615480565b905061312582600b8054806020026020016040519081016040528092919081815260200182805480156112ed576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116112cf5750505050503061490a565b6011546040516370a0823160e01b81526000916001600160a01b0316906370a08231906131569030906004016156b4565b60206040518083038186803b15801561316e57600080fd5b505afa158015613182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131a69190615480565b90506131b28282615b63565b925050505b6131c18185615a21565b93508082600101546131d39190615a21565b60018301819055600f54600588015490916131ee9190615b44565b6131f89190615a39565b600483015560105460145461320d9083615b44565b6132179190615a39565b82600501546132269190615a21565b826005018190555050505b8061323b81615ba6565b915050612f77565b5081156132ed5781613253613bc9565b10156132715760405162461bcd60e51b81526004016109eb906158c8565b61327a82614b28565b816019546132889190615a21565b6019558454613298908290615a21565b855560078301546132aa908290615a21565b60078401556015546132bd908290615a21565b6015556040805160ff88168152602081018390523391600080516020615c60833981519152910160405180910390a25b50505050505060018055565b33613302613747565b6001600160a01b0316146133285760405162461bcd60e51b81526004016109eb906157c9565b60005b601b5460ff8216101561335357613341816145f7565b8061334b81615bc1565b91505061332b565b506000601954613361613bc9565b61336b9190615a21565b9050601a5481111561341357601a546133849082615b63565b60125460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb906133b790339085906004016156c8565b602060405180830381600087803b1580156133d157600080fd5b505af11580156133e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134099190615385565b5061341381614b28565b4360078190556040519081527ffed9fcb0ca3d1e761a4b929792bb24082fba92dca81252646ad306d30680656690602001610b0a565b600d546001600160a01b0316331461349f5760405162461bcd60e51b815260206004820152601960248201527839b2ba29b2b93b34b1b2a4b733379d102327a92124a22222a760391b60448201526064016109eb565b6001600160a01b0382166134e75760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b60448201526064016109eb565b66b1a2bc2ec50000811061353d5760405162461bcd60e51b815260206004820152601c60248201527f6665652063616e6e6f742065786365656420302e30352065746865720000000060448201526064016109eb565b600d80546001600160a01b0319166001600160a01b038416179055600e8190556040517f232f2e6280d2064b1e439bf40ecdada042d84eefbb55039e4c49e8dc4f4c90c99061176190849084906156c8565b33613598613747565b6001600160a01b0316146135be5760405162461bcd60e51b81526004016109eb906157c9565b600260015414156135e15760405162461bcd60e51b81526004016109eb90615835565b6002600155806136035760405162461bcd60e51b81526004016109eb906157a1565b6012546040516370a0823160e01b81526000916001600160a01b0316906370a08231906136349030906004016156b4565b60206040518083038186803b15801561364c57600080fd5b505afa158015613660573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136849190615480565b60125490915061369f906001600160a01b0316333085614ab5565b6012546040516370a0823160e01b81526000916001600160a01b0316906370a08231906136d09030906004016156b4565b60206040518083038186803b1580156136e857600080fd5b505afa1580156136fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137209190615480565b905081816016546137319190615a21565b61373b9190615b63565b60165550506001805550565b6000546001600160a01b031690565b601b818154811061376657600080fd5b600091825260209091206009909102018054600182015460028301546003840154600485015460058601546006870154600788015460089098015460ff90971698509496939592949193909289565b600260015414156137d85760405162461bcd60e51b81526004016109eb90615835565b6002600155816137fa5760405162461bcd60e51b81526004016109eb906157fe565b601b5460ff82161061381e5760405162461bcd60e51b81526004016109eb9061586c565b61382661450f565b61382f816145f7565b336000908152601d60209081526040808320601c9092528220601b80549293919260ff861690811061387157634e487b7160e01b600052603260045260246000fd5b60009182526020822060099091020191508086815b8554811015613a295760008682815481106138b157634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805490915060ff8a81169116146138d85750613a17565b60018101546138e75750613a17565b826138f25750613a29565b60008160040154600f54886005015484600101546139109190615b44565b61391a9190615a39565b6139249190615b63565b9050816005015460105460145484600101546139409190615b44565b61394a9190615a39565b6139549190615b63565b61395e9086615a21565b945061396a8187615a21565b9550428260030154108061397f575043600754105b156139c75783826001015411156139ae578382600101546139a09190615b63565b6001830155600093506139c7565b60018201546139bd9085615b63565b6000600184015593505b600f54876005015483600101546139de9190615b44565b6139e89190615a39565b60048301556010546014546001840154613a029190615b44565b613a0c9190615a39565b826005018190555050505b80613a2181615ba6565b915050613886565b508215613a895782613a39613bc9565b1015613a575760405162461bcd60e51b81526004016109eb906158c8565b601254613a6e906001600160a01b031633856148b4565b613a7783614b28565b82601954613a859190615a21565b6019555b8115613ac457613a98826147b5565b601354909250613ab2906001600160a01b031633846147e5565b81601754613ac09190615b63565b6017555b6000613ad0828a615b63565b8754909150613ae0908290615b63565b87556007850154613af2908290615b63565b6007860155601554613b05908290615b63565b6015558015613b7c57600385015415613b65576000612710866003015483613b2d9190615b44565b613b379190615a39565b600c54601154919250613b57916001600160a01b039081169116836148b4565b613b618183615b63565b9150505b601154613b7c906001600160a01b031633836148b4565b6040805160ff8a1681526020810183905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a250506001805550505050505050565b6013546012546000916001600160a01b0391821691161415613bec575060165490565b6012546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613c1d9030906004016156b4565b60206040518083038186803b158015613c3557600080fd5b505afa158015613c49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c6d9190615480565b6011546012549192506001600160a01b03918216911614156121d357601554811015613c9b57600091505090565b601554613ca89082615b63565b91505090565b33613cb7613747565b6001600160a01b031614613cdd5760405162461bcd60e51b81526004016109eb906157c9565b8115613d39576005548111613d2f5760405162461bcd60e51b81526020600482015260186024820152772732bb903634b6b4ba1036bab9ba103132903434b3b432b960411b60448201526064016109eb565b6005819055613d3f565b60006005555b6004805460ff19168315159081179091556005546040805191825260208201929092527f19a6e21b354f2502655dd03f5ac08375f296d713847fbfbf7eec539cd22c44399101611761565b601c6020528160005260406000208181548110613da657600080fd5b600091825260209091206006909102018054600182015460028301546003840154600485015460059095015460ff909416965091945092909186565b600b8181548110610f9057600080fd5b33613dfb613747565b6001600160a01b031614613e215760405162461bcd60e51b81526004016109eb906157c9565b6103e3851115613e6e5760405162461bcd60e51b81526020600482015260186024820152770bee6d8d2e0e0c2ceca8cc2c6e8dee440e8dede40d0d2ced60431b60448201526064016109eb565b6001600160a01b038116613eb65760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964204164647265737360881b60448201526064016109eb565b6008859055600980546001600160a01b0319166001600160a01b0386161790558151613ee990600a906020850190615165565b508251613efd90600b906020860190615165565b50600c80546001600160a01b0319166001600160a01b0383161790556040517f0fae0d0e8768c1e54ef03d02ab9a3aea954cb05c643b8650d09b989b2cb27ac790613f5190879087908790879087906158ff565b60405180910390a15050505050565b33613f69613747565b6001600160a01b031614613f8f5760405162461bcd60e51b81526004016109eb906157c9565b6001600160a01b038116613ff45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109eb565b61156381614db6565b600080601a5490506000601954614012613bc9565b61401c9190615a21565b905060005b601b548110156141155760065461408f57600354601b828154811061405657634e487b7160e01b600052603260045260246000fd5b9060005260206000209060090201600401546140729190615b44565b61407e9061191a615b44565b6140889084615a21565b9250614103565b60006140b5601b8381548110611eda57634e487b7160e01b600052603260045260246000fd5b905080601b83815481106140d957634e487b7160e01b600052603260045260246000fd5b9060005260206000209060090201600401546140f59190615b44565b6140ff9085615a21565b9350505b8061410d81615ba6565b915050614021565b508181106141265760009250505090565b6141308183615b63565b9250505090565b33614140613747565b6001600160a01b0316146141665760405162461bcd60e51b81526004016109eb906157c9565b600654156141865760405162461bcd60e51b81526004016109eb90615714565b601e8110156141cd5760405162461bcd60e51b81526020600482015260136024820152721b1bddd95c881b1a5b5a5d081c995858da1959606a1b60448201526064016109eb565b60038190556040518181527f91abcc2d6823e3a3f11d31b208dd3065d2c6a791f1c7c9fe96a42ce12897eac590602001610b0a565b601b5460009060ff83161061421957506000919050565b601b8260ff168154811061423d57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060090201600401549050919050565b601b5460009060ff831610158061426d5750600654155b1561427a57506000612be6565b6001600160a01b0383166000908152601c6020908152604080832080548251818502810185019093528083529192909190849084015b8282101561431b5760008481526020908190206040805160c08101825260068602909201805460ff1683526001808201548486015260028201549284019290925260038101546060840152600481015460808401526005015460a083015290835290920191016142b0565b5050505090506000601b8460ff168154811061434757634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051610120810182526009909302909101805460ff1683526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460e0820181905260089092015461010082015291506143d257600092505050612be6565b60a081015160c0820151431180156143ed575060e082015115155b80156143fd575060008260c00151115b156144595760006144128360c0015143614aed565b905060008360800151826144269190615b44565b90508360e00151600f548261443b9190615b44565b6144459190615a39565b8460a001516144549190615a21565b925050505b6000805b845181101561450457600085828151811061448857634e487b7160e01b600052603260045260246000fd5b602002602001015190508760ff16816000015160ff16146144a957506144f2565b60208101516144b857506144f2565b8060800151600f548583602001516144d09190615b44565b6144da9190615a39565b6144e49190615b63565b6144ee9084615a21565b9250505b806144fc81615ba6565b91505061445d565b509695505050505050565b600e543410156145755760405162461bcd60e51b815260206004820152602b60248201527f73686f756c642070617920736d616c6c2067617320746f20636f6d706f756e6460448201526a081bdc881a185c9d995cdd60aa1b60648201526084016109eb565b600d54600e546040516001600160a01b039092169181156108fc0291906000818181858888f193505050501580156145b1573d6000803e3d6000fd5b50600e543411156117f457600e5433906108fc906145cf9034615b63565b6040518115909202916000818181858888f19350505050158015611563573d6000803e3d6000fd5b601554156146da5760006146096120c1565b905060175481101561461a57506017545b6015546000614627613bc9565b6012546011549192506001600160a01b03918216911614156146505761464d8183615a21565b91505b81601054601754856146629190615b63565b61466c9190615b44565b6146769190615a39565b6014546146839190615a21565b6014556012546011546001600160a01b03908116911614156146d4578181601754856146af9190615b63565b6146b99190615b44565b6146c39190615a39565b6018546146d09190615a21565b6018555b50506017555b6000601b8260ff168154811061470057634e487b7160e01b600052603260045260246000fd5b9060005260206000209060090201905080600601544311158061472557506006810154155b1561472e575050565b6007810154614741574360069091015550565b6000614751826006015443614aed565b905060008260040154826147659190615b44565b90508260070154600f548261477a9190615b44565b6147849190615a39565b83600501546147939190615a21565b6005840155436006840155601a546147ac908290615a21565b601a5550505050565b6000806147c06120c1565b90506017548311156147d25760175492505b808311156147de578092505b5090919050565b6001600160a01b03831661482f576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015614829573d6000803e3d6000fd5b50505050565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb9061485d90859085906004016156c8565b602060405180830381600087803b15801561487757600080fd5b505af115801561488b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148299190615385565b505050565b6148af8363a9059cbb60e01b84846040516024016148d39291906156c8565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614e06565b60095460405163d06ca61f60e01b81526000916001600160a01b03169063d06ca61f9061493d908790879060040161594f565b60006040518083038186803b15801561495557600080fd5b505afa158015614969573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261499191908101906152f2565b9050600081600183516149a49190615b63565b815181106149c257634e487b7160e01b600052603260045260246000fd5b60200260200101519050614a27600960009054906101000a90046001600160a01b03168686600081518110614a0757634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316614ed89092919063ffffffff16565b6009546008546001600160a01b0390911690635c11d7959087906103e890614a4f9086615b44565b614a599190615a39565b8787614a6742610258615a21565b6040518663ffffffff1660e01b8152600401614a87959493929190615968565b600060405180830381600087803b158015614aa157600080fd5b505af1158015611a8e573d6000803e3d6000fd5b6040516001600160a01b03808516602483015283166044820152606481018290526148299085906323b872dd60e01b906084016148d3565b60006007548211614b0957614b028383615b63565b9050612be6565b6007548310614b1a57506000612be6565b82600754614b029190615b63565b806016541115614b40578060165461155f9190615b63565b600060165550565b6001600160a01b0383166000908152601c6020526040812090614b6e8462015180615b44565b614b789042615a21565b82549091506101008110614bbb5760405162461bcd60e51b815260206004820152600a6024820152694d6178207374616b657360b01b60448201526064016109eb565b8254600101835560008390525b8015801590614c1157508183614bdf600184615b63565b81548110614bfd57634e487b7160e01b600052603260045260246000fd5b906000526020600020906006020160030154115b15614cd85782614c22600183615b63565b81548110614c4057634e487b7160e01b600052603260045260246000fd5b9060005260206000209060060201838281548110614c6e57634e487b7160e01b600052603260045260246000fd5b600091825260209091208254600690920201805460ff191660ff909216919091178155600180830154818301556002808401549083015560038084015490830155600480840154908301556005928301549290910191909155614cd19082615b63565b9050614bc8565b6000601b8860ff1681548110614cfe57634e487b7160e01b600052603260045260246000fd5b906000526020600020906009020190506000848381548110614d3057634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201805460ff191660ff8b16178155600281018890556003810185905560018101879055600f54600584015491925090614d789088615b44565b614d829190615a39565b60048201556010546014546001830154614d9c9190615b44565b614da69190615a39565b6005909101555050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000614e5b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614feb9092919063ffffffff16565b8051909150156148af5780806020019051810190614e799190615385565b6148af5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109eb565b801580614f615750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015614f2757600080fd5b505afa158015614f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f5f9190615480565b155b614fcc5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084016109eb565b6148af8363095ea7b360e01b84846040516024016148d39291906156c8565b6060614ffa8484600085615004565b90505b9392505050565b6060824710156150655760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109eb565b843b6150b35760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109eb565b600080866001600160a01b031685876040516150cf9190615698565b60006040518083038185875af1925050503d806000811461510c576040519150601f19603f3d011682016040523d82523d6000602084013e615111565b606091505b509150915061512182828661512c565b979650505050505050565b6060831561513b575081614ffd565b82511561514b5782518084602001fd5b8160405162461bcd60e51b81526004016109eb91906156e1565b8280548282559060005260206000209081019282156151ba579160200282015b828111156151ba57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615185565b506151c69291506151ca565b5090565b5b808211156151c657600081556001016151cb565b600082601f8301126151ef578081fd5b813560206152046151ff836159fd565b6159cc565b80838252828201915082860187848660051b8901011115615223578586fd5b855b8581101561524a57813561523881615c0d565b84529284019290840190600101615225565b5090979650505050505050565b600060208284031215615268578081fd5b8135614ffd81615c0d565b600060208284031215615284578081fd5b8151614ffd81615c0d565b600080604083850312156152a1578081fd5b82356152ac81615c0d565b946020939093013593505050565b600080604083850312156152cc578182fd5b82356152d781615c0d565b915060208301356152e781615c30565b809150509250929050565b60006020808385031215615304578182fd5b825167ffffffffffffffff81111561531a578283fd5b8301601f8101851361532a578283fd5b80516153386151ff826159fd565b80828252848201915084840188868560051b8701011115615357578687fd5b8694505b8385101561537957805183526001949094019391850191850161535b565b50979650505050505050565b600060208284031215615396578081fd5b8151614ffd81615c22565b600080604083850312156153b3578182fd5b82356152ac81615c22565b60008060008060008060c087890312156153d6578182fd5b86356153e181615c0d565b955060208701356153f181615c0d565b9450604087013561540181615c0d565b9350606087013561541181615c0d565b9250608087013567ffffffffffffffff8082111561542d578384fd5b6154398a838b016151df565b935060a089013591508082111561544e578283fd5b5061545b89828a016151df565b9150509295509295509295565b600060208284031215615479578081fd5b5035919050565b600060208284031215615491578081fd5b5051919050565b600080600080600060a086880312156154af578081fd5b8535945060208601356154c181615c0d565b9350604086013567ffffffffffffffff808211156154dd578283fd5b6154e989838a016151df565b945060608801359150808211156154fe578283fd5b5061550b888289016151df565b925050608086013561551c81615c0d565b809150509295509295909350565b600080600080600060a08688031215615541578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060408385031215615576578182fd5b8235915060208301356152e781615c30565b600060208284031215615599578081fd5b8135614ffd81615c30565b6000602082840312156155b5578081fd5b8151614ffd81615c30565b600080604083850312156155d2578182fd5b82356155dd81615c30565b915060208301356152e781615c0d565b600080604083850312156155ff578182fd5b82356152ac81615c30565b60008060008060008060c08789031215615622578384fd5b863561562d81615c30565b9860208801359850604088013597606081013597506080810135965060a00135945092505050565b6000815180845260208085019450808401835b8381101561568d5781516001600160a01b031687529582019590820190600101615668565b509495945050505050565b600082516156aa818460208701615b7a565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6020815260008251806020840152615700816040850160208701615b7a565b601f01601f19169190910160400192915050565b602080825260189082015277141bdbdb081dd85cc8185b1c9958591e481cdd185c9d195960421b604082015260600190565b602080825260139082015272496e76616c6964206465706f7369742066656560681b604082015260600190565b602080825260149082015273496e76616c69642077697468647261772066656560601b604082015260600190565b6020808252600e908201526d1a5b9d985b1a5908185b5bdd5b9d60921b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601f908201527f416d6f756e742073686f756c642062652067726561746f72207468616e203000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b602080825260129082015271496e76616c6964207374616b65207479706560701b604082015260600190565b60208082526016908201527504d75737420626520696e666572696f7220746f2033360541b604082015260600190565b6020808252601a908201527f496e73756666696369656e742072657761726420746f6b656e73000000000000604082015260600190565b858152600060018060a01b03808716602084015260a0604084015261592760a0840187615655565b83810360608501526159398187615655565b9250508084166080840152509695505050505050565b828152604060208201526000614ffa6040830184615655565b85815284602082015260a06040820152600061598760a0830186615655565b6001600160a01b0394909416606083015250608001529392505050565b60ff959095168552602085019390935260408401919091526060830152608082015260a00190565b604051601f8201601f1916810167ffffffffffffffff811182821017156159f5576159f5615bf7565b604052919050565b600067ffffffffffffffff821115615a1757615a17615bf7565b5060051b60200190565b60008219821115615a3457615a34615be1565b500190565b600082615a5457634e487b7160e01b81526012600452602481fd5b500490565b600181815b80851115615a94578160001904821115615a7a57615a7a615be1565b80851615615a8757918102915b93841c9390800290615a5e565b509250929050565b6000614ffd8383600082615ab257506001612be6565b81615abf57506000612be6565b8160018114615ad55760028114615adf57615afb565b6001915050612be6565b60ff841115615af057615af0615be1565b50506001821b612be6565b5060208310610133831016604e8410600b8410161715615b1e575081810a612be6565b615b288383615a59565b8060001904821115615b3c57615b3c615be1565b029392505050565b6000816000190483118215151615615b5e57615b5e615be1565b500290565b600082821015615b7557615b75615be1565b500390565b60005b83811015615b95578181015183820152602001615b7d565b838111156148295750506000910152565b6000600019821415615bba57615bba615be1565b5060010190565b600060ff821660ff811415615bd857615bd8615be1565b60010192915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461156357600080fd5b801515811461156357600080fd5b60ff8116811461156357600080fdfe2a9378497cb60e247e83eb6f2c7c371ba979e24ee25723c2e3275822b317175990890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15a26469706673582212204374d0f0e7f0d8406c5a91342522638e3c09082e5c00e413f888e6864e8f6c3d64736f6c63430008040033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.