Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
PacaFinanceWithBoostAndScheduleUSDC
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; pragma solidity ^0.8.20; interface iPriceOracle { // returns price in USD function getLatestPrice(address token) external view returns (uint256); } // File: paca.sol contract PacaFinanceWithBoostAndScheduleUSDC is Initializable, ReentrancyGuardUpgradeable { using SafeERC20 for IERC20; // Struct Definitions struct Pool { uint256 lockupPeriod; uint256 dailyRewardRate; uint256 totalStaked; uint256 totalRewards; address tokenAddress; } struct Stake { uint256 amount; uint256 lastClaimed; uint256 dailyRewardRate; uint256 unlockTime; bool complete; } struct StakeInput { address user; uint256 amount; uint256 lastClaimed; uint256 unlockTime; uint256 dailyRewardRate; } struct Vesting { uint256 amount; uint256 bonus; uint256 lockedUntil; uint256 claimedAmount; uint256 claimedBonus; uint256 lastClaimed; uint256 createdAt; address token; bool complete; uint256 usdAmount; } struct UnlockStep { uint256 timeOffset; uint256 percentage; } struct BoostRange { uint256 minTokens; uint256 maxTokens; uint256 boostPercentage; } struct WithdrawStake { uint256 stakeId; uint256 amount; uint256 unlockTime; } struct SellStake { uint256 price; uint256 bonusAmount; uint256 amount; uint256 lastClaimed; uint256 dailyRewardRate; } BoostRange[] public boosttiers; // Contract Variables Pool public pool; address public owner; mapping(address => bool) public owners; mapping(address => Stake[]) public stakes; mapping(address => Vesting[]) public vestings; mapping(address => UnlockStep[]) public unlockSchedules; mapping(address => address) public priceOracles; mapping(address => uint256) public dollarsVested; // per user address uint256 public lockupDuration; uint256 public minStakeLock; uint256 private constant BONUS_PERCENTAGE = 10; mapping(address => bool) public authorizedBots; mapping(address => uint256) public vestedTotal; // per vesting token uint256 public unlockDelay; uint256 public withdrawLiabilities; mapping(address => WithdrawStake[]) public withdrawStake; uint256 public restakeBonus; mapping(address => uint256) public addressFixedRate; mapping(address => mapping(uint256 => SellStake)) public sellStakes; uint256 public sellTax; uint256 public sellKickBack; // Events event Staked(address indexed user, uint256 amount); event RewardClaimed(address indexed user, uint256 reward); event VestingCreated(address indexed user, uint256 amount, uint256 bonus); event VestingClaimed(address indexed user, uint256 amount, uint256 bonus); event BonusClaimed(address indexed user, uint256 bonus); event PoolUpdated(uint256 lockupPeriod, uint256 dailyRewardRate); event UnlockScheduleSet(address indexed token); event FundsWithdrawn(address indexed owner, address indexed token, uint256 amount); event RewardsDeposited(uint256 amount); event CompoundRewards(address indexed user, uint256 amount); event MinStakeLockUpdated(uint256 amount); event StakeWithdrawn(address indexed user, uint256 amount, uint256 stakeId); event StakeUpForSale(address indexed user, uint256 saleAmount, uint256 stakeId); event StakeSaleCancelled(address indexed user, uint256 stakeId); event StakeSold(address indexed seller, address indexed buyer,uint256 saleAmount, uint256 stakeId); // Modifiers modifier onlyOwner() { require(owners[msg.sender], "Not authorized"); _; } modifier onlyBot() { require(authorizedBots[msg.sender], "Caller is not an authorized bot"); _; } function initialize() public initializer { __ReentrancyGuard_init(); // Initialize ReentrancyGuardUpgradeable owner = 0x41970Ce76b656030A79E7C1FA76FC4EB93980255; owners[0x41970Ce76b656030A79E7C1FA76FC4EB93980255] = true; lockupDuration = 250 days; minStakeLock = 16 ether; pool.tokenAddress = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913; pool.lockupPeriod = 250 * 1 days; pool.dailyRewardRate = 33; // Push boost tiers in ascending order (amounts in wei, boosts as percentages) boosttiers.push(BoostRange(3500 * 1e18, 9999 * 1e18, 1)); // $3,500 to $9,999 = 0.01 boost boosttiers.push(BoostRange(10000 * 1e18, 19999 * 1e18, 2)); // $10,000 to $19,999 = 0.02 boost boosttiers.push(BoostRange(20000 * 1e18, 29999 * 1e18, 3)); // $20,000 to $29,999 = 0.03 boost boosttiers.push(BoostRange(30000 * 1e18, 39999 * 1e18, 4)); // $30,000 to $39,999 = 0.04 boost boosttiers.push(BoostRange(40000 * 1e18, 59999 * 1e18, 5)); // $40,000 to $59,999 = 0.05 boost boosttiers.push(BoostRange(60000 * 1e18, 79999 * 1e18, 6)); // $60,000 to $79,999 = 0.06 boost boosttiers.push(BoostRange(80000 * 1e18, 99999 * 1e18, 8)); // $80,000 to $99,999 = 0.08 boost boosttiers.push(BoostRange(100000 * 1e18, type(uint256).max, 10)); // $100,000+ = 0.1 boost // Price oracle for a specific tokens // priceOracles[0x940181a94A35A4569E4529A3CDfB74e38FD98631] = 0x0Dde1b42F7B3891C9731280A74081501729A73c5; authorizedBots[0xbf12D3b827a230F7390EbCc9b83b289FdC98ba81] = true; authorizedBots[0x7c40f272570fdf9549d6f67493aC250a1DB52F27] = true; unlockDelay = 60 * 60 * 36; restakeBonus = 3; } // Ownership Management function addOwner(address _newOwner) external onlyOwner { require(!owners[_newOwner], "Already an owner"); owners[_newOwner] = true; } function removeOwner(address _owner) external onlyOwner { require(owners[_owner], "Not an owner"); require(_owner != msg.sender, "Cannot remove yourself"); owners[_owner] = false; } /// @notice Function to add a bot to the list (only callable by the contract owner) function addBot(address bot) external onlyOwner { require(bot != address(0), "Invalid address"); authorizedBots[bot] = true; } /// @notice Function to remove a bot from the list (only callable by the contract owner) function removeBot(address bot) external onlyOwner { require(bot != address(0), "Invalid address"); authorizedBots[bot] = false; } // Admin Functions function updatePool(uint256 _lockupPeriod, uint256 _dailyRewardRate) external onlyOwner { pool.lockupPeriod = _lockupPeriod * 1 days; pool.dailyRewardRate = _dailyRewardRate; emit PoolUpdated(_lockupPeriod, _dailyRewardRate); } function depositRewards(uint256 _amount) external onlyOwner { IERC20(pool.tokenAddress).safeTransferFrom(msg.sender, address(this), _amount); pool.totalRewards = pool.totalRewards + _amount; emit RewardsDeposited(_amount); } function updateStakeMin(uint256 _amount) external onlyOwner { minStakeLock = _amount; emit MinStakeLockUpdated(_amount); } function updateUnlockDelay(uint256 _delay) external onlyOwner { unlockDelay = _delay; } function updateRestakeBonus(uint256 _newBonus) external onlyOwner { restakeBonus = _newBonus; } /// @notice New Stake Sell Tax /// @param _newTax The rate expressed in 2 digits, ex: 20 function updateSellTax(uint256 _newTax) external onlyOwner { sellTax = _newTax; } /// @notice New Stake Sell kickback to the buyer /// @param _newKickback The rate expressed in 2 digits, ex: 5 function updatesellKickBack(uint256 _newKickback) external onlyOwner { sellKickBack = _newKickback; } /// @notice Function to add an address to have a fixed daily reward (only callable by the contract owner) /// @param _addr The address to give a fixed rate /// @param _rate The fixed rate expressed in 2 digits, ex: 40 function addFixedRate(address _addr, uint _rate) external onlyOwner { require(_addr != address(0), "Invalid address"); addressFixedRate[_addr] = _rate; } /// @notice Function to remove an address' fixed daily reward (only callable by the contract owner) /// @param _addr The address to 0 out function removeFixedRate(address _addr) external onlyOwner { require(_addr != address(0), "Invalid address"); addressFixedRate[_addr] = 0; } /// @notice Add or edit a tier range function addOrEditTier(uint256 minTokens, uint256 maxTokens, uint256 boostPercentage) public onlyOwner { require(minTokens < maxTokens, "Invalid range: minTokens must be < maxTokens"); require(!rangesOverlap(minTokens, maxTokens), "Range overlaps with existing tiers"); // Check if editing an existing range for (uint256 i = 0; i < boosttiers.length; ++i) { if (boosttiers[i].minTokens == minTokens && boosttiers[i].maxTokens == maxTokens) { // Edit the existing range boosttiers[i].boostPercentage = boostPercentage; return; } } // Add new range boosttiers.push(BoostRange(minTokens, maxTokens, boostPercentage)); // Sort the ranges after adding sortRanges(); } // Check for range overlap function rangesOverlap(uint256 minTokens, uint256 maxTokens) internal view returns (bool) { for (uint256 i = 0; i < boosttiers.length; ++i) { if (minTokens <= boosttiers[i].maxTokens && maxTokens >= boosttiers[i].minTokens) { return true; } } return false; } /// @notice Sort ranges by minTokens function sortRanges() internal { for (uint256 i = 0; i < boosttiers.length; ++i) { for (uint256 j = i + 1; j < boosttiers.length; j++) { if (boosttiers[i].minTokens > boosttiers[j].minTokens) { // Swap ranges BoostRange memory temp = boosttiers[i]; boosttiers[i] = boosttiers[j]; boosttiers[j] = temp; } } } } /// @notice Remove a range by index function removeTier(uint256 index) external onlyOwner { require(index < boosttiers.length, "Index out of bounds"); for (uint256 i = index; i < boosttiers.length - 1; ++i) { boosttiers[i] = boosttiers[i + 1]; } boosttiers.pop(); } function withdrawFromStakingPool(uint256 _amount) external onlyOwner { IERC20(pool.tokenAddress).safeTransfer(msg.sender, _amount); emit FundsWithdrawn(msg.sender, pool.tokenAddress, _amount); } function withdrawFromVestingPool(address _token, uint256 _amount) external onlyOwner { IERC20(_token).safeTransfer(msg.sender, _amount); emit FundsWithdrawn(msg.sender, _token, _amount); } function setUnlockScheduleByPercentage( address _token, uint256 _lockTime, // Total lock time in seconds uint256 _percentagePerStep // Percentage unlocked per step (in basis points, e.g., 100 = 1%) ) external onlyOwner { require(_lockTime != 0, "Lock time must be greater than zero"); require(_percentagePerStep != 0, "Percentage per step must be greater than zero"); uint256 totalPercentage = 10000; // 100% in basis points require(totalPercentage % _percentagePerStep == 0, "Percentage must divide 100% evenly"); uint256 steps = totalPercentage / _percentagePerStep; // Number of steps uint256 stepTime = _lockTime / steps; // Time interval per step delete unlockSchedules[_token]; // Clear existing schedule for this token for (uint256 i = 1; i <= steps; ++i) { unlockSchedules[_token].push(UnlockStep({ timeOffset: stepTime * i, // Time offset for this step percentage: _percentagePerStep })); } emit UnlockScheduleSet(_token); } /// @notice Get the boost percentage for a given token amount function getBoost(uint256 depositedTokens) public view returns (uint256) { for (uint256 i = 0; i < boosttiers.length; ++i) { if (depositedTokens >= boosttiers[i].minTokens && depositedTokens <= boosttiers[i].maxTokens) { return boosttiers[i].boostPercentage; } } return 0; // Default boost if no range matches } /// @notice This function will end and clear a user's stakes. /// @dev Only to be used by bots in emergencies /// @param user The user whose stakes will be ended and 0'd function clearStakes(address user) external onlyBot { uint256 clearedStakes = 0; for (uint256 i = 0; i < stakes[user].length; ++i) { Stake storage stake = stakes[user][i]; clearedStakes = clearedStakes + stake.amount; stake.amount = 0; stake.complete = true; } pool.totalStaked = pool.totalStaked - clearedStakes; } /// @notice This function will end and clear a user's withdraw stakes. /// @dev Only to be used by bots in emergencies /// @param user The user whose withdraw stakes will be 0'd function clearWithdrawStakes(address user) external onlyBot { uint256 clearedStakes = 0; for (uint256 i = 0; i < withdrawStake[user].length; ++i) { WithdrawStake storage stake = withdrawStake[user][i]; clearedStakes = clearedStakes + stake.amount; stake.amount = 0; } withdrawLiabilities -= clearedStakes; } function createStake(uint256 _amount) external { // Scale up for wei comparison, USDC is 1e6 require(_amount * 1e12 > minStakeLock, "Amount must be greater minStakeLock"); // Transfer tokens from the user into the contract IERC20(pool.tokenAddress).safeTransferFrom(msg.sender, address(this), _amount); // Check if user has a fixed reward rate set uint256 finalRewardRate; if (addressFixedRate[msg.sender] > 0) { // Use the fixed rate finalRewardRate = addressFixedRate[msg.sender]; } else { // Default logic, restake = false finalRewardRate = getUserRewardRate(msg.sender, false); } // Create the stake stakes[msg.sender].push(Stake({ amount: _amount, lastClaimed: block.timestamp, dailyRewardRate: finalRewardRate, unlockTime: block.timestamp + pool.lockupPeriod, complete: false })); // Update total staked pool.totalStaked += _amount; emit Staked(msg.sender, _amount); } /// @notice Restake an expired stake with a bonus daily reward function restake(uint256 _stakeIndex, uint256 _restakePercentage) nonReentrant external { require(_restakePercentage <= 100, "Invalid restake percentage"); Stake storage stake = stakes[msg.sender][_stakeIndex]; // Ensure there is a stake to claim require(stake.amount != 0, "No amount to claim"); require(block.timestamp >= stake.unlockTime, "Stake is still locked"); uint256 _amount = stake.amount; uint rewards = getPoolRewards(msg.sender, _stakeIndex); _amount = _amount + rewards; uint256 restake_amount = (_amount * _restakePercentage) / 100; uint256 withdraw_amount = _amount - restake_amount; // Update state before external calls stake.amount = 0; stake.complete = true; // Process withdraw if (withdraw_amount > 0) { withdrawLiabilities += withdraw_amount; if (pool.totalStaked >= withdraw_amount) { pool.totalStaked -= withdraw_amount; } else { pool.totalStaked = 0; } // Create temporary the stake for the user to delay withdraw withdrawStake[msg.sender].push(WithdrawStake({ stakeId: _stakeIndex, amount: withdraw_amount, unlockTime: block.timestamp + unlockDelay })); // Emit a detailed event emit RewardClaimed(msg.sender, withdraw_amount); } // Process restake if (restake_amount > 0) { // Check if user has a fixed reward rate set uint256 finalRewardRate; if (addressFixedRate[msg.sender] > 0) { // Use the fixed rate finalRewardRate = addressFixedRate[msg.sender]; } else { // restake = true finalRewardRate = getUserRewardRate(msg.sender, true); } stakes[msg.sender].push(Stake({ amount: restake_amount, lastClaimed: block.timestamp, dailyRewardRate: finalRewardRate, unlockTime: block.timestamp + pool.lockupPeriod, complete: false })); emit Staked(msg.sender, restake_amount); } } function createStakeForUser(address _user, uint256 _amount) external onlyOwner { require(_amount != 0, "Invalid amount"); stakes[_user].push(Stake({ amount: _amount, lastClaimed: block.timestamp, dailyRewardRate: pool.dailyRewardRate, unlockTime: block.timestamp + pool.lockupPeriod, complete: false })); pool.totalStaked = pool.totalStaked + _amount; emit Staked(_user, _amount); } function createStakes(StakeInput[] calldata stakesInput) external onlyBot payable { uint256 totalLength = stakesInput.length; for (uint256 i; i < totalLength;) { StakeInput calldata stakeInput = stakesInput[i]; // Update pool total pool.totalStaked = pool.totalStaked + stakeInput.amount; // Create the stake for the user stakes[stakeInput.user].push(Stake({ amount: stakeInput.amount, lastClaimed: stakeInput.lastClaimed, dailyRewardRate: stakeInput.dailyRewardRate, unlockTime: stakeInput.unlockTime, complete: false })); unchecked { ++i; } } } function getPoolRewards(address _user, uint _stakeIndex) public view returns (uint256) { Stake storage stake = stakes[_user][_stakeIndex]; uint256 elapsedTime = block.timestamp - stake.lastClaimed; uint256 rewards = (stake.amount * stake.dailyRewardRate * elapsedTime) / 1 days / 10000; return rewards; } function getUserRewardRate(address _user, bool isRestake) public view returns (uint256) { uint256 finalRewardRate = pool.dailyRewardRate + getBoost(dollarsVested[_user]); if (isRestake) { finalRewardRate += restakeBonus; } return finalRewardRate; } function claimRewards() external nonReentrant { uint256 totalReward = 0; for (uint256 i = 0; i < stakes[msg.sender].length; ++i) { Stake storage stake = stakes[msg.sender][i]; if (stake.amount > 0) { uint rewards = getPoolRewards(msg.sender, i); totalReward = totalReward + rewards; stake.lastClaimed = block.timestamp; } } require(totalReward != 0, "No rewards to claim"); require(pool.totalRewards >= totalReward, "Insufficient rewards in the pool"); pool.totalRewards = pool.totalRewards - totalReward; IERC20(pool.tokenAddress).safeTransfer(msg.sender, totalReward); emit RewardClaimed(msg.sender, totalReward); } function claimStake(uint256 _stakeIndex) external nonReentrant { // Ensure the stake index is valid require(_stakeIndex < stakes[msg.sender].length, "Invalid stake index"); // Load the stake Stake storage stake = stakes[msg.sender][_stakeIndex]; uint256 _amount = stake.amount; uint rewards = getPoolRewards(msg.sender, _stakeIndex); _amount = _amount + rewards; // Ensure there is a stake to claim require(_amount != 0, "No amount to claim"); // Ensure the stake is unlocked (if using lockup periods) require(block.timestamp >= stake.unlockTime, "Stake is still locked"); // Update state before external calls stake.amount = 0; stake.complete = true; withdrawLiabilities += _amount; if (pool.totalStaked >= _amount) { pool.totalStaked -= _amount; } else { pool.totalStaked = 0; } // Create temporary the stake for the user to delay withdraw withdrawStake[msg.sender].push(WithdrawStake({ stakeId: _stakeIndex, amount: _amount, unlockTime: block.timestamp + unlockDelay })); // Emit a detailed event emit RewardClaimed(msg.sender, _amount); } /** * @notice Withdraw a staked amount after its unlock time has passed. * @dev Locates the stake by `_stakeIndex`, checks that it's unlocked and non-zero, * and transfers tokens to the caller. For vesting stakes (where `_stakeIndex` >= 1e6), * the stored amount (in 1e18 decimals) is scaled to USDC's 1e6 decimals by dividing by 1e12. * * Requirements: * - Caller must have at least one stake. * - The stake must exist, be unlocked, and have a non-zero amount. * - The contract must have sufficient token balance. * * @param _stakeIndex The identifier of the stake to withdraw. */ function withdraw(uint256 _stakeIndex) external nonReentrant { uint256 _amount = 0; WithdrawStake[] storage userStakes = withdrawStake[msg.sender]; require(userStakes.length > 0, "No stakes available for withdrawal"); for (uint256 i = 0; i < userStakes.length; ++i) { WithdrawStake storage stake = userStakes[i]; if (stake.stakeId == _stakeIndex) { require(stake.amount != 0, "Stake already withdrawn or does not exist"); require(block.timestamp >= stake.unlockTime, "Withdraw Stake is still locked"); _amount = stake.amount; // Convert vesting stake amount to USDC decimals. if (_stakeIndex >= 1e6) { _amount = _amount / 1e12; } uint256 poolBalance = IERC20(pool.tokenAddress).balanceOf(address(this)); require(poolBalance >= _amount, "Insufficient rewards in the pool"); // Update state before external calls // withdrawLiabilities is in 1e18, deduct original amount withdrawLiabilities -= stake.amount; stake.amount = 0; // Transfer tokens IERC20(pool.tokenAddress).safeTransfer(msg.sender, _amount); emit StakeWithdrawn(msg.sender, _amount, _stakeIndex); return; } } // Revert if no matching stake was found revert("Invalid stake index"); } function compoundAllRewards() external { uint256 totalReward = 0; for (uint256 i = 0; i < stakes[msg.sender].length; ++i) { Stake storage stake = stakes[msg.sender][i]; if (stake.amount > 0) { uint rewards = getPoolRewards(msg.sender, i); totalReward = totalReward + rewards; stake.lastClaimed = block.timestamp; } } require(totalReward > minStakeLock, "Not enough to compound"); stakes[msg.sender].push(Stake({ amount: totalReward, lastClaimed: block.timestamp, dailyRewardRate: pool.dailyRewardRate + getBoost(dollarsVested[msg.sender]), unlockTime: block.timestamp + pool.lockupPeriod, complete: false })); pool.totalStaked = pool.totalStaked + totalReward; emit CompoundRewards(msg.sender, totalReward); } function createVesting(address _token, uint256 _amount) external { require(_amount != 0, "Amount must be greater than zero"); address oracle = priceOracles[_token]; require(oracle != address(0), "Price oracle not set for this token"); IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount); uint256 bonus = (_amount * BONUS_PERCENTAGE) / 100; uint256 usdPrice = (iPriceOracle(priceOracles[_token]).getLatestPrice(_token) * _amount) / 1e18; require(usdPrice > minStakeLock, "Amount must be greater minStakeLock"); // Update user's dollarsVested dollarsVested[msg.sender] += usdPrice; // Update token's vestedTotal vestedTotal[_token] += _amount; vestings[msg.sender].push(Vesting({ amount: _amount, bonus: bonus, lockedUntil: block.timestamp + lockupDuration, claimedAmount: 0, claimedBonus: 0, lastClaimed: block.timestamp, createdAt: block.timestamp, token: _token, complete: false, usdAmount: usdPrice })); emit VestingCreated(msg.sender, _amount, bonus); } function getUnlockedVesting(address _user, uint256 _vestingIndex) public view returns (uint256) { Vesting storage vesting = vestings[_user][_vestingIndex]; uint256 timeElapsed = block.timestamp - vesting.createdAt; address token = vesting.token; uint256 unlockedAmount = 0; for (uint256 i = 0; i < unlockSchedules[token].length; ++i) { UnlockStep storage step = unlockSchedules[token][i]; uint256 timeTier = step.timeOffset; uint256 percentage = step.percentage; if (timeElapsed >= timeTier) { unlockedAmount = unlockedAmount + ((vesting.amount * percentage) / 10000); } } return unlockedAmount; } function getVestingSchedule(address _user, uint256 _vestingIndex) public view returns (uint256[] memory, uint256[] memory) { Vesting storage vesting = vestings[_user][_vestingIndex]; address token = vesting.token; uint256 scheduleLength = unlockSchedules[token].length; uint256[] memory unlockTimestamps = new uint256[](scheduleLength); uint256[] memory unlockPercentages = new uint256[](scheduleLength); for (uint256 i = 0; i < scheduleLength; ++i) { UnlockStep storage step = unlockSchedules[token][i]; // Calculate the absolute unlock timestamp unlockTimestamps[i] = vesting.createdAt + step.timeOffset; unlockPercentages[i] = step.percentage; // Percentage is stored as scaled by 10000 (e.g., 2500 = 25%) } return (unlockTimestamps, unlockPercentages); } function getUnlockedVestingBonus(address _user, uint256 _vestingIndex) public view returns (uint256) { Vesting storage vesting = vestings[_user][_vestingIndex]; uint256 timeElapsed = block.timestamp - vesting.createdAt; address token = vesting.token; uint256 unlockedAmount = 0; for (uint256 i = 0; i < unlockSchedules[token].length; ++i) { UnlockStep storage step = unlockSchedules[token][i]; uint256 timeTier = step.timeOffset; uint256 percentage = step.percentage; uint256 maxBonusAmount = (vesting.usdAmount * BONUS_PERCENTAGE) / 100; if (timeElapsed >= timeTier) { unlockedAmount = unlockedAmount + ((maxBonusAmount * percentage) / 10000); } } return unlockedAmount; } function claimVesting(uint256 _vestingIndex) external nonReentrant { Vesting storage vesting = vestings[msg.sender][_vestingIndex]; require(vesting.complete == false, "Stake is Complete"); uint256 maxClaim = getUnlockedVesting(msg.sender, _vestingIndex); require(maxClaim >= vesting.claimedAmount, "Invalid claim amount"); uint256 amountToClaim = maxClaim - vesting.claimedAmount; require(amountToClaim != 0, "No vested amount to claim"); vesting.claimedAmount = vesting.claimedAmount + amountToClaim; if (vesting.claimedAmount >= vesting.amount) { vesting.complete = true; } // Update user's dollarsVested if (dollarsVested[msg.sender] > 0) { uint256 usdPrice = (iPriceOracle(priceOracles[vesting.token]).getLatestPrice(vesting.token) * amountToClaim) / 1e18; if (usdPrice >= dollarsVested[msg.sender]) { dollarsVested[msg.sender] = 0; } else { dollarsVested[msg.sender] -= usdPrice; } } vestedTotal[vesting.token] -= amountToClaim; IERC20(vesting.token).safeTransfer(msg.sender, amountToClaim); emit VestingClaimed(msg.sender, amountToClaim, 0); } function claimAllVestingByToken(address _token) external nonReentrant { uint256 totalReward = 0; uint256 vestingsProcessed = 0; for (uint256 i = 0; i < vestings[msg.sender].length; ++i) { Vesting storage vesting = vestings[msg.sender][i]; if (vesting.token == _token && !vesting.complete) { uint256 maxClaim = getUnlockedVesting(msg.sender, i); require(maxClaim >= vesting.claimedAmount, "Invalid claim amount"); uint256 amountToClaim = maxClaim - vesting.claimedAmount; if (amountToClaim > 0) { vesting.claimedAmount = vesting.claimedAmount + amountToClaim; totalReward = totalReward + amountToClaim; vesting.lastClaimed = block.timestamp; // Mark vesting as complete if fully claimed if (vesting.claimedAmount >= vesting.amount) { vesting.complete = true; } vestingsProcessed++; } } } require(totalReward != 0, "No rewards to claim"); // Update user's dollarsVested if (dollarsVested[msg.sender] > 0) { uint256 usdPrice = (iPriceOracle(priceOracles[_token]).getLatestPrice(_token) * totalReward) / 1e18; if (usdPrice >= dollarsVested[msg.sender]) { dollarsVested[msg.sender] = 0; } else { dollarsVested[msg.sender] -= usdPrice; } } // Ensure the contract has enough balance to fulfill the claim uint256 poolBalance = IERC20(_token).balanceOf(address(this)); require(poolBalance >= totalReward, "Insufficient rewards in the pool"); // Update vesting total vestedTotal[_token] -= totalReward; // Transfer the aggregated reward IERC20(_token).safeTransfer(msg.sender, totalReward); emit RewardClaimed(msg.sender, totalReward); } function claimBonus(uint256 _vestingIndex) external nonReentrant { Vesting storage vesting = vestings[msg.sender][_vestingIndex]; uint256 maxBonus = getUnlockedVestingBonus(msg.sender, _vestingIndex); require(maxBonus >= vesting.claimedBonus, "Invalid claim amount"); uint256 bonusToClaim = maxBonus - vesting.claimedBonus; require(bonusToClaim != 0, "No vested amount to claim"); vesting.claimedBonus = vesting.claimedBonus + bonusToClaim; withdrawLiabilities += bonusToClaim; // IERC20(vesting.token).safeTransfer(msg.sender, bonusToClaim); // Create temporary the stake for the user to delay withdraw. // Add 1e6 to the vesting index to distinguish them from normal stakes. withdrawStake[msg.sender].push(WithdrawStake({ stakeId: _vestingIndex + 1e6, amount: bonusToClaim, unlockTime: block.timestamp + unlockDelay })); emit BonusClaimed(msg.sender, bonusToClaim); } function setPriceOracle(address _token, address _oracle) external onlyOwner { priceOracles[_token] = _oracle; } function viewRewards(address _user) external view returns (uint256) { uint256 totalReward = 0; for (uint256 i = 0; i < stakes[_user].length; ++i) { uint rewards = getPoolRewards(_user, i); totalReward = totalReward + rewards; } return totalReward; } /// @notice View function to get all stakes for a specific address function getStakes(address user) external view returns (Stake[] memory) { return stakes[user]; } /// @notice View function to get all vestings for a specific address function getVestings(address user) external view returns (Vesting[] memory) { return vestings[user]; } /// @notice View to monitor contract pool deficits function getPoolStatus() external view returns (uint256) { uint256 poolBalance = IERC20(pool.tokenAddress).balanceOf(address(this)); // If the balance is greater than or equal to liabilities, return 0 if (poolBalance >= withdrawLiabilities) { return 0; } // Otherwise, return the deficit (amount needed to cover liabilities) return withdrawLiabilities - poolBalance; } /** * @notice Returns the vested amounts and USD values for an array of tokens. * @param _tokens The array of token addresses to evaluate. * @return amounts The array of vested amounts for each token. * @return usdValues The array of USD values for each token’s vested amount. * @return totalUsd The total USD value of all vested tokens in the array. */ function getVestedTotals(address[] calldata _tokens) external view returns ( uint256[] memory amounts, uint256[] memory usdValues, uint256 totalUsd ) { uint256 length = _tokens.length; amounts = new uint256[](length); usdValues = new uint256[](length); for (uint256 i = 0; i < length; i++) { address token = _tokens[i]; // 1. Get the total amount vested for this token. uint256 tokenAmount = vestedTotal[token]; amounts[i] = tokenAmount; // 2. Query the oracle for this token’s USD price. // Assumes the oracle returns a price scaled by 1e18. uint256 price = iPriceOracle(priceOracles[token]).getLatestPrice(token); // 3. Calculate the vested USD value: (price * amount) / 1e18 uint256 valueInUsd = (price * tokenAmount) / 1e18; usdValues[i] = valueInUsd; // 4. Accumulate the total USD amount totalUsd += valueInUsd; } return (amounts, usdValues, totalUsd); } /// @notice Returns the total USD value of the user's unclaimed, uncomplete, stake amounts, based on current token prices from the oracle. /// @return totalUsd The total unclaimed stake value, in USD (1e18 precision). function getUserTotalUnclaimedUsdValue(address user) external view returns (uint256 totalUsd) { uint256 length = vestings[user].length; for (uint256 i = 0; i < length; i++) { Vesting memory v = vestings[user][i]; if (!v.complete) { uint256 tokenPrice = iPriceOracle(priceOracles[v.token]).getLatestPrice(v.token); // The unclaimed portion of the stake uint256 unclaimedAmount = v.amount - v.claimedAmount; // Convert unclaimed tokens to USD value uint256 stakeUsd = (tokenPrice * unclaimedAmount) / 1e18; totalUsd += stakeUsd; } } return totalUsd; } /// @notice Function that lets you look up an address’s stake by stakeId. /// @param user The address to evaluate. /// @param _stakeId The stakeId of the ORIGINAL stake that is waiting to be unlocked function getWithdrawStake(address user, uint256 _stakeId) external view returns (WithdrawStake memory) { WithdrawStake[] storage userStakes = withdrawStake[user]; for (uint256 i = 0; i < userStakes.length; i++) { if (userStakes[i].stakeId == _stakeId) { return userStakes[i]; } } revert("WithdrawStake with the specified stakeId not found for this user."); } /// @notice Function that lets you look up an address’s stake by vestingId. /// @param user The address to evaluate. /// @param _vestingId The vestingId of the ORIGINAL vest that is waiting to be unlocked function getVestingWithdrawStake(address user, uint256 _vestingId) external view returns (WithdrawStake memory) { WithdrawStake[] storage userStakes = withdrawStake[user]; uint256 boostedVestingId = _vestingId + 1e6; for (uint256 i = 0; i < userStakes.length; i++) { if (userStakes[i].stakeId == boostedVestingId) { return userStakes[i]; } } revert("WithdrawStake with the specified stakeId not found for this user."); } /// @notice Function that returns an array of all the user's withdrawStakes. /// @param user The address to evaluate. /// @return An array of WithdrawStake for the given user. function getAllWithdrawStakes(address user) external view returns (WithdrawStake[] memory) { return withdrawStake[user]; } /// @notice Function to put a stake for sale. /// Sets the original stake amount to 0 to prevent any alterations while for sale. /// @param _stakeId The stake to sell. /// @param price The price of the stake. function sellStake(uint256 _stakeId, uint256 price) external { Stake storage stake = stakes[msg.sender][_stakeId]; require(!stake.complete, "Stake already complete"); require(stake.amount != 0, "Stake amount is 0"); // Ensure the stake isn't already on sale. require(sellStakes[msg.sender][_stakeId].amount == 0, "Stake already on sale"); // Create a SellStake entry directly in the mapping. sellStakes[msg.sender][_stakeId] = SellStake({ price: price, bonusAmount: (price * sellKickBack) / 100, amount: stake.amount, lastClaimed: stake.lastClaimed, dailyRewardRate: stake.dailyRewardRate }); // Lock the original stake by setting its amount to 0. stake.amount = 0; emit StakeUpForSale(msg.sender, price, _stakeId); } /// @notice Function to cancel a sell stake. /// Restores the stake amount to the original stake and removes the sell stake. /// @param _stakeId The stake ID to cancel the sale. function cancelSellStake(uint256 _stakeId) external { SellStake storage sellStakeEntry = sellStakes[msg.sender][_stakeId]; require(sellStakeEntry.amount != 0, "Sell stake not found"); // Access the original stake. Stake storage stake = stakes[msg.sender][_stakeId]; require(stake.amount == 0, "Stake not in sell state"); // Restore the original stake's amount. stake.amount = sellStakeEntry.amount; delete sellStakes[msg.sender][_stakeId]; emit StakeSaleCancelled(msg.sender, _stakeId); } /// @notice Function to update the price of a stake that is for sale. /// @param _stakeId The stake ID to update. /// @param newPrice The new price of the stake. function updateSellStake(uint256 _stakeId, uint256 newPrice) external { SellStake storage sellStakeEntry = sellStakes[msg.sender][_stakeId]; require(sellStakeEntry.amount != 0, "Sell stake not found"); sellStakeEntry.bonusAmount = (newPrice * sellKickBack) / 100; sellStakeEntry.price = newPrice; emit StakeUpForSale(msg.sender, newPrice, _stakeId); } /// @notice Buys a sell stake. /// Transfers the sale price from the buyer (using safeTransferFrom), /// pays the seller (applying the sellTax), /// creates a new stake for the buyer (amount = original amount + bonus), /// marks the original stake as complete, /// and sets the new stake's unlock time. /// @param seller The address of the seller. /// @param _stakeId The original stake id associated with the sell stake. function buySellStake(address seller, uint256 _stakeId) external { SellStake storage sellStakeEntry = sellStakes[seller][_stakeId]; require(sellStakeEntry.amount != 0, "Sell stake not available"); // Transfer the sale price from the buyer to this contract. IERC20(pool.tokenAddress).safeTransferFrom(msg.sender, address(this), sellStakeEntry.price); // Calculate the seller's payment using the sell tax. uint256 sellerPayment = (sellStakeEntry.price * sellTax) / 100; IERC20(pool.tokenAddress).safeTransfer(seller, sellerPayment); // Mark the original stake as complete. Stake storage originalStake = stakes[seller][_stakeId]; originalStake.complete = true; // Create the new stake for the buyer using the inline push pattern. stakes[msg.sender].push(Stake({ amount: sellStakeEntry.amount + sellStakeEntry.bonusAmount, lastClaimed: sellStakeEntry.lastClaimed, dailyRewardRate: sellStakeEntry.dailyRewardRate, unlockTime: block.timestamp + pool.lockupPeriod, complete: false })); // Remove the sell stake listing. delete sellStakes[seller][_stakeId]; emit StakeSold(seller, msg.sender, sellStakeEntry.price, _stakeId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @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 EIP-1153 (transient storage) is available on the chain you're deploying at, * consider using {ReentrancyGuardTransient} instead. * * 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 ReentrancyGuardUpgradeable is Initializable { // 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; /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard struct ReentrancyGuardStorage { uint256 _status; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) { assembly { $.slot := ReentrancyGuardStorageLocation } } /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); $._status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // On the first call to nonReentrant, _status will be NOT_ENTERED if ($._status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail $._status = ENTERED; } function _nonReentrantAfter() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) $._status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); return $._status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC165} from "./IERC165.sol"; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. * * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC-20 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 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @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). * * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @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). * * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"bonus","type":"uint256"}],"name":"BonusClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CompoundRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MinStakeLockUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lockupPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dailyRewardRate","type":"uint256"}],"name":"PoolUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"stakeId","type":"uint256"}],"name":"StakeSaleCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"saleAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakeId","type":"uint256"}],"name":"StakeSold","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"saleAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakeId","type":"uint256"}],"name":"StakeUpForSale","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakeId","type":"uint256"}],"name":"StakeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"UnlockScheduleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bonus","type":"uint256"}],"name":"VestingClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bonus","type":"uint256"}],"name":"VestingCreated","type":"event"},{"inputs":[{"internalType":"address","name":"bot","type":"address"}],"name":"addBot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"},{"internalType":"uint256","name":"_rate","type":"uint256"}],"name":"addFixedRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minTokens","type":"uint256"},{"internalType":"uint256","name":"maxTokens","type":"uint256"},{"internalType":"uint256","name":"boostPercentage","type":"uint256"}],"name":"addOrEditTier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"addOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"addressFixedRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"authorizedBots","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"boosttiers","outputs":[{"internalType":"uint256","name":"minTokens","type":"uint256"},{"internalType":"uint256","name":"maxTokens","type":"uint256"},{"internalType":"uint256","name":"boostPercentage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"_stakeId","type":"uint256"}],"name":"buySellStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakeId","type":"uint256"}],"name":"cancelSellStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"claimAllVestingByToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vestingIndex","type":"uint256"}],"name":"claimBonus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakeIndex","type":"uint256"}],"name":"claimStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vestingIndex","type":"uint256"}],"name":"claimVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"clearStakes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"clearWithdrawStakes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"compoundAllRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"createStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"createStakeForUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lastClaimed","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"},{"internalType":"uint256","name":"dailyRewardRate","type":"uint256"}],"internalType":"struct PacaFinanceWithBoostAndScheduleUSDC.StakeInput[]","name":"stakesInput","type":"tuple[]"}],"name":"createStakes","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"createVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"dollarsVested","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getAllWithdrawStakes","outputs":[{"components":[{"internalType":"uint256","name":"stakeId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"internalType":"struct PacaFinanceWithBoostAndScheduleUSDC.WithdrawStake[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"depositedTokens","type":"uint256"}],"name":"getBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_stakeIndex","type":"uint256"}],"name":"getPoolRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolStatus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getStakes","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lastClaimed","type":"uint256"},{"internalType":"uint256","name":"dailyRewardRate","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"},{"internalType":"bool","name":"complete","type":"bool"}],"internalType":"struct PacaFinanceWithBoostAndScheduleUSDC.Stake[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_vestingIndex","type":"uint256"}],"name":"getUnlockedVesting","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_vestingIndex","type":"uint256"}],"name":"getUnlockedVestingBonus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"bool","name":"isRestake","type":"bool"}],"name":"getUserRewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserTotalUnclaimedUsdValue","outputs":[{"internalType":"uint256","name":"totalUsd","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"getVestedTotals","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"usdValues","type":"uint256[]"},{"internalType":"uint256","name":"totalUsd","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_vestingIndex","type":"uint256"}],"name":"getVestingSchedule","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"_vestingId","type":"uint256"}],"name":"getVestingWithdrawStake","outputs":[{"components":[{"internalType":"uint256","name":"stakeId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"internalType":"struct PacaFinanceWithBoostAndScheduleUSDC.WithdrawStake","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getVestings","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"bonus","type":"uint256"},{"internalType":"uint256","name":"lockedUntil","type":"uint256"},{"internalType":"uint256","name":"claimedAmount","type":"uint256"},{"internalType":"uint256","name":"claimedBonus","type":"uint256"},{"internalType":"uint256","name":"lastClaimed","type":"uint256"},{"internalType":"uint256","name":"createdAt","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"complete","type":"bool"},{"internalType":"uint256","name":"usdAmount","type":"uint256"}],"internalType":"struct PacaFinanceWithBoostAndScheduleUSDC.Vesting[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"_stakeId","type":"uint256"}],"name":"getWithdrawStake","outputs":[{"components":[{"internalType":"uint256","name":"stakeId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"internalType":"struct PacaFinanceWithBoostAndScheduleUSDC.WithdrawStake","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockupDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minStakeLock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"owners","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"uint256","name":"lockupPeriod","type":"uint256"},{"internalType":"uint256","name":"dailyRewardRate","type":"uint256"},{"internalType":"uint256","name":"totalStaked","type":"uint256"},{"internalType":"uint256","name":"totalRewards","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"priceOracles","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bot","type":"address"}],"name":"removeBot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"removeFixedRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"removeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"removeTier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakeIndex","type":"uint256"},{"internalType":"uint256","name":"_restakePercentage","type":"uint256"}],"name":"restake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"restakeBonus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellKickBack","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakeId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"sellStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"sellStakes","outputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"bonusAmount","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lastClaimed","type":"uint256"},{"internalType":"uint256","name":"dailyRewardRate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_oracle","type":"address"}],"name":"setPriceOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_lockTime","type":"uint256"},{"internalType":"uint256","name":"_percentagePerStep","type":"uint256"}],"name":"setUnlockScheduleByPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakes","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lastClaimed","type":"uint256"},{"internalType":"uint256","name":"dailyRewardRate","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"},{"internalType":"bool","name":"complete","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"unlockSchedules","outputs":[{"internalType":"uint256","name":"timeOffset","type":"uint256"},{"internalType":"uint256","name":"percentage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lockupPeriod","type":"uint256"},{"internalType":"uint256","name":"_dailyRewardRate","type":"uint256"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newBonus","type":"uint256"}],"name":"updateRestakeBonus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakeId","type":"uint256"},{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"updateSellStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newTax","type":"uint256"}],"name":"updateSellTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"updateStakeMin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"updateUnlockDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newKickback","type":"uint256"}],"name":"updatesellKickBack","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"vestedTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"vestings","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"bonus","type":"uint256"},{"internalType":"uint256","name":"lockedUntil","type":"uint256"},{"internalType":"uint256","name":"claimedAmount","type":"uint256"},{"internalType":"uint256","name":"claimedBonus","type":"uint256"},{"internalType":"uint256","name":"lastClaimed","type":"uint256"},{"internalType":"uint256","name":"createdAt","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"complete","type":"bool"},{"internalType":"uint256","name":"usdAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"viewRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakeIndex","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawFromStakingPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawFromVestingPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawLiabilities","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawStake","outputs":[{"internalType":"uint256","name":"stakeId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50615ffd80620000216000396000f3fe6080604052600436106104315760003560e01c80637a0c6dc011610229578063b92a349f1161012e578063d6c680eb116100b6578063eb44e0a31161007a578063eb44e0a314610e99578063f2bb563014610eb9578063f8d8c61714610ed9578063fc424c5314610ef9578063ffecf51614610f0f57600080fd5b8063d6c680eb14610df9578063d919302514610e19578063d961341014610e39578063da40ef8014610e59578063e4d06f9014610e7957600080fd5b8063c6066272116100fd578063c606627214610d3b578063c7b530b014610d76578063cc1776d314610da3578063ce13d09014610db9578063cfb866da14610dd957600080fd5b8063b92a349f14610c4b578063bd72169814610c6b578063bd84477d14610c98578063bed9757e14610d0d57600080fd5b80638da5cb5b116101b157806396ed7f891161018057806396ed7f8914610bab578063ac97b41714610bcb578063b6c3dc4c14610beb578063b8e7023d14610c0b578063b90fba1914610c2b57600080fd5b80638da5cb5b14610b3557806392257cb514610b55578063953d16bf14610b6b5780639562ee1514610b8b57600080fd5b806380ca0ecf116101f857806380ca0ecf14610aa05780638129fc1c14610ac0578063853e0df214610ad5578063876b2d8314610af55780638bdf67f214610b1557600080fd5b80637a0c6dc014610a115780637ba6f45814610a3e5780637bc221ac14610a6b5780637f79496c14610a8b57600080fd5b80633ba8396e1161033a578063584b62a1116102c25780636ae21510116102865780636ae215101461097c5780636c3b0c53146109915780637065cb48146109b1578063710ea0ce146109d15780637497211b146109f157600080fd5b8063584b62a1146108a5578063592d1dd1146108ef578063599ab2c41461091c5780635fecd9261461093c57806367a74ddc1461095c57600080fd5b806343c7c0111161030957806343c7c011146107fa57806344c7d6ef1461081a57806351f6cf2f1461083a5780635339dcc11461086f578063581162271461088557600080fd5b80633ba8396e146106fe5780633c92f98d1461072e5780633f35e7221461075d57806343a32f891461077d57600080fd5b806316f0115b116103bd5780631d7a33611161038c5780631d7a33611461068057806322a26fc0146106a05780632e1a7d4d146106b3578063372500ab146106d357806338a85ce2146106e857600080fd5b806316f0115b146105c9578063173825d91461062a5780631ada70a81461064a5780631bf6ddae1461066057600080fd5b80630a84096a116104045780630a84096a1461051a5780630d046d111461053a57806312185a391461056757806313c8e2de1461058957806316be9b2a146105a957600080fd5b80630137451814610436578063022914a7146104895780630519da32146104c9578063092c7610146104ed575b600080fd5b34801561044257600080fd5b5061046c6104513660046158fb565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561049557600080fd5b506104b96104a43660046158fb565b60076020526000908152604090205460ff1681565b6040519015158152602001610480565b3480156104d557600080fd5b506104df60115481565b604051908152602001610480565b3480156104f957600080fd5b506104df6105083660046158fb565b60106020526000908152604090205481565b34801561052657600080fd5b506104df610535366004615916565b610f2f565b34801561054657600080fd5b5061055a610555366004615916565b611067565b6040516104809190615940565b34801561057357600080fd5b50610587610582366004615961565b6111cc565b005b34801561059557600080fd5b506104df6105a4366004615961565b611200565b3480156105b557600080fd5b506105876105c4366004615916565b6112b1565b3480156105d557600080fd5b506001546002546003546004546005546105f994939291906001600160a01b031685565b6040805195865260208601949094529284019190915260608301526001600160a01b0316608082015260a001610480565b34801561063657600080fd5b506105876106453660046158fb565b611322565b34801561065657600080fd5b506104df600d5481565b34801561066c57600080fd5b5061058761067b366004615961565b61141a565b34801561068c57600080fd5b5061058761069b3660046158fb565b61159f565b6105876106ae36600461597a565b611678565b3480156106bf57600080fd5b506105876106ce366004615961565b61179c565b3480156106df57600080fd5b50610587611a9b565b3480156106f457600080fd5b506104df600e5481565b34801561070a57600080fd5b506104b96107193660046158fb565b600f6020526000908152604090205460ff1681565b34801561073a57600080fd5b5061074e6107493660046159ef565b611bfd565b60405161048093929190615a8d565b34801561076957600080fd5b50610587610778366004615916565b611ded565b34801561078957600080fd5b506107d2610798366004615916565b6016602090815260009283526040808420909152908252902080546001820154600283015460038401546004909401549293919290919085565b604080519586526020860194909452928401919091526060830152608082015260a001610480565b34801561080657600080fd5b506105876108153660046158fb565b611e74565b34801561082657600080fd5b50610587610835366004615961565b612212565b34801561084657600080fd5b5061085a610855366004615916565b61242e565b60408051928352602083019190915201610480565b34801561087b57600080fd5b506104df60145481565b34801561089157600080fd5b506105876108a0366004615ac3565b61246a565b3480156108b157600080fd5b506108c56108c0366004615916565b61266f565b6040805195865260208601949094529284019190915260608301521515608082015260a001610480565b3480156108fb57600080fd5b506104df61090a3660046158fb565b600c6020526000908152604090205481565b34801561092857600080fd5b506104df610937366004615ae5565b6126c0565b34801561094857600080fd5b506105876109573660046158fb565b612710565b34801561096857600080fd5b50610587610977366004615b21565b612786565b34801561098857600080fd5b506105876127e3565b34801561099d57600080fd5b506105876109ac366004615916565b6129c7565b3480156109bd57600080fd5b506105876109cc3660046158fb565b612d22565b3480156109dd57600080fd5b506104df6109ec366004615916565b612dd1565b3480156109fd57600080fd5b50610587610a0c366004615961565b612e68565b348015610a1d57600080fd5b50610a31610a2c3660046158fb565b612fa6565b6040516104809190615b54565b348015610a4a57600080fd5b50610a5e610a593660046158fb565b61308d565b6040516104809190615c02565b348015610a7757600080fd5b506104df610a863660046158fb565b613128565b348015610a9757600080fd5b506104df6132fb565b348015610aac57600080fd5b506104df610abb366004615916565b613393565b348015610acc57600080fd5b5061058761349f565b348015610ae157600080fd5b50610587610af0366004615961565b6139a0565b348015610b0157600080fd5b50610587610b10366004615961565b613a2d565b348015610b2157600080fd5b50610587610b30366004615961565b613a61565b348015610b4157600080fd5b5060065461046c906001600160a01b031681565b348015610b6157600080fd5b506104df60125481565b348015610b7757600080fd5b50610587610b86366004615961565b613af0565b348015610b9757600080fd5b50610587610ba6366004615961565b613c4b565b348015610bb757600080fd5b50610587610bc6366004615ac3565b613caf565b348015610bd757600080fd5b50610587610be6366004615961565b613d30565b348015610bf757600080fd5b5061055a610c06366004615916565b614012565b348015610c1757600080fd5b50610587610c26366004615ac3565b6140e7565b348015610c3757600080fd5b50610587610c463660046158fb565b61447b565b348015610c5757600080fd5b50610587610c66366004615c65565b6144ea565b348015610c7757600080fd5b506104df610c863660046158fb565b60156020526000908152604090205481565b348015610ca457600080fd5b50610cb8610cb3366004615916565b614731565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925260a086015260c08501526001600160a01b031660e0840152151561010083015261012082015261014001610480565b348015610d1957600080fd5b50610d2d610d28366004615916565b6147af565b604051610480929190615c98565b348015610d4757600080fd5b50610d5b610d56366004615916565b614955565b60408051938452602084019290925290820152606001610480565b348015610d8257600080fd5b50610d96610d913660046158fb565b614997565b6040516104809190615cc6565b348015610daf57600080fd5b506104df60175481565b348015610dc557600080fd5b50610587610dd4366004615961565b614a1f565b348015610de557600080fd5b50610d5b610df4366004615961565b614a53565b348015610e0557600080fd5b50610587610e14366004615961565b614a86565b348015610e2557600080fd5b50610587610e34366004615961565b614aba565b348015610e4557600080fd5b50610587610e54366004615d28565b614c59565b348015610e6557600080fd5b506104df610e743660046158fb565b614ea3565b348015610e8557600080fd5b50610587610e94366004615916565b614efb565b348015610ea557600080fd5b50610587610eb4366004615916565b615071565b348015610ec557600080fd5b50610587610ed4366004615ac3565b6152c2565b348015610ee557600080fd5b50610587610ef43660046158fb565b615381565b348015610f0557600080fd5b506104df60185481565b348015610f1b57600080fd5b50610587610f2a3660046158fb565b615457565b6001600160a01b0382166000908152600960205260408120805482919084908110610f5c57610f5c615d54565b906000526020600020906009020190506000816006015442610f7e9190615d80565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a602052604090205481101561105a576001600160a01b0383166000908152600a60205260408120805483908110610fdd57610fdd615d54565b6000918252602082206002909102018054600182015460088a01549294509092909160649061100e90600a90615d93565b6110189190615dc0565b90508288106110455761271061102e8383615d93565b6110389190615dc0565b6110429087615dd4565b95505b505050508061105390615de7565b9050610f93565b5093505050505b92915050565b61108b60405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152601360205260408120906110b184620f4240615dd4565b905060005b825481101561114e57818382815481106110d2576110d2615d54565b9060005260206000209060030201600001540361113c578281815481106110fb576110fb615d54565b906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820154815250509350505050611061565b8061114681615de7565b9150506110b6565b5060405162461bcd60e51b815260206004820152604160248201527f57697468647261775374616b652077697468207468652073706563696669656460448201527f207374616b654964206e6f7420666f756e6420666f72207468697320757365726064820152601760f91b608482015260a4015b60405180910390fd5b3360009081526007602052604090205460ff166111fb5760405162461bcd60e51b81526004016111c390615e00565b601755565b6000805b6000548110156112a8576000818154811061122157611221615d54565b906000526020600020906003020160000154831015801561126657506000818154811061125057611250615d54565b9060005260206000209060030201600101548311155b15611298576000818154811061127e5761127e615d54565b906000526020600020906003020160020154915050919050565b6112a181615de7565b9050611204565b50600092915050565b3360009081526007602052604090205460ff166112e05760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b0382166113065760405162461bcd60e51b81526004016111c390615e28565b6001600160a01b03909116600090815260156020526040902055565b3360009081526007602052604090205460ff166113515760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b03811660009081526007602052604090205460ff166113a85760405162461bcd60e51b815260206004820152600c60248201526b2737ba1030b71037bbb732b960a11b60448201526064016111c3565b336001600160a01b038216036113f95760405162461bcd60e51b815260206004820152601660248201527521b0b73737ba103932b6b7bb32903cb7bab939b2b63360511b60448201526064016111c3565b6001600160a01b03166000908152600760205260409020805460ff19169055565b600e5461142c8264e8d4a51000615d93565b116114495760405162461bcd60e51b81526004016111c390615e51565b600554611461906001600160a01b03163330846154d0565b336000908152601560205260408120541561148c57503360009081526015602052604090205461149a565b6114973360006126c0565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a00160405280848152602001428152602001838152602001600160000154426114ed9190615dd4565b815260006020918201819052835460018082018655948252828220845160059092020190815591830151938201939093556040820151600282015560608201516003808301919091556080909201516004909101805460ff19169115159190911790558054849290611560908490615dd4565b909155505060405182815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906020015b60405180910390a25050565b336000908152600f602052604090205460ff166115ce5760405162461bcd60e51b81526004016111c390615e94565b6000805b6001600160a01b038316600090815260086020526040902054811015611662576001600160a01b038316600090815260086020526040812080548390811061161c5761161c615d54565b9060005260206000209060050201905080600001548361163c9190615dd4565b600082556004909101805460ff19166001179055915061165b81615de7565b90506115d2565b50600354611671908290615d80565b6003555050565b336000908152600f602052604090205460ff166116a75760405162461bcd60e51b81526004016111c390615e94565b8060005b8181101561179657368484838181106116c6576116c6615d54565b905060a00201905080602001356001600201546116e39190615dd4565b600355600860006116f760208401846158fb565b6001600160a01b0316815260208082019290925260409081016000908120825160a08101845285850135815285840135818601908152608080880135958301958652606097880135978301978852820184815283546001808201865594865296909420915160059096029091019485555184820155915160028401559251600383015591516004909101805460ff1916911515919091179055016116ab565b50505050565b6117a4615537565b336000908152601360205260408120805461180c5760405162461bcd60e51b815260206004820152602260248201527f4e6f207374616b657320617661696c61626c6520666f72207769746864726177604482015261185b60f21b60648201526084016111c3565b60005b8154811015611a4257600082828154811061182c5761182c615d54565b9060005260206000209060030201905084816000015403611a315780600101546000036118ad5760405162461bcd60e51b815260206004820152602960248201527f5374616b6520616c72656164792077697468647261776e206f7220646f6573206044820152681b9bdd08195e1a5cdd60ba1b60648201526084016111c3565b80600201544210156119015760405162461bcd60e51b815260206004820152601e60248201527f5769746864726177205374616b65206973207374696c6c206c6f636b6564000060448201526064016111c3565b80600101549350620f424085106119245761192164e8d4a5100085615dc0565b93505b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa15801561196d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119919190615ecb565b9050848110156119b35760405162461bcd60e51b81526004016111c390615ee4565b8160010154601260008282546119c99190615d80565b9091555050600060018301556005546119ec906001600160a01b0316338761556f565b604080518681526020810188905233917f933735aa8de6d7547d0126171b2f31b9c34dd00f3ecd4be85a0ba047db4fafef910160405180910390a25050505050611a81565b50611a3b81615de7565b905061180f565b5060405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b60448201526064016111c3565b611a986001600080516020615fa883398151915255565b50565b611aa3615537565b6000805b33600090815260086020526040902054811015611b2f57336000908152600860205260408120805483908110611adf57611adf615d54565b90600052602060002090600502019050600081600001541115611b1e576000611b083384612dd1565b9050611b148185615dd4565b4260018401559350505b50611b2881615de7565b9050611aa7565b5080600003611b765760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b60448201526064016111c3565b600454811115611b985760405162461bcd60e51b81526004016111c390615ee4565b600454611ba6908290615d80565b600455600554611bc0906001600160a01b0316338361556f565b6040518181523390600080516020615f888339815191529060200160405180910390a250611bfb6001600080516020615fa883398151915255565b565b6060806000838067ffffffffffffffff811115611c1c57611c1c615f19565b604051908082528060200260200182016040528015611c45578160200160208202803683370190505b5093508067ffffffffffffffff811115611c6157611c61615f19565b604051908082528060200260200182016040528015611c8a578160200160208202803683370190505b50925060005b81811015611de4576000878783818110611cac57611cac615d54565b9050602002016020810190611cc191906158fb565b6001600160a01b0381166000908152601060205260409020548751919250908190889085908110611cf457611cf4615d54565b6020908102919091018101919091526001600160a01b038381166000818152600b90935260408084205490516302c68be360e31b81526004810192909252909116906316345f1890602401602060405180830381865afa158015611d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d809190615ecb565b90506000670de0b6b3a7640000611d978484615d93565b611da19190615dc0565b905080888681518110611db657611db6615d54565b6020908102919091010152611dcb8188615dd4565b9650505050508080611ddc90615de7565b915050611c90565b50509250925092565b3360009081526007602052604090205460ff16611e1c5760405162461bcd60e51b81526004016111c390615e00565b611e306001600160a01b038316338361556f565b6040518181526001600160a01b0383169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a35050565b611e7c615537565b60008060005b33600090815260096020526040902054811015611fb557336000908152600960205260408120805483908110611eba57611eba615d54565b6000918252602090912060099091020160078101549091506001600160a01b038681169116148015611ef857506007810154600160a01b900460ff16155b15611fa4576000611f093384613393565b90508160030154811015611f2f5760405162461bcd60e51b81526004016111c390615f2f565b6000826003015482611f419190615d80565b90508015611fa157808360030154611f599190615dd4565b6003840155611f688187615dd4565b4260058501558354600385015491975011611f935760078301805460ff60a01b1916600160a01b1790555b84611f9d81615de7565b9550505b50505b50611fae81615de7565b9050611e82565b5081600003611ffc5760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b60448201526064016111c3565b336000908152600c602052604090205415612105576001600160a01b038381166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928692909116906316345f1890602401602060405180830381865afa158015612078573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209c9190615ecb565b6120a69190615d93565b6120b09190615dc0565b336000908152600c602052604090205490915081106120de57336000908152600c6020526040812055612103565b336000908152600c6020526040812080548392906120fd908490615d80565b90915550505b505b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa15801561214c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121709190615ecb565b9050828110156121925760405162461bcd60e51b81526004016111c390615ee4565b6001600160a01b038416600090815260106020526040812080548592906121ba908490615d80565b909155506121d490506001600160a01b038516338561556f565b6040518381523390600080516020615f88833981519152906020015b60405180910390a2505050611a986001600080516020615fa883398151915255565b61221a615537565b33600090815260086020526040902054811061226e5760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b60448201526064016111c3565b33600090815260086020526040812080548390811061228f5761228f615d54565b6000918252602082206005909102018054909250906122ae3385612dd1565b90506122ba8183615dd4565b9150816000036123015760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b60448201526064016111c3565b826003015442101561234d5760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b60448201526064016111c3565b600080845560048401805460ff1916600117905560128054849290612373908490615dd4565b909155505060035482116123a15781600160020160008282546123969190615d80565b909155506123a79050565b60006003555b33600090815260136020908152604091829020825160608101845287815291820185905260115490928201906123dd9042615dd4565b9052815460018082018455600093845260209384902083516003909302019182558284015190820155604091820151600290910155518381523391600080516020615f8883398151915291016121f0565b600a602052816000526040600020818154811061244a57600080fd5b600091825260209091206002909102018054600190910154909250905082565b33600090815260086020526040812080548490811061248b5761248b615d54565b60009182526020909120600590910201600481015490915060ff16156124ec5760405162461bcd60e51b81526020600482015260166024820152755374616b6520616c726561647920636f6d706c65746560501b60448201526064016111c3565b80546000036125315760405162461bcd60e51b815260206004820152601160248201527005374616b6520616d6f756e74206973203607c1b60448201526064016111c3565b336000908152601660209081526040808320868452909152902060020154156125945760405162461bcd60e51b81526020600482015260156024820152745374616b6520616c7265616479206f6e2073616c6560581b60448201526064016111c3565b6040518060a001604052808381526020016064601854856125b59190615d93565b6125bf9190615dc0565b81528254602080830191909152600180850154604080850191909152600280870154606095860152336000818152601686528381208b825286528381208851815588870151958101959095558784015192850192909255948601516003840155608090950151600490920191909155928455825185815290810186905290917f8e79b7ba8dab5ebfa59b9c6af1743c3ef14863680b3cc5ac837f8d636f76031c91015b60405180910390a2505050565b6008602052816000526040600020818154811061268b57600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919060ff1685565b6001600160a01b0382166000908152600c602052604081205481906126e490611200565b6002546126f19190615dd4565b90508215612709576014546127069082615dd4565b90505b9392505050565b3360009081526007602052604090205460ff1661273f5760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b0381166127655760405162461bcd60e51b81526004016111c390615e28565b6001600160a01b03166000908152600f60205260409020805460ff19169055565b3360009081526007602052604090205460ff166127b55760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b039182166000908152600b6020526040902080546001600160a01b03191691909216179055565b6000805b3360009081526008602052604090205481101561286f5733600090815260086020526040812080548390811061281f5761281f615d54565b9060005260206000209060050201905060008160000154111561285e5760006128483384612dd1565b90506128548185615dd4565b4260018401559350505b5061286881615de7565b90506127e7565b50600e5481116128ba5760405162461bcd60e51b8152602060048201526016602482015275139bdd08195b9bdd59da081d1bc818dbdb5c1bdd5b9960521b60448201526064016111c3565b336000818152600860209081526040808320815160a0810183528681524281850152948452600c90925291829020549092918201906128f890611200565b6002546129059190615dd4565b81526020016001600001544261291b9190615dd4565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff1916921515929092179091555461298c908290615dd4565b60035560405181815233907f3afe5b60dee16617a8adbbd7d6c28f17a27efabb834872efa8e7ad5dafddf6f19060200160405180910390a250565b80600003612a175760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f60448201526064016111c3565b6001600160a01b038083166000908152600b60205260409020541680612a8b5760405162461bcd60e51b815260206004820152602360248201527f5072696365206f7261636c65206e6f742073657420666f72207468697320746f60448201526235b2b760e91b60648201526084016111c3565b612aa06001600160a01b0384163330856154d0565b60006064612aaf600a85615d93565b612ab99190615dc0565b6001600160a01b038581166000818152600b60205260408082205490516302c68be360e31b8152600481019390935293945092670de0b6b3a76400009287929116906316345f1890602401602060405180830381865afa158015612b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b459190615ecb565b612b4f9190615d93565b612b599190615dc0565b9050600e548111612b7c5760405162461bcd60e51b81526004016111c390615e51565b336000908152600c602052604081208054839290612b9b908490615dd4565b90915550506001600160a01b03851660009081526010602052604081208054869290612bc8908490615dd4565b909155505033600090815260096020908152604091829020825161014081018452878152918201859052600d549092820190612c049042615dd4565b81526000602080830182905260408084018390524260608086018290526080808701929092526001600160a01b038d811660a08089019190915260c080890188905260e09889018c90528a5460018082018d559b8952978790208a51600990990201978855898701519a88019a909a558885015160028801559188015160038701559187015160048601558601516005850155958501516006840155928401516007830180546101008701511515600160a01b026001600160a81b031990911692909716919091179590951790945561012090920151600890920191909155805186815291820184905233917f9ade76f4385de306666dfb21a52b27d52db0fde8ad0f515fa261f532cac60d21910160405180910390a25050505050565b3360009081526007602052604090205460ff16612d515760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b03811660009081526007602052604090205460ff1615612dad5760405162461bcd60e51b815260206004820152601060248201526f20b63932b0b23c9030b71037bbb732b960811b60448201526064016111c3565b6001600160a01b03166000908152600760205260409020805460ff19166001179055565b6001600160a01b0382166000908152600860205260408120805482919084908110612dfe57612dfe615d54565b906000526020600020906005020190506000816001015442612e209190615d80565b90506000612710620151808385600201548660000154612e409190615d93565b612e4a9190615d93565b612e549190615dc0565b612e5e9190615dc0565b9695505050505050565b3360009081526007602052604090205460ff16612e975760405162461bcd60e51b81526004016111c390615e00565b6000548110612ede5760405162461bcd60e51b8152602060048201526013602482015272496e646578206f7574206f6620626f756e647360681b60448201526064016111c3565b805b600054612eef90600190615d80565b811015612f6c576000612f03826001615dd4565b81548110612f1357612f13615d54565b906000526020600020906003020160008281548110612f3457612f34615d54565b60009182526020909120825460039092020190815560018083015490820155600291820154910155612f6581615de7565b9050612ee0565b506000805480612f7e57612f7e615f5d565b6000828152602081206003600019909301928302018181556001810182905560020155905550565b6001600160a01b0381166000908152600960209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561308257600084815260209081902060408051610140810182526009860290920180548352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a0840152600681015460c084015260078101546001600160a01b03811660e0850152600160a01b900460ff161515610100840152600801546101208301529083529092019101612fde565b505050509050919050565b6001600160a01b0381166000908152600860209081526040808320805482518185028101850190935280835260609492939192909184015b828210156130825760008481526020908190206040805160a081018252600586029092018054835260018082015484860152600282015492840192909252600381015460608401526004015460ff161515608083015290835290920191016130c5565b6001600160a01b038116600090815260096020526040812054815b818110156132f4576001600160a01b038416600090815260096020526040812080548390811061317557613175615d54565b600091825260209182902060408051610140810182526009909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260078201546001600160a01b03811660e083015260ff600160a01b909104161515610100820181905260089092015461012082015291506132e15760e0810180516001600160a01b039081166000908152600b602052604080822054935190516302c68be360e31b815290831660048201529092909116906316345f1890602401602060405180830381865afa158015613272573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132969190615ecb565b90506000826060015183600001516132ae9190615d80565b90506000670de0b6b3a76400006132c58385615d93565b6132cf9190615dc0565b90506132db8188615dd4565b96505050505b50806132ec81615de7565b915050613143565b5050919050565b6005546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613348573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061336c9190615ecb565b9050601254811061337f57600091505090565b8060125461338d9190615d80565b91505090565b6001600160a01b03821660009081526009602052604081208054829190849081106133c0576133c0615d54565b9060005260206000209060090201905060008160060154426133e29190615d80565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a602052604090205481101561105a576001600160a01b0383166000908152600a6020526040812080548390811061344157613441615d54565b60009182526020909120600290910201805460018201549192509081871061348b57875461271090613474908390615d93565b61347e9190615dc0565b6134889086615dd4565b94505b5050508061349890615de7565b90506133f7565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156134e55750825b905060008267ffffffffffffffff1660011480156135025750303b155b905081158015613510575080155b1561352e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561355857845460ff60401b1916600160401b1785555b6135606155b4565b600680546001600160a01b03199081167341970ce76b656030a79e7c1fa76fc4eb93980255178255600760209081527f1428bfef657344f5f7a0019d1554dccabe000be344bb83cdab918bd50f24b573805460ff1990811660019081179092556301499700600d81905567de0b6b3a76400000600e556005805490951673833589fcd6edb6e08f4c7c32d4f71b54bda02913178555825560216002908155604080516060808201835268bdbc41e0348b300000825269021e0c0013070adc000082880190815282840187815260008054808a018255818052945160039586027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5638181019290925593517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5648086019190915592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565948501558651808601885269021e19e0c9bab2400000815269043c25e0dcc1bd1c0000818d01908152818901998a528354808d01855584805291519188028084019290925551818501559751978401979097558551808501875269043c33c1937564800000815269065a3fc1a67c6f5c0000818c019081528188018781528354808d0185558480529251928802808b019390935590518285015551908401558551808501875269065a4da25d3016c00000815269087859a27037219c0000818c0190815260048289019081528354808d0185558480529251928802808b0193909355905182850155519084015585518085018752690878678326eac90000008152690cb48d6403ac861c0000818c019081528188019c8d528254808c0184558380529151918702808a019290925551818401559a519a83019a909a5584518084018652690cb49b44ba602d80000081526910f0c1259721ea9c0000818b019081528187019c8d528b54808b018d558c805291519186028089019290925551818301559a519a82019a909a55835180830185526910f0cf064dd592000000815269152cf4e72a974f1c0000818a0190815260088287019081528b54808b018d558c80529251928602808901939093559051828d015551908201558351918201845269152d02c7e14af68000008252600019828901908152600a94830194855289548089018b558a805292519284029586019290925590519884019890985590519190960155600f9092527f77c9ddf83be31065a9eb7ed19d93a8a4db24cad8351f41cc546083ac9e9d8c7f8054831682179055737c40f272570fdf9549d6f67493ac250a1db52f279092527f1b209462f90614903451721396f08356b5037572bebcd67a02efc98f03bec9d1805490911690911790556201fa40601155601455831561399957845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b3360009081526007602052604090205460ff166139cf5760405162461bcd60e51b81526004016111c390615e00565b6005546139e6906001600160a01b0316338361556f565b6005546040518281526001600160a01b039091169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a350565b3360009081526007602052604090205460ff16613a5c5760405162461bcd60e51b81526004016111c390615e00565b601855565b3360009081526007602052604090205460ff16613a905760405162461bcd60e51b81526004016111c390615e00565b600554613aa8906001600160a01b03163330846154d0565b600454613ab6908290615dd4565b6004556040518181527f4e9221f2cca6ca0397acc6004ea0b716798254f5abcf53924fab34f0373e5d4e906020015b60405180910390a150565b33600090815260166020908152604080832084845290915281206002810154909103613b555760405162461bcd60e51b815260206004820152601460248201527314d95b1b081cdd185ad9481b9bdd08199bdd5b9960621b60448201526064016111c3565b336000908152600860205260408120805484908110613b7657613b76615d54565b906000526020600020906005020190508060000154600014613bda5760405162461bcd60e51b815260206004820152601760248201527f5374616b65206e6f7420696e2073656c6c20737461746500000000000000000060448201526064016111c3565b6002808301548255336000818152601660209081526040808320888452909152808220828155600181018390559384018290556003840182905560049093015590517f73d12dec3eb3b445b6c9feb2fd559ba7c852c525bc1e59d8f7ff760c55df041d906126629086815260200190565b3360009081526007602052604090205460ff16613c7a5760405162461bcd60e51b81526004016111c390615e00565b600e8190556040518181527fe5dadb089824c750e4e7a2e98bfbe130f1a09834769e81339639fbe18606859b90602001613ae5565b3360009081526007602052604090205460ff16613cde5760405162461bcd60e51b81526004016111c390615e00565b613ceb8262015180615d93565b600155600281905560408051838152602081018390527f7fa9647ec1cc14e3822b46d05a2b9d4e019bde8875c0088c46b6503d71bf1722910160405180910390a15050565b613d38615537565b336000908152600960205260408120805483908110613d5957613d59615d54565b600091825260209091206009909102016007810154909150600160a01b900460ff1615613dbc5760405162461bcd60e51b81526020600482015260116024820152705374616b6520697320436f6d706c65746560781b60448201526064016111c3565b6000613dc83384613393565b90508160030154811015613dee5760405162461bcd60e51b81526004016111c390615f2f565b6000826003015482613e009190615d80565b905080600003613e4e5760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b60448201526064016111c3565b808360030154613e5e9190615dd4565b60038401819055835411613e825760078301805460ff60a01b1916600160a01b1790555b336000908152600c602052604090205415613f905760078301546001600160a01b039081166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928592909116906316345f1890602401602060405180830381865afa158015613f03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f279190615ecb565b613f319190615d93565b613f3b9190615dc0565b336000908152600c60205260409020549091508110613f6957336000908152600c6020526040812055613f8e565b336000908152600c602052604081208054839290613f88908490615d80565b90915550505b505b60078301546001600160a01b031660009081526010602052604081208054839290613fbc908490615d80565b90915550506007830154613fda906001600160a01b0316338361556f565b604080518281526000602082015233917f4a94c2c356e29a6583071e731bdacf2ca56565ba5efebcff6936eb7923b5172191016121f0565b61403660405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152601360205260408120905b815481101561114e578382828154811061406c5761406c615d54565b906000526020600020906003020160000154036140d55781818154811061409557614095615d54565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505050611061565b806140df81615de7565b915050614050565b6140ef615537565b60648111156141405760405162461bcd60e51b815260206004820152601a60248201527f496e76616c69642072657374616b652070657263656e7461676500000000000060448201526064016111c3565b33600090815260086020526040812080548490811061416157614161615d54565b9060005260206000209060050201905080600001546000036141ba5760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b60448201526064016111c3565b80600301544210156142065760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b60448201526064016111c3565b805460006142143386612dd1565b90506142208183615dd4565b9150600060646142308685615d93565b61423a9190615dc0565b905060006142488285615d80565b6000865560048601805460ff19166001179055905080156143345780601260008282546142759190615dd4565b909155505060035481116142a35780600160020160008282546142989190615d80565b909155506142a99050565b60006003555b3360009081526013602090815260409182902082516060810184528a815291820184905260115490928201906142df9042615dd4565b9052815460018082018455600093845260209384902083516003909302019182558284015190820155604091820151600290910155518281523391600080516020615f88833981519152910160405180910390a25b811561445b573360009081526015602052604081205415614365575033600090815260156020526040902054614373565b6143703360016126c0565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a00160405280858152602001428152602001838152602001600160000154426143c69190615dd4565b81526000602091820181905283546001808201865594825290829020835160059092020190815582820151938101939093556040808301516002850155606083015160038501556080909201516004909301805460ff1916931515939093179092555184815233917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d910160405180910390a2505b50505050506144776001600080516020615fa883398151915255565b5050565b3360009081526007602052604090205460ff166144aa5760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b0381166144d05760405162461bcd60e51b81526004016111c390615e28565b6001600160a01b0316600090815260156020526040812055565b3360009081526007602052604090205460ff166145195760405162461bcd60e51b81526004016111c390615e00565b816000036145755760405162461bcd60e51b815260206004820152602360248201527f4c6f636b2074696d65206d7573742062652067726561746572207468616e207a60448201526265726f60e81b60648201526084016111c3565b806000036145db5760405162461bcd60e51b815260206004820152602d60248201527f50657263656e74616765207065722073746570206d757374206265206772656160448201526c746572207468616e207a65726f60981b60648201526084016111c3565b6127106145e88282615f73565b156146405760405162461bcd60e51b815260206004820152602260248201527f50657263656e74616765206d757374206469766964652031303025206576656e6044820152616c7960f01b60648201526084016111c3565b600061464c8383615dc0565b9050600061465a8286615dc0565b6001600160a01b0387166000908152600a6020526040812091925061467f91906158a4565b60015b8281116146f4576001600160a01b0387166000908152600a602052604090819020815180830190925290806146b78486615d93565b8152602090810188905282546001818101855560009485529382902083516002909202019081559101519101556146ed81615de7565b9050614682565b506040516001600160a01b038716907fde4b6ccc38b84f88129403b65a309f9b1c41d4c316bc2118d7614e449b9d4c4590600090a2505050505050565b6009602052816000526040600020818154811061474d57600080fd5b6000918252602090912060099091020180546001820154600283015460038401546004850154600586015460068701546007880154600890980154969950949750929591949093916001600160a01b03811691600160a01b90910460ff16908a565b6001600160a01b0382166000908152600960205260408120805460609283929091859081106147e0576147e0615d54565b600091825260208083206007600990930201918201546001600160a01b0316808452600a9091526040832054919350918167ffffffffffffffff81111561482957614829615f19565b604051908082528060200260200182016040528015614852578160200160208202803683370190505b50905060008267ffffffffffffffff81111561487057614870615f19565b604051908082528060200260200182016040528015614899578160200160208202803683370190505b50905060005b83811015614946576001600160a01b0385166000908152600a602052604081208054839081106148d1576148d1615d54565b90600052602060002090600202019050806000015487600601546148f59190615dd4565b84838151811061490757614907615d54565b602002602001018181525050806001015483838151811061492a5761492a615d54565b60209081029190910101525061493f81615de7565b905061489f565b50909890975095505050505050565b6013602052816000526040600020818154811061497157600080fd5b600091825260209091206003909102018054600182015460029092015490935090915083565b6001600160a01b0381166000908152601360209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561308257838290600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050815260200190600101906149cf565b3360009081526007602052604090205460ff16614a4e5760405162461bcd60e51b81526004016111c390615e00565b601155565b60008181548110614a6357600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b3360009081526007602052604090205460ff16614ab55760405162461bcd60e51b81526004016111c390615e00565b601455565b614ac2615537565b336000908152600960205260408120805483908110614ae357614ae3615d54565b906000526020600020906009020190506000614aff3384610f2f565b90508160040154811015614b255760405162461bcd60e51b81526004016111c390615f2f565b6000826004015482614b379190615d80565b905080600003614b855760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b60448201526064016111c3565b808360040154614b959190615dd4565b83600401819055508060126000828254614baf9190615dd4565b909155505033600090815260136020526040908190208151606081019092529080614bdd87620f4240615dd4565b815260200183815260200160115442614bf69190615dd4565b90528154600180820184556000938452602093849020835160039093020191825582840151908201556040918201516002909101555182815233917f4e69fdc49495bcab2b4375781457ba16653a90eb4ffb6588351bdc39071433e291016121f0565b3360009081526007602052604090205460ff16614c885760405162461bcd60e51b81526004016111c390615e00565b818310614cec5760405162461bcd60e51b815260206004820152602c60248201527f496e76616c69642072616e67653a206d696e546f6b656e73206d75737420626560448201526b203c206d6178546f6b656e7360a01b60648201526084016111c3565b614cf683836155c4565b15614d4e5760405162461bcd60e51b815260206004820152602260248201527f52616e6765206f7665726c6170732077697468206578697374696e6720746965604482015261727360f01b60648201526084016111c3565b60005b600054811015614df5578360008281548110614d6f57614d6f615d54565b906000526020600020906003020160000154148015614db157508260008281548110614d9d57614d9d615d54565b906000526020600020906003020160010154145b15614de5578160008281548110614dca57614dca615d54565b90600052602060002090600302016002018190555050505050565b614dee81615de7565b9050614d51565b5060408051606081018252848152602081018481529181018381526000805460018101825590805291517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56360039093029283015591517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56482015590517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56590910155614e9e615653565b505050565b600080805b6001600160a01b038416600090815260086020526040902054811015614ef4576000614ed48583612dd1565b9050614ee08184615dd4565b92505080614eed90615de7565b9050614ea8565b5092915050565b3360009081526007602052604090205460ff16614f2a5760405162461bcd60e51b81526004016111c390615e00565b80600003614f6b5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b60448201526064016111c3565b60086000836001600160a01b03166001600160a01b031681526020019081526020016000206040518060a001604052808381526020014281526020016001800154815260200160016000015442614fc29190615dd4565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff19169215159290921790915554615033908290615dd4565b6003556040518181526001600160a01b038316907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d90602001611593565b6001600160a01b0382166000908152601660209081526040808320848452909152812060028101549091036150e85760405162461bcd60e51b815260206004820152601860248201527f53656c6c207374616b65206e6f7420617661696c61626c65000000000000000060448201526064016111c3565b8054600554615106916001600160a01b0390911690339030906154d0565b60006064601754836000015461511c9190615d93565b6151269190615dc0565b600554909150615140906001600160a01b0316858361556f565b6001600160a01b038416600090815260086020526040812080548590811061516a5761516a615d54565b600091825260208083206004600590930201918201805460ff191660019081179091553384526008909152604092839020835160a0810190945290860154600287015492945090929182916151be91615dd4565b81526020018560030154815260200185600401548152602001600160000154426151e89190615dd4565b8152600060209182018190528354600180820186559482528282208451600590920201908155838301518186015560408085015160028084019190915560608601516003808501919091556080909601516004938401805460ff19169115159190911790556001600160a01b038c16808552601686528285208c865286528285208581559788018590559087018490559486018390559401558554835190815290810187905233927f7bb39d095b04a9986ed34adf14d74c33294d0a9e807f02bf634d532507422eba910160405180910390a35050505050565b336000908152601660209081526040808320858452909152812060028101549091036153275760405162461bcd60e51b815260206004820152601460248201527314d95b1b081cdd185ad9481b9bdd08199bdd5b9960621b60448201526064016111c3565b6064601854836153379190615d93565b6153419190615dc0565b6001820155818155604080518381526020810185905233917f8e79b7ba8dab5ebfa59b9c6af1743c3ef14863680b3cc5ac837f8d636f76031c9101612662565b336000908152600f602052604090205460ff166153b05760405162461bcd60e51b81526004016111c390615e94565b6000805b6001600160a01b03831660009081526013602052604090205481101561543b576001600160a01b03831660009081526013602052604081208054839081106153fe576153fe615d54565b9060005260206000209060030201905080600101548361541e9190615dd4565b6000600190920191909155915061543481615de7565b90506153b4565b50806012600082825461544e9190615d80565b90915550505050565b3360009081526007602052604090205460ff166154865760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b0381166154ac5760405162461bcd60e51b81526004016111c390615e28565b6001600160a01b03166000908152600f60205260409020805460ff19166001179055565b6040516001600160a01b0384811660248301528381166044830152606482018390526117969186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506157e2565b600080516020615fa883398151915280546001190161556957604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6040516001600160a01b03838116602483015260448201839052614e9e91859182169063a9059cbb90606401615505565b6001600080516020615fa883398151915255565b6155bc615853565b611bfb61589c565b6000805b60005481101561564957600081815481106155e5576155e5615d54565b906000526020600020906003020160010154841115801561562a57506000818154811061561457615614615d54565b9060005260206000209060030201600001548310155b15615639576001915050611061565b61564281615de7565b90506155c8565b5060009392505050565b60005b600054811015611a9857600061566d826001615dd4565b90505b6000548110156157d1576000818154811061568d5761568d615d54565b906000526020600020906003020160000154600083815481106156b2576156b2615d54565b90600052602060002090600302016000015411156157bf5760008083815481106156de576156de615d54565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505090506000828154811061572a5761572a615d54565b90600052602060002090600302016000848154811061574b5761574b615d54565b9060005260206000209060030201600082015481600001556001820154816001015560028201548160020155905050806000838154811061578e5761578e615d54565b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020155905050505b806157c981615de7565b915050615670565b506157db81615de7565b9050615656565b600080602060008451602086016000885af180615805576040513d6000823e3d81fd5b50506000513d9150811561581d57806001141561582a565b6001600160a01b0384163b155b1561179657604051635274afe760e01b81526001600160a01b03851660048201526024016111c3565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16611bfb57604051631afcd79f60e31b815260040160405180910390fd5b6155a0615853565b5080546000825560020290600052602060002090810190611a9891905b808211156158db57600080825560018201556002016158c1565b5090565b80356001600160a01b03811681146158f657600080fd5b919050565b60006020828403121561590d57600080fd5b612709826158df565b6000806040838503121561592957600080fd5b615932836158df565b946020939093013593505050565b81518152602080830151908201526040808301519082015260608101611061565b60006020828403121561597357600080fd5b5035919050565b6000806020838503121561598d57600080fd5b823567ffffffffffffffff808211156159a557600080fd5b818501915085601f8301126159b957600080fd5b8135818111156159c857600080fd5b86602060a0830285010111156159dd57600080fd5b60209290920196919550909350505050565b60008060208385031215615a0257600080fd5b823567ffffffffffffffff80821115615a1a57600080fd5b818501915085601f830112615a2e57600080fd5b813581811115615a3d57600080fd5b8660208260051b85010111156159dd57600080fd5b600081518084526020808501945080840160005b83811015615a8257815187529582019590820190600101615a66565b509495945050505050565b606081526000615aa06060830186615a52565b8281036020840152615ab28186615a52565b915050826040830152949350505050565b60008060408385031215615ad657600080fd5b50508035926020909101359150565b60008060408385031215615af857600080fd5b615b01836158df565b915060208301358015158114615b1657600080fd5b809150509250929050565b60008060408385031215615b3457600080fd5b615b3d836158df565b9150615b4b602084016158df565b90509250929050565b602080825282518282018190526000919060409081850190868401855b82811015615bf55781518051855286810151878601528581015186860152606080820151908601526080808201519086015260a0808201519086015260c0808201519086015260e0808201516001600160a01b0316908601526101008082015115159086015261012090810151908501526101409093019290850190600101615b71565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015615bf557815180518552868101518786015285810151868601526060808201519086015260809081015115159085015260a09093019290850190600101615c1f565b600080600060608486031215615c7a57600080fd5b615c83846158df565b95602085013595506040909401359392505050565b604081526000615cab6040830185615a52565b8281036020840152615cbd8185615a52565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015615d1c57615d098385518051825260208082015190830152604090810151910152565b9284019260609290920191600101615ce2565b50909695505050505050565b600080600060608486031215615d3d57600080fd5b505081359360208301359350604090920135919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561106157611061615d6a565b808202811582820484141761106157611061615d6a565b634e487b7160e01b600052601260045260246000fd5b600082615dcf57615dcf615daa565b500490565b8082018082111561106157611061615d6a565b600060018201615df957615df9615d6a565b5060010190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b60208082526023908201527f416d6f756e74206d7573742062652067726561746572206d696e5374616b654c6040820152626f636b60e81b606082015260800190565b6020808252601f908201527f43616c6c6572206973206e6f7420616e20617574686f72697a656420626f7400604082015260600190565b600060208284031215615edd57600080fd5b5051919050565b6020808252818101527f496e73756666696369656e74207265776172647320696e2074686520706f6f6c604082015260600190565b634e487b7160e01b600052604160045260246000fd5b602080825260149082015273125b9d985b1a590818db185a5b48185b5bdd5b9d60621b604082015260600190565b634e487b7160e01b600052603160045260246000fd5b600082615f8257615f82615daa565b50069056fe106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f72419b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a2646970667358221220d496485ba7f610817305b5625a528c4e80ffc695bc4c437518865ea4694bfb0464736f6c63430008140033
Deployed Bytecode
0x6080604052600436106104315760003560e01c80637a0c6dc011610229578063b92a349f1161012e578063d6c680eb116100b6578063eb44e0a31161007a578063eb44e0a314610e99578063f2bb563014610eb9578063f8d8c61714610ed9578063fc424c5314610ef9578063ffecf51614610f0f57600080fd5b8063d6c680eb14610df9578063d919302514610e19578063d961341014610e39578063da40ef8014610e59578063e4d06f9014610e7957600080fd5b8063c6066272116100fd578063c606627214610d3b578063c7b530b014610d76578063cc1776d314610da3578063ce13d09014610db9578063cfb866da14610dd957600080fd5b8063b92a349f14610c4b578063bd72169814610c6b578063bd84477d14610c98578063bed9757e14610d0d57600080fd5b80638da5cb5b116101b157806396ed7f891161018057806396ed7f8914610bab578063ac97b41714610bcb578063b6c3dc4c14610beb578063b8e7023d14610c0b578063b90fba1914610c2b57600080fd5b80638da5cb5b14610b3557806392257cb514610b55578063953d16bf14610b6b5780639562ee1514610b8b57600080fd5b806380ca0ecf116101f857806380ca0ecf14610aa05780638129fc1c14610ac0578063853e0df214610ad5578063876b2d8314610af55780638bdf67f214610b1557600080fd5b80637a0c6dc014610a115780637ba6f45814610a3e5780637bc221ac14610a6b5780637f79496c14610a8b57600080fd5b80633ba8396e1161033a578063584b62a1116102c25780636ae21510116102865780636ae215101461097c5780636c3b0c53146109915780637065cb48146109b1578063710ea0ce146109d15780637497211b146109f157600080fd5b8063584b62a1146108a5578063592d1dd1146108ef578063599ab2c41461091c5780635fecd9261461093c57806367a74ddc1461095c57600080fd5b806343c7c0111161030957806343c7c011146107fa57806344c7d6ef1461081a57806351f6cf2f1461083a5780635339dcc11461086f578063581162271461088557600080fd5b80633ba8396e146106fe5780633c92f98d1461072e5780633f35e7221461075d57806343a32f891461077d57600080fd5b806316f0115b116103bd5780631d7a33611161038c5780631d7a33611461068057806322a26fc0146106a05780632e1a7d4d146106b3578063372500ab146106d357806338a85ce2146106e857600080fd5b806316f0115b146105c9578063173825d91461062a5780631ada70a81461064a5780631bf6ddae1461066057600080fd5b80630a84096a116104045780630a84096a1461051a5780630d046d111461053a57806312185a391461056757806313c8e2de1461058957806316be9b2a146105a957600080fd5b80630137451814610436578063022914a7146104895780630519da32146104c9578063092c7610146104ed575b600080fd5b34801561044257600080fd5b5061046c6104513660046158fb565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561049557600080fd5b506104b96104a43660046158fb565b60076020526000908152604090205460ff1681565b6040519015158152602001610480565b3480156104d557600080fd5b506104df60115481565b604051908152602001610480565b3480156104f957600080fd5b506104df6105083660046158fb565b60106020526000908152604090205481565b34801561052657600080fd5b506104df610535366004615916565b610f2f565b34801561054657600080fd5b5061055a610555366004615916565b611067565b6040516104809190615940565b34801561057357600080fd5b50610587610582366004615961565b6111cc565b005b34801561059557600080fd5b506104df6105a4366004615961565b611200565b3480156105b557600080fd5b506105876105c4366004615916565b6112b1565b3480156105d557600080fd5b506001546002546003546004546005546105f994939291906001600160a01b031685565b6040805195865260208601949094529284019190915260608301526001600160a01b0316608082015260a001610480565b34801561063657600080fd5b506105876106453660046158fb565b611322565b34801561065657600080fd5b506104df600d5481565b34801561066c57600080fd5b5061058761067b366004615961565b61141a565b34801561068c57600080fd5b5061058761069b3660046158fb565b61159f565b6105876106ae36600461597a565b611678565b3480156106bf57600080fd5b506105876106ce366004615961565b61179c565b3480156106df57600080fd5b50610587611a9b565b3480156106f457600080fd5b506104df600e5481565b34801561070a57600080fd5b506104b96107193660046158fb565b600f6020526000908152604090205460ff1681565b34801561073a57600080fd5b5061074e6107493660046159ef565b611bfd565b60405161048093929190615a8d565b34801561076957600080fd5b50610587610778366004615916565b611ded565b34801561078957600080fd5b506107d2610798366004615916565b6016602090815260009283526040808420909152908252902080546001820154600283015460038401546004909401549293919290919085565b604080519586526020860194909452928401919091526060830152608082015260a001610480565b34801561080657600080fd5b506105876108153660046158fb565b611e74565b34801561082657600080fd5b50610587610835366004615961565b612212565b34801561084657600080fd5b5061085a610855366004615916565b61242e565b60408051928352602083019190915201610480565b34801561087b57600080fd5b506104df60145481565b34801561089157600080fd5b506105876108a0366004615ac3565b61246a565b3480156108b157600080fd5b506108c56108c0366004615916565b61266f565b6040805195865260208601949094529284019190915260608301521515608082015260a001610480565b3480156108fb57600080fd5b506104df61090a3660046158fb565b600c6020526000908152604090205481565b34801561092857600080fd5b506104df610937366004615ae5565b6126c0565b34801561094857600080fd5b506105876109573660046158fb565b612710565b34801561096857600080fd5b50610587610977366004615b21565b612786565b34801561098857600080fd5b506105876127e3565b34801561099d57600080fd5b506105876109ac366004615916565b6129c7565b3480156109bd57600080fd5b506105876109cc3660046158fb565b612d22565b3480156109dd57600080fd5b506104df6109ec366004615916565b612dd1565b3480156109fd57600080fd5b50610587610a0c366004615961565b612e68565b348015610a1d57600080fd5b50610a31610a2c3660046158fb565b612fa6565b6040516104809190615b54565b348015610a4a57600080fd5b50610a5e610a593660046158fb565b61308d565b6040516104809190615c02565b348015610a7757600080fd5b506104df610a863660046158fb565b613128565b348015610a9757600080fd5b506104df6132fb565b348015610aac57600080fd5b506104df610abb366004615916565b613393565b348015610acc57600080fd5b5061058761349f565b348015610ae157600080fd5b50610587610af0366004615961565b6139a0565b348015610b0157600080fd5b50610587610b10366004615961565b613a2d565b348015610b2157600080fd5b50610587610b30366004615961565b613a61565b348015610b4157600080fd5b5060065461046c906001600160a01b031681565b348015610b6157600080fd5b506104df60125481565b348015610b7757600080fd5b50610587610b86366004615961565b613af0565b348015610b9757600080fd5b50610587610ba6366004615961565b613c4b565b348015610bb757600080fd5b50610587610bc6366004615ac3565b613caf565b348015610bd757600080fd5b50610587610be6366004615961565b613d30565b348015610bf757600080fd5b5061055a610c06366004615916565b614012565b348015610c1757600080fd5b50610587610c26366004615ac3565b6140e7565b348015610c3757600080fd5b50610587610c463660046158fb565b61447b565b348015610c5757600080fd5b50610587610c66366004615c65565b6144ea565b348015610c7757600080fd5b506104df610c863660046158fb565b60156020526000908152604090205481565b348015610ca457600080fd5b50610cb8610cb3366004615916565b614731565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925260a086015260c08501526001600160a01b031660e0840152151561010083015261012082015261014001610480565b348015610d1957600080fd5b50610d2d610d28366004615916565b6147af565b604051610480929190615c98565b348015610d4757600080fd5b50610d5b610d56366004615916565b614955565b60408051938452602084019290925290820152606001610480565b348015610d8257600080fd5b50610d96610d913660046158fb565b614997565b6040516104809190615cc6565b348015610daf57600080fd5b506104df60175481565b348015610dc557600080fd5b50610587610dd4366004615961565b614a1f565b348015610de557600080fd5b50610d5b610df4366004615961565b614a53565b348015610e0557600080fd5b50610587610e14366004615961565b614a86565b348015610e2557600080fd5b50610587610e34366004615961565b614aba565b348015610e4557600080fd5b50610587610e54366004615d28565b614c59565b348015610e6557600080fd5b506104df610e743660046158fb565b614ea3565b348015610e8557600080fd5b50610587610e94366004615916565b614efb565b348015610ea557600080fd5b50610587610eb4366004615916565b615071565b348015610ec557600080fd5b50610587610ed4366004615ac3565b6152c2565b348015610ee557600080fd5b50610587610ef43660046158fb565b615381565b348015610f0557600080fd5b506104df60185481565b348015610f1b57600080fd5b50610587610f2a3660046158fb565b615457565b6001600160a01b0382166000908152600960205260408120805482919084908110610f5c57610f5c615d54565b906000526020600020906009020190506000816006015442610f7e9190615d80565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a602052604090205481101561105a576001600160a01b0383166000908152600a60205260408120805483908110610fdd57610fdd615d54565b6000918252602082206002909102018054600182015460088a01549294509092909160649061100e90600a90615d93565b6110189190615dc0565b90508288106110455761271061102e8383615d93565b6110389190615dc0565b6110429087615dd4565b95505b505050508061105390615de7565b9050610f93565b5093505050505b92915050565b61108b60405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152601360205260408120906110b184620f4240615dd4565b905060005b825481101561114e57818382815481106110d2576110d2615d54565b9060005260206000209060030201600001540361113c578281815481106110fb576110fb615d54565b906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820154815250509350505050611061565b8061114681615de7565b9150506110b6565b5060405162461bcd60e51b815260206004820152604160248201527f57697468647261775374616b652077697468207468652073706563696669656460448201527f207374616b654964206e6f7420666f756e6420666f72207468697320757365726064820152601760f91b608482015260a4015b60405180910390fd5b3360009081526007602052604090205460ff166111fb5760405162461bcd60e51b81526004016111c390615e00565b601755565b6000805b6000548110156112a8576000818154811061122157611221615d54565b906000526020600020906003020160000154831015801561126657506000818154811061125057611250615d54565b9060005260206000209060030201600101548311155b15611298576000818154811061127e5761127e615d54565b906000526020600020906003020160020154915050919050565b6112a181615de7565b9050611204565b50600092915050565b3360009081526007602052604090205460ff166112e05760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b0382166113065760405162461bcd60e51b81526004016111c390615e28565b6001600160a01b03909116600090815260156020526040902055565b3360009081526007602052604090205460ff166113515760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b03811660009081526007602052604090205460ff166113a85760405162461bcd60e51b815260206004820152600c60248201526b2737ba1030b71037bbb732b960a11b60448201526064016111c3565b336001600160a01b038216036113f95760405162461bcd60e51b815260206004820152601660248201527521b0b73737ba103932b6b7bb32903cb7bab939b2b63360511b60448201526064016111c3565b6001600160a01b03166000908152600760205260409020805460ff19169055565b600e5461142c8264e8d4a51000615d93565b116114495760405162461bcd60e51b81526004016111c390615e51565b600554611461906001600160a01b03163330846154d0565b336000908152601560205260408120541561148c57503360009081526015602052604090205461149a565b6114973360006126c0565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a00160405280848152602001428152602001838152602001600160000154426114ed9190615dd4565b815260006020918201819052835460018082018655948252828220845160059092020190815591830151938201939093556040820151600282015560608201516003808301919091556080909201516004909101805460ff19169115159190911790558054849290611560908490615dd4565b909155505060405182815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906020015b60405180910390a25050565b336000908152600f602052604090205460ff166115ce5760405162461bcd60e51b81526004016111c390615e94565b6000805b6001600160a01b038316600090815260086020526040902054811015611662576001600160a01b038316600090815260086020526040812080548390811061161c5761161c615d54565b9060005260206000209060050201905080600001548361163c9190615dd4565b600082556004909101805460ff19166001179055915061165b81615de7565b90506115d2565b50600354611671908290615d80565b6003555050565b336000908152600f602052604090205460ff166116a75760405162461bcd60e51b81526004016111c390615e94565b8060005b8181101561179657368484838181106116c6576116c6615d54565b905060a00201905080602001356001600201546116e39190615dd4565b600355600860006116f760208401846158fb565b6001600160a01b0316815260208082019290925260409081016000908120825160a08101845285850135815285840135818601908152608080880135958301958652606097880135978301978852820184815283546001808201865594865296909420915160059096029091019485555184820155915160028401559251600383015591516004909101805460ff1916911515919091179055016116ab565b50505050565b6117a4615537565b336000908152601360205260408120805461180c5760405162461bcd60e51b815260206004820152602260248201527f4e6f207374616b657320617661696c61626c6520666f72207769746864726177604482015261185b60f21b60648201526084016111c3565b60005b8154811015611a4257600082828154811061182c5761182c615d54565b9060005260206000209060030201905084816000015403611a315780600101546000036118ad5760405162461bcd60e51b815260206004820152602960248201527f5374616b6520616c72656164792077697468647261776e206f7220646f6573206044820152681b9bdd08195e1a5cdd60ba1b60648201526084016111c3565b80600201544210156119015760405162461bcd60e51b815260206004820152601e60248201527f5769746864726177205374616b65206973207374696c6c206c6f636b6564000060448201526064016111c3565b80600101549350620f424085106119245761192164e8d4a5100085615dc0565b93505b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa15801561196d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119919190615ecb565b9050848110156119b35760405162461bcd60e51b81526004016111c390615ee4565b8160010154601260008282546119c99190615d80565b9091555050600060018301556005546119ec906001600160a01b0316338761556f565b604080518681526020810188905233917f933735aa8de6d7547d0126171b2f31b9c34dd00f3ecd4be85a0ba047db4fafef910160405180910390a25050505050611a81565b50611a3b81615de7565b905061180f565b5060405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b60448201526064016111c3565b611a986001600080516020615fa883398151915255565b50565b611aa3615537565b6000805b33600090815260086020526040902054811015611b2f57336000908152600860205260408120805483908110611adf57611adf615d54565b90600052602060002090600502019050600081600001541115611b1e576000611b083384612dd1565b9050611b148185615dd4565b4260018401559350505b50611b2881615de7565b9050611aa7565b5080600003611b765760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b60448201526064016111c3565b600454811115611b985760405162461bcd60e51b81526004016111c390615ee4565b600454611ba6908290615d80565b600455600554611bc0906001600160a01b0316338361556f565b6040518181523390600080516020615f888339815191529060200160405180910390a250611bfb6001600080516020615fa883398151915255565b565b6060806000838067ffffffffffffffff811115611c1c57611c1c615f19565b604051908082528060200260200182016040528015611c45578160200160208202803683370190505b5093508067ffffffffffffffff811115611c6157611c61615f19565b604051908082528060200260200182016040528015611c8a578160200160208202803683370190505b50925060005b81811015611de4576000878783818110611cac57611cac615d54565b9050602002016020810190611cc191906158fb565b6001600160a01b0381166000908152601060205260409020548751919250908190889085908110611cf457611cf4615d54565b6020908102919091018101919091526001600160a01b038381166000818152600b90935260408084205490516302c68be360e31b81526004810192909252909116906316345f1890602401602060405180830381865afa158015611d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d809190615ecb565b90506000670de0b6b3a7640000611d978484615d93565b611da19190615dc0565b905080888681518110611db657611db6615d54565b6020908102919091010152611dcb8188615dd4565b9650505050508080611ddc90615de7565b915050611c90565b50509250925092565b3360009081526007602052604090205460ff16611e1c5760405162461bcd60e51b81526004016111c390615e00565b611e306001600160a01b038316338361556f565b6040518181526001600160a01b0383169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a35050565b611e7c615537565b60008060005b33600090815260096020526040902054811015611fb557336000908152600960205260408120805483908110611eba57611eba615d54565b6000918252602090912060099091020160078101549091506001600160a01b038681169116148015611ef857506007810154600160a01b900460ff16155b15611fa4576000611f093384613393565b90508160030154811015611f2f5760405162461bcd60e51b81526004016111c390615f2f565b6000826003015482611f419190615d80565b90508015611fa157808360030154611f599190615dd4565b6003840155611f688187615dd4565b4260058501558354600385015491975011611f935760078301805460ff60a01b1916600160a01b1790555b84611f9d81615de7565b9550505b50505b50611fae81615de7565b9050611e82565b5081600003611ffc5760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b60448201526064016111c3565b336000908152600c602052604090205415612105576001600160a01b038381166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928692909116906316345f1890602401602060405180830381865afa158015612078573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209c9190615ecb565b6120a69190615d93565b6120b09190615dc0565b336000908152600c602052604090205490915081106120de57336000908152600c6020526040812055612103565b336000908152600c6020526040812080548392906120fd908490615d80565b90915550505b505b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa15801561214c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121709190615ecb565b9050828110156121925760405162461bcd60e51b81526004016111c390615ee4565b6001600160a01b038416600090815260106020526040812080548592906121ba908490615d80565b909155506121d490506001600160a01b038516338561556f565b6040518381523390600080516020615f88833981519152906020015b60405180910390a2505050611a986001600080516020615fa883398151915255565b61221a615537565b33600090815260086020526040902054811061226e5760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b60448201526064016111c3565b33600090815260086020526040812080548390811061228f5761228f615d54565b6000918252602082206005909102018054909250906122ae3385612dd1565b90506122ba8183615dd4565b9150816000036123015760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b60448201526064016111c3565b826003015442101561234d5760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b60448201526064016111c3565b600080845560048401805460ff1916600117905560128054849290612373908490615dd4565b909155505060035482116123a15781600160020160008282546123969190615d80565b909155506123a79050565b60006003555b33600090815260136020908152604091829020825160608101845287815291820185905260115490928201906123dd9042615dd4565b9052815460018082018455600093845260209384902083516003909302019182558284015190820155604091820151600290910155518381523391600080516020615f8883398151915291016121f0565b600a602052816000526040600020818154811061244a57600080fd5b600091825260209091206002909102018054600190910154909250905082565b33600090815260086020526040812080548490811061248b5761248b615d54565b60009182526020909120600590910201600481015490915060ff16156124ec5760405162461bcd60e51b81526020600482015260166024820152755374616b6520616c726561647920636f6d706c65746560501b60448201526064016111c3565b80546000036125315760405162461bcd60e51b815260206004820152601160248201527005374616b6520616d6f756e74206973203607c1b60448201526064016111c3565b336000908152601660209081526040808320868452909152902060020154156125945760405162461bcd60e51b81526020600482015260156024820152745374616b6520616c7265616479206f6e2073616c6560581b60448201526064016111c3565b6040518060a001604052808381526020016064601854856125b59190615d93565b6125bf9190615dc0565b81528254602080830191909152600180850154604080850191909152600280870154606095860152336000818152601686528381208b825286528381208851815588870151958101959095558784015192850192909255948601516003840155608090950151600490920191909155928455825185815290810186905290917f8e79b7ba8dab5ebfa59b9c6af1743c3ef14863680b3cc5ac837f8d636f76031c91015b60405180910390a2505050565b6008602052816000526040600020818154811061268b57600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919060ff1685565b6001600160a01b0382166000908152600c602052604081205481906126e490611200565b6002546126f19190615dd4565b90508215612709576014546127069082615dd4565b90505b9392505050565b3360009081526007602052604090205460ff1661273f5760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b0381166127655760405162461bcd60e51b81526004016111c390615e28565b6001600160a01b03166000908152600f60205260409020805460ff19169055565b3360009081526007602052604090205460ff166127b55760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b039182166000908152600b6020526040902080546001600160a01b03191691909216179055565b6000805b3360009081526008602052604090205481101561286f5733600090815260086020526040812080548390811061281f5761281f615d54565b9060005260206000209060050201905060008160000154111561285e5760006128483384612dd1565b90506128548185615dd4565b4260018401559350505b5061286881615de7565b90506127e7565b50600e5481116128ba5760405162461bcd60e51b8152602060048201526016602482015275139bdd08195b9bdd59da081d1bc818dbdb5c1bdd5b9960521b60448201526064016111c3565b336000818152600860209081526040808320815160a0810183528681524281850152948452600c90925291829020549092918201906128f890611200565b6002546129059190615dd4565b81526020016001600001544261291b9190615dd4565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff1916921515929092179091555461298c908290615dd4565b60035560405181815233907f3afe5b60dee16617a8adbbd7d6c28f17a27efabb834872efa8e7ad5dafddf6f19060200160405180910390a250565b80600003612a175760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f60448201526064016111c3565b6001600160a01b038083166000908152600b60205260409020541680612a8b5760405162461bcd60e51b815260206004820152602360248201527f5072696365206f7261636c65206e6f742073657420666f72207468697320746f60448201526235b2b760e91b60648201526084016111c3565b612aa06001600160a01b0384163330856154d0565b60006064612aaf600a85615d93565b612ab99190615dc0565b6001600160a01b038581166000818152600b60205260408082205490516302c68be360e31b8152600481019390935293945092670de0b6b3a76400009287929116906316345f1890602401602060405180830381865afa158015612b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b459190615ecb565b612b4f9190615d93565b612b599190615dc0565b9050600e548111612b7c5760405162461bcd60e51b81526004016111c390615e51565b336000908152600c602052604081208054839290612b9b908490615dd4565b90915550506001600160a01b03851660009081526010602052604081208054869290612bc8908490615dd4565b909155505033600090815260096020908152604091829020825161014081018452878152918201859052600d549092820190612c049042615dd4565b81526000602080830182905260408084018390524260608086018290526080808701929092526001600160a01b038d811660a08089019190915260c080890188905260e09889018c90528a5460018082018d559b8952978790208a51600990990201978855898701519a88019a909a558885015160028801559188015160038701559187015160048601558601516005850155958501516006840155928401516007830180546101008701511515600160a01b026001600160a81b031990911692909716919091179590951790945561012090920151600890920191909155805186815291820184905233917f9ade76f4385de306666dfb21a52b27d52db0fde8ad0f515fa261f532cac60d21910160405180910390a25050505050565b3360009081526007602052604090205460ff16612d515760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b03811660009081526007602052604090205460ff1615612dad5760405162461bcd60e51b815260206004820152601060248201526f20b63932b0b23c9030b71037bbb732b960811b60448201526064016111c3565b6001600160a01b03166000908152600760205260409020805460ff19166001179055565b6001600160a01b0382166000908152600860205260408120805482919084908110612dfe57612dfe615d54565b906000526020600020906005020190506000816001015442612e209190615d80565b90506000612710620151808385600201548660000154612e409190615d93565b612e4a9190615d93565b612e549190615dc0565b612e5e9190615dc0565b9695505050505050565b3360009081526007602052604090205460ff16612e975760405162461bcd60e51b81526004016111c390615e00565b6000548110612ede5760405162461bcd60e51b8152602060048201526013602482015272496e646578206f7574206f6620626f756e647360681b60448201526064016111c3565b805b600054612eef90600190615d80565b811015612f6c576000612f03826001615dd4565b81548110612f1357612f13615d54565b906000526020600020906003020160008281548110612f3457612f34615d54565b60009182526020909120825460039092020190815560018083015490820155600291820154910155612f6581615de7565b9050612ee0565b506000805480612f7e57612f7e615f5d565b6000828152602081206003600019909301928302018181556001810182905560020155905550565b6001600160a01b0381166000908152600960209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561308257600084815260209081902060408051610140810182526009860290920180548352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a0840152600681015460c084015260078101546001600160a01b03811660e0850152600160a01b900460ff161515610100840152600801546101208301529083529092019101612fde565b505050509050919050565b6001600160a01b0381166000908152600860209081526040808320805482518185028101850190935280835260609492939192909184015b828210156130825760008481526020908190206040805160a081018252600586029092018054835260018082015484860152600282015492840192909252600381015460608401526004015460ff161515608083015290835290920191016130c5565b6001600160a01b038116600090815260096020526040812054815b818110156132f4576001600160a01b038416600090815260096020526040812080548390811061317557613175615d54565b600091825260209182902060408051610140810182526009909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260078201546001600160a01b03811660e083015260ff600160a01b909104161515610100820181905260089092015461012082015291506132e15760e0810180516001600160a01b039081166000908152600b602052604080822054935190516302c68be360e31b815290831660048201529092909116906316345f1890602401602060405180830381865afa158015613272573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132969190615ecb565b90506000826060015183600001516132ae9190615d80565b90506000670de0b6b3a76400006132c58385615d93565b6132cf9190615dc0565b90506132db8188615dd4565b96505050505b50806132ec81615de7565b915050613143565b5050919050565b6005546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613348573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061336c9190615ecb565b9050601254811061337f57600091505090565b8060125461338d9190615d80565b91505090565b6001600160a01b03821660009081526009602052604081208054829190849081106133c0576133c0615d54565b9060005260206000209060090201905060008160060154426133e29190615d80565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a602052604090205481101561105a576001600160a01b0383166000908152600a6020526040812080548390811061344157613441615d54565b60009182526020909120600290910201805460018201549192509081871061348b57875461271090613474908390615d93565b61347e9190615dc0565b6134889086615dd4565b94505b5050508061349890615de7565b90506133f7565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156134e55750825b905060008267ffffffffffffffff1660011480156135025750303b155b905081158015613510575080155b1561352e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561355857845460ff60401b1916600160401b1785555b6135606155b4565b600680546001600160a01b03199081167341970ce76b656030a79e7c1fa76fc4eb93980255178255600760209081527f1428bfef657344f5f7a0019d1554dccabe000be344bb83cdab918bd50f24b573805460ff1990811660019081179092556301499700600d81905567de0b6b3a76400000600e556005805490951673833589fcd6edb6e08f4c7c32d4f71b54bda02913178555825560216002908155604080516060808201835268bdbc41e0348b300000825269021e0c0013070adc000082880190815282840187815260008054808a018255818052945160039586027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5638181019290925593517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5648086019190915592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565948501558651808601885269021e19e0c9bab2400000815269043c25e0dcc1bd1c0000818d01908152818901998a528354808d01855584805291519188028084019290925551818501559751978401979097558551808501875269043c33c1937564800000815269065a3fc1a67c6f5c0000818c019081528188018781528354808d0185558480529251928802808b019390935590518285015551908401558551808501875269065a4da25d3016c00000815269087859a27037219c0000818c0190815260048289019081528354808d0185558480529251928802808b0193909355905182850155519084015585518085018752690878678326eac90000008152690cb48d6403ac861c0000818c019081528188019c8d528254808c0184558380529151918702808a019290925551818401559a519a83019a909a5584518084018652690cb49b44ba602d80000081526910f0c1259721ea9c0000818b019081528187019c8d528b54808b018d558c805291519186028089019290925551818301559a519a82019a909a55835180830185526910f0cf064dd592000000815269152cf4e72a974f1c0000818a0190815260088287019081528b54808b018d558c80529251928602808901939093559051828d015551908201558351918201845269152d02c7e14af68000008252600019828901908152600a94830194855289548089018b558a805292519284029586019290925590519884019890985590519190960155600f9092527f77c9ddf83be31065a9eb7ed19d93a8a4db24cad8351f41cc546083ac9e9d8c7f8054831682179055737c40f272570fdf9549d6f67493ac250a1db52f279092527f1b209462f90614903451721396f08356b5037572bebcd67a02efc98f03bec9d1805490911690911790556201fa40601155601455831561399957845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b3360009081526007602052604090205460ff166139cf5760405162461bcd60e51b81526004016111c390615e00565b6005546139e6906001600160a01b0316338361556f565b6005546040518281526001600160a01b039091169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a350565b3360009081526007602052604090205460ff16613a5c5760405162461bcd60e51b81526004016111c390615e00565b601855565b3360009081526007602052604090205460ff16613a905760405162461bcd60e51b81526004016111c390615e00565b600554613aa8906001600160a01b03163330846154d0565b600454613ab6908290615dd4565b6004556040518181527f4e9221f2cca6ca0397acc6004ea0b716798254f5abcf53924fab34f0373e5d4e906020015b60405180910390a150565b33600090815260166020908152604080832084845290915281206002810154909103613b555760405162461bcd60e51b815260206004820152601460248201527314d95b1b081cdd185ad9481b9bdd08199bdd5b9960621b60448201526064016111c3565b336000908152600860205260408120805484908110613b7657613b76615d54565b906000526020600020906005020190508060000154600014613bda5760405162461bcd60e51b815260206004820152601760248201527f5374616b65206e6f7420696e2073656c6c20737461746500000000000000000060448201526064016111c3565b6002808301548255336000818152601660209081526040808320888452909152808220828155600181018390559384018290556003840182905560049093015590517f73d12dec3eb3b445b6c9feb2fd559ba7c852c525bc1e59d8f7ff760c55df041d906126629086815260200190565b3360009081526007602052604090205460ff16613c7a5760405162461bcd60e51b81526004016111c390615e00565b600e8190556040518181527fe5dadb089824c750e4e7a2e98bfbe130f1a09834769e81339639fbe18606859b90602001613ae5565b3360009081526007602052604090205460ff16613cde5760405162461bcd60e51b81526004016111c390615e00565b613ceb8262015180615d93565b600155600281905560408051838152602081018390527f7fa9647ec1cc14e3822b46d05a2b9d4e019bde8875c0088c46b6503d71bf1722910160405180910390a15050565b613d38615537565b336000908152600960205260408120805483908110613d5957613d59615d54565b600091825260209091206009909102016007810154909150600160a01b900460ff1615613dbc5760405162461bcd60e51b81526020600482015260116024820152705374616b6520697320436f6d706c65746560781b60448201526064016111c3565b6000613dc83384613393565b90508160030154811015613dee5760405162461bcd60e51b81526004016111c390615f2f565b6000826003015482613e009190615d80565b905080600003613e4e5760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b60448201526064016111c3565b808360030154613e5e9190615dd4565b60038401819055835411613e825760078301805460ff60a01b1916600160a01b1790555b336000908152600c602052604090205415613f905760078301546001600160a01b039081166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928592909116906316345f1890602401602060405180830381865afa158015613f03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f279190615ecb565b613f319190615d93565b613f3b9190615dc0565b336000908152600c60205260409020549091508110613f6957336000908152600c6020526040812055613f8e565b336000908152600c602052604081208054839290613f88908490615d80565b90915550505b505b60078301546001600160a01b031660009081526010602052604081208054839290613fbc908490615d80565b90915550506007830154613fda906001600160a01b0316338361556f565b604080518281526000602082015233917f4a94c2c356e29a6583071e731bdacf2ca56565ba5efebcff6936eb7923b5172191016121f0565b61403660405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152601360205260408120905b815481101561114e578382828154811061406c5761406c615d54565b906000526020600020906003020160000154036140d55781818154811061409557614095615d54565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505050611061565b806140df81615de7565b915050614050565b6140ef615537565b60648111156141405760405162461bcd60e51b815260206004820152601a60248201527f496e76616c69642072657374616b652070657263656e7461676500000000000060448201526064016111c3565b33600090815260086020526040812080548490811061416157614161615d54565b9060005260206000209060050201905080600001546000036141ba5760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b60448201526064016111c3565b80600301544210156142065760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b60448201526064016111c3565b805460006142143386612dd1565b90506142208183615dd4565b9150600060646142308685615d93565b61423a9190615dc0565b905060006142488285615d80565b6000865560048601805460ff19166001179055905080156143345780601260008282546142759190615dd4565b909155505060035481116142a35780600160020160008282546142989190615d80565b909155506142a99050565b60006003555b3360009081526013602090815260409182902082516060810184528a815291820184905260115490928201906142df9042615dd4565b9052815460018082018455600093845260209384902083516003909302019182558284015190820155604091820151600290910155518281523391600080516020615f88833981519152910160405180910390a25b811561445b573360009081526015602052604081205415614365575033600090815260156020526040902054614373565b6143703360016126c0565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a00160405280858152602001428152602001838152602001600160000154426143c69190615dd4565b81526000602091820181905283546001808201865594825290829020835160059092020190815582820151938101939093556040808301516002850155606083015160038501556080909201516004909301805460ff1916931515939093179092555184815233917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d910160405180910390a2505b50505050506144776001600080516020615fa883398151915255565b5050565b3360009081526007602052604090205460ff166144aa5760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b0381166144d05760405162461bcd60e51b81526004016111c390615e28565b6001600160a01b0316600090815260156020526040812055565b3360009081526007602052604090205460ff166145195760405162461bcd60e51b81526004016111c390615e00565b816000036145755760405162461bcd60e51b815260206004820152602360248201527f4c6f636b2074696d65206d7573742062652067726561746572207468616e207a60448201526265726f60e81b60648201526084016111c3565b806000036145db5760405162461bcd60e51b815260206004820152602d60248201527f50657263656e74616765207065722073746570206d757374206265206772656160448201526c746572207468616e207a65726f60981b60648201526084016111c3565b6127106145e88282615f73565b156146405760405162461bcd60e51b815260206004820152602260248201527f50657263656e74616765206d757374206469766964652031303025206576656e6044820152616c7960f01b60648201526084016111c3565b600061464c8383615dc0565b9050600061465a8286615dc0565b6001600160a01b0387166000908152600a6020526040812091925061467f91906158a4565b60015b8281116146f4576001600160a01b0387166000908152600a602052604090819020815180830190925290806146b78486615d93565b8152602090810188905282546001818101855560009485529382902083516002909202019081559101519101556146ed81615de7565b9050614682565b506040516001600160a01b038716907fde4b6ccc38b84f88129403b65a309f9b1c41d4c316bc2118d7614e449b9d4c4590600090a2505050505050565b6009602052816000526040600020818154811061474d57600080fd5b6000918252602090912060099091020180546001820154600283015460038401546004850154600586015460068701546007880154600890980154969950949750929591949093916001600160a01b03811691600160a01b90910460ff16908a565b6001600160a01b0382166000908152600960205260408120805460609283929091859081106147e0576147e0615d54565b600091825260208083206007600990930201918201546001600160a01b0316808452600a9091526040832054919350918167ffffffffffffffff81111561482957614829615f19565b604051908082528060200260200182016040528015614852578160200160208202803683370190505b50905060008267ffffffffffffffff81111561487057614870615f19565b604051908082528060200260200182016040528015614899578160200160208202803683370190505b50905060005b83811015614946576001600160a01b0385166000908152600a602052604081208054839081106148d1576148d1615d54565b90600052602060002090600202019050806000015487600601546148f59190615dd4565b84838151811061490757614907615d54565b602002602001018181525050806001015483838151811061492a5761492a615d54565b60209081029190910101525061493f81615de7565b905061489f565b50909890975095505050505050565b6013602052816000526040600020818154811061497157600080fd5b600091825260209091206003909102018054600182015460029092015490935090915083565b6001600160a01b0381166000908152601360209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561308257838290600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050815260200190600101906149cf565b3360009081526007602052604090205460ff16614a4e5760405162461bcd60e51b81526004016111c390615e00565b601155565b60008181548110614a6357600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b3360009081526007602052604090205460ff16614ab55760405162461bcd60e51b81526004016111c390615e00565b601455565b614ac2615537565b336000908152600960205260408120805483908110614ae357614ae3615d54565b906000526020600020906009020190506000614aff3384610f2f565b90508160040154811015614b255760405162461bcd60e51b81526004016111c390615f2f565b6000826004015482614b379190615d80565b905080600003614b855760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b60448201526064016111c3565b808360040154614b959190615dd4565b83600401819055508060126000828254614baf9190615dd4565b909155505033600090815260136020526040908190208151606081019092529080614bdd87620f4240615dd4565b815260200183815260200160115442614bf69190615dd4565b90528154600180820184556000938452602093849020835160039093020191825582840151908201556040918201516002909101555182815233917f4e69fdc49495bcab2b4375781457ba16653a90eb4ffb6588351bdc39071433e291016121f0565b3360009081526007602052604090205460ff16614c885760405162461bcd60e51b81526004016111c390615e00565b818310614cec5760405162461bcd60e51b815260206004820152602c60248201527f496e76616c69642072616e67653a206d696e546f6b656e73206d75737420626560448201526b203c206d6178546f6b656e7360a01b60648201526084016111c3565b614cf683836155c4565b15614d4e5760405162461bcd60e51b815260206004820152602260248201527f52616e6765206f7665726c6170732077697468206578697374696e6720746965604482015261727360f01b60648201526084016111c3565b60005b600054811015614df5578360008281548110614d6f57614d6f615d54565b906000526020600020906003020160000154148015614db157508260008281548110614d9d57614d9d615d54565b906000526020600020906003020160010154145b15614de5578160008281548110614dca57614dca615d54565b90600052602060002090600302016002018190555050505050565b614dee81615de7565b9050614d51565b5060408051606081018252848152602081018481529181018381526000805460018101825590805291517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56360039093029283015591517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56482015590517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56590910155614e9e615653565b505050565b600080805b6001600160a01b038416600090815260086020526040902054811015614ef4576000614ed48583612dd1565b9050614ee08184615dd4565b92505080614eed90615de7565b9050614ea8565b5092915050565b3360009081526007602052604090205460ff16614f2a5760405162461bcd60e51b81526004016111c390615e00565b80600003614f6b5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b60448201526064016111c3565b60086000836001600160a01b03166001600160a01b031681526020019081526020016000206040518060a001604052808381526020014281526020016001800154815260200160016000015442614fc29190615dd4565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff19169215159290921790915554615033908290615dd4565b6003556040518181526001600160a01b038316907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d90602001611593565b6001600160a01b0382166000908152601660209081526040808320848452909152812060028101549091036150e85760405162461bcd60e51b815260206004820152601860248201527f53656c6c207374616b65206e6f7420617661696c61626c65000000000000000060448201526064016111c3565b8054600554615106916001600160a01b0390911690339030906154d0565b60006064601754836000015461511c9190615d93565b6151269190615dc0565b600554909150615140906001600160a01b0316858361556f565b6001600160a01b038416600090815260086020526040812080548590811061516a5761516a615d54565b600091825260208083206004600590930201918201805460ff191660019081179091553384526008909152604092839020835160a0810190945290860154600287015492945090929182916151be91615dd4565b81526020018560030154815260200185600401548152602001600160000154426151e89190615dd4565b8152600060209182018190528354600180820186559482528282208451600590920201908155838301518186015560408085015160028084019190915560608601516003808501919091556080909601516004938401805460ff19169115159190911790556001600160a01b038c16808552601686528285208c865286528285208581559788018590559087018490559486018390559401558554835190815290810187905233927f7bb39d095b04a9986ed34adf14d74c33294d0a9e807f02bf634d532507422eba910160405180910390a35050505050565b336000908152601660209081526040808320858452909152812060028101549091036153275760405162461bcd60e51b815260206004820152601460248201527314d95b1b081cdd185ad9481b9bdd08199bdd5b9960621b60448201526064016111c3565b6064601854836153379190615d93565b6153419190615dc0565b6001820155818155604080518381526020810185905233917f8e79b7ba8dab5ebfa59b9c6af1743c3ef14863680b3cc5ac837f8d636f76031c9101612662565b336000908152600f602052604090205460ff166153b05760405162461bcd60e51b81526004016111c390615e94565b6000805b6001600160a01b03831660009081526013602052604090205481101561543b576001600160a01b03831660009081526013602052604081208054839081106153fe576153fe615d54565b9060005260206000209060030201905080600101548361541e9190615dd4565b6000600190920191909155915061543481615de7565b90506153b4565b50806012600082825461544e9190615d80565b90915550505050565b3360009081526007602052604090205460ff166154865760405162461bcd60e51b81526004016111c390615e00565b6001600160a01b0381166154ac5760405162461bcd60e51b81526004016111c390615e28565b6001600160a01b03166000908152600f60205260409020805460ff19166001179055565b6040516001600160a01b0384811660248301528381166044830152606482018390526117969186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506157e2565b600080516020615fa883398151915280546001190161556957604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6040516001600160a01b03838116602483015260448201839052614e9e91859182169063a9059cbb90606401615505565b6001600080516020615fa883398151915255565b6155bc615853565b611bfb61589c565b6000805b60005481101561564957600081815481106155e5576155e5615d54565b906000526020600020906003020160010154841115801561562a57506000818154811061561457615614615d54565b9060005260206000209060030201600001548310155b15615639576001915050611061565b61564281615de7565b90506155c8565b5060009392505050565b60005b600054811015611a9857600061566d826001615dd4565b90505b6000548110156157d1576000818154811061568d5761568d615d54565b906000526020600020906003020160000154600083815481106156b2576156b2615d54565b90600052602060002090600302016000015411156157bf5760008083815481106156de576156de615d54565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505090506000828154811061572a5761572a615d54565b90600052602060002090600302016000848154811061574b5761574b615d54565b9060005260206000209060030201600082015481600001556001820154816001015560028201548160020155905050806000838154811061578e5761578e615d54565b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020155905050505b806157c981615de7565b915050615670565b506157db81615de7565b9050615656565b600080602060008451602086016000885af180615805576040513d6000823e3d81fd5b50506000513d9150811561581d57806001141561582a565b6001600160a01b0384163b155b1561179657604051635274afe760e01b81526001600160a01b03851660048201526024016111c3565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16611bfb57604051631afcd79f60e31b815260040160405180910390fd5b6155a0615853565b5080546000825560020290600052602060002090810190611a9891905b808211156158db57600080825560018201556002016158c1565b5090565b80356001600160a01b03811681146158f657600080fd5b919050565b60006020828403121561590d57600080fd5b612709826158df565b6000806040838503121561592957600080fd5b615932836158df565b946020939093013593505050565b81518152602080830151908201526040808301519082015260608101611061565b60006020828403121561597357600080fd5b5035919050565b6000806020838503121561598d57600080fd5b823567ffffffffffffffff808211156159a557600080fd5b818501915085601f8301126159b957600080fd5b8135818111156159c857600080fd5b86602060a0830285010111156159dd57600080fd5b60209290920196919550909350505050565b60008060208385031215615a0257600080fd5b823567ffffffffffffffff80821115615a1a57600080fd5b818501915085601f830112615a2e57600080fd5b813581811115615a3d57600080fd5b8660208260051b85010111156159dd57600080fd5b600081518084526020808501945080840160005b83811015615a8257815187529582019590820190600101615a66565b509495945050505050565b606081526000615aa06060830186615a52565b8281036020840152615ab28186615a52565b915050826040830152949350505050565b60008060408385031215615ad657600080fd5b50508035926020909101359150565b60008060408385031215615af857600080fd5b615b01836158df565b915060208301358015158114615b1657600080fd5b809150509250929050565b60008060408385031215615b3457600080fd5b615b3d836158df565b9150615b4b602084016158df565b90509250929050565b602080825282518282018190526000919060409081850190868401855b82811015615bf55781518051855286810151878601528581015186860152606080820151908601526080808201519086015260a0808201519086015260c0808201519086015260e0808201516001600160a01b0316908601526101008082015115159086015261012090810151908501526101409093019290850190600101615b71565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015615bf557815180518552868101518786015285810151868601526060808201519086015260809081015115159085015260a09093019290850190600101615c1f565b600080600060608486031215615c7a57600080fd5b615c83846158df565b95602085013595506040909401359392505050565b604081526000615cab6040830185615a52565b8281036020840152615cbd8185615a52565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015615d1c57615d098385518051825260208082015190830152604090810151910152565b9284019260609290920191600101615ce2565b50909695505050505050565b600080600060608486031215615d3d57600080fd5b505081359360208301359350604090920135919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561106157611061615d6a565b808202811582820484141761106157611061615d6a565b634e487b7160e01b600052601260045260246000fd5b600082615dcf57615dcf615daa565b500490565b8082018082111561106157611061615d6a565b600060018201615df957615df9615d6a565b5060010190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b60208082526023908201527f416d6f756e74206d7573742062652067726561746572206d696e5374616b654c6040820152626f636b60e81b606082015260800190565b6020808252601f908201527f43616c6c6572206973206e6f7420616e20617574686f72697a656420626f7400604082015260600190565b600060208284031215615edd57600080fd5b5051919050565b6020808252818101527f496e73756666696369656e74207265776172647320696e2074686520706f6f6c604082015260600190565b634e487b7160e01b600052604160045260246000fd5b602080825260149082015273125b9d985b1a590818db185a5b48185b5bdd5b9d60621b604082015260600190565b634e487b7160e01b600052603160045260246000fd5b600082615f8257615f82615daa565b50069056fe106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f72419b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a2646970667358221220d496485ba7f610817305b5625a528c4e80ffc695bc4c437518865ea4694bfb0464736f6c63430008140033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.