all files / contracts/ Keep3rHelper.sol

0% Statements 0/34
0% Branches 0/8
0% Functions 0/12
0% Lines 0/34
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157                                                                                                                                                                                                                                                                                                                         
// SPDX-License-Identifier: MIT
 
/*
 
Coded for The Keep3r Network with ♥ by
 
██████╗░███████╗███████╗██╗  ░██╗░░░░░░░██╗░█████╗░███╗░░██╗██████╗░███████╗██████╗░██╗░░░░░░█████╗░███╗░░██╗██████╗░
██╔══██╗██╔════╝██╔════╝██║  ░██║░░██╗░░██║██╔══██╗████╗░██║██╔══██╗██╔════╝██╔══██╗██║░░░░░██╔══██╗████╗░██║██╔══██╗
██║░░██║█████╗░░█████╗░░██║  ░╚██╗████╗██╔╝██║░░██║██╔██╗██║██║░░██║█████╗░░██████╔╝██║░░░░░███████║██╔██╗██║██║░░██║
██║░░██║██╔══╝░░██╔══╝░░██║  ░░████╔═████║░██║░░██║██║╚████║██║░░██║██╔══╝░░██╔══██╗██║░░░░░██╔══██║██║╚████║██║░░██║
██████╔╝███████╗██║░░░░░██║  ░░╚██╔╝░╚██╔╝░╚█████╔╝██║░╚███║██████╔╝███████╗██║░░██║███████╗██║░░██║██║░╚███║██████╔╝
╚═════╝░╚══════╝╚═╝░░░░░╚═╝  ░░░╚═╝░░░╚═╝░░░╚════╝░╚═╝░░╚══╝╚═════╝░╚══════╝╚═╝░░╚═╝╚══════╝╚═╝░░╚═╝╚═╝░░╚══╝╚═════╝░
 
https://defi.sucks
 
*/
 
pragma solidity >=0.8.7 <0.9.0;
 
import './libraries/FullMath.sol';
import './libraries/TickMath.sol';
import '../interfaces/IKeep3r.sol';
import '../interfaces/external/IKeep3rV1.sol';
import '../interfaces/IKeep3rHelper.sol';
 
import '@openzeppelin/contracts/utils/math/Math.sol';
import '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';
 
contract Keep3rHelper is IKeep3rHelper {
  address public immutable keep3rV2;
 
  constructor(address _keep3rV2) {
    keep3rV2 = _keep3rV2;
  }
 
  /// @inheritdoc IKeep3rHelper
  address public constant override KP3R = 0x1cEB5cB57C4D4E2b2433641b95Dd330A33185A44;
 
  /// @inheritdoc IKeep3rHelper
  address public constant override KP3R_WETH_POOL = 0x11B7a6bc0259ed6Cf9DB8F499988F9eCc7167bf5;
 
  /// @inheritdoc IKeep3rHelper
  uint256 public constant override MIN = 11_000;
 
  /// @inheritdoc IKeep3rHelper
  uint256 public constant override MAX = 12_000;
 
  /// @inheritdoc IKeep3rHelper
  uint256 public constant override BOOST_BASE = 10_000;
 
  /// @inheritdoc IKeep3rHelper
  uint256 public constant override TARGETBOND = 200 ether;
 
  /// @inheritdoc IKeep3rHelper
  function quote(uint256 _eth) public view override returns (uint256 _amountOut) {
    bool _isKP3RToken0 = isKP3RToken0(KP3R_WETH_POOL);
    int56 _tickDifference = IKeep3r(keep3rV2).observeLiquidity(KP3R_WETH_POOL).difference;
    _tickDifference = _isKP3RToken0 ? _tickDifference : -_tickDifference;
    uint256 _tickInterval = IKeep3r(keep3rV2).rewardPeriodTime();
    _amountOut = getQuoteAtTick(uint128(_eth), _tickDifference, _tickInterval);
  }
 
  /// @inheritdoc IKeep3rHelper
  function bonds(address _keeper) public view override returns (uint256 _amountBonded) {
    return IKeep3r(keep3rV2).bonds(_keeper, KP3R);
  }
 
  /// @inheritdoc IKeep3rHelper
  function getRewardAmountFor(address _keeper, uint256 _gasUsed) public view override returns (uint256 _kp3r) {
    uint256 _boost = getRewardBoostFor(bonds(_keeper));
    _kp3r = quote((_gasUsed * _boost) / BOOST_BASE);
  }
 
  /// @inheritdoc IKeep3rHelper
  function getRewardAmount(uint256 _gasUsed) external view override returns (uint256 _amount) {
    // solhint-disable-next-line avoid-tx-origin
    return getRewardAmountFor(tx.origin, _gasUsed);
  }
 
  /// @inheritdoc IKeep3rHelper
  function getRewardBoostFor(uint256 _bonds) public view override returns (uint256 _rewardBoost) {
    _bonds = Math.min(_bonds, TARGETBOND);
    uint256 _cap = Math.max(MIN, MIN + ((MAX - MIN) * _bonds) / TARGETBOND);
    _rewardBoost = _cap * _getBasefee();
  }
 
  /// @inheritdoc IKeep3rHelper
  function getPoolTokens(address _pool) public view override returns (address _token0, address _token1) {
    return (IUniswapV3Pool(_pool).token0(), IUniswapV3Pool(_pool).token1());
  }
 
  /// @inheritdoc IKeep3rHelper
  function isKP3RToken0(address _pool) public view override returns (bool _isKP3RToken0) {
    address _token0;
    address _token1;
    (_token0, _token1) = getPoolTokens(_pool);
    if (_token0 == KP3R) {
      return true;
    } else if (_token1 != KP3R) {
      revert LiquidityPairInvalid();
    }
  }
 
  /// @inheritdoc IKeep3rHelper
  function observe(address _pool, uint32[] memory _secondsAgo)
    public
    view
    override
    returns (
      int56 _tickCumulative1,
      int56 _tickCumulative2,
      bool _success
    )
  {
    try IUniswapV3Pool(_pool).observe(_secondsAgo) returns (int56[] memory _uniswapResponse, uint160[] memory) {
      _tickCumulative1 = _uniswapResponse[0];
      if (_uniswapResponse.length > 1) {
        _tickCumulative2 = _uniswapResponse[1];
      }
      _success = true;
    } catch (bytes memory) {}
  }
 
  /// @inheritdoc IKeep3rHelper
  function getKP3RsAtTick(
    uint256 _liquidityAmount,
    int56 _tickDifference,
    uint256 _timeInterval
  ) public pure override returns (uint256 _kp3rAmount) {
    uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(int24(_tickDifference / int256(_timeInterval)));
    _kp3rAmount = FullMath.mulDiv(1 << 96, _liquidityAmount, sqrtRatioX96);
  }
 
  /// @inheritdoc IKeep3rHelper
  function getQuoteAtTick(
    uint128 _baseAmount,
    int56 _tickDifference,
    uint256 _timeInterval
  ) public pure override returns (uint256 _quoteAmount) {
    uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(int24(_tickDifference / int256(_timeInterval)));
 
    if (sqrtRatioX96 <= type(uint128).max) {
      uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;
      _quoteAmount = FullMath.mulDiv(1 << 192, _baseAmount, ratioX192);
    } else {
      uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);
      _quoteAmount = FullMath.mulDiv(1 << 128, _baseAmount, ratioX128);
    }
  }
 
  /// @notice Gets the block's base fee
  /// @return _baseFee The block's basefee
  function _getBasefee() internal view virtual returns (uint256 _baseFee) {
    return block.basefee;
  }
}