creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/powerindex-mining/DeprecatedPoolsLens.sol": {
        "content": "/*\nhttps://powerpool.finance/\n          wrrrw r wrr\n         ppwr rrr wppr0       prwwwrp                                 prwwwrp                   wr0\n        rr 0rrrwrrprpwp0      pp   pr  prrrr0 pp   0r  prrrr0  0rwrrr pp   pr  prrrr0  prrrr0    r0\n        rrp pr   wr00rrp      prwww0  pp   wr pp w00r prwwwpr  0rw    prwww0  pp   wr pp   wr    r0\n        r0rprprwrrrp pr0      pp      wr   pr pp rwwr wr       0r     pp      wr   pr wr   pr    r0\n         prwr wrr0wpwr        00        www0   0w0ww    www0   0w     00        www0    www0   0www0\n          wrr ww0rrrr\n*/\n\n// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.11;\n\ninterface IVestedLpMining {\n  function pools(uint256 index) external view returns (Pool calldata);\n  function users(uint256 poolId, address userAddress) external view returns (miningUserDataStruct calldata);\n  function cvpPerBlock() external view returns (uint96);\n  function totalAllocPoint() external view returns (uint256);\n  function vestableCvp(uint256 pId, address user) external view returns (uint256);\n  function poolBoostByLp(uint256 pId) external view returns (uint256, uint256, uint32, uint256, uint256);\n  function usersPoolBoost(uint256 pId, address user) external view returns(uint256 balance, uint32 lastUpdateBlock);\n\n  function poolLength() external view returns(uint);\n  function reservoir() external view returns(address);\n}\n\ninterface ILpToken {\n  function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32);\n  function getBalance(address tokenAddress) external view returns (uint256);\n  function token0() external view returns (address);\n  function token1() external view returns (address);\n  function totalSupply() external view returns (uint256);\n  function balanceOf(address wallet) external view returns (uint256);\n  function symbol() external view returns (string memory);\n  function factory() external view returns (address);\n  function getFinalTokens() external view returns (address[] memory);\n  function getNormalizedWeight(address) external view returns (uint256);\n  function getDenormalizedWeight(address) external view returns (uint256);\n  function getTotalDenormalizedWeight() external view returns (uint256);\n  function getSwapFee() external view returns (uint256);\n  function getCommunityFee() external view returns (Fees memory);\n  function calcSingleOutGivenPoolIn(uint256, uint256, uint256, uint256, uint256, uint256) external view returns (uint256);\n}\n\ninterface ERC20 {\n  function balanceOf(address wallet) external view returns (uint256);\n  function allowance(address owner, address spender) external view returns(uint256);\n  function decimals() external view returns (uint8);\n}\n\nstruct Pool {\n  address lpToken; // address of the LP token contract\n  bool votesEnabled; // if the pool is enabled to write votes\n  uint8 poolType; // pool type (1 - Uniswap, 2 - Balancer, 3 - custom, 4 - sushi)\n  uint32 allocPoint; // points assigned to the pool, which affect CVPs distribution between pools\n  uint32 lastUpdateBlock; // latest block when the pool params which follow was updated\n  uint256 accCvpPerLpt; // accumulated distributed CVPs per one deposited LP token, times 1e12\n}\n\nstruct FarmingListItem {\n  address lpToken;\n  uint8 poolType;\n  uint256 pid;\n  uint256 lpAtMiningAmount;\n  uint256 vestableCvp;\n  bool isBoosted;\n}\n\nstruct EarnListItem {\n  address lpToken;\n  uint8 poolType;\n  uint256 pid;\n  uint256 totalSupply;\n  uint256 userTotalBalance; // user wallet balance + user mining balance\n  PartOfThePool[] tokensDistribution;\n}\n\nstruct PartOfThePool {\n  address tokenAddress;\n  string symbol;\n  uint256 percent;\n}\n\nstruct FarmingDetail {\n  address lpToken;\n  uint8 poolType;\n  uint256 pid;\n  uint256 lpMiningBalance;\n  uint256 lpUserBalance;\n  uint256 lpTotalSupply;\n  uint256 vestableCvp;\n  uint256 lpTokenUserStakedAtMining;\n  uint256 boostedAmount;\n  bool isReservoirEnough;\n  bool isSushi;\n  bool isBalancer;\n}\n\nstruct miningUserDataStruct {\n  uint32 lastUpdateBlock;\n  uint32 vestingBlock;\n  uint96 pendedCvp;\n  uint96 cvpAdjust;\n  uint256 lptAmount;\n}\n\nstruct tokenInfo {\n  address tokenAddress;\n  string tokenSymbol;\n  uint256 reserves;\n  uint8 decimals;\n  uint256 tokenAmountPerLPToken;\n}\n\nstruct tokenRemove {\n  address lpToken;\n  address routerAddress;\n  uint8 poolType;\n  uint256 pid;\n  uint256 lpTotalSupply;\n  uint256 balance;\n  uint256 allowance;\n  tokenInfo token1;\n  tokenInfo token2;\n}\n\nstruct LiquidityTokens {\n  address tokenAddress;\n  uint256 balance;\n  uint8 decimals;\n  string symbol;\n  uint256 tokenAmountForOneLpSingle;\n  uint256 tokenAmountForOneLpMulti;\n}\n\nstruct Fees {\n  uint256 communitySwapFee;\n  uint256 communityJoinFee;\n  uint256 communityExitFee;\n  address communityFeeReceiver;\n}\n\nstruct RemoveLiquidityData {\n  address lpToken;\n  uint8 poolType;\n  uint256 pid;\n  string symbol;\n  uint256 balance;\n  uint256 allowance;\n  Fees fees;\n  LiquidityTokens[] tokens;\n}\n\ncontract DeprecatedPoolsLens {\n  IVestedLpMining public mining;\n\n  address immutable public cvpAddress;\n  mapping(uint8 => uint8) public earnPidMap;\n\n  constructor(\n    IVestedLpMining _mining,\n    address _cvpAddress\n  ) {\n    mining = _mining;\n    cvpAddress = _cvpAddress;\n\n    earnPidMap[0] = 13;\n    earnPidMap[1] = 6;\n    earnPidMap[2] = 10;\n    earnPidMap[3] = 9;\n  }\n\n  function getFarmingList(address _user) external view returns (FarmingListItem[] memory) {\n    Pool[] memory pools = new Pool[](8);\n    pools[0] = mining.pools(6);\n    pools[1] = mining.pools(7);\n    pools[2] = mining.pools(8);\n    pools[3] = mining.pools(9);\n    pools[4] = mining.pools(10);\n    pools[5] = mining.pools(11);\n    pools[6] = mining.pools(12);\n    pools[7] = mining.pools(13);\n\n    FarmingListItem[] memory farmingPools = new FarmingListItem[](8);\n\n    for (uint256 i = 0; i < 8; i++) {\n      Pool memory pool = pools[i];\n\n      farmingPools[i] = FarmingListItem({\n        lpToken:          pool.lpToken,\n        poolType:         pool.poolType,\n        pid:              i + 6,\n        lpAtMiningAmount: 0,\n        vestableCvp:      0,\n        isBoosted:        false\n      });\n\n      FarmingListItem memory farmingPool = farmingPools[i];\n\n      // User total lp and balance\n      if (_user != address(0)) {\n        uint256 vestableCvp = mining.vestableCvp(farmingPool.pid, _user);\n        farmingPool.lpAtMiningAmount = mining.users(farmingPool.pid, _user).lptAmount;\n        farmingPool.vestableCvp = vestableCvp;\n      }\n\n      // Check if pool is boostable\n      (uint256 lpBoostRate,,,,) = mining.poolBoostByLp(farmingPool.pid);\n      if (lpBoostRate > 0) {\n        farmingPool.isBoosted = true;\n      }\n    }\n\n    return farmingPools;\n  }\n\n  function getFarmingDetail(address _user, uint256 _pid) external view returns (FarmingDetail memory) {\n    Pool memory pool = mining.pools(_pid);\n\n    // User total lp and balance\n    uint256 lpTokenUserStaked;\n    uint256 vestableCvp;\n    uint boostAmount;\n    if (_user != address(0)) {\n      lpTokenUserStaked = mining.users(_pid, _user).lptAmount;\n      vestableCvp = mining.vestableCvp(_pid, _user);\n      (boostAmount,) = mining.usersPoolBoost(_pid, _user);\n    }\n\n    // Check if can claim cvp\n    bool isReservoirEnough = vestableCvp <= ERC20(cvpAddress).balanceOf(mining.reservoir()) || vestableCvp <= ERC20(cvpAddress).allowance(mining.reservoir(), address(mining));\n\n    // check if 3rd party pool involved (so later it can be unwrapped to one of PowerPool pool)\n    bool isSushi = _pid == 11 || _pid == 12;\n    bool isBalancer = _pid == 7 || _pid == 8;\n\n    return FarmingDetail({\n      lpToken:                   pool.lpToken,\n      poolType:                  pool.poolType,\n      pid:                       _pid,\n      lpMiningBalance:           ILpToken(pool.lpToken).balanceOf(address(mining)),\n      lpUserBalance:           ILpToken(pool.lpToken).balanceOf(_user),\n      lpTotalSupply:             ILpToken(pool.lpToken).totalSupply(),\n      vestableCvp:               vestableCvp,\n      lpTokenUserStakedAtMining: lpTokenUserStaked,\n      boostedAmount:             boostAmount,\n      isReservoirEnough:         isReservoirEnough,\n      isSushi:                   isSushi,\n      isBalancer:                isBalancer\n    });\n  }\n\n  function getSecondaryLiquidityRemoveInfo(address _user, uint _pid) external view returns (tokenRemove memory) {\n    Pool memory pool = mining.pools(_pid);\n    bool isSushi = pool.poolType == 4;\n\n    address routerContract;\n    if (isSushi) { // sushi\n      routerContract = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F;\n      return getSushiInfo(_user, _pid, routerContract, pool);\n    } else {       // balancer\n      routerContract = pool.lpToken;\n      return getBalancerInfo(_user, _pid, routerContract, pool);\n    }\n  }\n\n  // Returns specific for balancer data. Used when building interface for balancer redeem\n  function getBalancerInfo(address _user, uint _pid, address _router, Pool memory _pool) internal view returns (tokenRemove memory) {\n    uint256 reserve0 = ILpToken(_pool.lpToken).getBalance(ILpToken(_pool.lpToken).getFinalTokens()[0]);\n    uint256 reserve1 = ILpToken(_pool.lpToken).getBalance(ILpToken(_pool.lpToken).getFinalTokens()[1]);\n\n    uint8 token1Decimals = ERC20(ILpToken(_pool.lpToken).getFinalTokens()[0]).decimals();\n    uint8 token2Decimals = ERC20(ILpToken(_pool.lpToken).getFinalTokens()[1]).decimals();\n    uint256 lpTotalSupply = ILpToken(_pool.lpToken).totalSupply();\n\n    return tokenRemove({\n      lpToken:                   _pool.lpToken,\n      routerAddress:             _router,\n      poolType:                  _pool.poolType,\n      pid:                       _pid,\n      lpTotalSupply:             lpTotalSupply,\n      balance:                   ERC20(_pool.lpToken).balanceOf(_user),\n      allowance:                 ERC20(_pool.lpToken).allowance(_user, _router),\n      token1: tokenInfo({\n      tokenAddress: ILpToken(_pool.lpToken).getFinalTokens()[0],\n      tokenSymbol: ILpToken(ILpToken(_pool.lpToken).getFinalTokens()[0]).symbol(),\n      decimals: token1Decimals,\n      reserves: reserve0,\n      tokenAmountPerLPToken:  (((1 ether * 10**18) / lpTotalSupply) * (reserve0 * 10**(18 - token1Decimals))) / 10**18\n    }),\n      token2: tokenInfo({\n      tokenAddress: ILpToken(_pool.lpToken).getFinalTokens()[1],\n      tokenSymbol: ILpToken(ILpToken(_pool.lpToken).getFinalTokens()[1]).symbol(),\n      decimals: token2Decimals,\n      reserves: reserve1,\n      tokenAmountPerLPToken:  (((1 ether * 10**18) / lpTotalSupply) * (reserve1 * 10**(18 - token2Decimals))) / 10**18\n    })\n    });\n  }\n\n  // Returns specific for sushi data. Used when building interface for sushi redeem\n  function getSushiInfo(address _user, uint _pid, address _router, Pool memory _pool) internal view returns (tokenRemove memory) {\n    (uint112 reserve0, uint112 reserve1,) = ILpToken(_pool.lpToken).getReserves();\n\n    uint8 token1Decimals = ERC20(ILpToken(_pool.lpToken).token0()).decimals();\n    uint8 token2Decimals = ERC20(ILpToken(_pool.lpToken).token1()).decimals();\n    uint256 lpTotalSupply = ILpToken(_pool.lpToken).totalSupply();\n\n    return tokenRemove({\n      lpToken:                   _pool.lpToken,\n      routerAddress:             _router,\n      poolType:                  _pool.poolType,\n      pid:                       _pid,\n      lpTotalSupply:             lpTotalSupply,\n      balance:                   ERC20(_pool.lpToken).balanceOf(_user),\n      allowance:                 ERC20(_pool.lpToken).allowance(_user, _router),\n      token1: tokenInfo({\n      tokenAddress: ILpToken(_pool.lpToken).token0(),\n      tokenSymbol: ILpToken(ILpToken(_pool.lpToken).token0()).symbol(),\n      decimals: token1Decimals,\n      reserves: reserve0,\n      tokenAmountPerLPToken:  (((1 ether * 10**18) / lpTotalSupply) * (reserve0 * 10**(18 - token1Decimals))) / 10**18\n    }),\n      token2: tokenInfo({\n      tokenAddress: ILpToken(_pool.lpToken).token1(),\n      tokenSymbol: ILpToken(ILpToken(_pool.lpToken).token1()).symbol(),\n      decimals: token2Decimals,\n      reserves: reserve1,\n      tokenAmountPerLPToken:  (((1 ether * 10**18) / lpTotalSupply) * (reserve1 * 10**(18 - token2Decimals))) / 10**18\n    })\n    });\n  }\n\n  function getEarnList(address _user) external view returns (EarnListItem[] memory) {\n    Pool[] memory pools = new Pool[](4);\n    pools[0] = mining.pools(13);\n    pools[1] = mining.pools(6);\n    pools[2] = mining.pools(10);\n    pools[3] = mining.pools(9);\n\n    EarnListItem[] memory earnPools = new EarnListItem[](4);\n    for (uint8 i = 0; i < 4; i++) {\n      Pool memory pool = pools[i];\n\n      earnPools[i] = EarnListItem({\n        lpToken:            pool.lpToken,\n        poolType:           pool.poolType,\n        pid:                earnPidMap[i],\n        totalSupply:        ILpToken(pool.lpToken).totalSupply(),\n        tokensDistribution: new PartOfThePool[](ILpToken(pool.lpToken).getFinalTokens().length),\n        userTotalBalance:   0\n      });\n\n      EarnListItem memory earnPool = earnPools[i];\n\n      // User balance\n      if (_user != address(0)) {\n        earnPool.userTotalBalance = ILpToken(pool.lpToken).balanceOf(_user) + mining.users(earnPool.pid, _user).lptAmount;\n      }\n\n      // get tokens percents\n      address[] memory finalTokens = ILpToken(pool.lpToken).getFinalTokens();\n      for (uint8 j = 0; j < finalTokens.length; j++) {\n        if (finalTokens[j] == 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2) continue; // fcked up token symbol (bytes32), pass that\n        earnPool.tokensDistribution[j] = PartOfThePool({\n          tokenAddress: finalTokens[j],\n          symbol:       ILpToken(finalTokens[j]).symbol(),\n          percent:      ILpToken(pool.lpToken).getNormalizedWeight(finalTokens[j])\n        });\n      }\n    }\n\n    return earnPools;\n  }\n\n  function removeLiquidityInfo(address _user, uint256 _pid) external view returns (RemoveLiquidityData memory) {\n    Pool memory pool = mining.pools(_pid);\n\n    LiquidityTokens[] memory tokens = new LiquidityTokens[](ILpToken(pool.lpToken).getFinalTokens().length);\n\n    for (uint8 i = 0; i < ILpToken(pool.lpToken).getFinalTokens().length; i++) {\n      LiquidityTokens memory token = tokens[i];\n\n      token.tokenAddress = ILpToken(pool.lpToken).getFinalTokens()[i];\n      token.balance = ERC20(ILpToken(pool.lpToken).getFinalTokens()[i]).balanceOf(_user);\n      token.decimals = ERC20(ILpToken(pool.lpToken).getFinalTokens()[i]).decimals();\n      if (ILpToken(pool.lpToken).getFinalTokens()[i] == 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2) {\n        token.symbol = 'MKR';\n      } else {\n        token.symbol = ILpToken(ILpToken(pool.lpToken).getFinalTokens()[i]).symbol();\n      }\n      token.tokenAmountForOneLpSingle = getSingleTokenOut(_pid, token.tokenAddress);\n      token.tokenAmountForOneLpMulti = getMultiTokensOut(_pid, token.tokenAddress, token.decimals);\n    }\n\n    return RemoveLiquidityData({\n      lpToken:    pool.lpToken,\n      poolType:   pool.poolType,\n      pid:        _pid,\n      symbol:     ILpToken(pool.lpToken).symbol(),\n      balance:    ILpToken(pool.lpToken).balanceOf(_user),\n      allowance:  ERC20(pool.lpToken).allowance(_user, pool.lpToken),\n      fees:       ILpToken(pool.lpToken).getCommunityFee(),\n      tokens:     tokens\n    });\n  }\n\n  function getSingleTokenOut(uint256 _pid, address _tokenAddress) internal view returns (uint256) {\n    Pool memory pool = mining.pools(_pid);\n\n    if (_pid == 13) {\n      // usd handler. Disabled due to security breach\n      return 0;\n    } else {\n      uint256 communitySwapFee = ILpToken(pool.lpToken).getCommunityFee().communitySwapFee;\n      return ILpToken(pool.lpToken).calcSingleOutGivenPoolIn(\n        ILpToken(pool.lpToken).getBalance(_tokenAddress),\n        ILpToken(pool.lpToken).getDenormalizedWeight(_tokenAddress),\n        ILpToken(pool.lpToken).totalSupply(),\n        ILpToken(pool.lpToken).getTotalDenormalizedWeight(),\n        1 ether - communitySwapFee,\n        ILpToken(pool.lpToken).getSwapFee()\n      );\n    }\n  }\n\n  function getMultiTokensOut(uint256 _pid, address _tokenAddress, uint8 _decimals) internal view returns (uint256) {\n    Pool memory pool = mining.pools(_pid);\n    uint256 totalSupply = ILpToken(pool.lpToken).totalSupply();\n    uint256 reserve = ILpToken(pool.lpToken).getBalance(_tokenAddress);\n\n    return (((1 ether * 10**18) / totalSupply) * (reserve * 10**(18 - _decimals))) / 10**18;\n  }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}