make slide and shift one function
This commit is contained in:
parent
ae8c3a1e4f
commit
694afbe9fe
3 changed files with 25 additions and 61 deletions
|
|
@ -73,7 +73,7 @@ contract SepoliaScript is Script {
|
|||
harb.setLiquidityManager(address(liquidityManager));
|
||||
(bool sent, ) = address(liquidityManager).call{value: 0.1 ether}("");
|
||||
require(sent, "Failed to send Ether");
|
||||
//TODO: wait few minutes and call slide
|
||||
//TODO: wait few minutes and call recenter
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,9 +40,6 @@ 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;
|
||||
|
||||
/* ============ Potential Gov Params ============ */
|
||||
|
||||
// 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%
|
||||
|
|
@ -52,11 +49,6 @@ contract LiquidityManager {
|
|||
uint256 internal constant MIN_CAPITAL_INEFFICIENCY = 100; // 120 = 20%
|
||||
uint256 internal constant MAX_CAPITAL_INEFFICIENCY = 200;
|
||||
|
||||
|
||||
|
||||
// the 3 positions this contract is managing
|
||||
enum Stage { FLOOR, ANCHOR, DISCOVERY }
|
||||
|
||||
// the address of the Uniswap V3 factory
|
||||
address private immutable factory;
|
||||
IWETH9 private immutable weth;
|
||||
|
|
@ -65,6 +57,9 @@ contract LiquidityManager {
|
|||
bool private immutable token0isWeth;
|
||||
PoolKey private poolKey;
|
||||
|
||||
// the 3 positions this contract is managing
|
||||
enum Stage { FLOOR, ANCHOR, DISCOVERY }
|
||||
|
||||
struct TokenPosition {
|
||||
// the liquidity of the position
|
||||
uint128 liquidity;
|
||||
|
|
@ -86,8 +81,8 @@ contract LiquidityManager {
|
|||
error ZeroAddressInSetter();
|
||||
error AddressAlreadySet();
|
||||
|
||||
event EthScarcity(int24 currentTick, uint256 ethBalance, uint256 outstandingSupply, uint256 vwap, uint256 CAPITAL_INEFFICIENCY, uint256 ANCHOR_LIQ_SHARE, int24 vwapTick);
|
||||
event EthAbundance(int24 currentTick, uint256 ethBalance, uint256 outstandingSupply, uint256 vwap, uint256 CAPITAL_INEFFICIENCY, uint256 ANCHOR_LIQ_SHARE, int24 vwapTick);
|
||||
event EthScarcity(int24 currentTick, uint256 ethBalance, uint256 outstandingSupply, uint256 vwap, uint256 capitalInfefficiency, uint256 anchorLiquidityShare, int24 vwapTick);
|
||||
event EthAbundance(int24 currentTick, uint256 ethBalance, uint256 outstandingSupply, uint256 vwap, uint256 capitalInfefficiency, uint256 anchorLiquidityShare, int24 vwapTick);
|
||||
|
||||
/// @dev Function modifier to ensure that the caller is the feeDestination
|
||||
modifier onlyFeeDestination() {
|
||||
|
|
@ -151,7 +146,6 @@ contract LiquidityManager {
|
|||
}
|
||||
|
||||
receive() external payable {
|
||||
|
||||
}
|
||||
|
||||
/// @notice Calculates the Uniswap V3 tick corresponding to a given price ratio between Harb and ETH.
|
||||
|
|
@ -401,64 +395,31 @@ contract LiquidityManager {
|
|||
secondsAgo[0] = timeInterval; // 5 minutes ago
|
||||
secondsAgo[1] = 0; // current block timestamp
|
||||
|
||||
//(int56[] memory tickCumulatives,) = pool.observe(secondsAgo);
|
||||
int56 tickCumulativeDiff;
|
||||
int24 averageTick;
|
||||
try pool.observe(secondsAgo) returns (int56[] memory tickCumulatives, uint160[] memory) {
|
||||
tickCumulativeDiff = tickCumulatives[1] - tickCumulatives[0];
|
||||
averageTick = int24(tickCumulativeDiff / int56(int32(timeInterval)));
|
||||
// Process the data
|
||||
} catch {
|
||||
return true;
|
||||
// TODO:
|
||||
return false;
|
||||
}
|
||||
|
||||
return (currentTick >= averageTick - MAX_TICK_DEVIATION && currentTick <= averageTick + MAX_TICK_DEVIATION);
|
||||
}
|
||||
|
||||
/// @notice Adjusts liquidity positions upward in response to an increase in the Harb token's price.
|
||||
/// @dev This function should be called when significant upward price movement is detected. It recalibrates the liquidity ranges to align with the new market conditions.
|
||||
function shift() external {
|
||||
require(positions[Stage.ANCHOR].liquidity > 0, "Not initialized");
|
||||
/// @notice Adjusts liquidity positions in response to an increase or decrease in the Harb token's price.
|
||||
/// @dev This function should be called when significant price movement is detected. It recalibrates the liquidity ranges to align with the new market conditions.
|
||||
function recenter() external {
|
||||
// Fetch the current tick from the Uniswap V3 pool
|
||||
(, int24 currentTick, , , , , ) = pool.slot0();
|
||||
// check slippage with oracle
|
||||
require(_isPriceStable(currentTick), "price deviated from oracle");
|
||||
|
||||
// ## check price moved up
|
||||
{
|
||||
// Check if current tick is within the specified range
|
||||
int24 anchorTickLower = positions[Stage.ANCHOR].tickLower;
|
||||
int24 anchorTickUpper = positions[Stage.ANCHOR].tickUpper;
|
||||
|
||||
int24 centerTick = token0isWeth ? anchorTickLower + ANCHOR_SPACING : anchorTickUpper - ANCHOR_SPACING;
|
||||
uint256 minAmplitude = uint256(uint24((anchorTickUpper - anchorTickLower) * 3 / 20));
|
||||
|
||||
// Determine the correct comparison direction based on token0isWeth
|
||||
bool isUp = token0isWeth ? currentTick < centerTick : currentTick > centerTick;
|
||||
bool isEnough = SignedMath.abs(currentTick - centerTick) > minAmplitude;
|
||||
|
||||
// Check Conditions
|
||||
require(isEnough, "amplitude not reached, come back later!");
|
||||
require(isUp, "call slide(), not shift()");
|
||||
}
|
||||
|
||||
// ## scrape positions
|
||||
_scrape();
|
||||
harb.setPreviousTotalSupply(harb.totalSupply());
|
||||
_set(currentTick);
|
||||
}
|
||||
|
||||
/// @notice Adjusts liquidity positions downward in response to a decrease in the Harb token's price.
|
||||
/// @dev This function should be called when significant downward price movement is detected. It recalibrates the liquidity ranges to align with the new market conditions.
|
||||
function slide() external {
|
||||
// Fetch the current tick from the Uniswap V3 pool
|
||||
(, int24 currentTick, , , , , ) = pool.slot0();
|
||||
// check slippage with oracle
|
||||
require(_isPriceStable(currentTick), "price deviated from oracle");
|
||||
|
||||
// ## check price moved down
|
||||
bool isUp = false;
|
||||
// check how price moved
|
||||
if (positions[Stage.ANCHOR].liquidity > 0) {
|
||||
// Check if current tick is within the specified range
|
||||
// get the anchor position
|
||||
int24 anchorTickLower = positions[Stage.ANCHOR].tickLower;
|
||||
int24 anchorTickUpper = positions[Stage.ANCHOR].tickUpper;
|
||||
|
||||
|
|
@ -467,15 +428,19 @@ contract LiquidityManager {
|
|||
uint256 minAmplitude = uint256(uint24((anchorTickUpper - anchorTickLower) * 3 / 20));
|
||||
|
||||
// Determine the correct comparison direction based on token0isWeth
|
||||
bool isDown = token0isWeth ? currentTick > centerTick : currentTick < centerTick;
|
||||
isUp = token0isWeth ? currentTick < centerTick : currentTick > centerTick;
|
||||
bool isEnough = SignedMath.abs(currentTick - centerTick) > minAmplitude;
|
||||
|
||||
// Check Conditions
|
||||
require(isEnough, "amplitude not reached, diamond hands!");
|
||||
require(isDown, "call shift(), not slide()");
|
||||
require(isEnough, "amplitude not reached.");
|
||||
}
|
||||
|
||||
// take out all old positions
|
||||
_scrape();
|
||||
if (isUp) {
|
||||
harb.setPreviousTotalSupply(harb.totalSupply());
|
||||
}
|
||||
// set new positions
|
||||
_set(currentTick);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ contract LiquidityManagerTest is Test {
|
|||
uint256 timeBefore = block.timestamp;
|
||||
vm.warp(timeBefore + (60 * 60 * 5));
|
||||
|
||||
try lm.slide() {
|
||||
try lm.recenter() {
|
||||
|
||||
// Check liquidity positions after slide
|
||||
(uint256 ethFloor, uint256 ethAnchor, uint256 ethDiscovery, uint256 harbFloor, uint256 harbAnchor, uint256 harbDiscovery) = checkLiquidityPositionsAfter("slide");
|
||||
|
|
@ -145,7 +145,7 @@ contract LiquidityManagerTest is Test {
|
|||
assertEq(harbFloor, 0, "slide - Floor should have no HARB");
|
||||
assertEq(ethDiscovery, 0, "slide - Discovery should have no ETH");
|
||||
} catch Error(string memory reason) {
|
||||
if (keccak256(abi.encodePacked(reason)) == keccak256(abi.encodePacked("amplitude not reached, diamond hands!"))) {
|
||||
if (keccak256(abi.encodePacked(reason)) == keccak256(abi.encodePacked("amplitude not reached."))) {
|
||||
console.log("slide failed on amplitude");
|
||||
} else {
|
||||
if (!last) {
|
||||
|
|
@ -160,8 +160,7 @@ contract LiquidityManagerTest is Test {
|
|||
uint256 timeBefore = block.timestamp;
|
||||
vm.warp(timeBefore + (60 * 60 * 5));
|
||||
|
||||
//lm.shift();
|
||||
try lm.shift() {
|
||||
try lm.recenter() {
|
||||
// Check liquidity positions after shift
|
||||
(uint256 ethFloor, uint256 ethAnchor, uint256 ethDiscovery, uint256 harbFloor, uint256 harbAnchor, uint256 harbDiscovery) = checkLiquidityPositionsAfter("shift");
|
||||
assertGt(ethFloor, ethAnchor, "shift - Floor should hold more ETH than Anchor");
|
||||
|
|
@ -169,7 +168,7 @@ contract LiquidityManagerTest is Test {
|
|||
assertEq(harbFloor, 0, "shift - Floor should have no HARB");
|
||||
assertEq(ethDiscovery, 0, "shift - Discovery should have no ETH");
|
||||
} catch Error(string memory reason) {
|
||||
if (keccak256(abi.encodePacked(reason)) == keccak256(abi.encodePacked("amplitude not reached, come back later!"))) {
|
||||
if (keccak256(abi.encodePacked(reason)) == keccak256(abi.encodePacked("amplitude not reached."))) {
|
||||
console.log("shift failed on amplitude");
|
||||
} else {
|
||||
revert(reason); // Rethrow the error if it's not the expected message
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue