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; } struct SellStakeKey { address seller; uint256 stakeId; } 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; SellStakeKey[] public sellStakeKeys; mapping(address => mapping(uint256 => uint256)) private sellStakeKeyIndex; // 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; // // 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 *commented out for size constraints* // 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"); // 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); } stakes[msg.sender].push(Stake({ amount: totalReward, lastClaimed: block.timestamp, dailyRewardRate: finalRewardRate, 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; // Add the key to the iteration array. sellStakeKeys.push(SellStakeKey({ seller: msg.sender, stakeId: _stakeId })); sellStakeKeyIndex[msg.sender][_stakeId] = sellStakeKeys.length - 1; 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]; // Remove the key from the iteration array using swap-and-pop. uint256 index = sellStakeKeyIndex[msg.sender][_stakeId]; uint256 lastIndex = sellStakeKeys.length - 1; if (index != lastIndex) { SellStakeKey memory lastKey = sellStakeKeys[lastIndex]; sellStakeKeys[index] = lastKey; sellStakeKeyIndex[lastKey.seller][lastKey.stakeId] = index; } sellStakeKeys.pop(); delete sellStakeKeyIndex[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 nonReentrant { 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 * (100 - 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]; // Remove the key from the iteration array. uint256 index = sellStakeKeyIndex[seller][_stakeId]; uint256 lastIndex = sellStakeKeys.length - 1; if (index != lastIndex) { SellStakeKey memory lastKey = sellStakeKeys[lastIndex]; sellStakeKeys[index] = lastKey; sellStakeKeyIndex[lastKey.seller][lastKey.stakeId] = index; } sellStakeKeys.pop(); delete sellStakeKeyIndex[seller][_stakeId]; emit StakeSold(seller, msg.sender, sellStakeEntry.price, _stakeId); } /// @notice Returns all active sell stakes with their keys. /// @return sellers Array of seller addresses for each stake /// @return stakeIds Array of stake IDs corresponding to each seller /// @return sellStakeData Array of SellStake structs containing the sell stake data function getAllSellStakesWithKeys() external view returns ( address[] memory sellers, uint256[] memory stakeIds, SellStake[] memory sellStakeData ) { uint256 length = sellStakeKeys.length; sellers = new address[](length); stakeIds = new uint256[](length); sellStakeData = new SellStake[](length); for (uint256 i = 0; i < length; i++) { SellStakeKey memory key = sellStakeKeys[i]; sellers[i] = key.seller; stakeIds[i] = key.stakeId; // Copy the SellStake struct from storage to memory SellStake storage sourceStake = sellStakes[key.seller][key.stakeId]; sellStakeData[i] = SellStake({ price: sourceStake.price, bonusAmount: sourceStake.bonusAmount, amount: sourceStake.amount, lastClaimed: sourceStake.lastClaimed, dailyRewardRate: sourceStake.dailyRewardRate }); } return (sellers, stakeIds, sellStakeData); } }
// 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":"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":[],"name":"getAllSellStakesWithKeys","outputs":[{"internalType":"address[]","name":"sellers","type":"address[]"},{"internalType":"uint256[]","name":"stakeIds","type":"uint256[]"},{"components":[{"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"}],"internalType":"struct PacaFinanceWithBoostAndScheduleUSDC.SellStake[]","name":"sellStakeData","type":"tuple[]"}],"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":"_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":"uint256","name":"","type":"uint256"}],"name":"sellStakeKeys","outputs":[{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"stakeId","type":"uint256"}],"stateMutability":"view","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
608060405234801561001057600080fd5b50615d9f80620000216000396000f3fe6080604052600436106104315760003560e01c80637a0c6dc011610229578063b90fba191161012e578063cfb866da116100b6578063eb44e0a31161007a578063eb44e0a314610ebc578063f2bb563014610edc578063f8d8c61714610efc578063fc424c5314610f1c578063ffecf51614610f3257600080fd5b8063cfb866da14610e1c578063d6c680eb14610e3c578063d919302514610e5c578063da40ef8014610e7c578063e4d06f9014610e9c57600080fd5b8063bed9757e116100fd578063bed9757e14610d50578063c606627214610d7e578063c7b530b014610db9578063cc1776d314610de6578063ce13d09014610dfc57600080fd5b8063b90fba1914610c6e578063b92a349f14610c8e578063bd72169814610cae578063bd84477d14610cdb57600080fd5b80638da5cb5b116101b157806396ed7f891161018057806396ed7f8914610bca5780639726582714610bea578063ac97b41714610c0e578063b6c3dc4c14610c2e578063b8e7023d14610c4e57600080fd5b80638da5cb5b14610b5457806392257cb514610b74578063953d16bf14610b8a5780639562ee1514610baa57600080fd5b806380ca0ecf116101f857806380ca0ecf14610abf5780638129fc1c14610adf578063853e0df214610af4578063876b2d8314610b145780638bdf67f214610b3457600080fd5b80637a0c6dc014610a305780637ba6f45814610a5d5780637bc221ac14610a8a5780637f79496c14610aaa57600080fd5b80633ba8396e1161033a57806358116227116102c257806367a74ddc1161028657806367a74ddc1461099b5780636ae21510146109bb5780636c3b0c53146109d05780637065cb48146109f0578063710ea0ce14610a1057600080fd5b806358116227146108c4578063584b62a1146108e4578063592d1dd11461092e578063599ab2c41461095b5780635fecd9261461097b57600080fd5b806343c7c0111161030957806343c7c011146107fa578063441a41751461081a57806344c7d6ef1461085957806351f6cf2f146108795780635339dcc1146108ae57600080fd5b80633ba8396e146106fe5780633c92f98d1461072e5780633f35e7221461075d57806343a32f891461077d57600080fd5b806316f0115b116103bd5780631d7a33611161038c5780631d7a33611461068057806322a26fc0146106a05780632e1a7d4d146106b3578063372500ab146106d357806338a85ce2146106e857600080fd5b806316f0115b146105c9578063173825d91461062a5780631ada70a81461064a5780631bf6ddae1461066057600080fd5b80630a84096a116104045780630a84096a1461051a5780630d046d111461053a57806312185a391461056757806313c8e2de1461058957806316be9b2a146105a957600080fd5b80630137451814610436578063022914a7146104895780630519da32146104c9578063092c7610146104ed575b600080fd5b34801561044257600080fd5b5061046c610451366004615602565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561049557600080fd5b506104b96104a4366004615602565b60076020526000908152604090205460ff1681565b6040519015158152602001610480565b3480156104d557600080fd5b506104df60115481565b604051908152602001610480565b3480156104f957600080fd5b506104df610508366004615602565b60106020526000908152604090205481565b34801561052657600080fd5b506104df61053536600461561d565b610f52565b34801561054657600080fd5b5061055a61055536600461561d565b61108a565b6040516104809190615647565b34801561057357600080fd5b50610587610582366004615668565b6111ef565b005b34801561059557600080fd5b506104df6105a4366004615668565b611223565b3480156105b557600080fd5b506105876105c436600461561d565b6112d4565b3480156105d557600080fd5b506001546002546003546004546005546105f994939291906001600160a01b031685565b6040805195865260208601949094529284019190915260608301526001600160a01b0316608082015260a001610480565b34801561063657600080fd5b50610587610645366004615602565b611345565b34801561065657600080fd5b506104df600d5481565b34801561066c57600080fd5b5061058761067b366004615668565b61143d565b34801561068c57600080fd5b5061058761069b366004615602565b6115c2565b6105876106ae366004615681565b61169b565b3480156106bf57600080fd5b506105876106ce366004615668565b6117bf565b3480156106df57600080fd5b50610587611abe565b3480156106f457600080fd5b506104df600e5481565b34801561070a57600080fd5b506104b9610719366004615602565b600f6020526000908152604090205460ff1681565b34801561073a57600080fd5b5061074e6107493660046156f6565b611c20565b60405161048093929190615794565b34801561076957600080fd5b5061058761077836600461561d565b611e10565b34801561078957600080fd5b506107d261079836600461561d565b6016602090815260009283526040808420909152908252902080546001820154600283015460038401546004909401549293919290919085565b604080519586526020860194909452928401919091526060830152608082015260a001610480565b34801561080657600080fd5b50610587610815366004615602565b611e97565b34801561082657600080fd5b5061083a610835366004615668565b612235565b604080516001600160a01b039093168352602083019190915201610480565b34801561086557600080fd5b50610587610874366004615668565b61226d565b34801561088557600080fd5b5061089961089436600461561d565b612489565b60408051928352602083019190915201610480565b3480156108ba57600080fd5b506104df60145481565b3480156108d057600080fd5b506105876108df3660046157ca565b6124c5565b3480156108f057600080fd5b506109046108ff36600461561d565b61277f565b6040805195865260208601949094529284019190915260608301521515608082015260a001610480565b34801561093a57600080fd5b506104df610949366004615602565b600c6020526000908152604090205481565b34801561096757600080fd5b506104df6109763660046157ec565b6127d0565b34801561098757600080fd5b50610587610996366004615602565b612820565b3480156109a757600080fd5b506105876109b6366004615828565b612896565b3480156109c757600080fd5b506105876128f3565b3480156109dc57600080fd5b506105876109eb36600461561d565b612afc565b3480156109fc57600080fd5b50610587610a0b366004615602565b612e58565b348015610a1c57600080fd5b506104df610a2b36600461561d565b612f07565b348015610a3c57600080fd5b50610a50610a4b366004615602565b612f9e565b604051610480919061585b565b348015610a6957600080fd5b50610a7d610a78366004615602565b613085565b6040516104809190615909565b348015610a9657600080fd5b506104df610aa5366004615602565b613120565b348015610ab657600080fd5b506104df6132f3565b348015610acb57600080fd5b506104df610ada36600461561d565b61338b565b348015610aeb57600080fd5b50610587613497565b348015610b0057600080fd5b50610587610b0f366004615668565b613602565b348015610b2057600080fd5b50610587610b2f366004615668565b61368f565b348015610b4057600080fd5b50610587610b4f366004615668565b6136c3565b348015610b6057600080fd5b5060065461046c906001600160a01b031681565b348015610b8057600080fd5b506104df60125481565b348015610b9657600080fd5b50610587610ba5366004615668565b613752565b348015610bb657600080fd5b50610587610bc5366004615668565b6139e4565b348015610bd657600080fd5b50610587610be53660046157ca565b613a48565b348015610bf657600080fd5b50610bff613ac9565b6040516104809392919061596c565b348015610c1a57600080fd5b50610587610c29366004615668565b613d2a565b348015610c3a57600080fd5b5061055a610c4936600461561d565b61400c565b348015610c5a57600080fd5b50610587610c693660046157ca565b6140e1565b348015610c7a57600080fd5b50610587610c89366004615602565b614475565b348015610c9a57600080fd5b50610587610ca9366004615a33565b6144e4565b348015610cba57600080fd5b506104df610cc9366004615602565b60156020526000908152604090205481565b348015610ce757600080fd5b50610cfb610cf636600461561d565b61472b565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925260a086015260c08501526001600160a01b031660e0840152151561010083015261012082015261014001610480565b348015610d5c57600080fd5b50610d70610d6b36600461561d565b6147a9565b604051610480929190615a66565b348015610d8a57600080fd5b50610d9e610d9936600461561d565b61494f565b60408051938452602084019290925290820152606001610480565b348015610dc557600080fd5b50610dd9610dd4366004615602565b614991565b6040516104809190615a94565b348015610df257600080fd5b506104df60175481565b348015610e0857600080fd5b50610587610e17366004615668565b614a19565b348015610e2857600080fd5b50610d9e610e37366004615668565b614a4d565b348015610e4857600080fd5b50610587610e57366004615668565b614a80565b348015610e6857600080fd5b50610587610e77366004615668565b614ab4565b348015610e8857600080fd5b506104df610e97366004615602565b614c53565b348015610ea857600080fd5b50610587610eb736600461561d565b614cab565b348015610ec857600080fd5b50610587610ed736600461561d565b614e21565b348015610ee857600080fd5b50610587610ef73660046157ca565b6151e2565b348015610f0857600080fd5b50610587610f17366004615602565b6152a1565b348015610f2857600080fd5b506104df60185481565b348015610f3e57600080fd5b50610587610f4d366004615602565b615377565b6001600160a01b0382166000908152600960205260408120805482919084908110610f7f57610f7f615af6565b906000526020600020906009020190506000816006015442610fa19190615b22565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a602052604090205481101561107d576001600160a01b0383166000908152600a6020526040812080548390811061100057611000615af6565b6000918252602082206002909102018054600182015460088a01549294509092909160649061103190600a90615b35565b61103b9190615b62565b9050828810611068576127106110518383615b35565b61105b9190615b62565b6110659087615b76565b95505b505050508061107690615b89565b9050610fb6565b5093505050505b92915050565b6110ae60405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152601360205260408120906110d484620f4240615b76565b905060005b825481101561117157818382815481106110f5576110f5615af6565b9060005260206000209060030201600001540361115f5782818154811061111e5761111e615af6565b906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820154815250509350505050611084565b8061116981615b89565b9150506110d9565b5060405162461bcd60e51b815260206004820152604160248201527f57697468647261775374616b652077697468207468652073706563696669656460448201527f207374616b654964206e6f7420666f756e6420666f72207468697320757365726064820152601760f91b608482015260a4015b60405180910390fd5b3360009081526007602052604090205460ff1661121e5760405162461bcd60e51b81526004016111e690615ba2565b601755565b6000805b6000548110156112cb576000818154811061124457611244615af6565b906000526020600020906003020160000154831015801561128957506000818154811061127357611273615af6565b9060005260206000209060030201600101548311155b156112bb57600081815481106112a1576112a1615af6565b906000526020600020906003020160020154915050919050565b6112c481615b89565b9050611227565b50600092915050565b3360009081526007602052604090205460ff166113035760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b0382166113295760405162461bcd60e51b81526004016111e690615bca565b6001600160a01b03909116600090815260156020526040902055565b3360009081526007602052604090205460ff166113745760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b03811660009081526007602052604090205460ff166113cb5760405162461bcd60e51b815260206004820152600c60248201526b2737ba1030b71037bbb732b960a11b60448201526064016111e6565b336001600160a01b0382160361141c5760405162461bcd60e51b815260206004820152601660248201527521b0b73737ba103932b6b7bb32903cb7bab939b2b63360511b60448201526064016111e6565b6001600160a01b03166000908152600760205260409020805460ff19169055565b600e5461144f8264e8d4a51000615b35565b1161146c5760405162461bcd60e51b81526004016111e690615bf3565b600554611484906001600160a01b03163330846153f0565b33600090815260156020526040812054156114af5750336000908152601560205260409020546114bd565b6114ba3360006127d0565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a00160405280848152602001428152602001838152602001600160000154426115109190615b76565b815260006020918201819052835460018082018655948252828220845160059092020190815591830151938201939093556040820151600282015560608201516003808301919091556080909201516004909101805460ff19169115159190911790558054849290611583908490615b76565b909155505060405182815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906020015b60405180910390a25050565b336000908152600f602052604090205460ff166115f15760405162461bcd60e51b81526004016111e690615c36565b6000805b6001600160a01b038316600090815260086020526040902054811015611685576001600160a01b038316600090815260086020526040812080548390811061163f5761163f615af6565b9060005260206000209060050201905080600001548361165f9190615b76565b600082556004909101805460ff19166001179055915061167e81615b89565b90506115f5565b50600354611694908290615b22565b6003555050565b336000908152600f602052604090205460ff166116ca5760405162461bcd60e51b81526004016111e690615c36565b8060005b818110156117b957368484838181106116e9576116e9615af6565b905060a00201905080602001356001600201546117069190615b76565b6003556008600061171a6020840184615602565b6001600160a01b0316815260208082019290925260409081016000908120825160a08101845285850135815285840135818601908152608080880135958301958652606097880135978301978852820184815283546001808201865594865296909420915160059096029091019485555184820155915160028401559251600383015591516004909101805460ff1916911515919091179055016116ce565b50505050565b6117c7615457565b336000908152601360205260408120805461182f5760405162461bcd60e51b815260206004820152602260248201527f4e6f207374616b657320617661696c61626c6520666f72207769746864726177604482015261185b60f21b60648201526084016111e6565b60005b8154811015611a6557600082828154811061184f5761184f615af6565b9060005260206000209060030201905084816000015403611a545780600101546000036118d05760405162461bcd60e51b815260206004820152602960248201527f5374616b6520616c72656164792077697468647261776e206f7220646f6573206044820152681b9bdd08195e1a5cdd60ba1b60648201526084016111e6565b80600201544210156119245760405162461bcd60e51b815260206004820152601e60248201527f5769746864726177205374616b65206973207374696c6c206c6f636b6564000060448201526064016111e6565b80600101549350620f424085106119475761194464e8d4a5100085615b62565b93505b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015611990573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b49190615c6d565b9050848110156119d65760405162461bcd60e51b81526004016111e690615c86565b8160010154601260008282546119ec9190615b22565b909155505060006001830155600554611a0f906001600160a01b0316338761548f565b604080518681526020810188905233917f933735aa8de6d7547d0126171b2f31b9c34dd00f3ecd4be85a0ba047db4fafef910160405180910390a25050505050611aa4565b50611a5e81615b89565b9050611832565b5060405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b60448201526064016111e6565b611abb6001600080516020615d4a83398151915255565b50565b611ac6615457565b6000805b33600090815260086020526040902054811015611b5257336000908152600860205260408120805483908110611b0257611b02615af6565b90600052602060002090600502019050600081600001541115611b41576000611b2b3384612f07565b9050611b378185615b76565b4260018401559350505b50611b4b81615b89565b9050611aca565b5080600003611b995760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b60448201526064016111e6565b600454811115611bbb5760405162461bcd60e51b81526004016111e690615c86565b600454611bc9908290615b22565b600455600554611be3906001600160a01b0316338361548f565b6040518181523390600080516020615d2a8339815191529060200160405180910390a250611c1e6001600080516020615d4a83398151915255565b565b6060806000838067ffffffffffffffff811115611c3f57611c3f615cbb565b604051908082528060200260200182016040528015611c68578160200160208202803683370190505b5093508067ffffffffffffffff811115611c8457611c84615cbb565b604051908082528060200260200182016040528015611cad578160200160208202803683370190505b50925060005b81811015611e07576000878783818110611ccf57611ccf615af6565b9050602002016020810190611ce49190615602565b6001600160a01b0381166000908152601060205260409020548751919250908190889085908110611d1757611d17615af6565b6020908102919091018101919091526001600160a01b038381166000818152600b90935260408084205490516302c68be360e31b81526004810192909252909116906316345f1890602401602060405180830381865afa158015611d7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da39190615c6d565b90506000670de0b6b3a7640000611dba8484615b35565b611dc49190615b62565b905080888681518110611dd957611dd9615af6565b6020908102919091010152611dee8188615b76565b9650505050508080611dff90615b89565b915050611cb3565b50509250925092565b3360009081526007602052604090205460ff16611e3f5760405162461bcd60e51b81526004016111e690615ba2565b611e536001600160a01b038316338361548f565b6040518181526001600160a01b0383169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a35050565b611e9f615457565b60008060005b33600090815260096020526040902054811015611fd857336000908152600960205260408120805483908110611edd57611edd615af6565b6000918252602090912060099091020160078101549091506001600160a01b038681169116148015611f1b57506007810154600160a01b900460ff16155b15611fc7576000611f2c338461338b565b90508160030154811015611f525760405162461bcd60e51b81526004016111e690615cd1565b6000826003015482611f649190615b22565b90508015611fc457808360030154611f7c9190615b76565b6003840155611f8b8187615b76565b4260058501558354600385015491975011611fb65760078301805460ff60a01b1916600160a01b1790555b84611fc081615b89565b9550505b50505b50611fd181615b89565b9050611ea5565b508160000361201f5760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b60448201526064016111e6565b336000908152600c602052604090205415612128576001600160a01b038381166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928692909116906316345f1890602401602060405180830381865afa15801561209b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120bf9190615c6d565b6120c99190615b35565b6120d39190615b62565b336000908152600c6020526040902054909150811061210157336000908152600c6020526040812055612126565b336000908152600c602052604081208054839290612120908490615b22565b90915550505b505b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa15801561216f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121939190615c6d565b9050828110156121b55760405162461bcd60e51b81526004016111e690615c86565b6001600160a01b038416600090815260106020526040812080548592906121dd908490615b22565b909155506121f790506001600160a01b038516338561548f565b6040518381523390600080516020615d2a833981519152906020015b60405180910390a2505050611abb6001600080516020615d4a83398151915255565b6019818154811061224557600080fd5b6000918252602090912060029091020180546001909101546001600160a01b03909116915082565b612275615457565b3360009081526008602052604090205481106122c95760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b60448201526064016111e6565b3360009081526008602052604081208054839081106122ea576122ea615af6565b6000918252602082206005909102018054909250906123093385612f07565b90506123158183615b76565b91508160000361235c5760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b60448201526064016111e6565b82600301544210156123a85760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b60448201526064016111e6565b600080845560048401805460ff19166001179055601280548492906123ce908490615b76565b909155505060035482116123fc5781600160020160008282546123f19190615b22565b909155506124029050565b60006003555b33600090815260136020908152604091829020825160608101845287815291820185905260115490928201906124389042615b76565b9052815460018082018455600093845260209384902083516003909302019182558284015190820155604091820151600290910155518381523391600080516020615d2a8339815191529101612213565b600a60205281600052604060002081815481106124a557600080fd5b600091825260209091206002909102018054600190910154909250905082565b3360009081526008602052604081208054849081106124e6576124e6615af6565b60009182526020909120600590910201600481015490915060ff16156125475760405162461bcd60e51b81526020600482015260166024820152755374616b6520616c726561647920636f6d706c65746560501b60448201526064016111e6565b805460000361258c5760405162461bcd60e51b815260206004820152601160248201527005374616b6520616d6f756e74206973203607c1b60448201526064016111e6565b336000908152601660209081526040808320868452909152902060020154156125ef5760405162461bcd60e51b81526020600482015260156024820152745374616b6520616c7265616479206f6e2073616c6560581b60448201526064016111e6565b6040518060a001604052808381526020016064601854856126109190615b35565b61261a9190615b62565b81528254602080830191909152600180850154604080850191909152600280870154606095860152336000818152601686528381208b82528652838120885181558887015181870155888501518185015596880151600388015560809097015160049096019590955585875581518083019092529381529182018781526019805480840182559581905292517f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c96959590940294850180546001600160a01b0319166001600160a01b039095169490941790935591517f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c96969093019290925590546127229190615b22565b336000818152601a6020908152604080832088845282529182902093909355805185815292830186905290917f8e79b7ba8dab5ebfa59b9c6af1743c3ef14863680b3cc5ac837f8d636f76031c91015b60405180910390a2505050565b6008602052816000526040600020818154811061279b57600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919060ff1685565b6001600160a01b0382166000908152600c602052604081205481906127f490611223565b6002546128019190615b76565b90508215612819576014546128169082615b76565b90505b9392505050565b3360009081526007602052604090205460ff1661284f5760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b0381166128755760405162461bcd60e51b81526004016111e690615bca565b6001600160a01b03166000908152600f60205260409020805460ff19169055565b3360009081526007602052604090205460ff166128c55760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b039182166000908152600b6020526040902080546001600160a01b03191691909216179055565b6000805b3360009081526008602052604090205481101561297f5733600090815260086020526040812080548390811061292f5761292f615af6565b9060005260206000209060050201905060008160000154111561296e5760006129583384612f07565b90506129648185615b76565b4260018401559350505b5061297881615b89565b90506128f7565b50600e5481116129ca5760405162461bcd60e51b8152602060048201526016602482015275139bdd08195b9bdd59da081d1bc818dbdb5c1bdd5b9960521b60448201526064016111e6565b33600090815260156020526040812054156129f5575033600090815260156020526040902054612a03565b612a003360006127d0565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a0016040528084815260200142815260200183815260200160016000015442612a569190615b76565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff19169215159290921790915554612ac7908390615b76565b60035560405182815233907f3afe5b60dee16617a8adbbd7d6c28f17a27efabb834872efa8e7ad5dafddf6f1906020016115b6565b80600003612b4c5760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f60448201526064016111e6565b6001600160a01b038083166000908152600b60205260409020541680612bc05760405162461bcd60e51b815260206004820152602360248201527f5072696365206f7261636c65206e6f742073657420666f72207468697320746f60448201526235b2b760e91b60648201526084016111e6565b612bd56001600160a01b0384163330856153f0565b60006064612be4600a85615b35565b612bee9190615b62565b6001600160a01b038581166000818152600b60205260408082205490516302c68be360e31b8152600481019390935293945092670de0b6b3a76400009287929116906316345f1890602401602060405180830381865afa158015612c56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7a9190615c6d565b612c849190615b35565b612c8e9190615b62565b9050600e548111612cb15760405162461bcd60e51b81526004016111e690615bf3565b336000908152600c602052604081208054839290612cd0908490615b76565b90915550506001600160a01b03851660009081526010602052604081208054869290612cfd908490615b76565b909155505033600090815260096020908152604091829020825161014081018452878152918201859052600d549092820190612d399042615b76565b81526000602080830182905260408084018390524260608086018290526080808701929092526001600160a01b038d811660a08089019190915260c080890188905260e09889018c90528a5460018082018d559b8952978790208a51600990990201978855898701519a88019a909a558885015160028801559188015160038701559187015160048601558601516005850155958501516006840155928401516007830180546101008701511515600160a01b026001600160a81b031990911692909716919091179590951790945561012090920151600890920191909155805186815291820184905233917f9ade76f4385de306666dfb21a52b27d52db0fde8ad0f515fa261f532cac60d2191015b60405180910390a25050505050565b3360009081526007602052604090205460ff16612e875760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b03811660009081526007602052604090205460ff1615612ee35760405162461bcd60e51b815260206004820152601060248201526f20b63932b0b23c9030b71037bbb732b960811b60448201526064016111e6565b6001600160a01b03166000908152600760205260409020805460ff19166001179055565b6001600160a01b0382166000908152600860205260408120805482919084908110612f3457612f34615af6565b906000526020600020906005020190506000816001015442612f569190615b22565b90506000612710620151808385600201548660000154612f769190615b35565b612f809190615b35565b612f8a9190615b62565b612f949190615b62565b9695505050505050565b6001600160a01b0381166000908152600960209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561307a57600084815260209081902060408051610140810182526009860290920180548352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a0840152600681015460c084015260078101546001600160a01b03811660e0850152600160a01b900460ff161515610100840152600801546101208301529083529092019101612fd6565b505050509050919050565b6001600160a01b0381166000908152600860209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561307a5760008481526020908190206040805160a081018252600586029092018054835260018082015484860152600282015492840192909252600381015460608401526004015460ff161515608083015290835290920191016130bd565b6001600160a01b038116600090815260096020526040812054815b818110156132ec576001600160a01b038416600090815260096020526040812080548390811061316d5761316d615af6565b600091825260209182902060408051610140810182526009909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260078201546001600160a01b03811660e083015260ff600160a01b909104161515610100820181905260089092015461012082015291506132d95760e0810180516001600160a01b039081166000908152600b602052604080822054935190516302c68be360e31b815290831660048201529092909116906316345f1890602401602060405180830381865afa15801561326a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061328e9190615c6d565b90506000826060015183600001516132a69190615b22565b90506000670de0b6b3a76400006132bd8385615b35565b6132c79190615b62565b90506132d38188615b76565b96505050505b50806132e481615b89565b91505061313b565b5050919050565b6005546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613340573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133649190615c6d565b9050601254811061337757600091505090565b806012546133859190615b22565b91505090565b6001600160a01b03821660009081526009602052604081208054829190849081106133b8576133b8615af6565b9060005260206000209060090201905060008160060154426133da9190615b22565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a602052604090205481101561107d576001600160a01b0383166000908152600a6020526040812080548390811061343957613439615af6565b6000918252602090912060029091020180546001820154919250908187106134835787546127109061346c908390615b35565b6134769190615b62565b6134809086615b76565b94505b5050508061349090615b89565b90506133ef565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156134dd5750825b905060008267ffffffffffffffff1660011480156134fa5750303b155b905081158015613508575080155b156135265760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561355057845460ff60401b1916600160401b1785555b6135586154d9565b600680546001600160a01b0319167341970ce76b656030a79e7c1fa76fc4eb9398025590811790915560005260076020527f1428bfef657344f5f7a0019d1554dccabe000be344bb83cdab918bd50f24b573805460ff1916600117905583156135fb57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b3360009081526007602052604090205460ff166136315760405162461bcd60e51b81526004016111e690615ba2565b600554613648906001600160a01b0316338361548f565b6005546040518281526001600160a01b039091169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a350565b3360009081526007602052604090205460ff166136be5760405162461bcd60e51b81526004016111e690615ba2565b601855565b3360009081526007602052604090205460ff166136f25760405162461bcd60e51b81526004016111e690615ba2565b60055461370a906001600160a01b03163330846153f0565b600454613718908290615b76565b6004556040518181527f4e9221f2cca6ca0397acc6004ea0b716798254f5abcf53924fab34f0373e5d4e906020015b60405180910390a150565b336000908152601660209081526040808320848452909152812060028101549091036137b75760405162461bcd60e51b815260206004820152601460248201527314d95b1b081cdd185ad9481b9bdd08199bdd5b9960621b60448201526064016111e6565b3360009081526008602052604081208054849081106137d8576137d8615af6565b90600052602060002090600502019050806000015460001461383c5760405162461bcd60e51b815260206004820152601760248201527f5374616b65206e6f7420696e2073656c6c20737461746500000000000000000060448201526064016111e6565b60028083015482553360008181526016602090815260408083208884528252808320838155600180820185905595810184905560038101849055600401839055928252601a8152828220878352905290812054601954909261389d91615b22565b905080821461395e576000601982815481106138bb576138bb615af6565b60009182526020918290206040805180820190915260029092020180546001600160a01b0316825260010154918101919091526019805491925082918590811061390757613907615af6565b6000918252602080832084516002939093020180546001600160a01b0319166001600160a01b03938416178155938101516001909401939093558351168152601a8252604080822093830151825292909152208290555b601980548061396f5761396f615cff565b600082815260208082206002600019949094019384020180546001600160a01b03191681556001018290559190925533808352601a8252604080842089855283528084209390935591518781527f73d12dec3eb3b445b6c9feb2fd559ba7c852c525bc1e59d8f7ff760c55df041d9101612e49565b3360009081526007602052604090205460ff16613a135760405162461bcd60e51b81526004016111e690615ba2565b600e8190556040518181527fe5dadb089824c750e4e7a2e98bfbe130f1a09834769e81339639fbe18606859b90602001613747565b3360009081526007602052604090205460ff16613a775760405162461bcd60e51b81526004016111e690615ba2565b613a848262015180615b35565b600155600281905560408051838152602081018390527f7fa9647ec1cc14e3822b46d05a2b9d4e019bde8875c0088c46b6503d71bf1722910160405180910390a15050565b601954606090819081908067ffffffffffffffff811115613aec57613aec615cbb565b604051908082528060200260200182016040528015613b15578160200160208202803683370190505b5093508067ffffffffffffffff811115613b3157613b31615cbb565b604051908082528060200260200182016040528015613b5a578160200160208202803683370190505b5092508067ffffffffffffffff811115613b7657613b76615cbb565b604051908082528060200260200182016040528015613bd957816020015b613bc66040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081613b945790505b50915060005b81811015613d2357600060198281548110613bfc57613bfc615af6565b60009182526020918290206040805180820190915260029092020180546001600160a01b0316808352600190910154928201929092528751909250879084908110613c4957613c49615af6565b60200260200101906001600160a01b031690816001600160a01b0316815250508060200151858381518110613c8057613c80615af6565b60209081029190910181019190915281516001600160a01b03166000908152601682526040808220848401518352835290819020815160a0810183528154815260018201549381019390935260028101549183019190915260038101546060830152600481015460808301528551909190869085908110613d0357613d03615af6565b602002602001018190525050508080613d1b90615b89565b915050613bdf565b5050909192565b613d32615457565b336000908152600960205260408120805483908110613d5357613d53615af6565b600091825260209091206009909102016007810154909150600160a01b900460ff1615613db65760405162461bcd60e51b81526020600482015260116024820152705374616b6520697320436f6d706c65746560781b60448201526064016111e6565b6000613dc2338461338b565b90508160030154811015613de85760405162461bcd60e51b81526004016111e690615cd1565b6000826003015482613dfa9190615b22565b905080600003613e485760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b60448201526064016111e6565b808360030154613e589190615b76565b60038401819055835411613e7c5760078301805460ff60a01b1916600160a01b1790555b336000908152600c602052604090205415613f8a5760078301546001600160a01b039081166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928592909116906316345f1890602401602060405180830381865afa158015613efd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f219190615c6d565b613f2b9190615b35565b613f359190615b62565b336000908152600c60205260409020549091508110613f6357336000908152600c6020526040812055613f88565b336000908152600c602052604081208054839290613f82908490615b22565b90915550505b505b60078301546001600160a01b031660009081526010602052604081208054839290613fb6908490615b22565b90915550506007830154613fd4906001600160a01b0316338361548f565b604080518281526000602082015233917f4a94c2c356e29a6583071e731bdacf2ca56565ba5efebcff6936eb7923b517219101612213565b61403060405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152601360205260408120905b8154811015611171578382828154811061406657614066615af6565b906000526020600020906003020160000154036140cf5781818154811061408f5761408f615af6565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505050611084565b806140d981615b89565b91505061404a565b6140e9615457565b606481111561413a5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c69642072657374616b652070657263656e7461676500000000000060448201526064016111e6565b33600090815260086020526040812080548490811061415b5761415b615af6565b9060005260206000209060050201905080600001546000036141b45760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b60448201526064016111e6565b80600301544210156142005760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b60448201526064016111e6565b8054600061420e3386612f07565b905061421a8183615b76565b91506000606461422a8685615b35565b6142349190615b62565b905060006142428285615b22565b6000865560048601805460ff191660011790559050801561432e57806012600082825461426f9190615b76565b9091555050600354811161429d5780600160020160008282546142929190615b22565b909155506142a39050565b60006003555b3360009081526013602090815260409182902082516060810184528a815291820184905260115490928201906142d99042615b76565b9052815460018082018455600093845260209384902083516003909302019182558284015190820155604091820151600290910155518281523391600080516020615d2a833981519152910160405180910390a25b811561445557336000908152601560205260408120541561435f57503360009081526015602052604090205461436d565b61436a3360016127d0565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a00160405280858152602001428152602001838152602001600160000154426143c09190615b76565b81526000602091820181905283546001808201865594825290829020835160059092020190815582820151938101939093556040808301516002850155606083015160038501556080909201516004909301805460ff1916931515939093179092555184815233917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d910160405180910390a2505b50505050506144716001600080516020615d4a83398151915255565b5050565b3360009081526007602052604090205460ff166144a45760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b0381166144ca5760405162461bcd60e51b81526004016111e690615bca565b6001600160a01b0316600090815260156020526040812055565b3360009081526007602052604090205460ff166145135760405162461bcd60e51b81526004016111e690615ba2565b8160000361456f5760405162461bcd60e51b815260206004820152602360248201527f4c6f636b2074696d65206d7573742062652067726561746572207468616e207a60448201526265726f60e81b60648201526084016111e6565b806000036145d55760405162461bcd60e51b815260206004820152602d60248201527f50657263656e74616765207065722073746570206d757374206265206772656160448201526c746572207468616e207a65726f60981b60648201526084016111e6565b6127106145e28282615d15565b1561463a5760405162461bcd60e51b815260206004820152602260248201527f50657263656e74616765206d757374206469766964652031303025206576656e6044820152616c7960f01b60648201526084016111e6565b60006146468383615b62565b905060006146548286615b62565b6001600160a01b0387166000908152600a6020526040812091925061467991906155ab565b60015b8281116146ee576001600160a01b0387166000908152600a602052604090819020815180830190925290806146b18486615b35565b8152602090810188905282546001818101855560009485529382902083516002909202019081559101519101556146e781615b89565b905061467c565b506040516001600160a01b038716907fde4b6ccc38b84f88129403b65a309f9b1c41d4c316bc2118d7614e449b9d4c4590600090a2505050505050565b6009602052816000526040600020818154811061474757600080fd5b6000918252602090912060099091020180546001820154600283015460038401546004850154600586015460068701546007880154600890980154969950949750929591949093916001600160a01b03811691600160a01b90910460ff16908a565b6001600160a01b0382166000908152600960205260408120805460609283929091859081106147da576147da615af6565b600091825260208083206007600990930201918201546001600160a01b0316808452600a9091526040832054919350918167ffffffffffffffff81111561482357614823615cbb565b60405190808252806020026020018201604052801561484c578160200160208202803683370190505b50905060008267ffffffffffffffff81111561486a5761486a615cbb565b604051908082528060200260200182016040528015614893578160200160208202803683370190505b50905060005b83811015614940576001600160a01b0385166000908152600a602052604081208054839081106148cb576148cb615af6565b90600052602060002090600202019050806000015487600601546148ef9190615b76565b84838151811061490157614901615af6565b602002602001018181525050806001015483838151811061492457614924615af6565b60209081029190910101525061493981615b89565b9050614899565b50909890975095505050505050565b6013602052816000526040600020818154811061496b57600080fd5b600091825260209091206003909102018054600182015460029092015490935090915083565b6001600160a01b0381166000908152601360209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561307a57838290600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050815260200190600101906149c9565b3360009081526007602052604090205460ff16614a485760405162461bcd60e51b81526004016111e690615ba2565b601155565b60008181548110614a5d57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b3360009081526007602052604090205460ff16614aaf5760405162461bcd60e51b81526004016111e690615ba2565b601455565b614abc615457565b336000908152600960205260408120805483908110614add57614add615af6565b906000526020600020906009020190506000614af93384610f52565b90508160040154811015614b1f5760405162461bcd60e51b81526004016111e690615cd1565b6000826004015482614b319190615b22565b905080600003614b7f5760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b60448201526064016111e6565b808360040154614b8f9190615b76565b83600401819055508060126000828254614ba99190615b76565b909155505033600090815260136020526040908190208151606081019092529080614bd787620f4240615b76565b815260200183815260200160115442614bf09190615b76565b90528154600180820184556000938452602093849020835160039093020191825582840151908201556040918201516002909101555182815233917f4e69fdc49495bcab2b4375781457ba16653a90eb4ffb6588351bdc39071433e29101612213565b600080805b6001600160a01b038416600090815260086020526040902054811015614ca4576000614c848583612f07565b9050614c908184615b76565b92505080614c9d90615b89565b9050614c58565b5092915050565b3360009081526007602052604090205460ff16614cda5760405162461bcd60e51b81526004016111e690615ba2565b80600003614d1b5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b60448201526064016111e6565b60086000836001600160a01b03166001600160a01b031681526020019081526020016000206040518060a001604052808381526020014281526020016001800154815260200160016000015442614d729190615b76565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff19169215159290921790915554614de3908290615b76565b6003556040518181526001600160a01b038316907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906020016115b6565b614e29615457565b6001600160a01b038216600090815260166020908152604080832084845290915281206002810154909103614ea05760405162461bcd60e51b815260206004820152601860248201527f53656c6c207374616b65206e6f7420617661696c61626c65000000000000000060448201526064016111e6565b8054600554614ebe916001600160a01b0390911690339030906153f0565b600060646017546064614ed19190615b22565b8354614edd9190615b35565b614ee79190615b62565b600554909150614f01906001600160a01b0316858361548f565b6001600160a01b0384166000908152600860205260408120805485908110614f2b57614f2b615af6565b600091825260208083206004600590930201918201805460ff191660019081179091553384526008909152604092839020835160a081019094529086015460028701549294509092918291614f7f91615b76565b8152602001856003015481526020018560040154815260200160016000015442614fa99190615b76565b8152600060209182018190528354600180820186559482528282208451600590920201908155838301518186015560408085015160028084019190915560608601516003808501919091556080909601516004938401805460ff19169115159190911790556001600160a01b038c16808552601686528285208c86528652828520858155808901869055918201859055958101849055909101829055928152601a825282812088825290915290812054601954909261506791615b22565b90508082146151285760006019828154811061508557615085615af6565b60009182526020918290206040805180820190915260029092020180546001600160a01b031682526001015491810191909152601980549192508291859081106150d1576150d1615af6565b6000918252602080832084516002939093020180546001600160a01b0319166001600160a01b03938416178155938101516001909401939093558351168152601a8252604080822093830151825292909152208290555b601980548061513957615139615cff565b600082815260208082206002600019949094019384020180546001600160a01b0319168155600101829055919092556001600160a01b038916808352601a825260408084208a855283528084209390935587548351908152918201899052339290917f7bb39d095b04a9986ed34adf14d74c33294d0a9e807f02bf634d532507422eba910160405180910390a350505050506144716001600080516020615d4a83398151915255565b336000908152601660209081526040808320858452909152812060028101549091036152475760405162461bcd60e51b815260206004820152601460248201527314d95b1b081cdd185ad9481b9bdd08199bdd5b9960621b60448201526064016111e6565b6064601854836152579190615b35565b6152619190615b62565b6001820155818155604080518381526020810185905233917f8e79b7ba8dab5ebfa59b9c6af1743c3ef14863680b3cc5ac837f8d636f76031c9101612772565b336000908152600f602052604090205460ff166152d05760405162461bcd60e51b81526004016111e690615c36565b6000805b6001600160a01b03831660009081526013602052604090205481101561535b576001600160a01b038316600090815260136020526040812080548390811061531e5761531e615af6565b9060005260206000209060030201905080600101548361533e9190615b76565b6000600190920191909155915061535481615b89565b90506152d4565b50806012600082825461536e9190615b22565b90915550505050565b3360009081526007602052604090205460ff166153a65760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b0381166153cc5760405162461bcd60e51b81526004016111e690615bca565b6001600160a01b03166000908152600f60205260409020805460ff19166001179055565b6040516001600160a01b0384811660248301528381166044830152606482018390526117b99186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506154e9565b600080516020615d4a83398151915280546001190161548957604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6040516001600160a01b038381166024830152604482018390526154c091859182169063a9059cbb90606401615425565b505050565b6001600080516020615d4a83398151915255565b6154e161555a565b611c1e6155a3565b600080602060008451602086016000885af18061550c576040513d6000823e3d81fd5b50506000513d91508115615524578060011415615531565b6001600160a01b0384163b155b156117b957604051635274afe760e01b81526001600160a01b03851660048201526024016111e6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16611c1e57604051631afcd79f60e31b815260040160405180910390fd5b6154c561555a565b5080546000825560020290600052602060002090810190611abb91905b808211156155e257600080825560018201556002016155c8565b5090565b80356001600160a01b03811681146155fd57600080fd5b919050565b60006020828403121561561457600080fd5b612819826155e6565b6000806040838503121561563057600080fd5b615639836155e6565b946020939093013593505050565b81518152602080830151908201526040808301519082015260608101611084565b60006020828403121561567a57600080fd5b5035919050565b6000806020838503121561569457600080fd5b823567ffffffffffffffff808211156156ac57600080fd5b818501915085601f8301126156c057600080fd5b8135818111156156cf57600080fd5b86602060a0830285010111156156e457600080fd5b60209290920196919550909350505050565b6000806020838503121561570957600080fd5b823567ffffffffffffffff8082111561572157600080fd5b818501915085601f83011261573557600080fd5b81358181111561574457600080fd5b8660208260051b85010111156156e457600080fd5b600081518084526020808501945080840160005b838110156157895781518752958201959082019060010161576d565b509495945050505050565b6060815260006157a76060830186615759565b82810360208401526157b98186615759565b915050826040830152949350505050565b600080604083850312156157dd57600080fd5b50508035926020909101359150565b600080604083850312156157ff57600080fd5b615808836155e6565b91506020830135801515811461581d57600080fd5b809150509250929050565b6000806040838503121561583b57600080fd5b615844836155e6565b9150615852602084016155e6565b90509250929050565b602080825282518282018190526000919060409081850190868401855b828110156158fc5781518051855286810151878601528581015186860152606080820151908601526080808201519086015260a0808201519086015260c0808201519086015260e0808201516001600160a01b0316908601526101008082015115159086015261012090810151908501526101409093019290850190600101615878565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b828110156158fc57815180518552868101518786015285810151868601526060808201519086015260809081015115159085015260a09093019290850190600101615926565b6060808252845182820181905260009190608090818501906020808a01865b838110156159b05781516001600160a01b03168552938201939082019060010161598b565b5050868303818801526159c3838a615759565b925060409150868303828801528288518085528285019150828a01945060005b81811015615a2257855180518452848101518585015285810151868501528881015189850152870151878401529483019460a0909201916001016159e3565b50909b9a5050505050505050505050565b600080600060608486031215615a4857600080fd5b615a51846155e6565b95602085013595506040909401359392505050565b604081526000615a796040830185615759565b8281036020840152615a8b8185615759565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015615aea57615ad78385518051825260208082015190830152604090810151910152565b9284019260609290920191600101615ab0565b50909695505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561108457611084615b0c565b808202811582820484141761108457611084615b0c565b634e487b7160e01b600052601260045260246000fd5b600082615b7157615b71615b4c565b500490565b8082018082111561108457611084615b0c565b600060018201615b9b57615b9b615b0c565b5060010190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b60208082526023908201527f416d6f756e74206d7573742062652067726561746572206d696e5374616b654c6040820152626f636b60e81b606082015260800190565b6020808252601f908201527f43616c6c6572206973206e6f7420616e20617574686f72697a656420626f7400604082015260600190565b600060208284031215615c7f57600080fd5b5051919050565b6020808252818101527f496e73756666696369656e74207265776172647320696e2074686520706f6f6c604082015260600190565b634e487b7160e01b600052604160045260246000fd5b602080825260149082015273125b9d985b1a590818db185a5b48185b5bdd5b9d60621b604082015260600190565b634e487b7160e01b600052603160045260246000fd5b600082615d2457615d24615b4c565b50069056fe106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f72419b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a26469706673582212200feb8e3145824828155191202ee307141b19ac44c4bf90bacd07beb11ab87fa964736f6c63430008140033
Deployed Bytecode
0x6080604052600436106104315760003560e01c80637a0c6dc011610229578063b90fba191161012e578063cfb866da116100b6578063eb44e0a31161007a578063eb44e0a314610ebc578063f2bb563014610edc578063f8d8c61714610efc578063fc424c5314610f1c578063ffecf51614610f3257600080fd5b8063cfb866da14610e1c578063d6c680eb14610e3c578063d919302514610e5c578063da40ef8014610e7c578063e4d06f9014610e9c57600080fd5b8063bed9757e116100fd578063bed9757e14610d50578063c606627214610d7e578063c7b530b014610db9578063cc1776d314610de6578063ce13d09014610dfc57600080fd5b8063b90fba1914610c6e578063b92a349f14610c8e578063bd72169814610cae578063bd84477d14610cdb57600080fd5b80638da5cb5b116101b157806396ed7f891161018057806396ed7f8914610bca5780639726582714610bea578063ac97b41714610c0e578063b6c3dc4c14610c2e578063b8e7023d14610c4e57600080fd5b80638da5cb5b14610b5457806392257cb514610b74578063953d16bf14610b8a5780639562ee1514610baa57600080fd5b806380ca0ecf116101f857806380ca0ecf14610abf5780638129fc1c14610adf578063853e0df214610af4578063876b2d8314610b145780638bdf67f214610b3457600080fd5b80637a0c6dc014610a305780637ba6f45814610a5d5780637bc221ac14610a8a5780637f79496c14610aaa57600080fd5b80633ba8396e1161033a57806358116227116102c257806367a74ddc1161028657806367a74ddc1461099b5780636ae21510146109bb5780636c3b0c53146109d05780637065cb48146109f0578063710ea0ce14610a1057600080fd5b806358116227146108c4578063584b62a1146108e4578063592d1dd11461092e578063599ab2c41461095b5780635fecd9261461097b57600080fd5b806343c7c0111161030957806343c7c011146107fa578063441a41751461081a57806344c7d6ef1461085957806351f6cf2f146108795780635339dcc1146108ae57600080fd5b80633ba8396e146106fe5780633c92f98d1461072e5780633f35e7221461075d57806343a32f891461077d57600080fd5b806316f0115b116103bd5780631d7a33611161038c5780631d7a33611461068057806322a26fc0146106a05780632e1a7d4d146106b3578063372500ab146106d357806338a85ce2146106e857600080fd5b806316f0115b146105c9578063173825d91461062a5780631ada70a81461064a5780631bf6ddae1461066057600080fd5b80630a84096a116104045780630a84096a1461051a5780630d046d111461053a57806312185a391461056757806313c8e2de1461058957806316be9b2a146105a957600080fd5b80630137451814610436578063022914a7146104895780630519da32146104c9578063092c7610146104ed575b600080fd5b34801561044257600080fd5b5061046c610451366004615602565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561049557600080fd5b506104b96104a4366004615602565b60076020526000908152604090205460ff1681565b6040519015158152602001610480565b3480156104d557600080fd5b506104df60115481565b604051908152602001610480565b3480156104f957600080fd5b506104df610508366004615602565b60106020526000908152604090205481565b34801561052657600080fd5b506104df61053536600461561d565b610f52565b34801561054657600080fd5b5061055a61055536600461561d565b61108a565b6040516104809190615647565b34801561057357600080fd5b50610587610582366004615668565b6111ef565b005b34801561059557600080fd5b506104df6105a4366004615668565b611223565b3480156105b557600080fd5b506105876105c436600461561d565b6112d4565b3480156105d557600080fd5b506001546002546003546004546005546105f994939291906001600160a01b031685565b6040805195865260208601949094529284019190915260608301526001600160a01b0316608082015260a001610480565b34801561063657600080fd5b50610587610645366004615602565b611345565b34801561065657600080fd5b506104df600d5481565b34801561066c57600080fd5b5061058761067b366004615668565b61143d565b34801561068c57600080fd5b5061058761069b366004615602565b6115c2565b6105876106ae366004615681565b61169b565b3480156106bf57600080fd5b506105876106ce366004615668565b6117bf565b3480156106df57600080fd5b50610587611abe565b3480156106f457600080fd5b506104df600e5481565b34801561070a57600080fd5b506104b9610719366004615602565b600f6020526000908152604090205460ff1681565b34801561073a57600080fd5b5061074e6107493660046156f6565b611c20565b60405161048093929190615794565b34801561076957600080fd5b5061058761077836600461561d565b611e10565b34801561078957600080fd5b506107d261079836600461561d565b6016602090815260009283526040808420909152908252902080546001820154600283015460038401546004909401549293919290919085565b604080519586526020860194909452928401919091526060830152608082015260a001610480565b34801561080657600080fd5b50610587610815366004615602565b611e97565b34801561082657600080fd5b5061083a610835366004615668565b612235565b604080516001600160a01b039093168352602083019190915201610480565b34801561086557600080fd5b50610587610874366004615668565b61226d565b34801561088557600080fd5b5061089961089436600461561d565b612489565b60408051928352602083019190915201610480565b3480156108ba57600080fd5b506104df60145481565b3480156108d057600080fd5b506105876108df3660046157ca565b6124c5565b3480156108f057600080fd5b506109046108ff36600461561d565b61277f565b6040805195865260208601949094529284019190915260608301521515608082015260a001610480565b34801561093a57600080fd5b506104df610949366004615602565b600c6020526000908152604090205481565b34801561096757600080fd5b506104df6109763660046157ec565b6127d0565b34801561098757600080fd5b50610587610996366004615602565b612820565b3480156109a757600080fd5b506105876109b6366004615828565b612896565b3480156109c757600080fd5b506105876128f3565b3480156109dc57600080fd5b506105876109eb36600461561d565b612afc565b3480156109fc57600080fd5b50610587610a0b366004615602565b612e58565b348015610a1c57600080fd5b506104df610a2b36600461561d565b612f07565b348015610a3c57600080fd5b50610a50610a4b366004615602565b612f9e565b604051610480919061585b565b348015610a6957600080fd5b50610a7d610a78366004615602565b613085565b6040516104809190615909565b348015610a9657600080fd5b506104df610aa5366004615602565b613120565b348015610ab657600080fd5b506104df6132f3565b348015610acb57600080fd5b506104df610ada36600461561d565b61338b565b348015610aeb57600080fd5b50610587613497565b348015610b0057600080fd5b50610587610b0f366004615668565b613602565b348015610b2057600080fd5b50610587610b2f366004615668565b61368f565b348015610b4057600080fd5b50610587610b4f366004615668565b6136c3565b348015610b6057600080fd5b5060065461046c906001600160a01b031681565b348015610b8057600080fd5b506104df60125481565b348015610b9657600080fd5b50610587610ba5366004615668565b613752565b348015610bb657600080fd5b50610587610bc5366004615668565b6139e4565b348015610bd657600080fd5b50610587610be53660046157ca565b613a48565b348015610bf657600080fd5b50610bff613ac9565b6040516104809392919061596c565b348015610c1a57600080fd5b50610587610c29366004615668565b613d2a565b348015610c3a57600080fd5b5061055a610c4936600461561d565b61400c565b348015610c5a57600080fd5b50610587610c693660046157ca565b6140e1565b348015610c7a57600080fd5b50610587610c89366004615602565b614475565b348015610c9a57600080fd5b50610587610ca9366004615a33565b6144e4565b348015610cba57600080fd5b506104df610cc9366004615602565b60156020526000908152604090205481565b348015610ce757600080fd5b50610cfb610cf636600461561d565b61472b565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925260a086015260c08501526001600160a01b031660e0840152151561010083015261012082015261014001610480565b348015610d5c57600080fd5b50610d70610d6b36600461561d565b6147a9565b604051610480929190615a66565b348015610d8a57600080fd5b50610d9e610d9936600461561d565b61494f565b60408051938452602084019290925290820152606001610480565b348015610dc557600080fd5b50610dd9610dd4366004615602565b614991565b6040516104809190615a94565b348015610df257600080fd5b506104df60175481565b348015610e0857600080fd5b50610587610e17366004615668565b614a19565b348015610e2857600080fd5b50610d9e610e37366004615668565b614a4d565b348015610e4857600080fd5b50610587610e57366004615668565b614a80565b348015610e6857600080fd5b50610587610e77366004615668565b614ab4565b348015610e8857600080fd5b506104df610e97366004615602565b614c53565b348015610ea857600080fd5b50610587610eb736600461561d565b614cab565b348015610ec857600080fd5b50610587610ed736600461561d565b614e21565b348015610ee857600080fd5b50610587610ef73660046157ca565b6151e2565b348015610f0857600080fd5b50610587610f17366004615602565b6152a1565b348015610f2857600080fd5b506104df60185481565b348015610f3e57600080fd5b50610587610f4d366004615602565b615377565b6001600160a01b0382166000908152600960205260408120805482919084908110610f7f57610f7f615af6565b906000526020600020906009020190506000816006015442610fa19190615b22565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a602052604090205481101561107d576001600160a01b0383166000908152600a6020526040812080548390811061100057611000615af6565b6000918252602082206002909102018054600182015460088a01549294509092909160649061103190600a90615b35565b61103b9190615b62565b9050828810611068576127106110518383615b35565b61105b9190615b62565b6110659087615b76565b95505b505050508061107690615b89565b9050610fb6565b5093505050505b92915050565b6110ae60405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152601360205260408120906110d484620f4240615b76565b905060005b825481101561117157818382815481106110f5576110f5615af6565b9060005260206000209060030201600001540361115f5782818154811061111e5761111e615af6565b906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820154815250509350505050611084565b8061116981615b89565b9150506110d9565b5060405162461bcd60e51b815260206004820152604160248201527f57697468647261775374616b652077697468207468652073706563696669656460448201527f207374616b654964206e6f7420666f756e6420666f72207468697320757365726064820152601760f91b608482015260a4015b60405180910390fd5b3360009081526007602052604090205460ff1661121e5760405162461bcd60e51b81526004016111e690615ba2565b601755565b6000805b6000548110156112cb576000818154811061124457611244615af6565b906000526020600020906003020160000154831015801561128957506000818154811061127357611273615af6565b9060005260206000209060030201600101548311155b156112bb57600081815481106112a1576112a1615af6565b906000526020600020906003020160020154915050919050565b6112c481615b89565b9050611227565b50600092915050565b3360009081526007602052604090205460ff166113035760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b0382166113295760405162461bcd60e51b81526004016111e690615bca565b6001600160a01b03909116600090815260156020526040902055565b3360009081526007602052604090205460ff166113745760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b03811660009081526007602052604090205460ff166113cb5760405162461bcd60e51b815260206004820152600c60248201526b2737ba1030b71037bbb732b960a11b60448201526064016111e6565b336001600160a01b0382160361141c5760405162461bcd60e51b815260206004820152601660248201527521b0b73737ba103932b6b7bb32903cb7bab939b2b63360511b60448201526064016111e6565b6001600160a01b03166000908152600760205260409020805460ff19169055565b600e5461144f8264e8d4a51000615b35565b1161146c5760405162461bcd60e51b81526004016111e690615bf3565b600554611484906001600160a01b03163330846153f0565b33600090815260156020526040812054156114af5750336000908152601560205260409020546114bd565b6114ba3360006127d0565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a00160405280848152602001428152602001838152602001600160000154426115109190615b76565b815260006020918201819052835460018082018655948252828220845160059092020190815591830151938201939093556040820151600282015560608201516003808301919091556080909201516004909101805460ff19169115159190911790558054849290611583908490615b76565b909155505060405182815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906020015b60405180910390a25050565b336000908152600f602052604090205460ff166115f15760405162461bcd60e51b81526004016111e690615c36565b6000805b6001600160a01b038316600090815260086020526040902054811015611685576001600160a01b038316600090815260086020526040812080548390811061163f5761163f615af6565b9060005260206000209060050201905080600001548361165f9190615b76565b600082556004909101805460ff19166001179055915061167e81615b89565b90506115f5565b50600354611694908290615b22565b6003555050565b336000908152600f602052604090205460ff166116ca5760405162461bcd60e51b81526004016111e690615c36565b8060005b818110156117b957368484838181106116e9576116e9615af6565b905060a00201905080602001356001600201546117069190615b76565b6003556008600061171a6020840184615602565b6001600160a01b0316815260208082019290925260409081016000908120825160a08101845285850135815285840135818601908152608080880135958301958652606097880135978301978852820184815283546001808201865594865296909420915160059096029091019485555184820155915160028401559251600383015591516004909101805460ff1916911515919091179055016116ce565b50505050565b6117c7615457565b336000908152601360205260408120805461182f5760405162461bcd60e51b815260206004820152602260248201527f4e6f207374616b657320617661696c61626c6520666f72207769746864726177604482015261185b60f21b60648201526084016111e6565b60005b8154811015611a6557600082828154811061184f5761184f615af6565b9060005260206000209060030201905084816000015403611a545780600101546000036118d05760405162461bcd60e51b815260206004820152602960248201527f5374616b6520616c72656164792077697468647261776e206f7220646f6573206044820152681b9bdd08195e1a5cdd60ba1b60648201526084016111e6565b80600201544210156119245760405162461bcd60e51b815260206004820152601e60248201527f5769746864726177205374616b65206973207374696c6c206c6f636b6564000060448201526064016111e6565b80600101549350620f424085106119475761194464e8d4a5100085615b62565b93505b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015611990573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b49190615c6d565b9050848110156119d65760405162461bcd60e51b81526004016111e690615c86565b8160010154601260008282546119ec9190615b22565b909155505060006001830155600554611a0f906001600160a01b0316338761548f565b604080518681526020810188905233917f933735aa8de6d7547d0126171b2f31b9c34dd00f3ecd4be85a0ba047db4fafef910160405180910390a25050505050611aa4565b50611a5e81615b89565b9050611832565b5060405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b60448201526064016111e6565b611abb6001600080516020615d4a83398151915255565b50565b611ac6615457565b6000805b33600090815260086020526040902054811015611b5257336000908152600860205260408120805483908110611b0257611b02615af6565b90600052602060002090600502019050600081600001541115611b41576000611b2b3384612f07565b9050611b378185615b76565b4260018401559350505b50611b4b81615b89565b9050611aca565b5080600003611b995760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b60448201526064016111e6565b600454811115611bbb5760405162461bcd60e51b81526004016111e690615c86565b600454611bc9908290615b22565b600455600554611be3906001600160a01b0316338361548f565b6040518181523390600080516020615d2a8339815191529060200160405180910390a250611c1e6001600080516020615d4a83398151915255565b565b6060806000838067ffffffffffffffff811115611c3f57611c3f615cbb565b604051908082528060200260200182016040528015611c68578160200160208202803683370190505b5093508067ffffffffffffffff811115611c8457611c84615cbb565b604051908082528060200260200182016040528015611cad578160200160208202803683370190505b50925060005b81811015611e07576000878783818110611ccf57611ccf615af6565b9050602002016020810190611ce49190615602565b6001600160a01b0381166000908152601060205260409020548751919250908190889085908110611d1757611d17615af6565b6020908102919091018101919091526001600160a01b038381166000818152600b90935260408084205490516302c68be360e31b81526004810192909252909116906316345f1890602401602060405180830381865afa158015611d7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da39190615c6d565b90506000670de0b6b3a7640000611dba8484615b35565b611dc49190615b62565b905080888681518110611dd957611dd9615af6565b6020908102919091010152611dee8188615b76565b9650505050508080611dff90615b89565b915050611cb3565b50509250925092565b3360009081526007602052604090205460ff16611e3f5760405162461bcd60e51b81526004016111e690615ba2565b611e536001600160a01b038316338361548f565b6040518181526001600160a01b0383169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a35050565b611e9f615457565b60008060005b33600090815260096020526040902054811015611fd857336000908152600960205260408120805483908110611edd57611edd615af6565b6000918252602090912060099091020160078101549091506001600160a01b038681169116148015611f1b57506007810154600160a01b900460ff16155b15611fc7576000611f2c338461338b565b90508160030154811015611f525760405162461bcd60e51b81526004016111e690615cd1565b6000826003015482611f649190615b22565b90508015611fc457808360030154611f7c9190615b76565b6003840155611f8b8187615b76565b4260058501558354600385015491975011611fb65760078301805460ff60a01b1916600160a01b1790555b84611fc081615b89565b9550505b50505b50611fd181615b89565b9050611ea5565b508160000361201f5760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b60448201526064016111e6565b336000908152600c602052604090205415612128576001600160a01b038381166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928692909116906316345f1890602401602060405180830381865afa15801561209b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120bf9190615c6d565b6120c99190615b35565b6120d39190615b62565b336000908152600c6020526040902054909150811061210157336000908152600c6020526040812055612126565b336000908152600c602052604081208054839290612120908490615b22565b90915550505b505b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa15801561216f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121939190615c6d565b9050828110156121b55760405162461bcd60e51b81526004016111e690615c86565b6001600160a01b038416600090815260106020526040812080548592906121dd908490615b22565b909155506121f790506001600160a01b038516338561548f565b6040518381523390600080516020615d2a833981519152906020015b60405180910390a2505050611abb6001600080516020615d4a83398151915255565b6019818154811061224557600080fd5b6000918252602090912060029091020180546001909101546001600160a01b03909116915082565b612275615457565b3360009081526008602052604090205481106122c95760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b60448201526064016111e6565b3360009081526008602052604081208054839081106122ea576122ea615af6565b6000918252602082206005909102018054909250906123093385612f07565b90506123158183615b76565b91508160000361235c5760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b60448201526064016111e6565b82600301544210156123a85760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b60448201526064016111e6565b600080845560048401805460ff19166001179055601280548492906123ce908490615b76565b909155505060035482116123fc5781600160020160008282546123f19190615b22565b909155506124029050565b60006003555b33600090815260136020908152604091829020825160608101845287815291820185905260115490928201906124389042615b76565b9052815460018082018455600093845260209384902083516003909302019182558284015190820155604091820151600290910155518381523391600080516020615d2a8339815191529101612213565b600a60205281600052604060002081815481106124a557600080fd5b600091825260209091206002909102018054600190910154909250905082565b3360009081526008602052604081208054849081106124e6576124e6615af6565b60009182526020909120600590910201600481015490915060ff16156125475760405162461bcd60e51b81526020600482015260166024820152755374616b6520616c726561647920636f6d706c65746560501b60448201526064016111e6565b805460000361258c5760405162461bcd60e51b815260206004820152601160248201527005374616b6520616d6f756e74206973203607c1b60448201526064016111e6565b336000908152601660209081526040808320868452909152902060020154156125ef5760405162461bcd60e51b81526020600482015260156024820152745374616b6520616c7265616479206f6e2073616c6560581b60448201526064016111e6565b6040518060a001604052808381526020016064601854856126109190615b35565b61261a9190615b62565b81528254602080830191909152600180850154604080850191909152600280870154606095860152336000818152601686528381208b82528652838120885181558887015181870155888501518185015596880151600388015560809097015160049096019590955585875581518083019092529381529182018781526019805480840182559581905292517f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c96959590940294850180546001600160a01b0319166001600160a01b039095169490941790935591517f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c96969093019290925590546127229190615b22565b336000818152601a6020908152604080832088845282529182902093909355805185815292830186905290917f8e79b7ba8dab5ebfa59b9c6af1743c3ef14863680b3cc5ac837f8d636f76031c91015b60405180910390a2505050565b6008602052816000526040600020818154811061279b57600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919060ff1685565b6001600160a01b0382166000908152600c602052604081205481906127f490611223565b6002546128019190615b76565b90508215612819576014546128169082615b76565b90505b9392505050565b3360009081526007602052604090205460ff1661284f5760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b0381166128755760405162461bcd60e51b81526004016111e690615bca565b6001600160a01b03166000908152600f60205260409020805460ff19169055565b3360009081526007602052604090205460ff166128c55760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b039182166000908152600b6020526040902080546001600160a01b03191691909216179055565b6000805b3360009081526008602052604090205481101561297f5733600090815260086020526040812080548390811061292f5761292f615af6565b9060005260206000209060050201905060008160000154111561296e5760006129583384612f07565b90506129648185615b76565b4260018401559350505b5061297881615b89565b90506128f7565b50600e5481116129ca5760405162461bcd60e51b8152602060048201526016602482015275139bdd08195b9bdd59da081d1bc818dbdb5c1bdd5b9960521b60448201526064016111e6565b33600090815260156020526040812054156129f5575033600090815260156020526040902054612a03565b612a003360006127d0565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a0016040528084815260200142815260200183815260200160016000015442612a569190615b76565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff19169215159290921790915554612ac7908390615b76565b60035560405182815233907f3afe5b60dee16617a8adbbd7d6c28f17a27efabb834872efa8e7ad5dafddf6f1906020016115b6565b80600003612b4c5760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f60448201526064016111e6565b6001600160a01b038083166000908152600b60205260409020541680612bc05760405162461bcd60e51b815260206004820152602360248201527f5072696365206f7261636c65206e6f742073657420666f72207468697320746f60448201526235b2b760e91b60648201526084016111e6565b612bd56001600160a01b0384163330856153f0565b60006064612be4600a85615b35565b612bee9190615b62565b6001600160a01b038581166000818152600b60205260408082205490516302c68be360e31b8152600481019390935293945092670de0b6b3a76400009287929116906316345f1890602401602060405180830381865afa158015612c56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7a9190615c6d565b612c849190615b35565b612c8e9190615b62565b9050600e548111612cb15760405162461bcd60e51b81526004016111e690615bf3565b336000908152600c602052604081208054839290612cd0908490615b76565b90915550506001600160a01b03851660009081526010602052604081208054869290612cfd908490615b76565b909155505033600090815260096020908152604091829020825161014081018452878152918201859052600d549092820190612d399042615b76565b81526000602080830182905260408084018390524260608086018290526080808701929092526001600160a01b038d811660a08089019190915260c080890188905260e09889018c90528a5460018082018d559b8952978790208a51600990990201978855898701519a88019a909a558885015160028801559188015160038701559187015160048601558601516005850155958501516006840155928401516007830180546101008701511515600160a01b026001600160a81b031990911692909716919091179590951790945561012090920151600890920191909155805186815291820184905233917f9ade76f4385de306666dfb21a52b27d52db0fde8ad0f515fa261f532cac60d2191015b60405180910390a25050505050565b3360009081526007602052604090205460ff16612e875760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b03811660009081526007602052604090205460ff1615612ee35760405162461bcd60e51b815260206004820152601060248201526f20b63932b0b23c9030b71037bbb732b960811b60448201526064016111e6565b6001600160a01b03166000908152600760205260409020805460ff19166001179055565b6001600160a01b0382166000908152600860205260408120805482919084908110612f3457612f34615af6565b906000526020600020906005020190506000816001015442612f569190615b22565b90506000612710620151808385600201548660000154612f769190615b35565b612f809190615b35565b612f8a9190615b62565b612f949190615b62565b9695505050505050565b6001600160a01b0381166000908152600960209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561307a57600084815260209081902060408051610140810182526009860290920180548352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a0840152600681015460c084015260078101546001600160a01b03811660e0850152600160a01b900460ff161515610100840152600801546101208301529083529092019101612fd6565b505050509050919050565b6001600160a01b0381166000908152600860209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561307a5760008481526020908190206040805160a081018252600586029092018054835260018082015484860152600282015492840192909252600381015460608401526004015460ff161515608083015290835290920191016130bd565b6001600160a01b038116600090815260096020526040812054815b818110156132ec576001600160a01b038416600090815260096020526040812080548390811061316d5761316d615af6565b600091825260209182902060408051610140810182526009909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260078201546001600160a01b03811660e083015260ff600160a01b909104161515610100820181905260089092015461012082015291506132d95760e0810180516001600160a01b039081166000908152600b602052604080822054935190516302c68be360e31b815290831660048201529092909116906316345f1890602401602060405180830381865afa15801561326a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061328e9190615c6d565b90506000826060015183600001516132a69190615b22565b90506000670de0b6b3a76400006132bd8385615b35565b6132c79190615b62565b90506132d38188615b76565b96505050505b50806132e481615b89565b91505061313b565b5050919050565b6005546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613340573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133649190615c6d565b9050601254811061337757600091505090565b806012546133859190615b22565b91505090565b6001600160a01b03821660009081526009602052604081208054829190849081106133b8576133b8615af6565b9060005260206000209060090201905060008160060154426133da9190615b22565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a602052604090205481101561107d576001600160a01b0383166000908152600a6020526040812080548390811061343957613439615af6565b6000918252602090912060029091020180546001820154919250908187106134835787546127109061346c908390615b35565b6134769190615b62565b6134809086615b76565b94505b5050508061349090615b89565b90506133ef565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156134dd5750825b905060008267ffffffffffffffff1660011480156134fa5750303b155b905081158015613508575080155b156135265760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561355057845460ff60401b1916600160401b1785555b6135586154d9565b600680546001600160a01b0319167341970ce76b656030a79e7c1fa76fc4eb9398025590811790915560005260076020527f1428bfef657344f5f7a0019d1554dccabe000be344bb83cdab918bd50f24b573805460ff1916600117905583156135fb57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b3360009081526007602052604090205460ff166136315760405162461bcd60e51b81526004016111e690615ba2565b600554613648906001600160a01b0316338361548f565b6005546040518281526001600160a01b039091169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a350565b3360009081526007602052604090205460ff166136be5760405162461bcd60e51b81526004016111e690615ba2565b601855565b3360009081526007602052604090205460ff166136f25760405162461bcd60e51b81526004016111e690615ba2565b60055461370a906001600160a01b03163330846153f0565b600454613718908290615b76565b6004556040518181527f4e9221f2cca6ca0397acc6004ea0b716798254f5abcf53924fab34f0373e5d4e906020015b60405180910390a150565b336000908152601660209081526040808320848452909152812060028101549091036137b75760405162461bcd60e51b815260206004820152601460248201527314d95b1b081cdd185ad9481b9bdd08199bdd5b9960621b60448201526064016111e6565b3360009081526008602052604081208054849081106137d8576137d8615af6565b90600052602060002090600502019050806000015460001461383c5760405162461bcd60e51b815260206004820152601760248201527f5374616b65206e6f7420696e2073656c6c20737461746500000000000000000060448201526064016111e6565b60028083015482553360008181526016602090815260408083208884528252808320838155600180820185905595810184905560038101849055600401839055928252601a8152828220878352905290812054601954909261389d91615b22565b905080821461395e576000601982815481106138bb576138bb615af6565b60009182526020918290206040805180820190915260029092020180546001600160a01b0316825260010154918101919091526019805491925082918590811061390757613907615af6565b6000918252602080832084516002939093020180546001600160a01b0319166001600160a01b03938416178155938101516001909401939093558351168152601a8252604080822093830151825292909152208290555b601980548061396f5761396f615cff565b600082815260208082206002600019949094019384020180546001600160a01b03191681556001018290559190925533808352601a8252604080842089855283528084209390935591518781527f73d12dec3eb3b445b6c9feb2fd559ba7c852c525bc1e59d8f7ff760c55df041d9101612e49565b3360009081526007602052604090205460ff16613a135760405162461bcd60e51b81526004016111e690615ba2565b600e8190556040518181527fe5dadb089824c750e4e7a2e98bfbe130f1a09834769e81339639fbe18606859b90602001613747565b3360009081526007602052604090205460ff16613a775760405162461bcd60e51b81526004016111e690615ba2565b613a848262015180615b35565b600155600281905560408051838152602081018390527f7fa9647ec1cc14e3822b46d05a2b9d4e019bde8875c0088c46b6503d71bf1722910160405180910390a15050565b601954606090819081908067ffffffffffffffff811115613aec57613aec615cbb565b604051908082528060200260200182016040528015613b15578160200160208202803683370190505b5093508067ffffffffffffffff811115613b3157613b31615cbb565b604051908082528060200260200182016040528015613b5a578160200160208202803683370190505b5092508067ffffffffffffffff811115613b7657613b76615cbb565b604051908082528060200260200182016040528015613bd957816020015b613bc66040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b815260200190600190039081613b945790505b50915060005b81811015613d2357600060198281548110613bfc57613bfc615af6565b60009182526020918290206040805180820190915260029092020180546001600160a01b0316808352600190910154928201929092528751909250879084908110613c4957613c49615af6565b60200260200101906001600160a01b031690816001600160a01b0316815250508060200151858381518110613c8057613c80615af6565b60209081029190910181019190915281516001600160a01b03166000908152601682526040808220848401518352835290819020815160a0810183528154815260018201549381019390935260028101549183019190915260038101546060830152600481015460808301528551909190869085908110613d0357613d03615af6565b602002602001018190525050508080613d1b90615b89565b915050613bdf565b5050909192565b613d32615457565b336000908152600960205260408120805483908110613d5357613d53615af6565b600091825260209091206009909102016007810154909150600160a01b900460ff1615613db65760405162461bcd60e51b81526020600482015260116024820152705374616b6520697320436f6d706c65746560781b60448201526064016111e6565b6000613dc2338461338b565b90508160030154811015613de85760405162461bcd60e51b81526004016111e690615cd1565b6000826003015482613dfa9190615b22565b905080600003613e485760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b60448201526064016111e6565b808360030154613e589190615b76565b60038401819055835411613e7c5760078301805460ff60a01b1916600160a01b1790555b336000908152600c602052604090205415613f8a5760078301546001600160a01b039081166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928592909116906316345f1890602401602060405180830381865afa158015613efd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f219190615c6d565b613f2b9190615b35565b613f359190615b62565b336000908152600c60205260409020549091508110613f6357336000908152600c6020526040812055613f88565b336000908152600c602052604081208054839290613f82908490615b22565b90915550505b505b60078301546001600160a01b031660009081526010602052604081208054839290613fb6908490615b22565b90915550506007830154613fd4906001600160a01b0316338361548f565b604080518281526000602082015233917f4a94c2c356e29a6583071e731bdacf2ca56565ba5efebcff6936eb7923b517219101612213565b61403060405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152601360205260408120905b8154811015611171578382828154811061406657614066615af6565b906000526020600020906003020160000154036140cf5781818154811061408f5761408f615af6565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505050611084565b806140d981615b89565b91505061404a565b6140e9615457565b606481111561413a5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c69642072657374616b652070657263656e7461676500000000000060448201526064016111e6565b33600090815260086020526040812080548490811061415b5761415b615af6565b9060005260206000209060050201905080600001546000036141b45760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b60448201526064016111e6565b80600301544210156142005760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b60448201526064016111e6565b8054600061420e3386612f07565b905061421a8183615b76565b91506000606461422a8685615b35565b6142349190615b62565b905060006142428285615b22565b6000865560048601805460ff191660011790559050801561432e57806012600082825461426f9190615b76565b9091555050600354811161429d5780600160020160008282546142929190615b22565b909155506142a39050565b60006003555b3360009081526013602090815260409182902082516060810184528a815291820184905260115490928201906142d99042615b76565b9052815460018082018455600093845260209384902083516003909302019182558284015190820155604091820151600290910155518281523391600080516020615d2a833981519152910160405180910390a25b811561445557336000908152601560205260408120541561435f57503360009081526015602052604090205461436d565b61436a3360016127d0565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a00160405280858152602001428152602001838152602001600160000154426143c09190615b76565b81526000602091820181905283546001808201865594825290829020835160059092020190815582820151938101939093556040808301516002850155606083015160038501556080909201516004909301805460ff1916931515939093179092555184815233917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d910160405180910390a2505b50505050506144716001600080516020615d4a83398151915255565b5050565b3360009081526007602052604090205460ff166144a45760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b0381166144ca5760405162461bcd60e51b81526004016111e690615bca565b6001600160a01b0316600090815260156020526040812055565b3360009081526007602052604090205460ff166145135760405162461bcd60e51b81526004016111e690615ba2565b8160000361456f5760405162461bcd60e51b815260206004820152602360248201527f4c6f636b2074696d65206d7573742062652067726561746572207468616e207a60448201526265726f60e81b60648201526084016111e6565b806000036145d55760405162461bcd60e51b815260206004820152602d60248201527f50657263656e74616765207065722073746570206d757374206265206772656160448201526c746572207468616e207a65726f60981b60648201526084016111e6565b6127106145e28282615d15565b1561463a5760405162461bcd60e51b815260206004820152602260248201527f50657263656e74616765206d757374206469766964652031303025206576656e6044820152616c7960f01b60648201526084016111e6565b60006146468383615b62565b905060006146548286615b62565b6001600160a01b0387166000908152600a6020526040812091925061467991906155ab565b60015b8281116146ee576001600160a01b0387166000908152600a602052604090819020815180830190925290806146b18486615b35565b8152602090810188905282546001818101855560009485529382902083516002909202019081559101519101556146e781615b89565b905061467c565b506040516001600160a01b038716907fde4b6ccc38b84f88129403b65a309f9b1c41d4c316bc2118d7614e449b9d4c4590600090a2505050505050565b6009602052816000526040600020818154811061474757600080fd5b6000918252602090912060099091020180546001820154600283015460038401546004850154600586015460068701546007880154600890980154969950949750929591949093916001600160a01b03811691600160a01b90910460ff16908a565b6001600160a01b0382166000908152600960205260408120805460609283929091859081106147da576147da615af6565b600091825260208083206007600990930201918201546001600160a01b0316808452600a9091526040832054919350918167ffffffffffffffff81111561482357614823615cbb565b60405190808252806020026020018201604052801561484c578160200160208202803683370190505b50905060008267ffffffffffffffff81111561486a5761486a615cbb565b604051908082528060200260200182016040528015614893578160200160208202803683370190505b50905060005b83811015614940576001600160a01b0385166000908152600a602052604081208054839081106148cb576148cb615af6565b90600052602060002090600202019050806000015487600601546148ef9190615b76565b84838151811061490157614901615af6565b602002602001018181525050806001015483838151811061492457614924615af6565b60209081029190910101525061493981615b89565b9050614899565b50909890975095505050505050565b6013602052816000526040600020818154811061496b57600080fd5b600091825260209091206003909102018054600182015460029092015490935090915083565b6001600160a01b0381166000908152601360209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561307a57838290600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050815260200190600101906149c9565b3360009081526007602052604090205460ff16614a485760405162461bcd60e51b81526004016111e690615ba2565b601155565b60008181548110614a5d57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b3360009081526007602052604090205460ff16614aaf5760405162461bcd60e51b81526004016111e690615ba2565b601455565b614abc615457565b336000908152600960205260408120805483908110614add57614add615af6565b906000526020600020906009020190506000614af93384610f52565b90508160040154811015614b1f5760405162461bcd60e51b81526004016111e690615cd1565b6000826004015482614b319190615b22565b905080600003614b7f5760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b60448201526064016111e6565b808360040154614b8f9190615b76565b83600401819055508060126000828254614ba99190615b76565b909155505033600090815260136020526040908190208151606081019092529080614bd787620f4240615b76565b815260200183815260200160115442614bf09190615b76565b90528154600180820184556000938452602093849020835160039093020191825582840151908201556040918201516002909101555182815233917f4e69fdc49495bcab2b4375781457ba16653a90eb4ffb6588351bdc39071433e29101612213565b600080805b6001600160a01b038416600090815260086020526040902054811015614ca4576000614c848583612f07565b9050614c908184615b76565b92505080614c9d90615b89565b9050614c58565b5092915050565b3360009081526007602052604090205460ff16614cda5760405162461bcd60e51b81526004016111e690615ba2565b80600003614d1b5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b60448201526064016111e6565b60086000836001600160a01b03166001600160a01b031681526020019081526020016000206040518060a001604052808381526020014281526020016001800154815260200160016000015442614d729190615b76565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff19169215159290921790915554614de3908290615b76565b6003556040518181526001600160a01b038316907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906020016115b6565b614e29615457565b6001600160a01b038216600090815260166020908152604080832084845290915281206002810154909103614ea05760405162461bcd60e51b815260206004820152601860248201527f53656c6c207374616b65206e6f7420617661696c61626c65000000000000000060448201526064016111e6565b8054600554614ebe916001600160a01b0390911690339030906153f0565b600060646017546064614ed19190615b22565b8354614edd9190615b35565b614ee79190615b62565b600554909150614f01906001600160a01b0316858361548f565b6001600160a01b0384166000908152600860205260408120805485908110614f2b57614f2b615af6565b600091825260208083206004600590930201918201805460ff191660019081179091553384526008909152604092839020835160a081019094529086015460028701549294509092918291614f7f91615b76565b8152602001856003015481526020018560040154815260200160016000015442614fa99190615b76565b8152600060209182018190528354600180820186559482528282208451600590920201908155838301518186015560408085015160028084019190915560608601516003808501919091556080909601516004938401805460ff19169115159190911790556001600160a01b038c16808552601686528285208c86528652828520858155808901869055918201859055958101849055909101829055928152601a825282812088825290915290812054601954909261506791615b22565b90508082146151285760006019828154811061508557615085615af6565b60009182526020918290206040805180820190915260029092020180546001600160a01b031682526001015491810191909152601980549192508291859081106150d1576150d1615af6565b6000918252602080832084516002939093020180546001600160a01b0319166001600160a01b03938416178155938101516001909401939093558351168152601a8252604080822093830151825292909152208290555b601980548061513957615139615cff565b600082815260208082206002600019949094019384020180546001600160a01b0319168155600101829055919092556001600160a01b038916808352601a825260408084208a855283528084209390935587548351908152918201899052339290917f7bb39d095b04a9986ed34adf14d74c33294d0a9e807f02bf634d532507422eba910160405180910390a350505050506144716001600080516020615d4a83398151915255565b336000908152601660209081526040808320858452909152812060028101549091036152475760405162461bcd60e51b815260206004820152601460248201527314d95b1b081cdd185ad9481b9bdd08199bdd5b9960621b60448201526064016111e6565b6064601854836152579190615b35565b6152619190615b62565b6001820155818155604080518381526020810185905233917f8e79b7ba8dab5ebfa59b9c6af1743c3ef14863680b3cc5ac837f8d636f76031c9101612772565b336000908152600f602052604090205460ff166152d05760405162461bcd60e51b81526004016111e690615c36565b6000805b6001600160a01b03831660009081526013602052604090205481101561535b576001600160a01b038316600090815260136020526040812080548390811061531e5761531e615af6565b9060005260206000209060030201905080600101548361533e9190615b76565b6000600190920191909155915061535481615b89565b90506152d4565b50806012600082825461536e9190615b22565b90915550505050565b3360009081526007602052604090205460ff166153a65760405162461bcd60e51b81526004016111e690615ba2565b6001600160a01b0381166153cc5760405162461bcd60e51b81526004016111e690615bca565b6001600160a01b03166000908152600f60205260409020805460ff19166001179055565b6040516001600160a01b0384811660248301528381166044830152606482018390526117b99186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506154e9565b600080516020615d4a83398151915280546001190161548957604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6040516001600160a01b038381166024830152604482018390526154c091859182169063a9059cbb90606401615425565b505050565b6001600080516020615d4a83398151915255565b6154e161555a565b611c1e6155a3565b600080602060008451602086016000885af18061550c576040513d6000823e3d81fd5b50506000513d91508115615524578060011415615531565b6001600160a01b0384163b155b156117b957604051635274afe760e01b81526001600160a01b03851660048201526024016111e6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16611c1e57604051631afcd79f60e31b815260040160405180910390fd5b6154c561555a565b5080546000825560020290600052602060002090810190611abb91905b808211156155e257600080825560018201556002016155c8565b5090565b80356001600160a01b03811681146155fd57600080fd5b919050565b60006020828403121561561457600080fd5b612819826155e6565b6000806040838503121561563057600080fd5b615639836155e6565b946020939093013593505050565b81518152602080830151908201526040808301519082015260608101611084565b60006020828403121561567a57600080fd5b5035919050565b6000806020838503121561569457600080fd5b823567ffffffffffffffff808211156156ac57600080fd5b818501915085601f8301126156c057600080fd5b8135818111156156cf57600080fd5b86602060a0830285010111156156e457600080fd5b60209290920196919550909350505050565b6000806020838503121561570957600080fd5b823567ffffffffffffffff8082111561572157600080fd5b818501915085601f83011261573557600080fd5b81358181111561574457600080fd5b8660208260051b85010111156156e457600080fd5b600081518084526020808501945080840160005b838110156157895781518752958201959082019060010161576d565b509495945050505050565b6060815260006157a76060830186615759565b82810360208401526157b98186615759565b915050826040830152949350505050565b600080604083850312156157dd57600080fd5b50508035926020909101359150565b600080604083850312156157ff57600080fd5b615808836155e6565b91506020830135801515811461581d57600080fd5b809150509250929050565b6000806040838503121561583b57600080fd5b615844836155e6565b9150615852602084016155e6565b90509250929050565b602080825282518282018190526000919060409081850190868401855b828110156158fc5781518051855286810151878601528581015186860152606080820151908601526080808201519086015260a0808201519086015260c0808201519086015260e0808201516001600160a01b0316908601526101008082015115159086015261012090810151908501526101409093019290850190600101615878565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b828110156158fc57815180518552868101518786015285810151868601526060808201519086015260809081015115159085015260a09093019290850190600101615926565b6060808252845182820181905260009190608090818501906020808a01865b838110156159b05781516001600160a01b03168552938201939082019060010161598b565b5050868303818801526159c3838a615759565b925060409150868303828801528288518085528285019150828a01945060005b81811015615a2257855180518452848101518585015285810151868501528881015189850152870151878401529483019460a0909201916001016159e3565b50909b9a5050505050505050505050565b600080600060608486031215615a4857600080fd5b615a51846155e6565b95602085013595506040909401359392505050565b604081526000615a796040830185615759565b8281036020840152615a8b8185615759565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015615aea57615ad78385518051825260208082015190830152604090810151910152565b9284019260609290920191600101615ab0565b50909695505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561108457611084615b0c565b808202811582820484141761108457611084615b0c565b634e487b7160e01b600052601260045260246000fd5b600082615b7157615b71615b4c565b500490565b8082018082111561108457611084615b0c565b600060018201615b9b57615b9b615b0c565b5060010190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b60208082526023908201527f416d6f756e74206d7573742062652067726561746572206d696e5374616b654c6040820152626f636b60e81b606082015260800190565b6020808252601f908201527f43616c6c6572206973206e6f7420616e20617574686f72697a656420626f7400604082015260600190565b600060208284031215615c7f57600080fd5b5051919050565b6020808252818101527f496e73756666696369656e74207265776172647320696e2074686520706f6f6c604082015260600190565b634e487b7160e01b600052604160045260246000fd5b602080825260149082015273125b9d985b1a590818db185a5b48185b5bdd5b9d60621b604082015260600190565b634e487b7160e01b600052603160045260246000fd5b600082615d2457615d24615b4c565b50069056fe106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f72419b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a26469706673582212200feb8e3145824828155191202ee307141b19ac44c4bf90bacd07beb11ab87fa964736f6c63430008140033
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.