priceRatio stored and used in vwap always ETH/HARB. fixed compatibility.

This commit is contained in:
roleengineer 2024-08-13 17:06:12 +03:00 committed by giteadmin
parent 1dfa81ea57
commit 0329a5da4f
2 changed files with 21 additions and 16 deletions

View file

@ -24,7 +24,7 @@ import {Harberg} from "./Harberg.sol";
* - Discovery Position: Expands liquidity by minting new Harberg tokens as the price rises, capturing potential growth in the ecosystem.
* The contract dynamically adjusts these positions in response to market movements to maintain strategic liquidity levels and support the Harberg token's price.
* It also collects and transfers fees generated from trading activities to a designated fee destination.
* @dev Utilizes Uniswap V3's concentrated liquidity feature, enabling highly efficient use of capital.
* @dev Utilizes Uniswap V3's concentrated liquidity feature, enabling highly efficient use of capital.
*/
contract LiquidityManager {
using Math for uint256;
@ -45,7 +45,7 @@ contract LiquidityManager {
// only working with UNI V3 1% fee tier pools
uint24 internal constant FEE = uint24(10_000);
uint160 internal constant MIN_SQRT_RATIO = 4295128739;
// ANCHOR_LIQ_SHARE is the mininum share of total ETH in control
// ANCHOR_LIQ_SHARE is the mininum share of total ETH in control
// that will be left to put into anchor positon.
uint256 internal constant MIN_ANCHOR_LIQ_SHARE = 5; // 5 = 5%
uint256 internal constant MAX_ANCHOR_LIQ_SHARE = 25;
@ -166,7 +166,8 @@ contract LiquidityManager {
function tickAtPrice(bool t0isWeth, uint256 tokenAmount, uint256 ethAmount) internal pure returns (int24 tick_) {
require(ethAmount > 0, "ETH amount cannot be zero");
if (tokenAmount == 0) {
tick_ = t0isWeth ? TickMath.MIN_TICK : TickMath.MAX_TICK;
// HARB/ETH
tick_ = TickMath.MAX_TICK;
} else {
// Use a fixed-point library or more precise arithmetic for the division here.
// For example, using ABDKMath64x64 for a more precise division and square root calculation.
@ -174,17 +175,19 @@ contract LiquidityManager {
int128(int256(tokenAmount)),
int128(int256(ethAmount))
);
tick_ = tickAtPriceRatio(t0isWeth, priceRatioX64);
// HARB/ETH
tick_ = tickAtPriceRatio(priceRatioX64);
}
// convert to tick in a pool
tick_ = t0isWeth ? tick_ : -tick_;
}
function tickAtPriceRatio(bool t0isWeth, int128 priceRatioX64) internal pure returns (int24 tick_) {
function tickAtPriceRatio(int128 priceRatioX64) internal pure returns (int24 tick_) {
// Convert the price ratio into a sqrt price in the format expected by Uniswap's TickMath.
uint160 sqrtPriceX96 = uint160(
int160(ABDKMath64x64.sqrt(priceRatioX64) << 32)
);
tick_ = TickMath.getTickAtSqrtRatio(sqrtPriceX96);
tick_ = t0isWeth ? tick_ : -tick_;
}
/// @notice Calculates the price ratio from a given Uniswap V3 tick as HARB/ETH.
@ -241,16 +244,17 @@ contract LiquidityManager {
// not enough ETH, find a lower price
requiredEthForBuyback = floorEthBalance;
vwapTick = tickAtPrice(token0isWeth, outstandingSupply * capitalInfefficiency / 100 , requiredEthForBuyback);
emit EthScarcity(currentTick, ethBalance, outstandingSupply, vwapX96, capitalInfefficiency, anchorLiquidityShare, vwapTick);
emit EthScarcity(currentTick, ethBalance, outstandingSupply, vwapX96, capitalInfefficiency, anchorLiquidityShare, vwapTick);
} else if (vwapX96 == 0) {
requiredEthForBuyback = floorEthBalance;
vwapTick = currentTick;
} else {
// recalculate vwap with capital inefficiency
vwapX96 = cumulativeVolumeWeightedPriceX96 * capitalInfefficiency / 100 / cumulativeVolume; // in harb/eth
vwapTick = tickAtPriceRatio(token0isWeth, int128(int256 (vwapX96 >> 32)));
vwapTick = token0isWeth ? vwapTick : -vwapTick;
// ETH/HARB tick
vwapTick = tickAtPriceRatio(int128(int256(vwapX96 >> 32)));
// convert to pool tick
vwapTick = token0isWeth ? -vwapTick : vwapTick;
emit EthAbundance(currentTick, ethBalance, outstandingSupply, vwapX96, capitalInfefficiency, anchorLiquidityShare, vwapTick);
}
// never make floor smaller than anchor
@ -265,7 +269,7 @@ contract LiquidityManager {
vwapTick = (vwapTick > currentTick - ANCHOR_SPACING) ? currentTick - ANCHOR_SPACING : vwapTick;
}
// normalize tick position for pool
// normalize tick position for pool
vwapTick = vwapTick / TICK_SPACING * TICK_SPACING;
// calculate liquidity
uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(vwapTick);
@ -336,7 +340,7 @@ contract LiquidityManager {
);
}
_mint(Stage.DISCOVERY, tickLower, tickUpper, liquidity);
harb.burn(harb.balanceOf(address(this)));
harb.burn(harb.balanceOf(address(this)));
}
}

View file

@ -127,6 +127,7 @@ contract LiquidityManagerTest is Test {
lm = new LiquidityManager(factoryAddress, address(weth), address(harberg));
lm.setFeeDestination(feeDestination);
harberg.setLiquidityManager(address(lm));
harberg.setLiquidityPool(address(pool));
vm.deal(address(lm), 10 ether);
createCSVHeader();
}
@ -137,7 +138,7 @@ contract LiquidityManagerTest is Test {
vm.warp(timeBefore + (60 * 60 * 5));
try lm.recenter() {
// Check liquidity positions after slide
(uint256 ethFloor, uint256 ethAnchor, uint256 ethDiscovery, uint256 harbergFloor, uint256 harbergAnchor, uint256 harbergDiscovery) = checkLiquidityPositionsAfter("slide");
assertGt(ethFloor, ethAnchor, "slide - Floor should hold more ETH than Anchor");
@ -180,7 +181,7 @@ contract LiquidityManagerTest is Test {
function getBalancesPool(LiquidityManager.Stage s) internal view returns (int24 currentTick, int24 tickLower, int24 tickUpper, uint256 ethAmount, uint256 harbergAmount) {
(,tickLower, tickUpper) = lm.positions(s);
(uint128 liquidity, , , ,) = pool.positions(keccak256(abi.encodePacked(address(lm), tickLower, tickUpper)));
// Fetch the current price from the pool
uint160 sqrtPriceX96;
(sqrtPriceX96, currentTick, , , , , ) = pool.slot0();
@ -425,7 +426,7 @@ contract LiquidityManagerTest is Test {
// assertEq(ethDiscovery, 0, "Discovery should not have ETH");
// assertEq(harbergFloor, 0, "Floor should have no HARB");
// assertGt(harbergAnchor, 0, "Anchor should have HARB");
// assertGt(harbergDiscovery, 0, "Discovery should have HARB");
// assertGt(harbergDiscovery, 0, "Discovery should have HARB");
// // Introduce large buy to push into discovery
// buy(3 ether);
@ -619,4 +620,4 @@ contract LiquidityManagerTest is Test {
assertGt(traderBalanceBefore, traderBalanceAfter, "trader should not have made profit");
}
}
}