false
true
0

Contract Address Details

0x1d841B34F23712c25dab430cA27Dd64b7F9FEA8e

Token
414 ペグの始まり (414 🖨️)
Creator
0xa3a4a2–9210cb at 0xc7c339–db8717
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
2,346 Transactions
Transfers
0 Transfers
Gas Used
0
Last Balance Update
25892051
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
IcariaSmartToken




Optimization enabled
true
Compiler version
v0.8.28+commit.7893614a




Optimization runs
20
EVM Version
paris




Verified at
2025-05-31T09:09:36.722307Z

Constructor Arguments

0x00000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000a3a4a285c777ec2264cb49b586681f5a0f9210cb000000000000000000000000fb8eff739d9a4ded54e441f566c1a0aeb5b9e6480000000000000000000000000000000000000000033b2e3c9fd0803ce800000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000ed044a9cd942b6c32751a1c6a83f5e3e886375b3000000000000000000000000a3a4a285c777ec2264cb49b586681f5a0f9210cb00000000000000000000000057bc1bc5c40a903a7ecbcf06e224f47e301bf1b1000000000000000000000000000000000000000000000000000000000000001634313420e3839ae382b0e381aee5a78be381bee3828a00000000000000000000000000000000000000000000000000000000000000000000000000000000000b34313420f09f96a8efb88f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000463413c579d29c26d59a65312657dfce30d545a100000000000000000000000000000000000000000000000000000000000003690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d6c31ba0754c4383a41c0e9df042c62b5e918f6d00000000000000000000000000000000000000000000000000000000000003690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000003690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d177cb9efeea49a8b97ab1c72785a3a37abc9ff00000000000000000000000000000000000000000000000000000000000003690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000369000000000000000000000000463413c579d29c26d59a65312657dfce30d545a1000000000000000000000000000000000000000000000000000000000000036900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
              

contracts/icaria/IcariaSmartToken.sol

//
//
//
//       ██╗ ██████╗ █████╗ ██████╗ ██╗ █████╗     ███████╗ ██████╗ ██████╗  ██████╗ ███████╗
//       ██║██╔════╝██╔══██╗██╔══██╗██║██╔══██╗    ██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██╔════╝
//       ██║██║     ███████║██████╔╝██║███████║    █████╗  ██║   ██║██████╔╝██║  ███╗█████╗  
//       ██║██║     ██╔══██║██╔══██╗██║██╔══██║    ██╔══╝  ██║   ██║██╔══██╗██║   ██║██╔══╝  
//       ██║╚██████╗██║  ██║██║  ██║██║██║  ██║    ██║     ╚██████╔╝██║  ██║╚██████╔╝███████╗
//       ╚═╝ ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═╝    ╚═╝      ╚═════╝ ╚═╝  ╚═╝ ╚═════╝ ╚══════╝
//                                                                                 
//     
//                                                                             
// Forge
// Web: https://forge.icaria.pro
// Tg:  https://t.me/icariaforge 
// 
// Icaria
// Web: https://icaria.pro
// Tg:  https://t.me/icarusprc20
// X:   https://x.com/IcarusPRC20     
//

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ERC20 } from "../ERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IcariaRYManager } from "./IcariaRYManager.sol";
import { Ownable }from "@openzeppelin/contracts/access/Ownable.sol";
import { IUniswapV2Factory } from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import { IUniswapV2Router02 } from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import { IUniswapV2Pair } from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol";
import { IIcariaHelpers } from "./interfaces/IIcariaHelpers.sol";
import { IIcariaSmartTrader } from "./interfaces/IIcariaSmartTrader.sol";
import { IIcariaSmartTokenFactory } from "./interfaces/IIcariaSmartTokenFactory.sol";
import { IWETH } from "./interfaces/IWETH.sol";

contract IcariaSmartToken is ERC20, Ownable, IcariaRYManager {
  uint256 public constant tokenVersion = 2;
  uint256 public initialSupply;

  uint256 private constant GLOBAL_DIVIDER = 10000;
  address private icariaSmartTrader;
  address private deployer;
  address private factory;
  address[] private routers = [0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02, 0x165C3410fC91EF562C50559f7d2289fEbed552d9, 0xcC73b59F8D7b7c532703bDfea2808a28a488cF47, 0xeB45a3c4aedd0F47F345fB4c8A1802BB5740d725];
  mapping (address => bool) isTaxExcluded;
  uint256 private currentSwapAmount;
  uint256 private accumulatedIcariaFee;

  bool private icariaFeeEnabled = false;
  bool private shouldAccumulateIcariaFee = false; 
  bool private reflectionsEnabled = false;
  bool private yieldEnabled = false;
  bool private firstPairInteractionHappened = false;
  bool private processedTaxesInTx;

  IIcariaHelpers.Tax[] public taxes;

  constructor(
    string memory name_, 
    string memory symbol_,
    address _owner,
    address _mintTo, 
    uint256 _initialSupply, 
    IIcariaHelpers.Tax[] memory _taxes, 
    address _icariaSmartTrader,
    address _factory,
    address _helpers
  ) ERC20(name_, symbol_) Ownable(_owner) IcariaRYManager(_helpers) {
    _mint(_mintTo, _initialSupply);
    deployer = _mintTo;
    initialSupply = _initialSupply;
    icariaSmartTrader = _icariaSmartTrader;
    factory = _factory;
    if(_taxes.length > 0) {
      address[] memory _yieldTokens;
      icariaFeeEnabled = true;
      (shouldAccumulateIcariaFee, reflectionsEnabled, yieldEnabled, taxes, _yieldTokens) = IIcariaHelpers(helpers).taxesInitialize(_taxes);
      inititlizeTaxExclusions();
      if (reflectionsEnabled || yieldEnabled) initializeReflectionExclusions();
      for(uint256 i = 0; i < _yieldTokens.length; i++) {
        addYieldToken(_yieldTokens[i]);
      }
    }
  }

  function _transfer(address from, address to, uint256 value) internal override {
    processedTaxesInTx = false;
    if(isDeadAddress(to)) {
      super._burn(from, value);
      return;
    }

    if (taxes.length == 0 || !firstPairInteractionHappened || isTaxExcluded[from] || isTaxExcluded[to] || inSwap) {
      if(!firstPairInteractionHappened && isPair(to)) firstPairInteractionHappened = true;

      _claimYield(from, to);
      super._transfer(from, to, value);
      return;
    }
    
    if(isPair(to) && !isReflectionExcluded[to]) isReflectionExcluded[to] = true;
    
    currentSwapAmount = value;
    uint256 amountAfterTaxs = processTaxes(from, to, value);
    
    if (hasAccumulatedTaxes() && firstPairInteractionHappened && !inSwap && !processedTaxesInTx || shouldAccumulateIcariaFee ) {
      if(!isBuy(from, to)) {
        processAccumulatedTaxes();
        processedTaxesInTx = true;
      }
    }
    
    _claimYield(from, to);
    _claimReflections(from, to);
    
    super._transfer(from, to, amountAfterTaxs);
  }

  function processTaxes(address from, address to, uint256 amount) internal returns (uint256) {
    uint256 totalTaxAmount = 0;
    uint256 totalIcariaFee = 0;
    
    for (uint256 i = 0; i < taxes.length; i++) {
      IIcariaHelpers.Tax memory tax = taxes[i];
      
      uint256 taxAmount;
      uint256 icariaFee;

      if (tax.taxMoment == IIcariaHelpers.TaxMoment.Both) {
        (taxAmount, icariaFee) = calculateTaxAmount(amount, tax);
        processTaxType(from, taxAmount, tax);
      } else if (tax.taxMoment == IIcariaHelpers.TaxMoment.Buy && isBuy(from, to)) {
        (taxAmount, icariaFee) = calculateTaxAmount(amount, tax);
        processTaxType(from, taxAmount, tax);
      } else if (tax.taxMoment == IIcariaHelpers.TaxMoment.Sell && isSell(from, to)) {
        (taxAmount, icariaFee) = calculateTaxAmount(amount, tax);
        processTaxType(from, taxAmount, tax);
      }
      totalTaxAmount += taxAmount;
      totalIcariaFee += icariaFee;
    }
    
    if (totalIcariaFee > 0) {
      if (shouldAccumulateIcariaFee) {
        super._transfer(from, address(this), totalIcariaFee);
        accumulatedIcariaFee += totalIcariaFee;
      } else {
        super._transfer(from, getIcariaWallet(), totalIcariaFee);
      }
    }
    
    return amount - totalTaxAmount - totalIcariaFee;
  }

  function calculateTaxAmount(uint256 originalAmount, IIcariaHelpers.Tax memory tax) internal view returns (uint256 taxAmount, uint256 icariaFee) {
    return IIcariaHelpers(helpers).calculateTaxAmount(
      originalAmount, 
      tax.percentage, 
      getIcariaFee(),
      icariaFeeEnabled,
      GLOBAL_DIVIDER
    );
  }

  function processTaxType(address from, uint256 taxAmount, IIcariaHelpers.Tax memory tax) internal {
    if (tax.taxType == IIcariaHelpers.TaxType.Burn) {
      processBurnTax(from, taxAmount);
    } else if (tax.taxType == IIcariaHelpers.TaxType.Reflection) {
      processReflectionTax(from, taxAmount);
    } else if (tax.taxType == IIcariaHelpers.TaxType.Dev) {
      processDevTax(from, taxAmount, tax);
    } else if (tax.taxType == IIcariaHelpers.TaxType.ExternalBurn) {
      processExternalBurnTax(from, taxAmount, tax);
    } else if (tax.taxType == IIcariaHelpers.TaxType.Yield) {
      processYieldTax(from, taxAmount, tax);
    }
  }

  function processBurnTax(address from, uint256 taxAmount) internal {
    super._burn(from, taxAmount);
  }

  function processDevTax(address from, uint256 taxAmount, IIcariaHelpers.Tax memory tax) internal {
    if(!isTaxExcluded[tax.receiver]) isTaxExcluded[tax.receiver] = true;
    if (tax.rewardInPls) {
      super._transfer(from, address(this), taxAmount);
      taxes[tax.id].amountAccumulated += taxAmount;
    } else {
      super._transfer(from, tax.receiver, taxAmount);
    }
  }

  function processReflectionTax(address from, uint256 taxAmount) internal {
    super._transfer(from, address(this), taxAmount);
    uint256 supply = totalSupply() - balanceOf(address(this));
    if (supply > 0) {
      reflectionsPerShareAmount += (taxAmount * PRECISION) / supply;
    }
  }

  function processExternalBurnTax(address from, uint256 taxAmount, IIcariaHelpers.Tax memory tax) internal lockSwap {
    super._transfer(from, address(this), taxAmount);
    taxes[tax.id].amountAccumulated += taxAmount;
  }

  function processYieldTax(address from, uint256 taxAmount, IIcariaHelpers.Tax memory tax) internal lockSwap {
    super._transfer(from, address(this), taxAmount);
    taxes[tax.id].amountAccumulated += taxAmount;
  }

  function processAccumulatedTaxes() internal lockSwap {
    uint256 totalToSwap = 0;
    uint256 totalTokenTypes = 0;
    
    bool[] memory taxesToProcess = new bool[](taxes.length);
    uint256[] memory taxAmounts = new uint256[](taxes.length);
    
    for (uint256 i = 0; i < taxes.length; i++) {
      IIcariaHelpers.Tax storage tax = taxes[i];
      if (tax.amountAccumulated == 0) continue;
      if (tax.taxType == IIcariaHelpers.TaxType.ExternalBurn || 
        (tax.taxType == IIcariaHelpers.TaxType.Dev && tax.rewardInPls) || 
        tax.taxType == IIcariaHelpers.TaxType.Yield) {
        
        (uint256 swapAmount, uint256 newAccumulatedAmount) = IIcariaHelpers(helpers).getProcessingAmount(tax.amountAccumulated, currentSwapAmount);
        if (swapAmount > 0) {
            taxesToProcess[i] = true;
            taxAmounts[i] = swapAmount;
            totalToSwap += swapAmount;
            totalTokenTypes++;
        }
        taxes[i].amountAccumulated = newAccumulatedAmount;
      }
    }
    
    (/*address bestPair*/, address bestRouter) = IIcariaHelpers(helpers).getBestPair(address(this), wethAddress, routers);
    if (bestRouter == address(0)) return;
    (uint256 icariaToProcess, uint256 newAccumulatedIcariaAmount) = IIcariaHelpers(helpers).getProcessingAmount(accumulatedIcariaFee, currentSwapAmount);
    
    totalToSwap += icariaToProcess;
    if (totalToSwap == 0) return;
    uint256 icariaToTaxesRatio = icariaToProcess * PRECISION / totalToSwap;
    accumulatedIcariaFee = newAccumulatedIcariaAmount;
    
    _approve(address(this), icariaSmartTrader, totalToSwap);
    try IIcariaSmartTrader(icariaSmartTrader).swapExactTokensForTokensSupportingFeeOnTransferTokens(
        bestRouter,
        address(this),
        totalToSwap,
        getTokenWETHPath(address(this))
    ) {
    } catch {
      for (uint256 i = 0; i < taxes.length; i++) {
        if (taxesToProcess[i]) {
          taxes[i].amountAccumulated += taxAmounts[i];
        }
      }
      accumulatedIcariaFee += icariaToProcess;
      return;
    }
    uint256 totalWethReceived = IERC20(wethAddress).balanceOf(address(this)) - wethYieldBalance;
    uint256 _icariaFee = totalWethReceived * icariaToTaxesRatio / PRECISION;
    sendWETH(_icariaFee, getIcariaWallet());
    totalWethReceived -= _icariaFee;
    totalToSwap -= icariaToProcess;
    if (totalWethReceived == 0) return;
    
    for (uint256 i = 0; i < taxes.length; i++) {
      if (!taxesToProcess[i] || taxAmounts[i] == 0) continue;
      
      uint256 wethPortion = (taxAmounts[i] * totalWethReceived) / totalToSwap;
      IIcariaHelpers.Tax storage tax = taxes[i];
      
      if (tax.taxType == IIcariaHelpers.TaxType.ExternalBurn) {
        processExternalBurnWeth(wethPortion, tax);
      } else if (tax.taxType == IIcariaHelpers.TaxType.Dev && tax.rewardInPls) {
        sendWETH(wethPortion, tax.receiver);
      } else if (tax.taxType == IIcariaHelpers.TaxType.Yield) {
        processYieldWeth(wethPortion, tax);
      }
    }
  }

  function processExternalBurnWeth(uint256 wethAmount, IIcariaHelpers.Tax memory tax) internal {
    if (wethAmount == 0) return;
    
    if (tax.tokenAddress == wethAddress) {
      IERC20(wethAddress).transfer(tax.receiver, wethAmount);
      return;
    }
    (/*address bestTargetPair*/, address bestTargetRouter) = IIcariaHelpers(helpers).getBestPair(wethAddress, tax.tokenAddress, routers);
    
    IERC20(wethAddress).approve(icariaSmartTrader, wethAmount);
    try IIcariaSmartTrader(icariaSmartTrader).buyToken(bestTargetRouter, tax.receiver, wethAmount, getWETHBuyBurnPath(tax.tokenAddress)) {
    } catch {
      IERC20(wethAddress).transfer(tax.receiver, wethAmount);
    }
  }

  function sendWETH(uint256 wethAmount,  address receiver) internal {
    if (wethAmount == 0) return;
    try IWETH(wethAddress).withdraw(wethAmount){
      (bool success,) = receiver.call{value: wethAmount}("");
      if (!success) {
        IERC20(wethAddress).transfer(receiver, wethAmount);
      }
    } catch {
      IERC20(wethAddress).transfer(receiver, wethAmount);
    }
  }

  function processYieldWeth(uint256 wethAmount, IIcariaHelpers.Tax memory tax) internal {
    if (wethAmount == 0) return;
    
    if (tax.tokenAddress == wethAddress) {
      wethYieldBalance += wethAmount;
      uint256 tokenIndex = addYieldToken(tax.tokenAddress);
      uint256 supply = totalSupply() - balanceOf(address(this));
      if (supply > 0) {
        yieldTokens[tokenIndex].reflectionsPerShareAmount += (wethAmount * PRECISION) / supply;
      }
      return;
    }
    
    (/*address bestTargetPair*/, address bestTargetRouter) = IIcariaHelpers(helpers).getBestPair(wethAddress, tax.tokenAddress, routers);
    
    uint256 initialTokenBalance = IERC20(tax.tokenAddress).balanceOf(address(this));

    IERC20(wethAddress).approve(icariaSmartTrader, wethAmount);
    try IIcariaSmartTrader(icariaSmartTrader).buyToken(bestTargetRouter, address(this), wethAmount, getWETHBuyBurnPath(tax.tokenAddress)) {
      uint256 finalTokenBalance = IERC20(tax.tokenAddress).balanceOf(address(this));
      uint256 boughtAmount = finalTokenBalance - initialTokenBalance;
      
      if (boughtAmount > 0) {
        uint256 tokenIndex = addYieldToken(tax.tokenAddress);
        uint256 supply = totalSupply() - balanceOf(address(this));
        if (supply > 0) {
          yieldTokens[tokenIndex].reflectionsPerShareAmount += (boughtAmount * PRECISION) / supply;
        }
      }
    } catch {}
  }

  function _claimReflections(address from, address to) internal {
    if (!reflectionsEnabled) return;
    (uint256 fromAmount, uint256 toAmount, uint256 deployerAmount) = updateAndClaimReflections(from, to, deployer);
    if(fromAmount != 0){
      if(!isPair(from)){
        super._transfer(address(this), from, fromAmount);
      }
    }
    if(toAmount != 0){
      if(!isPair(to)){
        super._transfer(address(this), to, toAmount);
      }
    }
    if(deployerAmount != 0){
      super._transfer(address(this), deployer, deployerAmount);
    }
  }

  function initializeReflectionExclusions() internal {
    isReflectionExcluded[address(0)] = true;
    isReflectionExcluded[address(this)] = true;
    for (uint256 i = 0; i < routers.length; ) {
      isReflectionExcluded[routers[i]] = true;
      unchecked { i++; }
    }
  }
  function isDeadAddress(address _address) internal view returns (bool) {
    return IIcariaHelpers(helpers).isDeadAddress(_address);
  }

  function isPair(address _address) internal view returns (bool) {
    return IIcariaHelpers(helpers).isPair(_address, address(this));
  }

  function isBuy(address from, address to) internal view returns (bool) {
    return IIcariaHelpers(helpers).isBuy(from, to, address(this));
  }

  function isSell(address from, address to) internal view returns (bool) {
    return IIcariaHelpers(helpers).isSell(from, to, address(this));
  }

  function getProcessingAmount(uint256 accumulatedAmount) internal view returns (uint256 processAmount, uint256 newAccumulatedAmount) {
    return IIcariaHelpers(helpers).getProcessingAmount(accumulatedAmount, currentSwapAmount);
  }

  function getTokenWETHPath(address tokenAddress) internal view returns (address[] memory) {
    return IIcariaHelpers(helpers).getTokenWPLSPath(tokenAddress);
  }

  function getWETHBuyBurnPath(address tokenAddress) internal view returns (address[] memory) {
    return IIcariaHelpers(helpers).getWPLSBuyBurnPath(tokenAddress);
  }

  function getTaxes() public view returns (IIcariaHelpers.Tax[] memory) {
    return taxes;
  }

  function getIcariaFee() public view returns (uint256) {
    return IIcariaSmartTokenFactory(factory).ICARIA_FEE();
  }

  function getIcariaWallet() public view returns (address) {
    return IIcariaSmartTokenFactory(factory).ICARIA_WALLET();
  }

  function getAccumulatedIcariaFee() external view returns (uint256) {
    return accumulatedIcariaFee;
  }

  function getTotalTaxs() external view returns (uint256) {
    return IIcariaHelpers(helpers).getTotalTaxs(taxes);
  }

  function forceProcessAccumulatedTaxes() external onlyOwner {
    processAccumulatedTaxes();
  }

  function _claimYield(address from, address to) internal {
    if (yieldEnabled) {
      updateAndClaimYield(from, to, deployer);
    }
  }

  function claimYield() external returns (bool) {
    _claimYield(msg.sender, msg.sender);
    return true;
  }

  function hasAccumulatedTaxes() internal view returns (bool) {
    return IIcariaHelpers(helpers).hasAccumulatedTaxes(taxes);
  }

  function addTaxExclusion(address _address) external onlyOwner {
    isTaxExcluded[_address] = true;
  }

  function removeTaxExclusion(address _address) external onlyOwner {
    isTaxExcluded[_address] = false;
  }

  function inititlizeTaxExclusions() internal {
    isTaxExcluded[deployer] = true;
    isTaxExcluded[address(this)] = true;
    isTaxExcluded[icariaSmartTrader] = true;
  }
  
  receive() external payable {}
}
        

@openzeppelin/contracts/access/Ownable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
          

@openzeppelin/contracts/interfaces/draft-IERC6093.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC-20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC-721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC-1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
          

@openzeppelin/contracts/token/ERC20/IERC20.sol

// 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);
}
          

@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}
          

@openzeppelin/contracts/utils/Context.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
          

@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol

pragma solidity >=0.5.0;

interface IUniswapV2Factory {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint);

    function feeTo() external view returns (address);
    function feeToSetter() external view returns (address);

    function getPair(address tokenA, address tokenB) external view returns (address pair);
    function allPairs(uint) external view returns (address pair);
    function allPairsLength() external view returns (uint);

    function createPair(address tokenA, address tokenB) external returns (address pair);

    function setFeeTo(address) external;
    function setFeeToSetter(address) external;
}
          

@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol

pragma solidity >=0.5.0;

interface IUniswapV2Pair {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function kLast() external view returns (uint);

    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}
          

@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol

pragma solidity >=0.6.2;

interface IUniswapV2Router01 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountToken, uint amountETH);
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);
    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);

    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
          

@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol

pragma solidity >=0.6.2;

import './IUniswapV2Router01.sol';

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}
          

contracts/ERC20.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC-20
 * applications.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

    mapping(address account => mapping(address spender => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Skips emitting an {Approval} event indicating an allowance update. This is not
     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     *
     * ```solidity
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance < type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}
          

contracts/icaria/IcariaRYManager.sol

//
//
//
//       ██╗ ██████╗ █████╗ ██████╗ ██╗ █████╗     ███████╗ ██████╗ ██████╗  ██████╗ ███████╗
//       ██║██╔════╝██╔══██╗██╔══██╗██║██╔══██╗    ██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██╔════╝
//       ██║██║     ███████║██████╔╝██║███████║    █████╗  ██║   ██║██████╔╝██║  ███╗█████╗  
//       ██║██║     ██╔══██║██╔══██╗██║██╔══██║    ██╔══╝  ██║   ██║██╔══██╗██║   ██║██╔══╝  
//       ██║╚██████╗██║  ██║██║  ██║██║██║  ██║    ██║     ╚██████╔╝██║  ██║╚██████╔╝███████╗
//       ╚═╝ ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═╝    ╚═╝      ╚═════╝ ╚═╝  ╚═╝ ╚═════╝ ╚══════╝
//                                                                                 
//     
//                                                                             
// Forge
// Web: https://forge.icaria.pro
// Tg:  https://t.me/icariaforge 
// 
// Icaria
// Web: https://icaria.pro
// Tg:  https://t.me/icarusprc20
// X:   https://x.com/IcarusPRC20     
//

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import { IERC20 }from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IIcariaHelpers } from "./interfaces/IIcariaHelpers.sol";

contract IcariaRYManager {
  // For yield tax tokens
  struct UserYield {
    uint256 reflectionDebt;
  }
  struct YieldToken {
    address tokenAddress;
    uint256 reflectionsPerShareAmount;
  }
  YieldToken[] internal yieldTokens;
  
  uint256 internal PRECISION;
  uint256 internal reflectionsPerShareAmount;
  uint256 internal wethYieldBalance;
  address internal helpers;
  address internal wethAddress = 0xA1077a294dDE1B09bB078844df40758a5D0f9a27; // WPLS on PulseChain

  mapping(address => uint256) internal reflectionDebt;
  mapping(address => bool) public isReflectionExcluded;
  mapping(address => mapping(address => UserYield)) internal userYields;
  mapping(address => uint256[]) internal yieldTokenReflectionDebts;

  bool internal inSwap;

  modifier lockSwap() {
    inSwap = true;
    _;
    inSwap = false;
  }

  constructor(address _helpers) {
    PRECISION = 10**28;
    helpers = _helpers;
  }

  // ------------------------------------------ REFLECTIONS -------------------------------------------------//
  function getCurrentReflectionsPerShareAmount() external view returns (uint256) {
    return reflectionsPerShareAmount;
  }
  
  function isExcludedFromReflections(address account) public view returns (bool) {
    return isReflectionExcluded[account];
  }
  
  function pendingReflections(address account) public view returns (uint256) {
    if (isExcludedFromReflections(account)) {
      return 0;
    }
    return cleanPendingReflections(account);
  }

  function cleanPendingReflections(address account) internal view returns (uint256) {
    return IIcariaHelpers(helpers).cleanPendingReflections(
      account,
      address(this),
      reflectionsPerShareAmount,
      reflectionDebt[account],
      PRECISION
    );
  }


  function updateAndClaimReflections(address from, address to, address deployer) internal returns (uint256 fromAmount, uint256 toAmount, uint256 deployerAmount) {
    if (from == to) {
      fromAmount = isExcludedFromReflections(from) ? 0 : pendingReflections(from);
      toAmount = 0; // Set to zero to avoid double claiming
    } else {
      fromAmount = isExcludedFromReflections(from) ? 0 : pendingReflections(from);
      toAmount = isExcludedFromReflections(to) ? 0 : pendingReflections(to);
    }
    deployerAmount = cleanPendingReflections(deployer);
    reflectionDebt[deployer] = reflectionsPerShareAmount;
    reflectionDebt[from] = reflectionsPerShareAmount;
    reflectionDebt[to] = reflectionsPerShareAmount;
  }

  // function tokenPendingReflections() public view returns (uint256) {
  //     uint256 currentBalance = IERC20(address(this)).balanceOf(address(this));
  //     uint256 newReflectionDebt = reflectionsPerShareAmount;
  //     if (newReflectionDebt <= reflectionDebt[address(this)]) {
  //         return 0;
  //     }
  //     return (newReflectionDebt - reflectionDebt[address(this)]) * currentBalance / PRECISION;
  // }
  
  // ------------------------------------------ YIELD TOKENS REFLECTIONS -------------------------------------------------//
  
  function addYieldToken(address tokenAddress) internal returns (uint256 tokenIndex) {
    for (uint256 i = 0; i < yieldTokens.length; i++) {
      if (yieldTokens[i].tokenAddress == tokenAddress) {
        return i;
      }
    }
    
    yieldTokens.push(YieldToken({
      tokenAddress: tokenAddress,
      reflectionsPerShareAmount: 0
    }));
    
    return yieldTokens.length - 1;
  }
  
  function pendingYields(address account, uint256 tokenIndex) public view returns (uint256) {
    if (tokenIndex >= yieldTokenReflectionDebts[account].length) {
      return 0;
    }
    return IIcariaHelpers(helpers).pendingYields(
      account,
      address(this),
      yieldTokens[tokenIndex].reflectionsPerShareAmount,
      yieldTokenReflectionDebts[account][tokenIndex],
      PRECISION
    );
  }
  
  function updateAndClaimYield(address from, address to, address deployer) internal  {
    for (uint256 i = 0; i < yieldTokens.length; i++) {
      while (yieldTokenReflectionDebts[from].length <= i) {
        yieldTokenReflectionDebts[from].push(yieldTokens[i].reflectionsPerShareAmount);
      }
      while (yieldTokenReflectionDebts[to].length <= i) {
        yieldTokenReflectionDebts[to].push(yieldTokens[i].reflectionsPerShareAmount);
      }
      while (yieldTokenReflectionDebts[deployer].length <= i) {
        yieldTokenReflectionDebts[deployer].push(yieldTokens[i].reflectionsPerShareAmount);
      }
      
      uint256 fromAmount = isExcludedFromReflections(from) ? 0 : pendingYields(from, i);
      uint256 toAmount = 0;  // Initialize to 0
      
      if (from != to) {
        toAmount = isExcludedFromReflections(to) ? 0 : pendingYields(to, i);
      }

      uint256[] memory transferAmounts = new uint256[](2);
      address[] memory recipients = new address[](2);
      uint256 recipientCount = 0;
      if (fromAmount > 0) {
        transferAmounts[recipientCount] = fromAmount;
        recipients[recipientCount] = from;
        recipientCount++;
      }
      if (toAmount > 0) {
        transferAmounts[recipientCount] = toAmount;
        recipients[recipientCount] = to;
        recipientCount++;
      }

      for (uint256 j = 0; j < recipientCount; j++) {
        if(transferAmounts[j] > 0){
          try IERC20(yieldTokens[i].tokenAddress).transfer(recipients[j], transferAmounts[j]) {
            if(yieldTokens[i].tokenAddress == wethAddress) {
              wethYieldBalance -= transferAmounts[j];
            }
            yieldTokenReflectionDebts[recipients[j]][i] = yieldTokens[i].reflectionsPerShareAmount;
          } catch {
            
          }
        }
      }
    }
  }
  
  function getYieldTokens() public view returns (YieldToken[] memory) {
    return yieldTokens;
  }

  function getYieldTokenReflectionDebts(address account) public view returns (uint256[] memory) {
    return yieldTokenReflectionDebts[account];
  }
  

  // function getYieldsPerShare(uint256 index) public view returns (uint256)   {
  //     return yieldTokens[index].reflectionsPerShareAmount;
  // }
  
  // ------------------------------------------ END REFLECTIONS -----------------------------------------------//

  //-------------------------------------------- HELPERS FUNCTIONS -------------------------------------------------//
  //   function excludeFromReflections(address account) external onlyOwner {
  //     require(!isExcludedFromReflections(account), "Account already excluded");
  //     isReflectionExcluded[account] = true;
  //     updateAndClaimReflections(account);
  //   }

  

  //   function includeInReflections(address account) external onlyOwner {
  //     require(isReflectionExcluded[account], "Not excluded");
  //     isReflectionExcluded[account] = false;
  //     reflectionDebt[account] = (balanceOf(account) * reflectionsPerShareAmount) / PRECISION;
  //   }
}
          

contracts/icaria/interfaces/IIcariaHelpers.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IIcariaHelpers {
    enum TaxType { Burn, ExternalBurn, Dev, Reflection, Yield }
    enum TaxMoment { Both, Buy, Sell }

    struct Tax {
        uint256 id;
        TaxType taxType;
        TaxMoment taxMoment;
        uint256 percentage;
        address receiver;
        address tokenAddress;
        address burnAddress;
        bool rewardInPls;
        uint256 amountAccumulated;
    }

    function getBestPair(
        address tokenA, 
        address tokenB, 
        address[] memory routers
    ) external view returns (address bestPair, address bestRouter);

    function getTotalPairsBalance(address tokenA, address tokenB, address[] memory routers) external view returns (uint256);

    function isPair(address _address, address _tokenAddress) external view returns (bool);

    function isBuy(address _from, address _to, address _tokenAddress) external view returns (bool);

    function isSell(address _from, address _to, address _tokenAddress) external view returns (bool);

    function getTokenWPLSPath(address tokenAddress) external pure returns (address[] memory path);

    function getWPLSBuyBurnPath(address tokenAddress) external pure returns (address[] memory path);

    function getProcessingAmount(
        uint256 accumulatedAmount, 
        uint256 currentSwapAmount
    ) external pure returns (uint256 processAmount, uint256 newAccumulatedAmount);
    
    function calculateTaxAmount(
        uint256 originalAmount, 
        uint256 taxPercentage, 
        uint256 icariaFee, 
        bool icariaFeeEnabled,
        uint256 globalDivider
    ) external pure returns (uint256 taxAmount, uint256 icariaFeeAmount);
    
    function hasAccumulatedTaxes(Tax[] memory taxes) external pure returns (bool);
    
    function getTotalTaxs(Tax[] memory taxes) external pure returns (uint256);
    
    function cleanPendingReflections(
        address account,
        address tokenAddress,
        uint256 reflectionsPerShareAmount,
        uint256 reflectionDebt,
        uint256 precision
    ) external view returns (uint256);
    
    function pendingYields(
        address account, 
        address tokenAddress,
        uint256 reflectionsPerShareAmount,
        uint256 reflectionDebt,
        uint256 precision
    ) external view returns (uint256);

    function isExcludedFromTax(
        address from, 
        address to, 
        address icariaSmartTrader, 
        address deployer,
        address thisContract
    ) external pure returns (bool);

    function taxesInitialize(IIcariaHelpers.Tax[] memory _taxes) external pure returns (bool, bool, bool, IIcariaHelpers.Tax[] memory, address[] memory);

    function isDeadAddress(address _address) external pure returns (bool);

}
          

contracts/icaria/interfaces/IIcariaSmartTokenFactory.sol

//
//
//
//       ██╗ ██████╗ █████╗ ██████╗ ██╗ █████╗     ███████╗ ██████╗ ██████╗  ██████╗ ███████╗
//       ██║██╔════╝██╔══██╗██╔══██╗██║██╔══██╗    ██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██╔════╝
//       ██║██║     ███████║██████╔╝██║███████║    █████╗  ██║   ██║██████╔╝██║  ███╗█████╗  
//       ██║██║     ██╔══██║██╔══██╗██║██╔══██║    ██╔══╝  ██║   ██║██╔══██╗██║   ██║██╔══╝  
//       ██║╚██████╗██║  ██║██║  ██║██║██║  ██║    ██║     ╚██████╔╝██║  ██║╚██████╔╝███████╗
//       ╚═╝ ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═╝    ╚═╝      ╚═════╝ ╚═╝  ╚═╝ ╚═════╝ ╚══════╝
//                                                                                 
//     
//                                                                             
// Forge
// Web: https://forge.icaria.pro
// Tg:  https://t.me/icariaforge 
// 
// Icaria
// Web: https://icaria.pro
// Tg:  https://t.me/icarusprc20
// X:   https://x.com/IcarusPRC20     
//

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IIcariaSmartTokenFactory {
  function ICARIA_FEE() external view returns (uint256);
  function ICARIA_WALLET() external view returns (address);
}
          

contracts/icaria/interfaces/IIcariaSmartTrader.sol

//
//
//
//       ██╗ ██████╗ █████╗ ██████╗ ██╗ █████╗     ███████╗ ██████╗ ██████╗  ██████╗ ███████╗
//       ██║██╔════╝██╔══██╗██╔══██╗██║██╔══██╗    ██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██╔════╝
//       ██║██║     ███████║██████╔╝██║███████║    █████╗  ██║   ██║██████╔╝██║  ███╗█████╗  
//       ██║██║     ██╔══██║██╔══██╗██║██╔══██║    ██╔══╝  ██║   ██║██╔══██╗██║   ██║██╔══╝  
//       ██║╚██████╗██║  ██║██║  ██║██║██║  ██║    ██║     ╚██████╔╝██║  ██║╚██████╔╝███████╗
//       ╚═╝ ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═╝    ╚═╝      ╚═════╝ ╚═╝  ╚═╝ ╚═════╝ ╚══════╝
//                                                                                 
//     
//                                                                             
// Forge
// Web: https://forge.icaria.pro
// Tg:  https://t.me/icariaforge 
// 
// Icaria
// Web: https://icaria.pro
// Tg:  https://t.me/icarusprc20
// X:   https://x.com/IcarusPRC20     
//

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IIcariaSmartTrader {
  function swapExactTokensForTokensSupportingFeeOnTransferTokens(
    address _router,
    address _receiver,
    uint256 amountIn,
    address[] memory path
  ) external;
  
  function swapExactTokensForETHSupportingFeeOnTransferTokens(
    address _router,
    address _receiver,
    uint256 amountIn,
    address[] calldata path
  ) external;

  function buyToken(
    address _router,
    address _receiver,
    uint256 amountIn,
    address[] memory path
  ) external;
}
          

contracts/icaria/interfaces/IWETH.sol

//
//
//
//       ██╗ ██████╗ █████╗ ██████╗ ██╗ █████╗     ███████╗ ██████╗ ██████╗  ██████╗ ███████╗
//       ██║██╔════╝██╔══██╗██╔══██╗██║██╔══██╗    ██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██╔════╝
//       ██║██║     ███████║██████╔╝██║███████║    █████╗  ██║   ██║██████╔╝██║  ███╗█████╗  
//       ██║██║     ██╔══██║██╔══██╗██║██╔══██║    ██╔══╝  ██║   ██║██╔══██╗██║   ██║██╔══╝  
//       ██║╚██████╗██║  ██║██║  ██║██║██║  ██║    ██║     ╚██████╔╝██║  ██║╚██████╔╝███████╗
//       ╚═╝ ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═╝    ╚═╝      ╚═════╝ ╚═╝  ╚═╝ ╚═════╝ ╚══════╝
//                                                                                 
//     
//                                                                             
// Forge
// Web: https://forge.icaria.pro
// Tg:  https://t.me/icariaforge 
// 
// Icaria
// Web: https://icaria.pro
// Tg:  https://t.me/icarusprc20
// X:   https://x.com/IcarusPRC20     
//

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IWETH {
  function withdraw(uint256 wad) external;
}
          

Compiler Settings

{"viaIR":true,"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":20,"enabled":true},"libraries":{},"evmVersion":"paris"}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"string","name":"name_","internalType":"string"},{"type":"string","name":"symbol_","internalType":"string"},{"type":"address","name":"_owner","internalType":"address"},{"type":"address","name":"_mintTo","internalType":"address"},{"type":"uint256","name":"_initialSupply","internalType":"uint256"},{"type":"tuple[]","name":"_taxes","internalType":"struct IIcariaHelpers.Tax[]","components":[{"type":"uint256","name":"id","internalType":"uint256"},{"type":"uint8","name":"taxType","internalType":"enum IIcariaHelpers.TaxType"},{"type":"uint8","name":"taxMoment","internalType":"enum IIcariaHelpers.TaxMoment"},{"type":"uint256","name":"percentage","internalType":"uint256"},{"type":"address","name":"receiver","internalType":"address"},{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"address","name":"burnAddress","internalType":"address"},{"type":"bool","name":"rewardInPls","internalType":"bool"},{"type":"uint256","name":"amountAccumulated","internalType":"uint256"}]},{"type":"address","name":"_icariaSmartTrader","internalType":"address"},{"type":"address","name":"_factory","internalType":"address"},{"type":"address","name":"_helpers","internalType":"address"}]},{"type":"error","name":"ERC20InsufficientAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"allowance","internalType":"uint256"},{"type":"uint256","name":"needed","internalType":"uint256"}]},{"type":"error","name":"ERC20InsufficientBalance","inputs":[{"type":"address","name":"sender","internalType":"address"},{"type":"uint256","name":"balance","internalType":"uint256"},{"type":"uint256","name":"needed","internalType":"uint256"}]},{"type":"error","name":"ERC20InvalidApprover","inputs":[{"type":"address","name":"approver","internalType":"address"}]},{"type":"error","name":"ERC20InvalidReceiver","inputs":[{"type":"address","name":"receiver","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSender","inputs":[{"type":"address","name":"sender","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSpender","inputs":[{"type":"address","name":"spender","internalType":"address"}]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addTaxExclusion","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"claimYield","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"forceProcessAccumulatedTaxes","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getAccumulatedIcariaFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentReflectionsPerShareAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getIcariaFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getIcariaWallet","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct IIcariaHelpers.Tax[]","components":[{"type":"uint256","name":"id","internalType":"uint256"},{"type":"uint8","name":"taxType","internalType":"enum IIcariaHelpers.TaxType"},{"type":"uint8","name":"taxMoment","internalType":"enum IIcariaHelpers.TaxMoment"},{"type":"uint256","name":"percentage","internalType":"uint256"},{"type":"address","name":"receiver","internalType":"address"},{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"address","name":"burnAddress","internalType":"address"},{"type":"bool","name":"rewardInPls","internalType":"bool"},{"type":"uint256","name":"amountAccumulated","internalType":"uint256"}]}],"name":"getTaxes","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTotalTaxs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getYieldTokenReflectionDebts","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct IcariaRYManager.YieldToken[]","components":[{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"uint256","name":"reflectionsPerShareAmount","internalType":"uint256"}]}],"name":"getYieldTokens","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialSupply","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExcludedFromReflections","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isReflectionExcluded","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pendingReflections","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pendingYields","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"tokenIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeTaxExclusion","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"id","internalType":"uint256"},{"type":"uint8","name":"taxType","internalType":"enum IIcariaHelpers.TaxType"},{"type":"uint8","name":"taxMoment","internalType":"enum IIcariaHelpers.TaxMoment"},{"type":"uint256","name":"percentage","internalType":"uint256"},{"type":"address","name":"receiver","internalType":"address"},{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"address","name":"burnAddress","internalType":"address"},{"type":"bool","name":"rewardInPls","internalType":"bool"},{"type":"uint256","name":"amountAccumulated","internalType":"uint256"}],"name":"taxes","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokenVersion","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"receive","stateMutability":"payable"}]
              

Contract Creation Code

Verify & Publish
0x60808060405234610bb157613fff803803809161001c8285610bb6565b8339810161012082820312610bb15781516001600160401b038111610bb15781610047918401610bd9565b60208301519092906001600160401b038111610bb15782610069918301610bd9565b61007560408301610c48565b9361008260608401610c48565b608084015160a085015190959192916001600160401b038211610bb1576100aa918601610c80565b956100b760c08601610c48565b936100d16101006100ca60e08901610c48565b9701610c48565b835190936001600160401b0382116109cc5760035490600182811c92168015610ba7575b6020831014610ac55781601f849311610b58575b50602090601f8311600114610af057600092610ae5575b50508160011b916000199060031b1c1916176003555b8051906001600160401b0382116109cc5760045490600182811c92168015610adb575b6020831014610ac55781601f849311610a6b575b50602090601f8311600114610a03576000926109f8575b50508160011b916000199060031b1c1916176004555b6001600160a01b03169081156109e257600580546001600160a01b03198116841790915560405192906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3600b80546001600160a01b031990811673a1077a294dde1b09bb078844df40758a5d0f9a27179091556b204fce5e3e25026110000000600755600a80549091166001600160a01b0392909216919091179055608081016001600160401b038111828210176109cc576040527398bf93ebf5c380c0e6ae8e192a7e2ae08edacc02815273165c3410fc91ef562c50559f7d2289febed552d9602082015273cc73b59f8d7b7c532703bdfea2808a28a488cf47604082015273eb45a3c4aedd0f47f345fb4c8a1802bb5740d7256060820152601554600460155580600410610987575b50601560005260206000209060005b6004811061096a5750506019805464ffffffffff19169055506001600160a01b03169283156109545760025481810180911161093e57600255600093808552846020526040852082815401905580857fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020604051868152a3601380546001600160a01b03199081169290921790556011919091556012805482166001600160a01b03938416179055601480549091169290911691909117905581516103b1575b6040516131019081610ebe8239f35b600160ff1960195416176019558060018060a01b03600a5416926040519384916316bc2cf360e21b83526024830160206004850152815180915260206044850192019085905b8082106108885750505082809103915afa91821561087b57818290839284908596610785575b5080519068010000000000000000821161077157601a5482601a558083106106d7575b50601a86528590600080516020613fdf833981519152906020015b8383106105cf575050505062ff00009063ff00000061ff0060195492151560081b1694151560181b169063ffffff0019161791151560101b16171760195560018060a01b03601354168152601660205260408120600160ff19825416179055308152601660205260408120600160ff1982541617905560018060a01b03601254168152601660205260408120600160ff1982541617905560195460ff8160101c169081156105c1575b50610547575b805b825181101561053d57600581901b83016020015160019190610536906001600160a01b0316610ddc565b500161050c565b50505038806103a2565b808052600d60205260408120600160ff19825416179055308152600d60205260408120600160ff19825416179055805b6015548110156105bb57600080516020613fbf8339815191528101546001600160a01b03168252600d60205260408220805460ff1916600190811790915501610577565b5061050a565b60ff915060181c1638610504565b80518051835560018301602082015160058110156106c3578154604084015160038110156106af5761ff0060089190911b1660ff9290921661ffff1991909116171790556060810151600284015560808101516003840180546001600160a01b039283166001600160a01b03199182161790915560a080840151600487018054918516919093161790915560c083015160058601805460e086015160ff60a01b90151590941b93909316919093166001600160a81b031990921691909117179055610100015160068301556001929092019160079091019060200161045b565b634e487b7160e01b8d52602160045260248dfd5b634e487b7160e01b8b52602160045260248bfd5b8060070290600782040361075d578260070260078104840361074957601a8852600080516020613fdf83398151915291820191015b8181106107195750610440565b8088600792558860018201558860028201558860038201558860048201558860058201558860068201550161070c565b634e487b7160e01b88526011600452602488fd5b634e487b7160e01b87526011600452602487fd5b634e487b7160e01b86526041600452602486fd5b9550505050503d8082843e61079a8184610bb6565b82019160a081840312610877576107b081610c73565b6107bc60208301610c73565b6107c860408401610c73565b60608401519092906001600160401b03811161086f57866107ea918601610c80565b608085015190946001600160401b03821161087357019580601f8801121561086f57865161081781610c5c565b97610825604051998a610bb6565b8189526020808a019260051b82010192831161086b57602001905b828210610853575050509091923861041d565b6020809161086084610c48565b815201910190610840565b8780fd5b8580fd5b8680fd5b5080fd5b50604051903d90823e3d90fd5b929194509294508351805182526020810151600581101561092a5760208301526040810151600381101561092a5782610100602093610120936040600197015260608101516060840152858060a01b036080820151166080840152858060a01b0360a08201511660a0840152858060a01b0360c08201511660c084015260e0810151151560e084015201516101008201520194019201918594928794926103f7565b634e487b7160e01b88526021600452602488fd5b634e487b7160e01b600052601160045260246000fd5b63ec442f0560e01b600052600060045260246000fd5b81516001600160a01b0316818401556020909101906001016102e1565b60156000526109c690600080516020613fbf833981519152017f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec479610d90565b386102d2565b634e487b7160e01b600052604160045260246000fd5b631e4fbdf760e01b600052600060045260246000fd5b015190503880610184565b600460009081528281209350601f198516905b818110610a535750908460019594939210610a3a575b505050811b0160045561019a565b015160001960f88460031b161c19169055388080610a2c565b92936020600181928786015181550195019301610a16565b6004600052610ab5907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f850160051c81019160208610610abb575b601f0160051c0190610d90565b3861016d565b9091508190610aa8565b634e487b7160e01b600052602260045260246000fd5b91607f1691610159565b015190503880610120565b600360009081528281209350601f198516905b818110610b405750908460019594939210610b27575b505050811b01600355610136565b015160001960f88460031b161c19169055388080610b19565b92936020600181928786015181550195019301610b03565b6003600052610ba1907fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f850160051c81019160208610610abb57601f0160051c0190610d90565b38610109565b91607f16916100f5565b600080fd5b601f909101601f19168101906001600160401b038211908210176109cc57604052565b81601f82011215610bb1578051906001600160401b0382116109cc5760405192610c0d601f8401601f191660200185610bb6565b82845260208383010111610bb15760005b828110610c3357505060206000918301015290565b80602080928401015182828701015201610c1e565b51906001600160a01b0382168203610bb157565b6001600160401b0381116109cc5760051b60200190565b51908115158203610bb157565b81601f82011215610bb157805190610c9782610c5c565b92610ca56040519485610bb6565b8284526020610120818601940283010191818311610bb157602001925b828410610cd0575050505090565b61012084830312610bb1576040519061012082016001600160401b038111838210176109cc576040528451825260208501516005811015610bb15760208301526040850151906003821015610bb15782602092604061012095015260608701516060820152610d4160808801610c48565b6080820152610d5260a08801610c48565b60a0820152610d6360c08801610c48565b60c0820152610d7460e08801610c73565b60e0820152610100870151610100820152815201930192610cc2565b818110610d9b575050565b60008155600101610d90565b600654811015610dc657600660005260206000209060011b0190600090565b634e487b7160e01b600052603260045260246000fd5b6006549060005b828110610e92575060408051919082016001600160401b038111838210176109cc576040526001600160a01b0316815260006020820190815291680100000000000000008110156109cc57806001610e3e9201600655610da7565b929092610e7c57905182546001600160a01b0319166001600160a01b03919091161782555160019190910155600654600019810190811161093e5790565b634e487b7160e01b600052600060045260246000fd5b610e9b81610da7565b50546001600160a01b03838116911614610eb757600101610de3565b9150509056fe608080604052600436101561001d575b50361561001b57600080fd5b005b60003560e01c90816306fdde0314610c1557508063095ea7b314610bef57806318160ddd14610bd157806323b872dd14610ae45780632973ef2d1461099f578063313ce56714610983578063378dc3dc14610965578063406cf2291461094a5780634f30800d1461092c57806356cdad1d1461090e5780635f75baf6146108f3578063695d69b3146108d05780636a2072d414610816578063709df63c1461072357806370a08231146106e9578063715018a61461068c5780638453ef99146106525780638da5cb5b146106295780639045be581461029957806395d89b41146105225780639b165f4e146104dd578063a9059cbb146104ac578063c5be2bc7146103f1578063cb78c16314610358578063dd62ed3e14610307578063e4f8d62e146102d8578063e6375d3e14610299578063eb50c06114610257578063f2fde38b146101cd578063f56b4d05146101a05763fec4ff171461017f573861000f565b3461019b57600036600319011261019b57602060405160028152f35b600080fd5b3461019b57600036600319011261019b5760206101bb61112c565b6040516001600160a01b039091168152f35b3461019b57602036600319011261019b576101e6610d19565b6101ee6119f9565b6001600160a01b0316801561024157600580546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b631e4fbdf760e01b600052600060045260246000fd5b3461019b57602036600319011261019b57610270610d19565b6102786119f9565b6001600160a01b03166000908152601660205260409020805460ff19169055005b3461019b57602036600319011261019b576001600160a01b036102ba610d19565b16600052600d602052602060ff604060002054166040519015158152f35b3461019b57604036600319011261019b5760206102ff6102f6610d19565b60243590611077565b604051908152f35b3461019b57604036600319011261019b57610320610d19565b610328610d2f565b6001600160a01b039182166000908152600160209081526040808320949093168252928352819020549051908152f35b3461019b57600036600319011261019b57600a54604051625f8d8f60e81b81529060209082906001600160a01b0316818061039560048201610f52565b03915afa80156103e5576000906103b2575b602090604051908152f35b506020813d6020116103dd575b816103cc60209383610ddb565b8101031261019b57602090516103a7565b3d91506103bf565b6040513d6000823e3d90fd5b3461019b57602036600319011261019b57600435601a5481101561019b5761041b61012091610d75565b5080549060ff600182015491600281015460018060a01b0360038301541660018060a01b0360048401541691610479600660058601549501549660405198895261046a60208a01888316610d45565b8660408a019160081c16610d68565b6060870152608086015260a0808601919091526001600160a01b03821660c08601521c16151560e0830152610100820152f35b3461019b57604036600319011261019b576104d26104c8610d19565b6024359033611198565b602060405160018152f35b3461019b57602036600319011261019b576104f6610d19565b6104fe6119f9565b6001600160a01b03166000908152601660205260409020805460ff19166001179055005b3461019b57600036600319011261019b5760405160006004548060011c9060018116801561061f575b60208310811461060b578285529081156105e75750600114610588575b6105848361057881850382610ddb565b60405191829182610cd0565b0390f35b600460009081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b8082106105cd57509091508101602001610578610568565b9192600181602092548385880101520191019092916105b5565b60ff191660208086019190915291151560051b840190910191506105789050610568565b634e487b7160e01b84526022600452602484fd5b91607f169161054b565b3461019b57600036600319011261019b576005546040516001600160a01b039091168152602090f35b3461019b57600036600319011261019b5761066b6119f9565b600160ff196010541617601055610680611bd2565b6010805460ff19169055005b3461019b57600036600319011261019b576106a56119f9565b600580546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461019b57602036600319011261019b576001600160a01b0361070a610d19565b1660005260006020526020604060002054604051908152f35b3461019b57600036600319011261019b5760065461074081610dfc565b9061074e6040519283610ddb565b808252600660009081526020830191907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f835b8383106107e25784866040519182916020830190602084525180915260408301919060005b8181106107b4575050500390f35b825180516001600160a01b0316855260209081015181860152869550604090940193909201916001016107a6565b600260206001926040516107f581610daa565b848060a01b0386541681528486015483820152815201920192019190610781565b3461019b57602036600319011261019b576001600160a01b03610837610d19565b16600052600f60205260406000206040518060208354918281520190819360005260206000209060005b8181106108ba5750505081610877910382610ddb565b6040519182916020830190602084525180915260408301919060005b8181106108a1575050500390f35b8251845285945060209384019390920191600101610893565b8254845260209093019260019283019201610861565b3461019b57602036600319011261019b5760206102ff6108ee610d19565b610f20565b3461019b57600036600319011261019b5760206102ff610eb9565b3461019b57600036600319011261019b576020601854604051908152f35b3461019b57600036600319011261019b576020600854604051908152f35b3461019b57600036600319011261019b576104d2333361166f565b3461019b57600036600319011261019b576020601154604051908152f35b3461019b57600036600319011261019b57602060405160128152f35b3461019b57600036600319011261019b57601a546109bc81610dfc565b906109ca6040519283610ddb565b808252601a60009081526020830191907f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e835b838310610ac65784866040519182916020830190602084525180915260408301919060005b818110610a30575050500390f35b919350916020610120600192610100875180518352610a558582015186850190610d45565b610a6760408201516040850190610d68565b60608101516060840152858060a01b036080820151166080840152858060a01b0360a08201511660a0840152858060a01b0360c08201511660c084015260e0810151151560e08401520151610100820152019401910191849392610a22565b60076020600192610ad685610e13565b8152019201920191906109fd565b3461019b57606036600319011261019b57610afd610d19565b610b05610d2f565b6001600160a01b0382166000818152600160209081526040808320338452909152902054909260443592916000198110610b45575b506104d29350611198565b838110610bb4578415610b9e573315610b88576104d2946000526001602052604060002060018060a01b0333166000526020528360406000209103905584610b3a565b634a1406b160e11b600052600060045260246000fd5b63e602df0560e01b600052600060045260246000fd5b8390637dc7a0d960e11b6000523360045260245260445260646000fd5b3461019b57600036600319011261019b576020600254604051908152f35b3461019b57604036600319011261019b576104d2610c0b610d19565b602435903361223a565b3461019b57600036600319011261019b5760006003548060011c90600181168015610cc6575b60208310811461060b578285529081156105e75750600114610c67576105848361057881850382610ddb565b600360009081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b939250905b808210610cac57509091508101602001610578610568565b919260018160209254838588010152019101909291610c94565b91607f1691610c3b565b91909160208152825180602083015260005b818110610d03575060409293506000838284010152601f8019910116010190565b8060208092870101516040828601015201610ce2565b600435906001600160a01b038216820361019b57565b602435906001600160a01b038216820361019b57565b906005821015610d525752565b634e487b7160e01b600052602160045260246000fd5b906003821015610d525752565b601a54811015610d9457601a6000526007602060002091020190600090565b634e487b7160e01b600052603260045260246000fd5b604081019081106001600160401b03821117610dc557604052565b634e487b7160e01b600052604160045260246000fd5b90601f801991011681019081106001600160401b03821117610dc557604052565b6001600160401b038111610dc55760051b60200190565b9060405161012081018181106001600160401b03821117610dc557604052809280548252600181015460ff8116906005821015610d525760ff91602085015260081c166003811015610d525760408301526002810154606083015260038101546001600160a01b0390811660808401526004820154811660a080850191909152600583015491821660c08501521c60ff16151560e0830152600601546101009190910152565b60145460405163441062ed60e01b815290602090829060049082906001600160a01b03165afa9081156103e557600091610ef1575090565b90506020813d602011610f18575b81610f0c60209383610ddb565b8101031261019b575190565b3d9150610eff565b6001600160a01b0381166000908152600d602052604090205460ff16610f4c57610f49906119ab565b90565b50600090565b6040602082019160208152601a548093520190601a60005260206000209060005b818110610f805750505090565b909192600761012060019286548152610fb684880154610fa66020840160ff8316610d45565b60ff604084019160081c16610d68565b60028701546060820152600387015460a085811b86900391821660808401526004890154821681840152600589015491821660c08401521c60ff16151560e08201526006870154610100820152019401929101610f73565b600654811015610d9457600660005260206000209060011b0190600090565b8054821015610d945760005260206000200190600090565b6001600160a01b0391821681529116602082015260408101919091526060810191909152608081019190915260a00190565b6001600160a01b0381166000818152600f6020526040902054919291821015611110576020916110cc60018060a01b03600a54169160016110b78261100e565b50015493600052600f8552604060002061102d565b90549060031b1c91600754946110fa6040519687958694859463a89055e560e01b8652309060048701611045565b03915afa9081156103e557600091610ef1575090565b505050600090565b51906001600160a01b038216820361019b57565b6014546040516327ab5d0f60e01b815290602090829060049082906001600160a01b03165afa9081156103e557600091611164575090565b90506020813d602011611190575b8161117f60209383610ddb565b8101031261019b57610f4990611118565b3d9150611172565b6019805460ff60281b19169055600a54604051639ca7068f60e01b81526001600160a01b03848116600483018190529596959260209183916024918391165afa9081156103e557600091611650575b5061164357601a54158015611633575b8015611611575b80156115f9575b80156115ed575b61159f5761121983612350565b80611586575b611568575b5083601755600090600080925b601a548410156113f25761124d61124785610d75565b50610e13565b90600080604084018051906003821015610d52576000916112a257505050508161129361128e611299936112836001968d612d4c565b92909294838a612ddf565b611a59565b93611a59565b93019290611231565b805160038110156113de57600114806113ce575b156112d657505050508161129361128e611299936112836001968d612d4c565b939192935160038110156113ba576002149081611325575b5091611299939160019593611309575b611293929350611a59565b611293925061131d9150611283848d612d4c565b8392506112fe565b905061135760208860018060a01b03600a54168c60405180958194829363154b004960e31b845230916004850161245e565b03915afa9182156113ae5791611299959391600197959391611380575b509193955091936112ee565b6113a1915060203d81116113a7575b6113998183610ddb565b8101906122a1565b38611374565b503d61138f565b604051903d90823e3d90fd5b634e487b7160e01b82526021600452602482fd5b506113d98a89612481565b6112b6565b634e487b7160e01b83526021600452602483fd5b61140993506114049192959683611529575b611bc5565b600a5460405163ca497e2360e01b8152939192919060209085906001600160a01b0316818061143a60048201610f52565b03915afa80156103e5576114889460009161150a575b50806114fb575b806114ee575b806114de575b80156114cf575b61148a575b611479828261166f565b61148382826124cb565b6123af565b565b6114948282612481565b61146f57600160ff1960105416176010556114ad611bd2565b6010805460ff191690556019805460ff60281b1916600160281b17905561146f565b5060ff60195460081c1661146a565b5060ff60195460281c1615611463565b5060ff601054161561145d565b5060ff60195460201c16611457565b611523915060203d6020116113a7576113998183610ddb565b38611450565b60195460081c60ff1615611556576115428430896123af565b61154e84601854611a59565b601855611bc5565b6114048461156261112c565b896123af565b600052600d6020526040600020600160ff1982541617905538611224565b5080600052600d60205260ff604060002054161561121f565b509061148892939160195460ff8160201c1615806115de575b6115c8575b50611483828261166f565b60ff60201b1916600160201b17601955386115bd565b506115e883612350565b6115b8565b5060ff6010541661120c565b5080600052601660205260ff60406000205416611205565b506001600160a01b03821660009081526016602052604090205460ff166111fe565b5060ff60195460201c16156111f7565b50611488929391506122b9565b611669915060203d6020116113a7576113998183610ddb565b386111e7565b60ff60195460181c16611680575050565b6013546001600160a01b0390811693600093838316939281169290916060916040918587141591905b60065489101561199f575b87600052600f60205288604060002054116116f35787600052600f6020526116ee604060002060016116e58c61100e565b5001549061261c565b6116b4565b9692939495965b87600052600f60205288604060002054116117305787600052600f60205261172b604060002060016116e58c61100e565b6116fa565b96939495965b89600052600f602052886040600020541161176c5789600052600f602052611767604060002060016116e58c61100e565b611736565b979694929695939587600052600d60205260ff604060002054166000146119905760005b600084611969575b6040516117a58882610ddb565b6002815286366020830137604051916117be8984610ddb565b600283528736602085013760009380611948575b508061191f575b5060005b8381106117f15750505050600101976116a9565b806117fe60019284611a45565b5161180a575b016117dd565b61185d60206118188861100e565b505460a085901b859003908116906118308589611a45565b51169061183d8588611a45565b5191600060405180968195829463a9059cbb60e01b84526004840161263f565b03925af19081611903575b5015611804576118778661100e565b5054600b5460a084901b8490039081169116146118e5575b6118e08261189c8861100e565b500154838060a01b036118af8488611a45565b5116600052600f6020526118c788604060002061102d565b90919082549060031b91821b91600019901b1916179055565b611804565b6118fb6118f28285611a45565b51600954611bc5565b60095561188f565b61191a9060203d81116113a7576113998183610ddb565b611868565b92819361192f8261194194611a45565b528a61193b8285611a45565b52611a7c565b91386117d9565b90935061195482611a38565b528a61195f83611a38565b52600192386117d2565b888152600d60205260ff604082205416600003611798575061198b8288611077565b611798565b61199a8183611077565b611790565b98505050505050505050565b602060018060a01b03600a54166008549060018060a01b038416600052600c835260406000205491600754946110fa60405196879586948594631d2fa43b60e11b8652309060048701611045565b6005546001600160a01b03163303611a0d57565b63118cdaa760e01b6000523360045260246000fd5b919082604091031261019b576020825192015190565b805115610d945760200190565b8051821015610d945760209160051b010190565b91908201809211611a6657565b634e487b7160e01b600052601160045260246000fd5b6000198114611a665760010190565b919082604091031261019b57610f496020611aa584611118565b9301611118565b6001600160a01b039182168152911660208201526060604082018190526015805491830182905260009081526080909201917f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec47591905b818110611b0f5750505090565b82546001600160a01b0316845260209093019260019283019201611b02565b81810292918115918404141715611a6657565b8115611b4b570490565b634e487b7160e01b600052601260045260246000fd5b60a091936020936080830195600180861b03168352600180851b03168483015260408201526080606082015284518094520192019060005b818110611ba65750505090565b82516001600160a01b0316845260209384019390920191600101611b99565b91908203918211611a6657565b6000908182601a5491611be483610dfc565b91611bf26040519384610ddb565b838352601f19611c0185610dfc565b01366020850137611c1184610dfc565b93611c1f6040519586610ddb565b808552611c2e601f1991610dfc565b0136602086013785915b601a54831015611de057611c4b83610d75565b50926006840154938415611dd45760ff600182015416600581101580611dc05760018214928315611d97575b508215611d72575b5050611c95575b6001919293505b019190611c38565b600a546017546040805163059b6d4760e21b81526004810197909752602487019190915290859060449082906001600160a01b03165afa938415611d675788908995611d34575b5080611d00575b5060019192936006611cf483610d75565b50015583929150611c86565b611d27611d2d9160019485611d15868b611a45565b5281611d21868c611a45565b52611a59565b93611a7c565b9291611ce3565b9050611d5891945060403d8111611d60575b611d508183610ddb565b810190611a22565b939038611cdc565b503d611d46565b6040513d8a823e3d90fd5b909150611d83576004143880611c7f565b634e487b7160e01b89526021600452602489fd5b8b935060028314915081611dae575b509138611c77565b60ff91506005015460a01c1638611da6565b634e487b7160e01b8b52602160045260248bfd5b50600191929350611c8d565b600a54600b5460408051632a8ddb2f60e01b815296996001600160a01b03938416999790965094509184918291611e1c91163060048401611aac565b0381895afa9182156121f3578392612207575b506001600160a01b038216156121fe5760406018546044601754918351998a93849263059b6d4760e21b8452600484015260248301525afa9081156121f357839684926121ca575b5086611e8291611a59565b9182156121c057602490611ea184611e9c6007548b611b2e565b611b41565b92601855611eba8460018060a01b03601254163061223a565b601254600a546040516343d7ef9f60e11b8152306004820152936001600160a01b03928316939288928692918391165afa9283156121b5578693612191575b50813b1561218d579185918583611f299560405196879586948593637e18437960e01b8552309060048601611b61565b03925af19081612179575b50611f9e5750505b601a54811015611f895780611f5360019287611a45565b51611f5f575b01611f3c565b611f698185611a45565b51611f826006611f7884610d75565b5001918254611a59565b9055611f59565b50925050611f9990601854611a59565b601855565b909294959391956024602060018060a01b03600b5416604051928380926370a0823160e01b82523060048301525afa908115611d67578891612145575b5061201e92612006611ffd611ff66120189460095490611bc5565b9283611b2e565b60075490611b41565b9061140461201261112c565b836126db565b93611bc5565b92821561213d57855b601a548110156121345761203b8183611a45565b51158015612122575b61211a5761206085611e9c8661205a8588611a45565b51611b2e565b61206982610d75565b509060ff6001830154166005811015612106576001939291908481036120a2575061209661209c92610e13565b90612b53565b01612027565b60028114806120f5575b156120cd57506120c8916003858060a01b0391015416906126db565b61209c565b6004146120dc575b505061209c565b6120e86120ee92610e13565b90612831565b38806120d5565b5060ff600584015460a01c166120ac565b634e487b7160e01b8a52602160045260248afd5b60019061209c565b5061212d8184611a45565b5115612044565b50505050509050565b505050509050565b90506020813d602011612171575b8161216060209383610ddb565b8101031261019b575161201e611fdb565b3d9150612153565b8461218691959295610ddb565b9238611f34565b8580fd5b6121ae9193503d8088833e6121a68183610ddb565b81019061265a565b9138611ef9565b6040513d88823e3d90fd5b5050505092505050565b611e8297506121e991925060403d604011611d6057611d508183610ddb565b9096509086611e77565b6040513d85823e3d90fd5b50505092505050565b61222a91925060403d604011612233575b6122228183610ddb565b810190611a8b565b90509038611e2f565b503d612218565b6001600160a01b0316908115610b9e576001600160a01b0316918215610b885760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260018252604060002085600052825280604060002055604051908152a3565b9081602091031261019b5751801515810361019b5790565b6001600160a01b0316801561233a5760009181835282602052604083205481811061232157817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef926020928587528684520360408620558060025403600255604051908152a3565b6064939263391434e360e21b8452600452602452604452fd5b634b637e8f60e11b600052600060045260246000fd5b600a54604051630d5c7b5d60e41b81526001600160a01b0392831660048201523060248201529160209183916044918391165afa9081156103e557600091612396575090565b610f49915060203d6020116113a7576113998183610ddb565b6001600160a01b031690811561233a576001600160a01b031691821561244857600082815280602052604081205482811061242e5791604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815280845220818154019055604051908152a3565b916064928463391434e360e21b8452600452602452604452fd5b63ec442f0560e01b600052600060045260246000fd5b6001600160a01b0391821681529181166020830152909116604082015260600190565b600a54604051636468b51760e01b81529260209284926001600160a01b031691839182916124b5913091906004850161245e565b03915afa9081156103e557600091612396575090565b9060ff60195460101c1615612618576013546001600160a01b03838116939181169190831660008582036125c2575084600052600d60205260ff604060002054166000146125b45760005b906000935b612524816119ab565b6008546000928352600c60205260408084208290559883528883208190559282529690205580612596575b505080612578575b5050806125615750565b60135461148891906001600160a01b0316306123af565b61258182612350565b6125575761258f91306123af565b3880612557565b61259f82612350565b61254f576125ad91306123af565b388061254f565b6125bd82610f20565b612516565b858152600d602052604081205460ff1615612609575b9080600052600d60205260ff604060002054166000146125fb5760005b9361251b565b61260485610f20565b6125f5565b5061261382610f20565b6125d8565b5050565b80549190600160401b831015610dc557826118c79160016114889501815561102d565b6001600160a01b039091168152602081019190915260400190565b60208183031261019b578051906001600160401b03821161019b57019080601f8301121561019b57815161268d81610dfc565b9261269b6040519485610ddb565b81845260208085019260051b82010192831161019b57602001905b8282106126c35750505090565b602080916126d084611118565b8152019101906126b6565b9060009082156127c757600b546001600160a01b0316803b1561282d57828091602460405180948193632e1a7d4d60e01b83528960048401525af19081612819575b5061278257600b5460405163a9059cbb60e01b81529360209285926001600160a01b03169183918691839161275691906004840161263f565b03925af19081156113ae575061276a575b50565b6127679060203d6020116113a7576113998183610ddb565b8180808086855af13d15612814573d6001600160401b03811161280057604051906127b7601f8201601f191660200183610ddb565b81528360203d92013e5b156127cc575b505050565b600b5460405163a9059cbb60e01b81529360209285926001600160a01b03169183918691839161275691906004840161263f565b634e487b7160e01b84526041600452602484fd5b6127c1565b8361282691949294610ddb565b913861271d565b8280fd5b60009181156127c75760a0018051600b549192916001600160a01b03908116911614612b0957600a54600b54835160408051632a8ddb2f60e01b815294936001600160a01b039384169391928692918216918391829161289691168760048401611aac565b03915afa928315612afe579060249392918693612adb575b5084516040516370a0823160e01b81523060048201529460209186919082906001600160a01b03165afa9384156121b5578694612aa6575b5060125460405163095ea7b360e01b81529160209183919082908a90829061291c9089906001600160a01b03166004840161263f565b03925af180156121b557612a89575b5060125484516001600160a01b0391821692916129489116613045565b92823b15612a855791612978939187809460405196879586948593632d4d638360e11b8552309060048601611b61565b03925af19081612a71575b5061298d57505050565b81516040516370a0823160e01b81523060048201529190602090839060249082906001600160a01b03165afa8015612a66578490612a32575b6129d09250611bc5565b90816129db57505050565b51612a08906129f2906001600160a01b0316612f79565b9260406002549130815280602052205490611bc5565b9081156127c757611f78612a28612a2e93611e9c60019460075490611b2e565b9361100e565b9055565b506020823d602011612a5e575b81612a4c60209383610ddb565b8101031261019b576129d091516129c6565b3d9150612a3f565b6040513d86823e3d90fd5b84612a7e91959295610ddb565b9238612983565b8680fd5b612aa19060203d6020116113a7576113998183610ddb565b61292b565b9093506020813d602011612ad3575b81612ac260209383610ddb565b8101031261218d57519260206128e6565b3d9150612ab5565b612af591935060403d604011612233576122228183610ddb565b905091386128ae565b6040513d87823e3d90fd5b906129f2612b2f91612b1d84600954611a59565b600955516001600160a01b0316612f79565b9081612b3a57505050565b611f78612a28612a2e93611e9c60019460075490611b2e565b9060009082156127c75760a081018051600b549192916001600160a01b0390811691168114612d155750600a54600b54835160408051632a8ddb2f60e01b815294936001600160a01b0393841693919286929182169183918291612bbc91168760048401611aac565b03915afa928315612afe579086918694612ce9575b5060125460405163095ea7b360e01b8152926020928492909183918a918391612c0791906001600160a01b03166004840161263f565b03925af18015612afe57612ccc575b506012546080919091018051935190936001600160a01b039283169290811691612c409116613045565b92823b1561218d57918691868094612c6e60405197889687958694632d4d638360e11b865260048601611b61565b03925af19081612cb8575b506127c757600b54905160405163a9059cbb60e01b81529360209285926001600160a01b0391821692849287928492612756929091166004840161263f565b83612cc591949294610ddb565b9138612c79565b612ce49060203d6020116113a7576113998183610ddb565b612c16565b602091945091612d0a612c079360403d604011612233576122228183610ddb565b905094915091612bd1565b60809091015160405163a9059cbb60e01b81529460209350859291839186918391612756916001600160a01b03166004840161263f565b600a546060909201516001600160a01b0392909216929160409160a490612d71610eb9565b9560ff6019541685519788958694632b8d28ef60e21b86526004860152602485015260448401521515606483015261271060848301525afa9182156103e557600090600093612dbf57509190565b9050612ddb91925060403d604011611d6057611d508183610ddb565b9091565b909160208101908151916005831015610d5257600092612e065750505090611488916122b9565b80516005811015612f655785929190600303612e6d575050612e2d90612e429330906123af565b60406002549130815280602052205490611bc5565b9081612e4c575050565b612e6891611e9c612e609260075490611b2e565b600854611a59565b600855565b8091949392505160058110156113de57600203612f1057506080830180516001600160a01b031682526016602052604082205490919060ff1615612ee9575b5060e083015115612ed35750611f78612a2e92612ecd8560069430906123af565b51610d75565b516114889392506001600160a01b0316906123af565b81516001600160a01b03168152601660205260409020805460ff1916600117905538612eac565b809492945160058110156113de57600103612f305750506114889261309a565b51906005821015612f515750600414612f4857505050565b6114889261309a565b634e487b7160e01b81526021600452602490fd5b634e487b7160e01b84526021600452602484fd5b6006549060005b82811061301a575060405190612f9582610daa565b6001600160a01b0316815260006020820190815291600160401b811015610dc557806001612fc6920160065561100e565b92909261300457905182546001600160a01b0319166001600160a01b039190911617825551600191909101556006546000198101908111611a665790565b634e487b7160e01b600052600060045260246000fd5b6130238161100e565b50546001600160a01b0383811691161461303f57600101612f80565b91505090565b600a546040516377a9efe360e11b81526001600160a01b0392831660048201529160009183916024918391165afa9081156103e557600091613085575090565b610f4991503d806000833e6121a68183610ddb565b611f788293612ecd6130bd94600694600160ff19601054161760105530906123af565b905560ff196010541660105556fea264697066735822122005404067a9c75949def711aac05d72403bef69300432efb25296511b50eaf2dd64736f6c634300081c003355f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec475057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e00000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000a3a4a285c777ec2264cb49b586681f5a0f9210cb000000000000000000000000fb8eff739d9a4ded54e441f566c1a0aeb5b9e6480000000000000000000000000000000000000000033b2e3c9fd0803ce800000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000ed044a9cd942b6c32751a1c6a83f5e3e886375b3000000000000000000000000a3a4a285c777ec2264cb49b586681f5a0f9210cb00000000000000000000000057bc1bc5c40a903a7ecbcf06e224f47e301bf1b1000000000000000000000000000000000000000000000000000000000000001634313420e3839ae382b0e381aee5a78be381bee3828a00000000000000000000000000000000000000000000000000000000000000000000000000000000000b34313420f09f96a8efb88f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000463413c579d29c26d59a65312657dfce30d545a100000000000000000000000000000000000000000000000000000000000003690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d6c31ba0754c4383a41c0e9df042c62b5e918f6d00000000000000000000000000000000000000000000000000000000000003690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000003690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d177cb9efeea49a8b97ab1c72785a3a37abc9ff00000000000000000000000000000000000000000000000000000000000003690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000369000000000000000000000000463413c579d29c26d59a65312657dfce30d545a1000000000000000000000000000000000000000000000000000000000000036900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Deployed ByteCode

0x608080604052600436101561001d575b50361561001b57600080fd5b005b60003560e01c90816306fdde0314610c1557508063095ea7b314610bef57806318160ddd14610bd157806323b872dd14610ae45780632973ef2d1461099f578063313ce56714610983578063378dc3dc14610965578063406cf2291461094a5780634f30800d1461092c57806356cdad1d1461090e5780635f75baf6146108f3578063695d69b3146108d05780636a2072d414610816578063709df63c1461072357806370a08231146106e9578063715018a61461068c5780638453ef99146106525780638da5cb5b146106295780639045be581461029957806395d89b41146105225780639b165f4e146104dd578063a9059cbb146104ac578063c5be2bc7146103f1578063cb78c16314610358578063dd62ed3e14610307578063e4f8d62e146102d8578063e6375d3e14610299578063eb50c06114610257578063f2fde38b146101cd578063f56b4d05146101a05763fec4ff171461017f573861000f565b3461019b57600036600319011261019b57602060405160028152f35b600080fd5b3461019b57600036600319011261019b5760206101bb61112c565b6040516001600160a01b039091168152f35b3461019b57602036600319011261019b576101e6610d19565b6101ee6119f9565b6001600160a01b0316801561024157600580546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b631e4fbdf760e01b600052600060045260246000fd5b3461019b57602036600319011261019b57610270610d19565b6102786119f9565b6001600160a01b03166000908152601660205260409020805460ff19169055005b3461019b57602036600319011261019b576001600160a01b036102ba610d19565b16600052600d602052602060ff604060002054166040519015158152f35b3461019b57604036600319011261019b5760206102ff6102f6610d19565b60243590611077565b604051908152f35b3461019b57604036600319011261019b57610320610d19565b610328610d2f565b6001600160a01b039182166000908152600160209081526040808320949093168252928352819020549051908152f35b3461019b57600036600319011261019b57600a54604051625f8d8f60e81b81529060209082906001600160a01b0316818061039560048201610f52565b03915afa80156103e5576000906103b2575b602090604051908152f35b506020813d6020116103dd575b816103cc60209383610ddb565b8101031261019b57602090516103a7565b3d91506103bf565b6040513d6000823e3d90fd5b3461019b57602036600319011261019b57600435601a5481101561019b5761041b61012091610d75565b5080549060ff600182015491600281015460018060a01b0360038301541660018060a01b0360048401541691610479600660058601549501549660405198895261046a60208a01888316610d45565b8660408a019160081c16610d68565b6060870152608086015260a0808601919091526001600160a01b03821660c08601521c16151560e0830152610100820152f35b3461019b57604036600319011261019b576104d26104c8610d19565b6024359033611198565b602060405160018152f35b3461019b57602036600319011261019b576104f6610d19565b6104fe6119f9565b6001600160a01b03166000908152601660205260409020805460ff19166001179055005b3461019b57600036600319011261019b5760405160006004548060011c9060018116801561061f575b60208310811461060b578285529081156105e75750600114610588575b6105848361057881850382610ddb565b60405191829182610cd0565b0390f35b600460009081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b8082106105cd57509091508101602001610578610568565b9192600181602092548385880101520191019092916105b5565b60ff191660208086019190915291151560051b840190910191506105789050610568565b634e487b7160e01b84526022600452602484fd5b91607f169161054b565b3461019b57600036600319011261019b576005546040516001600160a01b039091168152602090f35b3461019b57600036600319011261019b5761066b6119f9565b600160ff196010541617601055610680611bd2565b6010805460ff19169055005b3461019b57600036600319011261019b576106a56119f9565b600580546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461019b57602036600319011261019b576001600160a01b0361070a610d19565b1660005260006020526020604060002054604051908152f35b3461019b57600036600319011261019b5760065461074081610dfc565b9061074e6040519283610ddb565b808252600660009081526020830191907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f835b8383106107e25784866040519182916020830190602084525180915260408301919060005b8181106107b4575050500390f35b825180516001600160a01b0316855260209081015181860152869550604090940193909201916001016107a6565b600260206001926040516107f581610daa565b848060a01b0386541681528486015483820152815201920192019190610781565b3461019b57602036600319011261019b576001600160a01b03610837610d19565b16600052600f60205260406000206040518060208354918281520190819360005260206000209060005b8181106108ba5750505081610877910382610ddb565b6040519182916020830190602084525180915260408301919060005b8181106108a1575050500390f35b8251845285945060209384019390920191600101610893565b8254845260209093019260019283019201610861565b3461019b57602036600319011261019b5760206102ff6108ee610d19565b610f20565b3461019b57600036600319011261019b5760206102ff610eb9565b3461019b57600036600319011261019b576020601854604051908152f35b3461019b57600036600319011261019b576020600854604051908152f35b3461019b57600036600319011261019b576104d2333361166f565b3461019b57600036600319011261019b576020601154604051908152f35b3461019b57600036600319011261019b57602060405160128152f35b3461019b57600036600319011261019b57601a546109bc81610dfc565b906109ca6040519283610ddb565b808252601a60009081526020830191907f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e835b838310610ac65784866040519182916020830190602084525180915260408301919060005b818110610a30575050500390f35b919350916020610120600192610100875180518352610a558582015186850190610d45565b610a6760408201516040850190610d68565b60608101516060840152858060a01b036080820151166080840152858060a01b0360a08201511660a0840152858060a01b0360c08201511660c084015260e0810151151560e08401520151610100820152019401910191849392610a22565b60076020600192610ad685610e13565b8152019201920191906109fd565b3461019b57606036600319011261019b57610afd610d19565b610b05610d2f565b6001600160a01b0382166000818152600160209081526040808320338452909152902054909260443592916000198110610b45575b506104d29350611198565b838110610bb4578415610b9e573315610b88576104d2946000526001602052604060002060018060a01b0333166000526020528360406000209103905584610b3a565b634a1406b160e11b600052600060045260246000fd5b63e602df0560e01b600052600060045260246000fd5b8390637dc7a0d960e11b6000523360045260245260445260646000fd5b3461019b57600036600319011261019b576020600254604051908152f35b3461019b57604036600319011261019b576104d2610c0b610d19565b602435903361223a565b3461019b57600036600319011261019b5760006003548060011c90600181168015610cc6575b60208310811461060b578285529081156105e75750600114610c67576105848361057881850382610ddb565b600360009081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b939250905b808210610cac57509091508101602001610578610568565b919260018160209254838588010152019101909291610c94565b91607f1691610c3b565b91909160208152825180602083015260005b818110610d03575060409293506000838284010152601f8019910116010190565b8060208092870101516040828601015201610ce2565b600435906001600160a01b038216820361019b57565b602435906001600160a01b038216820361019b57565b906005821015610d525752565b634e487b7160e01b600052602160045260246000fd5b906003821015610d525752565b601a54811015610d9457601a6000526007602060002091020190600090565b634e487b7160e01b600052603260045260246000fd5b604081019081106001600160401b03821117610dc557604052565b634e487b7160e01b600052604160045260246000fd5b90601f801991011681019081106001600160401b03821117610dc557604052565b6001600160401b038111610dc55760051b60200190565b9060405161012081018181106001600160401b03821117610dc557604052809280548252600181015460ff8116906005821015610d525760ff91602085015260081c166003811015610d525760408301526002810154606083015260038101546001600160a01b0390811660808401526004820154811660a080850191909152600583015491821660c08501521c60ff16151560e0830152600601546101009190910152565b60145460405163441062ed60e01b815290602090829060049082906001600160a01b03165afa9081156103e557600091610ef1575090565b90506020813d602011610f18575b81610f0c60209383610ddb565b8101031261019b575190565b3d9150610eff565b6001600160a01b0381166000908152600d602052604090205460ff16610f4c57610f49906119ab565b90565b50600090565b6040602082019160208152601a548093520190601a60005260206000209060005b818110610f805750505090565b909192600761012060019286548152610fb684880154610fa66020840160ff8316610d45565b60ff604084019160081c16610d68565b60028701546060820152600387015460a085811b86900391821660808401526004890154821681840152600589015491821660c08401521c60ff16151560e08201526006870154610100820152019401929101610f73565b600654811015610d9457600660005260206000209060011b0190600090565b8054821015610d945760005260206000200190600090565b6001600160a01b0391821681529116602082015260408101919091526060810191909152608081019190915260a00190565b6001600160a01b0381166000818152600f6020526040902054919291821015611110576020916110cc60018060a01b03600a54169160016110b78261100e565b50015493600052600f8552604060002061102d565b90549060031b1c91600754946110fa6040519687958694859463a89055e560e01b8652309060048701611045565b03915afa9081156103e557600091610ef1575090565b505050600090565b51906001600160a01b038216820361019b57565b6014546040516327ab5d0f60e01b815290602090829060049082906001600160a01b03165afa9081156103e557600091611164575090565b90506020813d602011611190575b8161117f60209383610ddb565b8101031261019b57610f4990611118565b3d9150611172565b6019805460ff60281b19169055600a54604051639ca7068f60e01b81526001600160a01b03848116600483018190529596959260209183916024918391165afa9081156103e557600091611650575b5061164357601a54158015611633575b8015611611575b80156115f9575b80156115ed575b61159f5761121983612350565b80611586575b611568575b5083601755600090600080925b601a548410156113f25761124d61124785610d75565b50610e13565b90600080604084018051906003821015610d52576000916112a257505050508161129361128e611299936112836001968d612d4c565b92909294838a612ddf565b611a59565b93611a59565b93019290611231565b805160038110156113de57600114806113ce575b156112d657505050508161129361128e611299936112836001968d612d4c565b939192935160038110156113ba576002149081611325575b5091611299939160019593611309575b611293929350611a59565b611293925061131d9150611283848d612d4c565b8392506112fe565b905061135760208860018060a01b03600a54168c60405180958194829363154b004960e31b845230916004850161245e565b03915afa9182156113ae5791611299959391600197959391611380575b509193955091936112ee565b6113a1915060203d81116113a7575b6113998183610ddb565b8101906122a1565b38611374565b503d61138f565b604051903d90823e3d90fd5b634e487b7160e01b82526021600452602482fd5b506113d98a89612481565b6112b6565b634e487b7160e01b83526021600452602483fd5b61140993506114049192959683611529575b611bc5565b600a5460405163ca497e2360e01b8152939192919060209085906001600160a01b0316818061143a60048201610f52565b03915afa80156103e5576114889460009161150a575b50806114fb575b806114ee575b806114de575b80156114cf575b61148a575b611479828261166f565b61148382826124cb565b6123af565b565b6114948282612481565b61146f57600160ff1960105416176010556114ad611bd2565b6010805460ff191690556019805460ff60281b1916600160281b17905561146f565b5060ff60195460081c1661146a565b5060ff60195460281c1615611463565b5060ff601054161561145d565b5060ff60195460201c16611457565b611523915060203d6020116113a7576113998183610ddb565b38611450565b60195460081c60ff1615611556576115428430896123af565b61154e84601854611a59565b601855611bc5565b6114048461156261112c565b896123af565b600052600d6020526040600020600160ff1982541617905538611224565b5080600052600d60205260ff604060002054161561121f565b509061148892939160195460ff8160201c1615806115de575b6115c8575b50611483828261166f565b60ff60201b1916600160201b17601955386115bd565b506115e883612350565b6115b8565b5060ff6010541661120c565b5080600052601660205260ff60406000205416611205565b506001600160a01b03821660009081526016602052604090205460ff166111fe565b5060ff60195460201c16156111f7565b50611488929391506122b9565b611669915060203d6020116113a7576113998183610ddb565b386111e7565b60ff60195460181c16611680575050565b6013546001600160a01b0390811693600093838316939281169290916060916040918587141591905b60065489101561199f575b87600052600f60205288604060002054116116f35787600052600f6020526116ee604060002060016116e58c61100e565b5001549061261c565b6116b4565b9692939495965b87600052600f60205288604060002054116117305787600052600f60205261172b604060002060016116e58c61100e565b6116fa565b96939495965b89600052600f602052886040600020541161176c5789600052600f602052611767604060002060016116e58c61100e565b611736565b979694929695939587600052600d60205260ff604060002054166000146119905760005b600084611969575b6040516117a58882610ddb565b6002815286366020830137604051916117be8984610ddb565b600283528736602085013760009380611948575b508061191f575b5060005b8381106117f15750505050600101976116a9565b806117fe60019284611a45565b5161180a575b016117dd565b61185d60206118188861100e565b505460a085901b859003908116906118308589611a45565b51169061183d8588611a45565b5191600060405180968195829463a9059cbb60e01b84526004840161263f565b03925af19081611903575b5015611804576118778661100e565b5054600b5460a084901b8490039081169116146118e5575b6118e08261189c8861100e565b500154838060a01b036118af8488611a45565b5116600052600f6020526118c788604060002061102d565b90919082549060031b91821b91600019901b1916179055565b611804565b6118fb6118f28285611a45565b51600954611bc5565b60095561188f565b61191a9060203d81116113a7576113998183610ddb565b611868565b92819361192f8261194194611a45565b528a61193b8285611a45565b52611a7c565b91386117d9565b90935061195482611a38565b528a61195f83611a38565b52600192386117d2565b888152600d60205260ff604082205416600003611798575061198b8288611077565b611798565b61199a8183611077565b611790565b98505050505050505050565b602060018060a01b03600a54166008549060018060a01b038416600052600c835260406000205491600754946110fa60405196879586948594631d2fa43b60e11b8652309060048701611045565b6005546001600160a01b03163303611a0d57565b63118cdaa760e01b6000523360045260246000fd5b919082604091031261019b576020825192015190565b805115610d945760200190565b8051821015610d945760209160051b010190565b91908201809211611a6657565b634e487b7160e01b600052601160045260246000fd5b6000198114611a665760010190565b919082604091031261019b57610f496020611aa584611118565b9301611118565b6001600160a01b039182168152911660208201526060604082018190526015805491830182905260009081526080909201917f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec47591905b818110611b0f5750505090565b82546001600160a01b0316845260209093019260019283019201611b02565b81810292918115918404141715611a6657565b8115611b4b570490565b634e487b7160e01b600052601260045260246000fd5b60a091936020936080830195600180861b03168352600180851b03168483015260408201526080606082015284518094520192019060005b818110611ba65750505090565b82516001600160a01b0316845260209384019390920191600101611b99565b91908203918211611a6657565b6000908182601a5491611be483610dfc565b91611bf26040519384610ddb565b838352601f19611c0185610dfc565b01366020850137611c1184610dfc565b93611c1f6040519586610ddb565b808552611c2e601f1991610dfc565b0136602086013785915b601a54831015611de057611c4b83610d75565b50926006840154938415611dd45760ff600182015416600581101580611dc05760018214928315611d97575b508215611d72575b5050611c95575b6001919293505b019190611c38565b600a546017546040805163059b6d4760e21b81526004810197909752602487019190915290859060449082906001600160a01b03165afa938415611d675788908995611d34575b5080611d00575b5060019192936006611cf483610d75565b50015583929150611c86565b611d27611d2d9160019485611d15868b611a45565b5281611d21868c611a45565b52611a59565b93611a7c565b9291611ce3565b9050611d5891945060403d8111611d60575b611d508183610ddb565b810190611a22565b939038611cdc565b503d611d46565b6040513d8a823e3d90fd5b909150611d83576004143880611c7f565b634e487b7160e01b89526021600452602489fd5b8b935060028314915081611dae575b509138611c77565b60ff91506005015460a01c1638611da6565b634e487b7160e01b8b52602160045260248bfd5b50600191929350611c8d565b600a54600b5460408051632a8ddb2f60e01b815296996001600160a01b03938416999790965094509184918291611e1c91163060048401611aac565b0381895afa9182156121f3578392612207575b506001600160a01b038216156121fe5760406018546044601754918351998a93849263059b6d4760e21b8452600484015260248301525afa9081156121f357839684926121ca575b5086611e8291611a59565b9182156121c057602490611ea184611e9c6007548b611b2e565b611b41565b92601855611eba8460018060a01b03601254163061223a565b601254600a546040516343d7ef9f60e11b8152306004820152936001600160a01b03928316939288928692918391165afa9283156121b5578693612191575b50813b1561218d579185918583611f299560405196879586948593637e18437960e01b8552309060048601611b61565b03925af19081612179575b50611f9e5750505b601a54811015611f895780611f5360019287611a45565b51611f5f575b01611f3c565b611f698185611a45565b51611f826006611f7884610d75565b5001918254611a59565b9055611f59565b50925050611f9990601854611a59565b601855565b909294959391956024602060018060a01b03600b5416604051928380926370a0823160e01b82523060048301525afa908115611d67578891612145575b5061201e92612006611ffd611ff66120189460095490611bc5565b9283611b2e565b60075490611b41565b9061140461201261112c565b836126db565b93611bc5565b92821561213d57855b601a548110156121345761203b8183611a45565b51158015612122575b61211a5761206085611e9c8661205a8588611a45565b51611b2e565b61206982610d75565b509060ff6001830154166005811015612106576001939291908481036120a2575061209661209c92610e13565b90612b53565b01612027565b60028114806120f5575b156120cd57506120c8916003858060a01b0391015416906126db565b61209c565b6004146120dc575b505061209c565b6120e86120ee92610e13565b90612831565b38806120d5565b5060ff600584015460a01c166120ac565b634e487b7160e01b8a52602160045260248afd5b60019061209c565b5061212d8184611a45565b5115612044565b50505050509050565b505050509050565b90506020813d602011612171575b8161216060209383610ddb565b8101031261019b575161201e611fdb565b3d9150612153565b8461218691959295610ddb565b9238611f34565b8580fd5b6121ae9193503d8088833e6121a68183610ddb565b81019061265a565b9138611ef9565b6040513d88823e3d90fd5b5050505092505050565b611e8297506121e991925060403d604011611d6057611d508183610ddb565b9096509086611e77565b6040513d85823e3d90fd5b50505092505050565b61222a91925060403d604011612233575b6122228183610ddb565b810190611a8b565b90509038611e2f565b503d612218565b6001600160a01b0316908115610b9e576001600160a01b0316918215610b885760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260018252604060002085600052825280604060002055604051908152a3565b9081602091031261019b5751801515810361019b5790565b6001600160a01b0316801561233a5760009181835282602052604083205481811061232157817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef926020928587528684520360408620558060025403600255604051908152a3565b6064939263391434e360e21b8452600452602452604452fd5b634b637e8f60e11b600052600060045260246000fd5b600a54604051630d5c7b5d60e41b81526001600160a01b0392831660048201523060248201529160209183916044918391165afa9081156103e557600091612396575090565b610f49915060203d6020116113a7576113998183610ddb565b6001600160a01b031690811561233a576001600160a01b031691821561244857600082815280602052604081205482811061242e5791604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815280845220818154019055604051908152a3565b916064928463391434e360e21b8452600452602452604452fd5b63ec442f0560e01b600052600060045260246000fd5b6001600160a01b0391821681529181166020830152909116604082015260600190565b600a54604051636468b51760e01b81529260209284926001600160a01b031691839182916124b5913091906004850161245e565b03915afa9081156103e557600091612396575090565b9060ff60195460101c1615612618576013546001600160a01b03838116939181169190831660008582036125c2575084600052600d60205260ff604060002054166000146125b45760005b906000935b612524816119ab565b6008546000928352600c60205260408084208290559883528883208190559282529690205580612596575b505080612578575b5050806125615750565b60135461148891906001600160a01b0316306123af565b61258182612350565b6125575761258f91306123af565b3880612557565b61259f82612350565b61254f576125ad91306123af565b388061254f565b6125bd82610f20565b612516565b858152600d602052604081205460ff1615612609575b9080600052600d60205260ff604060002054166000146125fb5760005b9361251b565b61260485610f20565b6125f5565b5061261382610f20565b6125d8565b5050565b80549190600160401b831015610dc557826118c79160016114889501815561102d565b6001600160a01b039091168152602081019190915260400190565b60208183031261019b578051906001600160401b03821161019b57019080601f8301121561019b57815161268d81610dfc565b9261269b6040519485610ddb565b81845260208085019260051b82010192831161019b57602001905b8282106126c35750505090565b602080916126d084611118565b8152019101906126b6565b9060009082156127c757600b546001600160a01b0316803b1561282d57828091602460405180948193632e1a7d4d60e01b83528960048401525af19081612819575b5061278257600b5460405163a9059cbb60e01b81529360209285926001600160a01b03169183918691839161275691906004840161263f565b03925af19081156113ae575061276a575b50565b6127679060203d6020116113a7576113998183610ddb565b8180808086855af13d15612814573d6001600160401b03811161280057604051906127b7601f8201601f191660200183610ddb565b81528360203d92013e5b156127cc575b505050565b600b5460405163a9059cbb60e01b81529360209285926001600160a01b03169183918691839161275691906004840161263f565b634e487b7160e01b84526041600452602484fd5b6127c1565b8361282691949294610ddb565b913861271d565b8280fd5b60009181156127c75760a0018051600b549192916001600160a01b03908116911614612b0957600a54600b54835160408051632a8ddb2f60e01b815294936001600160a01b039384169391928692918216918391829161289691168760048401611aac565b03915afa928315612afe579060249392918693612adb575b5084516040516370a0823160e01b81523060048201529460209186919082906001600160a01b03165afa9384156121b5578694612aa6575b5060125460405163095ea7b360e01b81529160209183919082908a90829061291c9089906001600160a01b03166004840161263f565b03925af180156121b557612a89575b5060125484516001600160a01b0391821692916129489116613045565b92823b15612a855791612978939187809460405196879586948593632d4d638360e11b8552309060048601611b61565b03925af19081612a71575b5061298d57505050565b81516040516370a0823160e01b81523060048201529190602090839060249082906001600160a01b03165afa8015612a66578490612a32575b6129d09250611bc5565b90816129db57505050565b51612a08906129f2906001600160a01b0316612f79565b9260406002549130815280602052205490611bc5565b9081156127c757611f78612a28612a2e93611e9c60019460075490611b2e565b9361100e565b9055565b506020823d602011612a5e575b81612a4c60209383610ddb565b8101031261019b576129d091516129c6565b3d9150612a3f565b6040513d86823e3d90fd5b84612a7e91959295610ddb565b9238612983565b8680fd5b612aa19060203d6020116113a7576113998183610ddb565b61292b565b9093506020813d602011612ad3575b81612ac260209383610ddb565b8101031261218d57519260206128e6565b3d9150612ab5565b612af591935060403d604011612233576122228183610ddb565b905091386128ae565b6040513d87823e3d90fd5b906129f2612b2f91612b1d84600954611a59565b600955516001600160a01b0316612f79565b9081612b3a57505050565b611f78612a28612a2e93611e9c60019460075490611b2e565b9060009082156127c75760a081018051600b549192916001600160a01b0390811691168114612d155750600a54600b54835160408051632a8ddb2f60e01b815294936001600160a01b0393841693919286929182169183918291612bbc91168760048401611aac565b03915afa928315612afe579086918694612ce9575b5060125460405163095ea7b360e01b8152926020928492909183918a918391612c0791906001600160a01b03166004840161263f565b03925af18015612afe57612ccc575b506012546080919091018051935190936001600160a01b039283169290811691612c409116613045565b92823b1561218d57918691868094612c6e60405197889687958694632d4d638360e11b865260048601611b61565b03925af19081612cb8575b506127c757600b54905160405163a9059cbb60e01b81529360209285926001600160a01b0391821692849287928492612756929091166004840161263f565b83612cc591949294610ddb565b9138612c79565b612ce49060203d6020116113a7576113998183610ddb565b612c16565b602091945091612d0a612c079360403d604011612233576122228183610ddb565b905094915091612bd1565b60809091015160405163a9059cbb60e01b81529460209350859291839186918391612756916001600160a01b03166004840161263f565b600a546060909201516001600160a01b0392909216929160409160a490612d71610eb9565b9560ff6019541685519788958694632b8d28ef60e21b86526004860152602485015260448401521515606483015261271060848301525afa9182156103e557600090600093612dbf57509190565b9050612ddb91925060403d604011611d6057611d508183610ddb565b9091565b909160208101908151916005831015610d5257600092612e065750505090611488916122b9565b80516005811015612f655785929190600303612e6d575050612e2d90612e429330906123af565b60406002549130815280602052205490611bc5565b9081612e4c575050565b612e6891611e9c612e609260075490611b2e565b600854611a59565b600855565b8091949392505160058110156113de57600203612f1057506080830180516001600160a01b031682526016602052604082205490919060ff1615612ee9575b5060e083015115612ed35750611f78612a2e92612ecd8560069430906123af565b51610d75565b516114889392506001600160a01b0316906123af565b81516001600160a01b03168152601660205260409020805460ff1916600117905538612eac565b809492945160058110156113de57600103612f305750506114889261309a565b51906005821015612f515750600414612f4857505050565b6114889261309a565b634e487b7160e01b81526021600452602490fd5b634e487b7160e01b84526021600452602484fd5b6006549060005b82811061301a575060405190612f9582610daa565b6001600160a01b0316815260006020820190815291600160401b811015610dc557806001612fc6920160065561100e565b92909261300457905182546001600160a01b0319166001600160a01b039190911617825551600191909101556006546000198101908111611a665790565b634e487b7160e01b600052600060045260246000fd5b6130238161100e565b50546001600160a01b0383811691161461303f57600101612f80565b91505090565b600a546040516377a9efe360e11b81526001600160a01b0392831660048201529160009183916024918391165afa9081156103e557600091613085575090565b610f4991503d806000833e6121a68183610ddb565b611f788293612ecd6130bd94600694600160ff19601054161760105530906123af565b905560ff196010541660105556fea264697066735822122005404067a9c75949def711aac05d72403bef69300432efb25296511b50eaf2dd64736f6c634300081c0033