78 lines
2.7 KiB
Solidity
78 lines
2.7 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.20;
|
|
|
|
import "./libraries/FixedPoint.sol";
|
|
|
|
import "@openzeppelin-contracts/utils/Address.sol";
|
|
import "@openzeppelin-contracts/token/ERC20/IERC20.sol";
|
|
import "@openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
|
|
import "@openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
|
|
import "@uniswap-v2-core/interfaces/IUniswapV2ERC20.sol";
|
|
import "@uniswap-v2-core/interfaces/IUniswapV2Pair.sol";
|
|
|
|
import "./interfaces/IBondingCalculator.sol";
|
|
|
|
contract GhostBondingCalculator is IBondingCalculator {
|
|
using FixedPoint for *;
|
|
|
|
uint256 public override immutable fraction;
|
|
address internal immutable ftso;
|
|
|
|
constructor(address _ftso, uint256 _numerator, uint256 _denominator) {
|
|
ftso = _ftso;
|
|
fraction = FixedPoint.fraction(_numerator, _denominator).decode112with18();
|
|
}
|
|
|
|
function getKValue(address pair, bool isCoefficient) public view returns (uint256 k) {
|
|
uint256 token0 = IERC20Metadata(IUniswapV2Pair(pair).token0()).decimals();
|
|
uint256 token1 = IERC20Metadata(IUniswapV2Pair(pair).token1()).decimals();
|
|
uint256 decimals = token0 + token1 - IERC20Metadata(pair).decimals();
|
|
|
|
(uint256 reserve0, uint256 reserve1, ) = IUniswapV2Pair(pair).getReserves();
|
|
k = reserve0 * reserve1 / (10**decimals);
|
|
|
|
if (isCoefficient) {
|
|
k = k * 1e18 / fraction;
|
|
}
|
|
}
|
|
|
|
function getTotalValue(address pair, bool isCoefficient) public view returns (uint256) {
|
|
return _sqrt(getKValue(pair, isCoefficient)) * 2;
|
|
}
|
|
|
|
function valuation(address pair, uint256 amount) external view override returns (uint256 value) {
|
|
uint256 totalValue = getTotalValue(pair, true);
|
|
uint256 totalSupply = IUniswapV2Pair(pair).totalSupply();
|
|
|
|
value = totalValue * FixedPoint.fraction(amount, totalSupply).decode112with18() / 1e18;
|
|
}
|
|
|
|
function markdown(address pair) external view override returns (uint256 reserve) {
|
|
(uint256 reserve0, uint256 reserve1, ) = IUniswapV2Pair(pair).getReserves();
|
|
|
|
if (IUniswapV2Pair(pair).token0() == ftso) {
|
|
reserve = reserve1;
|
|
} else {
|
|
if (IUniswapV2Pair(pair).token1() != ftso) revert InvalidPair();
|
|
reserve = reserve0;
|
|
}
|
|
|
|
reserve = reserve * (2 * 1e9) / getTotalValue(pair, false);
|
|
reserve = reserve * _sqrt(fraction) / 1e9;
|
|
}
|
|
|
|
function _sqrt(uint256 a) private pure returns (uint256 c) {
|
|
if (a > 3) {
|
|
c = a;
|
|
uint256 b = (a / 2) + 1;
|
|
while (b < c) {
|
|
c = b;
|
|
b = ((a / b) + b) / 2;
|
|
}
|
|
} else if (a != 0) {
|
|
c = 1;
|
|
}
|
|
}
|
|
}
|