Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
PacaFinanceWithBoostAndSchedule
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 PacaFinanceWithBoostAndSchedule 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; } 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; // 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); // Modifiers modifier onlyOwner() { require(owners[msg.sender], "Not authorized"); _; } modifier onlyBot() { require(authorizedBots[msg.sender], "Caller is not an authorized bot"); _; } function initialize() public initializer { __ReentrancyGuard_init(); // Initialize ReentrancyGuardUpgradeable owner = 0x41970Ce76b656030A79E7C1FA76FC4EB93980255; owners[0x41970Ce76b656030A79E7C1FA76FC4EB93980255] = true; lockupDuration = 250 days; minStakeLock = 16 ether; pool.tokenAddress = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913; pool.lockupPeriod = 250 * 1 days; pool.dailyRewardRate = 33; // Push boost tiers in ascending order (amounts in wei, boosts as percentages) boosttiers.push(BoostRange(3500 * 1e18, 9999 * 1e18, 1)); // $3,500 to $9,999 = 0.01 boost boosttiers.push(BoostRange(10000 * 1e18, 19999 * 1e18, 2)); // $10,000 to $19,999 = 0.02 boost boosttiers.push(BoostRange(20000 * 1e18, 29999 * 1e18, 3)); // $20,000 to $29,999 = 0.03 boost boosttiers.push(BoostRange(30000 * 1e18, 39999 * 1e18, 4)); // $30,000 to $39,999 = 0.04 boost boosttiers.push(BoostRange(40000 * 1e18, 59999 * 1e18, 5)); // $40,000 to $59,999 = 0.05 boost boosttiers.push(BoostRange(60000 * 1e18, 79999 * 1e18, 6)); // $60,000 to $79,999 = 0.06 boost boosttiers.push(BoostRange(80000 * 1e18, 99999 * 1e18, 8)); // $80,000 to $99,999 = 0.08 boost boosttiers.push(BoostRange(100000 * 1e18, type(uint256).max, 10)); // $100,000+ = 0.1 boost // Price oracle for a specific tokens // priceOracles[0x940181a94A35A4569E4529A3CDfB74e38FD98631] = 0x0Dde1b42F7B3891C9731280A74081501729A73c5; authorizedBots[0xbf12D3b827a230F7390EbCc9b83b289FdC98ba81] = true; authorizedBots[0x7c40f272570fdf9549d6f67493aC250a1DB52F27] = true; unlockDelay = 60 * 60 * 36; restakeBonus = 3; } // Ownership Management function addOwner(address _newOwner) external onlyOwner { require(!owners[_newOwner], "Already an owner"); owners[_newOwner] = true; } function removeOwner(address _owner) external onlyOwner { require(owners[_owner], "Not an owner"); require(_owner != msg.sender, "Cannot remove yourself"); owners[_owner] = false; } /// @notice Function to add a bot to the list (only callable by the contract owner) function addBot(address bot) external onlyOwner { require(bot != address(0), "Invalid address"); authorizedBots[bot] = true; } /// @notice Function to remove a bot from the list (only callable by the contract owner) function removeBot(address bot) external onlyOwner { require(bot != address(0), "Invalid address"); authorizedBots[bot] = false; } // Admin Functions function updatePool(uint256 _lockupPeriod, uint256 _dailyRewardRate) external onlyOwner { pool.lockupPeriod = _lockupPeriod * 1 days; pool.dailyRewardRate = _dailyRewardRate; emit PoolUpdated(_lockupPeriod, _dailyRewardRate); } function depositRewards(uint256 _amount) external onlyOwner { IERC20(pool.tokenAddress).safeTransferFrom(msg.sender, address(this), _amount); pool.totalRewards = pool.totalRewards + _amount; emit RewardsDeposited(_amount); } function updateStakeMin(uint256 _amount) external onlyOwner { minStakeLock = _amount; emit MinStakeLockUpdated(_amount); } function updateUnlockDelay(uint256 _delay) external onlyOwner { unlockDelay = _delay; } function updateRestakeBonus(uint256 _newBonus) external onlyOwner { restakeBonus = _newBonus; } /// @notice Function to add an address to have a fixed daily reward (only callable by the contract owner) /// @param _addr The address to give a fixed rate /// @param _rate The fixed rate expressed in 2 digits, ex: 40 function addFixedRate(address _addr, uint _rate) external onlyOwner { require(_addr != address(0), "Invalid address"); addressFixedRate[_addr] = _rate; } /// @notice Function to remove an address' fixed daily reward (only callable by the contract owner) /// @param _addr The address to 0 out function removeFixedRate(address _addr) external onlyOwner { require(_addr != address(0), "Invalid address"); addressFixedRate[_addr] = 0; } /// @notice Add or edit a tier range function addOrEditTier(uint256 minTokens, uint256 maxTokens, uint256 boostPercentage) public onlyOwner { require(minTokens < maxTokens, "Invalid range: minTokens must be < maxTokens"); require(!rangesOverlap(minTokens, maxTokens), "Range overlaps with existing tiers"); // Check if editing an existing range for (uint256 i = 0; i < boosttiers.length; ++i) { if (boosttiers[i].minTokens == minTokens && boosttiers[i].maxTokens == maxTokens) { // Edit the existing range boosttiers[i].boostPercentage = boostPercentage; return; } } // Add new range boosttiers.push(BoostRange(minTokens, maxTokens, boostPercentage)); // Sort the ranges after adding sortRanges(); } // Check for range overlap function rangesOverlap(uint256 minTokens, uint256 maxTokens) internal view returns (bool) { for (uint256 i = 0; i < boosttiers.length; ++i) { if (minTokens <= boosttiers[i].maxTokens && maxTokens >= boosttiers[i].minTokens) { return true; } } return false; } /// @notice Sort ranges by minTokens function sortRanges() internal { for (uint256 i = 0; i < boosttiers.length; ++i) { for (uint256 j = i + 1; j < boosttiers.length; j++) { if (boosttiers[i].minTokens > boosttiers[j].minTokens) { // Swap ranges BoostRange memory temp = boosttiers[i]; boosttiers[i] = boosttiers[j]; boosttiers[j] = temp; } } } } /// @notice Remove a range by index function removeTier(uint256 index) external onlyOwner { require(index < boosttiers.length, "Index out of bounds"); for (uint256 i = index; i < boosttiers.length - 1; ++i) { boosttiers[i] = boosttiers[i + 1]; } boosttiers.pop(); } function withdrawFromStakingPool(uint256 _amount) external onlyOwner { IERC20(pool.tokenAddress).safeTransfer(msg.sender, _amount); emit FundsWithdrawn(msg.sender, pool.tokenAddress, _amount); } function withdrawFromVestingPool(address _token, uint256 _amount) external onlyOwner { IERC20(_token).safeTransfer(msg.sender, _amount); emit FundsWithdrawn(msg.sender, _token, _amount); } function setUnlockScheduleByPercentage( address _token, uint256 _lockTime, // Total lock time in seconds uint256 _percentagePerStep // Percentage unlocked per step (in basis points, e.g., 100 = 1%) ) external onlyOwner { require(_lockTime != 0, "Lock time must be greater than zero"); require(_percentagePerStep != 0, "Percentage per step must be greater than zero"); uint256 totalPercentage = 10000; // 100% in basis points require(totalPercentage % _percentagePerStep == 0, "Percentage must divide 100% evenly"); uint256 steps = totalPercentage / _percentagePerStep; // Number of steps uint256 stepTime = _lockTime / steps; // Time interval per step delete unlockSchedules[_token]; // Clear existing schedule for this token for (uint256 i = 1; i <= steps; ++i) { unlockSchedules[_token].push(UnlockStep({ timeOffset: stepTime * i, // Time offset for this step percentage: _percentagePerStep })); } emit UnlockScheduleSet(_token); } /// @notice Get the boost percentage for a given token amount function getBoost(uint256 depositedTokens) public view returns (uint256) { for (uint256 i = 0; i < boosttiers.length; ++i) { if (depositedTokens >= boosttiers[i].minTokens && depositedTokens <= boosttiers[i].maxTokens) { return boosttiers[i].boostPercentage; } } return 0; // Default boost if no range matches } /// @notice This function will end and clear a user's stakes. /// @dev Only to be used by bots in emergencies /// @param user The user whose stakes will be ended and 0'd function clearStakes(address user) external onlyBot { uint256 clearedStakes = 0; for (uint256 i = 0; i < stakes[user].length; ++i) { Stake storage stake = stakes[user][i]; clearedStakes = clearedStakes + stake.amount; stake.amount = 0; stake.complete = true; } pool.totalStaked = pool.totalStaked - clearedStakes; } 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]; 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); } 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"); uint256 poolBalance = IERC20(pool.tokenAddress).balanceOf(address(this)); require(poolBalance >= stake.amount, "Insufficient rewards in the pool"); _amount = stake.amount; // Update state before external calls stake.amount = 0; withdrawLiabilities -= _amount; // 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]; uint rewards = getPoolRewards(msg.sender, i); totalReward = totalReward + rewards; stake.lastClaimed = block.timestamp; } require(totalReward > minStakeLock, "Not enough to compound"); stakes[msg.sender].push(Stake({ amount: totalReward, lastClaimed: block.timestamp, dailyRewardRate: pool.dailyRewardRate + getBoost(dollarsVested[msg.sender]), unlockTime: block.timestamp + pool.lockupPeriod, complete: false })); pool.totalStaked = pool.totalStaked + totalReward; emit CompoundRewards(msg.sender, totalReward); } function createVesting(address _token, uint256 _amount) external { require(_amount != 0, "Amount must be greater than zero"); address oracle = priceOracles[_token]; require(oracle != address(0), "Price oracle not set for this token"); IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount); uint256 bonus = (_amount * BONUS_PERCENTAGE) / 100; uint256 usdPrice = (iPriceOracle(priceOracles[_token]).getLatestPrice(_token) * _amount) / 1e18; require(usdPrice > minStakeLock, "Amount must be greater minStakeLock"); // Update user's dollarsVested dollarsVested[msg.sender] += usdPrice; // Update token's vestedTotal vestedTotal[_token] += _amount; vestings[msg.sender].push(Vesting({ amount: _amount, bonus: bonus, lockedUntil: block.timestamp + lockupDuration, claimedAmount: 0, claimedBonus: 0, lastClaimed: block.timestamp, createdAt: block.timestamp, token: _token, complete: false, usdAmount: usdPrice })); emit VestingCreated(msg.sender, _amount, bonus); } function getUnlockedVesting(address _user, uint256 _vestingIndex) public view returns (uint256) { Vesting storage vesting = vestings[_user][_vestingIndex]; uint256 timeElapsed = block.timestamp - vesting.createdAt; address token = vesting.token; uint256 unlockedAmount = 0; for (uint256 i = 0; i < unlockSchedules[token].length; ++i) { UnlockStep storage step = unlockSchedules[token][i]; uint256 timeTier = step.timeOffset; uint256 percentage = step.percentage; if (timeElapsed >= timeTier) { unlockedAmount = unlockedAmount + ((vesting.amount * percentage) / 10000); } } return unlockedAmount; } function getVestingSchedule(address _user, uint256 _vestingIndex) public view returns (uint256[] memory, uint256[] memory) { Vesting storage vesting = vestings[_user][_vestingIndex]; address token = vesting.token; uint256 scheduleLength = unlockSchedules[token].length; uint256[] memory unlockTimestamps = new uint256[](scheduleLength); uint256[] memory unlockPercentages = new uint256[](scheduleLength); for (uint256 i = 0; i < scheduleLength; ++i) { UnlockStep storage step = unlockSchedules[token][i]; // Calculate the absolute unlock timestamp unlockTimestamps[i] = vesting.createdAt + step.timeOffset; unlockPercentages[i] = step.percentage; // Percentage is stored as scaled by 10000 (e.g., 2500 = 25%) } return (unlockTimestamps, unlockPercentages); } function getUnlockedVestingBonus(address _user, uint256 _vestingIndex) public view returns (uint256) { Vesting storage vesting = vestings[_user][_vestingIndex]; uint256 timeElapsed = block.timestamp - vesting.createdAt; address token = vesting.token; uint256 unlockedAmount = 0; for (uint256 i = 0; i < unlockSchedules[token].length; ++i) { UnlockStep storage step = unlockSchedules[token][i]; uint256 timeTier = step.timeOffset; uint256 percentage = step.percentage; uint256 maxBonusAmount = (vesting.usdAmount * BONUS_PERCENTAGE) / 100; if (timeElapsed >= timeTier) { unlockedAmount = unlockedAmount + ((maxBonusAmount * percentage) / 10000); } } return unlockedAmount; } function claimVesting(uint256 _vestingIndex) external nonReentrant { Vesting storage vesting = vestings[msg.sender][_vestingIndex]; require(vesting.complete == false, "Stake is Complete"); uint256 maxClaim = getUnlockedVesting(msg.sender, _vestingIndex); require(maxClaim >= vesting.claimedAmount, "Invalid claim amount"); uint256 amountToClaim = maxClaim - vesting.claimedAmount; require(amountToClaim != 0, "No vested amount to claim"); vesting.claimedAmount = vesting.claimedAmount + amountToClaim; if (vesting.claimedAmount >= vesting.amount) { vesting.complete = true; } // Update user's dollarsVested if (dollarsVested[msg.sender] > 0) { uint256 usdPrice = (iPriceOracle(priceOracles[vesting.token]).getLatestPrice(vesting.token) * amountToClaim) / 1e18; if (usdPrice >= dollarsVested[msg.sender]) { dollarsVested[msg.sender] = 0; } else { dollarsVested[msg.sender] -= usdPrice; } } vestedTotal[vesting.token] -= amountToClaim; IERC20(vesting.token).safeTransfer(msg.sender, amountToClaim); emit VestingClaimed(msg.sender, amountToClaim, 0); } function claimAllVestingByToken(address _token) external nonReentrant { uint256 totalReward = 0; uint256 vestingsProcessed = 0; for (uint256 i = 0; i < vestings[msg.sender].length; ++i) { Vesting storage vesting = vestings[msg.sender][i]; if (vesting.token == _token && !vesting.complete) { uint256 maxClaim = getUnlockedVesting(msg.sender, i); require(maxClaim >= vesting.claimedAmount, "Invalid claim amount"); uint256 amountToClaim = maxClaim - vesting.claimedAmount; if (amountToClaim > 0) { vesting.claimedAmount = vesting.claimedAmount + amountToClaim; totalReward = totalReward + amountToClaim; vesting.lastClaimed = block.timestamp; // Mark vesting as complete if fully claimed if (vesting.claimedAmount >= vesting.amount) { vesting.complete = true; } vestingsProcessed++; } } } require(totalReward != 0, "No rewards to claim"); // Update user's dollarsVested if (dollarsVested[msg.sender] > 0) { uint256 usdPrice = (iPriceOracle(priceOracles[_token]).getLatestPrice(_token) * totalReward) / 1e18; if (usdPrice >= dollarsVested[msg.sender]) { dollarsVested[msg.sender] = 0; } else { dollarsVested[msg.sender] -= usdPrice; } } // Ensure the contract has enough balance to fulfill the claim uint256 poolBalance = IERC20(_token).balanceOf(address(this)); require(poolBalance >= totalReward, "Insufficient rewards in the pool"); // Update vesting total vestedTotal[_token] -= totalReward; // Transfer the aggregated reward IERC20(_token).safeTransfer(msg.sender, totalReward); emit RewardClaimed(msg.sender, totalReward); } function claimBonus(uint256 _vestingIndex) external nonReentrant { Vesting storage vesting = vestings[msg.sender][_vestingIndex]; uint256 maxBonus = getUnlockedVestingBonus(msg.sender, _vestingIndex); require(maxBonus >= vesting.claimedBonus, "Invalid claim amount"); uint256 bonusToClaim = maxBonus - vesting.claimedBonus; require(bonusToClaim != 0, "No vested amount to claim"); vesting.claimedBonus = vesting.claimedBonus + bonusToClaim; withdrawLiabilities += bonusToClaim; // IERC20(vesting.token).safeTransfer(msg.sender, bonusToClaim); // Create temporary the stake for the user to delay withdraw. // Add 1e6 to the vesting index to distinguish them from normal stakes. withdrawStake[msg.sender].push(WithdrawStake({ stakeId: _vestingIndex + 1e6, amount: bonusToClaim, unlockTime: block.timestamp + unlockDelay })); emit BonusClaimed(msg.sender, bonusToClaim); } function setPriceOracle(address _token, address _oracle) external onlyOwner { priceOracles[_token] = _oracle; } function viewRewards(address _user) external view returns (uint256) { uint256 totalReward = 0; for (uint256 i = 0; i < stakes[_user].length; ++i) { uint rewards = getPoolRewards(_user, i); totalReward = totalReward + rewards; } return totalReward; } /// @notice View function to get all stakes for a specific address function getStakes(address user) external view returns (Stake[] memory) { return stakes[user]; } /// @notice View function to get all vestings for a specific address function getVestings(address user) external view returns (Vesting[] memory) { return vestings[user]; } /// @notice View to monitor contract pool deficits function getPoolStatus() external view returns (uint256) { uint256 poolBalance = IERC20(pool.tokenAddress).balanceOf(address(this)); // If the balance is greater than or equal to liabilities, return 0 if (poolBalance >= withdrawLiabilities) { return 0; } // Otherwise, return the deficit (amount needed to cover liabilities) return withdrawLiabilities - poolBalance; } /** * @notice Returns the vested amounts and USD values for an array of tokens. * @param _tokens The array of token addresses to evaluate. * @return amounts The array of vested amounts for each token. * @return usdValues The array of USD values for each token’s vested amount. * @return totalUsd The total USD value of all vested tokens in the array. */ function getVestedTotals(address[] calldata _tokens) external view returns ( uint256[] memory amounts, uint256[] memory usdValues, uint256 totalUsd ) { uint256 length = _tokens.length; amounts = new uint256[](length); usdValues = new uint256[](length); for (uint256 i = 0; i < length; i++) { address token = _tokens[i]; // 1. Get the total amount vested for this token. uint256 tokenAmount = vestedTotal[token]; amounts[i] = tokenAmount; // 2. Query the oracle for this token’s USD price. // Assumes the oracle returns a price scaled by 1e18. uint256 price = iPriceOracle(priceOracles[token]).getLatestPrice(token); // 3. Calculate the vested USD value: (price * amount) / 1e18 uint256 valueInUsd = (price * tokenAmount) / 1e18; usdValues[i] = valueInUsd; // 4. Accumulate the total USD amount totalUsd += valueInUsd; } return (amounts, usdValues, totalUsd); } /// @notice Returns the total USD value of the user's unclaimed, uncomplete, stake amounts, based on current token prices from the oracle. /// @return totalUsd The total unclaimed stake value, in USD (1e18 precision). function getUserTotalUnclaimedUsdValue(address user) external view returns (uint256 totalUsd) { uint256 length = vestings[user].length; for (uint256 i = 0; i < length; i++) { Vesting memory v = vestings[user][i]; if (!v.complete) { uint256 tokenPrice = iPriceOracle(priceOracles[v.token]).getLatestPrice(v.token); // The unclaimed portion of the stake uint256 unclaimedAmount = v.amount - v.claimedAmount; // Convert unclaimed tokens to USD value uint256 stakeUsd = (tokenPrice * unclaimedAmount) / 1e18; totalUsd += stakeUsd; } } return totalUsd; } /// @notice Function that lets you look up an address’s stake by stakeId. /// @param user The address to evaluate. /// @param _stakeId The stakeId of the ORIGINAL stake that is waiting to be unlocked function getWithdrawStake(address user, uint256 _stakeId) external view returns (WithdrawStake memory) { WithdrawStake[] storage userStakes = withdrawStake[user]; for (uint256 i = 0; i < userStakes.length; i++) { if (userStakes[i].stakeId == _stakeId) { return userStakes[i]; } } revert("WithdrawStake with the specified stakeId not found for this user."); } /// @notice Function that lets you look up an address’s stake by vestingId. /// @param user The address to evaluate. /// @param _vestingId The vestingId of the ORIGINAL vest that is waiting to be unlocked function getVestingWithdrawStake(address user, uint256 _vestingId) external view returns (WithdrawStake memory) { WithdrawStake[] storage userStakes = withdrawStake[user]; uint256 boostedVestingId = _vestingId + 1e6; for (uint256 i = 0; i < userStakes.length; i++) { if (userStakes[i].stakeId == boostedVestingId) { return userStakes[i]; } } revert("WithdrawStake with the specified stakeId not found for this user."); } /// @notice Function that returns an array of all the user's withdrawStakes. /// @param user The address to evaluate. /// @return An array of WithdrawStake for the given user. function getAllWithdrawStakes(address user) external view returns (WithdrawStake[] memory) { return withdrawStake[user]; } }
// 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
[{"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":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakeId","type":"uint256"}],"name":"StakeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"UnlockScheduleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bonus","type":"uint256"}],"name":"VestingClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bonus","type":"uint256"}],"name":"VestingCreated","type":"event"},{"inputs":[{"internalType":"address","name":"bot","type":"address"}],"name":"addBot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"},{"internalType":"uint256","name":"_rate","type":"uint256"}],"name":"addFixedRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minTokens","type":"uint256"},{"internalType":"uint256","name":"maxTokens","type":"uint256"},{"internalType":"uint256","name":"boostPercentage","type":"uint256"}],"name":"addOrEditTier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"addOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"addressFixedRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"authorizedBots","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"boosttiers","outputs":[{"internalType":"uint256","name":"minTokens","type":"uint256"},{"internalType":"uint256","name":"maxTokens","type":"uint256"},{"internalType":"uint256","name":"boostPercentage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_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":[],"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 PacaFinanceWithBoostAndSchedule.StakeInput[]","name":"stakesInput","type":"tuple[]"}],"name":"createStakes","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"createVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"dollarsVested","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getAllWithdrawStakes","outputs":[{"components":[{"internalType":"uint256","name":"stakeId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"internalType":"struct PacaFinanceWithBoostAndSchedule.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 PacaFinanceWithBoostAndSchedule.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 PacaFinanceWithBoostAndSchedule.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 PacaFinanceWithBoostAndSchedule.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 PacaFinanceWithBoostAndSchedule.WithdrawStake","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockupDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minStakeLock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"owners","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"uint256","name":"lockupPeriod","type":"uint256"},{"internalType":"uint256","name":"dailyRewardRate","type":"uint256"},{"internalType":"uint256","name":"totalStaked","type":"uint256"},{"internalType":"uint256","name":"totalRewards","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"priceOracles","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bot","type":"address"}],"name":"removeBot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"removeFixedRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"removeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"removeTier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakeIndex","type":"uint256"},{"internalType":"uint256","name":"_restakePercentage","type":"uint256"}],"name":"restake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"restakeBonus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"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":"_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":"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
608060405234801561001057600080fd5b5061565280620000216000396000f3fe6080604052600436106103c35760003560e01c8063710ea0ce116101f2578063b8e7023d1161010d578063ce13d090116100a0578063d96134101161006f578063d961341014610cb8578063da40ef8014610cd8578063e4d06f9014610cf8578063ffecf51614610d1857600080fd5b8063ce13d09014610c38578063cfb866da14610c58578063d6c680eb14610c78578063d919302514610c9857600080fd5b8063bd84477d116100dc578063bd84477d14610b2d578063bed9757e14610ba2578063c606627214610bd0578063c7b530b014610c0b57600080fd5b8063b8e7023d14610aa0578063b90fba1914610ac0578063b92a349f14610ae0578063bd72169814610b0057600080fd5b8063853e0df2116101855780639562ee15116101545780639562ee1514610a2057806396ed7f8914610a40578063ac97b41714610a60578063b6c3dc4c14610a8057600080fd5b8063853e0df2146109aa5780638bdf67f2146109ca5780638da5cb5b146109ea57806392257cb514610a0a57600080fd5b80637bc221ac116101c15780637bc221ac146109405780637f79496c1461096057806380ca0ecf146109755780638129fc1c1461099557600080fd5b8063710ea0ce146108a65780637497211b146108c65780637a0c6dc0146108e65780637ba6f4581461091357600080fd5b806338a85ce2116102e2578063584b62a11161027557806367a74ddc1161024457806367a74ddc146108315780636ae21510146108515780636c3b0c53146108665780637065cb481461088657600080fd5b8063584b62a11461077a578063592d1dd1146107c4578063599ab2c4146107f15780635fecd9261461081157600080fd5b806343c7c011116102b157806343c7c011146106ef57806344c7d6ef1461070f57806351f6cf2f1461072f5780635339dcc11461076457600080fd5b806338a85ce21461065a5780633ba8396e146106705780633c92f98d146106a05780633f35e722146106cf57600080fd5b806316f0115b1161035a5780631d7a3361116103295780631d7a3361146105f257806322a26fc0146106125780632e1a7d4d14610625578063372500ab1461064557600080fd5b806316f0115b1461053b578063173825d91461059c5780631ada70a8146105bc5780631bf6ddae146105d257600080fd5b80630a84096a116103965780630a84096a146104ac5780630d046d11146104cc57806313c8e2de146104f957806316be9b2a1461051957600080fd5b806301374518146103c8578063022914a71461041b5780630519da321461045b578063092c76101461047f575b600080fd5b3480156103d457600080fd5b506103fe6103e3366004614f87565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561042757600080fd5b5061044b610436366004614f87565b60076020526000908152604090205460ff1681565b6040519015158152602001610412565b34801561046757600080fd5b5061047160115481565b604051908152602001610412565b34801561048b57600080fd5b5061047161049a366004614f87565b60106020526000908152604090205481565b3480156104b857600080fd5b506104716104c7366004614fa2565b610d38565b3480156104d857600080fd5b506104ec6104e7366004614fa2565b610e70565b6040516104129190614fcc565b34801561050557600080fd5b50610471610514366004614fed565b610fd5565b34801561052557600080fd5b50610539610534366004614fa2565b611086565b005b34801561054757600080fd5b5060015460025460035460045460055461056b94939291906001600160a01b031685565b6040805195865260208601949094529284019190915260608301526001600160a01b0316608082015260a001610412565b3480156105a857600080fd5b506105396105b7366004614f87565b6110f7565b3480156105c857600080fd5b50610471600d5481565b3480156105de57600080fd5b506105396105ed366004614fed565b6111ef565b3480156105fe57600080fd5b5061053961060d366004614f87565b611374565b610539610620366004615006565b61147d565b34801561063157600080fd5b50610539610640366004614fed565b6115d1565b34801561065157600080fd5b506105396118b7565b34801561066657600080fd5b50610471600e5481565b34801561067c57600080fd5b5061044b61068b366004614f87565b600f6020526000908152604090205460ff1681565b3480156106ac57600080fd5b506106c06106bb36600461507b565b611a0e565b60405161041293929190615119565b3480156106db57600080fd5b506105396106ea366004614fa2565b611bfe565b3480156106fb57600080fd5b5061053961070a366004614f87565b611c85565b34801561071b57600080fd5b5061053961072a366004614fed565b612023565b34801561073b57600080fd5b5061074f61074a366004614fa2565b61223f565b60408051928352602083019190915201610412565b34801561077057600080fd5b5061047160145481565b34801561078657600080fd5b5061079a610795366004614fa2565b61227b565b6040805195865260208601949094529284019190915260608301521515608082015260a001610412565b3480156107d057600080fd5b506104716107df366004614f87565b600c6020526000908152604090205481565b3480156107fd57600080fd5b5061047161080c36600461514f565b6122cc565b34801561081d57600080fd5b5061053961082c366004614f87565b61231c565b34801561083d57600080fd5b5061053961084c36600461518b565b612392565b34801561085d57600080fd5b506105396123ef565b34801561087257600080fd5b50610539610881366004614fa2565b6125c8565b34801561089257600080fd5b506105396108a1366004614f87565b612923565b3480156108b257600080fd5b506104716108c1366004614fa2565b6129d2565b3480156108d257600080fd5b506105396108e1366004614fed565b612a69565b3480156108f257600080fd5b50610906610901366004614f87565b612ba7565b60405161041291906151be565b34801561091f57600080fd5b5061093361092e366004614f87565b612c8e565b604051610412919061526c565b34801561094c57600080fd5b5061047161095b366004614f87565b612d29565b34801561096c57600080fd5b50610471612efc565b34801561098157600080fd5b50610471610990366004614fa2565b612f94565b3480156109a157600080fd5b506105396130a0565b3480156109b657600080fd5b506105396109c5366004614fed565b6135a1565b3480156109d657600080fd5b506105396109e5366004614fed565b61362e565b3480156109f657600080fd5b506006546103fe906001600160a01b031681565b348015610a1657600080fd5b5061047160125481565b348015610a2c57600080fd5b50610539610a3b366004614fed565b6136bd565b348015610a4c57600080fd5b50610539610a5b3660046152cf565b613721565b348015610a6c57600080fd5b50610539610a7b366004614fed565b6137a2565b348015610a8c57600080fd5b506104ec610a9b366004614fa2565b613a84565b348015610aac57600080fd5b50610539610abb3660046152cf565b613b59565b348015610acc57600080fd5b50610539610adb366004614f87565b613eed565b348015610aec57600080fd5b50610539610afb3660046152f1565b613f5c565b348015610b0c57600080fd5b50610471610b1b366004614f87565b60156020526000908152604090205481565b348015610b3957600080fd5b50610b4d610b48366004614fa2565b6141a3565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925260a086015260c08501526001600160a01b031660e0840152151561010083015261012082015261014001610412565b348015610bae57600080fd5b50610bc2610bbd366004614fa2565b614221565b604051610412929190615324565b348015610bdc57600080fd5b50610bf0610beb366004614fa2565b6143c7565b60408051938452602084019290925290820152606001610412565b348015610c1757600080fd5b50610c2b610c26366004614f87565b614409565b6040516104129190615352565b348015610c4457600080fd5b50610539610c53366004614fed565b614491565b348015610c6457600080fd5b50610bf0610c73366004614fed565b6144c5565b348015610c8457600080fd5b50610539610c93366004614fed565b6144f8565b348015610ca457600080fd5b50610539610cb3366004614fed565b61452c565b348015610cc457600080fd5b50610539610cd33660046153b4565b6146cb565b348015610ce457600080fd5b50610471610cf3366004614f87565b614915565b348015610d0457600080fd5b50610539610d13366004614fa2565b61496d565b348015610d2457600080fd5b50610539610d33366004614f87565b614ae3565b6001600160a01b0382166000908152600960205260408120805482919084908110610d6557610d656153e0565b906000526020600020906009020190506000816006015442610d87919061540c565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a6020526040902054811015610e63576001600160a01b0383166000908152600a60205260408120805483908110610de657610de66153e0565b6000918252602082206002909102018054600182015460088a015492945090929091606490610e1790600a9061541f565b610e21919061544c565b9050828810610e4e57612710610e37838361541f565b610e41919061544c565b610e4b9087615460565b95505b5050505080610e5c90615473565b9050610d9c565b5093505050505b92915050565b610e9460405180606001604052806000815260200160008152602001600081525090565b6001600160a01b038316600090815260136020526040812090610eba84620f4240615460565b905060005b8254811015610f575781838281548110610edb57610edb6153e0565b90600052602060002090600302016000015403610f4557828181548110610f0457610f046153e0565b906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820154815250509350505050610e6a565b80610f4f81615473565b915050610ebf565b5060405162461bcd60e51b815260206004820152604160248201527f57697468647261775374616b652077697468207468652073706563696669656460448201527f207374616b654964206e6f7420666f756e6420666f72207468697320757365726064820152601760f91b608482015260a4015b60405180910390fd5b6000805b60005481101561107d5760008181548110610ff657610ff66153e0565b906000526020600020906003020160000154831015801561103b575060008181548110611025576110256153e0565b9060005260206000209060030201600101548311155b1561106d5760008181548110611053576110536153e0565b906000526020600020906003020160020154915050919050565b61107681615473565b9050610fd9565b50600092915050565b3360009081526007602052604090205460ff166110b55760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b0382166110db5760405162461bcd60e51b8152600401610fcc906154b4565b6001600160a01b03909116600090815260156020526040902055565b3360009081526007602052604090205460ff166111265760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b03811660009081526007602052604090205460ff1661117d5760405162461bcd60e51b815260206004820152600c60248201526b2737ba1030b71037bbb732b960a11b6044820152606401610fcc565b336001600160a01b038216036111ce5760405162461bcd60e51b815260206004820152601660248201527521b0b73737ba103932b6b7bb32903cb7bab939b2b63360511b6044820152606401610fcc565b6001600160a01b03166000908152600760205260409020805460ff19169055565b600e546112018264e8d4a5100061541f565b1161121e5760405162461bcd60e51b8152600401610fcc906154dd565b600554611236906001600160a01b0316333084614b5c565b336000908152601560205260408120541561126157503360009081526015602052604090205461126f565b61126c3360006122cc565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a00160405280848152602001428152602001838152602001600160000154426112c29190615460565b815260006020918201819052835460018082018655948252828220845160059092020190815591830151938201939093556040820151600282015560608201516003808301919091556080909201516004909101805460ff19169115159190911790558054849290611335908490615460565b909155505060405182815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906020015b60405180910390a25050565b336000908152600f602052604090205460ff166113d35760405162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206973206e6f7420616e20617574686f72697a656420626f74006044820152606401610fcc565b6000805b6001600160a01b038316600090815260086020526040902054811015611467576001600160a01b0383166000908152600860205260408120805483908110611421576114216153e0565b906000526020600020906005020190508060000154836114419190615460565b600082556004909101805460ff19166001179055915061146081615473565b90506113d7565b5060035461147690829061540c565b6003555050565b336000908152600f602052604090205460ff166114dc5760405162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206973206e6f7420616e20617574686f72697a656420626f74006044820152606401610fcc565b8060005b818110156115cb57368484838181106114fb576114fb6153e0565b905060a00201905080602001356001600201546115189190615460565b6003556008600061152c6020840184614f87565b6001600160a01b0316815260208082019290925260409081016000908120825160a08101845285850135815285840135818601908152608080880135958301958652606097880135978301978852820184815283546001808201865594865296909420915160059096029091019485555184820155915160028401559251600383015591516004909101805460ff1916911515919091179055016114e0565b50505050565b6115d9614bc3565b33600090815260136020526040812080546116415760405162461bcd60e51b815260206004820152602260248201527f4e6f207374616b657320617661696c61626c6520666f72207769746864726177604482015261185b60f21b6064820152608401610fcc565b60005b815481101561185e576000828281548110611661576116616153e0565b906000526020600020906003020190508481600001540361184d5780600101546000036116e25760405162461bcd60e51b815260206004820152602960248201527f5374616b6520616c72656164792077697468647261776e206f7220646f6573206044820152681b9bdd08195e1a5cdd60ba1b6064820152608401610fcc565b80600201544210156117365760405162461bcd60e51b815260206004820152601e60248201527f5769746864726177205374616b65206973207374696c6c206c6f636b656400006044820152606401610fcc565b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa15801561177f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a39190615520565b905081600101548110156117c95760405162461bcd60e51b8152600401610fcc90615539565b816001015494506000826001018190555084601260008282546117ec919061540c565b9091555050600554611808906001600160a01b03163387614bfb565b604080518681526020810188905233917f933735aa8de6d7547d0126171b2f31b9c34dd00f3ecd4be85a0ba047db4fafef910160405180910390a2505050505061189d565b5061185781615473565b9050611644565b5060405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b6044820152606401610fcc565b6118b460016000805160206155fd83398151915255565b50565b6118bf614bc3565b6000805b33600090815260086020526040902054811015611940573360009081526008602052604081208054839081106118fb576118fb6153e0565b90600052602060002090600502019050600061191733846129d2565b90506119238185615460565b4260019093019290925550915061193981615473565b90506118c3565b50806000036119875760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b6044820152606401610fcc565b6004548111156119a95760405162461bcd60e51b8152600401610fcc90615539565b6004546119b790829061540c565b6004556005546119d1906001600160a01b03163383614bfb565b60405181815233906000805160206155dd8339815191529060200160405180910390a250611a0c60016000805160206155fd83398151915255565b565b6060806000838067ffffffffffffffff811115611a2d57611a2d61556e565b604051908082528060200260200182016040528015611a56578160200160208202803683370190505b5093508067ffffffffffffffff811115611a7257611a7261556e565b604051908082528060200260200182016040528015611a9b578160200160208202803683370190505b50925060005b81811015611bf5576000878783818110611abd57611abd6153e0565b9050602002016020810190611ad29190614f87565b6001600160a01b0381166000908152601060205260409020548751919250908190889085908110611b0557611b056153e0565b6020908102919091018101919091526001600160a01b038381166000818152600b90935260408084205490516302c68be360e31b81526004810192909252909116906316345f1890602401602060405180830381865afa158015611b6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b919190615520565b90506000670de0b6b3a7640000611ba8848461541f565b611bb2919061544c565b905080888681518110611bc757611bc76153e0565b6020908102919091010152611bdc8188615460565b9650505050508080611bed90615473565b915050611aa1565b50509250925092565b3360009081526007602052604090205460ff16611c2d5760405162461bcd60e51b8152600401610fcc9061548c565b611c416001600160a01b0383163383614bfb565b6040518181526001600160a01b0383169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a35050565b611c8d614bc3565b60008060005b33600090815260096020526040902054811015611dc657336000908152600960205260408120805483908110611ccb57611ccb6153e0565b6000918252602090912060099091020160078101549091506001600160a01b038681169116148015611d0957506007810154600160a01b900460ff16155b15611db5576000611d1a3384612f94565b90508160030154811015611d405760405162461bcd60e51b8152600401610fcc90615584565b6000826003015482611d52919061540c565b90508015611db257808360030154611d6a9190615460565b6003840155611d798187615460565b4260058501558354600385015491975011611da45760078301805460ff60a01b1916600160a01b1790555b84611dae81615473565b9550505b50505b50611dbf81615473565b9050611c93565b5081600003611e0d5760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b6044820152606401610fcc565b336000908152600c602052604090205415611f16576001600160a01b038381166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928692909116906316345f1890602401602060405180830381865afa158015611e89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ead9190615520565b611eb7919061541f565b611ec1919061544c565b336000908152600c60205260409020549091508110611eef57336000908152600c6020526040812055611f14565b336000908152600c602052604081208054839290611f0e90849061540c565b90915550505b505b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015611f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f819190615520565b905082811015611fa35760405162461bcd60e51b8152600401610fcc90615539565b6001600160a01b03841660009081526010602052604081208054859290611fcb90849061540c565b90915550611fe590506001600160a01b0385163385614bfb565b60405183815233906000805160206155dd833981519152906020015b60405180910390a25050506118b460016000805160206155fd83398151915255565b61202b614bc3565b33600090815260086020526040902054811061207f5760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b6044820152606401610fcc565b3360009081526008602052604081208054839081106120a0576120a06153e0565b6000918252602082206005909102018054909250906120bf33856129d2565b90506120cb8183615460565b9150816000036121125760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b6044820152606401610fcc565b826003015442101561215e5760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b6044820152606401610fcc565b600080845560048401805460ff1916600117905560128054849290612184908490615460565b909155505060035482116121b25781600160020160008282546121a7919061540c565b909155506121b89050565b60006003555b33600090815260136020908152604091829020825160608101845287815291820185905260115490928201906121ee9042615460565b90528154600180820184556000938452602093849020835160039093020191825582840151908201556040918201516002909101555183815233916000805160206155dd8339815191529101612001565b600a602052816000526040600020818154811061225b57600080fd5b600091825260209091206002909102018054600190910154909250905082565b6008602052816000526040600020818154811061229757600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919060ff1685565b6001600160a01b0382166000908152600c602052604081205481906122f090610fd5565b6002546122fd9190615460565b90508215612315576014546123129082615460565b90505b9392505050565b3360009081526007602052604090205460ff1661234b5760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b0381166123715760405162461bcd60e51b8152600401610fcc906154b4565b6001600160a01b03166000908152600f60205260409020805460ff19169055565b3360009081526007602052604090205460ff166123c15760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b039182166000908152600b6020526040902080546001600160a01b03191691909216179055565b6000805b336000908152600860205260409020548110156124705733600090815260086020526040812080548390811061242b5761242b6153e0565b90600052602060002090600502019050600061244733846129d2565b90506124538185615460565b4260019093019290925550915061246981615473565b90506123f3565b50600e5481116124bb5760405162461bcd60e51b8152602060048201526016602482015275139bdd08195b9bdd59da081d1bc818dbdb5c1bdd5b9960521b6044820152606401610fcc565b336000818152600860209081526040808320815160a0810183528681524281850152948452600c90925291829020549092918201906124f990610fd5565b6002546125069190615460565b81526020016001600001544261251c9190615460565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff1916921515929092179091555461258d908290615460565b60035560405181815233907f3afe5b60dee16617a8adbbd7d6c28f17a27efabb834872efa8e7ad5dafddf6f19060200160405180910390a250565b806000036126185760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610fcc565b6001600160a01b038083166000908152600b6020526040902054168061268c5760405162461bcd60e51b815260206004820152602360248201527f5072696365206f7261636c65206e6f742073657420666f72207468697320746f60448201526235b2b760e91b6064820152608401610fcc565b6126a16001600160a01b038416333085614b5c565b600060646126b0600a8561541f565b6126ba919061544c565b6001600160a01b038581166000818152600b60205260408082205490516302c68be360e31b8152600481019390935293945092670de0b6b3a76400009287929116906316345f1890602401602060405180830381865afa158015612722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127469190615520565b612750919061541f565b61275a919061544c565b9050600e54811161277d5760405162461bcd60e51b8152600401610fcc906154dd565b336000908152600c60205260408120805483929061279c908490615460565b90915550506001600160a01b038516600090815260106020526040812080548692906127c9908490615460565b909155505033600090815260096020908152604091829020825161014081018452878152918201859052600d5490928201906128059042615460565b81526000602080830182905260408084018390524260608086018290526080808701929092526001600160a01b038d811660a08089019190915260c080890188905260e09889018c90528a5460018082018d559b8952978790208a51600990990201978855898701519a88019a909a558885015160028801559188015160038701559187015160048601558601516005850155958501516006840155928401516007830180546101008701511515600160a01b026001600160a81b031990911692909716919091179590951790945561012090920151600890920191909155805186815291820184905233917f9ade76f4385de306666dfb21a52b27d52db0fde8ad0f515fa261f532cac60d21910160405180910390a25050505050565b3360009081526007602052604090205460ff166129525760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b03811660009081526007602052604090205460ff16156129ae5760405162461bcd60e51b815260206004820152601060248201526f20b63932b0b23c9030b71037bbb732b960811b6044820152606401610fcc565b6001600160a01b03166000908152600760205260409020805460ff19166001179055565b6001600160a01b03821660009081526008602052604081208054829190849081106129ff576129ff6153e0565b906000526020600020906005020190506000816001015442612a21919061540c565b90506000612710620151808385600201548660000154612a41919061541f565b612a4b919061541f565b612a55919061544c565b612a5f919061544c565b9695505050505050565b3360009081526007602052604090205460ff16612a985760405162461bcd60e51b8152600401610fcc9061548c565b6000548110612adf5760405162461bcd60e51b8152602060048201526013602482015272496e646578206f7574206f6620626f756e647360681b6044820152606401610fcc565b805b600054612af09060019061540c565b811015612b6d576000612b04826001615460565b81548110612b1457612b146153e0565b906000526020600020906003020160008281548110612b3557612b356153e0565b60009182526020909120825460039092020190815560018083015490820155600291820154910155612b6681615473565b9050612ae1565b506000805480612b7f57612b7f6155b2565b6000828152602081206003600019909301928302018181556001810182905560020155905550565b6001600160a01b0381166000908152600960209081526040808320805482518185028101850190935280835260609492939192909184015b82821015612c8357600084815260209081902060408051610140810182526009860290920180548352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a0840152600681015460c084015260078101546001600160a01b03811660e0850152600160a01b900460ff161515610100840152600801546101208301529083529092019101612bdf565b505050509050919050565b6001600160a01b0381166000908152600860209081526040808320805482518185028101850190935280835260609492939192909184015b82821015612c835760008481526020908190206040805160a081018252600586029092018054835260018082015484860152600282015492840192909252600381015460608401526004015460ff16151560808301529083529092019101612cc6565b6001600160a01b038116600090815260096020526040812054815b81811015612ef5576001600160a01b0384166000908152600960205260408120805483908110612d7657612d766153e0565b600091825260209182902060408051610140810182526009909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260078201546001600160a01b03811660e083015260ff600160a01b90910416151561010082018190526008909201546101208201529150612ee25760e0810180516001600160a01b039081166000908152600b602052604080822054935190516302c68be360e31b815290831660048201529092909116906316345f1890602401602060405180830381865afa158015612e73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e979190615520565b9050600082606001518360000151612eaf919061540c565b90506000670de0b6b3a7640000612ec6838561541f565b612ed0919061544c565b9050612edc8188615460565b96505050505b5080612eed81615473565b915050612d44565b5050919050565b6005546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612f49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f6d9190615520565b90506012548110612f8057600091505090565b80601254612f8e919061540c565b91505090565b6001600160a01b0382166000908152600960205260408120805482919084908110612fc157612fc16153e0565b906000526020600020906009020190506000816006015442612fe3919061540c565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a6020526040902054811015610e63576001600160a01b0383166000908152600a60205260408120805483908110613042576130426153e0565b60009182526020909120600290910201805460018201549192509081871061308c5787546127109061307590839061541f565b61307f919061544c565b6130899086615460565b94505b5050508061309990615473565b9050612ff8565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156130e65750825b905060008267ffffffffffffffff1660011480156131035750303b155b905081158015613111575080155b1561312f5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561315957845460ff60401b1916600160401b1785555b613161614c40565b600680546001600160a01b03199081167341970ce76b656030a79e7c1fa76fc4eb93980255178255600760209081527f1428bfef657344f5f7a0019d1554dccabe000be344bb83cdab918bd50f24b573805460ff1990811660019081179092556301499700600d81905567de0b6b3a76400000600e556005805490951673833589fcd6edb6e08f4c7c32d4f71b54bda02913178555825560216002908155604080516060808201835268bdbc41e0348b300000825269021e0c0013070adc000082880190815282840187815260008054808a018255818052945160039586027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5638181019290925593517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5648086019190915592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565948501558651808601885269021e19e0c9bab2400000815269043c25e0dcc1bd1c0000818d01908152818901998a528354808d01855584805291519188028084019290925551818501559751978401979097558551808501875269043c33c1937564800000815269065a3fc1a67c6f5c0000818c019081528188018781528354808d0185558480529251928802808b019390935590518285015551908401558551808501875269065a4da25d3016c00000815269087859a27037219c0000818c0190815260048289019081528354808d0185558480529251928802808b0193909355905182850155519084015585518085018752690878678326eac90000008152690cb48d6403ac861c0000818c019081528188019c8d528254808c0184558380529151918702808a019290925551818401559a519a83019a909a5584518084018652690cb49b44ba602d80000081526910f0c1259721ea9c0000818b019081528187019c8d528b54808b018d558c805291519186028089019290925551818301559a519a82019a909a55835180830185526910f0cf064dd592000000815269152cf4e72a974f1c0000818a0190815260088287019081528b54808b018d558c80529251928602808901939093559051828d015551908201558351918201845269152d02c7e14af68000008252600019828901908152600a94830194855289548089018b558a805292519284029586019290925590519884019890985590519190960155600f9092527f77c9ddf83be31065a9eb7ed19d93a8a4db24cad8351f41cc546083ac9e9d8c7f8054831682179055737c40f272570fdf9549d6f67493ac250a1db52f279092527f1b209462f90614903451721396f08356b5037572bebcd67a02efc98f03bec9d1805490911690911790556201fa40601155601455831561359a57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b3360009081526007602052604090205460ff166135d05760405162461bcd60e51b8152600401610fcc9061548c565b6005546135e7906001600160a01b03163383614bfb565b6005546040518281526001600160a01b039091169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a350565b3360009081526007602052604090205460ff1661365d5760405162461bcd60e51b8152600401610fcc9061548c565b600554613675906001600160a01b0316333084614b5c565b600454613683908290615460565b6004556040518181527f4e9221f2cca6ca0397acc6004ea0b716798254f5abcf53924fab34f0373e5d4e906020015b60405180910390a150565b3360009081526007602052604090205460ff166136ec5760405162461bcd60e51b8152600401610fcc9061548c565b600e8190556040518181527fe5dadb089824c750e4e7a2e98bfbe130f1a09834769e81339639fbe18606859b906020016136b2565b3360009081526007602052604090205460ff166137505760405162461bcd60e51b8152600401610fcc9061548c565b61375d826201518061541f565b600155600281905560408051838152602081018390527f7fa9647ec1cc14e3822b46d05a2b9d4e019bde8875c0088c46b6503d71bf1722910160405180910390a15050565b6137aa614bc3565b3360009081526009602052604081208054839081106137cb576137cb6153e0565b600091825260209091206009909102016007810154909150600160a01b900460ff161561382e5760405162461bcd60e51b81526020600482015260116024820152705374616b6520697320436f6d706c65746560781b6044820152606401610fcc565b600061383a3384612f94565b905081600301548110156138605760405162461bcd60e51b8152600401610fcc90615584565b6000826003015482613872919061540c565b9050806000036138c05760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b6044820152606401610fcc565b8083600301546138d09190615460565b600384018190558354116138f45760078301805460ff60a01b1916600160a01b1790555b336000908152600c602052604090205415613a025760078301546001600160a01b039081166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928592909116906316345f1890602401602060405180830381865afa158015613975573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139999190615520565b6139a3919061541f565b6139ad919061544c565b336000908152600c602052604090205490915081106139db57336000908152600c6020526040812055613a00565b336000908152600c6020526040812080548392906139fa90849061540c565b90915550505b505b60078301546001600160a01b031660009081526010602052604081208054839290613a2e90849061540c565b90915550506007830154613a4c906001600160a01b03163383614bfb565b604080518281526000602082015233917f4a94c2c356e29a6583071e731bdacf2ca56565ba5efebcff6936eb7923b517219101612001565b613aa860405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152601360205260408120905b8154811015610f575783828281548110613ade57613ade6153e0565b90600052602060002090600302016000015403613b4757818181548110613b0757613b076153e0565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505050610e6a565b80613b5181615473565b915050613ac2565b613b61614bc3565b6064811115613bb25760405162461bcd60e51b815260206004820152601a60248201527f496e76616c69642072657374616b652070657263656e746167650000000000006044820152606401610fcc565b336000908152600860205260408120805484908110613bd357613bd36153e0565b906000526020600020906005020190508060000154600003613c2c5760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b6044820152606401610fcc565b8060030154421015613c785760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b6044820152606401610fcc565b80546000613c8633866129d2565b9050613c928183615460565b915060006064613ca2868561541f565b613cac919061544c565b90506000613cba828561540c565b6000865560048601805460ff1916600117905590508015613da6578060126000828254613ce79190615460565b90915550506003548111613d15578060016002016000828254613d0a919061540c565b90915550613d1b9050565b60006003555b3360009081526013602090815260409182902082516060810184528a81529182018490526011549092820190613d519042615460565b90528154600180820184556000938452602093849020835160039093020191825582840151908201556040918201516002909101555182815233916000805160206155dd833981519152910160405180910390a25b8115613ecd573360009081526015602052604081205415613dd7575033600090815260156020526040902054613de5565b613de23360016122cc565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a0016040528085815260200142815260200183815260200160016000015442613e389190615460565b81526000602091820181905283546001808201865594825290829020835160059092020190815582820151938101939093556040808301516002850155606083015160038501556080909201516004909301805460ff1916931515939093179092555184815233917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d910160405180910390a2505b5050505050613ee960016000805160206155fd83398151915255565b5050565b3360009081526007602052604090205460ff16613f1c5760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b038116613f425760405162461bcd60e51b8152600401610fcc906154b4565b6001600160a01b0316600090815260156020526040812055565b3360009081526007602052604090205460ff16613f8b5760405162461bcd60e51b8152600401610fcc9061548c565b81600003613fe75760405162461bcd60e51b815260206004820152602360248201527f4c6f636b2074696d65206d7573742062652067726561746572207468616e207a60448201526265726f60e81b6064820152608401610fcc565b8060000361404d5760405162461bcd60e51b815260206004820152602d60248201527f50657263656e74616765207065722073746570206d757374206265206772656160448201526c746572207468616e207a65726f60981b6064820152608401610fcc565b61271061405a82826155c8565b156140b25760405162461bcd60e51b815260206004820152602260248201527f50657263656e74616765206d757374206469766964652031303025206576656e6044820152616c7960f01b6064820152608401610fcc565b60006140be838361544c565b905060006140cc828661544c565b6001600160a01b0387166000908152600a602052604081209192506140f19190614f30565b60015b828111614166576001600160a01b0387166000908152600a60205260409081902081518083019092529080614129848661541f565b81526020908101889052825460018181018555600094855293829020835160029092020190815591015191015561415f81615473565b90506140f4565b506040516001600160a01b038716907fde4b6ccc38b84f88129403b65a309f9b1c41d4c316bc2118d7614e449b9d4c4590600090a2505050505050565b600960205281600052604060002081815481106141bf57600080fd5b6000918252602090912060099091020180546001820154600283015460038401546004850154600586015460068701546007880154600890980154969950949750929591949093916001600160a01b03811691600160a01b90910460ff16908a565b6001600160a01b038216600090815260096020526040812080546060928392909185908110614252576142526153e0565b600091825260208083206007600990930201918201546001600160a01b0316808452600a9091526040832054919350918167ffffffffffffffff81111561429b5761429b61556e565b6040519080825280602002602001820160405280156142c4578160200160208202803683370190505b50905060008267ffffffffffffffff8111156142e2576142e261556e565b60405190808252806020026020018201604052801561430b578160200160208202803683370190505b50905060005b838110156143b8576001600160a01b0385166000908152600a60205260408120805483908110614343576143436153e0565b90600052602060002090600202019050806000015487600601546143679190615460565b848381518110614379576143796153e0565b602002602001018181525050806001015483838151811061439c5761439c6153e0565b6020908102919091010152506143b181615473565b9050614311565b50909890975095505050505050565b601360205281600052604060002081815481106143e357600080fd5b600091825260209091206003909102018054600182015460029092015490935090915083565b6001600160a01b0381166000908152601360209081526040808320805482518185028101850190935280835260609492939192909184015b82821015612c835783829060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505081526020019060010190614441565b3360009081526007602052604090205460ff166144c05760405162461bcd60e51b8152600401610fcc9061548c565b601155565b600081815481106144d557600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b3360009081526007602052604090205460ff166145275760405162461bcd60e51b8152600401610fcc9061548c565b601455565b614534614bc3565b336000908152600960205260408120805483908110614555576145556153e0565b9060005260206000209060090201905060006145713384610d38565b905081600401548110156145975760405162461bcd60e51b8152600401610fcc90615584565b60008260040154826145a9919061540c565b9050806000036145f75760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b6044820152606401610fcc565b8083600401546146079190615460565b836004018190555080601260008282546146219190615460565b90915550503360009081526013602052604090819020815160608101909252908061464f87620f4240615460565b8152602001838152602001601154426146689190615460565b90528154600180820184556000938452602093849020835160039093020191825582840151908201556040918201516002909101555182815233917f4e69fdc49495bcab2b4375781457ba16653a90eb4ffb6588351bdc39071433e29101612001565b3360009081526007602052604090205460ff166146fa5760405162461bcd60e51b8152600401610fcc9061548c565b81831061475e5760405162461bcd60e51b815260206004820152602c60248201527f496e76616c69642072616e67653a206d696e546f6b656e73206d75737420626560448201526b203c206d6178546f6b656e7360a01b6064820152608401610fcc565b6147688383614c50565b156147c05760405162461bcd60e51b815260206004820152602260248201527f52616e6765206f7665726c6170732077697468206578697374696e6720746965604482015261727360f01b6064820152608401610fcc565b60005b6000548110156148675783600082815481106147e1576147e16153e0565b9060005260206000209060030201600001541480156148235750826000828154811061480f5761480f6153e0565b906000526020600020906003020160010154145b1561485757816000828154811061483c5761483c6153e0565b90600052602060002090600302016002018190555050505050565b61486081615473565b90506147c3565b5060408051606081018252848152602081018481529181018381526000805460018101825590805291517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56360039093029283015591517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56482015590517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56590910155614910614cdf565b505050565b600080805b6001600160a01b03841660009081526008602052604090205481101561496657600061494685836129d2565b90506149528184615460565b9250508061495f90615473565b905061491a565b5092915050565b3360009081526007602052604090205460ff1661499c5760405162461bcd60e51b8152600401610fcc9061548c565b806000036149dd5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606401610fcc565b60086000836001600160a01b03166001600160a01b031681526020019081526020016000206040518060a001604052808381526020014281526020016001800154815260200160016000015442614a349190615460565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff19169215159290921790915554614aa5908290615460565b6003556040518181526001600160a01b038316907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d90602001611368565b3360009081526007602052604090205460ff16614b125760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b038116614b385760405162461bcd60e51b8152600401610fcc906154b4565b6001600160a01b03166000908152600f60205260409020805460ff19166001179055565b6040516001600160a01b0384811660248301528381166044830152606482018390526115cb9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050614e6e565b6000805160206155fd833981519152805460011901614bf557604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6040516001600160a01b0383811660248301526044820183905261491091859182169063a9059cbb90606401614b91565b60016000805160206155fd83398151915255565b614c48614edf565b611a0c614f28565b6000805b600054811015614cd55760008181548110614c7157614c716153e0565b9060005260206000209060030201600101548411158015614cb6575060008181548110614ca057614ca06153e0565b9060005260206000209060030201600001548310155b15614cc5576001915050610e6a565b614cce81615473565b9050614c54565b5060009392505050565b60005b6000548110156118b4576000614cf9826001615460565b90505b600054811015614e5d5760008181548110614d1957614d196153e0565b90600052602060002090600302016000015460008381548110614d3e57614d3e6153e0565b9060005260206000209060030201600001541115614e4b576000808381548110614d6a57614d6a6153e0565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905060008281548110614db657614db66153e0565b906000526020600020906003020160008481548110614dd757614dd76153e0565b90600052602060002090600302016000820154816000015560018201548160010155600282015481600201559050508060008381548110614e1a57614e1a6153e0565b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020155905050505b80614e5581615473565b915050614cfc565b50614e6781615473565b9050614ce2565b600080602060008451602086016000885af180614e91576040513d6000823e3d81fd5b50506000513d91508115614ea9578060011415614eb6565b6001600160a01b0384163b155b156115cb57604051635274afe760e01b81526001600160a01b0385166004820152602401610fcc565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16611a0c57604051631afcd79f60e31b815260040160405180910390fd5b614c2c614edf565b50805460008255600202906000526020600020908101906118b491905b80821115614f675760008082556001820155600201614f4d565b5090565b80356001600160a01b0381168114614f8257600080fd5b919050565b600060208284031215614f9957600080fd5b61231582614f6b565b60008060408385031215614fb557600080fd5b614fbe83614f6b565b946020939093013593505050565b81518152602080830151908201526040808301519082015260608101610e6a565b600060208284031215614fff57600080fd5b5035919050565b6000806020838503121561501957600080fd5b823567ffffffffffffffff8082111561503157600080fd5b818501915085601f83011261504557600080fd5b81358181111561505457600080fd5b86602060a08302850101111561506957600080fd5b60209290920196919550909350505050565b6000806020838503121561508e57600080fd5b823567ffffffffffffffff808211156150a657600080fd5b818501915085601f8301126150ba57600080fd5b8135818111156150c957600080fd5b8660208260051b850101111561506957600080fd5b600081518084526020808501945080840160005b8381101561510e578151875295820195908201906001016150f2565b509495945050505050565b60608152600061512c60608301866150de565b828103602084015261513e81866150de565b915050826040830152949350505050565b6000806040838503121561516257600080fd5b61516b83614f6b565b91506020830135801515811461518057600080fd5b809150509250929050565b6000806040838503121561519e57600080fd5b6151a783614f6b565b91506151b560208401614f6b565b90509250929050565b602080825282518282018190526000919060409081850190868401855b8281101561525f5781518051855286810151878601528581015186860152606080820151908601526080808201519086015260a0808201519086015260c0808201519086015260e0808201516001600160a01b03169086015261010080820151151590860152610120908101519085015261014090930192908501906001016151db565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b8281101561525f57815180518552868101518786015285810151868601526060808201519086015260809081015115159085015260a09093019290850190600101615289565b600080604083850312156152e257600080fd5b50508035926020909101359150565b60008060006060848603121561530657600080fd5b61530f84614f6b565b95602085013595506040909401359392505050565b60408152600061533760408301856150de565b828103602084015261534981856150de565b95945050505050565b6020808252825182820181905260009190848201906040850190845b818110156153a8576153958385518051825260208082015190830152604090810151910152565b928401926060929092019160010161536e565b50909695505050505050565b6000806000606084860312156153c957600080fd5b505081359360208301359350604090920135919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610e6a57610e6a6153f6565b8082028115828204841417610e6a57610e6a6153f6565b634e487b7160e01b600052601260045260246000fd5b60008261545b5761545b615436565b500490565b80820180821115610e6a57610e6a6153f6565b600060018201615485576154856153f6565b5060010190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b60208082526023908201527f416d6f756e74206d7573742062652067726561746572206d696e5374616b654c6040820152626f636b60e81b606082015260800190565b60006020828403121561553257600080fd5b5051919050565b6020808252818101527f496e73756666696369656e74207265776172647320696e2074686520706f6f6c604082015260600190565b634e487b7160e01b600052604160045260246000fd5b602080825260149082015273125b9d985b1a590818db185a5b48185b5bdd5b9d60621b604082015260600190565b634e487b7160e01b600052603160045260246000fd5b6000826155d7576155d7615436565b50069056fe106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f72419b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a26469706673582212202b6f6199c593a45a23592a8c432ee855fb599203e15918b5fd3fecb50030499664736f6c63430008140033
Deployed Bytecode
0x6080604052600436106103c35760003560e01c8063710ea0ce116101f2578063b8e7023d1161010d578063ce13d090116100a0578063d96134101161006f578063d961341014610cb8578063da40ef8014610cd8578063e4d06f9014610cf8578063ffecf51614610d1857600080fd5b8063ce13d09014610c38578063cfb866da14610c58578063d6c680eb14610c78578063d919302514610c9857600080fd5b8063bd84477d116100dc578063bd84477d14610b2d578063bed9757e14610ba2578063c606627214610bd0578063c7b530b014610c0b57600080fd5b8063b8e7023d14610aa0578063b90fba1914610ac0578063b92a349f14610ae0578063bd72169814610b0057600080fd5b8063853e0df2116101855780639562ee15116101545780639562ee1514610a2057806396ed7f8914610a40578063ac97b41714610a60578063b6c3dc4c14610a8057600080fd5b8063853e0df2146109aa5780638bdf67f2146109ca5780638da5cb5b146109ea57806392257cb514610a0a57600080fd5b80637bc221ac116101c15780637bc221ac146109405780637f79496c1461096057806380ca0ecf146109755780638129fc1c1461099557600080fd5b8063710ea0ce146108a65780637497211b146108c65780637a0c6dc0146108e65780637ba6f4581461091357600080fd5b806338a85ce2116102e2578063584b62a11161027557806367a74ddc1161024457806367a74ddc146108315780636ae21510146108515780636c3b0c53146108665780637065cb481461088657600080fd5b8063584b62a11461077a578063592d1dd1146107c4578063599ab2c4146107f15780635fecd9261461081157600080fd5b806343c7c011116102b157806343c7c011146106ef57806344c7d6ef1461070f57806351f6cf2f1461072f5780635339dcc11461076457600080fd5b806338a85ce21461065a5780633ba8396e146106705780633c92f98d146106a05780633f35e722146106cf57600080fd5b806316f0115b1161035a5780631d7a3361116103295780631d7a3361146105f257806322a26fc0146106125780632e1a7d4d14610625578063372500ab1461064557600080fd5b806316f0115b1461053b578063173825d91461059c5780631ada70a8146105bc5780631bf6ddae146105d257600080fd5b80630a84096a116103965780630a84096a146104ac5780630d046d11146104cc57806313c8e2de146104f957806316be9b2a1461051957600080fd5b806301374518146103c8578063022914a71461041b5780630519da321461045b578063092c76101461047f575b600080fd5b3480156103d457600080fd5b506103fe6103e3366004614f87565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561042757600080fd5b5061044b610436366004614f87565b60076020526000908152604090205460ff1681565b6040519015158152602001610412565b34801561046757600080fd5b5061047160115481565b604051908152602001610412565b34801561048b57600080fd5b5061047161049a366004614f87565b60106020526000908152604090205481565b3480156104b857600080fd5b506104716104c7366004614fa2565b610d38565b3480156104d857600080fd5b506104ec6104e7366004614fa2565b610e70565b6040516104129190614fcc565b34801561050557600080fd5b50610471610514366004614fed565b610fd5565b34801561052557600080fd5b50610539610534366004614fa2565b611086565b005b34801561054757600080fd5b5060015460025460035460045460055461056b94939291906001600160a01b031685565b6040805195865260208601949094529284019190915260608301526001600160a01b0316608082015260a001610412565b3480156105a857600080fd5b506105396105b7366004614f87565b6110f7565b3480156105c857600080fd5b50610471600d5481565b3480156105de57600080fd5b506105396105ed366004614fed565b6111ef565b3480156105fe57600080fd5b5061053961060d366004614f87565b611374565b610539610620366004615006565b61147d565b34801561063157600080fd5b50610539610640366004614fed565b6115d1565b34801561065157600080fd5b506105396118b7565b34801561066657600080fd5b50610471600e5481565b34801561067c57600080fd5b5061044b61068b366004614f87565b600f6020526000908152604090205460ff1681565b3480156106ac57600080fd5b506106c06106bb36600461507b565b611a0e565b60405161041293929190615119565b3480156106db57600080fd5b506105396106ea366004614fa2565b611bfe565b3480156106fb57600080fd5b5061053961070a366004614f87565b611c85565b34801561071b57600080fd5b5061053961072a366004614fed565b612023565b34801561073b57600080fd5b5061074f61074a366004614fa2565b61223f565b60408051928352602083019190915201610412565b34801561077057600080fd5b5061047160145481565b34801561078657600080fd5b5061079a610795366004614fa2565b61227b565b6040805195865260208601949094529284019190915260608301521515608082015260a001610412565b3480156107d057600080fd5b506104716107df366004614f87565b600c6020526000908152604090205481565b3480156107fd57600080fd5b5061047161080c36600461514f565b6122cc565b34801561081d57600080fd5b5061053961082c366004614f87565b61231c565b34801561083d57600080fd5b5061053961084c36600461518b565b612392565b34801561085d57600080fd5b506105396123ef565b34801561087257600080fd5b50610539610881366004614fa2565b6125c8565b34801561089257600080fd5b506105396108a1366004614f87565b612923565b3480156108b257600080fd5b506104716108c1366004614fa2565b6129d2565b3480156108d257600080fd5b506105396108e1366004614fed565b612a69565b3480156108f257600080fd5b50610906610901366004614f87565b612ba7565b60405161041291906151be565b34801561091f57600080fd5b5061093361092e366004614f87565b612c8e565b604051610412919061526c565b34801561094c57600080fd5b5061047161095b366004614f87565b612d29565b34801561096c57600080fd5b50610471612efc565b34801561098157600080fd5b50610471610990366004614fa2565b612f94565b3480156109a157600080fd5b506105396130a0565b3480156109b657600080fd5b506105396109c5366004614fed565b6135a1565b3480156109d657600080fd5b506105396109e5366004614fed565b61362e565b3480156109f657600080fd5b506006546103fe906001600160a01b031681565b348015610a1657600080fd5b5061047160125481565b348015610a2c57600080fd5b50610539610a3b366004614fed565b6136bd565b348015610a4c57600080fd5b50610539610a5b3660046152cf565b613721565b348015610a6c57600080fd5b50610539610a7b366004614fed565b6137a2565b348015610a8c57600080fd5b506104ec610a9b366004614fa2565b613a84565b348015610aac57600080fd5b50610539610abb3660046152cf565b613b59565b348015610acc57600080fd5b50610539610adb366004614f87565b613eed565b348015610aec57600080fd5b50610539610afb3660046152f1565b613f5c565b348015610b0c57600080fd5b50610471610b1b366004614f87565b60156020526000908152604090205481565b348015610b3957600080fd5b50610b4d610b48366004614fa2565b6141a3565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925260a086015260c08501526001600160a01b031660e0840152151561010083015261012082015261014001610412565b348015610bae57600080fd5b50610bc2610bbd366004614fa2565b614221565b604051610412929190615324565b348015610bdc57600080fd5b50610bf0610beb366004614fa2565b6143c7565b60408051938452602084019290925290820152606001610412565b348015610c1757600080fd5b50610c2b610c26366004614f87565b614409565b6040516104129190615352565b348015610c4457600080fd5b50610539610c53366004614fed565b614491565b348015610c6457600080fd5b50610bf0610c73366004614fed565b6144c5565b348015610c8457600080fd5b50610539610c93366004614fed565b6144f8565b348015610ca457600080fd5b50610539610cb3366004614fed565b61452c565b348015610cc457600080fd5b50610539610cd33660046153b4565b6146cb565b348015610ce457600080fd5b50610471610cf3366004614f87565b614915565b348015610d0457600080fd5b50610539610d13366004614fa2565b61496d565b348015610d2457600080fd5b50610539610d33366004614f87565b614ae3565b6001600160a01b0382166000908152600960205260408120805482919084908110610d6557610d656153e0565b906000526020600020906009020190506000816006015442610d87919061540c565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a6020526040902054811015610e63576001600160a01b0383166000908152600a60205260408120805483908110610de657610de66153e0565b6000918252602082206002909102018054600182015460088a015492945090929091606490610e1790600a9061541f565b610e21919061544c565b9050828810610e4e57612710610e37838361541f565b610e41919061544c565b610e4b9087615460565b95505b5050505080610e5c90615473565b9050610d9c565b5093505050505b92915050565b610e9460405180606001604052806000815260200160008152602001600081525090565b6001600160a01b038316600090815260136020526040812090610eba84620f4240615460565b905060005b8254811015610f575781838281548110610edb57610edb6153e0565b90600052602060002090600302016000015403610f4557828181548110610f0457610f046153e0565b906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820154815250509350505050610e6a565b80610f4f81615473565b915050610ebf565b5060405162461bcd60e51b815260206004820152604160248201527f57697468647261775374616b652077697468207468652073706563696669656460448201527f207374616b654964206e6f7420666f756e6420666f72207468697320757365726064820152601760f91b608482015260a4015b60405180910390fd5b6000805b60005481101561107d5760008181548110610ff657610ff66153e0565b906000526020600020906003020160000154831015801561103b575060008181548110611025576110256153e0565b9060005260206000209060030201600101548311155b1561106d5760008181548110611053576110536153e0565b906000526020600020906003020160020154915050919050565b61107681615473565b9050610fd9565b50600092915050565b3360009081526007602052604090205460ff166110b55760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b0382166110db5760405162461bcd60e51b8152600401610fcc906154b4565b6001600160a01b03909116600090815260156020526040902055565b3360009081526007602052604090205460ff166111265760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b03811660009081526007602052604090205460ff1661117d5760405162461bcd60e51b815260206004820152600c60248201526b2737ba1030b71037bbb732b960a11b6044820152606401610fcc565b336001600160a01b038216036111ce5760405162461bcd60e51b815260206004820152601660248201527521b0b73737ba103932b6b7bb32903cb7bab939b2b63360511b6044820152606401610fcc565b6001600160a01b03166000908152600760205260409020805460ff19169055565b600e546112018264e8d4a5100061541f565b1161121e5760405162461bcd60e51b8152600401610fcc906154dd565b600554611236906001600160a01b0316333084614b5c565b336000908152601560205260408120541561126157503360009081526015602052604090205461126f565b61126c3360006122cc565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a00160405280848152602001428152602001838152602001600160000154426112c29190615460565b815260006020918201819052835460018082018655948252828220845160059092020190815591830151938201939093556040820151600282015560608201516003808301919091556080909201516004909101805460ff19169115159190911790558054849290611335908490615460565b909155505060405182815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906020015b60405180910390a25050565b336000908152600f602052604090205460ff166113d35760405162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206973206e6f7420616e20617574686f72697a656420626f74006044820152606401610fcc565b6000805b6001600160a01b038316600090815260086020526040902054811015611467576001600160a01b0383166000908152600860205260408120805483908110611421576114216153e0565b906000526020600020906005020190508060000154836114419190615460565b600082556004909101805460ff19166001179055915061146081615473565b90506113d7565b5060035461147690829061540c565b6003555050565b336000908152600f602052604090205460ff166114dc5760405162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206973206e6f7420616e20617574686f72697a656420626f74006044820152606401610fcc565b8060005b818110156115cb57368484838181106114fb576114fb6153e0565b905060a00201905080602001356001600201546115189190615460565b6003556008600061152c6020840184614f87565b6001600160a01b0316815260208082019290925260409081016000908120825160a08101845285850135815285840135818601908152608080880135958301958652606097880135978301978852820184815283546001808201865594865296909420915160059096029091019485555184820155915160028401559251600383015591516004909101805460ff1916911515919091179055016114e0565b50505050565b6115d9614bc3565b33600090815260136020526040812080546116415760405162461bcd60e51b815260206004820152602260248201527f4e6f207374616b657320617661696c61626c6520666f72207769746864726177604482015261185b60f21b6064820152608401610fcc565b60005b815481101561185e576000828281548110611661576116616153e0565b906000526020600020906003020190508481600001540361184d5780600101546000036116e25760405162461bcd60e51b815260206004820152602960248201527f5374616b6520616c72656164792077697468647261776e206f7220646f6573206044820152681b9bdd08195e1a5cdd60ba1b6064820152608401610fcc565b80600201544210156117365760405162461bcd60e51b815260206004820152601e60248201527f5769746864726177205374616b65206973207374696c6c206c6f636b656400006044820152606401610fcc565b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa15801561177f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a39190615520565b905081600101548110156117c95760405162461bcd60e51b8152600401610fcc90615539565b816001015494506000826001018190555084601260008282546117ec919061540c565b9091555050600554611808906001600160a01b03163387614bfb565b604080518681526020810188905233917f933735aa8de6d7547d0126171b2f31b9c34dd00f3ecd4be85a0ba047db4fafef910160405180910390a2505050505061189d565b5061185781615473565b9050611644565b5060405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b6044820152606401610fcc565b6118b460016000805160206155fd83398151915255565b50565b6118bf614bc3565b6000805b33600090815260086020526040902054811015611940573360009081526008602052604081208054839081106118fb576118fb6153e0565b90600052602060002090600502019050600061191733846129d2565b90506119238185615460565b4260019093019290925550915061193981615473565b90506118c3565b50806000036119875760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b6044820152606401610fcc565b6004548111156119a95760405162461bcd60e51b8152600401610fcc90615539565b6004546119b790829061540c565b6004556005546119d1906001600160a01b03163383614bfb565b60405181815233906000805160206155dd8339815191529060200160405180910390a250611a0c60016000805160206155fd83398151915255565b565b6060806000838067ffffffffffffffff811115611a2d57611a2d61556e565b604051908082528060200260200182016040528015611a56578160200160208202803683370190505b5093508067ffffffffffffffff811115611a7257611a7261556e565b604051908082528060200260200182016040528015611a9b578160200160208202803683370190505b50925060005b81811015611bf5576000878783818110611abd57611abd6153e0565b9050602002016020810190611ad29190614f87565b6001600160a01b0381166000908152601060205260409020548751919250908190889085908110611b0557611b056153e0565b6020908102919091018101919091526001600160a01b038381166000818152600b90935260408084205490516302c68be360e31b81526004810192909252909116906316345f1890602401602060405180830381865afa158015611b6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b919190615520565b90506000670de0b6b3a7640000611ba8848461541f565b611bb2919061544c565b905080888681518110611bc757611bc76153e0565b6020908102919091010152611bdc8188615460565b9650505050508080611bed90615473565b915050611aa1565b50509250925092565b3360009081526007602052604090205460ff16611c2d5760405162461bcd60e51b8152600401610fcc9061548c565b611c416001600160a01b0383163383614bfb565b6040518181526001600160a01b0383169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a35050565b611c8d614bc3565b60008060005b33600090815260096020526040902054811015611dc657336000908152600960205260408120805483908110611ccb57611ccb6153e0565b6000918252602090912060099091020160078101549091506001600160a01b038681169116148015611d0957506007810154600160a01b900460ff16155b15611db5576000611d1a3384612f94565b90508160030154811015611d405760405162461bcd60e51b8152600401610fcc90615584565b6000826003015482611d52919061540c565b90508015611db257808360030154611d6a9190615460565b6003840155611d798187615460565b4260058501558354600385015491975011611da45760078301805460ff60a01b1916600160a01b1790555b84611dae81615473565b9550505b50505b50611dbf81615473565b9050611c93565b5081600003611e0d5760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b6044820152606401610fcc565b336000908152600c602052604090205415611f16576001600160a01b038381166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928692909116906316345f1890602401602060405180830381865afa158015611e89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ead9190615520565b611eb7919061541f565b611ec1919061544c565b336000908152600c60205260409020549091508110611eef57336000908152600c6020526040812055611f14565b336000908152600c602052604081208054839290611f0e90849061540c565b90915550505b505b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015611f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f819190615520565b905082811015611fa35760405162461bcd60e51b8152600401610fcc90615539565b6001600160a01b03841660009081526010602052604081208054859290611fcb90849061540c565b90915550611fe590506001600160a01b0385163385614bfb565b60405183815233906000805160206155dd833981519152906020015b60405180910390a25050506118b460016000805160206155fd83398151915255565b61202b614bc3565b33600090815260086020526040902054811061207f5760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b6044820152606401610fcc565b3360009081526008602052604081208054839081106120a0576120a06153e0565b6000918252602082206005909102018054909250906120bf33856129d2565b90506120cb8183615460565b9150816000036121125760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b6044820152606401610fcc565b826003015442101561215e5760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b6044820152606401610fcc565b600080845560048401805460ff1916600117905560128054849290612184908490615460565b909155505060035482116121b25781600160020160008282546121a7919061540c565b909155506121b89050565b60006003555b33600090815260136020908152604091829020825160608101845287815291820185905260115490928201906121ee9042615460565b90528154600180820184556000938452602093849020835160039093020191825582840151908201556040918201516002909101555183815233916000805160206155dd8339815191529101612001565b600a602052816000526040600020818154811061225b57600080fd5b600091825260209091206002909102018054600190910154909250905082565b6008602052816000526040600020818154811061229757600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919060ff1685565b6001600160a01b0382166000908152600c602052604081205481906122f090610fd5565b6002546122fd9190615460565b90508215612315576014546123129082615460565b90505b9392505050565b3360009081526007602052604090205460ff1661234b5760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b0381166123715760405162461bcd60e51b8152600401610fcc906154b4565b6001600160a01b03166000908152600f60205260409020805460ff19169055565b3360009081526007602052604090205460ff166123c15760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b039182166000908152600b6020526040902080546001600160a01b03191691909216179055565b6000805b336000908152600860205260409020548110156124705733600090815260086020526040812080548390811061242b5761242b6153e0565b90600052602060002090600502019050600061244733846129d2565b90506124538185615460565b4260019093019290925550915061246981615473565b90506123f3565b50600e5481116124bb5760405162461bcd60e51b8152602060048201526016602482015275139bdd08195b9bdd59da081d1bc818dbdb5c1bdd5b9960521b6044820152606401610fcc565b336000818152600860209081526040808320815160a0810183528681524281850152948452600c90925291829020549092918201906124f990610fd5565b6002546125069190615460565b81526020016001600001544261251c9190615460565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff1916921515929092179091555461258d908290615460565b60035560405181815233907f3afe5b60dee16617a8adbbd7d6c28f17a27efabb834872efa8e7ad5dafddf6f19060200160405180910390a250565b806000036126185760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610fcc565b6001600160a01b038083166000908152600b6020526040902054168061268c5760405162461bcd60e51b815260206004820152602360248201527f5072696365206f7261636c65206e6f742073657420666f72207468697320746f60448201526235b2b760e91b6064820152608401610fcc565b6126a16001600160a01b038416333085614b5c565b600060646126b0600a8561541f565b6126ba919061544c565b6001600160a01b038581166000818152600b60205260408082205490516302c68be360e31b8152600481019390935293945092670de0b6b3a76400009287929116906316345f1890602401602060405180830381865afa158015612722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127469190615520565b612750919061541f565b61275a919061544c565b9050600e54811161277d5760405162461bcd60e51b8152600401610fcc906154dd565b336000908152600c60205260408120805483929061279c908490615460565b90915550506001600160a01b038516600090815260106020526040812080548692906127c9908490615460565b909155505033600090815260096020908152604091829020825161014081018452878152918201859052600d5490928201906128059042615460565b81526000602080830182905260408084018390524260608086018290526080808701929092526001600160a01b038d811660a08089019190915260c080890188905260e09889018c90528a5460018082018d559b8952978790208a51600990990201978855898701519a88019a909a558885015160028801559188015160038701559187015160048601558601516005850155958501516006840155928401516007830180546101008701511515600160a01b026001600160a81b031990911692909716919091179590951790945561012090920151600890920191909155805186815291820184905233917f9ade76f4385de306666dfb21a52b27d52db0fde8ad0f515fa261f532cac60d21910160405180910390a25050505050565b3360009081526007602052604090205460ff166129525760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b03811660009081526007602052604090205460ff16156129ae5760405162461bcd60e51b815260206004820152601060248201526f20b63932b0b23c9030b71037bbb732b960811b6044820152606401610fcc565b6001600160a01b03166000908152600760205260409020805460ff19166001179055565b6001600160a01b03821660009081526008602052604081208054829190849081106129ff576129ff6153e0565b906000526020600020906005020190506000816001015442612a21919061540c565b90506000612710620151808385600201548660000154612a41919061541f565b612a4b919061541f565b612a55919061544c565b612a5f919061544c565b9695505050505050565b3360009081526007602052604090205460ff16612a985760405162461bcd60e51b8152600401610fcc9061548c565b6000548110612adf5760405162461bcd60e51b8152602060048201526013602482015272496e646578206f7574206f6620626f756e647360681b6044820152606401610fcc565b805b600054612af09060019061540c565b811015612b6d576000612b04826001615460565b81548110612b1457612b146153e0565b906000526020600020906003020160008281548110612b3557612b356153e0565b60009182526020909120825460039092020190815560018083015490820155600291820154910155612b6681615473565b9050612ae1565b506000805480612b7f57612b7f6155b2565b6000828152602081206003600019909301928302018181556001810182905560020155905550565b6001600160a01b0381166000908152600960209081526040808320805482518185028101850190935280835260609492939192909184015b82821015612c8357600084815260209081902060408051610140810182526009860290920180548352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a0840152600681015460c084015260078101546001600160a01b03811660e0850152600160a01b900460ff161515610100840152600801546101208301529083529092019101612bdf565b505050509050919050565b6001600160a01b0381166000908152600860209081526040808320805482518185028101850190935280835260609492939192909184015b82821015612c835760008481526020908190206040805160a081018252600586029092018054835260018082015484860152600282015492840192909252600381015460608401526004015460ff16151560808301529083529092019101612cc6565b6001600160a01b038116600090815260096020526040812054815b81811015612ef5576001600160a01b0384166000908152600960205260408120805483908110612d7657612d766153e0565b600091825260209182902060408051610140810182526009909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260078201546001600160a01b03811660e083015260ff600160a01b90910416151561010082018190526008909201546101208201529150612ee25760e0810180516001600160a01b039081166000908152600b602052604080822054935190516302c68be360e31b815290831660048201529092909116906316345f1890602401602060405180830381865afa158015612e73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e979190615520565b9050600082606001518360000151612eaf919061540c565b90506000670de0b6b3a7640000612ec6838561541f565b612ed0919061544c565b9050612edc8188615460565b96505050505b5080612eed81615473565b915050612d44565b5050919050565b6005546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612f49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f6d9190615520565b90506012548110612f8057600091505090565b80601254612f8e919061540c565b91505090565b6001600160a01b0382166000908152600960205260408120805482919084908110612fc157612fc16153e0565b906000526020600020906009020190506000816006015442612fe3919061540c565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a6020526040902054811015610e63576001600160a01b0383166000908152600a60205260408120805483908110613042576130426153e0565b60009182526020909120600290910201805460018201549192509081871061308c5787546127109061307590839061541f565b61307f919061544c565b6130899086615460565b94505b5050508061309990615473565b9050612ff8565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156130e65750825b905060008267ffffffffffffffff1660011480156131035750303b155b905081158015613111575080155b1561312f5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561315957845460ff60401b1916600160401b1785555b613161614c40565b600680546001600160a01b03199081167341970ce76b656030a79e7c1fa76fc4eb93980255178255600760209081527f1428bfef657344f5f7a0019d1554dccabe000be344bb83cdab918bd50f24b573805460ff1990811660019081179092556301499700600d81905567de0b6b3a76400000600e556005805490951673833589fcd6edb6e08f4c7c32d4f71b54bda02913178555825560216002908155604080516060808201835268bdbc41e0348b300000825269021e0c0013070adc000082880190815282840187815260008054808a018255818052945160039586027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5638181019290925593517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5648086019190915592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565948501558651808601885269021e19e0c9bab2400000815269043c25e0dcc1bd1c0000818d01908152818901998a528354808d01855584805291519188028084019290925551818501559751978401979097558551808501875269043c33c1937564800000815269065a3fc1a67c6f5c0000818c019081528188018781528354808d0185558480529251928802808b019390935590518285015551908401558551808501875269065a4da25d3016c00000815269087859a27037219c0000818c0190815260048289019081528354808d0185558480529251928802808b0193909355905182850155519084015585518085018752690878678326eac90000008152690cb48d6403ac861c0000818c019081528188019c8d528254808c0184558380529151918702808a019290925551818401559a519a83019a909a5584518084018652690cb49b44ba602d80000081526910f0c1259721ea9c0000818b019081528187019c8d528b54808b018d558c805291519186028089019290925551818301559a519a82019a909a55835180830185526910f0cf064dd592000000815269152cf4e72a974f1c0000818a0190815260088287019081528b54808b018d558c80529251928602808901939093559051828d015551908201558351918201845269152d02c7e14af68000008252600019828901908152600a94830194855289548089018b558a805292519284029586019290925590519884019890985590519190960155600f9092527f77c9ddf83be31065a9eb7ed19d93a8a4db24cad8351f41cc546083ac9e9d8c7f8054831682179055737c40f272570fdf9549d6f67493ac250a1db52f279092527f1b209462f90614903451721396f08356b5037572bebcd67a02efc98f03bec9d1805490911690911790556201fa40601155601455831561359a57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b3360009081526007602052604090205460ff166135d05760405162461bcd60e51b8152600401610fcc9061548c565b6005546135e7906001600160a01b03163383614bfb565b6005546040518281526001600160a01b039091169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a350565b3360009081526007602052604090205460ff1661365d5760405162461bcd60e51b8152600401610fcc9061548c565b600554613675906001600160a01b0316333084614b5c565b600454613683908290615460565b6004556040518181527f4e9221f2cca6ca0397acc6004ea0b716798254f5abcf53924fab34f0373e5d4e906020015b60405180910390a150565b3360009081526007602052604090205460ff166136ec5760405162461bcd60e51b8152600401610fcc9061548c565b600e8190556040518181527fe5dadb089824c750e4e7a2e98bfbe130f1a09834769e81339639fbe18606859b906020016136b2565b3360009081526007602052604090205460ff166137505760405162461bcd60e51b8152600401610fcc9061548c565b61375d826201518061541f565b600155600281905560408051838152602081018390527f7fa9647ec1cc14e3822b46d05a2b9d4e019bde8875c0088c46b6503d71bf1722910160405180910390a15050565b6137aa614bc3565b3360009081526009602052604081208054839081106137cb576137cb6153e0565b600091825260209091206009909102016007810154909150600160a01b900460ff161561382e5760405162461bcd60e51b81526020600482015260116024820152705374616b6520697320436f6d706c65746560781b6044820152606401610fcc565b600061383a3384612f94565b905081600301548110156138605760405162461bcd60e51b8152600401610fcc90615584565b6000826003015482613872919061540c565b9050806000036138c05760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b6044820152606401610fcc565b8083600301546138d09190615460565b600384018190558354116138f45760078301805460ff60a01b1916600160a01b1790555b336000908152600c602052604090205415613a025760078301546001600160a01b039081166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928592909116906316345f1890602401602060405180830381865afa158015613975573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139999190615520565b6139a3919061541f565b6139ad919061544c565b336000908152600c602052604090205490915081106139db57336000908152600c6020526040812055613a00565b336000908152600c6020526040812080548392906139fa90849061540c565b90915550505b505b60078301546001600160a01b031660009081526010602052604081208054839290613a2e90849061540c565b90915550506007830154613a4c906001600160a01b03163383614bfb565b604080518281526000602082015233917f4a94c2c356e29a6583071e731bdacf2ca56565ba5efebcff6936eb7923b517219101612001565b613aa860405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152601360205260408120905b8154811015610f575783828281548110613ade57613ade6153e0565b90600052602060002090600302016000015403613b4757818181548110613b0757613b076153e0565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505050610e6a565b80613b5181615473565b915050613ac2565b613b61614bc3565b6064811115613bb25760405162461bcd60e51b815260206004820152601a60248201527f496e76616c69642072657374616b652070657263656e746167650000000000006044820152606401610fcc565b336000908152600860205260408120805484908110613bd357613bd36153e0565b906000526020600020906005020190508060000154600003613c2c5760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b6044820152606401610fcc565b8060030154421015613c785760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b6044820152606401610fcc565b80546000613c8633866129d2565b9050613c928183615460565b915060006064613ca2868561541f565b613cac919061544c565b90506000613cba828561540c565b6000865560048601805460ff1916600117905590508015613da6578060126000828254613ce79190615460565b90915550506003548111613d15578060016002016000828254613d0a919061540c565b90915550613d1b9050565b60006003555b3360009081526013602090815260409182902082516060810184528a81529182018490526011549092820190613d519042615460565b90528154600180820184556000938452602093849020835160039093020191825582840151908201556040918201516002909101555182815233916000805160206155dd833981519152910160405180910390a25b8115613ecd573360009081526015602052604081205415613dd7575033600090815260156020526040902054613de5565b613de23360016122cc565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a0016040528085815260200142815260200183815260200160016000015442613e389190615460565b81526000602091820181905283546001808201865594825290829020835160059092020190815582820151938101939093556040808301516002850155606083015160038501556080909201516004909301805460ff1916931515939093179092555184815233917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d910160405180910390a2505b5050505050613ee960016000805160206155fd83398151915255565b5050565b3360009081526007602052604090205460ff16613f1c5760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b038116613f425760405162461bcd60e51b8152600401610fcc906154b4565b6001600160a01b0316600090815260156020526040812055565b3360009081526007602052604090205460ff16613f8b5760405162461bcd60e51b8152600401610fcc9061548c565b81600003613fe75760405162461bcd60e51b815260206004820152602360248201527f4c6f636b2074696d65206d7573742062652067726561746572207468616e207a60448201526265726f60e81b6064820152608401610fcc565b8060000361404d5760405162461bcd60e51b815260206004820152602d60248201527f50657263656e74616765207065722073746570206d757374206265206772656160448201526c746572207468616e207a65726f60981b6064820152608401610fcc565b61271061405a82826155c8565b156140b25760405162461bcd60e51b815260206004820152602260248201527f50657263656e74616765206d757374206469766964652031303025206576656e6044820152616c7960f01b6064820152608401610fcc565b60006140be838361544c565b905060006140cc828661544c565b6001600160a01b0387166000908152600a602052604081209192506140f19190614f30565b60015b828111614166576001600160a01b0387166000908152600a60205260409081902081518083019092529080614129848661541f565b81526020908101889052825460018181018555600094855293829020835160029092020190815591015191015561415f81615473565b90506140f4565b506040516001600160a01b038716907fde4b6ccc38b84f88129403b65a309f9b1c41d4c316bc2118d7614e449b9d4c4590600090a2505050505050565b600960205281600052604060002081815481106141bf57600080fd5b6000918252602090912060099091020180546001820154600283015460038401546004850154600586015460068701546007880154600890980154969950949750929591949093916001600160a01b03811691600160a01b90910460ff16908a565b6001600160a01b038216600090815260096020526040812080546060928392909185908110614252576142526153e0565b600091825260208083206007600990930201918201546001600160a01b0316808452600a9091526040832054919350918167ffffffffffffffff81111561429b5761429b61556e565b6040519080825280602002602001820160405280156142c4578160200160208202803683370190505b50905060008267ffffffffffffffff8111156142e2576142e261556e565b60405190808252806020026020018201604052801561430b578160200160208202803683370190505b50905060005b838110156143b8576001600160a01b0385166000908152600a60205260408120805483908110614343576143436153e0565b90600052602060002090600202019050806000015487600601546143679190615460565b848381518110614379576143796153e0565b602002602001018181525050806001015483838151811061439c5761439c6153e0565b6020908102919091010152506143b181615473565b9050614311565b50909890975095505050505050565b601360205281600052604060002081815481106143e357600080fd5b600091825260209091206003909102018054600182015460029092015490935090915083565b6001600160a01b0381166000908152601360209081526040808320805482518185028101850190935280835260609492939192909184015b82821015612c835783829060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505081526020019060010190614441565b3360009081526007602052604090205460ff166144c05760405162461bcd60e51b8152600401610fcc9061548c565b601155565b600081815481106144d557600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b3360009081526007602052604090205460ff166145275760405162461bcd60e51b8152600401610fcc9061548c565b601455565b614534614bc3565b336000908152600960205260408120805483908110614555576145556153e0565b9060005260206000209060090201905060006145713384610d38565b905081600401548110156145975760405162461bcd60e51b8152600401610fcc90615584565b60008260040154826145a9919061540c565b9050806000036145f75760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b6044820152606401610fcc565b8083600401546146079190615460565b836004018190555080601260008282546146219190615460565b90915550503360009081526013602052604090819020815160608101909252908061464f87620f4240615460565b8152602001838152602001601154426146689190615460565b90528154600180820184556000938452602093849020835160039093020191825582840151908201556040918201516002909101555182815233917f4e69fdc49495bcab2b4375781457ba16653a90eb4ffb6588351bdc39071433e29101612001565b3360009081526007602052604090205460ff166146fa5760405162461bcd60e51b8152600401610fcc9061548c565b81831061475e5760405162461bcd60e51b815260206004820152602c60248201527f496e76616c69642072616e67653a206d696e546f6b656e73206d75737420626560448201526b203c206d6178546f6b656e7360a01b6064820152608401610fcc565b6147688383614c50565b156147c05760405162461bcd60e51b815260206004820152602260248201527f52616e6765206f7665726c6170732077697468206578697374696e6720746965604482015261727360f01b6064820152608401610fcc565b60005b6000548110156148675783600082815481106147e1576147e16153e0565b9060005260206000209060030201600001541480156148235750826000828154811061480f5761480f6153e0565b906000526020600020906003020160010154145b1561485757816000828154811061483c5761483c6153e0565b90600052602060002090600302016002018190555050505050565b61486081615473565b90506147c3565b5060408051606081018252848152602081018481529181018381526000805460018101825590805291517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56360039093029283015591517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56482015590517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56590910155614910614cdf565b505050565b600080805b6001600160a01b03841660009081526008602052604090205481101561496657600061494685836129d2565b90506149528184615460565b9250508061495f90615473565b905061491a565b5092915050565b3360009081526007602052604090205460ff1661499c5760405162461bcd60e51b8152600401610fcc9061548c565b806000036149dd5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606401610fcc565b60086000836001600160a01b03166001600160a01b031681526020019081526020016000206040518060a001604052808381526020014281526020016001800154815260200160016000015442614a349190615460565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff19169215159290921790915554614aa5908290615460565b6003556040518181526001600160a01b038316907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d90602001611368565b3360009081526007602052604090205460ff16614b125760405162461bcd60e51b8152600401610fcc9061548c565b6001600160a01b038116614b385760405162461bcd60e51b8152600401610fcc906154b4565b6001600160a01b03166000908152600f60205260409020805460ff19166001179055565b6040516001600160a01b0384811660248301528381166044830152606482018390526115cb9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050614e6e565b6000805160206155fd833981519152805460011901614bf557604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6040516001600160a01b0383811660248301526044820183905261491091859182169063a9059cbb90606401614b91565b60016000805160206155fd83398151915255565b614c48614edf565b611a0c614f28565b6000805b600054811015614cd55760008181548110614c7157614c716153e0565b9060005260206000209060030201600101548411158015614cb6575060008181548110614ca057614ca06153e0565b9060005260206000209060030201600001548310155b15614cc5576001915050610e6a565b614cce81615473565b9050614c54565b5060009392505050565b60005b6000548110156118b4576000614cf9826001615460565b90505b600054811015614e5d5760008181548110614d1957614d196153e0565b90600052602060002090600302016000015460008381548110614d3e57614d3e6153e0565b9060005260206000209060030201600001541115614e4b576000808381548110614d6a57614d6a6153e0565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905060008281548110614db657614db66153e0565b906000526020600020906003020160008481548110614dd757614dd76153e0565b90600052602060002090600302016000820154816000015560018201548160010155600282015481600201559050508060008381548110614e1a57614e1a6153e0565b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020155905050505b80614e5581615473565b915050614cfc565b50614e6781615473565b9050614ce2565b600080602060008451602086016000885af180614e91576040513d6000823e3d81fd5b50506000513d91508115614ea9578060011415614eb6565b6001600160a01b0384163b155b156115cb57604051635274afe760e01b81526001600160a01b0385166004820152602401610fcc565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16611a0c57604051631afcd79f60e31b815260040160405180910390fd5b614c2c614edf565b50805460008255600202906000526020600020908101906118b491905b80821115614f675760008082556001820155600201614f4d565b5090565b80356001600160a01b0381168114614f8257600080fd5b919050565b600060208284031215614f9957600080fd5b61231582614f6b565b60008060408385031215614fb557600080fd5b614fbe83614f6b565b946020939093013593505050565b81518152602080830151908201526040808301519082015260608101610e6a565b600060208284031215614fff57600080fd5b5035919050565b6000806020838503121561501957600080fd5b823567ffffffffffffffff8082111561503157600080fd5b818501915085601f83011261504557600080fd5b81358181111561505457600080fd5b86602060a08302850101111561506957600080fd5b60209290920196919550909350505050565b6000806020838503121561508e57600080fd5b823567ffffffffffffffff808211156150a657600080fd5b818501915085601f8301126150ba57600080fd5b8135818111156150c957600080fd5b8660208260051b850101111561506957600080fd5b600081518084526020808501945080840160005b8381101561510e578151875295820195908201906001016150f2565b509495945050505050565b60608152600061512c60608301866150de565b828103602084015261513e81866150de565b915050826040830152949350505050565b6000806040838503121561516257600080fd5b61516b83614f6b565b91506020830135801515811461518057600080fd5b809150509250929050565b6000806040838503121561519e57600080fd5b6151a783614f6b565b91506151b560208401614f6b565b90509250929050565b602080825282518282018190526000919060409081850190868401855b8281101561525f5781518051855286810151878601528581015186860152606080820151908601526080808201519086015260a0808201519086015260c0808201519086015260e0808201516001600160a01b03169086015261010080820151151590860152610120908101519085015261014090930192908501906001016151db565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b8281101561525f57815180518552868101518786015285810151868601526060808201519086015260809081015115159085015260a09093019290850190600101615289565b600080604083850312156152e257600080fd5b50508035926020909101359150565b60008060006060848603121561530657600080fd5b61530f84614f6b565b95602085013595506040909401359392505050565b60408152600061533760408301856150de565b828103602084015261534981856150de565b95945050505050565b6020808252825182820181905260009190848201906040850190845b818110156153a8576153958385518051825260208082015190830152604090810151910152565b928401926060929092019160010161536e565b50909695505050505050565b6000806000606084860312156153c957600080fd5b505081359360208301359350604090920135919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610e6a57610e6a6153f6565b8082028115828204841417610e6a57610e6a6153f6565b634e487b7160e01b600052601260045260246000fd5b60008261545b5761545b615436565b500490565b80820180821115610e6a57610e6a6153f6565b600060018201615485576154856153f6565b5060010190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b60208082526023908201527f416d6f756e74206d7573742062652067726561746572206d696e5374616b654c6040820152626f636b60e81b606082015260800190565b60006020828403121561553257600080fd5b5051919050565b6020808252818101527f496e73756666696369656e74207265776172647320696e2074686520706f6f6c604082015260600190565b634e487b7160e01b600052604160045260246000fd5b602080825260149082015273125b9d985b1a590818db185a5b48185b5bdd5b9d60621b604082015260600190565b634e487b7160e01b600052603160045260246000fd5b6000826155d7576155d7615436565b50069056fe106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f72419b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a26469706673582212202b6f6199c593a45a23592a8c432ee855fb599203e15918b5fd3fecb50030499664736f6c63430008140033
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.