Contract 0xabca7538233cbe69709c004c52dc37e61c03796b

 
 
Txn Hash
Method
Block
From
To
Value [Txn Fee]
0x975faa8ac395f234ef9e8e632782840095318d82decc65a162e412819dc3f564Approve380779862023-01-14 18:28:13138 days 23 hrs ago0x9680243788d33af307b10f39a65156a1db1152ed IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.001205500243 45.846970559
0xee755dd13e112de1aea0865ee87c980e031c176e76cecffb4e4214d7e6aa62c9Approve352051622022-11-04 21:17:13209 days 20 hrs ago0x782ff8960bced0e73b2acc0322cde7ef952f3bf6 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.026064406 977
0x634d54803d50678aeafa448107554935e9f15f1d83d368ae0e57efc863e38eaeApprove352051622022-11-04 21:17:13209 days 20 hrs ago0x782ff8960bced0e73b2acc0322cde7ef952f3bf6 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.001976769937 74.097381274
0x67cefe941d84efa886a8d709c727cef82c5262ecd8388994903c7db01efc21b5Approve351901352022-11-04 12:28:51210 days 5 hrs ago0x782ff8960bced0e73b2acc0322cde7ef952f3bf6 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.013345290732 286.514893994
0xff42fa1b46e1f93fd08e7b92d1bb55aecdd48e989e3fd65fef461129bd9ae556Approve350214362022-10-31 9:22:09214 days 8 hrs ago0x4ffd0a59a26cb2aa76d403215e4cc2845c053994 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.001445782395 31.040027376
0x2bed62dcbb797ea9e31ed8e5d6c3330724efdddb933beb2f8e2b0a4fc338eb17Approve349953312022-10-30 17:52:30215 days 9 mins ago0x51c1ce246708b2a198f7e7e9dc3d154ee4cd9572 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.002096010039 45.000000845
0xe7e6ae8641b71315f56d9434024aca8612063e669cc1ecdb195fcd56faf87545Approve347459162022-10-24 15:06:30221 days 2 hrs ago0x862e31966762ab36eea0a43e5d7ee5fddfa47e93 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.008280910821 310.402234857
0x5c19615ccb5faf138fc29d6c6e46ba737d0acd3f8d644f367d3b8e53fcd11ff2Approve347459162022-10-24 15:06:30221 days 2 hrs ago0x862e31966762ab36eea0a43e5d7ee5fddfa47e93 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.011041887583 237.062295151
0xc4baf1adacf11cc93de6afd68ae8ebdae7752853efbcdf524546acfbeb7fdfabApprove344254062022-10-16 18:08:03228 days 23 hrs ago0x63712c2f30f48ff20beb3837578071b70cea9f07 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.004131757546 88.706203507
0x39bf3921103702c5ab1185d31cd981272e754a7979d9a4686751d65805ecc503Approve325018952022-08-31 2:00:21275 days 16 hrs ago0x751329b3a2a92fbeffdac3eaa5f9fbea7584a0bc IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.001407484582 30.217797718
0x7053de7374d528a9fa66da0cfc83a00c762a7f2ba7c334574956951aee0086adApprove313515392022-07-31 11:24:42306 days 6 hrs ago0xe4693c25dccf4e34ea71336ccdb1bbff61aac267 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.002045784965 43.921700495
0xfc7c1bf4791abc484f256828b53664afd5d4fff56b94c7686b34a5e2e9660a45Approve302250712022-07-01 19:46:19335 days 22 hrs ago0xcfdd6663018840621fa812ba6043acb5b1fa29d1 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.001557403921 33.436470479
0x5d860be8a720b143cb8cd054600a6038623a338972ca7967d2be6591fda75eadApprove300499862022-06-27 7:00:49340 days 11 hrs ago0xa674af21ef3b5b2a8c0a944bce1e394fa2982a65 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.004005708 86
0x48613c16da878700bfa121dee5629e1a631e6b784da8dd18bb4905919298004cApprove298558762022-06-22 5:17:27345 days 12 hrs ago0x396932cf21d7a37eb8db923d669fcd5bc0c751d2 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.0014299446 30.7
0xfca3eb7fbaf50f958cc78efaa6d1e3ab81a6e318a6fc6a20d6ce1d118a469b36Approve291012932022-06-03 4:37:16364 days 13 hrs ago0x49a5492fdfe5acc966dd5f41310dfdfe8daa349c IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.00139734 30.000000018
0x9b4aee098de41cb832e9fdfed730ff8ebb173125630042d5e209e054d336e624Approve276797942022-04-28 14:13:25400 days 3 hrs ago0x4f49d938c3ad2437c52eb314f9bd7bdb7fa58da9 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.002690061061 57.753898018
0x9067912a2e5981db93801aea496ff2fb48947b40d23c08e1dbf27180e0e0e335Approve274491862022-04-22 16:57:12406 days 1 hr ago0xd0548dbbc3683a6c0b6a98445372c403585dea20 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.001987949439 42.680008587
0xeac59321999338e9c597479ba7a1209000ab0a6209d510bf9834c5eb4e513c5dApprove273170042022-04-19 8:33:13409 days 9 hrs ago0xeddb8b0c46193caea0c2b453fb1e256ab68826df IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.00281995259 60.542586418
0x880a6c29513914a79c1f5ca45b07a9a6c7a3fc0d7a616f8771f0215f5c252b25Approve272943782022-04-18 18:35:18409 days 23 hrs ago0x6ab880afd1e0c7786cc5d05f4fd9b17761768da8 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.0069867 150
0x4578ed903399ac6958a21ac5b1ed31328d150c2a9b9ff0b895acb7fcabdee856Approve270208162022-04-11 19:58:48416 days 22 hrs ago0x5df89d47506b03180bd0c77fc23e0fe1b33f5853 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.00198794943942.680008587
0x87234f6c20f3c5056f95699c70aa5b54d6a0b7e64041270a3c59741ffbdf2d47Approve268461962022-04-07 8:43:30421 days 9 hrs ago0x7b2483d0f917a4f7a04d1e13743c99ad9d249462 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.001536265027 32.982631879
0xd2a93731c470000cac0d4b6e0984725b5d6168648d8b89def989f1a0e0878e21Approve268290492022-04-06 22:08:53421 days 19 hrs ago0xe6fcb51c7ee5d15a5c8fc2b23d167db6a963c799 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.001892589328 40.632687714
0x19ee85ad5df3830000dbcd7de2d2e2f91cd222c690348e59fb7d0959fdd2543cApprove267766262022-04-05 14:37:19423 days 3 hrs ago0xece7c7a2524fd3c08a351134f101794dbfc96b0d IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.001987949439 42.680008587
0x38e3662e179fc8e12dded65eed5d56f6e1bbe7390cf7a60eac4d10a8ffa07474Approve267324672022-04-04 11:37:51424 days 6 hrs ago0x69d0341d380a1229f4751a0a721345dbc716586c IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.00198794943942.680008587
0x48d3107fab0b9c5243dd7051ac2164b7a6a8f4d30dc19abef65a37151ffb2665Approve266426882022-04-02 4:43:07426 days 13 hrs ago0xdb19c47e87ed3ff37425a99b9dee1f4920f755b9 IN  0xabca7538233cbe69709c004c52dc37e61c03796b0 MATIC0.003271359252 70.234000003
[ Download CSV Export 
Latest 1 internal transaction
Parent Txn Hash Block From To Value
0xf76f022003e5e6512ba85823865b2955911700534134fe83d773dd491761e0ed262998652022-03-24 8:48:17435 days 9 hrs ago Tetu: TetuSwap Factory  Contract Creation0 MATIC
[ Download CSV Export 
Loading

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

Contract Name:
TetuSwapPair

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 150 runs

Other Settings:
default evmVersion
File 1 of 16 : TetuSwapPair.sol
// SPDX-License-Identifier: ISC
/**
* By using this software, you understand, acknowledge and accept that Tetu
* and/or the underlying software are provided “as is” and “as available”
* basis and without warranties or representations of any kind either expressed
* or implied. Any use of this open source software released under the ISC
* Internet Systems Consortium license is done at your own risk to the fullest
* extent permissible pursuant to applicable law any and all liability as well
* as all warranties, including any fitness for a particular purpose with respect
* to Tetu and/or the underlying software and the use thereof are disclaimed.
*/

pragma solidity 0.8.4;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

import "./TetuSwapERC20.sol";
import "./libraries/UQ112x112.sol";
import "./libraries/Math.sol";
import "./libraries/TetuSwapLibrary.sol";
import "../third_party/uniswap/IUniswapV2Callee.sol";
import "../third_party/uniswap/IUniswapV2Factory.sol";
import "../third_party/IERC20Name.sol";
import "../base/interface/ISmartVault.sol";
import "./interfaces/ITetuSwapPair.sol";

/// @title Tetu swap pair based on Uniswap solution
///        Invest underlying assets to Tetu SmartVaults
/// @author belbix
contract TetuSwapPair is TetuSwapERC20, ITetuSwapPair, ReentrancyGuard {
  using SafeERC20 for IERC20;
  using UQ112x112 for uint224;

  // ********** CONSTANTS ********************
  /// @notice Version of the contract
  /// @dev Should be incremented when contract changed
  string public constant VERSION = "1.0.0";
  uint public constant PRECISION = 10000;
  uint public constant MAX_FEE = 30;
  uint public constant override MINIMUM_LIQUIDITY = 10 ** 3;

  // ********** VARIABLES ********************
  address public override factory;
  address public override rewardRecipient;
  address public override token0;
  address public override token1;
  address public override vault0;
  address public override vault1;

  uint112 private reserve0;
  uint112 private reserve1;

  uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves
  uint public override price0CumulativeLast;
  uint public override price1CumulativeLast;
  string private _symbol;
  uint public override fee;
  uint public createdTs;
  uint public createdBlock;

  // ********** EVENTS ********************

  event Mint(address indexed sender, uint amount0, uint amount1);
  event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
  event Swap(
    address indexed sender,
    uint amount0In,
    uint amount1In,
    uint amount0Out,
    uint amount1Out,
    address indexed to
  );
  event Sync(uint112 reserve0, uint112 reserve1);
  event FeeChanged(uint oldFee, uint newFee);
  event VaultsChanged(address vault0, address vault1);
  event RewardRecipientChanged(address oldRecipient, address newRecipient);
  event Claimed(uint blockTs);

  /// @dev Should be create only from factory
  constructor() {
    factory = msg.sender;
  }

  modifier onlyFactory() {
    require(msg.sender == factory, "TSP: Not factory");
    _;
  }

  /// @dev Called once by the factory at time of deployment
  function initialize(
    address _token0,
    address _token1,
    uint _fee
  ) external override onlyFactory {
    require(_fee <= MAX_FEE, "TSP: Too high fee");
    require(token0 == address(0), "TSP: Already initialized");
    require(token1 == address(0), "TSP: Already initialized");
    token0 = _token0;
    token1 = _token1;
    fee = _fee;
    _symbol = createPairSymbol(IERC20Name(_token0).symbol(), IERC20Name(_token1).symbol());
    createdTs = block.timestamp;
    createdBlock = block.number;
  }

  function symbol() external override view returns (string memory) {
    return _symbol;
  }

  /// @dev Return saved reserves. Be aware that reserves always fluctuate!
  ///      For actual values need to call update
  function getReserves() public view override returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
    _reserve0 = reserve0;
    _reserve1 = reserve1;
    _blockTimestampLast = blockTimestampLast;
  }

  /// @dev Update reserves and, on the first call per block, price accumulators
  function _update() private {
    uint _balance0 = vaultReserve0();
    uint _balance1 = vaultReserve1();
    require(_balance0 <= type(uint112).max && _balance1 <= type(uint112).max, "TSP: OVERFLOW");

    uint32 blockTimestamp = uint32(block.timestamp % 2 ** 32);
    uint32 timeElapsed = blockTimestamp - blockTimestampLast;

    if (timeElapsed > 0 && reserve0 != 0 && reserve1 != 0) {
      price0CumulativeLast += uint(UQ112x112.encode(reserve1).uqdiv(reserve0)) * timeElapsed;
      price1CumulativeLast += uint(UQ112x112.encode(reserve0).uqdiv(reserve1)) * timeElapsed;
    }

    reserve0 = uint112(_balance0);
    reserve1 = uint112(_balance1);
    blockTimestampLast = blockTimestamp;
    emit Sync(reserve0, reserve1);
  }

  /// @dev Assume underlying tokens already sent to this contract
  ///      Mint new LP tokens to sender. Based on vault shares
  function mint(address to) external nonReentrant override returns (uint liquidity) {
    uint shareAmount0 = IERC20(vault0).balanceOf(address(this));
    uint shareAmount1 = IERC20(vault1).balanceOf(address(this));

    uint underlyingAmount0 = depositAllToVault(vault0);
    uint underlyingAmount1 = depositAllToVault(vault1);

    uint depositedAmount0 = IERC20(vault0).balanceOf(address(this)) - shareAmount0;
    uint depositedAmount1 = IERC20(vault1).balanceOf(address(this)) - shareAmount1;

    uint _totalSupply = totalSupply;
    if (_totalSupply == 0) {
      liquidity = Math.sqrt(depositedAmount0 * depositedAmount1) - MINIMUM_LIQUIDITY;
      // permanently lock the first MINIMUM_LIQUIDITY tokens
      _mint(address(0), MINIMUM_LIQUIDITY);
    } else {
      liquidity = Math.min(
        depositedAmount0 * _totalSupply / shareAmount0,
        depositedAmount1 * _totalSupply / shareAmount1
      );
    }

    require(liquidity > 0, "TSP: Insufficient liquidity minted");
    _mint(to, liquidity);

    _update();
    emit Mint(msg.sender, underlyingAmount0, underlyingAmount1);
  }

  /// @dev Assume lp token already sent to this contract
  ///      Burn LP tokens and send back underlying assets. Based on vault shares
  function burn(address to) external nonReentrant override returns (uint amount0, uint amount1) {
    uint shareAmount0 = IERC20(vault0).balanceOf(address(this));
    uint shareAmount1 = IERC20(vault1).balanceOf(address(this));
    uint liquidity = balanceOf[address(this)];

    uint shareToWithdraw0 = liquidity * shareAmount0 / totalSupply;
    uint shareToWithdraw1 = liquidity * shareAmount1 / totalSupply;

    require(shareToWithdraw0 > 0 && shareToWithdraw1 > 0, "TSP: Insufficient liquidity burned");
    _burn(address(this), liquidity);

    require(shareToWithdraw0 <= IERC20(vault0).balanceOf(address(this)), "TSP: Insufficient shares 0");
    require(shareToWithdraw1 <= IERC20(vault1).balanceOf(address(this)), "TSP: Insufficient shares 1");

    ISmartVault(vault0).withdraw(shareToWithdraw0);
    ISmartVault(vault1).withdraw(shareToWithdraw1);

    amount0 = IERC20(token0).balanceOf(address(this));
    amount1 = IERC20(token1).balanceOf(address(this));

    IERC20(token0).safeTransfer(to, amount0);
    IERC20(token1).safeTransfer(to, amount1);

    _update();
    emit Burn(msg.sender, amount0, amount1, to);
  }

  /// @dev Assume tokenIn already sent to this contract
  ///      During swap process underlying assets will be deposited and withdrew from vaults
  ///      Depends on vault logic, underlying asset can be deposited with little reducing of amount
  ///      For keeping healthy K we are auto-compounding 1/10 of fees
  function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external nonReentrant override {
    require(amount0Out > 0 || amount1Out > 0, "TSP: Insufficient output amount");
    (uint112 _reserve0, uint112 _reserve1,) = getReserves();
    require(amount0Out < _reserve0 && amount1Out < _reserve1, "TSP: Insufficient liquidity");

    uint expectedAmountIn0 = getAmountIn(amount1Out, _reserve0, _reserve1);
    uint expectedAmountIn1 = getAmountIn(amount0Out, _reserve1, _reserve0);

    // assume we invested all funds and have on balance only new tokens for current swap
    uint amount0In = IERC20(token0).balanceOf(address(this));
    uint amount1In = IERC20(token1).balanceOf(address(this));
    // check amountIn for cases of vault reserves fluctuations
    // we check accurate input value with required fees
    require(amount0In >= expectedAmountIn0 && amount1In >= expectedAmountIn1, "TSP: Insufficient input amount");

    if (amount0In > 0) {
      ISmartVault(vault0).deposit(amount0In);
    }
    if (amount1In > 0) {
      ISmartVault(vault1).deposit(amount1In);
    }

    {// scope for optimistically transfer output amount
      uint amountFee = 0;
      if (amount0In > amount1In) {
        amountFee = getFeeAmount(amount0In, _reserve0, _reserve1, amount1Out);
      } else {
        amountFee = getFeeAmount(amount1In, _reserve1, _reserve0, amount0Out);
      }
      _optimisticallyTransfer(amount0Out, amount1Out, to, data, amountFee);
    }

    // K value should be in a healthy range
    // in a normal circumstance not required after input amount checking
    // but kept for excluding for any possibilities of vault reserve manipulation
    {// scope for K checking
      uint balance0 = vaultReserve0();
      uint balance1 = vaultReserve1();
      // check K without fees
      require(balance0 * balance1 >= uint(_reserve0) * uint(_reserve1), "TSP: K too low");
    }

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

  /// @dev Force update
  function sync() external nonReentrant override {
    _update();
  }

  // ******************************************************
  // ************ NON UNISWAP FUNCTIONS *******************
  // ******************************************************

  /// @dev Returns expected input amount for given output amount
  function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) public view returns (uint amountIn){
    if (amountOut == 0) {
      return 0;
    }
    return TetuSwapLibrary.getAmountIn(amountOut, reserveIn, reserveOut, fee);
  }

  /// @dev Calculates fee amount assuming that amountOutWithFee includes actual fee
  ///      Keep 1/10 of fee for auto-compounding
  ///      In case of 0 fees we will not able to use vaults with deposited amount fluctuations
  function getFeeAmount(uint amountIn, uint reserveIn, uint reserveOut, uint amountOutWithFee) public pure returns (uint amountFee){
    if (amountIn == 0) {
      return 0;
    }
    uint amountOutWithoutFee = TetuSwapLibrary.getAmountOut(amountIn, reserveIn, reserveOut, 0);
    if (amountOutWithoutFee <= amountOutWithFee) {
      return 0;
    }
    // keep 10% for auto compounding
    amountFee = (amountOutWithoutFee - amountOutWithFee) * 9 / 10;
  }

  /// @dev Returns vault underlying balance, or zero if it is not a underlying token
  function balanceOfVaultUnderlying(address _token) external view override returns (uint){
    if (_token == ISmartVault(vault0).underlying()) {
      return ISmartVault(vault0).underlyingBalanceWithInvestmentForHolder(address(this));
    } else if (_token == ISmartVault(vault1).underlying()) {
      return ISmartVault(vault1).underlyingBalanceWithInvestmentForHolder(address(this));
    }
    return 0;
  }

  /// @dev Returns vault underlying balance for this contract
  function vaultReserve0() public view returns (uint112) {
    return uint112(ISmartVault(vault0).underlyingBalanceWithInvestmentForHolder(address(this)));
  }

  /// @dev Returns vault underlying balance for this contract
  function vaultReserve1() public view returns (uint112){
    return uint112(ISmartVault(vault1).underlyingBalanceWithInvestmentForHolder(address(this)));
  }

  // ********* GOVERNANCE FUNCTIONS ****************

  /// @dev Set fee in range 0-0.3%
  function setFee(uint _fee) external override onlyFactory {
    require(_fee <= MAX_FEE, "TSP: Too high fee");
    emit FeeChanged(fee, _fee);
    fee = _fee;
  }

  /// @dev Called by fee setter after pair initialization
  function setVaults(address _vault0, address _vault1) external override onlyFactory {
    require(ISmartVault(_vault0).underlying() == token0, "TSP: Wrong vault0 underlying");
    require(ISmartVault(_vault1).underlying() == token1, "TSP: Wrong vault1 underlying");

    exitFromVault(vault0);
    exitFromVault(vault1);

    vault0 = _vault0;
    vault1 = _vault1;

    IERC20(token0).safeApprove(_vault0, type(uint).max);
    IERC20(token1).safeApprove(_vault1, type(uint).max);

    depositAllToVault(vault0);
    depositAllToVault(vault1);
    emit VaultsChanged(vault0, vault1);
  }

  /// @dev Set rewards recipient. This address will able to claim vault rewards and get swap fees
  function setRewardRecipient(address _recipient) external override onlyFactory {
    emit RewardRecipientChanged(rewardRecipient, _recipient);
    rewardRecipient = _recipient;
  }

  /// @dev Only reward recipient able to call it
  ///      Claims vaults rewards and send it to recipient
  function claimAll() external override {
    require(msg.sender == rewardRecipient, "TSP: Only recipient can claim");
    _claim(vault0);
    _claim(vault1);
    emit Claimed(block.timestamp);
  }

  // ***************** INTERNAL LOGIC ****************

  /// @dev Transfers output amount + fees
  function _optimisticallyTransfer(
    uint amount0Out,
    uint amount1Out,
    address to,
    bytes calldata data,
    uint amountFee
  ) private {
    address _token0 = token0;
    address _token1 = token1;
    require(to != _token0 && to != _token1, "TSP: Invalid to");
    if (amount0Out > 0) {
      withdrawFromVault(vault0, amount0Out + amountFee);
      IERC20(_token0).safeTransfer(to, amount0Out);
      if (amountFee > 0) {
        IERC20(_token0).safeTransfer(rewardRecipient, amountFee);
      }
    }
    if (amount1Out > 0) {
      withdrawFromVault(vault1, amount1Out + amountFee);
      IERC20(_token1).safeTransfer(to, amount1Out);
      if (amountFee > 0) {
        IERC20(_token1).safeTransfer(rewardRecipient, amountFee);
      }
    }
    if (data.length > 0) {
      IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data);
    }
  }

  /// @dev Deposit all underlying tokens to given vault
  function depositAllToVault(address _vault) private returns (uint) {
    uint underlyingAmount = IERC20(ISmartVault(_vault).underlying()).balanceOf(address(this));
    if (underlyingAmount > 0) {
      ISmartVault(_vault).deposit(underlyingAmount);
    }
    return underlyingAmount;
  }

  /// @dev Exit from given vault and set approve to zero for underlying token
  function exitFromVault(address _vault) private {
    if (_vault == address(0)) {
      return;
    }
    uint balance = IERC20(_vault).balanceOf(address(this));
    if (balance > 0) {
      ISmartVault(_vault).withdraw(balance);
    }
    IERC20(ISmartVault(_vault).underlying()).safeApprove(_vault, 0);
  }

  /// @dev Withdraw approx amount of underlying amount from given vault
  function withdrawFromVault(address _vault, uint _underlyingAmount) private {
    ISmartVault sv = ISmartVault(_vault);
    uint shareBalance = IERC20(_vault).balanceOf(address(this));
    uint shareToWithdraw = _underlyingAmount * sv.underlyingUnit() / sv.getPricePerFullShare();
    // add 1 for avoiding rounding issues
    shareToWithdraw = Math.min(shareToWithdraw + 1, shareBalance);
    require(shareToWithdraw <= shareBalance, "TSP: Insufficient shares");
    sv.withdraw(shareToWithdraw);
  }

  /// @dev Creates symbol string from given names
  function createPairSymbol(string memory name0, string memory name1) private pure returns (string memory) {
    return string(abi.encodePacked("TLP_", name0, "_", name1));
  }

  /// @dev Claim all rewards from given vault and send to reward recipient
  function _claim(address _vault) private {
    require(_vault != address(0), "TSP: Zero vault");
    ISmartVault sv = ISmartVault(_vault);

    for (uint i = 0; i < sv.rewardTokensLength(); i++) {
      address rt = sv.rewardTokens()[i];
      uint bal = IERC20(rt).balanceOf(address(this));
      sv.getReward(rt);
      uint claimed = IERC20(rt).balanceOf(address(this)) - bal;
      if (claimed > 0) {
        IERC20(rt).safeTransfer(rewardRecipient, claimed);
      }
    }
  }
}

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

pragma solidity ^0.8.0;

/**
 * @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 16 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../../../utils/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,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

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

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

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

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - 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 4 of 16 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 5 of 16 : TetuSwapERC20.sol
// SPDX-License-Identifier: ISC
/**
* By using this software, you understand, acknowledge and accept that Tetu
* and/or the underlying software are provided “as is” and “as available”
* basis and without warranties or representations of any kind either expressed
* or implied. Any use of this open source software released under the ISC
* Internet Systems Consortium license is done at your own risk to the fullest
* extent permissible pursuant to applicable law any and all liability as well
* as all warranties, including any fitness for a particular purpose with respect
* to Tetu and/or the underlying software and the use thereof are disclaimed.
*/

pragma solidity 0.8.4;

/// @title Uniswap implementation of ERC20 token with permit
///        https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2ERC20.sol
abstract contract TetuSwapERC20 {

  // ******** CONSTANTS ****************

  string private constant DEFAULT_SYMBOL = "TLP";
  string public constant name = "TetuSwap LP";
  uint8 public constant decimals = 18;

  // ******** VARIABLES ****************
  uint  public totalSupply;
  mapping(address => uint) public balanceOf;
  mapping(address => mapping(address => uint)) public allowance;
  bytes32 public DOMAIN_SEPARATOR;
  // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
  bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
  mapping(address => uint) public nonces;

  // ******** EVENTS ******************

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

  constructor() {
    uint _chainId;
    assembly {
      _chainId := chainid()
    }
    DOMAIN_SEPARATOR = keccak256(
      abi.encode(
        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
        keccak256(bytes(name)),
        keccak256(bytes("1")),
        _chainId,
        address(this)
      )
    );
  }

  function symbol() external virtual view returns (string memory) {
    return DEFAULT_SYMBOL;
  }

  function _mint(address to, uint value) internal {
    totalSupply += value;
    balanceOf[to] += value;
    emit Transfer(address(0), to, value);
  }

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

  function _approve(address owner, address spender, uint value) private {
    allowance[owner][spender] = value;
    emit Approval(owner, spender, value);
  }

  function _transfer(address from, address to, uint value) private {
    balanceOf[from] -= value;
    balanceOf[to] += value;
    emit Transfer(from, to, value);
  }

  function approve(address spender, uint value) external returns (bool) {
    _approve(msg.sender, spender, value);
    return true;
  }

  function transfer(address to, uint value) external returns (bool) {
    _transfer(msg.sender, to, value);
    return true;
  }

  function transferFrom(address from, address to, uint value) external returns (bool) {
    if (allowance[from][msg.sender] != type(uint).max) {
      allowance[from][msg.sender] -= value;
    }
    _transfer(from, to, value);
    return true;
  }

  function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
    require(deadline >= block.timestamp, "TetuSwapERC20: 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, "TetuSwapERC20: INVALID_SIGNATURE");
    _approve(owner, spender, value);
  }
}

File 6 of 16 : UQ112x112.sol
// SPDX-License-Identifier: ISC
/**
* By using this software, you understand, acknowledge and accept that Tetu
* and/or the underlying software are provided “as is” and “as available”
* basis and without warranties or representations of any kind either expressed
* or implied. Any use of this open source software released under the ISC
* Internet Systems Consortium license is done at your own risk to the fullest
* extent permissible pursuant to applicable law any and all liability as well
* as all warranties, including any fitness for a particular purpose with respect
* to Tetu and/or the underlying software and the use thereof are disclaimed.
*/

pragma solidity 0.8.4;

/// @title Uniswap UQ112x112 solution https://github.com/Uniswap/v2-core/blob/master/contracts/libraries/UQ112x112.sol
///        A library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
/// @dev range: [0, 2**112 - 1]
///      resolution: 1 / 2**112
library UQ112x112 {
  uint224 constant Q112 = 2 ** 112;

  /// @dev Encode a uint112 as a UQ112x112
  function encode(uint112 y) internal pure returns (uint224 z) {
    z = uint224(y) * Q112;
    // never overflows
  }

  /// @dev Divide a UQ112x112 by a uint112, returning a UQ112x112
  function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
    z = x / uint224(y);
  }
}

File 7 of 16 : Math.sol
// SPDX-License-Identifier: ISC
/**
* By using this software, you understand, acknowledge and accept that Tetu
* and/or the underlying software are provided “as is” and “as available”
* basis and without warranties or representations of any kind either expressed
* or implied. Any use of this open source software released under the ISC
* Internet Systems Consortium license is done at your own risk to the fullest
* extent permissible pursuant to applicable law any and all liability as well
* as all warranties, including any fitness for a particular purpose with respect
* to Tetu and/or the underlying software and the use thereof are disclaimed.
*/

pragma solidity 0.8.4;

/// @title Uniswap Math https://github.com/Uniswap/v2-core/blob/master/contracts/libraries/Math.sol
///        A library for performing various math operations
library Math {

  function min(uint x, uint y) internal pure returns (uint z) {
    z = x < y ? x : y;
  }

  /// @dev Babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
  function sqrt(uint y) internal pure returns (uint z) {
    z = 0;
    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 8 of 16 : TetuSwapLibrary.sol
// SPDX-License-Identifier: ISC
/**
* By using this software, you understand, acknowledge and accept that Tetu
* and/or the underlying software are provided “as is” and “as available”
* basis and without warranties or representations of any kind either expressed
* or implied. Any use of this open source software released under the ISC
* Internet Systems Consortium license is done at your own risk to the fullest
* extent permissible pursuant to applicable law any and all liability as well
* as all warranties, including any fitness for a particular purpose with respect
* to Tetu and/or the underlying software and the use thereof are disclaimed.
*/

pragma solidity 0.8.4;

import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "../interfaces/ITetuSwapPair.sol";
import "../interfaces/ITetuSwapFactory.sol";

/// @title UniswapV2Library https://github.com/Uniswap/v2-periphery/blob/master/contracts/libraries/UniswapV2Library.sol
library TetuSwapLibrary {
  using SafeMath for uint;

  uint constant private _PRECISION = 10000;
  uint constant private _FEE = 2;

  /// @dev returns sorted token addresses, used to handle return values from pairs sorted in this order
  function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
    require(tokenA != tokenB, "TSL: IDENTICAL_ADDRESSES");
    (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
    require(token0 != address(0), "TSL: ZERO_ADDRESS");
  }

  /// @dev use stored in factory pairs instead on the flay calculation
  ///      we have more flexible system and can't use old function
  function pairFor(address factory, address tokenA, address tokenB) internal view returns (address pair) {
    return ITetuSwapFactory(factory).getPair(tokenA, tokenB);
  }

  /// @dev fetches and sorts the reserves for a pair
  function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) {
    (address token0,) = sortTokens(tokenA, tokenB);
    (uint reserve0, uint reserve1,) = ITetuSwapPair(pairFor(factory, tokenA, tokenB)).getReserves();
    (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
  }

  /// @dev given some amount of an asset and pair reserves, returns an equivalent amount of the other asset
  function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) {
    require(amountA > 0, "TSL: INSUFFICIENT_AMOUNT");
    require(reserveA > 0 && reserveB > 0, "TSL: INSUFFICIENT_LIQUIDITY");
    amountB = amountA.mul(reserveB) / reserveA;
  }

  /// @dev given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
  function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut, uint fee) internal pure returns (uint amountOut) {
    require(amountIn > 0, "TSL: INSUFFICIENT_INPUT_AMOUNT");
    require(reserveIn > 0 && reserveOut > 0, "TSL: INSUFFICIENT_LIQUIDITY");
    uint amountInWithFee = amountIn.mul(_PRECISION - fee);
    uint numerator = amountInWithFee.mul(reserveOut);
    uint denominator = reserveIn.mul(_PRECISION).add(amountInWithFee);
    amountOut = numerator / denominator;
  }

  /// @dev given an output amount of an asset and pair reserves, returns a required input amount of the other asset
  function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut, uint fee) internal pure returns (uint amountIn) {
    require(amountOut > 0, "TSL: INSUFFICIENT_OUTPUT_AMOUNT");
    require(reserveIn > 0 && reserveOut > 0, "TSL: INSUFFICIENT_LIQUIDITY");
    uint numerator = reserveIn.mul(amountOut).mul(_PRECISION);
    uint denominator = reserveOut.sub(amountOut).mul(_PRECISION - fee);
    amountIn = (numerator / denominator).add(1);
  }

  /// @dev performs chained getAmountOut calculations on any number of pairs
  function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) {
    require(path.length >= 2, "TSL: INVALID_PATH");
    amounts = new uint[](path.length);
    amounts[0] = amountIn;
    for (uint i; i < path.length - 1; i++) {
      (uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]);
      amounts[i + 1] = getAmountOut(
        amounts[i],
        reserveIn,
        reserveOut,
        ITetuSwapPair(pairFor(factory, path[i], path[i + 1])).fee()
      );
    }
  }

  /// @dev performs chained getAmountIn calculations on any number of pairs
  function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) {
    require(path.length >= 2, "TSL: INVALID_PATH");
    amounts = new uint[](path.length);
    amounts[amounts.length - 1] = amountOut;
    for (uint i = path.length - 1; i > 0; i--) {
      (uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]);
      amounts[i - 1] = getAmountIn(
        amounts[i],
        reserveIn,
        reserveOut,
        ITetuSwapPair(pairFor(factory, path[i - 1], path[i])).fee()
      );
    }
  }
}

File 9 of 16 : IUniswapV2Callee.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.4;

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

File 10 of 16 : IUniswapV2Factory.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.4;

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

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

  function allPairs(uint) external view returns (address pair);

  function allPairsLength() external view returns (uint);

  function feeTo() external view returns (address);

  function feeToSetter() external view returns (address);

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

File 11 of 16 : IERC20Name.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.4;

interface IERC20Name {
  function name() external view returns (string memory);

  function symbol() external view returns (string memory);
}

File 12 of 16 : ISmartVault.sol
// SPDX-License-Identifier: ISC
/**
* By using this software, you understand, acknowledge and accept that Tetu
* and/or the underlying software are provided “as is” and “as available”
* basis and without warranties or representations of any kind either expressed
* or implied. Any use of this open source software released under the ISC
* Internet Systems Consortium license is done at your own risk to the fullest
* extent permissible pursuant to applicable law any and all liability as well
* as all warranties, including any fitness for a particular purpose with respect
* to Tetu and/or the underlying software and the use thereof are disclaimed.
*/

pragma solidity 0.8.4;

interface ISmartVault {

  function setStrategy(address _strategy) external;

  function changeActivityStatus(bool _active) external;

  function changePpfsDecreaseAllowed(bool _value) external;

  function setLockPeriod(uint256 _value) external;

  function setLockPenalty(uint256 _value) external;

  function setToInvest(uint256 _value) external;

  function doHardWork() external;

  function rebalance() external;

  function disableLock() external;

  function notifyTargetRewardAmount(address _rewardToken, uint256 reward) external;

  function notifyRewardWithoutPeriodChange(address _rewardToken, uint256 reward) external;

  function deposit(uint256 amount) external;

  function depositAndInvest(uint256 amount) external;

  function depositFor(uint256 amount, address holder) external;

  function withdraw(uint256 numberOfShares) external;

  function exit() external;

  function getAllRewards() external;

  function getReward(address rt) external;

  function underlying() external view returns (address);

  function strategy() external view returns (address);

  function getRewardTokenIndex(address rt) external view returns (uint256);

  function getPricePerFullShare() external view returns (uint256);

  function underlyingUnit() external view returns (uint256);

  function duration() external view returns (uint256);

  function underlyingBalanceInVault() external view returns (uint256);

  function underlyingBalanceWithInvestment() external view returns (uint256);

  function underlyingBalanceWithInvestmentForHolder(address holder) external view returns (uint256);

  function availableToInvestOut() external view returns (uint256);

  function earned(address rt, address account) external view returns (uint256);

  function earnedWithBoost(address rt, address account) external view returns (uint256);

  function rewardPerToken(address rt) external view returns (uint256);

  function lastTimeRewardApplicable(address rt) external view returns (uint256);

  function rewardTokensLength() external view returns (uint256);

  function active() external view returns (bool);

  function rewardTokens() external view returns (address[] memory);

  function periodFinishForToken(address _rt) external view returns (uint256);

  function rewardRateForToken(address _rt) external view returns (uint256);

  function lastUpdateTimeForToken(address _rt) external view returns (uint256);

  function rewardPerTokenStoredForToken(address _rt) external view returns (uint256);

  function userRewardPerTokenPaidForToken(address _rt, address account) external view returns (uint256);

  function rewardsForToken(address _rt, address account) external view returns (uint256);

  function userLastWithdrawTs(address _user) external returns (uint256);

  function userLastDepositTs(address _user) external returns (uint256);

  function userBoostTs(address _user) external returns (uint256);

  function userLockTs(address _user) external returns (uint256);

  function addRewardToken(address rt) external;

  function removeRewardToken(address rt) external;

  function stop() external;

  function ppfsDecreaseAllowed() external view returns (bool);

  function lockPeriod() external view returns (uint256);

  function lockPenalty() external view returns (uint256);

  function toInvest() external view returns (uint256);

  function lockAllowed() external view returns (bool);
}

File 13 of 16 : ITetuSwapPair.sol
// SPDX-License-Identifier: ISC
/**
* By using this software, you understand, acknowledge and accept that Tetu
* and/or the underlying software are provided “as is” and “as available”
* basis and without warranties or representations of any kind either expressed
* or implied. Any use of this open source software released under the ISC
* Internet Systems Consortium license is done at your own risk to the fullest
* extent permissible pursuant to applicable law any and all liability as well
* as all warranties, including any fitness for a particular purpose with respect
* to Tetu and/or the underlying software and the use thereof are disclaimed.
*/

pragma solidity 0.8.4;

interface ITetuSwapPair {

  function balanceOfVaultUnderlying(address _token) external view returns (uint);

  function setFee(uint _fee) external;

  function setVaults(address _vault0, address _vault1) external;

  function setRewardRecipient(address _recipient) external;

  function claimAll() external;

  function MINIMUM_LIQUIDITY() external pure returns (uint);

  function factory() external view returns (address);

  function rewardRecipient() external view returns (address);

  function fee() external view returns (uint);

  function token0() external view returns (address);

  function token1() external view returns (address);

  function vault0() external view returns (address);

  function vault1() external view returns (address);

  function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);

  function price0CumulativeLast() external view returns (uint);

  function price1CumulativeLast() external view returns (uint);

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

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

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

  function sync() external;

  function initialize(
    address _token0,
    address _token1,
    uint _fee
  ) external;

}

File 14 of 16 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @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
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(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);
            }
        }
    }
}

File 15 of 16 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 16 of 16 : ITetuSwapFactory.sol
// SPDX-License-Identifier: ISC
/**
* By using this software, you understand, acknowledge and accept that Tetu
* and/or the underlying software are provided “as is” and “as available”
* basis and without warranties or representations of any kind either expressed
* or implied. Any use of this open source software released under the ISC
* Internet Systems Consortium license is done at your own risk to the fullest
* extent permissible pursuant to applicable law any and all liability as well
* as all warranties, including any fitness for a particular purpose with respect
* to Tetu and/or the underlying software and the use thereof are disclaimed.
*/

pragma solidity 0.8.4;

interface ITetuSwapFactory {

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

  function allPairs(uint) external view returns (address pair);

  function allPairsLength() external view returns (uint);

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

  function validPairs(address _pair) external view returns (bool);

}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 150
  },
  "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":false,"internalType":"uint256","name":"blockTs","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"FeeChanged","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":false,"internalType":"address","name":"oldRecipient","type":"address"},{"indexed":false,"internalType":"address","name":"newRecipient","type":"address"}],"name":"RewardRecipientChanged","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":"uint112","name":"reserve0","type":"uint112"},{"indexed":false,"internalType":"uint112","name":"reserve1","type":"uint112"}],"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":false,"internalType":"address","name":"vault0","type":"address"},{"indexed":false,"internalType":"address","name":"vault1","type":"address"}],"name":"VaultsChanged","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINIMUM_LIQUIDITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"value","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":[{"internalType":"address","name":"_token","type":"address"}],"name":"balanceOfVaultUnderlying","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":"claimAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"createdBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"createdTs","outputs":[{"internalType":"uint256","name":"","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":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"},{"internalType":"uint256","name":"amountOutWithFee","type":"uint256"}],"name":"getFeeAmount","outputs":[{"internalType":"uint256","name":"amountFee","type":"uint256"}],"stateMutability":"pure","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":[{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"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":[],"name":"price0CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price1CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"}],"name":"setRewardRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault0","type":"address"},{"internalType":"address","name":"_vault1","type":"address"}],"name":"setVaults","outputs":[],"stateMutability":"nonpayable","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":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultReserve0","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultReserve1","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50604080518082018252600b81526a05465747553776170204c560ac1b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f918101919091527fb78cf64ac322bb8ec4cb80679b3778f97968af51fa1924a34ca2e65a7ba800ac918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606082015246608082018190523060a08301529060c00160408051601f198184030181529190528051602090910120600355506001600555600680546001600160a01b03191633179055613ebe806101136000396000f3fe608060405234801561001057600080fd5b50600436106102695760003560e01c806385f8c25911610151578063d1058e59116100c3578063e521136f11610087578063e521136f146105a6578063ebbdfc00146105b9578063f070ba03146105c1578063f53f83ab146105ca578063ffa1ad74146105dd578063fff6cae91461060157600080fd5b8063d1058e5914610544578063d21220a71461054c578063d505accf1461055f578063dd62ed3e14610572578063ddca3f431461059d57600080fd5b8063a7af479611610115578063a7af4796146104f1578063a9059cbb14610504578063aaf5eb6814610517578063ba9a7a5614610520578063bc063e1a14610529578063c45a01551461053157600080fd5b806385f8c2591461048857806389afcb441461049b57806395d89b41146104c35780639bec62c9146104cb578063a1512a2b146104de57600080fd5b8063313ce567116101ea5780635a3d5493116101ae5780635a3d5493146103f957806362cecf801461040257806369fe0e2d146104225780636a6278421461043557806370a08231146104485780637ecebe001461046857600080fd5b8063313ce567146103b15780633644e515146103cb5780634593144c146103d45780634c451a6a146103dd5780635909c0d5146103f057600080fd5b80631794bb3c116102315780631794bb3c1461033a57806317f333401461034d57806318160ddd1461036057806323b872dd1461037757806330adf81f1461038a57600080fd5b8063022c0d9f1461026e57806306fdde03146102835780630902f1ac146102c3578063095ea7b3146102f75780630dfe16811461031a575b600080fd5b61028161027c366004613a44565b610609565b005b6102ad6040518060400160405280600b81526020016a05465747553776170204c560ac1b81525081565b6040516102ba9190613bf9565b60405180910390f35b6102cb610ae5565b604080516001600160701b03948516815293909216602084015263ffffffff16908201526060016102ba565b61030a610305366004613885565b610b0f565b60405190151581526020016102ba565b60085461032d906001600160a01b031681565b6040516102ba9190613b99565b6102816103483660046137d0565b610b25565b60075461032d906001600160a01b031681565b61036960005481565b6040519081526020016102ba565b61030a6103853660046137d0565b610d81565b6103697f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b6103b9601281565b60405160ff90911681526020016102ba565b61036960035481565b61036960125481565b6102816103eb366004613798565b610dfc565b610369600d5481565b610369600e5481565b61040a6110cd565b6040516001600160701b0390911681526020016102ba565b610281610430366004613a14565b611153565b610369610443366004613760565b611203565b610369610456366004613760565b60016020526000908152604090205481565b610369610476366004613760565b60046020526000908152604090205481565b610369610496366004613ad5565b6115b7565b6104ae6104a9366004613760565b6115dc565b604080519283526020830191909152016102ba565b6102ad611bb3565b600b5461032d906001600160a01b031681565b600a5461032d906001600160a01b031681565b6103696104ff366004613760565b611c45565b61030a610512366004613885565b611e38565b61036961271081565b6103696103e881565b610369601e81565b60065461032d906001600160a01b031681565b610281611e45565b60095461032d906001600160a01b031681565b61028161056d366004613810565b611efe565b610369610580366004613798565b600260209081526000928352604080842090915290825290205481565b61036960105481565b6102816105b4366004613760565b612116565b61040a6121a9565b61036960115481565b6103696105d8366004613b00565b6121da565b6102ad604051806040016040528060058152602001640312e302e360dc1b81525081565b610281612236565b600260055414156106355760405162461bcd60e51b815260040161062c90613c56565b60405180910390fd5b6002600555841515806106485750600084115b6106945760405162461bcd60e51b815260206004820152601f60248201527f5453503a20496e73756666696369656e74206f757470757420616d6f756e7400604482015260640161062c565b60008061069f610ae5565b5091509150816001600160701b0316871080156106c45750806001600160701b031686105b6107105760405162461bcd60e51b815260206004820152601b60248201527f5453503a20496e73756666696369656e74206c69717569646974790000000000604482015260640161062c565b600061072f87846001600160701b0316846001600160701b03166115b7565b9050600061075089846001600160701b0316866001600160701b03166115b7565b6008546040516370a0823160e01b81529192506000916001600160a01b03909116906370a0823190610786903090600401613b99565b60206040518083038186803b15801561079e57600080fd5b505afa1580156107b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d69190613a2c565b6009546040516370a0823160e01b81529192506000916001600160a01b03909116906370a082319061080c903090600401613b99565b60206040518083038186803b15801561082457600080fd5b505afa158015610838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085c9190613a2c565b905083821015801561086e5750828110155b6108ba5760405162461bcd60e51b815260206004820152601e60248201527f5453503a20496e73756666696369656e7420696e70757420616d6f756e740000604482015260640161062c565b811561091f57600a5460405163b6b55f2560e01b8152600481018490526001600160a01b039091169063b6b55f2590602401600060405180830381600087803b15801561090657600080fd5b505af115801561091a573d6000803e3d6000fd5b505050505b801561098457600b5460405163b6b55f2560e01b8152600481018390526001600160a01b039091169063b6b55f2590602401600060405180830381600087803b15801561096b57600080fd5b505af115801561097f573d6000803e3d6000fd5b505050505b6000818311156109b3576109ac83886001600160701b0316886001600160701b03168e6121da565b90506109d4565b6109d182876001600160701b0316896001600160701b03168f6121da565b90505b6109e28c8c8c8c8c8661226d565b5060006109ed6121a9565b6001600160701b031690506000610a026110cd565b6001600160701b03169050866001600160701b0316886001600160701b0316610a2b9190613d3f565b610a358284613d3f565b1015610a745760405162461bcd60e51b815260206004820152600e60248201526d5453503a204b20746f6f206c6f7760901b604482015260640161062c565b5050610a7e612408565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001600555505050505050505050565b600c546001600160701b0380821692600160701b830490911691600160e01b900463ffffffff1690565b6000610b1c33848461264b565b50600192915050565b6006546001600160a01b03163314610b4f5760405162461bcd60e51b815260040161062c90613c2c565b601e811115610b945760405162461bcd60e51b81526020600482015260116024820152705453503a20546f6f20686967682066656560781b604482015260640161062c565b6008546001600160a01b031615610be85760405162461bcd60e51b81526020600482015260186024820152771514d40e88105b1c9958591e481a5b9a5d1a585b1a5e995960421b604482015260640161062c565b6009546001600160a01b031615610c3c5760405162461bcd60e51b81526020600482015260186024820152771514d40e88105b1c9958591e481a5b9a5d1a585b1a5e995960421b604482015260640161062c565b600880546001600160a01b038086166001600160a01b0319928316811790935560098054918616919092161790556010829055604080516395d89b4160e01b81529051610d5f92916395d89b41916004808301926000929190829003018186803b158015610ca957600080fd5b505afa158015610cbd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ce59190810190613984565b836001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b158015610d1e57600080fd5b505afa158015610d32573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d5a9190810190613984565b6126ad565b8051610d7391600f916020909101906136c7565b505042601155505043601255565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001914610de6576001600160a01b038416600090815260026020908152604080832033845290915281208054849290610de0908490613d5e565b90915550505b610df18484846126d9565b5060015b9392505050565b6006546001600160a01b03163314610e265760405162461bcd60e51b815260040161062c90613c2c565b60085460408051636f307dc360e01b815290516001600160a01b0392831692851691636f307dc3916004808301926020929190829003018186803b158015610e6d57600080fd5b505afa158015610e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea5919061377c565b6001600160a01b031614610efb5760405162461bcd60e51b815260206004820152601c60248201527f5453503a2057726f6e67207661756c743020756e6465726c79696e6700000000604482015260640161062c565b60095460408051636f307dc360e01b815290516001600160a01b0392831692841691636f307dc3916004808301926020929190829003018186803b158015610f4257600080fd5b505afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061377c565b6001600160a01b031614610fd05760405162461bcd60e51b815260206004820152601c60248201527f5453503a2057726f6e67207661756c743120756e6465726c79696e6700000000604482015260640161062c565b600a54610fe5906001600160a01b031661277a565b600b54610ffa906001600160a01b031661277a565b600a80546001600160a01b038085166001600160a01b031992831617909255600b805484841692169190911790556008546110399116836000196128f8565b600954611052906001600160a01b0316826000196128f8565b600a54611067906001600160a01b0316612a54565b50600b5461107d906001600160a01b0316612a54565b50600a54600b54604080516001600160a01b0393841681529290911660208301527f61e68e33253f2a551a18c535ab9b82eca5bcd1708100bc72a549595262fd8ac3910160405180910390a15050565b600b54604051638cb1d67f60e01b81526000916001600160a01b031690638cb1d67f906110fe903090600401613b99565b60206040518083038186803b15801561111657600080fd5b505afa15801561112a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114e9190613a2c565b905090565b6006546001600160a01b0316331461117d5760405162461bcd60e51b815260040161062c90613c2c565b601e8111156111c25760405162461bcd60e51b81526020600482015260116024820152705453503a20546f6f20686967682066656560781b604482015260640161062c565b60105460408051918252602082018390527f5fc463da23c1b063e66f9e352006a7fbe8db7223c455dc429e881a2dfe2f94f1910160405180910390a1601055565b6000600260055414156112285760405162461bcd60e51b815260040161062c90613c56565b6002600555600a546040516370a0823160e01b81526000916001600160a01b0316906370a082319061125e903090600401613b99565b60206040518083038186803b15801561127657600080fd5b505afa15801561128a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ae9190613a2c565b600b546040516370a0823160e01b81529192506000916001600160a01b03909116906370a08231906112e4903090600401613b99565b60206040518083038186803b1580156112fc57600080fd5b505afa158015611310573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113349190613a2c565b600a5490915060009061134f906001600160a01b0316612a54565b600b5490915060009061136a906001600160a01b0316612a54565b600a546040516370a0823160e01b815291925060009186916001600160a01b0316906370a08231906113a0903090600401613b99565b60206040518083038186803b1580156113b857600080fd5b505afa1580156113cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f09190613a2c565b6113fa9190613d5e565b600b546040516370a0823160e01b815291925060009186916001600160a01b0316906370a0823190611430903090600401613b99565b60206040518083038186803b15801561144857600080fd5b505afa15801561145c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114809190613a2c565b61148a9190613d5e565b600054909150806114c8576103e86114aa6114a58486613d3f565b612bab565b6114b49190613d5e565b97506114c360006103e8612c1b565b6114fd565b6114fa876114d68386613d3f565b6114e09190613cfc565b876114eb8486613d3f565b6114f59190613cfc565b612ca4565b97505b600088116115585760405162461bcd60e51b815260206004820152602260248201527f5453503a20496e73756666696369656e74206c6971756964697479206d696e74604482015261195960f21b606482015260840161062c565b6115628989612c1b565b61156a612408565b604080518681526020810186905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001600555509395945050505050565b6000836115c657506000610df5565b6115d4848484601054612cba565b949350505050565b600080600260055414156116025760405162461bcd60e51b815260040161062c90613c56565b6002600555600a546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611638903090600401613b99565b60206040518083038186803b15801561165057600080fd5b505afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a2c565b600b546040516370a0823160e01b81529192506000916001600160a01b03909116906370a08231906116be903090600401613b99565b60206040518083038186803b1580156116d657600080fd5b505afa1580156116ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061170e9190613a2c565b3060009081526001602052604081205481549293509161172e8584613d3f565b6117389190613cfc565b905060008054848461174a9190613d3f565b6117549190613cfc565b90506000821180156117665750600081115b6117bd5760405162461bcd60e51b815260206004820152602260248201527f5453503a20496e73756666696369656e74206c6971756964697479206275726e604482015261195960f21b606482015260840161062c565b6117c73084612dbe565b600a546040516370a0823160e01b81526001600160a01b03909116906370a08231906117f7903090600401613b99565b60206040518083038186803b15801561180f57600080fd5b505afa158015611823573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118479190613a2c565b8211156118965760405162461bcd60e51b815260206004820152601a60248201527f5453503a20496e73756666696369656e74207368617265732030000000000000604482015260640161062c565b600b546040516370a0823160e01b81526001600160a01b03909116906370a08231906118c6903090600401613b99565b60206040518083038186803b1580156118de57600080fd5b505afa1580156118f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119169190613a2c565b8111156119655760405162461bcd60e51b815260206004820152601a60248201527f5453503a20496e73756666696369656e74207368617265732031000000000000604482015260640161062c565b600a54604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b1580156119ab57600080fd5b505af11580156119bf573d6000803e3d6000fd5b5050600b54604051632e1a7d4d60e01b8152600481018590526001600160a01b039091169250632e1a7d4d9150602401600060405180830381600087803b158015611a0957600080fd5b505af1158015611a1d573d6000803e3d6000fd5b50506008546040516370a0823160e01b81526001600160a01b0390911692506370a082319150611a51903090600401613b99565b60206040518083038186803b158015611a6957600080fd5b505afa158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613a2c565b6009546040516370a0823160e01b81529198506001600160a01b0316906370a0823190611ad2903090600401613b99565b60206040518083038186803b158015611aea57600080fd5b505afa158015611afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b229190613a2c565b600854909650611b3c906001600160a01b03168989612e41565b600954611b53906001600160a01b03168988612e41565b611b5b612408565b60408051888152602081018890526001600160a01b038a169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050506001600581905550915091565b6060600f8054611bc290613dca565b80601f0160208091040260200160405190810160405280929190818152602001828054611bee90613dca565b8015611c3b5780601f10611c1057610100808354040283529160200191611c3b565b820191906000526020600020905b815481529060010190602001808311611c1e57829003601f168201915b5050505050905090565b600a5460408051636f307dc360e01b815290516000926001600160a01b031691636f307dc3916004808301926020929190829003018186803b158015611c8a57600080fd5b505afa158015611c9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc2919061377c565b6001600160a01b0316826001600160a01b03161415611d6157600a54604051638cb1d67f60e01b81526001600160a01b0390911690638cb1d67f90611d0b903090600401613b99565b60206040518083038186803b158015611d2357600080fd5b505afa158015611d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5b9190613a2c565b92915050565b600b60009054906101000a90046001600160a01b03166001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015611daf57600080fd5b505afa158015611dc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611de7919061377c565b6001600160a01b0316826001600160a01b03161415611e3057600b54604051638cb1d67f60e01b81526001600160a01b0390911690638cb1d67f90611d0b903090600401613b99565b506000919050565b6000610b1c3384846126d9565b6007546001600160a01b03163314611e9f5760405162461bcd60e51b815260206004820152601d60248201527f5453503a204f6e6c7920726563697069656e742063616e20636c61696d000000604482015260640161062c565b600a54611eb4906001600160a01b0316612e71565b600b54611ec9906001600160a01b0316612e71565b6040514281527f7a355715549cfe7c1cba26304350343fbddc4b4f72d3ce3e7c27117dd20b5cb89060200160405180910390a1565b42841015611f475760405162461bcd60e51b815260206004820152601660248201527515195d1d54ddd85c115490cc8c0e881156141254915160521b604482015260640161062c565b6003546001600160a01b038816600090815260046020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087611f9a83613dff565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e0016040516020818303038152906040528051906020012060405160200161201392919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa15801561207e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906120b45750886001600160a01b0316816001600160a01b0316145b6121005760405162461bcd60e51b815260206004820181905260248201527f546574755377617045524332303a20494e56414c49445f5349474e4154555245604482015260640161062c565b61210b89898961264b565b505050505050505050565b6006546001600160a01b031633146121405760405162461bcd60e51b815260040161062c90613c2c565b600754604080516001600160a01b03928316815291831660208301527fae1f37ae5efbfb242e3b24245f203971d97a432a097847314eb005bed5d00f4a910160405180910390a1600780546001600160a01b0319166001600160a01b0392909216919091179055565b600a54604051638cb1d67f60e01b81526000916001600160a01b031690638cb1d67f906110fe903090600401613b99565b6000846121e9575060006115d4565b60006121f88686866000613175565b905082811161220b5760009150506115d4565b600a6122178483613d5e565b612222906009613d3f565b61222c9190613cfc565b9695505050505050565b600260055414156122595760405162461bcd60e51b815260040161062c90613c56565b6002600555612266612408565b6001600555565b6008546009546001600160a01b039182169190811690861682148015906122a65750806001600160a01b0316866001600160a01b031614155b6122e45760405162461bcd60e51b815260206004820152600f60248201526e5453503a20496e76616c696420746f60881b604482015260640161062c565b871561233d57600a54612309906001600160a01b0316612304858b613cbe565b613274565b61231d6001600160a01b038316878a612e41565b821561233d5760075461233d906001600160a01b03848116911685612e41565b861561239157600b5461235d906001600160a01b0316612304858a613cbe565b6123716001600160a01b0382168789612e41565b821561239157600754612391906001600160a01b03838116911685612e41565b83156123fe576040516304347a1760e21b81526001600160a01b038716906310d1e85c906123cb9033908c908c908b908b90600401613bad565b600060405180830381600087803b1580156123e557600080fd5b505af11580156123f9573d6000803e3d6000fd5b505050505b5050505050505050565b60006124126121a9565b6001600160701b0316905060006124276110cd565b6001600160701b039081169150821180159061244a57506001600160701b038111155b6124865760405162461bcd60e51b815260206004820152600d60248201526c5453503a204f564552464c4f5760981b604482015260640161062c565b600061249764010000000042613e1a565b600c549091506000906124b790600160e01b900463ffffffff1683613d75565b905060008163ffffffff161180156124d95750600c546001600160701b031615155b80156124f65750600c54600160701b90046001600160701b031615155b156125b557600c5463ffffffff821690612537906001600160701b038082169161252891600160701b909104166134a8565b6001600160e01b0316906134c1565b6001600160e01b031661254a9190613d3f565b600d600082825461255b9190613cbe565b9091555050600c5463ffffffff82169061258b906001600160701b03600160701b820481169161252891166134a8565b6001600160e01b031661259e9190613d3f565b600e60008282546125af9190613cbe565b90915550505b600c805463ffffffff8416600160e01b026001600160e01b036001600160701b03878116600160701b9081026001600160e01b03199095168a83161794909417918216831794859055604080519382169282169290921783529290930490911660208201527f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a150505050565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b606082826040516020016126c2929190613b4d565b604051602081830303815290604052905092915050565b6001600160a01b03831660009081526001602052604081208054839290612701908490613d5e565b90915550506001600160a01b0382166000908152600160205260408120805483929061272e908490613cbe565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516126a091815260200190565b6001600160a01b03811661278b5750565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906127ba903090600401613b99565b60206040518083038186803b1580156127d257600080fd5b505afa1580156127e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280a9190613a2c565b9050801561286d57604051632e1a7d4d60e01b8152600481018290526001600160a01b03831690632e1a7d4d90602401600060405180830381600087803b15801561285457600080fd5b505af1158015612868573d6000803e3d6000fd5b505050505b6128f4826000846001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156128ac57600080fd5b505afa1580156128c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e4919061377c565b6001600160a01b031691906128f8565b5050565b8015806129815750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561294757600080fd5b505afa15801561295b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297f9190613a2c565b155b6129ec5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840161062c565b6040516001600160a01b038316602482015260448101829052612a4f90849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526134d6565b505050565b600080826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015612a9057600080fd5b505afa158015612aa4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac8919061377c565b6001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612af39190613b99565b60206040518083038186803b158015612b0b57600080fd5b505afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613a2c565b90508015611d5b5760405163b6b55f2560e01b8152600481018290526001600160a01b0384169063b6b55f2590602401600060405180830381600087803b158015612b8d57600080fd5b505af1158015612ba1573d6000803e3d6000fd5b5050505092915050565b60006003821115612c0c5750806000612bc5600283613cfc565b612bd0906001613cbe565b90505b81811015612c0657905080600281612beb8186613cfc565b612bf59190613cbe565b612bff9190613cfc565b9050612bd3565b50919050565b8115612c16575060015b919050565b80600080828254612c2c9190613cbe565b90915550506001600160a01b03821660009081526001602052604081208054839290612c59908490613cbe565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6000818310612cb35781610df5565b5090919050565b6000808511612d0b5760405162461bcd60e51b815260206004820152601f60248201527f54534c3a20494e53554646494349454e545f4f55545055545f414d4f554e5400604482015260640161062c565b600084118015612d1b5750600083115b612d675760405162461bcd60e51b815260206004820152601b60248201527f54534c3a20494e53554646494349454e545f4c49515549444954590000000000604482015260640161062c565b6000612d7f612710612d7987896135a8565b906135a8565b90506000612d9c612d9285612710613d5e565b612d79878a6135b4565b9050612db36001612dad8385613cfc565b906135c0565b979650505050505050565b6001600160a01b03821660009081526001602052604081208054839290612de6908490613d5e565b9250508190555080600080828254612dfe9190613d5e565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612c98565b6040516001600160a01b038316602482015260448101829052612a4f90849063a9059cbb60e01b90606401612a18565b6001600160a01b038116612eb95760405162461bcd60e51b815260206004820152600f60248201526e1514d40e8816995c9bc81d985d5b1d608a1b604482015260640161062c565b8060005b816001600160a01b031663bf199e626040518163ffffffff1660e01b815260040160206040518083038186803b158015612ef657600080fd5b505afa158015612f0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f2e9190613a2c565b811015612a4f576000826001600160a01b031663c2b18aa06040518163ffffffff1660e01b815260040160006040518083038186803b158015612f7057600080fd5b505afa158015612f84573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612fac91908101906138b0565b8281518110612fcb57634e487b7160e01b600052603260045260246000fd5b602002602001015190506000816001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016130039190613b99565b60206040518083038186803b15801561301b57600080fd5b505afa15801561302f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130539190613a2c565b604051630c00007b60e41b81529091506001600160a01b0385169063c00007b090613082908590600401613b99565b600060405180830381600087803b15801561309c57600080fd5b505af11580156130b0573d6000803e3d6000fd5b50505050600081836001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016130e39190613b99565b60206040518083038186803b1580156130fb57600080fd5b505afa15801561310f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131339190613a2c565b61313d9190613d5e565b9050801561315f5760075461315f906001600160a01b03858116911683612e41565b505050808061316d90613dff565b915050612ebd565b60008085116131c65760405162461bcd60e51b815260206004820152601e60248201527f54534c3a20494e53554646494349454e545f494e5055545f414d4f554e540000604482015260640161062c565b6000841180156131d65750600083115b6132225760405162461bcd60e51b815260206004820152601b60248201527f54534c3a20494e53554646494349454e545f4c49515549444954590000000000604482015260640161062c565b600061323a61323384612710613d5e565b87906135a8565b9050600061324882866135a8565b9050600061325c83612dad896127106135a8565b90506132688183613cfc565b98975050505050505050565b6040516370a0823160e01b815282906000906001600160a01b038316906370a08231906132a5903090600401613b99565b60206040518083038186803b1580156132bd57600080fd5b505afa1580156132d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132f59190613a2c565b90506000826001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561333257600080fd5b505afa158015613346573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061336a9190613a2c565b836001600160a01b03166353ceb01c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156133a357600080fd5b505afa1580156133b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133db9190613a2c565b6133e59086613d3f565b6133ef9190613cfc565b90506134056133ff826001613cbe565b83612ca4565b9050818111156134525760405162461bcd60e51b81526020600482015260186024820152775453503a20496e73756666696369656e742073686172657360401b604482015260640161062c565b604051632e1a7d4d60e01b8152600481018290526001600160a01b03841690632e1a7d4d90602401600060405180830381600087803b15801561349457600080fd5b505af115801561210b573d6000803e3d6000fd5b6000611d5b600160701b6001600160701b038416613d10565b6000610df56001600160701b03831684613cd6565b600061352b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166135cc9092919063ffffffff16565b805190915015612a4f57808060200190518101906135499190613964565b612a4f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161062c565b6000610df58284613d3f565b6000610df58284613d5e565b6000610df58284613cbe565b60606115d4848460008585843b6136255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161062c565b600080866001600160a01b031685876040516136419190613b31565b60006040518083038185875af1925050503d806000811461367e576040519150601f19603f3d011682016040523d82523d6000602084013e613683565b606091505b5091509150612db38282866060831561369d575081610df5565b8251156136ad5782518084602001fd5b8160405162461bcd60e51b815260040161062c9190613bf9565b8280546136d390613dca565b90600052602060002090601f0160209004810192826136f5576000855561373b565b82601f1061370e57805160ff191683800117855561373b565b8280016001018555821561373b579182015b8281111561373b578251825591602001919060010190613720565b5061374792915061374b565b5090565b5b80821115613747576000815560010161374c565b600060208284031215613771578081fd5b8135610df581613e70565b60006020828403121561378d578081fd5b8151610df581613e70565b600080604083850312156137aa578081fd5b82356137b581613e70565b915060208301356137c581613e70565b809150509250929050565b6000806000606084860312156137e4578081fd5b83356137ef81613e70565b925060208401356137ff81613e70565b929592945050506040919091013590565b600080600080600080600060e0888a03121561382a578283fd5b873561383581613e70565b9650602088013561384581613e70565b95506040880135945060608801359350608088013560ff81168114613868578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215613897578182fd5b82356138a281613e70565b946020939093013593505050565b600060208083850312156138c2578182fd5b825167ffffffffffffffff808211156138d9578384fd5b818501915085601f8301126138ec578384fd5b8151818111156138fe576138fe613e5a565b8060051b915061390f848301613c8d565b8181528481019084860184860187018a1015613929578788fd5b8795505b83861015613957578051945061394285613e70565b8483526001959095019491860191860161392d565b5098975050505050505050565b600060208284031215613975578081fd5b81518015158114610df5578182fd5b600060208284031215613995578081fd5b815167ffffffffffffffff808211156139ac578283fd5b818401915084601f8301126139bf578283fd5b8151818111156139d1576139d1613e5a565b6139e4601f8201601f1916602001613c8d565b91508082528560208285010111156139fa578384fd5b613a0b816020840160208601613d9a565b50949350505050565b600060208284031215613a25578081fd5b5035919050565b600060208284031215613a3d578081fd5b5051919050565b600080600080600060808688031215613a5b578081fd5b85359450602086013593506040860135613a7481613e70565b9250606086013567ffffffffffffffff80821115613a90578283fd5b818801915088601f830112613aa3578283fd5b813581811115613ab1578384fd5b896020828501011115613ac2578384fd5b9699959850939650602001949392505050565b600080600060608486031215613ae9578081fd5b505081359360208301359350604090920135919050565b60008060008060808587031215613b15578182fd5b5050823594602084013594506040840135936060013592509050565b60008251613b43818460208701613d9a565b9190910192915050565b63544c505f60e01b815260008351613b6c816004850160208801613d9a565b605f60f81b6004918401918201528351613b8d816005840160208801613d9a565b01600501949350505050565b6001600160a01b0391909116815260200190565b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b6020815260008251806020840152613c18816040850160208701613d9a565b601f01601f19169190910160400192915050565b60208082526010908201526f5453503a204e6f7420666163746f727960801b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b604051601f8201601f1916810167ffffffffffffffff81118282101715613cb657613cb6613e5a565b604052919050565b60008219821115613cd157613cd1613e2e565b500190565b60006001600160e01b0383811680613cf057613cf0613e44565b92169190910492915050565b600082613d0b57613d0b613e44565b500490565b60006001600160e01b0382811684821681151582840482111615613d3657613d36613e2e565b02949350505050565b6000816000190483118215151615613d5957613d59613e2e565b500290565b600082821015613d7057613d70613e2e565b500390565b600063ffffffff83811690831681811015613d9257613d92613e2e565b039392505050565b60005b83811015613db5578181015183820152602001613d9d565b83811115613dc4576000848401525b50505050565b600181811c90821680613dde57607f821691505b60208210811415612c0657634e487b7160e01b600052602260045260246000fd5b6000600019821415613e1357613e13613e2e565b5060010190565b600082613e2957613e29613e44565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114613e8557600080fd5b5056fea2646970667358221220acc799683694a385b19304a1a3f480aee197367f6f20af9c612d605bdc94182464736f6c63430008040033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.