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; if (timeElapsed >= timeTier) { unlockedAmount = unlockedAmount + ((vesting.bonus * 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; IERC20(vesting.token).safeTransfer(msg.sender, bonusToClaim); 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."); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at, * consider using {ReentrancyGuardTransient} instead. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard struct ReentrancyGuardStorage { uint256 _status; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) { assembly { $.slot := ReentrancyGuardStorageLocation } } /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); $._status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // On the first call to nonReentrant, _status will be NOT_ENTERED if ($._status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail $._status = ENTERED; } function _nonReentrantAfter() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) $._status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); return $._status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC165} from "./IERC165.sol"; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. * * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC-20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"bonus","type":"uint256"}],"name":"BonusClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CompoundRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MinStakeLockUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lockupPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dailyRewardRate","type":"uint256"}],"name":"PoolUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"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":"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"}],"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
608060405234801561001057600080fd5b50615385806100206000396000f3fe6080604052600436106103ad5760003560e01c8063710ea0ce116101e7578063b6c3dc4c1161010d578063ce13d090116100a0578063d96134101161006f578063d961341014610c6a578063da40ef8014610c8a578063e4d06f9014610caa578063ffecf51614610cca57600080fd5b8063ce13d09014610bea578063cfb866da14610c0a578063d6c680eb14610c2a578063d919302514610c4a57600080fd5b8063bd721698116100dc578063bd72169814610adf578063bd84477d14610b0c578063bed9757e14610b81578063c606627214610baf57600080fd5b8063b6c3dc4c14610a3d578063b8e7023d14610a7f578063b90fba1914610a9f578063b92a349f14610abf57600080fd5b80638129fc1c1161018557806392257cb51161015457806392257cb5146109c75780639562ee15146109dd57806396ed7f89146109fd578063ac97b41714610a1d57600080fd5b80638129fc1c14610952578063853e0df2146109675780638bdf67f2146109875780638da5cb5b146109a757600080fd5b80637ba6f458116101c15780637ba6f458146108d05780637bc221ac146108fd5780637f79496c1461091d57806380ca0ecf1461093257600080fd5b8063710ea0ce146108635780637497211b146108835780637a0c6dc0146108a357600080fd5b806338a85ce2116102d7578063584b62a11161026a57806367a74ddc1161023957806367a74ddc146107ee5780636ae215101461080e5780636c3b0c53146108235780637065cb481461084357600080fd5b8063584b62a114610737578063592d1dd114610781578063599ab2c4146107ae5780635fecd926146107ce57600080fd5b806343c7c011116102a657806343c7c011146106ac57806344c7d6ef146106cc57806351f6cf2f146106ec5780635339dcc11461072157600080fd5b806338a85ce2146106175780633ba8396e1461062d5780633c92f98d1461065d5780633f35e7221461068c57600080fd5b806316f0115b1161034f5780631d7a33611161031e5780631d7a3361146105af57806322a26fc0146105cf5780632e1a7d4d146105e2578063372500ab1461060257600080fd5b806316f0115b146104f8578063173825d9146105595780631ada70a8146105795780631bf6ddae1461058f57600080fd5b8063092c76101161038b578063092c7610146104695780630a84096a1461049657806313c8e2de146104b657806316be9b2a146104d657600080fd5b806301374518146103b2578063022914a7146104055780630519da3214610445575b600080fd5b3480156103be57600080fd5b506103e86103cd366004614d3d565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561041157600080fd5b50610435610420366004614d3d565b60076020526000908152604090205460ff1681565b60405190151581526020016103fc565b34801561045157600080fd5b5061045b60115481565b6040519081526020016103fc565b34801561047557600080fd5b5061045b610484366004614d3d565b60106020526000908152604090205481565b3480156104a257600080fd5b5061045b6104b1366004614d58565b610cea565b3480156104c257600080fd5b5061045b6104d1366004614d82565b610e05565b3480156104e257600080fd5b506104f66104f1366004614d58565b610eb6565b005b34801561050457600080fd5b5060015460025460035460045460055461052894939291906001600160a01b031685565b6040805195865260208601949094529284019190915260608301526001600160a01b0316608082015260a0016103fc565b34801561056557600080fd5b506104f6610574366004614d3d565b610f30565b34801561058557600080fd5b5061045b600d5481565b34801561059b57600080fd5b506104f66105aa366004614d82565b611028565b3480156105bb57600080fd5b506104f66105ca366004614d3d565b6111ad565b6104f66105dd366004614d9b565b6112b6565b3480156105ee57600080fd5b506104f66105fd366004614d82565b61140a565b34801561060e57600080fd5b506104f66116f0565b34801561062357600080fd5b5061045b600e5481565b34801561063957600080fd5b50610435610648366004614d3d565b600f6020526000908152604090205460ff1681565b34801561066957600080fd5b5061067d610678366004614e10565b611847565b6040516103fc93929190614eae565b34801561069857600080fd5b506104f66106a7366004614d58565b611a37565b3480156106b857600080fd5b506104f66106c7366004614d3d565b611abe565b3480156106d857600080fd5b506104f66106e7366004614d82565b611e5c565b3480156106f857600080fd5b5061070c610707366004614d58565b612078565b604080519283526020830191909152016103fc565b34801561072d57600080fd5b5061045b60145481565b34801561074357600080fd5b50610757610752366004614d58565b6120b4565b6040805195865260208601949094529284019190915260608301521515608082015260a0016103fc565b34801561078d57600080fd5b5061045b61079c366004614d3d565b600c6020526000908152604090205481565b3480156107ba57600080fd5b5061045b6107c9366004614ee4565b612105565b3480156107da57600080fd5b506104f66107e9366004614d3d565b612155565b3480156107fa57600080fd5b506104f6610809366004614f20565b6121cb565b34801561081a57600080fd5b506104f6612228565b34801561082f57600080fd5b506104f661083e366004614d58565b612401565b34801561084f57600080fd5b506104f661085e366004614d3d565b61275c565b34801561086f57600080fd5b5061045b61087e366004614d58565b61280b565b34801561088f57600080fd5b506104f661089e366004614d82565b6128a2565b3480156108af57600080fd5b506108c36108be366004614d3d565b6129e0565b6040516103fc9190614f53565b3480156108dc57600080fd5b506108f06108eb366004614d3d565b612ac7565b6040516103fc9190615001565b34801561090957600080fd5b5061045b610918366004614d3d565b612b62565b34801561092957600080fd5b5061045b612d35565b34801561093e57600080fd5b5061045b61094d366004614d58565b612dcd565b34801561095e57600080fd5b506104f6612ed9565b34801561097357600080fd5b506104f6610982366004614d82565b6133da565b34801561099357600080fd5b506104f66109a2366004614d82565b613467565b3480156109b357600080fd5b506006546103e8906001600160a01b031681565b3480156109d357600080fd5b5061045b60125481565b3480156109e957600080fd5b506104f66109f8366004614d82565b6134f6565b348015610a0957600080fd5b506104f6610a18366004615064565b61355a565b348015610a2957600080fd5b506104f6610a38366004614d82565b6135db565b348015610a4957600080fd5b50610a5d610a58366004614d58565b6138bd565b60408051825181526020808401519082015291810151908201526060016103fc565b348015610a8b57600080fd5b506104f6610a9a366004615064565b613a0b565b348015610aab57600080fd5b506104f6610aba366004614d3d565b613d9f565b348015610acb57600080fd5b506104f6610ada366004615086565b613e0e565b348015610aeb57600080fd5b5061045b610afa366004614d3d565b60156020526000908152604090205481565b348015610b1857600080fd5b50610b2c610b27366004614d58565b614055565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925260a086015260c08501526001600160a01b031660e08401521515610100830152610120820152610140016103fc565b348015610b8d57600080fd5b50610ba1610b9c366004614d58565b6140d3565b6040516103fc9291906150b9565b348015610bbb57600080fd5b50610bcf610bca366004614d58565b614279565b604080519384526020840192909252908201526060016103fc565b348015610bf657600080fd5b506104f6610c05366004614d82565b6142bb565b348015610c1657600080fd5b50610bcf610c25366004614d82565b6142ef565b348015610c3657600080fd5b506104f6610c45366004614d82565b614322565b348015610c5657600080fd5b506104f6610c65366004614d82565b614356565b348015610c7657600080fd5b506104f6610c853660046150e7565b614481565b348015610c9657600080fd5b5061045b610ca5366004614d3d565b6146cb565b348015610cb657600080fd5b506104f6610cc5366004614d58565b614723565b348015610cd657600080fd5b506104f6610ce5366004614d3d565b614899565b6001600160a01b0382166000908152600960205260408120805482919084908110610d1757610d17615113565b906000526020600020906009020190506000816006015442610d39919061513f565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a6020526040902054811015610df8576001600160a01b0383166000908152600a60205260408120805483908110610d9857610d98615113565b600091825260209091206002909102018054600182015491925090818710610de457612710818960010154610dcd9190615152565b610dd7919061517f565b610de19086615193565b94505b50505080610df1906151a6565b9050610d4e565b5093505050505b92915050565b6000805b600054811015610ead5760008181548110610e2657610e26615113565b9060005260206000209060030201600001548310158015610e6b575060008181548110610e5557610e55615113565b9060005260206000209060030201600101548311155b15610e9d5760008181548110610e8357610e83615113565b906000526020600020906003020160020154915050919050565b610ea6816151a6565b9050610e09565b50600092915050565b3360009081526007602052604090205460ff16610eee5760405162461bcd60e51b8152600401610ee5906151bf565b60405180910390fd5b6001600160a01b038216610f145760405162461bcd60e51b8152600401610ee5906151e7565b6001600160a01b03909116600090815260156020526040902055565b3360009081526007602052604090205460ff16610f5f5760405162461bcd60e51b8152600401610ee5906151bf565b6001600160a01b03811660009081526007602052604090205460ff16610fb65760405162461bcd60e51b815260206004820152600c60248201526b2737ba1030b71037bbb732b960a11b6044820152606401610ee5565b336001600160a01b038216036110075760405162461bcd60e51b815260206004820152601660248201527521b0b73737ba103932b6b7bb32903cb7bab939b2b63360511b6044820152606401610ee5565b6001600160a01b03166000908152600760205260409020805460ff19169055565b600e5461103a8264e8d4a51000615152565b116110575760405162461bcd60e51b8152600401610ee590615210565b60055461106f906001600160a01b0316333084614912565b336000908152601560205260408120541561109a5750336000908152601560205260409020546110a8565b6110a5336000612105565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a00160405280848152602001428152602001838152602001600160000154426110fb9190615193565b815260006020918201819052835460018082018655948252828220845160059092020190815591830151938201939093556040820151600282015560608201516003808301919091556080909201516004909101805460ff1916911515919091179055805484929061116e908490615193565b909155505060405182815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906020015b60405180910390a25050565b336000908152600f602052604090205460ff1661120c5760405162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206973206e6f7420616e20617574686f72697a656420626f74006044820152606401610ee5565b6000805b6001600160a01b0383166000908152600860205260409020548110156112a0576001600160a01b038316600090815260086020526040812080548390811061125a5761125a615113565b9060005260206000209060050201905080600001548361127a9190615193565b600082556004909101805460ff191660011790559150611299816151a6565b9050611210565b506003546112af90829061513f565b6003555050565b336000908152600f602052604090205460ff166113155760405162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206973206e6f7420616e20617574686f72697a656420626f74006044820152606401610ee5565b8060005b81811015611404573684848381811061133457611334615113565b905060a00201905080602001356001600201546113519190615193565b600355600860006113656020840184614d3d565b6001600160a01b0316815260208082019290925260409081016000908120825160a08101845285850135815285840135818601908152608080880135958301958652606097880135978301978852820184815283546001808201865594865296909420915160059096029091019485555184820155915160028401559251600383015591516004909101805460ff191691151591909117905501611319565b50505050565b611412614979565b336000908152601360205260408120805461147a5760405162461bcd60e51b815260206004820152602260248201527f4e6f207374616b657320617661696c61626c6520666f72207769746864726177604482015261185b60f21b6064820152608401610ee5565b60005b815481101561169757600082828154811061149a5761149a615113565b906000526020600020906003020190508481600001540361168657806001015460000361151b5760405162461bcd60e51b815260206004820152602960248201527f5374616b6520616c72656164792077697468647261776e206f7220646f6573206044820152681b9bdd08195e1a5cdd60ba1b6064820152608401610ee5565b806002015442101561156f5760405162461bcd60e51b815260206004820152601e60248201527f5769746864726177205374616b65206973207374696c6c206c6f636b656400006044820152606401610ee5565b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156115b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115dc9190615253565b905081600101548110156116025760405162461bcd60e51b8152600401610ee59061526c565b81600101549450600082600101819055508460126000828254611625919061513f565b9091555050600554611641906001600160a01b031633876149b1565b604080518681526020810188905233917f933735aa8de6d7547d0126171b2f31b9c34dd00f3ecd4be85a0ba047db4fafef910160405180910390a250505050506116d6565b50611690816151a6565b905061147d565b5060405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b6044820152606401610ee5565b6116ed600160008051602061533083398151915255565b50565b6116f8614979565b6000805b336000908152600860205260409020548110156117795733600090815260086020526040812080548390811061173457611734615113565b906000526020600020906005020190506000611750338461280b565b905061175c8185615193565b42600190930192909255509150611772816151a6565b90506116fc565b50806000036117c05760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b6044820152606401610ee5565b6004548111156117e25760405162461bcd60e51b8152600401610ee59061526c565b6004546117f090829061513f565b60045560055461180a906001600160a01b031633836149b1565b60405181815233906000805160206153108339815191529060200160405180910390a250611845600160008051602061533083398151915255565b565b6060806000838067ffffffffffffffff811115611866576118666152a1565b60405190808252806020026020018201604052801561188f578160200160208202803683370190505b5093508067ffffffffffffffff8111156118ab576118ab6152a1565b6040519080825280602002602001820160405280156118d4578160200160208202803683370190505b50925060005b81811015611a2e5760008787838181106118f6576118f6615113565b905060200201602081019061190b9190614d3d565b6001600160a01b038116600090815260106020526040902054875191925090819088908590811061193e5761193e615113565b6020908102919091018101919091526001600160a01b038381166000818152600b90935260408084205490516302c68be360e31b81526004810192909252909116906316345f1890602401602060405180830381865afa1580156119a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ca9190615253565b90506000670de0b6b3a76400006119e18484615152565b6119eb919061517f565b905080888681518110611a0057611a00615113565b6020908102919091010152611a158188615193565b9650505050508080611a26906151a6565b9150506118da565b50509250925092565b3360009081526007602052604090205460ff16611a665760405162461bcd60e51b8152600401610ee5906151bf565b611a7a6001600160a01b03831633836149b1565b6040518181526001600160a01b0383169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a35050565b611ac6614979565b60008060005b33600090815260096020526040902054811015611bff57336000908152600960205260408120805483908110611b0457611b04615113565b6000918252602090912060099091020160078101549091506001600160a01b038681169116148015611b4257506007810154600160a01b900460ff16155b15611bee576000611b533384612dcd565b90508160030154811015611b795760405162461bcd60e51b8152600401610ee5906152b7565b6000826003015482611b8b919061513f565b90508015611beb57808360030154611ba39190615193565b6003840155611bb28187615193565b4260058501558354600385015491975011611bdd5760078301805460ff60a01b1916600160a01b1790555b84611be7816151a6565b9550505b50505b50611bf8816151a6565b9050611acc565b5081600003611c465760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b6044820152606401610ee5565b336000908152600c602052604090205415611d4f576001600160a01b038381166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928692909116906316345f1890602401602060405180830381865afa158015611cc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce69190615253565b611cf09190615152565b611cfa919061517f565b336000908152600c60205260409020549091508110611d2857336000908152600c6020526040812055611d4d565b336000908152600c602052604081208054839290611d4790849061513f565b90915550505b505b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015611d96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dba9190615253565b905082811015611ddc5760405162461bcd60e51b8152600401610ee59061526c565b6001600160a01b03841660009081526010602052604081208054859290611e0490849061513f565b90915550611e1e90506001600160a01b03851633856149b1565b6040518381523390600080516020615310833981519152906020015b60405180910390a25050506116ed600160008051602061533083398151915255565b611e64614979565b336000908152600860205260409020548110611eb85760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b6044820152606401610ee5565b336000908152600860205260408120805483908110611ed957611ed9615113565b600091825260208220600590910201805490925090611ef8338561280b565b9050611f048183615193565b915081600003611f4b5760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b6044820152606401610ee5565b8260030154421015611f975760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b6044820152606401610ee5565b600080845560048401805460ff1916600117905560128054849290611fbd908490615193565b90915550506003548211611feb578160016002016000828254611fe0919061513f565b90915550611ff19050565b60006003555b33600090815260136020908152604091829020825160608101845287815291820185905260115490928201906120279042615193565b90528154600180820184556000938452602093849020835160039093020191825582840151908201556040918201516002909101555183815233916000805160206153108339815191529101611e3a565b600a602052816000526040600020818154811061209457600080fd5b600091825260209091206002909102018054600190910154909250905082565b600860205281600052604060002081815481106120d057600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919060ff1685565b6001600160a01b0382166000908152600c6020526040812054819061212990610e05565b6002546121369190615193565b9050821561214e5760145461214b9082615193565b90505b9392505050565b3360009081526007602052604090205460ff166121845760405162461bcd60e51b8152600401610ee5906151bf565b6001600160a01b0381166121aa5760405162461bcd60e51b8152600401610ee5906151e7565b6001600160a01b03166000908152600f60205260409020805460ff19169055565b3360009081526007602052604090205460ff166121fa5760405162461bcd60e51b8152600401610ee5906151bf565b6001600160a01b039182166000908152600b6020526040902080546001600160a01b03191691909216179055565b6000805b336000908152600860205260409020548110156122a95733600090815260086020526040812080548390811061226457612264615113565b906000526020600020906005020190506000612280338461280b565b905061228c8185615193565b426001909301929092555091506122a2816151a6565b905061222c565b50600e5481116122f45760405162461bcd60e51b8152602060048201526016602482015275139bdd08195b9bdd59da081d1bc818dbdb5c1bdd5b9960521b6044820152606401610ee5565b336000818152600860209081526040808320815160a0810183528681524281850152948452600c909252918290205490929182019061233290610e05565b60025461233f9190615193565b8152602001600160000154426123559190615193565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff191692151592909217909155546123c6908290615193565b60035560405181815233907f3afe5b60dee16617a8adbbd7d6c28f17a27efabb834872efa8e7ad5dafddf6f19060200160405180910390a250565b806000036124515760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610ee5565b6001600160a01b038083166000908152600b602052604090205416806124c55760405162461bcd60e51b815260206004820152602360248201527f5072696365206f7261636c65206e6f742073657420666f72207468697320746f60448201526235b2b760e91b6064820152608401610ee5565b6124da6001600160a01b038416333085614912565b600060646124e9600a85615152565b6124f3919061517f565b6001600160a01b038581166000818152600b60205260408082205490516302c68be360e31b8152600481019390935293945092670de0b6b3a76400009287929116906316345f1890602401602060405180830381865afa15801561255b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257f9190615253565b6125899190615152565b612593919061517f565b9050600e5481116125b65760405162461bcd60e51b8152600401610ee590615210565b336000908152600c6020526040812080548392906125d5908490615193565b90915550506001600160a01b03851660009081526010602052604081208054869290612602908490615193565b909155505033600090815260096020908152604091829020825161014081018452878152918201859052600d54909282019061263e9042615193565b81526000602080830182905260408084018390524260608086018290526080808701929092526001600160a01b038d811660a08089019190915260c080890188905260e09889018c90528a5460018082018d559b8952978790208a51600990990201978855898701519a88019a909a558885015160028801559188015160038701559187015160048601558601516005850155958501516006840155928401516007830180546101008701511515600160a01b026001600160a81b031990911692909716919091179590951790945561012090920151600890920191909155805186815291820184905233917f9ade76f4385de306666dfb21a52b27d52db0fde8ad0f515fa261f532cac60d21910160405180910390a25050505050565b3360009081526007602052604090205460ff1661278b5760405162461bcd60e51b8152600401610ee5906151bf565b6001600160a01b03811660009081526007602052604090205460ff16156127e75760405162461bcd60e51b815260206004820152601060248201526f20b63932b0b23c9030b71037bbb732b960811b6044820152606401610ee5565b6001600160a01b03166000908152600760205260409020805460ff19166001179055565b6001600160a01b038216600090815260086020526040812080548291908490811061283857612838615113565b90600052602060002090600502019050600081600101544261285a919061513f565b9050600061271062015180838560020154866000015461287a9190615152565b6128849190615152565b61288e919061517f565b612898919061517f565b9695505050505050565b3360009081526007602052604090205460ff166128d15760405162461bcd60e51b8152600401610ee5906151bf565b60005481106129185760405162461bcd60e51b8152602060048201526013602482015272496e646578206f7574206f6620626f756e647360681b6044820152606401610ee5565b805b6000546129299060019061513f565b8110156129a657600061293d826001615193565b8154811061294d5761294d615113565b90600052602060002090600302016000828154811061296e5761296e615113565b6000918252602090912082546003909202019081556001808301549082015560029182015491015561299f816151a6565b905061291a565b5060008054806129b8576129b86152e5565b6000828152602081206003600019909301928302018181556001810182905560020155905550565b6001600160a01b0381166000908152600960209081526040808320805482518185028101850190935280835260609492939192909184015b82821015612abc57600084815260209081902060408051610140810182526009860290920180548352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a0840152600681015460c084015260078101546001600160a01b03811660e0850152600160a01b900460ff161515610100840152600801546101208301529083529092019101612a18565b505050509050919050565b6001600160a01b0381166000908152600860209081526040808320805482518185028101850190935280835260609492939192909184015b82821015612abc5760008481526020908190206040805160a081018252600586029092018054835260018082015484860152600282015492840192909252600381015460608401526004015460ff16151560808301529083529092019101612aff565b6001600160a01b038116600090815260096020526040812054815b81811015612d2e576001600160a01b0384166000908152600960205260408120805483908110612baf57612baf615113565b600091825260209182902060408051610140810182526009909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260078201546001600160a01b03811660e083015260ff600160a01b90910416151561010082018190526008909201546101208201529150612d1b5760e0810180516001600160a01b039081166000908152600b602052604080822054935190516302c68be360e31b815290831660048201529092909116906316345f1890602401602060405180830381865afa158015612cac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cd09190615253565b9050600082606001518360000151612ce8919061513f565b90506000670de0b6b3a7640000612cff8385615152565b612d09919061517f565b9050612d158188615193565b96505050505b5080612d26816151a6565b915050612b7d565b5050919050565b6005546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612d82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da69190615253565b90506012548110612db957600091505090565b80601254612dc7919061513f565b91505090565b6001600160a01b0382166000908152600960205260408120805482919084908110612dfa57612dfa615113565b906000526020600020906009020190506000816006015442612e1c919061513f565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a6020526040902054811015610df8576001600160a01b0383166000908152600a60205260408120805483908110612e7b57612e7b615113565b600091825260209091206002909102018054600182015491925090818710612ec557875461271090612eae908390615152565b612eb8919061517f565b612ec29086615193565b94505b50505080612ed2906151a6565b9050612e31565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015612f1f5750825b905060008267ffffffffffffffff166001148015612f3c5750303b155b905081158015612f4a575080155b15612f685760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315612f9257845460ff60401b1916600160401b1785555b612f9a6149f6565b600680546001600160a01b03199081167341970ce76b656030a79e7c1fa76fc4eb93980255178255600760209081527f1428bfef657344f5f7a0019d1554dccabe000be344bb83cdab918bd50f24b573805460ff1990811660019081179092556301499700600d81905567de0b6b3a76400000600e556005805490951673833589fcd6edb6e08f4c7c32d4f71b54bda02913178555825560216002908155604080516060808201835268bdbc41e0348b300000825269021e0c0013070adc000082880190815282840187815260008054808a018255818052945160039586027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5638181019290925593517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5648086019190915592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565948501558651808601885269021e19e0c9bab2400000815269043c25e0dcc1bd1c0000818d01908152818901998a528354808d01855584805291519188028084019290925551818501559751978401979097558551808501875269043c33c1937564800000815269065a3fc1a67c6f5c0000818c019081528188018781528354808d0185558480529251928802808b019390935590518285015551908401558551808501875269065a4da25d3016c00000815269087859a27037219c0000818c0190815260048289019081528354808d0185558480529251928802808b0193909355905182850155519084015585518085018752690878678326eac90000008152690cb48d6403ac861c0000818c019081528188019c8d528254808c0184558380529151918702808a019290925551818401559a519a83019a909a5584518084018652690cb49b44ba602d80000081526910f0c1259721ea9c0000818b019081528187019c8d528b54808b018d558c805291519186028089019290925551818301559a519a82019a909a55835180830185526910f0cf064dd592000000815269152cf4e72a974f1c0000818a0190815260088287019081528b54808b018d558c80529251928602808901939093559051828d015551908201558351918201845269152d02c7e14af68000008252600019828901908152600a94830194855289548089018b558a805292519284029586019290925590519884019890985590519190960155600f9092527f77c9ddf83be31065a9eb7ed19d93a8a4db24cad8351f41cc546083ac9e9d8c7f8054831682179055737c40f272570fdf9549d6f67493ac250a1db52f279092527f1b209462f90614903451721396f08356b5037572bebcd67a02efc98f03bec9d1805490911690911790556201fa4060115560145583156133d357845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b3360009081526007602052604090205460ff166134095760405162461bcd60e51b8152600401610ee5906151bf565b600554613420906001600160a01b031633836149b1565b6005546040518281526001600160a01b039091169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a350565b3360009081526007602052604090205460ff166134965760405162461bcd60e51b8152600401610ee5906151bf565b6005546134ae906001600160a01b0316333084614912565b6004546134bc908290615193565b6004556040518181527f4e9221f2cca6ca0397acc6004ea0b716798254f5abcf53924fab34f0373e5d4e906020015b60405180910390a150565b3360009081526007602052604090205460ff166135255760405162461bcd60e51b8152600401610ee5906151bf565b600e8190556040518181527fe5dadb089824c750e4e7a2e98bfbe130f1a09834769e81339639fbe18606859b906020016134eb565b3360009081526007602052604090205460ff166135895760405162461bcd60e51b8152600401610ee5906151bf565b6135968262015180615152565b600155600281905560408051838152602081018390527f7fa9647ec1cc14e3822b46d05a2b9d4e019bde8875c0088c46b6503d71bf1722910160405180910390a15050565b6135e3614979565b33600090815260096020526040812080548390811061360457613604615113565b600091825260209091206009909102016007810154909150600160a01b900460ff16156136675760405162461bcd60e51b81526020600482015260116024820152705374616b6520697320436f6d706c65746560781b6044820152606401610ee5565b60006136733384612dcd565b905081600301548110156136995760405162461bcd60e51b8152600401610ee5906152b7565b60008260030154826136ab919061513f565b9050806000036136f95760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b6044820152606401610ee5565b8083600301546137099190615193565b6003840181905583541161372d5760078301805460ff60a01b1916600160a01b1790555b336000908152600c60205260409020541561383b5760078301546001600160a01b039081166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928592909116906316345f1890602401602060405180830381865afa1580156137ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137d29190615253565b6137dc9190615152565b6137e6919061517f565b336000908152600c6020526040902054909150811061381457336000908152600c6020526040812055613839565b336000908152600c60205260408120805483929061383390849061513f565b90915550505b505b60078301546001600160a01b03166000908152601060205260408120805483929061386790849061513f565b90915550506007830154613885906001600160a01b031633836149b1565b604080518281526000602082015233917f4a94c2c356e29a6583071e731bdacf2ca56565ba5efebcff6936eb7923b517219101611e3a565b6138e160405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152601360205260408120905b8154811015613992578382828154811061391757613917615113565b906000526020600020906003020160000154036139805781818154811061394057613940615113565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505050610dff565b8061398a816151a6565b9150506138fb565b5060405162461bcd60e51b815260206004820152604160248201527f57697468647261775374616b652077697468207468652073706563696669656460448201527f207374616b654964206e6f7420666f756e6420666f72207468697320757365726064820152601760f91b608482015260a401610ee5565b613a13614979565b6064811115613a645760405162461bcd60e51b815260206004820152601a60248201527f496e76616c69642072657374616b652070657263656e746167650000000000006044820152606401610ee5565b336000908152600860205260408120805484908110613a8557613a85615113565b906000526020600020906005020190508060000154600003613ade5760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b6044820152606401610ee5565b8060030154421015613b2a5760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b6044820152606401610ee5565b80546000613b38338661280b565b9050613b448183615193565b915060006064613b548685615152565b613b5e919061517f565b90506000613b6c828561513f565b6000865560048601805460ff1916600117905590508015613c58578060126000828254613b999190615193565b90915550506003548111613bc7578060016002016000828254613bbc919061513f565b90915550613bcd9050565b60006003555b3360009081526013602090815260409182902082516060810184528a81529182018490526011549092820190613c039042615193565b9052815460018082018455600093845260209384902083516003909302019182558284015190820155604091820151600290910155518281523391600080516020615310833981519152910160405180910390a25b8115613d7f573360009081526015602052604081205415613c89575033600090815260156020526040902054613c97565b613c94336001612105565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a0016040528085815260200142815260200183815260200160016000015442613cea9190615193565b81526000602091820181905283546001808201865594825290829020835160059092020190815582820151938101939093556040808301516002850155606083015160038501556080909201516004909301805460ff1916931515939093179092555184815233917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d910160405180910390a2505b5050505050613d9b600160008051602061533083398151915255565b5050565b3360009081526007602052604090205460ff16613dce5760405162461bcd60e51b8152600401610ee5906151bf565b6001600160a01b038116613df45760405162461bcd60e51b8152600401610ee5906151e7565b6001600160a01b0316600090815260156020526040812055565b3360009081526007602052604090205460ff16613e3d5760405162461bcd60e51b8152600401610ee5906151bf565b81600003613e995760405162461bcd60e51b815260206004820152602360248201527f4c6f636b2074696d65206d7573742062652067726561746572207468616e207a60448201526265726f60e81b6064820152608401610ee5565b80600003613eff5760405162461bcd60e51b815260206004820152602d60248201527f50657263656e74616765207065722073746570206d757374206265206772656160448201526c746572207468616e207a65726f60981b6064820152608401610ee5565b612710613f0c82826152fb565b15613f645760405162461bcd60e51b815260206004820152602260248201527f50657263656e74616765206d757374206469766964652031303025206576656e6044820152616c7960f01b6064820152608401610ee5565b6000613f70838361517f565b90506000613f7e828661517f565b6001600160a01b0387166000908152600a60205260408120919250613fa39190614ce6565b60015b828111614018576001600160a01b0387166000908152600a60205260409081902081518083019092529080613fdb8486615152565b815260209081018890528254600181810185556000948552938290208351600290920201908155910151910155614011816151a6565b9050613fa6565b506040516001600160a01b038716907fde4b6ccc38b84f88129403b65a309f9b1c41d4c316bc2118d7614e449b9d4c4590600090a2505050505050565b6009602052816000526040600020818154811061407157600080fd5b6000918252602090912060099091020180546001820154600283015460038401546004850154600586015460068701546007880154600890980154969950949750929591949093916001600160a01b03811691600160a01b90910460ff16908a565b6001600160a01b03821660009081526009602052604081208054606092839290918590811061410457614104615113565b600091825260208083206007600990930201918201546001600160a01b0316808452600a9091526040832054919350918167ffffffffffffffff81111561414d5761414d6152a1565b604051908082528060200260200182016040528015614176578160200160208202803683370190505b50905060008267ffffffffffffffff811115614194576141946152a1565b6040519080825280602002602001820160405280156141bd578160200160208202803683370190505b50905060005b8381101561426a576001600160a01b0385166000908152600a602052604081208054839081106141f5576141f5615113565b90600052602060002090600202019050806000015487600601546142199190615193565b84838151811061422b5761422b615113565b602002602001018181525050806001015483838151811061424e5761424e615113565b602090810291909101015250614263816151a6565b90506141c3565b50909890975095505050505050565b6013602052816000526040600020818154811061429557600080fd5b600091825260209091206003909102018054600182015460029092015490935090915083565b3360009081526007602052604090205460ff166142ea5760405162461bcd60e51b8152600401610ee5906151bf565b601155565b600081815481106142ff57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b3360009081526007602052604090205460ff166143515760405162461bcd60e51b8152600401610ee5906151bf565b601455565b61435e614979565b33600090815260096020526040812080548390811061437f5761437f615113565b90600052602060002090600902019050600061439b3384610cea565b905081600401548110156143c15760405162461bcd60e51b8152600401610ee5906152b7565b60008260040154826143d3919061513f565b9050806000036144215760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b6044820152606401610ee5565b8083600401546144319190615193565b6004840155600783015461444f906001600160a01b031633836149b1565b60405181815233907f4e69fdc49495bcab2b4375781457ba16653a90eb4ffb6588351bdc39071433e290602001611e3a565b3360009081526007602052604090205460ff166144b05760405162461bcd60e51b8152600401610ee5906151bf565b8183106145145760405162461bcd60e51b815260206004820152602c60248201527f496e76616c69642072616e67653a206d696e546f6b656e73206d75737420626560448201526b203c206d6178546f6b656e7360a01b6064820152608401610ee5565b61451e8383614a06565b156145765760405162461bcd60e51b815260206004820152602260248201527f52616e6765206f7665726c6170732077697468206578697374696e6720746965604482015261727360f01b6064820152608401610ee5565b60005b60005481101561461d57836000828154811061459757614597615113565b9060005260206000209060030201600001541480156145d9575082600082815481106145c5576145c5615113565b906000526020600020906003020160010154145b1561460d5781600082815481106145f2576145f2615113565b90600052602060002090600302016002018190555050505050565b614616816151a6565b9050614579565b5060408051606081018252848152602081018481529181018381526000805460018101825590805291517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56360039093029283015591517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56482015590517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565909101556146c6614a95565b505050565b600080805b6001600160a01b03841660009081526008602052604090205481101561471c5760006146fc858361280b565b90506147088184615193565b92505080614715906151a6565b90506146d0565b5092915050565b3360009081526007602052604090205460ff166147525760405162461bcd60e51b8152600401610ee5906151bf565b806000036147935760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606401610ee5565b60086000836001600160a01b03166001600160a01b031681526020019081526020016000206040518060a0016040528083815260200142815260200160018001548152602001600160000154426147ea9190615193565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff1916921515929092179091555461485b908290615193565b6003556040518181526001600160a01b038316907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906020016111a1565b3360009081526007602052604090205460ff166148c85760405162461bcd60e51b8152600401610ee5906151bf565b6001600160a01b0381166148ee5760405162461bcd60e51b8152600401610ee5906151e7565b6001600160a01b03166000908152600f60205260409020805460ff19166001179055565b6040516001600160a01b0384811660248301528381166044830152606482018390526114049186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050614c24565b6000805160206153308339815191528054600119016149ab57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6040516001600160a01b038381166024830152604482018390526146c691859182169063a9059cbb90606401614947565b600160008051602061533083398151915255565b6149fe614c95565b611845614cde565b6000805b600054811015614a8b5760008181548110614a2757614a27615113565b9060005260206000209060030201600101548411158015614a6c575060008181548110614a5657614a56615113565b9060005260206000209060030201600001548310155b15614a7b576001915050610dff565b614a84816151a6565b9050614a0a565b5060009392505050565b60005b6000548110156116ed576000614aaf826001615193565b90505b600054811015614c135760008181548110614acf57614acf615113565b90600052602060002090600302016000015460008381548110614af457614af4615113565b9060005260206000209060030201600001541115614c01576000808381548110614b2057614b20615113565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905060008281548110614b6c57614b6c615113565b906000526020600020906003020160008481548110614b8d57614b8d615113565b90600052602060002090600302016000820154816000015560018201548160010155600282015481600201559050508060008381548110614bd057614bd0615113565b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020155905050505b80614c0b816151a6565b915050614ab2565b50614c1d816151a6565b9050614a98565b600080602060008451602086016000885af180614c47576040513d6000823e3d81fd5b50506000513d91508115614c5f578060011415614c6c565b6001600160a01b0384163b155b1561140457604051635274afe760e01b81526001600160a01b0385166004820152602401610ee5565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661184557604051631afcd79f60e31b815260040160405180910390fd5b6149e2614c95565b50805460008255600202906000526020600020908101906116ed91905b80821115614d1d5760008082556001820155600201614d03565b5090565b80356001600160a01b0381168114614d3857600080fd5b919050565b600060208284031215614d4f57600080fd5b61214e82614d21565b60008060408385031215614d6b57600080fd5b614d7483614d21565b946020939093013593505050565b600060208284031215614d9457600080fd5b5035919050565b60008060208385031215614dae57600080fd5b823567ffffffffffffffff80821115614dc657600080fd5b818501915085601f830112614dda57600080fd5b813581811115614de957600080fd5b86602060a083028501011115614dfe57600080fd5b60209290920196919550909350505050565b60008060208385031215614e2357600080fd5b823567ffffffffffffffff80821115614e3b57600080fd5b818501915085601f830112614e4f57600080fd5b813581811115614e5e57600080fd5b8660208260051b8501011115614dfe57600080fd5b600081518084526020808501945080840160005b83811015614ea357815187529582019590820190600101614e87565b509495945050505050565b606081526000614ec16060830186614e73565b8281036020840152614ed38186614e73565b915050826040830152949350505050565b60008060408385031215614ef757600080fd5b614f0083614d21565b915060208301358015158114614f1557600080fd5b809150509250929050565b60008060408385031215614f3357600080fd5b614f3c83614d21565b9150614f4a60208401614d21565b90509250929050565b602080825282518282018190526000919060409081850190868401855b82811015614ff45781518051855286810151878601528581015186860152606080820151908601526080808201519086015260a0808201519086015260c0808201519086015260e0808201516001600160a01b0316908601526101008082015115159086015261012090810151908501526101409093019290850190600101614f70565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015614ff457815180518552868101518786015285810151868601526060808201519086015260809081015115159085015260a0909301929085019060010161501e565b6000806040838503121561507757600080fd5b50508035926020909101359150565b60008060006060848603121561509b57600080fd5b6150a484614d21565b95602085013595506040909401359392505050565b6040815260006150cc6040830185614e73565b82810360208401526150de8185614e73565b95945050505050565b6000806000606084860312156150fc57600080fd5b505081359360208301359350604090920135919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610dff57610dff615129565b8082028115828204841417610dff57610dff615129565b634e487b7160e01b600052601260045260246000fd5b60008261518e5761518e615169565b500490565b80820180821115610dff57610dff615129565b6000600182016151b8576151b8615129565b5060010190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b60208082526023908201527f416d6f756e74206d7573742062652067726561746572206d696e5374616b654c6040820152626f636b60e81b606082015260800190565b60006020828403121561526557600080fd5b5051919050565b6020808252818101527f496e73756666696369656e74207265776172647320696e2074686520706f6f6c604082015260600190565b634e487b7160e01b600052604160045260246000fd5b602080825260149082015273125b9d985b1a590818db185a5b48185b5bdd5b9d60621b604082015260600190565b634e487b7160e01b600052603160045260246000fd5b60008261530a5761530a615169565b50069056fe106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f72419b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a264697066735822122045358477ab3c3bdadb8fed55d327409e93a4df155bca5804b01e746c7266292a64736f6c63430008140033
Deployed Bytecode
0x6080604052600436106103ad5760003560e01c8063710ea0ce116101e7578063b6c3dc4c1161010d578063ce13d090116100a0578063d96134101161006f578063d961341014610c6a578063da40ef8014610c8a578063e4d06f9014610caa578063ffecf51614610cca57600080fd5b8063ce13d09014610bea578063cfb866da14610c0a578063d6c680eb14610c2a578063d919302514610c4a57600080fd5b8063bd721698116100dc578063bd72169814610adf578063bd84477d14610b0c578063bed9757e14610b81578063c606627214610baf57600080fd5b8063b6c3dc4c14610a3d578063b8e7023d14610a7f578063b90fba1914610a9f578063b92a349f14610abf57600080fd5b80638129fc1c1161018557806392257cb51161015457806392257cb5146109c75780639562ee15146109dd57806396ed7f89146109fd578063ac97b41714610a1d57600080fd5b80638129fc1c14610952578063853e0df2146109675780638bdf67f2146109875780638da5cb5b146109a757600080fd5b80637ba6f458116101c15780637ba6f458146108d05780637bc221ac146108fd5780637f79496c1461091d57806380ca0ecf1461093257600080fd5b8063710ea0ce146108635780637497211b146108835780637a0c6dc0146108a357600080fd5b806338a85ce2116102d7578063584b62a11161026a57806367a74ddc1161023957806367a74ddc146107ee5780636ae215101461080e5780636c3b0c53146108235780637065cb481461084357600080fd5b8063584b62a114610737578063592d1dd114610781578063599ab2c4146107ae5780635fecd926146107ce57600080fd5b806343c7c011116102a657806343c7c011146106ac57806344c7d6ef146106cc57806351f6cf2f146106ec5780635339dcc11461072157600080fd5b806338a85ce2146106175780633ba8396e1461062d5780633c92f98d1461065d5780633f35e7221461068c57600080fd5b806316f0115b1161034f5780631d7a33611161031e5780631d7a3361146105af57806322a26fc0146105cf5780632e1a7d4d146105e2578063372500ab1461060257600080fd5b806316f0115b146104f8578063173825d9146105595780631ada70a8146105795780631bf6ddae1461058f57600080fd5b8063092c76101161038b578063092c7610146104695780630a84096a1461049657806313c8e2de146104b657806316be9b2a146104d657600080fd5b806301374518146103b2578063022914a7146104055780630519da3214610445575b600080fd5b3480156103be57600080fd5b506103e86103cd366004614d3d565b600b602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561041157600080fd5b50610435610420366004614d3d565b60076020526000908152604090205460ff1681565b60405190151581526020016103fc565b34801561045157600080fd5b5061045b60115481565b6040519081526020016103fc565b34801561047557600080fd5b5061045b610484366004614d3d565b60106020526000908152604090205481565b3480156104a257600080fd5b5061045b6104b1366004614d58565b610cea565b3480156104c257600080fd5b5061045b6104d1366004614d82565b610e05565b3480156104e257600080fd5b506104f66104f1366004614d58565b610eb6565b005b34801561050457600080fd5b5060015460025460035460045460055461052894939291906001600160a01b031685565b6040805195865260208601949094529284019190915260608301526001600160a01b0316608082015260a0016103fc565b34801561056557600080fd5b506104f6610574366004614d3d565b610f30565b34801561058557600080fd5b5061045b600d5481565b34801561059b57600080fd5b506104f66105aa366004614d82565b611028565b3480156105bb57600080fd5b506104f66105ca366004614d3d565b6111ad565b6104f66105dd366004614d9b565b6112b6565b3480156105ee57600080fd5b506104f66105fd366004614d82565b61140a565b34801561060e57600080fd5b506104f66116f0565b34801561062357600080fd5b5061045b600e5481565b34801561063957600080fd5b50610435610648366004614d3d565b600f6020526000908152604090205460ff1681565b34801561066957600080fd5b5061067d610678366004614e10565b611847565b6040516103fc93929190614eae565b34801561069857600080fd5b506104f66106a7366004614d58565b611a37565b3480156106b857600080fd5b506104f66106c7366004614d3d565b611abe565b3480156106d857600080fd5b506104f66106e7366004614d82565b611e5c565b3480156106f857600080fd5b5061070c610707366004614d58565b612078565b604080519283526020830191909152016103fc565b34801561072d57600080fd5b5061045b60145481565b34801561074357600080fd5b50610757610752366004614d58565b6120b4565b6040805195865260208601949094529284019190915260608301521515608082015260a0016103fc565b34801561078d57600080fd5b5061045b61079c366004614d3d565b600c6020526000908152604090205481565b3480156107ba57600080fd5b5061045b6107c9366004614ee4565b612105565b3480156107da57600080fd5b506104f66107e9366004614d3d565b612155565b3480156107fa57600080fd5b506104f6610809366004614f20565b6121cb565b34801561081a57600080fd5b506104f6612228565b34801561082f57600080fd5b506104f661083e366004614d58565b612401565b34801561084f57600080fd5b506104f661085e366004614d3d565b61275c565b34801561086f57600080fd5b5061045b61087e366004614d58565b61280b565b34801561088f57600080fd5b506104f661089e366004614d82565b6128a2565b3480156108af57600080fd5b506108c36108be366004614d3d565b6129e0565b6040516103fc9190614f53565b3480156108dc57600080fd5b506108f06108eb366004614d3d565b612ac7565b6040516103fc9190615001565b34801561090957600080fd5b5061045b610918366004614d3d565b612b62565b34801561092957600080fd5b5061045b612d35565b34801561093e57600080fd5b5061045b61094d366004614d58565b612dcd565b34801561095e57600080fd5b506104f6612ed9565b34801561097357600080fd5b506104f6610982366004614d82565b6133da565b34801561099357600080fd5b506104f66109a2366004614d82565b613467565b3480156109b357600080fd5b506006546103e8906001600160a01b031681565b3480156109d357600080fd5b5061045b60125481565b3480156109e957600080fd5b506104f66109f8366004614d82565b6134f6565b348015610a0957600080fd5b506104f6610a18366004615064565b61355a565b348015610a2957600080fd5b506104f6610a38366004614d82565b6135db565b348015610a4957600080fd5b50610a5d610a58366004614d58565b6138bd565b60408051825181526020808401519082015291810151908201526060016103fc565b348015610a8b57600080fd5b506104f6610a9a366004615064565b613a0b565b348015610aab57600080fd5b506104f6610aba366004614d3d565b613d9f565b348015610acb57600080fd5b506104f6610ada366004615086565b613e0e565b348015610aeb57600080fd5b5061045b610afa366004614d3d565b60156020526000908152604090205481565b348015610b1857600080fd5b50610b2c610b27366004614d58565b614055565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925260a086015260c08501526001600160a01b031660e08401521515610100830152610120820152610140016103fc565b348015610b8d57600080fd5b50610ba1610b9c366004614d58565b6140d3565b6040516103fc9291906150b9565b348015610bbb57600080fd5b50610bcf610bca366004614d58565b614279565b604080519384526020840192909252908201526060016103fc565b348015610bf657600080fd5b506104f6610c05366004614d82565b6142bb565b348015610c1657600080fd5b50610bcf610c25366004614d82565b6142ef565b348015610c3657600080fd5b506104f6610c45366004614d82565b614322565b348015610c5657600080fd5b506104f6610c65366004614d82565b614356565b348015610c7657600080fd5b506104f6610c853660046150e7565b614481565b348015610c9657600080fd5b5061045b610ca5366004614d3d565b6146cb565b348015610cb657600080fd5b506104f6610cc5366004614d58565b614723565b348015610cd657600080fd5b506104f6610ce5366004614d3d565b614899565b6001600160a01b0382166000908152600960205260408120805482919084908110610d1757610d17615113565b906000526020600020906009020190506000816006015442610d39919061513f565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a6020526040902054811015610df8576001600160a01b0383166000908152600a60205260408120805483908110610d9857610d98615113565b600091825260209091206002909102018054600182015491925090818710610de457612710818960010154610dcd9190615152565b610dd7919061517f565b610de19086615193565b94505b50505080610df1906151a6565b9050610d4e565b5093505050505b92915050565b6000805b600054811015610ead5760008181548110610e2657610e26615113565b9060005260206000209060030201600001548310158015610e6b575060008181548110610e5557610e55615113565b9060005260206000209060030201600101548311155b15610e9d5760008181548110610e8357610e83615113565b906000526020600020906003020160020154915050919050565b610ea6816151a6565b9050610e09565b50600092915050565b3360009081526007602052604090205460ff16610eee5760405162461bcd60e51b8152600401610ee5906151bf565b60405180910390fd5b6001600160a01b038216610f145760405162461bcd60e51b8152600401610ee5906151e7565b6001600160a01b03909116600090815260156020526040902055565b3360009081526007602052604090205460ff16610f5f5760405162461bcd60e51b8152600401610ee5906151bf565b6001600160a01b03811660009081526007602052604090205460ff16610fb65760405162461bcd60e51b815260206004820152600c60248201526b2737ba1030b71037bbb732b960a11b6044820152606401610ee5565b336001600160a01b038216036110075760405162461bcd60e51b815260206004820152601660248201527521b0b73737ba103932b6b7bb32903cb7bab939b2b63360511b6044820152606401610ee5565b6001600160a01b03166000908152600760205260409020805460ff19169055565b600e5461103a8264e8d4a51000615152565b116110575760405162461bcd60e51b8152600401610ee590615210565b60055461106f906001600160a01b0316333084614912565b336000908152601560205260408120541561109a5750336000908152601560205260409020546110a8565b6110a5336000612105565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a00160405280848152602001428152602001838152602001600160000154426110fb9190615193565b815260006020918201819052835460018082018655948252828220845160059092020190815591830151938201939093556040820151600282015560608201516003808301919091556080909201516004909101805460ff1916911515919091179055805484929061116e908490615193565b909155505060405182815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906020015b60405180910390a25050565b336000908152600f602052604090205460ff1661120c5760405162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206973206e6f7420616e20617574686f72697a656420626f74006044820152606401610ee5565b6000805b6001600160a01b0383166000908152600860205260409020548110156112a0576001600160a01b038316600090815260086020526040812080548390811061125a5761125a615113565b9060005260206000209060050201905080600001548361127a9190615193565b600082556004909101805460ff191660011790559150611299816151a6565b9050611210565b506003546112af90829061513f565b6003555050565b336000908152600f602052604090205460ff166113155760405162461bcd60e51b815260206004820152601f60248201527f43616c6c6572206973206e6f7420616e20617574686f72697a656420626f74006044820152606401610ee5565b8060005b81811015611404573684848381811061133457611334615113565b905060a00201905080602001356001600201546113519190615193565b600355600860006113656020840184614d3d565b6001600160a01b0316815260208082019290925260409081016000908120825160a08101845285850135815285840135818601908152608080880135958301958652606097880135978301978852820184815283546001808201865594865296909420915160059096029091019485555184820155915160028401559251600383015591516004909101805460ff191691151591909117905501611319565b50505050565b611412614979565b336000908152601360205260408120805461147a5760405162461bcd60e51b815260206004820152602260248201527f4e6f207374616b657320617661696c61626c6520666f72207769746864726177604482015261185b60f21b6064820152608401610ee5565b60005b815481101561169757600082828154811061149a5761149a615113565b906000526020600020906003020190508481600001540361168657806001015460000361151b5760405162461bcd60e51b815260206004820152602960248201527f5374616b6520616c72656164792077697468647261776e206f7220646f6573206044820152681b9bdd08195e1a5cdd60ba1b6064820152608401610ee5565b806002015442101561156f5760405162461bcd60e51b815260206004820152601e60248201527f5769746864726177205374616b65206973207374696c6c206c6f636b656400006044820152606401610ee5565b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156115b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115dc9190615253565b905081600101548110156116025760405162461bcd60e51b8152600401610ee59061526c565b81600101549450600082600101819055508460126000828254611625919061513f565b9091555050600554611641906001600160a01b031633876149b1565b604080518681526020810188905233917f933735aa8de6d7547d0126171b2f31b9c34dd00f3ecd4be85a0ba047db4fafef910160405180910390a250505050506116d6565b50611690816151a6565b905061147d565b5060405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b6044820152606401610ee5565b6116ed600160008051602061533083398151915255565b50565b6116f8614979565b6000805b336000908152600860205260409020548110156117795733600090815260086020526040812080548390811061173457611734615113565b906000526020600020906005020190506000611750338461280b565b905061175c8185615193565b42600190930192909255509150611772816151a6565b90506116fc565b50806000036117c05760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b6044820152606401610ee5565b6004548111156117e25760405162461bcd60e51b8152600401610ee59061526c565b6004546117f090829061513f565b60045560055461180a906001600160a01b031633836149b1565b60405181815233906000805160206153108339815191529060200160405180910390a250611845600160008051602061533083398151915255565b565b6060806000838067ffffffffffffffff811115611866576118666152a1565b60405190808252806020026020018201604052801561188f578160200160208202803683370190505b5093508067ffffffffffffffff8111156118ab576118ab6152a1565b6040519080825280602002602001820160405280156118d4578160200160208202803683370190505b50925060005b81811015611a2e5760008787838181106118f6576118f6615113565b905060200201602081019061190b9190614d3d565b6001600160a01b038116600090815260106020526040902054875191925090819088908590811061193e5761193e615113565b6020908102919091018101919091526001600160a01b038381166000818152600b90935260408084205490516302c68be360e31b81526004810192909252909116906316345f1890602401602060405180830381865afa1580156119a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ca9190615253565b90506000670de0b6b3a76400006119e18484615152565b6119eb919061517f565b905080888681518110611a0057611a00615113565b6020908102919091010152611a158188615193565b9650505050508080611a26906151a6565b9150506118da565b50509250925092565b3360009081526007602052604090205460ff16611a665760405162461bcd60e51b8152600401610ee5906151bf565b611a7a6001600160a01b03831633836149b1565b6040518181526001600160a01b0383169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a35050565b611ac6614979565b60008060005b33600090815260096020526040902054811015611bff57336000908152600960205260408120805483908110611b0457611b04615113565b6000918252602090912060099091020160078101549091506001600160a01b038681169116148015611b4257506007810154600160a01b900460ff16155b15611bee576000611b533384612dcd565b90508160030154811015611b795760405162461bcd60e51b8152600401610ee5906152b7565b6000826003015482611b8b919061513f565b90508015611beb57808360030154611ba39190615193565b6003840155611bb28187615193565b4260058501558354600385015491975011611bdd5760078301805460ff60a01b1916600160a01b1790555b84611be7816151a6565b9550505b50505b50611bf8816151a6565b9050611acc565b5081600003611c465760405162461bcd60e51b81526020600482015260136024820152724e6f207265776172647320746f20636c61696d60681b6044820152606401610ee5565b336000908152600c602052604090205415611d4f576001600160a01b038381166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928692909116906316345f1890602401602060405180830381865afa158015611cc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce69190615253565b611cf09190615152565b611cfa919061517f565b336000908152600c60205260409020549091508110611d2857336000908152600c6020526040812055611d4d565b336000908152600c602052604081208054839290611d4790849061513f565b90915550505b505b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015611d96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dba9190615253565b905082811015611ddc5760405162461bcd60e51b8152600401610ee59061526c565b6001600160a01b03841660009081526010602052604081208054859290611e0490849061513f565b90915550611e1e90506001600160a01b03851633856149b1565b6040518381523390600080516020615310833981519152906020015b60405180910390a25050506116ed600160008051602061533083398151915255565b611e64614979565b336000908152600860205260409020548110611eb85760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b6044820152606401610ee5565b336000908152600860205260408120805483908110611ed957611ed9615113565b600091825260208220600590910201805490925090611ef8338561280b565b9050611f048183615193565b915081600003611f4b5760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b6044820152606401610ee5565b8260030154421015611f975760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b6044820152606401610ee5565b600080845560048401805460ff1916600117905560128054849290611fbd908490615193565b90915550506003548211611feb578160016002016000828254611fe0919061513f565b90915550611ff19050565b60006003555b33600090815260136020908152604091829020825160608101845287815291820185905260115490928201906120279042615193565b90528154600180820184556000938452602093849020835160039093020191825582840151908201556040918201516002909101555183815233916000805160206153108339815191529101611e3a565b600a602052816000526040600020818154811061209457600080fd5b600091825260209091206002909102018054600190910154909250905082565b600860205281600052604060002081815481106120d057600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919060ff1685565b6001600160a01b0382166000908152600c6020526040812054819061212990610e05565b6002546121369190615193565b9050821561214e5760145461214b9082615193565b90505b9392505050565b3360009081526007602052604090205460ff166121845760405162461bcd60e51b8152600401610ee5906151bf565b6001600160a01b0381166121aa5760405162461bcd60e51b8152600401610ee5906151e7565b6001600160a01b03166000908152600f60205260409020805460ff19169055565b3360009081526007602052604090205460ff166121fa5760405162461bcd60e51b8152600401610ee5906151bf565b6001600160a01b039182166000908152600b6020526040902080546001600160a01b03191691909216179055565b6000805b336000908152600860205260409020548110156122a95733600090815260086020526040812080548390811061226457612264615113565b906000526020600020906005020190506000612280338461280b565b905061228c8185615193565b426001909301929092555091506122a2816151a6565b905061222c565b50600e5481116122f45760405162461bcd60e51b8152602060048201526016602482015275139bdd08195b9bdd59da081d1bc818dbdb5c1bdd5b9960521b6044820152606401610ee5565b336000818152600860209081526040808320815160a0810183528681524281850152948452600c909252918290205490929182019061233290610e05565b60025461233f9190615193565b8152602001600160000154426123559190615193565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff191692151592909217909155546123c6908290615193565b60035560405181815233907f3afe5b60dee16617a8adbbd7d6c28f17a27efabb834872efa8e7ad5dafddf6f19060200160405180910390a250565b806000036124515760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610ee5565b6001600160a01b038083166000908152600b602052604090205416806124c55760405162461bcd60e51b815260206004820152602360248201527f5072696365206f7261636c65206e6f742073657420666f72207468697320746f60448201526235b2b760e91b6064820152608401610ee5565b6124da6001600160a01b038416333085614912565b600060646124e9600a85615152565b6124f3919061517f565b6001600160a01b038581166000818152600b60205260408082205490516302c68be360e31b8152600481019390935293945092670de0b6b3a76400009287929116906316345f1890602401602060405180830381865afa15801561255b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257f9190615253565b6125899190615152565b612593919061517f565b9050600e5481116125b65760405162461bcd60e51b8152600401610ee590615210565b336000908152600c6020526040812080548392906125d5908490615193565b90915550506001600160a01b03851660009081526010602052604081208054869290612602908490615193565b909155505033600090815260096020908152604091829020825161014081018452878152918201859052600d54909282019061263e9042615193565b81526000602080830182905260408084018390524260608086018290526080808701929092526001600160a01b038d811660a08089019190915260c080890188905260e09889018c90528a5460018082018d559b8952978790208a51600990990201978855898701519a88019a909a558885015160028801559188015160038701559187015160048601558601516005850155958501516006840155928401516007830180546101008701511515600160a01b026001600160a81b031990911692909716919091179590951790945561012090920151600890920191909155805186815291820184905233917f9ade76f4385de306666dfb21a52b27d52db0fde8ad0f515fa261f532cac60d21910160405180910390a25050505050565b3360009081526007602052604090205460ff1661278b5760405162461bcd60e51b8152600401610ee5906151bf565b6001600160a01b03811660009081526007602052604090205460ff16156127e75760405162461bcd60e51b815260206004820152601060248201526f20b63932b0b23c9030b71037bbb732b960811b6044820152606401610ee5565b6001600160a01b03166000908152600760205260409020805460ff19166001179055565b6001600160a01b038216600090815260086020526040812080548291908490811061283857612838615113565b90600052602060002090600502019050600081600101544261285a919061513f565b9050600061271062015180838560020154866000015461287a9190615152565b6128849190615152565b61288e919061517f565b612898919061517f565b9695505050505050565b3360009081526007602052604090205460ff166128d15760405162461bcd60e51b8152600401610ee5906151bf565b60005481106129185760405162461bcd60e51b8152602060048201526013602482015272496e646578206f7574206f6620626f756e647360681b6044820152606401610ee5565b805b6000546129299060019061513f565b8110156129a657600061293d826001615193565b8154811061294d5761294d615113565b90600052602060002090600302016000828154811061296e5761296e615113565b6000918252602090912082546003909202019081556001808301549082015560029182015491015561299f816151a6565b905061291a565b5060008054806129b8576129b86152e5565b6000828152602081206003600019909301928302018181556001810182905560020155905550565b6001600160a01b0381166000908152600960209081526040808320805482518185028101850190935280835260609492939192909184015b82821015612abc57600084815260209081902060408051610140810182526009860290920180548352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a0840152600681015460c084015260078101546001600160a01b03811660e0850152600160a01b900460ff161515610100840152600801546101208301529083529092019101612a18565b505050509050919050565b6001600160a01b0381166000908152600860209081526040808320805482518185028101850190935280835260609492939192909184015b82821015612abc5760008481526020908190206040805160a081018252600586029092018054835260018082015484860152600282015492840192909252600381015460608401526004015460ff16151560808301529083529092019101612aff565b6001600160a01b038116600090815260096020526040812054815b81811015612d2e576001600160a01b0384166000908152600960205260408120805483908110612baf57612baf615113565b600091825260209182902060408051610140810182526009909302909101805483526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a0820152600682015460c082015260078201546001600160a01b03811660e083015260ff600160a01b90910416151561010082018190526008909201546101208201529150612d1b5760e0810180516001600160a01b039081166000908152600b602052604080822054935190516302c68be360e31b815290831660048201529092909116906316345f1890602401602060405180830381865afa158015612cac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cd09190615253565b9050600082606001518360000151612ce8919061513f565b90506000670de0b6b3a7640000612cff8385615152565b612d09919061517f565b9050612d158188615193565b96505050505b5080612d26816151a6565b915050612b7d565b5050919050565b6005546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612d82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da69190615253565b90506012548110612db957600091505090565b80601254612dc7919061513f565b91505090565b6001600160a01b0382166000908152600960205260408120805482919084908110612dfa57612dfa615113565b906000526020600020906009020190506000816006015442612e1c919061513f565b60078301549091506001600160a01b03166000805b6001600160a01b0383166000908152600a6020526040902054811015610df8576001600160a01b0383166000908152600a60205260408120805483908110612e7b57612e7b615113565b600091825260209091206002909102018054600182015491925090818710612ec557875461271090612eae908390615152565b612eb8919061517f565b612ec29086615193565b94505b50505080612ed2906151a6565b9050612e31565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff16600081158015612f1f5750825b905060008267ffffffffffffffff166001148015612f3c5750303b155b905081158015612f4a575080155b15612f685760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315612f9257845460ff60401b1916600160401b1785555b612f9a6149f6565b600680546001600160a01b03199081167341970ce76b656030a79e7c1fa76fc4eb93980255178255600760209081527f1428bfef657344f5f7a0019d1554dccabe000be344bb83cdab918bd50f24b573805460ff1990811660019081179092556301499700600d81905567de0b6b3a76400000600e556005805490951673833589fcd6edb6e08f4c7c32d4f71b54bda02913178555825560216002908155604080516060808201835268bdbc41e0348b300000825269021e0c0013070adc000082880190815282840187815260008054808a018255818052945160039586027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5638181019290925593517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5648086019190915592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565948501558651808601885269021e19e0c9bab2400000815269043c25e0dcc1bd1c0000818d01908152818901998a528354808d01855584805291519188028084019290925551818501559751978401979097558551808501875269043c33c1937564800000815269065a3fc1a67c6f5c0000818c019081528188018781528354808d0185558480529251928802808b019390935590518285015551908401558551808501875269065a4da25d3016c00000815269087859a27037219c0000818c0190815260048289019081528354808d0185558480529251928802808b0193909355905182850155519084015585518085018752690878678326eac90000008152690cb48d6403ac861c0000818c019081528188019c8d528254808c0184558380529151918702808a019290925551818401559a519a83019a909a5584518084018652690cb49b44ba602d80000081526910f0c1259721ea9c0000818b019081528187019c8d528b54808b018d558c805291519186028089019290925551818301559a519a82019a909a55835180830185526910f0cf064dd592000000815269152cf4e72a974f1c0000818a0190815260088287019081528b54808b018d558c80529251928602808901939093559051828d015551908201558351918201845269152d02c7e14af68000008252600019828901908152600a94830194855289548089018b558a805292519284029586019290925590519884019890985590519190960155600f9092527f77c9ddf83be31065a9eb7ed19d93a8a4db24cad8351f41cc546083ac9e9d8c7f8054831682179055737c40f272570fdf9549d6f67493ac250a1db52f279092527f1b209462f90614903451721396f08356b5037572bebcd67a02efc98f03bec9d1805490911690911790556201fa4060115560145583156133d357845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b3360009081526007602052604090205460ff166134095760405162461bcd60e51b8152600401610ee5906151bf565b600554613420906001600160a01b031633836149b1565b6005546040518281526001600160a01b039091169033907fa92ff919b850e4909ab2261d907ef955f11bc1716733a6cbece38d163a69af8a9060200160405180910390a350565b3360009081526007602052604090205460ff166134965760405162461bcd60e51b8152600401610ee5906151bf565b6005546134ae906001600160a01b0316333084614912565b6004546134bc908290615193565b6004556040518181527f4e9221f2cca6ca0397acc6004ea0b716798254f5abcf53924fab34f0373e5d4e906020015b60405180910390a150565b3360009081526007602052604090205460ff166135255760405162461bcd60e51b8152600401610ee5906151bf565b600e8190556040518181527fe5dadb089824c750e4e7a2e98bfbe130f1a09834769e81339639fbe18606859b906020016134eb565b3360009081526007602052604090205460ff166135895760405162461bcd60e51b8152600401610ee5906151bf565b6135968262015180615152565b600155600281905560408051838152602081018390527f7fa9647ec1cc14e3822b46d05a2b9d4e019bde8875c0088c46b6503d71bf1722910160405180910390a15050565b6135e3614979565b33600090815260096020526040812080548390811061360457613604615113565b600091825260209091206009909102016007810154909150600160a01b900460ff16156136675760405162461bcd60e51b81526020600482015260116024820152705374616b6520697320436f6d706c65746560781b6044820152606401610ee5565b60006136733384612dcd565b905081600301548110156136995760405162461bcd60e51b8152600401610ee5906152b7565b60008260030154826136ab919061513f565b9050806000036136f95760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b6044820152606401610ee5565b8083600301546137099190615193565b6003840181905583541161372d5760078301805460ff60a01b1916600160a01b1790555b336000908152600c60205260409020541561383b5760078301546001600160a01b039081166000818152600b60205260408082205490516302c68be360e31b815260048101939093529092670de0b6b3a7640000928592909116906316345f1890602401602060405180830381865afa1580156137ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137d29190615253565b6137dc9190615152565b6137e6919061517f565b336000908152600c6020526040902054909150811061381457336000908152600c6020526040812055613839565b336000908152600c60205260408120805483929061383390849061513f565b90915550505b505b60078301546001600160a01b03166000908152601060205260408120805483929061386790849061513f565b90915550506007830154613885906001600160a01b031633836149b1565b604080518281526000602082015233917f4a94c2c356e29a6583071e731bdacf2ca56565ba5efebcff6936eb7923b517219101611e3a565b6138e160405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152601360205260408120905b8154811015613992578382828154811061391757613917615113565b906000526020600020906003020160000154036139805781818154811061394057613940615113565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505050610dff565b8061398a816151a6565b9150506138fb565b5060405162461bcd60e51b815260206004820152604160248201527f57697468647261775374616b652077697468207468652073706563696669656460448201527f207374616b654964206e6f7420666f756e6420666f72207468697320757365726064820152601760f91b608482015260a401610ee5565b613a13614979565b6064811115613a645760405162461bcd60e51b815260206004820152601a60248201527f496e76616c69642072657374616b652070657263656e746167650000000000006044820152606401610ee5565b336000908152600860205260408120805484908110613a8557613a85615113565b906000526020600020906005020190508060000154600003613ade5760405162461bcd60e51b81526020600482015260126024820152714e6f20616d6f756e7420746f20636c61696d60701b6044820152606401610ee5565b8060030154421015613b2a5760405162461bcd60e51b815260206004820152601560248201527414dd185ad9481a5cc81cdd1a5b1b081b1bd8dad959605a1b6044820152606401610ee5565b80546000613b38338661280b565b9050613b448183615193565b915060006064613b548685615152565b613b5e919061517f565b90506000613b6c828561513f565b6000865560048601805460ff1916600117905590508015613c58578060126000828254613b999190615193565b90915550506003548111613bc7578060016002016000828254613bbc919061513f565b90915550613bcd9050565b60006003555b3360009081526013602090815260409182902082516060810184528a81529182018490526011549092820190613c039042615193565b9052815460018082018455600093845260209384902083516003909302019182558284015190820155604091820151600290910155518281523391600080516020615310833981519152910160405180910390a25b8115613d7f573360009081526015602052604081205415613c89575033600090815260156020526040902054613c97565b613c94336001612105565b90505b60086000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060a0016040528085815260200142815260200183815260200160016000015442613cea9190615193565b81526000602091820181905283546001808201865594825290829020835160059092020190815582820151938101939093556040808301516002850155606083015160038501556080909201516004909301805460ff1916931515939093179092555184815233917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d910160405180910390a2505b5050505050613d9b600160008051602061533083398151915255565b5050565b3360009081526007602052604090205460ff16613dce5760405162461bcd60e51b8152600401610ee5906151bf565b6001600160a01b038116613df45760405162461bcd60e51b8152600401610ee5906151e7565b6001600160a01b0316600090815260156020526040812055565b3360009081526007602052604090205460ff16613e3d5760405162461bcd60e51b8152600401610ee5906151bf565b81600003613e995760405162461bcd60e51b815260206004820152602360248201527f4c6f636b2074696d65206d7573742062652067726561746572207468616e207a60448201526265726f60e81b6064820152608401610ee5565b80600003613eff5760405162461bcd60e51b815260206004820152602d60248201527f50657263656e74616765207065722073746570206d757374206265206772656160448201526c746572207468616e207a65726f60981b6064820152608401610ee5565b612710613f0c82826152fb565b15613f645760405162461bcd60e51b815260206004820152602260248201527f50657263656e74616765206d757374206469766964652031303025206576656e6044820152616c7960f01b6064820152608401610ee5565b6000613f70838361517f565b90506000613f7e828661517f565b6001600160a01b0387166000908152600a60205260408120919250613fa39190614ce6565b60015b828111614018576001600160a01b0387166000908152600a60205260409081902081518083019092529080613fdb8486615152565b815260209081018890528254600181810185556000948552938290208351600290920201908155910151910155614011816151a6565b9050613fa6565b506040516001600160a01b038716907fde4b6ccc38b84f88129403b65a309f9b1c41d4c316bc2118d7614e449b9d4c4590600090a2505050505050565b6009602052816000526040600020818154811061407157600080fd5b6000918252602090912060099091020180546001820154600283015460038401546004850154600586015460068701546007880154600890980154969950949750929591949093916001600160a01b03811691600160a01b90910460ff16908a565b6001600160a01b03821660009081526009602052604081208054606092839290918590811061410457614104615113565b600091825260208083206007600990930201918201546001600160a01b0316808452600a9091526040832054919350918167ffffffffffffffff81111561414d5761414d6152a1565b604051908082528060200260200182016040528015614176578160200160208202803683370190505b50905060008267ffffffffffffffff811115614194576141946152a1565b6040519080825280602002602001820160405280156141bd578160200160208202803683370190505b50905060005b8381101561426a576001600160a01b0385166000908152600a602052604081208054839081106141f5576141f5615113565b90600052602060002090600202019050806000015487600601546142199190615193565b84838151811061422b5761422b615113565b602002602001018181525050806001015483838151811061424e5761424e615113565b602090810291909101015250614263816151a6565b90506141c3565b50909890975095505050505050565b6013602052816000526040600020818154811061429557600080fd5b600091825260209091206003909102018054600182015460029092015490935090915083565b3360009081526007602052604090205460ff166142ea5760405162461bcd60e51b8152600401610ee5906151bf565b601155565b600081815481106142ff57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b3360009081526007602052604090205460ff166143515760405162461bcd60e51b8152600401610ee5906151bf565b601455565b61435e614979565b33600090815260096020526040812080548390811061437f5761437f615113565b90600052602060002090600902019050600061439b3384610cea565b905081600401548110156143c15760405162461bcd60e51b8152600401610ee5906152b7565b60008260040154826143d3919061513f565b9050806000036144215760405162461bcd60e51b81526020600482015260196024820152784e6f2076657374656420616d6f756e7420746f20636c61696d60381b6044820152606401610ee5565b8083600401546144319190615193565b6004840155600783015461444f906001600160a01b031633836149b1565b60405181815233907f4e69fdc49495bcab2b4375781457ba16653a90eb4ffb6588351bdc39071433e290602001611e3a565b3360009081526007602052604090205460ff166144b05760405162461bcd60e51b8152600401610ee5906151bf565b8183106145145760405162461bcd60e51b815260206004820152602c60248201527f496e76616c69642072616e67653a206d696e546f6b656e73206d75737420626560448201526b203c206d6178546f6b656e7360a01b6064820152608401610ee5565b61451e8383614a06565b156145765760405162461bcd60e51b815260206004820152602260248201527f52616e6765206f7665726c6170732077697468206578697374696e6720746965604482015261727360f01b6064820152608401610ee5565b60005b60005481101561461d57836000828154811061459757614597615113565b9060005260206000209060030201600001541480156145d9575082600082815481106145c5576145c5615113565b906000526020600020906003020160010154145b1561460d5781600082815481106145f2576145f2615113565b90600052602060002090600302016002018190555050505050565b614616816151a6565b9050614579565b5060408051606081018252848152602081018481529181018381526000805460018101825590805291517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56360039093029283015591517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56482015590517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565909101556146c6614a95565b505050565b600080805b6001600160a01b03841660009081526008602052604090205481101561471c5760006146fc858361280b565b90506147088184615193565b92505080614715906151a6565b90506146d0565b5092915050565b3360009081526007602052604090205460ff166147525760405162461bcd60e51b8152600401610ee5906151bf565b806000036147935760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606401610ee5565b60086000836001600160a01b03166001600160a01b031681526020019081526020016000206040518060a0016040528083815260200142815260200160018001548152602001600160000154426147ea9190615193565b81526000602091820181905283546001808201865594825290829020835160059092020190815590820151928101929092556040810151600283015560608101516003808401919091556080909101516004909201805460ff1916921515929092179091555461485b908290615193565b6003556040518181526001600160a01b038316907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906020016111a1565b3360009081526007602052604090205460ff166148c85760405162461bcd60e51b8152600401610ee5906151bf565b6001600160a01b0381166148ee5760405162461bcd60e51b8152600401610ee5906151e7565b6001600160a01b03166000908152600f60205260409020805460ff19166001179055565b6040516001600160a01b0384811660248301528381166044830152606482018390526114049186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050614c24565b6000805160206153308339815191528054600119016149ab57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6040516001600160a01b038381166024830152604482018390526146c691859182169063a9059cbb90606401614947565b600160008051602061533083398151915255565b6149fe614c95565b611845614cde565b6000805b600054811015614a8b5760008181548110614a2757614a27615113565b9060005260206000209060030201600101548411158015614a6c575060008181548110614a5657614a56615113565b9060005260206000209060030201600001548310155b15614a7b576001915050610dff565b614a84816151a6565b9050614a0a565b5060009392505050565b60005b6000548110156116ed576000614aaf826001615193565b90505b600054811015614c135760008181548110614acf57614acf615113565b90600052602060002090600302016000015460008381548110614af457614af4615113565b9060005260206000209060030201600001541115614c01576000808381548110614b2057614b20615113565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905060008281548110614b6c57614b6c615113565b906000526020600020906003020160008481548110614b8d57614b8d615113565b90600052602060002090600302016000820154816000015560018201548160010155600282015481600201559050508060008381548110614bd057614bd0615113565b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020155905050505b80614c0b816151a6565b915050614ab2565b50614c1d816151a6565b9050614a98565b600080602060008451602086016000885af180614c47576040513d6000823e3d81fd5b50506000513d91508115614c5f578060011415614c6c565b6001600160a01b0384163b155b1561140457604051635274afe760e01b81526001600160a01b0385166004820152602401610ee5565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661184557604051631afcd79f60e31b815260040160405180910390fd5b6149e2614c95565b50805460008255600202906000526020600020908101906116ed91905b80821115614d1d5760008082556001820155600201614d03565b5090565b80356001600160a01b0381168114614d3857600080fd5b919050565b600060208284031215614d4f57600080fd5b61214e82614d21565b60008060408385031215614d6b57600080fd5b614d7483614d21565b946020939093013593505050565b600060208284031215614d9457600080fd5b5035919050565b60008060208385031215614dae57600080fd5b823567ffffffffffffffff80821115614dc657600080fd5b818501915085601f830112614dda57600080fd5b813581811115614de957600080fd5b86602060a083028501011115614dfe57600080fd5b60209290920196919550909350505050565b60008060208385031215614e2357600080fd5b823567ffffffffffffffff80821115614e3b57600080fd5b818501915085601f830112614e4f57600080fd5b813581811115614e5e57600080fd5b8660208260051b8501011115614dfe57600080fd5b600081518084526020808501945080840160005b83811015614ea357815187529582019590820190600101614e87565b509495945050505050565b606081526000614ec16060830186614e73565b8281036020840152614ed38186614e73565b915050826040830152949350505050565b60008060408385031215614ef757600080fd5b614f0083614d21565b915060208301358015158114614f1557600080fd5b809150509250929050565b60008060408385031215614f3357600080fd5b614f3c83614d21565b9150614f4a60208401614d21565b90509250929050565b602080825282518282018190526000919060409081850190868401855b82811015614ff45781518051855286810151878601528581015186860152606080820151908601526080808201519086015260a0808201519086015260c0808201519086015260e0808201516001600160a01b0316908601526101008082015115159086015261012090810151908501526101409093019290850190600101614f70565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015614ff457815180518552868101518786015285810151868601526060808201519086015260809081015115159085015260a0909301929085019060010161501e565b6000806040838503121561507757600080fd5b50508035926020909101359150565b60008060006060848603121561509b57600080fd5b6150a484614d21565b95602085013595506040909401359392505050565b6040815260006150cc6040830185614e73565b82810360208401526150de8185614e73565b95945050505050565b6000806000606084860312156150fc57600080fd5b505081359360208301359350604090920135919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610dff57610dff615129565b8082028115828204841417610dff57610dff615129565b634e487b7160e01b600052601260045260246000fd5b60008261518e5761518e615169565b500490565b80820180821115610dff57610dff615129565b6000600182016151b8576151b8615129565b5060010190565b6020808252600e908201526d139bdd08185d5d1a1bdc9a5e995960921b604082015260600190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b60208082526023908201527f416d6f756e74206d7573742062652067726561746572206d696e5374616b654c6040820152626f636b60e81b606082015260800190565b60006020828403121561526557600080fd5b5051919050565b6020808252818101527f496e73756666696369656e74207265776172647320696e2074686520706f6f6c604082015260600190565b634e487b7160e01b600052604160045260246000fd5b602080825260149082015273125b9d985b1a590818db185a5b48185b5bdd5b9d60621b604082015260600190565b634e487b7160e01b600052603160045260246000fd5b60008261530a5761530a615169565b50069056fe106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f72419b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a264697066735822122045358477ab3c3bdadb8fed55d327409e93a4df155bca5804b01e746c7266292a64736f6c63430008140033
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.