Token VolatileV1 AMM - WMATIC/KOGECOIN

 

Overview ERC-20

Price
$0.00 @ 0.000000 MATIC
Fully Diluted Market Cap
Total Supply:
0.039239 vAMM-WMATIC/KOGECOIN

Holders:
5 addresses
Contract:
0x007174bed34bd4bfb656de52122b5246e487de3e0x007174bED34Bd4BfB656De52122b5246e487de3e

Decimals:
18

Social Profiles:
Not Available, Update ?

 
Balance
0.004690415759822428 vAMM-WMATIC/KOGECOIN

Value
$0.00
0x4A170561126a1D765A6B80a081dB639945a8b53b
Loading
[ Download CSV Export  ] 
Loading
[ Download CSV Export  ] 
Loading

Click here to update the token ICO / general information
# Exchange Pair Price  24H Volume % Volume
Loading

Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0xD934e1F25645A767A687A9494465dbe8e09A0cc4

Contract Name:
DystPair

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 14 : DystPair.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

import "../../interface/IERC20.sol";
import "../../interface/IERC721Metadata.sol";
import "../../interface/IPair.sol";
import "../../interface/IFactory.sol";
import "../../interface/ICallee.sol";
import "../../interface/IUnderlying.sol";
import "./PairFees.sol";
import "../../lib/Math.sol";
import "../../lib/SafeERC20.sol";
import "../Reentrancy.sol";

// The base pair of pools, either stable or volatile
contract DystPair is IERC20, IPair, Reentrancy {
  using SafeERC20 for IERC20;

  string public name;
  string public symbol;
  uint8 public constant decimals = 18;

  /// @dev Used to denote stable or volatile pair
  bool public immutable stable;

  uint public override totalSupply = 0;

  mapping(address => mapping(address => uint)) public override allowance;
  mapping(address => uint) public override balanceOf;

  bytes32 public immutable DOMAIN_SEPARATOR;
  // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
  bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
  uint internal constant _FEE_PRECISION = 1e32;
  mapping(address => uint) public nonces;
  uint public immutable chainId;

  uint internal constant MINIMUM_LIQUIDITY = 10 ** 3;
  /// @dev 0.05% swap fee
  uint internal constant SWAP_FEE = 2000;
  /// @dev 50% of swap fee
  uint internal constant TREASURY_FEE = 2;
  /// @dev Capture oracle reading every 30 minutes
  uint internal constant PERIOD_SIZE = 1800;

  address public immutable override token0;
  address public immutable override token1;
  address public immutable fees;
  address public immutable factory;
  address public immutable treasury;

  Observation[] public observations;

  uint internal immutable decimals0;
  uint internal immutable decimals1;

  uint public reserve0;
  uint public reserve1;
  uint public blockTimestampLast;

  uint public reserve0CumulativeLast;
  uint public reserve1CumulativeLast;

  // index0 and index1 are used to accumulate fees,
  // this is split out from normal trades to keep the swap "clean"
  // this further allows LP holders to easily claim fees for tokens they have/staked
  uint public index0 = 0;
  uint public index1 = 0;

  // position assigned to each LP to track their current index0 & index1 vs the global position
  mapping(address => uint) public supplyIndex0;
  mapping(address => uint) public supplyIndex1;

  // tracks the amount of unclaimed, but claimable tokens off of fees for token0 and token1
  mapping(address => uint) public claimable0;
  mapping(address => uint) public claimable1;

  event Treasury(address indexed sender, uint amount0, uint amount1);
  event Fees(address indexed sender, uint amount0, uint amount1);
  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(uint reserve0, uint reserve1);
  event Claim(address indexed sender, address indexed recipient, uint amount0, uint amount1);

  constructor() {
    factory = msg.sender;
    treasury = IFactory(msg.sender).treasury();
    (address _token0, address _token1, bool _stable) = IFactory(msg.sender).getInitializable();
    (token0, token1, stable) = (_token0, _token1, _stable);
    fees = address(new PairFees(_token0, _token1));
    if (_stable) {
      name = string(abi.encodePacked("StableV1 AMM - ", IERC721Metadata(_token0).symbol(), "/", IERC721Metadata(_token1).symbol()));
      symbol = string(abi.encodePacked("sAMM-", IERC721Metadata(_token0).symbol(), "/", IERC721Metadata(_token1).symbol()));
    } else {
      name = string(abi.encodePacked("VolatileV1 AMM - ", IERC721Metadata(_token0).symbol(), "/", IERC721Metadata(_token1).symbol()));
      symbol = string(abi.encodePacked("vAMM-", IERC721Metadata(_token0).symbol(), "/", IERC721Metadata(_token1).symbol()));
    }

    decimals0 = 10 ** IUnderlying(_token0).decimals();
    decimals1 = 10 ** IUnderlying(_token1).decimals();

    observations.push(Observation(block.timestamp, 0, 0));

    DOMAIN_SEPARATOR = keccak256(
      abi.encode(
        keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
        keccak256(bytes(name)),
        keccak256('1'),
        block.chainid,
        address(this)
      )
    );
    chainId = block.chainid;
  }

  function observationLength() external view returns (uint) {
    return observations.length;
  }

  function lastObservation() public view returns (Observation memory) {
    return observations[observations.length - 1];
  }

  function metadata() external view returns (
    uint dec0,
    uint dec1,
    uint r0,
    uint r1,
    bool st,
    address t0,
    address t1
  ) {
    return (decimals0, decimals1, reserve0, reserve1, stable, token0, token1);
  }

  function tokens() external view override returns (address, address) {
    return (token0, token1);
  }

  /// @dev Claim accumulated but unclaimed fees (viewable via claimable0 and claimable1)
  function claimFees() external override returns (uint claimed0, uint claimed1) {
    _updateFor(msg.sender);

    claimed0 = claimable0[msg.sender];
    claimed1 = claimable1[msg.sender];

    if (claimed0 > 0 || claimed1 > 0) {
      claimable0[msg.sender] = 0;
      claimable1[msg.sender] = 0;

      PairFees(fees).claimFeesFor(msg.sender, claimed0, claimed1);

      emit Claim(msg.sender, msg.sender, claimed0, claimed1);
    }
  }

  /// @dev Accrue fees on token0
  function _update0(uint amount) internal {
    uint toTreasury = amount / TREASURY_FEE;
    uint toFees = amount - toTreasury;

    // transfer the fees out to PairFees and Treasury
    IERC20(token0).safeTransfer(treasury, toTreasury);
    IERC20(token0).safeTransfer(fees, toFees);
    // 1e32 adjustment is removed during claim
    uint _ratio = toFees * _FEE_PRECISION / totalSupply;
    if (_ratio > 0) {
      index0 += _ratio;
    }
    // keep the same structure of events for compatability
    emit Treasury(msg.sender, toTreasury, 0);
    emit Fees(msg.sender, toFees, 0);
  }

  /// @dev Accrue fees on token1
  function _update1(uint amount) internal {
    uint toTreasury = amount / TREASURY_FEE;
    uint toFees = amount - toTreasury;

    IERC20(token1).safeTransfer(treasury, toTreasury);
    IERC20(token1).safeTransfer(fees, toFees);
    uint _ratio = toFees * _FEE_PRECISION / totalSupply;
    if (_ratio > 0) {
      index1 += _ratio;
    }
    // keep the same structure of events for compatability
    emit Treasury(msg.sender, 0, toTreasury);
    emit Fees(msg.sender, 0, toFees);
  }

  /// @dev This function MUST be called on any balance changes,
  ///      otherwise can be used to infinitely claim fees
  //       Fees are segregated from core funds, so fees can never put liquidity at risk
  function _updateFor(address recipient) internal {
    uint _supplied = balanceOf[recipient];
    // get LP balance of `recipient`
    if (_supplied > 0) {
      uint _supplyIndex0 = supplyIndex0[recipient];
      // get last adjusted index0 for recipient
      uint _supplyIndex1 = supplyIndex1[recipient];
      uint _index0 = index0;
      // get global index0 for accumulated fees
      uint _index1 = index1;
      supplyIndex0[recipient] = _index0;
      // update user current position to global position
      supplyIndex1[recipient] = _index1;
      uint _delta0 = _index0 - _supplyIndex0;
      // see if there is any difference that need to be accrued
      uint _delta1 = _index1 - _supplyIndex1;
      if (_delta0 > 0) {
        uint _share = _supplied * _delta0 / _FEE_PRECISION;
        // add accrued difference for each supplied token
        claimable0[recipient] += _share;
      }
      if (_delta1 > 0) {
        uint _share = _supplied * _delta1 / _FEE_PRECISION;
        claimable1[recipient] += _share;
      }
    } else {
      supplyIndex0[recipient] = index0;
      // new users are set to the default global state
      supplyIndex1[recipient] = index1;
    }
  }

  function getReserves() public view override returns (
    uint112 _reserve0,
    uint112 _reserve1,
    uint32 _blockTimestampLast
  ) {
    _reserve0 = uint112(reserve0);
    _reserve1 = uint112(reserve1);
    _blockTimestampLast = uint32(blockTimestampLast);
  }

  /// @dev Update reserves and, on the first call per block, price accumulators
  function _update(uint balance0, uint balance1, uint _reserve0, uint _reserve1) internal {
    uint blockTimestamp = block.timestamp;
    uint timeElapsed = blockTimestamp - blockTimestampLast;
    // overflow is desired
    if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
    unchecked {
      reserve0CumulativeLast += _reserve0 * timeElapsed;
      reserve1CumulativeLast += _reserve1 * timeElapsed;
    }
    }

    Observation memory _point = lastObservation();
    timeElapsed = blockTimestamp - _point.timestamp;
    // compare the last observation with current timestamp,
    // if greater than 30 minutes, record a new event
    if (timeElapsed > PERIOD_SIZE) {
      observations.push(Observation(blockTimestamp, reserve0CumulativeLast, reserve1CumulativeLast));
    }
    reserve0 = balance0;
    reserve1 = balance1;
    blockTimestampLast = blockTimestamp;
    emit Sync(reserve0, reserve1);
  }

  /// @dev Produces the cumulative price using counterfactuals to save gas and avoid a call to sync.
  function currentCumulativePrices() public view returns (
    uint reserve0Cumulative,
    uint reserve1Cumulative,
    uint blockTimestamp
  ) {
    blockTimestamp = block.timestamp;
    reserve0Cumulative = reserve0CumulativeLast;
    reserve1Cumulative = reserve1CumulativeLast;

    // if time has elapsed since the last update on the pair, mock the accumulated price values
    (uint _reserve0, uint _reserve1, uint _blockTimestampLast) = getReserves();
    if (_blockTimestampLast != blockTimestamp) {
      // subtraction overflow is desired
      uint timeElapsed = blockTimestamp - _blockTimestampLast;
    unchecked {
      reserve0Cumulative += _reserve0 * timeElapsed;
      reserve1Cumulative += _reserve1 * timeElapsed;
    }
    }
  }

  /// @dev Gives the current twap price measured from amountIn * tokenIn gives amountOut
  function current(address tokenIn, uint amountIn) external view returns (uint amountOut) {
    Observation memory _observation = lastObservation();
    (uint reserve0Cumulative, uint reserve1Cumulative,) = currentCumulativePrices();
    if (block.timestamp == _observation.timestamp) {
      _observation = observations[observations.length - 2];
    }

    uint timeElapsed = block.timestamp - _observation.timestamp;
    uint _reserve0 = (reserve0Cumulative - _observation.reserve0Cumulative) / timeElapsed;
    uint _reserve1 = (reserve1Cumulative - _observation.reserve1Cumulative) / timeElapsed;
    amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);
  }

  /// @dev As per `current`, however allows user configured granularity, up to the full window size
  function quote(address tokenIn, uint amountIn, uint granularity)
  external view returns (uint amountOut) {
    uint [] memory _prices = sample(tokenIn, amountIn, granularity, 1);
    uint priceAverageCumulative;
    for (uint i = 0; i < _prices.length; i++) {
      priceAverageCumulative += _prices[i];
    }
    return priceAverageCumulative / granularity;
  }

  /// @dev Returns a memory set of twap prices
  function prices(address tokenIn, uint amountIn, uint points)
  external view returns (uint[] memory) {
    return sample(tokenIn, amountIn, points, 1);
  }

  function sample(address tokenIn, uint amountIn, uint points, uint window)
  public view returns (uint[] memory) {
    uint[] memory _prices = new uint[](points);

    uint length = observations.length - 1;
    uint i = length - (points * window);
    uint nextIndex = 0;
    uint index = 0;

    for (; i < length; i += window) {
      nextIndex = i + window;
      uint timeElapsed = observations[nextIndex].timestamp - observations[i].timestamp;
      uint _reserve0 = (observations[nextIndex].reserve0Cumulative - observations[i].reserve0Cumulative) / timeElapsed;
      uint _reserve1 = (observations[nextIndex].reserve1Cumulative - observations[i].reserve1Cumulative) / timeElapsed;
      _prices[index] = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);
      index = index + 1;
    }
    return _prices;
  }

  /// @dev This low-level function should be called from a contract which performs important safety checks
  ///      standard uniswap v2 implementation
  function mint(address to) external lock override returns (uint liquidity) {
    (uint _reserve0, uint _reserve1) = (reserve0, reserve1);
    uint _balance0 = IERC20(token0).balanceOf(address(this));
    uint _balance1 = IERC20(token1).balanceOf(address(this));
    uint _amount0 = _balance0 - _reserve0;
    uint _amount1 = _balance1 - _reserve1;

    uint _totalSupply = totalSupply;
    // gas savings, must be defined here since totalSupply can update in _mintFee
    if (_totalSupply == 0) {
      liquidity = Math.sqrt(_amount0 * _amount1) - MINIMUM_LIQUIDITY;
      // permanently lock the first MINIMUM_LIQUIDITY tokens
      _mint(address(0), MINIMUM_LIQUIDITY);
    } else {
      liquidity = Math.min(_amount0 * _totalSupply / _reserve0, _amount1 * _totalSupply / _reserve1);
    }
    require(liquidity > 0, 'DystPair: INSUFFICIENT_LIQUIDITY_MINTED');
    _mint(to, liquidity);

    _update(_balance0, _balance1, _reserve0, _reserve1);
    emit Mint(msg.sender, _amount0, _amount1);
  }

  /// @dev This low-level function should be called from a contract which performs important safety checks
  ///      standard uniswap v2 implementation
  function burn(address to) external lock override returns (uint amount0, uint amount1) {
    (uint _reserve0, uint _reserve1) = (reserve0, reserve1);
    (address _token0, address _token1) = (token0, token1);
    uint _balance0 = IERC20(_token0).balanceOf(address(this));
    uint _balance1 = IERC20(_token1).balanceOf(address(this));
    uint _liquidity = balanceOf[address(this)];

    // gas savings, must be defined here since totalSupply can update in _mintFee
    uint _totalSupply = totalSupply;
    // using balances ensures pro-rata distribution
    amount0 = _liquidity * _balance0 / _totalSupply;
    // using balances ensures pro-rata distribution
    amount1 = _liquidity * _balance1 / _totalSupply;
    require(amount0 > 0 && amount1 > 0, 'DystPair: INSUFFICIENT_LIQUIDITY_BURNED');
    _burn(address(this), _liquidity);
    IERC20(_token0).safeTransfer(to, amount0);
    IERC20(_token1).safeTransfer(to, amount1);
    _balance0 = IERC20(_token0).balanceOf(address(this));
    _balance1 = IERC20(_token1).balanceOf(address(this));

    _update(_balance0, _balance1, _reserve0, _reserve1);
    emit Burn(msg.sender, amount0, amount1, to);
  }

  /// @dev This low-level function should be called from a contract which performs important safety checks
  function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external override lock {
    require(!IFactory(factory).isPaused(), "DystPair: PAUSE");
    require(amount0Out > 0 || amount1Out > 0, 'DystPair: INSUFFICIENT_OUTPUT_AMOUNT');
    (uint _reserve0, uint _reserve1) = (reserve0, reserve1);
    require(amount0Out < _reserve0 && amount1Out < _reserve1, 'DystPair: INSUFFICIENT_LIQUIDITY');
    uint _balance0;
    uint _balance1;
    {// scope for _token{0,1}, avoids stack too deep errors
      (address _token0, address _token1) = (token0, token1);
      require(to != _token0 && to != _token1, 'DystPair: INVALID_TO');
      // optimistically transfer tokens
      if (amount0Out > 0) IERC20(_token0).safeTransfer(to, amount0Out);
      // optimistically transfer tokens
      if (amount1Out > 0) IERC20(_token1).safeTransfer(to, amount1Out);
      // callback, used for flash loans
      if (data.length > 0) ICallee(to).hook(msg.sender, amount0Out, amount1Out, data);
      _balance0 = IERC20(_token0).balanceOf(address(this));
      _balance1 = IERC20(_token1).balanceOf(address(this));
    }
    uint amount0In = _balance0 > _reserve0 - amount0Out ? _balance0 - (_reserve0 - amount0Out) : 0;
    uint amount1In = _balance1 > _reserve1 - amount1Out ? _balance1 - (_reserve1 - amount1Out) : 0;
    require(amount0In > 0 || amount1In > 0, 'DystPair: INSUFFICIENT_INPUT_AMOUNT');
    {// scope for reserve{0,1}Adjusted, avoids stack too deep errors
      (address _token0, address _token1) = (token0, token1);
      // accrue fees for token0 and move them out of pool
      if (amount0In > 0) _update0(amount0In / SWAP_FEE);
      // accrue fees for token1 and move them out of pool
      if (amount1In > 0) _update1(amount1In / SWAP_FEE);
      // since we removed tokens, we need to reconfirm balances,
      // can also simply use previous balance - amountIn/ SWAP_FEE,
      // but doing balanceOf again as safety check
      _balance0 = IERC20(_token0).balanceOf(address(this));
      _balance1 = IERC20(_token1).balanceOf(address(this));
      // The curve, either x3y+y3x for stable pools, or x*y for volatile pools
      require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), 'DystPair: K');
    }

    _update(_balance0, _balance1, _reserve0, _reserve1);
    emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
  }

  /// @dev Force balances to match reserves
  function skim(address to) external lock {
    (address _token0, address _token1) = (token0, token1);
    IERC20(_token0).safeTransfer(to, IERC20(_token0).balanceOf(address(this)) - (reserve0));
    IERC20(_token1).safeTransfer(to, IERC20(_token1).balanceOf(address(this)) - (reserve1));
  }

  // force reserves to match balances
  function sync() external lock {
    _update(
      IERC20(token0).balanceOf(address(this)),
      IERC20(token1).balanceOf(address(this)),
      reserve0,
      reserve1
    );
  }

  function _f(uint x0, uint y) internal pure returns (uint) {
    return x0 * (y * y / 1e18 * y / 1e18) / 1e18 + (x0 * x0 / 1e18 * x0 / 1e18) * y / 1e18;
  }

  function _d(uint x0, uint y) internal pure returns (uint) {
    return 3 * x0 * (y * y / 1e18) / 1e18 + (x0 * x0 / 1e18 * x0 / 1e18);
  }

  function _getY(uint x0, uint xy, uint y) internal pure returns (uint) {
    for (uint i = 0; i < 255; i++) {
      uint yPrev = y;
      uint k = _f(x0, y);
      if (k < xy) {
        uint dy = (xy - k) * 1e18 / _d(x0, y);
        y = y + dy;
      } else {
        uint dy = (k - xy) * 1e18 / _d(x0, y);
        y = y - dy;
      }
      if (Math.closeTo(y, yPrev, 1)) {
        break;
      }
    }
    return y;
  }

  function getAmountOut(uint amountIn, address tokenIn) external view override returns (uint) {
    (uint _reserve0, uint _reserve1) = (reserve0, reserve1);
    // remove fee from amount received
    amountIn -= amountIn / SWAP_FEE;
    return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);
  }

  function _getAmountOut(uint amountIn, address tokenIn, uint _reserve0, uint _reserve1) internal view returns (uint) {
    if (stable) {
      uint xy = _k(_reserve0, _reserve1);
      _reserve0 = _reserve0 * 1e18 / decimals0;
      _reserve1 = _reserve1 * 1e18 / decimals1;
      (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);
      amountIn = tokenIn == token0 ? amountIn * 1e18 / decimals0 : amountIn * 1e18 / decimals1;
      uint y = reserveB - _getY(amountIn + reserveA, xy, reserveB);
      return y * (tokenIn == token0 ? decimals1 : decimals0) / 1e18;
    } else {
      (uint reserveA, uint reserveB) = tokenIn == token0 ? (_reserve0, _reserve1) : (_reserve1, _reserve0);
      return amountIn * reserveB / (reserveA + amountIn);
    }
  }

  function _k(uint x, uint y) internal view returns (uint) {
    if (stable) {
      uint _x = x * 1e18 / decimals0;
      uint _y = y * 1e18 / decimals1;
      uint _a = (_x * _y) / 1e18;
      uint _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);
      // x3y+y3x >= k
      return _a * _b / 1e18;
    } else {
      // xy >= k
      return x * y;
    }
  }

  //****************************************************************************
  //**************************** ERC20 *****************************************
  //****************************************************************************

  function _mint(address dst, uint amount) internal {
    // balances must be updated on mint/burn/transfer
    _updateFor(dst);
    totalSupply += amount;
    balanceOf[dst] += amount;
    emit Transfer(address(0), dst, amount);
  }

  function _burn(address dst, uint amount) internal {
    _updateFor(dst);
    totalSupply -= amount;
    balanceOf[dst] -= amount;
    emit Transfer(dst, address(0), amount);
  }

  function approve(address spender, uint amount) external override returns (bool) {
    require(spender != address(0), "DystPair: Approve to the zero address");
    allowance[msg.sender][spender] = amount;

    emit Approval(msg.sender, spender, amount);
    return true;
  }

  function permit(
    address owner,
    address spender,
    uint value,
    uint deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external override {
    require(deadline >= block.timestamp, 'DystPair: EXPIRED');
    bytes32 digest = keccak256(
      abi.encodePacked(
        '\x19\x01',
        DOMAIN_SEPARATOR,
        keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
      )
    );
    address recoveredAddress = ecrecover(digest, v, r, s);
    require(recoveredAddress != address(0) && recoveredAddress == owner, 'DystPair: INVALID_SIGNATURE');
    allowance[owner][spender] = value;

    emit Approval(owner, spender, value);
  }

  function transfer(address dst, uint amount) external override returns (bool) {
    _transferTokens(msg.sender, dst, amount);
    return true;
  }

  function transferFrom(address src, address dst, uint amount) external override returns (bool) {
    address spender = msg.sender;
    uint spenderAllowance = allowance[src][spender];

    if (spender != src && spenderAllowance != type(uint).max) {
      require(spenderAllowance >= amount, "DystPair: Insufficient allowance");
    unchecked {
      uint newAllowance = spenderAllowance - amount;
      allowance[src][spender] = newAllowance;
      emit Approval(src, spender, newAllowance);
    }
    }

    _transferTokens(src, dst, amount);
    return true;
  }

  function _transferTokens(address src, address dst, uint amount) internal {
    require(dst != address(0), "DystPair: Transfer to the zero address");

    // update fee position for src
    _updateFor(src);
    // update fee position for dst
    _updateFor(dst);

    uint srcBalance = balanceOf[src];
    require(srcBalance >= amount, "DystPair: Transfer amount exceeds balance");
  unchecked {
    balanceOf[src] = srcBalance - amount;
  }

    balanceOf[dst] += amount;

    emit Transfer(src, dst, amount);
  }
}

File 2 of 14 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
  /**
   * @dev Returns the amount of tokens in existence.
   */
  function totalSupply() external view returns (uint256);

  /**
   * @dev Returns the amount of tokens owned by `account`.
   */
  function balanceOf(address account) external view returns (uint256);

  /**
   * @dev Moves `amount` tokens from the caller's account to `recipient`.
   *
   * Returns a boolean value indicating whether the operation succeeded.
   *
   * Emits a {Transfer} event.
   */
  function transfer(address recipient, uint256 amount) 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 `amount` 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 amount) external returns (bool);

  /**
   * @dev Moves `amount` tokens from `sender` to `recipient` using the
   * allowance mechanism. `amount` is then deducted from the caller's
   * allowance.
   *
   * Returns a boolean value indicating whether the operation succeeded.
   *
   * Emits a {Transfer} event.
   */
  function transferFrom(
    address sender,
    address recipient,
    uint256 amount
  ) external returns (bool);

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

File 3 of 14 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

import "./IERC721.sol";

/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
  /**
  * @dev Returns the token collection name.
  */
  function name() external view returns (string memory);

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

  /**
  * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
  */
  function tokenURI(uint tokenId) external view returns (string memory);
}

File 4 of 14 : IPair.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

interface IPair {

  // Structure to capture time period obervations every 30 minutes, used for local oracles
  struct Observation {
    uint timestamp;
    uint reserve0Cumulative;
    uint reserve1Cumulative;
  }

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

  function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;

  function burn(address to) external returns (uint amount0, uint amount1);

  function mint(address to) external returns (uint liquidity);

  function getReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast);

  function getAmountOut(uint, address) external view returns (uint);

  function claimFees() external returns (uint, uint);

  function tokens() external returns (address, address);

  function token0() external returns (address);

  function token1() external returns (address);
}

File 5 of 14 : IFactory.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

interface IFactory {
  function treasury() external view returns (address);

  function isPair(address pair) external view returns (bool);

  function getInitializable() external view returns (address, address, bool);

  function isPaused() external view returns (bool);

  function pairCodeHash() external pure returns (bytes32);

  function getPair(address tokenA, address token, bool stable) external view returns (address);

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

File 6 of 14 : ICallee.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

interface ICallee {
  function hook(address sender, uint amount0, uint amount1, bytes calldata data) external;
}

File 7 of 14 : IUnderlying.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

interface IUnderlying {
  function approve(address spender, uint value) external returns (bool);

  function mint(address, uint) external;

  function totalSupply() external view returns (uint);

  function balanceOf(address) external view returns (uint);

  function transfer(address, uint) external returns (bool);

  function decimals() external returns (uint8);
}

File 8 of 14 : PairFees.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

import "../../interface/IERC20.sol";
import "../../lib/SafeERC20.sol";

/// @title Base V1 Fees contract is used as a 1:1 pair relationship to split out fees,
///        this ensures that the curve does not need to be modified for LP shares
contract PairFees {
  using SafeERC20 for IERC20;

  /// @dev The pair it is bonded to
  address internal immutable pair;
  /// @dev Token0 of pair, saved localy and statically for gas optimization
  address internal immutable token0;
  /// @dev Token1 of pair, saved localy and statically for gas optimization
  address internal immutable token1;

  constructor(address _token0, address _token1) {
    pair = msg.sender;
    token0 = _token0;
    token1 = _token1;
  }

  // Allow the pair to transfer fees to users
  function claimFeesFor(address recipient, uint amount0, uint amount1) external {
    require(msg.sender == pair, "Not pair");
    if (amount0 > 0) {
      IERC20(token0).safeTransfer(recipient, amount0);
    }
    if (amount1 > 0) {
      IERC20(token1).safeTransfer(recipient, amount1);
    }
  }

}

File 9 of 14 : Math.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

library Math {

  function max(uint a, uint b) internal pure returns (uint) {
    return a >= b ? a : b;
  }

  function min(uint a, uint b) internal pure returns (uint) {
    return a < b ? a : b;
  }

  function positiveInt128(int128 value) internal pure returns (int128) {
    return value < 0 ? int128(0) : value;
  }

  function closeTo(uint a, uint b, uint target) internal pure returns (bool) {
    if (a > b) {
      if (a - b <= target) {
        return true;
      }
    } else {
      if (b - a <= target) {
        return true;
      }
    }
    return false;
  }

  function sqrt(uint y) internal pure returns (uint z) {
    if (y > 3) {
      z = y;
      uint x = y / 2 + 1;
      while (x < z) {
        z = x;
        x = (y / x + x) / 2;
      }
    } else if (y != 0) {
      z = 1;
    }
  }

}

File 10 of 14 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.13;

import "../interface/IERC20.sol";
import "./Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
  using Address for address;

  function safeTransfer(
    IERC20 token,
    address to,
    uint value
  ) internal {
    _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
  }

  function safeTransferFrom(
    IERC20 token,
    address from,
    address to,
    uint value
  ) internal {
    _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
  }

  function safeIncreaseAllowance(
    IERC20 token,
    address spender,
    uint value
  ) internal {
    uint newAllowance = token.allowance(address(this), spender) + value;
    _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
  }

  /**
   * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
  function _callOptionalReturn(IERC20 token, bytes memory data) private {
    // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
    // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
    // the target address contains contract code and also asserts for success in the low-level call.

    bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
    if (returndata.length > 0) {
      // Return data is optional
      require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
    }
  }

}

File 11 of 14 : Reentrancy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

abstract contract Reentrancy {

  /// @dev simple re-entrancy check
  uint internal _unlocked = 1;

  modifier lock() {
    require(_unlocked == 1, "Reentrant call");
    _unlocked = 2;
    _;
    _unlocked = 1;
  }

}

File 12 of 14 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

import "./IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
  /**
   * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
   */
  event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

  /**
   * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
   */
  event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

  /**
   * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
   */
  event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

  /**
   * @dev Returns the number of tokens in ``owner``'s account.
   */
  function balanceOf(address owner) external view returns (uint256 balance);

  /**
   * @dev Returns the owner of the `tokenId` token.
   *
   * Requirements:
   *
   * - `tokenId` must exist.
   */
  function ownerOf(uint256 tokenId) external view returns (address owner);

  /**
   * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
   * are aware of the ERC721 protocol to prevent tokens from being forever locked.
   *
   * Requirements:
   *
   * - `from` cannot be the zero address.
   * - `to` cannot be the zero address.
   * - `tokenId` token must exist and be owned by `from`.
   * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
   * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
   *
   * Emits a {Transfer} event.
   */
  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId
  ) external;

  /**
   * @dev Transfers `tokenId` token from `from` to `to`.
   *
   * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
   *
   * Requirements:
   *
   * - `from` cannot be the zero address.
   * - `to` cannot be the zero address.
   * - `tokenId` token must be owned by `from`.
   * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
   *
   * Emits a {Transfer} event.
   */
  function transferFrom(
    address from,
    address to,
    uint256 tokenId
  ) external;

  /**
   * @dev Gives permission to `to` to transfer `tokenId` token to another account.
   * The approval is cleared when the token is transferred.
   *
   * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
   *
   * Requirements:
   *
   * - The caller must own the token or be an approved operator.
   * - `tokenId` must exist.
   *
   * Emits an {Approval} event.
   */
  function approve(address to, uint256 tokenId) external;

  /**
   * @dev Returns the account approved for `tokenId` token.
   *
   * Requirements:
   *
   * - `tokenId` must exist.
   */
  function getApproved(uint256 tokenId) external view returns (address operator);

  /**
   * @dev Approve or remove `operator` as an operator for the caller.
   * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
   *
   * Requirements:
   *
   * - The `operator` cannot be the caller.
   *
   * Emits an {ApprovalForAll} event.
   */
  function setApprovalForAll(address operator, bool _approved) external;

  /**
   * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
   *
   * See {setApprovalForAll}
   */
  function isApprovedForAll(address owner, address operator) external view returns (bool);

  /**
   * @dev Safely transfers `tokenId` token from `from` to `to`.
   *
   * Requirements:
   *
   * - `from` cannot be the zero address.
   * - `to` cannot be the zero address.
   * - `tokenId` token must exist and be owned by `from`.
   * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
   * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
   *
   * Emits a {Transfer} event.
   */
  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId,
    bytes calldata data
  ) external;
}

File 13 of 14 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
  /**
   * @dev Returns true if this contract implements the interface defined by
   * `interfaceId`. See the corresponding
   * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
   * to learn more about how these ids are created.
   *
   * This function call must use less than 30 000 gas.
   */
  function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 14 of 14 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.13;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
  /**
   * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
  function isContract(address account) internal view returns (bool) {
    // This method relies on extcodesize/address.code.length, which returns 0
    // for contracts in construction, since the code is only stored at the end
    // of the constructor execution.

    return account.code.length > 0;
  }

  function functionCall(
    address target,
    bytes memory data,
    string memory errorMessage
  ) internal returns (bytes memory) {
    require(isContract(target), "Address: call to non-contract");
    (bool success, bytes memory returndata) = target.call(data);
    return verifyCallResult(success, returndata, errorMessage);
  }

  /**
   * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
  function verifyCallResult(
    bool success,
    bytes memory returndata,
    string memory errorMessage
  ) internal pure returns (bytes memory) {
    if (success) {
      return returndata;
    } else {
      // Look for revert reason and bubble it up if present
      if (returndata.length > 0) {
        // The easiest way to bubble the revert reason is using memory via assembly
        assembly {
          let returndata_size := mload(returndata)
          revert(add(32, returndata), returndata_size)
        }
      } else {
        revert(errorMessage);
      }
    }
  }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Fees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0Out","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1Out","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reserve0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reserve1","type":"uint256"}],"name":"Sync","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Treasury","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockTimestampLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"burn","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimFees","outputs":[{"internalType":"uint256","name":"claimed0","type":"uint256"},{"internalType":"uint256","name":"claimed1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimable0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimable1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"current","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentCumulativePrices","outputs":[{"internalType":"uint256","name":"reserve0Cumulative","type":"uint256"},{"internalType":"uint256","name":"reserve1Cumulative","type":"uint256"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fees","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint112","name":"_reserve0","type":"uint112"},{"internalType":"uint112","name":"_reserve1","type":"uint112"},{"internalType":"uint32","name":"_blockTimestampLast","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"index0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"index1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastObservation","outputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"reserve0Cumulative","type":"uint256"},{"internalType":"uint256","name":"reserve1Cumulative","type":"uint256"}],"internalType":"struct IPair.Observation","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadata","outputs":[{"internalType":"uint256","name":"dec0","type":"uint256"},{"internalType":"uint256","name":"dec1","type":"uint256"},{"internalType":"uint256","name":"r0","type":"uint256"},{"internalType":"uint256","name":"r1","type":"uint256"},{"internalType":"bool","name":"st","type":"bool"},{"internalType":"address","name":"t0","type":"address"},{"internalType":"address","name":"t1","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"observationLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"observations","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"reserve0Cumulative","type":"uint256"},{"internalType":"uint256","name":"reserve1Cumulative","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"points","type":"uint256"}],"name":"prices","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"granularity","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve0CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve1CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"points","type":"uint256"},{"internalType":"uint256","name":"window","type":"uint256"}],"name":"sample","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"skim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supplyIndex0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supplyIndex1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0Out","type":"uint256"},{"internalType":"uint256","name":"amount1Out","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokens","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

6101c0604052600160005560006003556000600d556000600e553480156200002657600080fd5b5033610140819052604080516361d027b360e01b815290516361d027b3916004808201926020929091908290030181865afa1580156200006a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000909190620008d4565b6001600160a01b0316610160816001600160a01b0316815250506000806000336001600160a01b031663eb13c4cf6040518163ffffffff1660e01b8152600401606060405180830381865afa158015620000ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001149190620008f9565b8015156080526001600160a01b0380831661010052831660e052604051929550909350915083908390620001489062000803565b6001600160a01b03928316815291166020820152604001604051809103906000f0801580156200017c573d6000803e3d6000fd5b506001600160a01b0316610120528015620003af57826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001d0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001fa919081019062000994565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000239573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000263919081019062000994565b6040516020016200027692919062000a4c565b604051602081830303815290604052600190805190602001906200029c92919062000811565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620002dc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000306919081019062000994565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000345573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200036f919081019062000994565b6040516020016200038292919062000aa7565b60405160208183030381529060405260029080519060200190620003a892919062000811565b50620005c8565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620003ee573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000418919081019062000994565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000457573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000481919081019062000994565b6040516020016200049492919062000af8565b60405160208183030381529060405260019080519060200190620004ba92919062000811565b50826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620004fa573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000524919081019062000994565b826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000563573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200058d919081019062000994565b604051602001620005a092919062000b55565b60405160208183030381529060405260029080519060200190620005c692919062000811565b505b826001600160a01b031663313ce5676040518163ffffffff1660e01b81526004016020604051808303816000875af115801562000609573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200062f919062000b77565b6200063c90600a62000cb1565b6101808181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b81526004016020604051808303816000875af115801562000685573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006ab919062000b77565b620006b890600a62000cb1565b6101a0526040805160608101825242815260006020820181815282840182815260078054600180820183559190945293517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860039094029384015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a9091015590517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f916200078e9162000cfe565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f19818403018152919052805160209091012060a05250504660c0525062000da1565b61051b806200496e83390190565b8280546200081f9062000cc2565b90600052602060002090601f0160209004810192826200084357600085556200088e565b82601f106200085e57805160ff19168380011785556200088e565b828001600101855582156200088e579182015b828111156200088e57825182559160200191906001019062000871565b506200089c929150620008a0565b5090565b5b808211156200089c5760008155600101620008a1565b80516001600160a01b0381168114620008cf57600080fd5b919050565b600060208284031215620008e757600080fd5b620008f282620008b7565b9392505050565b6000806000606084860312156200090f57600080fd5b6200091a84620008b7565b92506200092a60208501620008b7565b9150604084015180151581146200094057600080fd5b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200097e57818101518382015260200162000964565b838111156200098e576000848401525b50505050565b600060208284031215620009a757600080fd5b81516001600160401b0380821115620009bf57600080fd5b818401915084601f830112620009d457600080fd5b815181811115620009e957620009e96200094b565b604051601f8201601f19908116603f0116810190838211818310171562000a145762000a146200094b565b8160405282815287602084870101111562000a2e57600080fd5b62000a4183602083016020880162000961565b979650505050505050565b6e029ba30b13632ab189020a6a690169608d1b81526000835162000a7881600f85016020880162000961565b602f60f81b600f91840191820152835162000a9b81601084016020880162000961565b01601001949350505050565b6473414d4d2d60d81b81526000835162000ac981600585016020880162000961565b602f60f81b600591840191820152835162000aec81600684016020880162000961565b01600601949350505050565b7002b37b630ba34b632ab189020a6a690169607d1b81526000835162000b2681601185016020880162000961565b602f60f81b601191840191820152835162000b4981601284016020880162000961565b01601201949350505050565b6476414d4d2d60d81b81526000835162000ac981600585016020880162000961565b60006020828403121562000b8a57600080fd5b815160ff81168114620008f257600080fd5b634e487b7160e01b600052601160045260246000fd5b600181815b8085111562000bf357816000190482111562000bd75762000bd762000b9c565b8085161562000be557918102915b93841c939080029062000bb7565b509250929050565b60008262000c0c5750600162000cab565b8162000c1b5750600062000cab565b816001811462000c34576002811462000c3f5762000c5f565b600191505062000cab565b60ff84111562000c535762000c5362000b9c565b50506001821b62000cab565b5060208310610133831016604e8410600b841016171562000c84575081810a62000cab565b62000c90838362000bb2565b806000190482111562000ca75762000ca762000b9c565b0290505b92915050565b6000620008f260ff84168362000bfb565b600181811c9082168062000cd757607f821691505b60208210810362000cf857634e487b7160e01b600052602260045260246000fd5b50919050565b600080835481600182811c91508083168062000d1b57607f831692505b6020808410820362000d3b57634e487b7160e01b86526022600452602486fd5b81801562000d52576001811462000d645762000d93565b60ff1986168952848901965062000d93565b60008a81526020902060005b8681101562000d8b5781548b82015290850190830162000d70565b505084890196505b509498975050505050505050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a051613a2b62000f43600039600081816104f10152818161273b015281816129f801528181612aba0152612bc50152600081816104ce015281816126fa015281816129b901528181612afc0152612b9f0152600081816106050152818161240e0152612598015260008181610819015261090901526000818161070001528181611eca0152818161246201526125ec01526000818161057b015281816107550152818161084901528181610ab501528181610da701528181611674015281816118a201528181611d15015281816122e60152818161257601526125ca015260008181610350015281816105530152818161073001528181610a9401528181610d86015281816115de0152818161188001528181611cf30152818161225e015281816123ec0152818161244001528181612a3a01528181612a8101528181612b660152612c09015260006106d90152600081816104a00152611fc801526000818161040901528181610523015281816126d201526129850152613a2b6000f3fe608060405234801561001057600080fd5b50600436106102bb5760003560e01c806370a0823111610182578063bc25cf77116100e9578063d21220a7116100a2578063dd62ed3e1161007c578063dd62ed3e14610886578063ebeb31db146108b1578063f140a35a146108b9578063fff6cae9146108cc57600080fd5b8063d21220a714610844578063d294f0931461086b578063d505accf1461087357600080fd5b8063bc25cf77146107e6578063bda39cad146107f9578063bf944dbc14610802578063c245febc1461080b578063c45a015514610814578063c5700a021461083b57600080fd5b80639af1d35a1161013b5780639af1d35a146106fb5780639d63848a146107225780639e8cc04b146107805780639f767c8814610793578063a1ac4d13146107b3578063a9059cbb146107d357600080fd5b806370a082311461063a5780637ecebe001461065a57806389afcb441461067a5780638a7b8cf2146106a257806395d89b41146106cc5780639a8a0592146106d457600080fd5b806330adf81f116102265780634d5a9f8a116101df5780634d5a9f8a146105b1578063517b3f82146105d15780635881c475146105e45780635a76f25e146105f757806361d027b3146106005780636a6278421461062757600080fd5b806330adf81f14610451578063313ce5671461047857806332c0defd146104925780633644e5151461049b578063392f37e9146104c2578063443cb4bc146105a857600080fd5b806318160ddd1161027857806318160ddd146103aa5780631df8c717146103c1578063205aabf1146103e457806322be3de11461040457806323b872dd1461042b578063252c09d71461043e57600080fd5b8063022c0d9f146102c057806306fdde03146102d55780630902f1ac146102f3578063095ea7b3146103285780630dfe16811461034b57806313345fe11461038a575b600080fd5b6102d36102ce366004613521565b6108d4565b005b6102dd610f94565b6040516102ea91906135e5565b60405180910390f35b600854600954600a54604080516001600160701b03948516815293909216602084015263ffffffff16908201526060016102ea565b61033b610336366004613618565b611022565b60405190151581526020016102ea565b6103727f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102ea565b61039d610398366004613642565b6110ed565b6040516102ea919061367b565b6103b360035481565b6040519081526020016102ea565b6103c96112f5565b604080519384526020840192909252908201526060016102ea565b6103b36103f23660046136bf565b60106020526000908152604090205481565b61033b7f000000000000000000000000000000000000000000000000000000000000000081565b61033b6104393660046136da565b61135d565b6103c961044c366004613716565b61146b565b6103b37f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b610480601281565b60405160ff90911681526020016102ea565b6103b3600d5481565b6103b37f000000000000000000000000000000000000000000000000000000000000000081565b600854600954604080517f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201529081019290925260608201527f0000000000000000000000000000000000000000000000000000000000000000151560808201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660a08301527f00000000000000000000000000000000000000000000000000000000000000001660c082015260e0016102ea565b6103b360085481565b6103b36105bf3660046136bf565b60116020526000908152604090205481565b6103b36105df366004613618565b61149e565b61039d6105f236600461372f565b611586565b6103b360095481565b6103727f000000000000000000000000000000000000000000000000000000000000000081565b6103b36106353660046136bf565b611595565b6103b36106483660046136bf565b60056020526000908152604090205481565b6103b36106683660046136bf565b60066020526000908152604090205481565b61068d6106883660046136bf565b611835565b604080519283526020830191909152016102ea565b6106aa611ba4565b60408051825181526020808401519082015291810151908201526060016102ea565b6102dd611c24565b6103b37f000000000000000000000000000000000000000000000000000000000000000081565b6103727f000000000000000000000000000000000000000000000000000000000000000081565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000166020820152016102ea565b6103b361078e36600461372f565b611c31565b6103b36107a13660046136bf565b600f6020526000908152604090205481565b6103b36107c13660046136bf565b60126020526000908152604090205481565b61033b6107e1366004613618565b611c9e565b6102d36107f43660046136bf565b611cb4565b6103b3600e5481565b6103b3600b5481565b6103b3600c5481565b6103727f000000000000000000000000000000000000000000000000000000000000000081565b6103b3600a5481565b6103727f000000000000000000000000000000000000000000000000000000000000000081565b61068d611e41565b6102d3610881366004613762565b611f68565b6103b36108943660046137d5565b600460209081526000928352604080842090915290825290205481565b6007546103b3565b6103b36108c7366004613808565b6121e7565b6102d361221e565b6000546001146108ff5760405162461bcd60e51b81526004016108f69061382b565b60405180910390fd5b60026000819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b187bd266040518163ffffffff1660e01b8152600401602060405180830381865afa158015610965573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109899190613853565b156109c85760405162461bcd60e51b815260206004820152600f60248201526e44797374506169723a20504155534560881b60448201526064016108f6565b60008511806109d75750600084115b610a2f5760405162461bcd60e51b8152602060048201526024808201527f44797374506169723a20494e53554646494349454e545f4f55545055545f414d60448201526313d5539560e21b60648201526084016108f6565b6008546009548187108015610a4357508086105b610a8f5760405162461bcd60e51b815260206004820181905260248201527f44797374506169723a20494e53554646494349454e545f4c495155494449545960448201526064016108f6565b6000807f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0389811690831614801590610b025750806001600160a01b0316896001600160a01b031614155b610b455760405162461bcd60e51b815260206004820152601460248201527344797374506169723a20494e56414c49445f544f60601b60448201526064016108f6565b8a15610b5f57610b5f6001600160a01b0383168a8d61236b565b8915610b7957610b796001600160a01b0382168a8c61236b565b8615610be657604051639a7bff7960e01b81526001600160a01b038a1690639a7bff7990610bb39033908f908f908e908e90600401613875565b600060405180830381600087803b158015610bcd57600080fd5b505af1158015610be1573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610c2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4e91906138c1565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610c95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb991906138c1565b9250505060008985610ccb91906138f0565b8311610cd8576000610cec565b610ce28a866138f0565b610cec90846138f0565b90506000610cfa8a866138f0565b8311610d07576000610d1b565b610d118a866138f0565b610d1b90846138f0565b90506000821180610d2c5750600081115b610d845760405162461bcd60e51b815260206004820152602360248201527f44797374506169723a20494e53554646494349454e545f494e5055545f414d4f60448201526215539560ea1b60648201526084016108f6565b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008315610de057610de0610ddb6107d086613907565b6123c2565b8215610dfa57610dfa610df56107d085613907565b61254c565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610e3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6291906138c1565b6040516370a0823160e01b81523060048201529096506001600160a01b038216906370a0823190602401602060405180830381865afa158015610ea9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ecd91906138c1565b9450610ed988886126ce565b610ee387876126ce565b1015610f1f5760405162461bcd60e51b815260206004820152600b60248201526a44797374506169723a204b60a81b60448201526064016108f6565b5050610f2d8484888861281a565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001600055505050505050505050565b60018054610fa190613929565b80601f0160208091040260200160405190810160405280929190818152602001828054610fcd90613929565b801561101a5780601f10610fef5761010080835404028352916020019161101a565b820191906000526020600020905b815481529060010190602001808311610ffd57829003601f168201915b505050505081565b60006001600160a01b0383166110885760405162461bcd60e51b815260206004820152602560248201527f44797374506169723a20417070726f766520746f20746865207a65726f206164604482015264647265737360d81b60648201526084016108f6565b3360008181526004602090815260408083206001600160a01b03881680855290835292819020869055518581529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35060015b92915050565b606060008367ffffffffffffffff81111561110a5761110a61395d565b604051908082528060200260200182016040528015611133578160200160208202803683370190505b50600754909150600090611149906001906138f0565b905060006111578587613973565b61116190836138f0565b90506000805b838310156112e5576111798784613992565b9150600060078481548110611190576111906139aa565b906000526020600020906003020160000154600784815481106111b5576111b56139aa565b9060005260206000209060030201600001546111d191906138f0565b9050600081600786815481106111e9576111e96139aa565b9060005260206000209060030201600101546007868154811061120e5761120e6139aa565b90600052602060002090600302016001015461122a91906138f0565b6112349190613907565b90506000826007878154811061124c5761124c6139aa565b90600052602060002090600302016002015460078781548110611271576112716139aa565b90600052602060002090600302016002015461128d91906138f0565b6112979190613907565b90506112a58c8e8484612981565b8885815181106112b7576112b76139aa565b60209081029190910101526112cd846001613992565b935050505086836112de9190613992565b9250611167565b509293505050505b949350505050565b600b54600c544260008080611313600854600954600a549192909190565b63ffffffff1692506001600160701b031692506001600160701b0316925083811461135557600061134482866138f0565b848102979097019683029590950194505b505050909192565b6001600160a01b03831660008181526004602090815260408083203380855292528220549192909190821480159061139757506000198114155b1561145257838110156113ec5760405162461bcd60e51b815260206004820181905260248201527f44797374506169723a20496e73756666696369656e7420616c6c6f77616e636560448201526064016108f6565b6001600160a01b03868116600081815260046020908152604080832094871680845294825291829020888603908190559151828152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505b61145d868686612c76565b6001925050505b9392505050565b6007818154811061147b57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b6000806114a9611ba4565b90506000806114b66112f5565b5084519193509150420361151e57600780546114d4906002906138f0565b815481106114e4576114e46139aa565b9060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505092505b825160009061152d90426138f0565b905060008185602001518561154291906138f0565b61154c9190613907565b905060008286604001518561156191906138f0565b61156b9190613907565b9050611579888a8484612981565b9998505050505050505050565b60606112ed84848460016110ed565b600080546001146115b85760405162461bcd60e51b81526004016108f69061382b565b600260009081556008546009546040516370a0823160e01b8152306004820152919290917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561162d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165191906138c1565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156116bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116df91906138c1565b905060006116ed85846138f0565b905060006116fb85846138f0565b600354909150600081900361173d576103e861171f61171a8486613973565b612df9565b61172991906138f0565b975061173860006103e8612e69565b611772565b61176f8761174b8386613973565b6117559190613907565b876117608486613973565b61176a9190613907565b612efc565b97505b600088116117d25760405162461bcd60e51b815260206004820152602760248201527f44797374506169723a20494e53554646494349454e545f4c495155494449545960448201526617d3525395115160ca1b60648201526084016108f6565b6117dc8989612e69565b6117e88585898961281a565b604080518481526020810184905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001600055509395945050505050565b60008060005460011461185a5760405162461bcd60e51b81526004016108f69061382b565b600260009081556008546009546040516370a0823160e01b8152306004820152919290917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000916001600160a01b038416906370a0823190602401602060405180830381865afa1580156118f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191791906138c1565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611961573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198591906138c1565b3060009081526005602052604090205460035491925090806119a78584613973565b6119b19190613907565b9950806119be8484613973565b6119c89190613907565b985060008a1180156119da5750600089115b611a365760405162461bcd60e51b815260206004820152602760248201527f44797374506169723a20494e53554646494349454e545f4c495155494449545960448201526617d0955493915160ca1b60648201526084016108f6565b611a403083612f12565b611a546001600160a01b0387168c8c61236b565b611a686001600160a01b0386168c8b61236b565b6040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa158015611aac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad091906138c1565b6040516370a0823160e01b81523060048201529094506001600160a01b038616906370a0823190602401602060405180830381865afa158015611b17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3b91906138c1565b9250611b4984848a8a61281a565b604080518b8152602081018b90526001600160a01b038d169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050506001600081905550915091565b611bc860405180606001604052806000815260200160008152602001600081525090565b60078054611bd8906001906138f0565b81548110611be857611be86139aa565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905090565b60028054610fa190613929565b600080611c4185858560016110ed565b90506000805b8251811015611c8957828181518110611c6257611c626139aa565b602002602001015182611c759190613992565b915080611c81816139c0565b915050611c47565b50611c948482613907565b9695505050505050565b6000611cab338484612c76565b50600192915050565b600054600114611cd65760405162461bcd60e51b81526004016108f69061382b565b60026000556008546040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091611dab9185916001600160a01b038616906370a0823190602401602060405180830381865afa158015611d6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9091906138c1565b611d9a91906138f0565b6001600160a01b038516919061236b565b6009546040516370a0823160e01b8152306004820152611e379185916001600160a01b038516906370a0823190602401602060405180830381865afa158015611df8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1c91906138c1565b611e2691906138f0565b6001600160a01b038416919061236b565b5050600160005550565b600080611e4d33612f9d565b50503360009081526011602090815260408083205460129092529091205481151580611e795750600081115b15611f64573360008181526011602090815260408083208390556012909152808220919091555163299e7ae760e11b8152600481019190915260248101839052604481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063533cf5ce90606401600060405180830381600087803b158015611f0e57600080fd5b505af1158015611f22573d6000803e3d6000fd5b505060408051858152602081018590523393508392507f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645910160405180910390a35b9091565b42841015611fac5760405162461bcd60e51b8152602060048201526011602482015270111e5cdd14185a5c8e8811561412549151607a1b60448201526064016108f6565b6001600160a01b038716600090815260066020526040812080547f0000000000000000000000000000000000000000000000000000000000000000917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b918761201a836139c0565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e0016040516020818303038152906040528051906020012060405160200161209392919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa1580156120fe573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906121345750886001600160a01b0316816001600160a01b0316145b6121805760405162461bcd60e51b815260206004820152601b60248201527f44797374506169723a20494e56414c49445f5349474e4154555245000000000060448201526064016108f6565b6001600160a01b038981166000818152600460209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b600854600954600091906121fd6107d086613907565b61220790866138f0565b945061221585858484612981565b95945050505050565b6000546001146122405760405162461bcd60e51b81526004016108f69061382b565b60026000556040516370a0823160e01b8152306004820152612364907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156122ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d191906138c1565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612335573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235991906138c1565b60085460095461281a565b6001600055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526123bd908490613109565b505050565b60006123cf600283613907565b905060006123dd82846138f0565b90506124336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000008461236b565b6124876001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000008361236b565b6003546000906124a56d04ee2d6d415b85acef810000000084613973565b6124af9190613907565b905080156124cf5780600d60008282546124c99190613992565b90915550505b604080518481526000602082015233917ffd26d3e0e8324438b2b556a62f87e2e5864535089e691e5119466433de1ebc61910160405180910390a2604080518381526000602082015233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860291015b60405180910390a250505050565b6000612559600283613907565b9050600061256782846138f0565b90506125bd6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000008461236b565b6126116001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000008361236b565b60035460009061262f6d04ee2d6d415b85acef810000000084613973565b6126399190613907565b905080156126595780600e60008282546126539190613992565b90915550505b60408051600081526020810185905233917ffd26d3e0e8324438b2b556a62f87e2e5864535089e691e5119466433de1ebc61910160405180910390a260408051600081526020810184905233917f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a8602910161253e565b60007f0000000000000000000000000000000000000000000000000000000000000000156128095760007f000000000000000000000000000000000000000000000000000000000000000061272b85670de0b6b3a7640000613973565b6127359190613907565b905060007f000000000000000000000000000000000000000000000000000000000000000061276c85670de0b6b3a7640000613973565b6127769190613907565b90506000670de0b6b3a764000061278d8385613973565b6127979190613907565b90506000670de0b6b3a76400006127ae8480613973565b6127b89190613907565b670de0b6b3a76400006127cb8680613973565b6127d59190613907565b6127df9190613992565b9050670de0b6b3a76400006127f48284613973565b6127fe9190613907565b9450505050506110e7565b6128138284613973565b90506110e7565b600a54429060009061282c90836138f0565b905060008111801561283d57508315155b801561284857508215155b1561286257600b8054858302019055600c80548483020190555b600061286c611ba4565b805190915061287b90846138f0565b91506107088211156129305760408051606081018252848152600b5460208201908152600c549282019283526007805460018101825560009190915291517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390930292830155517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68982015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a909101555b60088790556009869055600a83905560408051888152602081018890527fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a150505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000015612c045760006129b584846126ce565b90507f00000000000000000000000000000000000000000000000000000000000000006129ea85670de0b6b3a7640000613973565b6129f49190613907565b93507f0000000000000000000000000000000000000000000000000000000000000000612a2984670de0b6b3a7640000613973565b612a339190613907565b92506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612a78578486612a7b565b85855b915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b031614612afa577f0000000000000000000000000000000000000000000000000000000000000000612aeb89670de0b6b3a7640000613973565b612af59190613907565b612b37565b7f0000000000000000000000000000000000000000000000000000000000000000612b2d89670de0b6b3a7640000613973565b612b379190613907565b97506000612b4f612b48848b613992565b85846131db565b612b5990836138f0565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b031614612bc3577f0000000000000000000000000000000000000000000000000000000000000000612be5565b7f00000000000000000000000000000000000000000000000000000000000000005b612bef9083613973565b612bf99190613907565b9450505050506112ed565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614612c47578385612c4a565b84845b9092509050612c598783613992565b612c638289613973565b612c6d9190613907565b925050506112ed565b6001600160a01b038216612cdb5760405162461bcd60e51b815260206004820152602660248201527f44797374506169723a205472616e7366657220746f20746865207a65726f206160448201526564647265737360d01b60648201526084016108f6565b612ce483612f9d565b612ced82612f9d565b6001600160a01b03831660009081526005602052604090205481811015612d685760405162461bcd60e51b815260206004820152602960248201527f44797374506169723a205472616e7366657220616d6f756e7420657863656564604482015268732062616c616e636560b81b60648201526084016108f6565b6001600160a01b03808516600090815260056020526040808220858503905591851681529081208054849290612d9f908490613992565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612deb91815260200190565b60405180910390a350505050565b60006003821115612e5a5750806000612e13600283613907565b612e1e906001613992565b90505b81811015612e5457905080600281612e398186613907565b612e439190613992565b612e4d9190613907565b9050612e21565b50919050565b8115612e64575060015b919050565b612e7282612f9d565b8060036000828254612e849190613992565b90915550506001600160a01b03821660009081526005602052604081208054839290612eb1908490613992565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612f0b5781611464565b5090919050565b612f1b82612f9d565b8060036000828254612f2d91906138f0565b90915550506001600160a01b03821660009081526005602052604081208054839290612f5a9084906138f0565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612ef0565b6001600160a01b03811660009081526005602052604090205480156130d7576001600160a01b0382166000908152600f60209081526040808320805460108085529285208054600d54600e54948190559490955282905593612fff85846138f0565b9050600061300d85846138f0565b9050811561306e5760006d04ee2d6d415b85acef8100000000613030848a613973565b61303a9190613907565b6001600160a01b038a16600090815260116020526040812080549293508392909190613067908490613992565b9091555050505b80156130cd5760006d04ee2d6d415b85acef810000000061308f838a613973565b6130999190613907565b6001600160a01b038a166000908152601260205260408120805492935083929091906130c6908490613992565b9091555050505b5050505050505050565b600d546001600160a01b0383166000908152600f6020908152604080832093909355600e546010909152919020555050565b600061315e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132bd9092919063ffffffff16565b8051909150156123bd578080602001905181019061317c9190613853565b6123bd5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108f6565b6000805b60ff8110156132b4578260006131f58783613383565b90508581101561324557600061320b8887613420565b61321583896138f0565b61322790670de0b6b3a7640000613973565b6132319190613907565b905061323d8187613992565b955050613287565b60006132518887613420565b61325b88846138f0565b61326d90670de0b6b3a7640000613973565b6132779190613907565b905061328381876138f0565b9550505b61329385836001613488565b1561329f5750506132b4565b505080806132ac906139c0565b9150506131df565b50909392505050565b60606001600160a01b0384163b6133165760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108f6565b600080856001600160a01b03168560405161333191906139d9565b6000604051808303816000865af19150503d806000811461336e576040519150601f19603f3d011682016040523d82523d6000602084013e613373565b606091505b5091509150611c948282866134d1565b6000670de0b6b3a76400008281858161339c8280613973565b6133a69190613907565b6133b09190613973565b6133ba9190613907565b6133c49190613973565b6133ce9190613907565b670de0b6b3a76400008084816133e48280613973565b6133ee9190613907565b6133f89190613973565b6134029190613907565b61340c9086613973565b6134169190613907565b6114649190613992565b6000670de0b6b3a764000083816134378280613973565b6134419190613907565b61344b9190613973565b6134559190613907565b670de0b6b3a7640000806134698580613973565b6134739190613907565b61347e866003613973565b61340c9190613973565b6000828411156134af578161349d84866138f0565b116134aa57506001611464565b6134c7565b816134ba85856138f0565b116134c757506001611464565b5060009392505050565b606083156134e0575081611464565b8251156134f05782518084602001fd5b8160405162461bcd60e51b81526004016108f691906135e5565b80356001600160a01b0381168114612e6457600080fd5b60008060008060006080868803121561353957600080fd5b85359450602086013593506135506040870161350a565b9250606086013567ffffffffffffffff8082111561356d57600080fd5b818801915088601f83011261358157600080fd5b81358181111561359057600080fd5b8960208285010111156135a257600080fd5b9699959850939650602001949392505050565b60005b838110156135d05781810151838201526020016135b8565b838111156135df576000848401525b50505050565b60208152600082518060208401526136048160408501602087016135b5565b601f01601f19169190910160400192915050565b6000806040838503121561362b57600080fd5b6136348361350a565b946020939093013593505050565b6000806000806080858703121561365857600080fd5b6136618561350a565b966020860135965060408601359560600135945092505050565b6020808252825182820181905260009190848201906040850190845b818110156136b357835183529284019291840191600101613697565b50909695505050505050565b6000602082840312156136d157600080fd5b6114648261350a565b6000806000606084860312156136ef57600080fd5b6136f88461350a565b92506137066020850161350a565b9150604084013590509250925092565b60006020828403121561372857600080fd5b5035919050565b60008060006060848603121561374457600080fd5b61374d8461350a565b95602085013595506040909401359392505050565b600080600080600080600060e0888a03121561377d57600080fd5b6137868861350a565b96506137946020890161350a565b95506040880135945060608801359350608088013560ff811681146137b857600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156137e857600080fd5b6137f18361350a565b91506137ff6020840161350a565b90509250929050565b6000806040838503121561381b57600080fd5b823591506137ff6020840161350a565b6020808252600e908201526d1499595b9d1c985b9d0818d85b1b60921b604082015260600190565b60006020828403121561386557600080fd5b8151801515811461146457600080fd5b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b6000602082840312156138d357600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082821015613902576139026138da565b500390565b60008261392457634e487b7160e01b600052601260045260246000fd5b500490565b600181811c9082168061393d57607f821691505b602082108103612e5457634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600081600019048311821515161561398d5761398d6138da565b500290565b600082198211156139a5576139a56138da565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016139d2576139d26138da565b5060010190565b600082516139eb8184602087016135b5565b919091019291505056fea264697066735822122006bb5909be9ff4c297da1d5f3d4dbe342cc91af21b15a3b82decb59c6c7274e564736f6c634300080d003360e060405234801561001057600080fd5b5060405161051b38038061051b83398101604081905261002f91610066565b336080526001600160a01b0391821660a0521660c052610099565b80516001600160a01b038116811461006157600080fd5b919050565b6000806040838503121561007957600080fd5b6100828361004a565b91506100906020840161004a565b90509250929050565b60805160a05160c0516104566100c5600039600060fa0152600060c001526000605001526104566000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063533cf5ce14610030575b600080fd5b61004361003e36600461033e565b610045565b005b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146100ad5760405162461bcd60e51b81526020600482015260086024820152672737ba103830b4b960c11b60448201526064015b60405180910390fd5b81156100e7576100e76001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168484610126565b8015610121576101216001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168483610126565b505050565b604080516001600160a01b03848116602483015260448083018590528351808403909101815260649092018352602080830180516001600160e01b031663a9059cbb60e01b17905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490840152610121928692916000916101b6918516908490610233565b80519091501561012157808060200190518101906101d4919061037f565b6101215760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016100a4565b60606001600160a01b0384163b61028c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016100a4565b600080856001600160a01b0316856040516102a791906103d1565b6000604051808303816000865af19150503d80600081146102e4576040519150601f19603f3d011682016040523d82523d6000602084013e6102e9565b606091505b50915091506102f9828286610305565b925050505b9392505050565b606083156103145750816102fe565b8251156103245782518084602001fd5b8160405162461bcd60e51b81526004016100a491906103ed565b60008060006060848603121561035357600080fd5b83356001600160a01b038116811461036a57600080fd5b95602085013595506040909401359392505050565b60006020828403121561039157600080fd5b815180151581146102fe57600080fd5b60005b838110156103bc5781810151838201526020016103a4565b838111156103cb576000848401525b50505050565b600082516103e38184602087016103a1565b9190910192915050565b602081526000825180602084015261040c8160408501602087016103a1565b601f01601f1916919091016040019291505056fea2646970667358221220d1ce0140efcf34827a9f874df7170c8c9fad0afa1115373845d238368c2706ff64736f6c634300080d0033

Loading