draft fixes for native-only support; tests broken

Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
Uncle Fatso 2025-10-06 15:34:25 +03:00
parent 8746bc747a
commit 9dfd10aff7
Signed by: f4ts0
GPG Key ID: 565F4F2860226EBB
4 changed files with 81 additions and 10 deletions

View File

@ -16,27 +16,33 @@ import "./interfaces/IBondingCalculator.sol";
contract GhostBondingCalculator is IBondingCalculator {
using FixedPoint for *;
uint256 public override immutable fraction;
address internal immutable ftso;
constructor(address _ftso) {
constructor(address _ftso, uint256 _numerator, uint256 _denominator) {
ftso = _ftso;
fraction = FixedPoint.fraction(_numerator, _denominator).decode112with18();
}
function getKValue(address pair) public view returns (uint256 k) {
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) public view returns (uint256 value) {
return _sqrt(getKValue(pair)) * 2;
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);
uint256 totalValue = getTotalValue(pair, true);
uint256 totalSupply = IUniswapV2Pair(pair).totalSupply();
value = totalValue * FixedPoint.fraction(amount, totalSupply).decode112with18() / 1e18;
@ -52,7 +58,8 @@ contract GhostBondingCalculator is IBondingCalculator {
reserve = reserve0;
}
reserve = reserve * (2 * 1e9) / getTotalValue(pair);
reserve = reserve * (2 * 1e9) / getTotalValue(pair, false);
reserve = reserve * _sqrt(fraction) / 1e9;
}
function _sqrt(uint256 a) private pure returns (uint256 c) {

View File

@ -190,7 +190,7 @@ contract GhostTreasury is GhostAccessControlled, ITreasury {
stnk = someAddress;
} else {
permissions[status][someAddress] = true;
if (status == STATUS.LIQUIDITYTOKEN) {
if (status == STATUS.LIQUIDITYTOKEN || status == STATUS.RESERVETOKEN) {
bondCalculator[someAddress] = calculatorAddress;
}
@ -211,6 +211,66 @@ contract GhostTreasury is GhostAccessControlled, ITreasury {
emit Permissioned(toDisable, status, false);
}
// function redeemReserve(
// address router,
// address token,
// uint256 amountIn
// ) external onlyGovernor {
// uint256 balance;
// uint256 amountOutMin;
// uint256 deadline = block.timestamp; // No delays in timestamp
// address weth = IUniswapV2Router(router).WETH();
//
// // Reconstruct path based on token address.
// // Avoid user's input error.
// address[2] memory path = [token, weth];
// if (token >= weth) {
// path[0] = weth;
// path[1] = token;
// }
//
// for (uint256 i; i < path.length;) {
// if (path[i] != WETH) {
// balance = IERC20(path[i]).balanceOf(address(this));
// // amountOutMin = ...
// // put big sqrt formula here
// }
// unchecked { ++i; }
// }
//
// // Approve amountIn for swap only.
// if (IERC20(token).allowance(router) <= amountIn) {
// IERC20(token).approve(router, 1e64);
// }
//
// (amountIn, amountOut) = IUniswapV2Router(router).swapExactTokensForTokens(
// amountIn,
// amountOutMin,
// path,
// address(this),
// deadline
// );
//
// if (IERC20(token).allowance(router) <= desiredA) {
// IERC20(token).approve(router, 1e64);
// }
//
// if (IERC20(weth).allowance(router) <= desiredB) {
// IERC20(token).approve(router, 1e64);
// }
//
// IUniswapV2Router(router).addLiquidity(
// path[0],
// path[1],
// desiredA, // could be calculated with sqrt formula
// desiredB, // same as above
// minA, // zeroed or calculated or precomputed?
// minB, // zeroed or calculated or precomputed?
// address(this),
// deadline
// );
// }
function indexInRegistry(
address someAddress,
STATUS status
@ -266,7 +326,7 @@ contract GhostTreasury is GhostAccessControlled, ITreasury {
} else {
permissions[info.managing][info.toPermit] = true;
if (info.managing == STATUS.LIQUIDITYTOKEN) {
if (info.managing == STATUS.LIQUIDITYTOKEN || info.managing == STATUS.RESERVETOKEN) {
bondCalculator[info.toPermit] = info.calculator;
}
@ -301,10 +361,13 @@ contract GhostTreasury is GhostAccessControlled, ITreasury {
address token,
uint256 amount
) public view override returns (uint256 value) {
value = amount * 1e9 / (10**IERC20Metadata(token).decimals());
address currentBondCalculator = bondCalculator[token];
if (permissions[STATUS.LIQUIDITYTOKEN][token]) {
value = IBondingCalculator(bondCalculator[token]).valuation(token, amount);
} else {
value = amount * 1e9 / (10**IERC20Metadata(token).decimals());
value = value * IBondingCalculator(currentBondCalculator).fraction() / 1e18;
}
}

View File

@ -3,6 +3,7 @@ pragma solidity ^0.8.20;
interface IBondingCalculator {
error InvalidPair();
function fraction() external view returns (uint256);
function markdown(address _lp) external view returns (uint256);
function valuation(address pair_, uint256 amount_) external view returns (uint256 _value);
}

View File

@ -37,7 +37,7 @@ contract GhostTreasuryTest is Test {
liquidity = new ERC20Mock("Liquidity Token", "LDT");
ftso = new Fatso(address(authority), "Fatso", "FTSO");
treasury = new GhostTreasury(address(ftso), 69, address(authority));
calculator = new GhostBondingCalculator(address(ftso));
calculator = new GhostBondingCalculator(address(ftso), 1, 1);
vm.stopPrank();
vm.prank(governor);