From 9dc543df0c65f47bccba2875fabe62e372d1739b Mon Sep 17 00:00:00 2001 From: MazyGio Date: Sun, 6 Jul 2025 10:33:02 -0500 Subject: [PATCH 1/5] fix rebalancing calculations. Add more steps to the example script --- foundry.toml | 3 + script/scenarios/EulerSwapDebtScenario.s.sol | 85 ++++-- src/JITpilot.sol | 262 ++++++++++++++----- 3 files changed, 269 insertions(+), 81 deletions(-) diff --git a/foundry.toml b/foundry.toml index ec90863..adfa41a 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,6 +2,9 @@ src = "src" out = "out" libs = ["lib"] +viaIR = true +optimizer = true +optimizer_runs = 1000 # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/script/scenarios/EulerSwapDebtScenario.s.sol b/script/scenarios/EulerSwapDebtScenario.s.sol index 1070249..2424af1 100644 --- a/script/scenarios/EulerSwapDebtScenario.s.sol +++ b/script/scenarios/EulerSwapDebtScenario.s.sol @@ -7,10 +7,11 @@ import {IEulerSwap} from "euler-swap/interfaces/IEulerSwap.sol"; import {HookMiner} from "../../libflat/euler-swap/test/utils/HookMiner.sol"; import {Hooks} from "v4-core/libraries/Hooks.sol"; import {MetaProxyDeployer} from "euler-swap/utils/MetaProxyDeployer.sol"; -import {console2 as console} from "forge-std/console2.sol"; import {TestERC20} from "evk-test/unit/evault/EVaultTestBase.t.sol"; import {IEVault} from "evk/EVault/IEVault.sol"; +import {console2 as console} from "forge-std/console2.sol"; + contract EulerSwapDebtScenario is DeployScenario { address eulerSwap; JITpilot jitPilot; @@ -19,10 +20,14 @@ contract EulerSwapDebtScenario is DeployScenario { vm.startBroadcast(user3PK); eUSDC.setLTV(address(eWETH), 0.65e4, 0.67e4, 0); eUSDC.setLTV(address(eUSDT), 0.85e4, 0.87e4, 0); - deployJITPilot(); + deployJITpilot(); vm.stopBroadcast(); - createEulerSwap(); // user 2 + vm.startBroadcast(user2PK); + createEulerSwap(); + authorizeJITpilot(user2); + jitPilot.configureLp(user2, 1.4e18, 1.5e18); + vm.stopBroadcast(); // create borrow positions for other users giveTonsOfCash(user0); @@ -35,12 +40,38 @@ contract EulerSwapDebtScenario is DeployScenario { borrowFromVault(user0, user0PK, address(eWETH), 500_000e18); borrowFromVault(user1, user1PK, address(eUSDC), 1_600_000_000e6); - jitPilot.getData(user2); - console.log("user2", user2); + console.log("user2 vault deposits: ", eWETH.balanceOf(user2)); + console.log("user2 vault deposits: ", eUSDC.balanceOf(user2)); - // buy USDC so that user2's EulerSwap position has to borrow + // buy USDC so that user2's EulerSwap position has to borrow USDC uint256 amountOut = 286_500_000e6; - _swapExactOut(address(assetWETH), address(assetUSDC), amountOut, user0, user0PK); + uint256 amountIn = _swapExactOut(address(assetWETH), address(assetUSDC), amountOut, user0, user0PK); + console.log("SOLD %s WETH FOR %s USDC", amountIn, amountOut); + + // user2 is in debt now. Let's fetch that data + JITpilot.BlockData memory blockData = jitPilot.getData(user2); + + console.log("=========================================================="); + console.log("EulerSwap instance is in debt now:"); + console.log("allowedLTV: ", blockData.allowedLTV); + console.log("currentLTV: ", blockData.currentLTV); + console.log("swapFees: ", blockData.swapFees); + console.log("netInterest: ", blockData.netInterest); + console.log("depositValue: ", blockData.depositValue); + console.log("controllerVault: ", blockData.controllerVault); + console.log("=========================================================="); + + // Get a quote for the current price of ETH in the EulerSwap instance + uint256 ethPrice = eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18); + console.log("New price of ETH: ", ethPrice); + + // ETH price has dropped to ~2510. Let's update the oracle + vm.prank(user3); + oracle.setPrice(address(eWETH), unitOfAccount, ethPrice * 1e18 / 1e6); + + // Let's see what the rebalancing params would be + IEulerSwap.Params memory newParams = jitPilot.getRebalancingParams(user2); + printEulerSwapParams(newParams); } function giveTonsOfCash(address user) internal virtual { @@ -52,7 +83,7 @@ contract EulerSwapDebtScenario is DeployScenario { assetUSDZ.mint(user, 1_000_000_000e18); } - function deployJITPilot() internal { + function deployJITpilot() internal { jitPilot = new JITpilot(); jitPilot.setEVC(address(evc)); // jitPilot.setEVK(address(factory)); @@ -63,9 +94,11 @@ contract EulerSwapDebtScenario is DeployScenario { vm.writeJson(result, "./dev-ctx/addresses/31337/JITpilotAddresses.json"); } - function createEulerSwap() internal { - vm.startBroadcast(user2PK); + function authorizeJITpilot(address user) internal { + evc.setAccountOperator(user, address(jitPilot), true); + } + function createEulerSwap() internal { // Create pool parameters IEulerSwap.Params memory poolParams = IEulerSwap.Params({ vault0: address(eUSDC), @@ -82,6 +115,9 @@ contract EulerSwapDebtScenario is DeployScenario { protocolFeeRecipient: address(0) }); + console.log("INITIAL EULERSWAP PARAMS"); + printEulerSwapParams(poolParams); + // Define required hook flags uint160 flags = uint160( Hooks.BEFORE_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG @@ -101,7 +137,6 @@ contract EulerSwapDebtScenario is DeployScenario { string memory result = vm.serializeAddress("eulerSwap", "eulerSwap", address(eulerSwap)); vm.writeJson(result, "./dev-ctx/addresses/31337/EulerSwapAddresses.json"); - vm.stopBroadcast(); } function depositCollateralIntoVault(address user, uint256 userPK, address vaultAddress, uint256 amount) internal { @@ -133,18 +168,13 @@ contract EulerSwapDebtScenario is DeployScenario { function _swapExactOut(address tokenIn, address tokenOut, uint256 amountOut, address receiver, uint256 userPK) internal + returns (uint256 amountIn) { vm.startBroadcast(userPK); - uint256 amountIn = eulerSwapPeriphery.quoteExactOutput(eulerSwap, tokenIn, tokenOut, amountOut); + amountIn = eulerSwapPeriphery.quoteExactOutput(eulerSwap, tokenIn, tokenOut, amountOut); console.log("amountIn", amountIn); TestERC20(tokenIn).approve(address(eulerSwapPeriphery), type(uint256).max); - console.log("user1's WETH balance (tokenIn)", TestERC20(tokenIn).balanceOf(user1)); - console.log("WETH address (tokenIn)", tokenIn); - console.log("user1's USDC balance (tokenOut)", TestERC20(tokenOut).balanceOf(user1)); - console.log("USDC address (tokenOut)", tokenOut); - console.log("user1's address: ", user1); - console.log("eulerSwap address: ", eulerSwap); eulerSwapPeriphery.swapExactOut( eulerSwap, tokenIn, @@ -155,5 +185,24 @@ contract EulerSwapDebtScenario is DeployScenario { 0 ); vm.stopBroadcast(); + + return amountIn; + } + + function printEulerSwapParams(IEulerSwap.Params memory params) internal { + console.log("=========================================================="); + console.log("vault0: ", params.vault0); + console.log("vault1: ", params.vault1); + console.log("eulerAccount: ", params.eulerAccount); + console.log("equilibriumReserve0: ", params.equilibriumReserve0); + console.log("equilibriumReserve1: ", params.equilibriumReserve1); + console.log("priceX: ", params.priceX); + console.log("priceY: ", params.priceY); + console.log("concentrationX: ", params.concentrationX); + console.log("concentrationY: ", params.concentrationY); + console.log("fee: ", params.fee); + console.log("protocolFee: ", params.protocolFee); + console.log("protocolFeeRecipient: ", params.protocolFeeRecipient); + console.log("=========================================================="); } } diff --git a/src/JITpilot.sol b/src/JITpilot.sol index 9ca73dc..896dcf8 100644 --- a/src/JITpilot.sol +++ b/src/JITpilot.sol @@ -8,6 +8,9 @@ import {IEulerSwapFactory} from "euler-swap/interfaces/IEulerSwapFactory.sol"; import {IMaglevLens} from "src/interfaces/IMaglevLens.sol"; import {IPriceOracle} from "evk/interfaces/IPriceOracle.sol"; import {console2 as console} from "forge-std/console2.sol"; +import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; + +import {CurveLib} from "euler-swap/libraries/CurveLib.sol"; /** * @title JITpilot @@ -39,6 +42,7 @@ contract JITpilot { uint256 swapFees; int256 netInterest; int256 depositValue; + address controllerVault; } // LP data structure @@ -59,6 +63,8 @@ contract JITpilot { // Tracking uint256 lastUpdateBlock; // Last block when metrics were updated uint256 startBlock; // Block when LP started + EulerSwapData eulerSwapData; // Latest EulerSwap parameters + BlockData blockData; // Latest EulerSwap state data bool initialized; // Whether LP data is initialized } @@ -73,13 +79,12 @@ contract JITpilot { uint256 healthFactor, uint256 yield, uint256 twaHF, - uint256 twaYield, - uint256 compositeScore + uint256 twaYield ); - event RebalanceTriggered(address indexed lp, uint256 indexed blockNumber, uint256 compositeScore, uint256 threshold, uint256 targetScore); + event RebalanceTriggered(address indexed lp, uint256 indexed blockNumber, uint256 hf, uint256 threshold); - event LPConfigured(address indexed lp, uint256 hfMin, uint256 hfDesired, uint256 yieldTarget); + event LPConfigured(address indexed lp, uint256 hfMin, uint256 hfDesired); // Modifiers modifier onlyAuthorized() { @@ -120,24 +125,19 @@ contract JITpilot { * @param lp LP address * @param _hfMin Liquidation threshold * @param _hfDesired Target health factor - * @param _yieldTarget Target yield */ - function configureLp(address lp, uint256 _hfMin, uint256 _hfDesired, uint256 _yieldTarget) external { + function configureLp(address lp, uint256 _hfMin, uint256 _hfDesired) external { require(lp != address(0), "Invalid LP address"); require(_hfDesired > _hfMin, "HF desired must be > HF min"); LPData storage data = lpData[lp]; data.hfMin = _hfMin; data.hfDesired = _hfDesired; - data.yieldTarget = _yieldTarget; + // data.yieldTarget = _yieldTarget; data.initialized = true; data.startBlock = block.number; - // Calculate and store thresholds once during configuration - data.rebalanceThreshold = calculateRebalanceThreshold(lp); - data.rebalanceDesired = calculateRebalanceDesired(lp); - - emit LPConfigured(lp, _hfMin, _hfDesired, _yieldTarget); + emit LPConfigured(lp, _hfMin, _hfDesired); } /** @@ -159,25 +159,25 @@ contract JITpilot { } // Calculate current Yield - uint256 currentYield = 0; - uint256 swapApy = uint256(int256(currentData.swapFees) * 1e18 / currentData.depositValue); - if (currentData.depositValue > 0) { - if (currentData.netInterest >= 0) { - currentYield = (uint256(currentData.netInterest) * PRECISION) + swapApy; - } else if (swapApy >= uint256(currentData.netInterest)) { - // netInterest is negative, but swapApy is greater, so yield is positive. - currentYield = swapApy - uint256(currentData.netInterest); - } else { - // Yield is negative. Set to 0 for simplicity. - currentYield = 0; - } - } + // uint256 currentYield = 0; + // uint256 swapApy = uint256(int256(currentData.swapFees) * 1e18 / currentData.depositValue); + // if (currentData.depositValue > 0) { + // if (currentData.netInterest >= 0) { + // currentYield = (uint256(currentData.netInterest) * PRECISION) + swapApy; + // } else if (swapApy >= uint256(currentData.netInterest)) { + // // netInterest is negative, but swapApy is greater, so yield is positive. + // currentYield = swapApy - uint256(currentData.netInterest); + // } else { + // // Yield is negative. Set to 0 for simplicity. + // currentYield = 0; + // } + // } // Update sliding window for Health Factor _updateSlidingWindow(data.hfHistory, currentHF); // Update sliding window for Yield - _updateSlidingWindow(data.yieldHistory, currentYield); + // _updateSlidingWindow(data.yieldHistory, currentYield); // Calculate TWA for Health Factor data.twaHF = _calculateTWA(data.hfHistory, data.startBlock); @@ -187,20 +187,21 @@ contract JITpilot { // Calculate normalized values uint256 normalizedHF = _normalizeHealthFactor(data.twaHF, data.hfMin, data.hfDesired); - uint256 normalizedYield = _normalizeYield(data.twaYield, data.yieldTarget); + // uint256 normalizedYield = _normalizeYield(data.twaYield, data.yieldTarget); // Calculate composite score - uint256 compositeScore = (weightHF * normalizedHF + weightYield * normalizedYield) / PRECISION; + // uint256 compositeScore = (weightHF * normalizedHF + weightYield * normalizedYield) / PRECISION; // Update last update block data.lastUpdateBlock = block.number; // Emit metrics updated event - emit MetricsUpdated(lp, block.number, currentHF, currentYield, data.twaHF, data.twaYield, compositeScore); + // emit MetricsUpdated(lp, block.number, currentHF, currentYield, data.twaHF, data.twaYield); + emit MetricsUpdated(lp, block.number, currentHF, 0, data.twaHF, 0); - // Check if rebalancing is needed using stored threshold values - if (compositeScore < data.rebalanceThreshold) { - emit RebalanceTriggered(lp, block.number, compositeScore, data.rebalanceThreshold, data.rebalanceDesired); + // Check if rebalancing is needed + if (normalizedHF < data.rebalanceThreshold) { + emit RebalanceTriggered(lp, block.number, normalizedHF, data.rebalanceThreshold); rebalance(lp, data.rebalanceDesired); } } @@ -339,6 +340,7 @@ contract JITpilot { blockData.currentLTV = 0; // If there is no debt, there is no looping or leverage, so interest is just supplyAPY blockData.netInterest = int256(supplyApyTotal); + blockData.controllerVault = address(0); } else { console.log("has controller vault: ", controllerVault); // Figure out which vault is the collateralVault @@ -369,6 +371,7 @@ contract JITpilot { / uint256(blockData.depositValue) ) * 1e9; } + blockData.controllerVault = controllerVault; } blockData.depositValue = int256(collateralValueTotal) - int256(debtValue); @@ -423,10 +426,10 @@ contract JITpilot { address asset1; uint256 reserve0; uint256 reserve1; - uint256 inLimit01; - uint256 outLimit01; - uint256 inLimit10; - uint256 outLimit10; + // uint256 inLimit01; + // uint256 outLimit01; + // uint256 inLimit10; + // uint256 outLimit10; uint16 borrowLTV01; uint16 borrowLTV10; } @@ -443,8 +446,8 @@ contract JITpilot { (address asset0, address asset1) = pool.getAssets(); output.asset0 = asset0; output.asset1 = asset1; - (output.inLimit01, output.outLimit01) = pool.getLimits(asset0, asset1); - (output.inLimit10, output.outLimit10) = pool.getLimits(asset1, asset0); + // (output.inLimit01, output.outLimit01) = pool.getLimits(asset0, asset1); + // (output.inLimit10, output.outLimit10) = pool.getLimits(asset1, asset0); // fetch borrow LTVs. These will be used to calculate reserves for rebalancing output.borrowLTV01 = IEVault(output.params.vault0).LTVBorrow(output.params.vault1); output.borrowLTV10 = IEVault(output.params.vault1).LTVBorrow(output.params.vault0); @@ -458,7 +461,35 @@ contract JITpilot { function rebalance(address lp, uint256 targetScore) internal { // Placeholder implementation - this will perform actual rebalancing // Will be implemented in later iterations - // The rebalancing logic will adjust positions to achieve targetScore + // This function is only called after confirming that a rebalance is needed + + // #1 Fetch current EulerSwap data + EulerSwapData memory eulerSwapData = getEulerSwapData(lp); + + // #2 Calculate new EulerSwap params + bool asset0IsDebt = lpData[lp].blockData.controllerVault == eulerSwapData.params.vault0; + IEulerSwap.Params memory newParams = calculateRebalancingParams(lp, eulerSwapData, asset0IsDebt); + + // #5 Uninstall current EulerSwap through EVC batch + // IEVC(EVC).BatchItem( + // IEulerSwapFactory(EulerSwapFactory).uninstallPool(); + + // ); + + // Deploy pool via EVC batch + // IEVC.BatchItem[] memory items = new IEVC.BatchItem[](2); + // items[0] = IEVC.BatchItem({ + // onBehalfOfAccount: address(0), + // targetContract: address(evc), + // value: 0, + // data: abi.encodeCall(evc.setAccountOperator, (user0, hookAddress, true)) + // }); + // items[1] = IEVC.BatchItem({ + // onBehalfOfAccount: user0, + // targetContract: address(eulerSwapFactory), + // value: 0, + // data: abi.encodeCall(IEulerSwapFactory.deployPool, (poolParams, initialState, salt)) + // }); } /** @@ -523,6 +554,8 @@ contract JITpilot { data.hfMin, data.hfDesired, data.yieldTarget, + data.rebalanceThreshold, + data.rebalanceDesired, data.lastUpdateBlock, data.initialized ); @@ -600,35 +633,49 @@ contract JITpilot { return currentControllerVault; } - function getCollateralValue(address account, address collateral) internal view virtual returns (uint256 value) { - IEVault collateralVault = IEVault(collateral); - uint256 balance = IERC20(collateral).balanceOf(account); - if (balance == 0) return 0; + // function getCollateralValue(address account, address vaultAddress) internal view virtual returns (uint256 value) { + // IEVault collateralVault = IEVault(vaultAddress); + // uint256 balance = IERC20(vaultAddress).balanceOf(account); + // if (balance == 0) return 0; - uint256 currentCollateralValue; + // uint256 currentCollateralValue; - // mid-point price - currentCollateralValue = - IPriceOracle(collateralVault.oracle()).getQuote(balance, collateral, collateralVault.unitOfAccount()); + // // mid-point price + // currentCollateralValue = + // IPriceOracle(collateralVault.oracle()).getQuote(balance, vaultAddress, collateralVault.unitOfAccount()); - return currentCollateralValue; - } + // return currentCollateralValue; + // } - function getDebtValue(address account, address vault) internal view virtual returns (uint256 value) { - IEVault controllerVault = IEVault(vault); - uint256 debt = controllerVault.debtOf(account); - if (debt == 0) return 0; + // function getDebtValue(address account, address vault) internal view virtual returns (uint256 value) { + // IEVault controllerVault = IEVault(vault); + // uint256 debt = controllerVault.debtOf(account); + // if (debt == 0) return 0; - uint256 currentDebtValue; + // uint256 currentDebtValue; - // mid-point price - currentDebtValue = IPriceOracle(controllerVault.oracle()).getQuote(debt, vault, controllerVault.unitOfAccount()); + // // mid-point price + // currentDebtValue = IPriceOracle(controllerVault.oracle()).getQuote(debt, vault, controllerVault.unitOfAccount()); - return currentDebtValue; - } + // return currentDebtValue; + // } - function getData(address lp) external view returns (BlockData memory) { - return fetchData(lp); + function getPositionValue(address account, address vaultAddress, bool isControllerVault) + internal + view + virtual + returns (uint256 value) + { + IEVault vault = IEVault(vaultAddress); + uint256 balance = isControllerVault ? vault.debtOf(account) : IERC20(vaultAddress).balanceOf(account); + if (balance == 0) return 0; + + uint256 currentPositionValue; + + // mid-point price + currentPositionValue = IPriceOracle(vault.oracle()).getQuote(balance, vaultAddress, vault.unitOfAccount()); + + return currentPositionValue; } /** @@ -647,8 +694,9 @@ contract JITpilot { IEulerSwap.Params memory eulerSwapParams = IEulerSwap(poolAddr).getParams(); collateralValueTotal = - getCollateralValue(lp, eulerSwapParams.vault0) + getCollateralValue(lp, eulerSwapParams.vault1); - debtValue = getDebtValue(lp, eulerSwapParams.vault0) + getDebtValue(lp, eulerSwapParams.vault1); + getPositionValue(lp, eulerSwapParams.vault0, false) + getPositionValue(lp, eulerSwapParams.vault1, false); + debtValue = + getPositionValue(lp, eulerSwapParams.vault0, true) + getPositionValue(lp, eulerSwapParams.vault1, true); return (collateralValueTotal, debtValue); } @@ -672,7 +720,7 @@ contract JITpilot { uint256 collateralValueTotal; for (uint256 i; i < collateralVaultsGlobal.length; ++i) { uint256 supplyApy = uint256((collateralVaultsGlobal[i].packed2 << (256 - 96)) >> (256 - 48)); - uint256 collateralValue = getCollateralValue(lp, collateralVaults[i]); + uint256 collateralValue = getPositionValue(lp, collateralVaults[i], false); supplyApyTotal += supplyApy * collateralValue; collateralValueTotal += collateralValue; console.log("Supply APY for vault", collateralVaults[i], "is", supplyApy); @@ -683,4 +731,92 @@ contract JITpilot { return supplyApyTotal; } + + function calculateRebalancingParams(address lp, EulerSwapData memory eulerSwapData, bool asset0IsDebt) + internal + view + returns (IEulerSwap.Params memory) + { + // Calculate delta reserves. This is the amount of trading we want to service, to repay the debt. + uint256 deltaReservesValueUsd = calculateDeltaReserves(lp, eulerSwapData); + uint256 asset0Scale = FixedPointMathLib.rpow(10e18, IERC20(IEVault(eulerSwapData.params.vault0).asset()).decimals(), 1e18) / 1e18; + uint256 asset1Scale = FixedPointMathLib.rpow(10e18, IERC20(IEVault(eulerSwapData.params.vault1).asset()).decimals(), 1e18) / 1e18; + uint256 asset0PriceUsd = IPriceOracle(IEVault(eulerSwapData.params.vault0).oracle()).getQuote( + asset0Scale, IEVault(eulerSwapData.params.vault0).asset(), IEVault(eulerSwapData.params.vault0).unitOfAccount() + ); + uint256 asset1PriceUsd = IPriceOracle(IEVault(eulerSwapData.params.vault1).oracle()).getQuote( + asset1Scale, IEVault(eulerSwapData.params.vault1).asset(), IEVault(eulerSwapData.params.vault1).unitOfAccount() + ); + + // Calculate balancedEquilibriumReserves given current depositValue + // Both equilibriumReserves are maxed at the point in the curve where vaults are balanced. + uint256 desiredEqRsvCollateralAsset; + uint256 desiredEqRsvDebtAsset; + (uint256 collateralValueTotal, uint256 debtValue) = getDepositValue(lp); + uint256 depositValue = collateralValueTotal - debtValue; + { + if (asset0IsDebt) { + uint256 balEqRsv1 = depositValue * 1e4 / (1e4 - eulerSwapData.borrowLTV01) * asset1Scale / asset1PriceUsd; + desiredEqRsvCollateralAsset = balEqRsv1 + + debtValue * asset1Scale / asset1PriceUsd + - deltaReservesValueUsd * asset1Scale / asset1PriceUsd - depositValue * asset1Scale / 2 / asset1PriceUsd; + // we've chosen an arbitrary amount of 3x deltaReserves and a 99% concentration to prevent over-borrowing and allow for arbitrage + desiredEqRsvDebtAsset = deltaReservesValueUsd * 3 * asset0Scale / asset0PriceUsd; + } else { + uint256 balEqRsv0 = depositValue * 1e4 / (1e4 - eulerSwapData.borrowLTV01) * asset0Scale / asset0PriceUsd; + desiredEqRsvCollateralAsset = balEqRsv0 + + debtValue * asset0Scale / asset0PriceUsd + - deltaReservesValueUsd * asset0Scale / asset0PriceUsd - depositValue * asset0Scale / 2 / asset0PriceUsd; + // we've chosen an arbitrary amount of 3x deltaReserves and a 99% concentration to prevent over-borrowing and allow for arbitrage + desiredEqRsvDebtAsset = deltaReservesValueUsd * 3 * asset1Scale / asset1PriceUsd; + } + } + uint256 concentrationDebtAsset = 99 * 1e16; + + return IEulerSwap.Params({ + vault0: eulerSwapData.params.vault0, + vault1: eulerSwapData.params.vault1, + eulerAccount: eulerSwapData.params.eulerAccount, + equilibriumReserve0: uint112(asset0IsDebt ? desiredEqRsvDebtAsset : desiredEqRsvCollateralAsset), + equilibriumReserve1: uint112(asset0IsDebt ? desiredEqRsvCollateralAsset : desiredEqRsvDebtAsset), + priceX: 1 * asset1Scale, + priceY: asset1PriceUsd * 1e18 / asset0PriceUsd * asset0Scale / asset1Scale * 99/100, + concentrationX: asset0IsDebt ? concentrationDebtAsset : eulerSwapData.params.concentrationX, + concentrationY: asset0IsDebt ? eulerSwapData.params.concentrationY : concentrationDebtAsset, + fee: eulerSwapData.params.fee, + protocolFee: eulerSwapData.params.protocolFee, + protocolFeeRecipient: eulerSwapData.params.protocolFeeRecipient + }); + } + + function calculateDeltaReserves(address lp, EulerSwapData memory eulerSwapData) internal view returns (uint256) { + // $\Delta L = \frac{\frac{HF'}{LLTV} \cdot L - C}{\frac{HF'}{LLTV} - 1}$ + uint256 hfPrime = lpData[lp].hfDesired; + address controllerVault = getCurrentControllerVault(lp); + address collateralVault = + controllerVault == eulerSwapData.params.vault0 ? eulerSwapData.params.vault1 : eulerSwapData.params.vault0; + uint256 lltv = uint256(IEVault(controllerVault).LTVLiquidation(collateralVault)) * 1e18 / 1e4; + + uint256 collateralValue = getPositionValue(lp, collateralVault, false); + uint256 liabilityValue = getPositionValue(lp, controllerVault, true); + + return ((hfPrime * liabilityValue / lltv) - collateralValue) / (hfPrime * 1e18 / lltv - 1e18) * 1e18; + } + + // EXTERNAL HELPER FUNCTIONS FOR TESTING + + function getData(address lp) external view returns (BlockData memory) { + return fetchData(lp); + } + + function getRebalancingParams(address lp) external view returns (IEulerSwap.Params memory) { + // #1 Fetch current EulerSwap data + address poolAddr = IEulerSwapFactory(EulerSwapFactory).poolByEulerAccount(lp); + EulerSwapData memory eulerSwapData = getEulerSwapData(poolAddr); + + // #2 Calculate new EulerSwap params + bool asset0IsDebt = getCurrentControllerVault(lp) == eulerSwapData.params.vault0; + + return calculateRebalancingParams(lp, eulerSwapData, asset0IsDebt); + } } From 67736d3c5fc1046252b7f2e931ea6d13d374c17f Mon Sep 17 00:00:00 2001 From: MazyGio Date: Sun, 6 Jul 2025 22:54:32 -0500 Subject: [PATCH 2/5] feat: add rebalancing calcs, and arbitrage steps to the example script --- script/scenarios/EulerSwapDebtScenario.s.sol | 196 ++++++++++++---- src/JITpilot.sol | 234 +++++++++++++------ 2 files changed, 313 insertions(+), 117 deletions(-) diff --git a/script/scenarios/EulerSwapDebtScenario.s.sol b/script/scenarios/EulerSwapDebtScenario.s.sol index 2424af1..846c724 100644 --- a/script/scenarios/EulerSwapDebtScenario.s.sol +++ b/script/scenarios/EulerSwapDebtScenario.s.sol @@ -9,6 +9,9 @@ import {Hooks} from "v4-core/libraries/Hooks.sol"; import {MetaProxyDeployer} from "euler-swap/utils/MetaProxyDeployer.sol"; import {TestERC20} from "evk-test/unit/evault/EVaultTestBase.t.sol"; import {IEVault} from "evk/EVault/IEVault.sol"; +import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; +import {IEulerSwapFactory} from "euler-swap/interfaces/IEulerSwapFactory.sol"; +import {CurveLib} from "euler-swap/libraries/CurveLib.sol"; import {console2 as console} from "forge-std/console2.sol"; @@ -20,11 +23,15 @@ contract EulerSwapDebtScenario is DeployScenario { vm.startBroadcast(user3PK); eUSDC.setLTV(address(eWETH), 0.65e4, 0.67e4, 0); eUSDC.setLTV(address(eUSDT), 0.85e4, 0.87e4, 0); + eWETH.setLTV(address(eUSDC), 0.65e4, 0.67e4, 0); + eWETH.setLTV(address(eUSDT), 0.85e4, 0.87e4, 0); + eUSDT.setLTV(address(eWETH), 0.85e4, 0.87e4, 0); + eUSDT.setLTV(address(eUSDC), 0.85e4, 0.87e4, 0); deployJITpilot(); vm.stopBroadcast(); vm.startBroadcast(user2PK); - createEulerSwap(); + deployEulerSwap(getInitialEulerSwapParams(), false); authorizeJITpilot(user2); jitPilot.configureLp(user2, 1.4e18, 1.5e18); vm.stopBroadcast(); @@ -40,26 +47,14 @@ contract EulerSwapDebtScenario is DeployScenario { borrowFromVault(user0, user0PK, address(eWETH), 500_000e18); borrowFromVault(user1, user1PK, address(eUSDC), 1_600_000_000e6); - console.log("user2 vault deposits: ", eWETH.balanceOf(user2)); - console.log("user2 vault deposits: ", eUSDC.balanceOf(user2)); - // buy USDC so that user2's EulerSwap position has to borrow USDC uint256 amountOut = 286_500_000e6; uint256 amountIn = _swapExactOut(address(assetWETH), address(assetUSDC), amountOut, user0, user0PK); - console.log("SOLD %s WETH FOR %s USDC", amountIn, amountOut); + console.log("marketUser SOLD %s WETH FOR %s USDC", amountIn, amountOut); // user2 is in debt now. Let's fetch that data - JITpilot.BlockData memory blockData = jitPilot.getData(user2); - - console.log("=========================================================="); - console.log("EulerSwap instance is in debt now:"); - console.log("allowedLTV: ", blockData.allowedLTV); - console.log("currentLTV: ", blockData.currentLTV); - console.log("swapFees: ", blockData.swapFees); - console.log("netInterest: ", blockData.netInterest); - console.log("depositValue: ", blockData.depositValue); - console.log("controllerVault: ", blockData.controllerVault); - console.log("=========================================================="); + console.log("EulerSwap state now after servicing trades: "); + printEulerSwapData(user2); // Get a quote for the current price of ETH in the EulerSwap instance uint256 ethPrice = eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18); @@ -72,6 +67,33 @@ contract EulerSwapDebtScenario is DeployScenario { // Let's see what the rebalancing params would be IEulerSwap.Params memory newParams = jitPilot.getRebalancingParams(user2); printEulerSwapParams(newParams); + + // let's do the actual rebalancing then + vm.startBroadcast(user2PK); + jitPilot.updateMetrics(user2); + IEVC(evc).setAccountOperator(user2, eulerSwap, false); + IEulerSwapFactory(eulerSwapFactory).uninstallPool(); + deployEulerSwap(newParams, true); + vm.stopBroadcast(); + + // Now let's see if the rebalancing was successful + address poolAddr = eulerSwapFactory.poolByEulerAccount(user2); + newParams = IEulerSwap(poolAddr).getParams(); + printEulerSwapParams(newParams); + + // Let's buy some WETH on the EulerSwap pool and see the effect on the debt + // sell USDC so that user2's EulerSwap position has to borrow USDC + uint256 newEthPrice = eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18); + console.log("price of ETH (market): ", ethPrice); + console.log("price of ETH (EulerSwap): ", newEthPrice); + amountIn = 105_000_000e6; + amountOut = _swapExactIn(address(assetUSDC), address(assetWETH), amountIn, user0, user0PK); + console.log("marketUser BOUGHT %s WETH FOR %s USDC (price: %s)", amountOut, amountIn, amountIn * 1e18 / amountOut); + + // Let's see the new state of the EulerSwap pool after arbitrage + console.log("EulerSwap state now (after arbitrage):"); + printEulerSwapData(user2); + console.log("price of ETH (EulerSwap, after arbitrage): ", eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18)); } function giveTonsOfCash(address user) internal virtual { @@ -98,26 +120,39 @@ contract EulerSwapDebtScenario is DeployScenario { evc.setAccountOperator(user, address(jitPilot), true); } - function createEulerSwap() internal { - // Create pool parameters - IEulerSwap.Params memory poolParams = IEulerSwap.Params({ - vault0: address(eUSDC), - vault1: address(eWETH), - eulerAccount: user2, - equilibriumReserve0: 800_000_000e6, - equilibriumReserve1: 280_000e18, - priceX: 1e18, - priceY: 2865e6, - concentrationX: 0.9e18, - concentrationY: 0.9e18, - fee: 0, - protocolFee: 0, - protocolFeeRecipient: address(0) - }); + function deployEulerSwap(IEulerSwap.Params memory poolParams, bool rebalancing) internal { - console.log("INITIAL EULERSWAP PARAMS"); + console.log("DEPLOYING EULERSWAP WITH PARAMS"); printEulerSwapParams(poolParams); + bool asset0IsDebt = getCurrentControllerVault(poolParams.eulerAccount) == poolParams.vault0; + uint112 currentReserve0 = poolParams.equilibriumReserve0; + uint112 currentReserve1 = poolParams.equilibriumReserve1; + + IEulerSwap.InitialState memory initialState; + if (!rebalancing) { + initialState = IEulerSwap.InitialState({currReserve0: poolParams.equilibriumReserve0, currReserve1: poolParams.equilibriumReserve1}); + } else { + if (asset0IsDebt) { + { + uint256 deltaReservesAsset0 = poolParams.equilibriumReserve0 * 1/3; + // uint256 deltaReservesAsset1 = deltaReservesAsset0 * poolParams.priceX / poolParams.priceY; + currentReserve0 = uint112(poolParams.equilibriumReserve0 - deltaReservesAsset0); + // currentReserve1 = uint112(poolParams.equilibriumReserve1 + deltaReservesAsset1); + currentReserve1 = uint112(CurveLib.f(uint256(currentReserve0), uint256(poolParams.priceX), uint256(poolParams.priceY), uint256(poolParams.equilibriumReserve0), uint256(poolParams.equilibriumReserve1), uint256(poolParams.concentrationX))); + } + } else { + { + uint256 deltaReservesAsset1 = poolParams.equilibriumReserve1 * 1/3; + // uint256 deltaReservesAsset0 = deltaReservesAsset1 * poolParams.priceY / poolParams.priceX; + currentReserve1 = uint112(poolParams.equilibriumReserve1 - deltaReservesAsset1); + // currentReserve0 = uint112(poolParams.equilibriumReserve0 + deltaReservesAsset0); + currentReserve0 = uint112(CurveLib.fInverse(uint256(currentReserve1), uint256(poolParams.priceY), uint256(poolParams.priceX), uint256(poolParams.equilibriumReserve1), uint256(poolParams.equilibriumReserve0), uint256(poolParams.concentrationY))); + } + } + initialState = IEulerSwap.InitialState({currReserve0: currentReserve0, currReserve1: currentReserve1}); + } + // Define required hook flags uint160 flags = uint160( Hooks.BEFORE_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG @@ -129,11 +164,21 @@ contract EulerSwapDebtScenario is DeployScenario { (address hookAddress, bytes32 salt) = HookMiner.find(address(eulerSwapFactory), flags, creationCode); eulerSwap = hookAddress; - evc.setAccountOperator(user2, eulerSwap, true); - - eulerSwapFactory.deployPool( - poolParams, IEulerSwap.InitialState({currReserve0: 800_000_000e6, currReserve1: 280_000e18}), salt - ); + // Deploy pool via EVC batch + IEVC.BatchItem[] memory items = new IEVC.BatchItem[](2); + items[0] = IEVC.BatchItem({ + onBehalfOfAccount: address(0), + targetContract: address(evc), + value: 0, + data: abi.encodeCall(evc.setAccountOperator, (user2, eulerSwap, true)) + }); + items[1] = IEVC.BatchItem({ + onBehalfOfAccount: user2, + targetContract: address(eulerSwapFactory), + value: 0, + data: abi.encodeCall(IEulerSwapFactory.deployPool, (poolParams, initialState, salt)) + }); + evc.batch(items); string memory result = vm.serializeAddress("eulerSwap", "eulerSwap", address(eulerSwap)); vm.writeJson(result, "./dev-ctx/addresses/31337/EulerSwapAddresses.json"); @@ -172,7 +217,7 @@ contract EulerSwapDebtScenario is DeployScenario { { vm.startBroadcast(userPK); amountIn = eulerSwapPeriphery.quoteExactOutput(eulerSwap, tokenIn, tokenOut, amountOut); - console.log("amountIn", amountIn); + // console.log("amountIn", amountIn); TestERC20(tokenIn).approve(address(eulerSwapPeriphery), type(uint256).max); eulerSwapPeriphery.swapExactOut( @@ -189,7 +234,47 @@ contract EulerSwapDebtScenario is DeployScenario { return amountIn; } - function printEulerSwapParams(IEulerSwap.Params memory params) internal { + function _swapExactIn(address tokenIn, address tokenOut, uint256 amountIn, address receiver, uint256 userPK) + internal + returns (uint256 amountOut) + { + vm.startBroadcast(userPK); + amountOut = eulerSwapPeriphery.quoteExactInput(eulerSwap, tokenIn, tokenOut, amountIn); + // console.log("amountOut", amountOut); + + TestERC20(tokenIn).approve(address(eulerSwapPeriphery), type(uint256).max); + eulerSwapPeriphery.swapExactIn( + eulerSwap, + tokenIn, + tokenOut, + amountIn, + receiver, + amountOut * 99 / 100, // allow up to 1% slippage + 0 + ); + vm.stopBroadcast(); + + return amountOut; + } + + function getInitialEulerSwapParams() internal view returns (IEulerSwap.Params memory) { + return IEulerSwap.Params({ + vault0: address(eUSDC), + vault1: address(eWETH), + eulerAccount: user2, + equilibriumReserve0: 800_000_000e6, + equilibriumReserve1: 280_000e18, + priceX: 1e18, + priceY: 2865e6, + concentrationX: 0.9e18, + concentrationY: 0.9e18, + fee: 0, + protocolFee: 0, + protocolFeeRecipient: address(0) + }); + } + + function printEulerSwapParams(IEulerSwap.Params memory params) internal pure { console.log("=========================================================="); console.log("vault0: ", params.vault0); console.log("vault1: ", params.vault1); @@ -205,4 +290,35 @@ contract EulerSwapDebtScenario is DeployScenario { console.log("protocolFeeRecipient: ", params.protocolFeeRecipient); console.log("=========================================================="); } + + function printEulerSwapData(address user) internal view { + + JITpilot.BlockData memory blockData = jitPilot.getData(user); + + console.log("=========================================================="); + console.log("healthFactor: ", blockData.allowedLTV * 1e4 / blockData.currentLTV / 100, "%"); + console.log("allowedLTV: ", blockData.allowedLTV); + console.log("currentLTV: ", blockData.currentLTV); + console.log("swapFees: ", blockData.swapFees); + console.log("netInterest: ", blockData.netInterest); + console.log("depositValue: ", blockData.depositValue); + console.log("controllerVault: ", blockData.controllerVault); + console.log("=========================================================="); + } + + function getCurrentControllerVault(address lp) internal view returns (address) { + address[] memory controllerVaults = evc.getControllers(lp); + address currentControllerVault; + + if (controllerVaults.length == 0) return address(0); + + // find which of the LP's controller vaults is the enabled debt vault + for (uint256 i; i < controllerVaults.length; ++i) { + if (evc.isControllerEnabled(lp, controllerVaults[i])) { + currentControllerVault = controllerVaults[i]; + break; + } + } + return currentControllerVault; + } } diff --git a/src/JITpilot.sol b/src/JITpilot.sol index 896dcf8..fbda783 100644 --- a/src/JITpilot.sol +++ b/src/JITpilot.sol @@ -9,6 +9,9 @@ import {IMaglevLens} from "src/interfaces/IMaglevLens.sol"; import {IPriceOracle} from "evk/interfaces/IPriceOracle.sol"; import {console2 as console} from "forge-std/console2.sol"; import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; +import {MetaProxyDeployer} from "euler-swap/utils/MetaProxyDeployer.sol"; +import {HookMiner} from "../libflat/euler-swap/test/utils/HookMiner.sol"; +import {Hooks} from "v4-core/libraries/Hooks.sol"; import {CurveLib} from "euler-swap/libraries/CurveLib.sol"; @@ -24,16 +27,21 @@ contract JITpilot { // Constants uint256 private constant WINDOW_SIZE = 100; uint256 private constant PRECISION = 1e18; + enum RebalancingStatus { + NOT_REBALANCING, + REBALANCING + } // Configurable parameters uint256 public weightHF = 6e17; // 0.6 weight for Health Factor uint256 public weightYield = 4e17; // 0.4 weight for Yield // Euler contract addresses - address public EVC; - address public EVK; - address public MaglevLens; - address public EulerSwapFactory; + address public evcAddress; + address public evkAddress; + address public maglevLensAddress; + address public eulerSwapFactoryAddress; + address public eulerSwapImplAddress; // Data structure to store block-level data from fetchData struct BlockData { @@ -66,6 +74,7 @@ contract JITpilot { EulerSwapData eulerSwapData; // Latest EulerSwap parameters BlockData blockData; // Latest EulerSwap state data bool initialized; // Whether LP data is initialized + RebalancingStatus rebalancingStatus; // Whether LP is currently rebalancing } // Mappings @@ -105,19 +114,23 @@ contract JITpilot { // Setters for contract addresses function setEVC(address _EVC) external onlyOwner { - EVC = _EVC; + evcAddress = _EVC; } function setEVK(address _EVK) external onlyOwner { - EVK = _EVK; + evkAddress = _EVK; } function setMaglevLens(address _MaglevLens) external onlyOwner { - MaglevLens = _MaglevLens; + maglevLensAddress = _MaglevLens; } function setEulerSwapFactory(address _EulerSwapFactory) external onlyOwner { - EulerSwapFactory = _EulerSwapFactory; + eulerSwapFactoryAddress = _EulerSwapFactory; + } + + function setEulerSwapImpl(address _EulerSwapImpl) external onlyOwner { + eulerSwapImplAddress = _EulerSwapImpl; } /** @@ -136,6 +149,9 @@ contract JITpilot { // data.yieldTarget = _yieldTarget; data.initialized = true; data.startBlock = block.number; + data.rebalanceThreshold = _hfDesired; + data.rebalanceDesired = _hfDesired; + emit LPConfigured(lp, _hfMin, _hfDesired); } @@ -149,6 +165,10 @@ contract JITpilot { LPData storage data = lpData[lp]; + // update EulerSwap pool data + address poolAddr = IEulerSwapFactory(eulerSwapFactoryAddress).poolByEulerAccount(lp); + data.eulerSwapData = getEulerSwapData(poolAddr); + // Fetch current block data BlockData memory currentData = fetchData(lp); @@ -158,23 +178,8 @@ contract JITpilot { currentHF = (currentData.allowedLTV * PRECISION) / currentData.currentLTV; } - // Calculate current Yield - // uint256 currentYield = 0; - // uint256 swapApy = uint256(int256(currentData.swapFees) * 1e18 / currentData.depositValue); - // if (currentData.depositValue > 0) { - // if (currentData.netInterest >= 0) { - // currentYield = (uint256(currentData.netInterest) * PRECISION) + swapApy; - // } else if (swapApy >= uint256(currentData.netInterest)) { - // // netInterest is negative, but swapApy is greater, so yield is positive. - // currentYield = swapApy - uint256(currentData.netInterest); - // } else { - // // Yield is negative. Set to 0 for simplicity. - // currentYield = 0; - // } - // } - // Update sliding window for Health Factor - _updateSlidingWindow(data.hfHistory, currentHF); + // _updateSlidingWindow(data.hfHistory, currentHF); // Update sliding window for Yield // _updateSlidingWindow(data.yieldHistory, currentYield); @@ -186,7 +191,7 @@ contract JITpilot { data.twaYield = _calculateTWA(data.yieldHistory, data.startBlock); // Calculate normalized values - uint256 normalizedHF = _normalizeHealthFactor(data.twaHF, data.hfMin, data.hfDesired); + // uint256 normalizedHF = _normalizeHealthFactor(data.twaHF, data.hfMin, data.hfDesired); // uint256 normalizedYield = _normalizeYield(data.twaYield, data.yieldTarget); // Calculate composite score @@ -198,11 +203,21 @@ contract JITpilot { // Emit metrics updated event // emit MetricsUpdated(lp, block.number, currentHF, currentYield, data.twaHF, data.twaYield); emit MetricsUpdated(lp, block.number, currentHF, 0, data.twaHF, 0); - - // Check if rebalancing is needed - if (normalizedHF < data.rebalanceThreshold) { - emit RebalanceTriggered(lp, block.number, normalizedHF, data.rebalanceThreshold); - rebalance(lp, data.rebalanceDesired); + if (data.rebalancingStatus == RebalancingStatus.NOT_REBALANCING) { + + // Check if rebalancing is needed + console.log("Checking if rebalancing is needed."); + if (currentHF < data.rebalanceThreshold && data.rebalancingStatus != RebalancingStatus.REBALANCING) { + emit RebalanceTriggered(lp, block.number, currentHF, data.rebalanceThreshold); + _rebalance(lp); + data.rebalancingStatus = RebalancingStatus.REBALANCING; + } + } else { + // LP is in the middle of rebalancing + if (currentHF >= data.rebalanceThreshold) { + _afterRebalanceFinished(lp); + data.rebalancingStatus = RebalancingStatus.NOT_REBALANCING; + } } } @@ -287,7 +302,7 @@ contract JITpilot { // Placeholder implementation - to be researched and implemented // Should calculate threshold based on hfMin as main parameter // with thresholdSafetyMargin for fine-tuning - return 5e17; // Default 0.5 for now + return data.hfDesired; // Default hfDesired for now } /** @@ -314,10 +329,8 @@ contract JITpilot { // Placeholder implementation - this will fetch real data from Euler contracts // For now, return dummy data to avoid compilation errors - // get LP's eulerSwap pool address - address poolAddr = IEulerSwapFactory(EulerSwapFactory).poolByEulerAccount(lp); - - // get eulerSwap pool data + // update EulerSwap pool data + address poolAddr = IEulerSwapFactory(eulerSwapFactoryAddress).poolByEulerAccount(lp); EulerSwapData memory eulerSwapData = getEulerSwapData(poolAddr); BlockData memory blockData; @@ -326,7 +339,7 @@ contract JITpilot { uint256 supplyApyTotal = 0; uint256 borrowApyTotal = 0; - (uint256 collateralValueTotal, uint256 debtValue) = getDepositValue(lp); + (uint256 collateralValueTotal, uint256 debtValue) = _getDepositValue(lp); blockData.depositValue = int256(collateralValueTotal) - int256(debtValue); supplyApyTotal = getSupplyApy(lp); @@ -335,19 +348,23 @@ contract JITpilot { // If there is no controller, there is no debt, and no liquidation metrics to calculate if (controllerVault == address(0)) { - console.log("doesn't have controller vault: ", controllerVault); + // console.log("doesn't have controller vault: ", controllerVault); blockData.allowedLTV = 0; blockData.currentLTV = 0; // If there is no debt, there is no looping or leverage, so interest is just supplyAPY blockData.netInterest = int256(supplyApyTotal); blockData.controllerVault = address(0); } else { - console.log("has controller vault: ", controllerVault); + // console.log("has controller vault: ", controllerVault); // Figure out which vault is the collateralVault address collateralVault = (controllerVault == eulerSwapData.params.vault0) ? eulerSwapData.params.vault1 : eulerSwapData.params.vault0; - console.log("debtValue: ", debtValue); + // console.log("debtValue: ", debtValue); + // console.log("collateralVault: ", collateralVault); + // console.log("controllerVault: ", controllerVault); + // console.log("LLTV: ", uint256(IEVault(controllerVault).LTVLiquidation(collateralVault))); + // console.log("LLTV other: ", uint256(IEVault(collateralVault).LTVLiquidation(controllerVault))); blockData.allowedLTV = uint256(IEVault(controllerVault).LTVLiquidation(collateralVault)) * 1e18 / 1e4; blockData.currentLTV = debtValue * 1e18 / collateralValueTotal; console.log("currentLTV: ", blockData.currentLTV); @@ -355,7 +372,7 @@ contract JITpilot { address[] memory controllerVaultArray = new address[](1); controllerVaultArray[0] = controllerVault; IMaglevLens.VaultGlobal[] memory controllerVaultsGlobal = - IMaglevLens(MaglevLens).vaultsGlobal(controllerVaultArray); + IMaglevLens(maglevLensAddress).vaultsGlobal(controllerVaultArray); // borrow APY is on the last 48 bits. Shift left then right to extract it. uint256 borrowApy = uint256((controllerVaultsGlobal[0].packed2 << (256 - 48)) >> (256 - 48)); borrowApyTotal = borrowApy; @@ -452,45 +469,71 @@ contract JITpilot { output.borrowLTV01 = IEVault(output.params.vault0).LTVBorrow(output.params.vault1); output.borrowLTV10 = IEVault(output.params.vault1).LTVBorrow(output.params.vault0); } + /** * @dev Rebalance LP position (placeholder - to be implemented later) * @param lp LP address to rebalance - * @param targetScore Target composite score to achieve after rebalancing */ - - function rebalance(address lp, uint256 targetScore) internal { + function _rebalance(address lp) internal view { // Placeholder implementation - this will perform actual rebalancing // Will be implemented in later iterations // This function is only called after confirming that a rebalance is needed // #1 Fetch current EulerSwap data - EulerSwapData memory eulerSwapData = getEulerSwapData(lp); + address poolAddr = IEulerSwapFactory(eulerSwapFactoryAddress).poolByEulerAccount(lp); + EulerSwapData memory eulerSwapData = getEulerSwapData(poolAddr); // #2 Calculate new EulerSwap params - bool asset0IsDebt = lpData[lp].blockData.controllerVault == eulerSwapData.params.vault0; + bool asset0IsDebt = getCurrentControllerVault(lp) == eulerSwapData.params.vault0; IEulerSwap.Params memory newParams = calculateRebalancingParams(lp, eulerSwapData, asset0IsDebt); - // #5 Uninstall current EulerSwap through EVC batch - // IEVC(EVC).BatchItem( - // IEulerSwapFactory(EulerSwapFactory).uninstallPool(); - + // IEulerSwap.InitialState memory initialState = IEulerSwap.InitialState({ + // currReserve0: newParams.equilibriumReserve0, + // currReserve1: newParams.equilibriumReserve1 + // }); + // #3 Uninstall current EulerSwap via EVC batch + // IEVC(evcAddress).call( + // address(evcAddress), + // lp, + // 0, + // abi.encodeCall(IEVC(evcAddress).setAccountOperator, (lp, poolAddr, false)) // ); - - // Deploy pool via EVC batch - // IEVC.BatchItem[] memory items = new IEVC.BatchItem[](2); - // items[0] = IEVC.BatchItem({ + // IEVC(evcAddress).call( + // address(eulerSwapFactoryAddress), + // lp, + // 0, + // abi.encodeCall(IEulerSwapFactory.uninstallPool, ()) + // ); + // IEVC(evcAddress).setAccountOperator(lp, poolAddr, false); + // IEulerSwapFactory(eulerSwapFactoryAddress).uninstallPool(); + + // #4 Reinstall EulerSwap through EVC + // #4.1 Mine salt + // (address hookAddress, bytes32 salt) = mineSalt(newParams); + // #4.2 Deploy pool via EVC batch + // IEVC.BatchItem[] memory items3 = new IEVC.BatchItem[](2); + // items3[0] = IEVC.BatchItem({ // onBehalfOfAccount: address(0), - // targetContract: address(evc), + // targetContract: address(evcAddress), // value: 0, - // data: abi.encodeCall(evc.setAccountOperator, (user0, hookAddress, true)) + // data: abi.encodeCall(IEVC(evcAddress).setAccountOperator, (lp, hookAddress, true)) // }); - // items[1] = IEVC.BatchItem({ - // onBehalfOfAccount: user0, - // targetContract: address(eulerSwapFactory), + // items3[1] = IEVC.BatchItem({ + // onBehalfOfAccount: lp, + // targetContract: address(eulerSwapFactoryAddress), // value: 0, - // data: abi.encodeCall(IEulerSwapFactory.deployPool, (poolParams, initialState, salt)) + // data: abi.encodeCall(IEulerSwapFactory.deployPool, (newParams, initialState, salt)) // }); + // IEVC(evcAddress).batch(items3); + + // console.log("reinstalled EulerSwap."); + } + + function _afterRebalanceFinished(address lp) internal { + // reinstall EulerSwap with original params but updated price + } + /** * @dev Add authorized caller @@ -530,7 +573,10 @@ contract JITpilot { * @return rebalanceThreshold Threshold below which rebalancing is triggered * @return rebalanceDesired Target score to achieve after rebalancing * @return lastUpdateBlock Last block when metrics were updated + * @return eulerSwapData Latest EulerSwap parameters + * @return blockData Latest EulerSwap state data * @return initialized Whether LP data is initialized + * @return rebalancingStatus Whether LP is currently rebalancing */ function getLPData(address lp) external @@ -544,7 +590,10 @@ contract JITpilot { uint256 rebalanceThreshold, uint256 rebalanceDesired, uint256 lastUpdateBlock, - bool initialized + EulerSwapData memory eulerSwapData, // Latest EulerSwap parameters + BlockData memory blockData, // Latest EulerSwap state data + bool initialized, // Whether LP data is initialized + RebalancingStatus rebalancingStatus // Whether LP is currently rebalancing ) { LPData storage data = lpData[lp]; @@ -557,7 +606,10 @@ contract JITpilot { data.rebalanceThreshold, data.rebalanceDesired, data.lastUpdateBlock, - data.initialized + data.eulerSwapData, + data.blockData, + data.initialized, + data.rebalancingStatus ); } @@ -618,14 +670,14 @@ contract JITpilot { // HELPER FUNCTIONS function getCurrentControllerVault(address lp) internal view returns (address) { - address[] memory controllerVaults = IEVC(EVC).getControllers(lp); + address[] memory controllerVaults = IEVC(evcAddress).getControllers(lp); address currentControllerVault; if (controllerVaults.length == 0) return address(0); // find which of the LP's controller vaults is the enabled debt vault for (uint256 i; i < controllerVaults.length; ++i) { - if (IEVC(EVC).isControllerEnabled(lp, controllerVaults[i])) { + if (IEVC(evcAddress).isControllerEnabled(lp, controllerVaults[i])) { currentControllerVault = controllerVaults[i]; break; } @@ -684,13 +736,13 @@ contract JITpilot { * @return collateralValueTotal Collateral value of the LP * @return debtValue Debt value of the LP */ - function getDepositValue(address lp) + function _getDepositValue(address lp) internal view virtual returns (uint256 collateralValueTotal, uint256 debtValue) { - address poolAddr = IEulerSwapFactory(EulerSwapFactory).poolByEulerAccount(lp); + address poolAddr = IEulerSwapFactory(eulerSwapFactoryAddress).poolByEulerAccount(lp); IEulerSwap.Params memory eulerSwapParams = IEulerSwap(poolAddr).getParams(); collateralValueTotal = @@ -707,11 +759,11 @@ contract JITpilot { * @return supplyApyTotal Supply APY of the LP, weighted by collateral value */ function getSupplyApy(address lp) internal view virtual returns (uint256 supplyApyTotal) { - address poolAddr = IEulerSwapFactory(EulerSwapFactory).poolByEulerAccount(lp); + address poolAddr = IEulerSwapFactory(eulerSwapFactoryAddress).poolByEulerAccount(lp); IEulerSwap.Params memory eulerSwapParams = IEulerSwap(poolAddr).getParams(); // get supply APY data using the MaglevLens contract - IMaglevLens maglevLens = IMaglevLens(MaglevLens); + IMaglevLens maglevLens = IMaglevLens(maglevLensAddress); address[] memory collateralVaults = new address[](2); collateralVaults[0] = eulerSwapParams.vault0; collateralVaults[1] = eulerSwapParams.vault1; @@ -723,8 +775,8 @@ contract JITpilot { uint256 collateralValue = getPositionValue(lp, collateralVaults[i], false); supplyApyTotal += supplyApy * collateralValue; collateralValueTotal += collateralValue; - console.log("Supply APY for vault", collateralVaults[i], "is", supplyApy); - console.log("Supply APY total is", supplyApyTotal); + // console.log("Supply APY for vault", collateralVaults[i], "is", supplyApy); + // console.log("Supply APY total is", supplyApyTotal); } supplyApyTotal = supplyApyTotal / collateralValueTotal; @@ -737,8 +789,9 @@ contract JITpilot { view returns (IEulerSwap.Params memory) { + console.log("calculating params for rebalance: ", asset0IsDebt); // Calculate delta reserves. This is the amount of trading we want to service, to repay the debt. - uint256 deltaReservesValueUsd = calculateDeltaReserves(lp, eulerSwapData); + uint256 deltaReservesValueUsd = calculateDeltaReserves(lp, eulerSwapData.params); uint256 asset0Scale = FixedPointMathLib.rpow(10e18, IERC20(IEVault(eulerSwapData.params.vault0).asset()).decimals(), 1e18) / 1e18; uint256 asset1Scale = FixedPointMathLib.rpow(10e18, IERC20(IEVault(eulerSwapData.params.vault1).asset()).decimals(), 1e18) / 1e18; uint256 asset0PriceUsd = IPriceOracle(IEVault(eulerSwapData.params.vault0).oracle()).getQuote( @@ -752,7 +805,7 @@ contract JITpilot { // Both equilibriumReserves are maxed at the point in the curve where vaults are balanced. uint256 desiredEqRsvCollateralAsset; uint256 desiredEqRsvDebtAsset; - (uint256 collateralValueTotal, uint256 debtValue) = getDepositValue(lp); + (uint256 collateralValueTotal, uint256 debtValue) = _getDepositValue(lp); uint256 depositValue = collateralValueTotal - debtValue; { if (asset0IsDebt) { @@ -771,7 +824,7 @@ contract JITpilot { desiredEqRsvDebtAsset = deltaReservesValueUsd * 3 * asset1Scale / asset1PriceUsd; } } - uint256 concentrationDebtAsset = 99 * 1e16; + uint256 concentrationDebtAsset = 99.3 * 1e16; return IEulerSwap.Params({ vault0: eulerSwapData.params.vault0, @@ -779,8 +832,8 @@ contract JITpilot { eulerAccount: eulerSwapData.params.eulerAccount, equilibriumReserve0: uint112(asset0IsDebt ? desiredEqRsvDebtAsset : desiredEqRsvCollateralAsset), equilibriumReserve1: uint112(asset0IsDebt ? desiredEqRsvCollateralAsset : desiredEqRsvDebtAsset), - priceX: 1 * asset1Scale, - priceY: asset1PriceUsd * 1e18 / asset0PriceUsd * asset0Scale / asset1Scale * 99/100, + priceX: 1 * asset1Scale, + priceY: asset1PriceUsd * 1e18 / asset0PriceUsd * asset0Scale / asset1Scale, concentrationX: asset0IsDebt ? concentrationDebtAsset : eulerSwapData.params.concentrationX, concentrationY: asset0IsDebt ? eulerSwapData.params.concentrationY : concentrationDebtAsset, fee: eulerSwapData.params.fee, @@ -789,12 +842,12 @@ contract JITpilot { }); } - function calculateDeltaReserves(address lp, EulerSwapData memory eulerSwapData) internal view returns (uint256) { + function calculateDeltaReserves(address lp, IEulerSwap.Params memory poolParams) internal view returns (uint256) { // $\Delta L = \frac{\frac{HF'}{LLTV} \cdot L - C}{\frac{HF'}{LLTV} - 1}$ uint256 hfPrime = lpData[lp].hfDesired; address controllerVault = getCurrentControllerVault(lp); address collateralVault = - controllerVault == eulerSwapData.params.vault0 ? eulerSwapData.params.vault1 : eulerSwapData.params.vault0; + controllerVault == poolParams.vault0 ? poolParams.vault1 : poolParams.vault0; uint256 lltv = uint256(IEVault(controllerVault).LTVLiquidation(collateralVault)) * 1e18 / 1e4; uint256 collateralValue = getPositionValue(lp, collateralVault, false); @@ -803,6 +856,17 @@ contract JITpilot { return ((hfPrime * liabilityValue / lltv) - collateralValue) / (hfPrime * 1e18 / lltv - 1e18) * 1e18; } + function mineSalt(IEulerSwap.Params memory params) internal view returns (address, bytes32) { + // Define required hook flags + uint160 flags = uint160( + Hooks.BEFORE_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG + | Hooks.BEFORE_DONATE_FLAG | Hooks.BEFORE_ADD_LIQUIDITY_FLAG + ); + + bytes memory creationCode = MetaProxyDeployer.creationCodeMetaProxy(eulerSwapImplAddress, abi.encode(params)); + return HookMiner.find(address(eulerSwapFactoryAddress), flags, creationCode); + } + // EXTERNAL HELPER FUNCTIONS FOR TESTING function getData(address lp) external view returns (BlockData memory) { @@ -811,7 +875,7 @@ contract JITpilot { function getRebalancingParams(address lp) external view returns (IEulerSwap.Params memory) { // #1 Fetch current EulerSwap data - address poolAddr = IEulerSwapFactory(EulerSwapFactory).poolByEulerAccount(lp); + address poolAddr = IEulerSwapFactory(eulerSwapFactoryAddress).poolByEulerAccount(lp); EulerSwapData memory eulerSwapData = getEulerSwapData(poolAddr); // #2 Calculate new EulerSwap params @@ -819,4 +883,20 @@ contract JITpilot { return calculateRebalancingParams(lp, eulerSwapData, asset0IsDebt); } + + /** + * @dev Rebalance LP position (placeholder - to be implemented later) + * @param lp LP address to rebalance + */ + function rebalance(address lp) external { + _rebalance(lp); + } + + function getDepositValue(address lp) external view returns (uint256 collateralValueTotal, uint256 debtValue) { + return _getDepositValue(lp); + } + + function getDeltaReserves(address lp, IEulerSwap.Params memory poolParams) external view returns (uint256) { + return calculateDeltaReserves(lp, poolParams); + } } From 01f0a8be565252531f25331423b8a64fc3440411 Mon Sep 17 00:00:00 2001 From: MazyGio Date: Mon, 7 Jul 2025 03:30:46 -0500 Subject: [PATCH 3/5] update script, rename functions, clean up logs --- ....s.sol => JITpilotRebalanceScenario.s.sol} | 60 +-- src/JITpilot.sol | 353 ++++++++---------- test/Counter.t.sol | 24 -- 3 files changed, 183 insertions(+), 254 deletions(-) rename script/scenarios/{EulerSwapDebtScenario.s.sol => JITpilotRebalanceScenario.s.sol} (91%) delete mode 100644 test/Counter.t.sol diff --git a/script/scenarios/EulerSwapDebtScenario.s.sol b/script/scenarios/JITpilotRebalanceScenario.s.sol similarity index 91% rename from script/scenarios/EulerSwapDebtScenario.s.sol rename to script/scenarios/JITpilotRebalanceScenario.s.sol index 846c724..1c1c677 100644 --- a/script/scenarios/EulerSwapDebtScenario.s.sol +++ b/script/scenarios/JITpilotRebalanceScenario.s.sol @@ -15,7 +15,7 @@ import {CurveLib} from "euler-swap/libraries/CurveLib.sol"; import {console2 as console} from "forge-std/console2.sol"; -contract EulerSwapDebtScenario is DeployScenario { +contract JITpilotRebalanceScenario is DeployScenario { address eulerSwap; JITpilot jitPilot; @@ -30,16 +30,9 @@ contract EulerSwapDebtScenario is DeployScenario { deployJITpilot(); vm.stopBroadcast(); - vm.startBroadcast(user2PK); - deployEulerSwap(getInitialEulerSwapParams(), false); - authorizeJITpilot(user2); - jitPilot.configureLp(user2, 1.4e18, 1.5e18); - vm.stopBroadcast(); - // create borrow positions for other users giveTonsOfCash(user0); giveTonsOfCash(user1); - // giveTonsOfCash(user3); depositCollateralIntoVault(user0, user0PK, address(eUSDC), 3_000_000_000e6); depositCollateralIntoVault(user1, user1PK, address(eWETH), 1_000_000e18); @@ -47,25 +40,38 @@ contract EulerSwapDebtScenario is DeployScenario { borrowFromVault(user0, user0PK, address(eWETH), 500_000e18); borrowFromVault(user1, user1PK, address(eUSDC), 1_600_000_000e6); + vm.startBroadcast(user2PK); + deployEulerSwap(getInitialEulerSwapParams(), false); + authorizeJITpilot(user2); + jitPilot.configureLp(user2, 1.4e18, 1.5e18); + vm.stopBroadcast(); + + // Initial EulerSwap state + console.log("Initial EulerSwap state: "); + printEulerSwapData(user2); + // buy USDC so that user2's EulerSwap position has to borrow USDC uint256 amountOut = 286_500_000e6; uint256 amountIn = _swapExactOut(address(assetWETH), address(assetUSDC), amountOut, user0, user0PK); console.log("marketUser SOLD %s WETH FOR %s USDC", amountIn, amountOut); - // user2 is in debt now. Let's fetch that data - console.log("EulerSwap state now after servicing trades: "); - printEulerSwapData(user2); - // Get a quote for the current price of ETH in the EulerSwap instance - uint256 ethPrice = eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18); - console.log("New price of ETH: ", ethPrice); + uint256 startingEthPrice = 2865e18; + uint256 ethPriceInUSDC = eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18); + console.log("Starting price of ETH: ", startingEthPrice); + console.log("New price of ETH: ", ethPriceInUSDC); // ETH price has dropped to ~2510. Let's update the oracle vm.prank(user3); - oracle.setPrice(address(eWETH), unitOfAccount, ethPrice * 1e18 / 1e6); + oracle.setPrice(address(eWETH), unitOfAccount, ethPriceInUSDC * 1e18 / 1e6); + + // user2 is in debt now. Let's see their position state + console.log("EulerSwap state now after servicing trades: "); + printEulerSwapData(user2); // Let's see what the rebalancing params would be IEulerSwap.Params memory newParams = jitPilot.getRebalancingParams(user2); + console.log("Rebalancing params:"); printEulerSwapParams(newParams); // let's do the actual rebalancing then @@ -76,24 +82,23 @@ contract EulerSwapDebtScenario is DeployScenario { deployEulerSwap(newParams, true); vm.stopBroadcast(); - // Now let's see if the rebalancing was successful - address poolAddr = eulerSwapFactory.poolByEulerAccount(user2); - newParams = IEulerSwap(poolAddr).getParams(); - printEulerSwapParams(newParams); + // EulerSwap state before arbitrage + console.log("EulerSwap state now after rebalancing, before arbitrage: "); + printEulerSwapData(user2); // Let's buy some WETH on the EulerSwap pool and see the effect on the debt // sell USDC so that user2's EulerSwap position has to borrow USDC uint256 newEthPrice = eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18); - console.log("price of ETH (market): ", ethPrice); + console.log("price of ETH (market): ", ethPriceInUSDC); console.log("price of ETH (EulerSwap): ", newEthPrice); - amountIn = 105_000_000e6; + amountIn = 101_000_000e6; amountOut = _swapExactIn(address(assetUSDC), address(assetWETH), amountIn, user0, user0PK); console.log("marketUser BOUGHT %s WETH FOR %s USDC (price: %s)", amountOut, amountIn, amountIn * 1e18 / amountOut); + console.log("price of ETH (EulerSwap, after arbitrage): ", eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18)); // Let's see the new state of the EulerSwap pool after arbitrage console.log("EulerSwap state now (after arbitrage):"); printEulerSwapData(user2); - console.log("price of ETH (EulerSwap, after arbitrage): ", eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18)); } function giveTonsOfCash(address user) internal virtual { @@ -279,12 +284,12 @@ contract EulerSwapDebtScenario is DeployScenario { console.log("vault0: ", params.vault0); console.log("vault1: ", params.vault1); console.log("eulerAccount: ", params.eulerAccount); - console.log("equilibriumReserve0: ", params.equilibriumReserve0); - console.log("equilibriumReserve1: ", params.equilibriumReserve1); + console.log("equilibriumReserve0: ", params.equilibriumReserve0, "<---------------"); + console.log("equilibriumReserve1: ", params.equilibriumReserve1, "<---------------"); console.log("priceX: ", params.priceX); console.log("priceY: ", params.priceY); - console.log("concentrationX: ", params.concentrationX); - console.log("concentrationY: ", params.concentrationY); + console.log("concentrationX: ", params.concentrationX, "<---------------"); + console.log("concentrationY: ", params.concentrationY, "<---------------"); console.log("fee: ", params.fee); console.log("protocolFee: ", params.protocolFee); console.log("protocolFeeRecipient: ", params.protocolFeeRecipient); @@ -294,9 +299,10 @@ contract EulerSwapDebtScenario is DeployScenario { function printEulerSwapData(address user) internal view { JITpilot.BlockData memory blockData = jitPilot.getData(user); + uint256 healthFactor = blockData.allowedLTV > 0 ? blockData.allowedLTV * 1e4 / blockData.currentLTV / 100 : 0; console.log("=========================================================="); - console.log("healthFactor: ", blockData.allowedLTV * 1e4 / blockData.currentLTV / 100, "%"); + console.log("healthFactor: ", healthFactor, "%"); console.log("allowedLTV: ", blockData.allowedLTV); console.log("currentLTV: ", blockData.currentLTV); console.log("swapFees: ", blockData.swapFees); diff --git a/src/JITpilot.sol b/src/JITpilot.sol index fbda783..9a6f7e5 100644 --- a/src/JITpilot.sol +++ b/src/JITpilot.sol @@ -43,16 +43,6 @@ contract JITpilot { address public eulerSwapFactoryAddress; address public eulerSwapImplAddress; - // Data structure to store block-level data from fetchData - struct BlockData { - uint256 allowedLTV; - uint256 currentLTV; - uint256 swapFees; - int256 netInterest; - int256 depositValue; - address controllerVault; - } - // LP data structure struct LPData { // Health Factor data @@ -77,6 +67,16 @@ contract JITpilot { RebalancingStatus rebalancingStatus; // Whether LP is currently rebalancing } + // Data structure to store block-level data from fetchData + struct BlockData { + uint256 allowedLTV; + uint256 currentLTV; + uint256 swapFees; + int256 netInterest; + int256 depositValue; + address controllerVault; + } + // Mappings mapping(address => LPData) public lpData; mapping(address => bool) public authorizedCallers; @@ -146,6 +146,7 @@ contract JITpilot { LPData storage data = lpData[lp]; data.hfMin = _hfMin; data.hfDesired = _hfDesired; + // TODO: implement yield-based rebalancing // data.yieldTarget = _yieldTarget; data.initialized = true; data.startBlock = block.number; @@ -179,8 +180,9 @@ contract JITpilot { } // Update sliding window for Health Factor - // _updateSlidingWindow(data.hfHistory, currentHF); + _updateSlidingWindow(data.hfHistory, currentHF); + // TODO: re-enable yield-based rebalancing // Update sliding window for Yield // _updateSlidingWindow(data.yieldHistory, currentYield); @@ -191,11 +193,11 @@ contract JITpilot { data.twaYield = _calculateTWA(data.yieldHistory, data.startBlock); // Calculate normalized values - // uint256 normalizedHF = _normalizeHealthFactor(data.twaHF, data.hfMin, data.hfDesired); - // uint256 normalizedYield = _normalizeYield(data.twaYield, data.yieldTarget); + uint256 normalizedHF = _normalizeHealthFactor(data.twaHF, data.hfMin, data.hfDesired); + uint256 normalizedYield = _normalizeYield(data.twaYield, data.yieldTarget); // Calculate composite score - // uint256 compositeScore = (weightHF * normalizedHF + weightYield * normalizedYield) / PRECISION; + uint256 compositeScore = (weightHF * normalizedHF + weightYield * normalizedYield) / PRECISION; // Update last update block data.lastUpdateBlock = block.number; @@ -204,17 +206,15 @@ contract JITpilot { // emit MetricsUpdated(lp, block.number, currentHF, currentYield, data.twaHF, data.twaYield); emit MetricsUpdated(lp, block.number, currentHF, 0, data.twaHF, 0); if (data.rebalancingStatus == RebalancingStatus.NOT_REBALANCING) { - // Check if rebalancing is needed - console.log("Checking if rebalancing is needed."); - if (currentHF < data.rebalanceThreshold && data.rebalancingStatus != RebalancingStatus.REBALANCING) { + if (currentHF < data.rebalanceThreshold) { emit RebalanceTriggered(lp, block.number, currentHF, data.rebalanceThreshold); _rebalance(lp); data.rebalancingStatus = RebalancingStatus.REBALANCING; } } else { // LP is in the middle of rebalancing - if (currentHF >= data.rebalanceThreshold) { + if (currentHF >= data.hfDesired) { _afterRebalanceFinished(lp); data.rebalancingStatus = RebalancingStatus.NOT_REBALANCING; } @@ -344,7 +344,7 @@ contract JITpilot { supplyApyTotal = getSupplyApy(lp); // get the currently enabled controller vault (i.e. the debt vault) - address controllerVault = getCurrentControllerVault(lp); + address controllerVault = _getCurrentControllerVault(lp); // If there is no controller, there is no debt, and no liquidation metrics to calculate if (controllerVault == address(0)) { @@ -355,19 +355,12 @@ contract JITpilot { blockData.netInterest = int256(supplyApyTotal); blockData.controllerVault = address(0); } else { - // console.log("has controller vault: ", controllerVault); // Figure out which vault is the collateralVault address collateralVault = (controllerVault == eulerSwapData.params.vault0) ? eulerSwapData.params.vault1 : eulerSwapData.params.vault0; - // console.log("debtValue: ", debtValue); - // console.log("collateralVault: ", collateralVault); - // console.log("controllerVault: ", controllerVault); - // console.log("LLTV: ", uint256(IEVault(controllerVault).LTVLiquidation(collateralVault))); - // console.log("LLTV other: ", uint256(IEVault(collateralVault).LTVLiquidation(controllerVault))); blockData.allowedLTV = uint256(IEVault(controllerVault).LTVLiquidation(collateralVault)) * 1e18 / 1e4; blockData.currentLTV = debtValue * 1e18 / collateralValueTotal; - console.log("currentLTV: ", blockData.currentLTV); address[] memory controllerVaultArray = new address[](1); controllerVaultArray[0] = controllerVault; @@ -393,46 +386,6 @@ contract JITpilot { blockData.depositValue = int256(collateralValueTotal) - int256(debtValue); - // get LP's liquidity status in the controller vault, with regards to liquidation - // ( - // address[] memory collateralVaults, - // uint256[] memory collateralValues, - // uint256 liabilityValue - // ) = IEVault(controllerVault).accountLiquidityFull(lp, true); - - // these collateralValues are adjusted to LTV. We need to divide by liquidationLTV to get the non-adjusted LTV - // uint256 collateralValueTotal; - // uint256 allowedLTV = 0; // Will be weighted average of all collateral LTVs - // uint256 totalWeight = 0; - // for (uint256 i; i < collateralVaults.length; ++i) { - // uint16 ltv = IEVault(controllerVault).LTVLiquidation(collateralVaults[i]); - // collateralValues[i] = collateralValues[i] * 10000 / ltv; // Convert back to non-adjusted value - // collateralValueTotal += collateralValues[i]; - - // // Calculate weighted average LTV - // allowedLTV += ltv * collateralValues[i]; - // totalWeight += collateralValues[i]; - // } - - // Finalize weighted average LTV - // if (totalWeight > 0) { - // allowedLTV = allowedLTV / totalWeight; - // } - - // #2 calculate the currentLTV - // uint256 currentLTV = liabilityValue / collateralValueTotal; - - // TODO: get swap fees - // uint256 swapFees = 0; - - // uint256 borrowApy = uint256((controllerVaultGlobals[0].packed2 << (256 - 48)) >> (256 - 48)); - - // #4 calculate net interest - // uint256 netInterest = supplyApyTotal - borrowApy; - - // #5 get the depositValue - // uint256 depositValue = collateralValueTotal - liabilityValue; - return blockData; } @@ -443,10 +396,6 @@ contract JITpilot { address asset1; uint256 reserve0; uint256 reserve1; - // uint256 inLimit01; - // uint256 outLimit01; - // uint256 inLimit10; - // uint256 outLimit10; uint16 borrowLTV01; uint16 borrowLTV10; } @@ -463,8 +412,6 @@ contract JITpilot { (address asset0, address asset1) = pool.getAssets(); output.asset0 = asset0; output.asset1 = asset1; - // (output.inLimit01, output.outLimit01) = pool.getLimits(asset0, asset1); - // (output.inLimit10, output.outLimit10) = pool.getLimits(asset1, asset0); // fetch borrow LTVs. These will be used to calculate reserves for rebalancing output.borrowLTV01 = IEVault(output.params.vault0).LTVBorrow(output.params.vault1); output.borrowLTV10 = IEVault(output.params.vault1).LTVBorrow(output.params.vault0); @@ -474,7 +421,7 @@ contract JITpilot { * @dev Rebalance LP position (placeholder - to be implemented later) * @param lp LP address to rebalance */ - function _rebalance(address lp) internal view { + function _rebalance(address lp) internal { // Placeholder implementation - this will perform actual rebalancing // Will be implemented in later iterations // This function is only called after confirming that a rebalance is needed @@ -484,7 +431,7 @@ contract JITpilot { EulerSwapData memory eulerSwapData = getEulerSwapData(poolAddr); // #2 Calculate new EulerSwap params - bool asset0IsDebt = getCurrentControllerVault(lp) == eulerSwapData.params.vault0; + bool asset0IsDebt = _getCurrentControllerVault(lp) == eulerSwapData.params.vault0; IEulerSwap.Params memory newParams = calculateRebalancingParams(lp, eulerSwapData, asset0IsDebt); // IEulerSwap.InitialState memory initialState = IEulerSwap.InitialState({ @@ -525,15 +472,105 @@ contract JITpilot { // data: abi.encodeCall(IEulerSwapFactory.deployPool, (newParams, initialState, salt)) // }); // IEVC(evcAddress).batch(items3); + } + + /** + * @dev Calculate rebalancing params for an LP. + * We create a new EulerSwap pool with the equilibrium reserves and initial state set in + * a way that incentivizes the market to arbitrage by selling the debt asset to this EulerSwap + * instance, causing the user's debt to be repaid. + * @param lp LP address + * @param eulerSwapData EulerSwap data + * @param asset0IsDebt Whether asset0 is the debt asset + * @return newParams New EulerSwap params to use when deploying the new pool + */ + function calculateRebalancingParams(address lp, EulerSwapData memory eulerSwapData, bool asset0IsDebt) + internal + view + returns (IEulerSwap.Params memory) + { + // Calculate delta reserves. This is the amount of trading we want to service, to repay the debt. + uint256 deltaReservesValueUsd = calculateDeltaReserves(lp, eulerSwapData.params); + (uint256 collateralValueTotal, uint256 debtValue) = _getDepositValue(lp); + uint256 depositValue = collateralValueTotal - debtValue; + + uint256 asset0Scale = FixedPointMathLib.rpow(10e18, IERC20(IEVault(eulerSwapData.params.vault0).asset()).decimals(), 1e18) / 1e18; + uint256 asset1Scale = FixedPointMathLib.rpow(10e18, IERC20(IEVault(eulerSwapData.params.vault1).asset()).decimals(), 1e18) / 1e18; + uint256 asset0PriceUsd = IPriceOracle(IEVault(eulerSwapData.params.vault0).oracle()).getQuote( + asset0Scale, IEVault(eulerSwapData.params.vault0).asset(), IEVault(eulerSwapData.params.vault0).unitOfAccount() + ); + uint256 asset1PriceUsd = IPriceOracle(IEVault(eulerSwapData.params.vault1).oracle()).getQuote( + asset1Scale, IEVault(eulerSwapData.params.vault1).asset(), IEVault(eulerSwapData.params.vault1).unitOfAccount() + ); + + // Calculate balancedEquilibriumReserves given current depositValue + // Both equilibriumReserves are maxed at the point in the curve where vaults are balanced. + uint256 desiredEqRsvCollateralAsset; + uint256 desiredEqRsvDebtAsset; + { + if (asset0IsDebt) { + // we've chosen an arbitrary amount of 3x deltaReserves and a 99.3% concentration to prevent over-borrowing and allow for arbitrage + desiredEqRsvDebtAsset = deltaReservesValueUsd * 3 * asset0Scale / asset0PriceUsd; + + uint256 balEqRsv1 = depositValue * 1e4 / (1e4 - eulerSwapData.borrowLTV01) * asset1Scale / asset1PriceUsd; + desiredEqRsvCollateralAsset = balEqRsv1 + + depositValue * asset1Scale / 2 / asset1PriceUsd + + debtValue * asset1Scale / asset1PriceUsd + - deltaReservesValueUsd * asset1Scale / asset1PriceUsd; + } else { + // we've chosen an arbitrary amount of 3x deltaReserves and a 99% concentration to prevent over-borrowing and allow for arbitrage + desiredEqRsvDebtAsset = deltaReservesValueUsd * 3 * asset1Scale / asset1PriceUsd; + + uint256 balEqRsv0 = depositValue * 1e4 / (1e4 - eulerSwapData.borrowLTV01) * asset0Scale / asset0PriceUsd; + desiredEqRsvCollateralAsset = balEqRsv0 + + depositValue * asset0Scale / 2 / asset0PriceUsd + + debtValue * asset0Scale / asset0PriceUsd + - deltaReservesValueUsd * asset0Scale / asset0PriceUsd; + } + } + uint256 concentrationDebtAsset = 99.3 * 1e16; + + return IEulerSwap.Params({ + vault0: eulerSwapData.params.vault0, + vault1: eulerSwapData.params.vault1, + eulerAccount: eulerSwapData.params.eulerAccount, + equilibriumReserve0: uint112(asset0IsDebt ? desiredEqRsvDebtAsset : desiredEqRsvCollateralAsset), + equilibriumReserve1: uint112(asset0IsDebt ? desiredEqRsvCollateralAsset : desiredEqRsvDebtAsset), + priceX: 1 * asset1Scale, + priceY: asset1PriceUsd * 1e18 / asset0PriceUsd * asset0Scale / asset1Scale, + concentrationX: asset0IsDebt ? concentrationDebtAsset : eulerSwapData.params.concentrationX, + concentrationY: asset0IsDebt ? eulerSwapData.params.concentrationY : concentrationDebtAsset, + fee: eulerSwapData.params.fee, + protocolFee: eulerSwapData.params.protocolFee, + protocolFeeRecipient: eulerSwapData.params.protocolFeeRecipient + }); + } - // console.log("reinstalled EulerSwap."); + /** + * @dev Calculate delta reserves for an LP. This is the amount of trading that the LP needs to service + * in order for their debt to be repaid and their Health Factor to be restored to their desired value. + * @param lp LP address + * @param poolParams EulerSwap params + * @return deltaReservesValueUsd Delta reserves value in USD + */ + function calculateDeltaReserves(address lp, IEulerSwap.Params memory poolParams) internal view returns (uint256) { + // $\Delta L = \frac{\frac{HF'}{LLTV} \cdot L - C}{\frac{HF'}{LLTV} - 1}$ + uint256 hfPrime = lpData[lp].hfDesired; + address controllerVault = _getCurrentControllerVault(lp); + address collateralVault = + controllerVault == poolParams.vault0 ? poolParams.vault1 : poolParams.vault0; + uint256 lltv = uint256(IEVault(controllerVault).LTVLiquidation(collateralVault)) * 1e18 / 1e4; + + uint256 collateralValue = _getPositionValue(lp, collateralVault, false); + uint256 liabilityValue = _getPositionValue(lp, controllerVault, true); + + return ((hfPrime * liabilityValue / lltv) - collateralValue) / (hfPrime * 1e18 / lltv - 1e18) * 1.01e18; } function _afterRebalanceFinished(address lp) internal { - // reinstall EulerSwap with original params but updated price - + // reinstall EulerSwap with original params but updated price. + // TODO: implement redeploying EulerSwap pool with original params. } - /** * @dev Add authorized caller @@ -669,7 +706,12 @@ contract JITpilot { // HELPER FUNCTIONS - function getCurrentControllerVault(address lp) internal view returns (address) { + /** + * @dev Get current controller vault for an LP. This tells us which vault is the debt vault. + * @param lp LP address + * @return Controller vault address + */ + function _getCurrentControllerVault(address lp) internal view returns (address) { address[] memory controllerVaults = IEVC(evcAddress).getControllers(lp); address currentControllerVault; @@ -685,51 +727,6 @@ contract JITpilot { return currentControllerVault; } - // function getCollateralValue(address account, address vaultAddress) internal view virtual returns (uint256 value) { - // IEVault collateralVault = IEVault(vaultAddress); - // uint256 balance = IERC20(vaultAddress).balanceOf(account); - // if (balance == 0) return 0; - - // uint256 currentCollateralValue; - - // // mid-point price - // currentCollateralValue = - // IPriceOracle(collateralVault.oracle()).getQuote(balance, vaultAddress, collateralVault.unitOfAccount()); - - // return currentCollateralValue; - // } - - // function getDebtValue(address account, address vault) internal view virtual returns (uint256 value) { - // IEVault controllerVault = IEVault(vault); - // uint256 debt = controllerVault.debtOf(account); - // if (debt == 0) return 0; - - // uint256 currentDebtValue; - - // // mid-point price - // currentDebtValue = IPriceOracle(controllerVault.oracle()).getQuote(debt, vault, controllerVault.unitOfAccount()); - - // return currentDebtValue; - // } - - function getPositionValue(address account, address vaultAddress, bool isControllerVault) - internal - view - virtual - returns (uint256 value) - { - IEVault vault = IEVault(vaultAddress); - uint256 balance = isControllerVault ? vault.debtOf(account) : IERC20(vaultAddress).balanceOf(account); - if (balance == 0) return 0; - - uint256 currentPositionValue; - - // mid-point price - currentPositionValue = IPriceOracle(vault.oracle()).getQuote(balance, vaultAddress, vault.unitOfAccount()); - - return currentPositionValue; - } - /** * @dev Get the deposit value of an LP * @param lp LP address @@ -746,13 +743,38 @@ contract JITpilot { IEulerSwap.Params memory eulerSwapParams = IEulerSwap(poolAddr).getParams(); collateralValueTotal = - getPositionValue(lp, eulerSwapParams.vault0, false) + getPositionValue(lp, eulerSwapParams.vault1, false); + _getPositionValue(lp, eulerSwapParams.vault0, false) + _getPositionValue(lp, eulerSwapParams.vault1, false); debtValue = - getPositionValue(lp, eulerSwapParams.vault0, true) + getPositionValue(lp, eulerSwapParams.vault1, true); + _getPositionValue(lp, eulerSwapParams.vault0, true) + _getPositionValue(lp, eulerSwapParams.vault1, true); return (collateralValueTotal, debtValue); } + /** + * @dev Get the USD value of a collateral or debt position + * @param account Account address + * @param vaultAddress Vault address + * @param isControllerVault Whether the vault is the controller vault + * @return value Position value in USD + */ + function _getPositionValue(address account, address vaultAddress, bool isControllerVault) + internal + view + virtual + returns (uint256 value) + { + IEVault vault = IEVault(vaultAddress); + uint256 balance = isControllerVault ? vault.debtOf(account) : IERC20(vaultAddress).balanceOf(account); + if (balance == 0) return 0; + + uint256 currentPositionValue; + + // mid-point price + currentPositionValue = IPriceOracle(vault.oracle()).getQuote(balance, vaultAddress, vault.unitOfAccount()); + + return currentPositionValue; + } + /** * @dev Get the supply APY of an LP * @param lp LP address @@ -772,11 +794,9 @@ contract JITpilot { uint256 collateralValueTotal; for (uint256 i; i < collateralVaultsGlobal.length; ++i) { uint256 supplyApy = uint256((collateralVaultsGlobal[i].packed2 << (256 - 96)) >> (256 - 48)); - uint256 collateralValue = getPositionValue(lp, collateralVaults[i], false); + uint256 collateralValue = _getPositionValue(lp, collateralVaults[i], false); supplyApyTotal += supplyApy * collateralValue; collateralValueTotal += collateralValue; - // console.log("Supply APY for vault", collateralVaults[i], "is", supplyApy); - // console.log("Supply APY total is", supplyApyTotal); } supplyApyTotal = supplyApyTotal / collateralValueTotal; @@ -784,78 +804,6 @@ contract JITpilot { return supplyApyTotal; } - function calculateRebalancingParams(address lp, EulerSwapData memory eulerSwapData, bool asset0IsDebt) - internal - view - returns (IEulerSwap.Params memory) - { - console.log("calculating params for rebalance: ", asset0IsDebt); - // Calculate delta reserves. This is the amount of trading we want to service, to repay the debt. - uint256 deltaReservesValueUsd = calculateDeltaReserves(lp, eulerSwapData.params); - uint256 asset0Scale = FixedPointMathLib.rpow(10e18, IERC20(IEVault(eulerSwapData.params.vault0).asset()).decimals(), 1e18) / 1e18; - uint256 asset1Scale = FixedPointMathLib.rpow(10e18, IERC20(IEVault(eulerSwapData.params.vault1).asset()).decimals(), 1e18) / 1e18; - uint256 asset0PriceUsd = IPriceOracle(IEVault(eulerSwapData.params.vault0).oracle()).getQuote( - asset0Scale, IEVault(eulerSwapData.params.vault0).asset(), IEVault(eulerSwapData.params.vault0).unitOfAccount() - ); - uint256 asset1PriceUsd = IPriceOracle(IEVault(eulerSwapData.params.vault1).oracle()).getQuote( - asset1Scale, IEVault(eulerSwapData.params.vault1).asset(), IEVault(eulerSwapData.params.vault1).unitOfAccount() - ); - - // Calculate balancedEquilibriumReserves given current depositValue - // Both equilibriumReserves are maxed at the point in the curve where vaults are balanced. - uint256 desiredEqRsvCollateralAsset; - uint256 desiredEqRsvDebtAsset; - (uint256 collateralValueTotal, uint256 debtValue) = _getDepositValue(lp); - uint256 depositValue = collateralValueTotal - debtValue; - { - if (asset0IsDebt) { - uint256 balEqRsv1 = depositValue * 1e4 / (1e4 - eulerSwapData.borrowLTV01) * asset1Scale / asset1PriceUsd; - desiredEqRsvCollateralAsset = balEqRsv1 - + debtValue * asset1Scale / asset1PriceUsd - - deltaReservesValueUsd * asset1Scale / asset1PriceUsd - depositValue * asset1Scale / 2 / asset1PriceUsd; - // we've chosen an arbitrary amount of 3x deltaReserves and a 99% concentration to prevent over-borrowing and allow for arbitrage - desiredEqRsvDebtAsset = deltaReservesValueUsd * 3 * asset0Scale / asset0PriceUsd; - } else { - uint256 balEqRsv0 = depositValue * 1e4 / (1e4 - eulerSwapData.borrowLTV01) * asset0Scale / asset0PriceUsd; - desiredEqRsvCollateralAsset = balEqRsv0 - + debtValue * asset0Scale / asset0PriceUsd - - deltaReservesValueUsd * asset0Scale / asset0PriceUsd - depositValue * asset0Scale / 2 / asset0PriceUsd; - // we've chosen an arbitrary amount of 3x deltaReserves and a 99% concentration to prevent over-borrowing and allow for arbitrage - desiredEqRsvDebtAsset = deltaReservesValueUsd * 3 * asset1Scale / asset1PriceUsd; - } - } - uint256 concentrationDebtAsset = 99.3 * 1e16; - - return IEulerSwap.Params({ - vault0: eulerSwapData.params.vault0, - vault1: eulerSwapData.params.vault1, - eulerAccount: eulerSwapData.params.eulerAccount, - equilibriumReserve0: uint112(asset0IsDebt ? desiredEqRsvDebtAsset : desiredEqRsvCollateralAsset), - equilibriumReserve1: uint112(asset0IsDebt ? desiredEqRsvCollateralAsset : desiredEqRsvDebtAsset), - priceX: 1 * asset1Scale, - priceY: asset1PriceUsd * 1e18 / asset0PriceUsd * asset0Scale / asset1Scale, - concentrationX: asset0IsDebt ? concentrationDebtAsset : eulerSwapData.params.concentrationX, - concentrationY: asset0IsDebt ? eulerSwapData.params.concentrationY : concentrationDebtAsset, - fee: eulerSwapData.params.fee, - protocolFee: eulerSwapData.params.protocolFee, - protocolFeeRecipient: eulerSwapData.params.protocolFeeRecipient - }); - } - - function calculateDeltaReserves(address lp, IEulerSwap.Params memory poolParams) internal view returns (uint256) { - // $\Delta L = \frac{\frac{HF'}{LLTV} \cdot L - C}{\frac{HF'}{LLTV} - 1}$ - uint256 hfPrime = lpData[lp].hfDesired; - address controllerVault = getCurrentControllerVault(lp); - address collateralVault = - controllerVault == poolParams.vault0 ? poolParams.vault1 : poolParams.vault0; - uint256 lltv = uint256(IEVault(controllerVault).LTVLiquidation(collateralVault)) * 1e18 / 1e4; - - uint256 collateralValue = getPositionValue(lp, collateralVault, false); - uint256 liabilityValue = getPositionValue(lp, controllerVault, true); - - return ((hfPrime * liabilityValue / lltv) - collateralValue) / (hfPrime * 1e18 / lltv - 1e18) * 1e18; - } - function mineSalt(IEulerSwap.Params memory params) internal view returns (address, bytes32) { // Define required hook flags uint160 flags = uint160( @@ -868,7 +816,6 @@ contract JITpilot { } // EXTERNAL HELPER FUNCTIONS FOR TESTING - function getData(address lp) external view returns (BlockData memory) { return fetchData(lp); } @@ -879,7 +826,7 @@ contract JITpilot { EulerSwapData memory eulerSwapData = getEulerSwapData(poolAddr); // #2 Calculate new EulerSwap params - bool asset0IsDebt = getCurrentControllerVault(lp) == eulerSwapData.params.vault0; + bool asset0IsDebt = _getCurrentControllerVault(lp) == eulerSwapData.params.vault0; return calculateRebalancingParams(lp, eulerSwapData, asset0IsDebt); } diff --git a/test/Counter.t.sol b/test/Counter.t.sol deleted file mode 100644 index 58305bb..0000000 --- a/test/Counter.t.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test, console} from "forge-std/Test.sol"; -import {JITpilot} from "../src/JITpilot.sol"; - -contract JITpilotTest is Test { - // JITpilot public JITpilot; - - function setUp() public { - // JITpilot = new JITpilot(); - // counter.setNumber(0); - } - - function test_Increment() public { - // counter.increment(); - // assertEq(counter.number(), 1); - } - - function testFuzz_SetNumber(uint256 x) public { - // counter.setNumber(x); - // assertEq(counter.number(), x); - } -} From 622ecba18fba3328d5d706062e9516277f2e753e Mon Sep 17 00:00:00 2001 From: MazyGio Date: Mon, 7 Jul 2025 03:57:55 -0500 Subject: [PATCH 4/5] run forge fmt --- .../scenarios/JITpilotRebalanceScenario.s.sol | 52 ++++++++++++----- src/JITpilot.sol | 58 ++++++++++--------- 2 files changed, 69 insertions(+), 41 deletions(-) diff --git a/script/scenarios/JITpilotRebalanceScenario.s.sol b/script/scenarios/JITpilotRebalanceScenario.s.sol index 1c1c677..ca47169 100644 --- a/script/scenarios/JITpilotRebalanceScenario.s.sol +++ b/script/scenarios/JITpilotRebalanceScenario.s.sol @@ -57,7 +57,8 @@ contract JITpilotRebalanceScenario is DeployScenario { // Get a quote for the current price of ETH in the EulerSwap instance uint256 startingEthPrice = 2865e18; - uint256 ethPriceInUSDC = eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18); + uint256 ethPriceInUSDC = + eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18); console.log("Starting price of ETH: ", startingEthPrice); console.log("New price of ETH: ", ethPriceInUSDC); @@ -88,13 +89,19 @@ contract JITpilotRebalanceScenario is DeployScenario { // Let's buy some WETH on the EulerSwap pool and see the effect on the debt // sell USDC so that user2's EulerSwap position has to borrow USDC - uint256 newEthPrice = eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18); + uint256 newEthPrice = + eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18); console.log("price of ETH (market): ", ethPriceInUSDC); console.log("price of ETH (EulerSwap): ", newEthPrice); amountIn = 101_000_000e6; amountOut = _swapExactIn(address(assetUSDC), address(assetWETH), amountIn, user0, user0PK); - console.log("marketUser BOUGHT %s WETH FOR %s USDC (price: %s)", amountOut, amountIn, amountIn * 1e18 / amountOut); - console.log("price of ETH (EulerSwap, after arbitrage): ", eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18)); + console.log( + "marketUser BOUGHT %s WETH FOR %s USDC (price: %s)", amountOut, amountIn, amountIn * 1e18 / amountOut + ); + console.log( + "price of ETH (EulerSwap, after arbitrage): ", + eulerSwapPeriphery.quoteExactOutput(eulerSwap, address(assetUSDC), address(assetWETH), 1e18) + ); // Let's see the new state of the EulerSwap pool after arbitrage console.log("EulerSwap state now (after arbitrage):"); @@ -126,7 +133,6 @@ contract JITpilotRebalanceScenario is DeployScenario { } function deployEulerSwap(IEulerSwap.Params memory poolParams, bool rebalancing) internal { - console.log("DEPLOYING EULERSWAP WITH PARAMS"); printEulerSwapParams(poolParams); @@ -136,23 +142,44 @@ contract JITpilotRebalanceScenario is DeployScenario { IEulerSwap.InitialState memory initialState; if (!rebalancing) { - initialState = IEulerSwap.InitialState({currReserve0: poolParams.equilibriumReserve0, currReserve1: poolParams.equilibriumReserve1}); - } else { + initialState = IEulerSwap.InitialState({ + currReserve0: poolParams.equilibriumReserve0, + currReserve1: poolParams.equilibriumReserve1 + }); + } else { if (asset0IsDebt) { { - uint256 deltaReservesAsset0 = poolParams.equilibriumReserve0 * 1/3; + uint256 deltaReservesAsset0 = poolParams.equilibriumReserve0 * 1 / 3; // uint256 deltaReservesAsset1 = deltaReservesAsset0 * poolParams.priceX / poolParams.priceY; currentReserve0 = uint112(poolParams.equilibriumReserve0 - deltaReservesAsset0); // currentReserve1 = uint112(poolParams.equilibriumReserve1 + deltaReservesAsset1); - currentReserve1 = uint112(CurveLib.f(uint256(currentReserve0), uint256(poolParams.priceX), uint256(poolParams.priceY), uint256(poolParams.equilibriumReserve0), uint256(poolParams.equilibriumReserve1), uint256(poolParams.concentrationX))); + currentReserve1 = uint112( + CurveLib.f( + uint256(currentReserve0), + uint256(poolParams.priceX), + uint256(poolParams.priceY), + uint256(poolParams.equilibriumReserve0), + uint256(poolParams.equilibriumReserve1), + uint256(poolParams.concentrationX) + ) + ); } } else { { - uint256 deltaReservesAsset1 = poolParams.equilibriumReserve1 * 1/3; + uint256 deltaReservesAsset1 = poolParams.equilibriumReserve1 * 1 / 3; // uint256 deltaReservesAsset0 = deltaReservesAsset1 * poolParams.priceY / poolParams.priceX; currentReserve1 = uint112(poolParams.equilibriumReserve1 - deltaReservesAsset1); // currentReserve0 = uint112(poolParams.equilibriumReserve0 + deltaReservesAsset0); - currentReserve0 = uint112(CurveLib.fInverse(uint256(currentReserve1), uint256(poolParams.priceY), uint256(poolParams.priceX), uint256(poolParams.equilibriumReserve1), uint256(poolParams.equilibriumReserve0), uint256(poolParams.concentrationY))); + currentReserve0 = uint112( + CurveLib.fInverse( + uint256(currentReserve1), + uint256(poolParams.priceY), + uint256(poolParams.priceX), + uint256(poolParams.equilibriumReserve1), + uint256(poolParams.equilibriumReserve0), + uint256(poolParams.concentrationY) + ) + ); } } initialState = IEulerSwap.InitialState({currReserve0: currentReserve0, currReserve1: currentReserve1}); @@ -297,7 +324,6 @@ contract JITpilotRebalanceScenario is DeployScenario { } function printEulerSwapData(address user) internal view { - JITpilot.BlockData memory blockData = jitPilot.getData(user); uint256 healthFactor = blockData.allowedLTV > 0 ? blockData.allowedLTV * 1e4 / blockData.currentLTV / 100 : 0; @@ -311,7 +337,7 @@ contract JITpilotRebalanceScenario is DeployScenario { console.log("controllerVault: ", blockData.controllerVault); console.log("=========================================================="); } - + function getCurrentControllerVault(address lp) internal view returns (address) { address[] memory controllerVaults = evc.getControllers(lp); address currentControllerVault; diff --git a/src/JITpilot.sol b/src/JITpilot.sol index 9a6f7e5..12e9d6a 100644 --- a/src/JITpilot.sol +++ b/src/JITpilot.sol @@ -27,6 +27,7 @@ contract JITpilot { // Constants uint256 private constant WINDOW_SIZE = 100; uint256 private constant PRECISION = 1e18; + enum RebalancingStatus { NOT_REBALANCING, REBALANCING @@ -152,7 +153,6 @@ contract JITpilot { data.startBlock = block.number; data.rebalanceThreshold = _hfDesired; data.rebalanceDesired = _hfDesired; - emit LPConfigured(lp, _hfMin, _hfDesired); } @@ -298,13 +298,13 @@ contract JITpilot { function calculateRebalanceThreshold(address lp) internal view returns (uint256) { LPData storage data = lpData[lp]; if (!data.initialized) return 0; - + // Placeholder implementation - to be researched and implemented // Should calculate threshold based on hfMin as main parameter // with thresholdSafetyMargin for fine-tuning return data.hfDesired; // Default hfDesired for now } - + /** * @dev Calculate dynamic rebalance desired target based on LP configuration (placeholder) * @param lp LP address @@ -313,7 +313,7 @@ contract JITpilot { function calculateRebalanceDesired(address lp) internal view returns (uint256) { LPData storage data = lpData[lp]; if (!data.initialized) return 0; - + // Placeholder implementation - to be researched and implemented // Should calculate target based on hfDesired and yieldTarget as main parameters // with desiredTargetRatio for fine-tuning @@ -494,13 +494,19 @@ contract JITpilot { (uint256 collateralValueTotal, uint256 debtValue) = _getDepositValue(lp); uint256 depositValue = collateralValueTotal - debtValue; - uint256 asset0Scale = FixedPointMathLib.rpow(10e18, IERC20(IEVault(eulerSwapData.params.vault0).asset()).decimals(), 1e18) / 1e18; - uint256 asset1Scale = FixedPointMathLib.rpow(10e18, IERC20(IEVault(eulerSwapData.params.vault1).asset()).decimals(), 1e18) / 1e18; + uint256 asset0Scale = + FixedPointMathLib.rpow(10e18, IERC20(IEVault(eulerSwapData.params.vault0).asset()).decimals(), 1e18) / 1e18; + uint256 asset1Scale = + FixedPointMathLib.rpow(10e18, IERC20(IEVault(eulerSwapData.params.vault1).asset()).decimals(), 1e18) / 1e18; uint256 asset0PriceUsd = IPriceOracle(IEVault(eulerSwapData.params.vault0).oracle()).getQuote( - asset0Scale, IEVault(eulerSwapData.params.vault0).asset(), IEVault(eulerSwapData.params.vault0).unitOfAccount() + asset0Scale, + IEVault(eulerSwapData.params.vault0).asset(), + IEVault(eulerSwapData.params.vault0).unitOfAccount() ); uint256 asset1PriceUsd = IPriceOracle(IEVault(eulerSwapData.params.vault1).oracle()).getQuote( - asset1Scale, IEVault(eulerSwapData.params.vault1).asset(), IEVault(eulerSwapData.params.vault1).unitOfAccount() + asset1Scale, + IEVault(eulerSwapData.params.vault1).asset(), + IEVault(eulerSwapData.params.vault1).unitOfAccount() ); // Calculate balancedEquilibriumReserves given current depositValue @@ -512,20 +518,18 @@ contract JITpilot { // we've chosen an arbitrary amount of 3x deltaReserves and a 99.3% concentration to prevent over-borrowing and allow for arbitrage desiredEqRsvDebtAsset = deltaReservesValueUsd * 3 * asset0Scale / asset0PriceUsd; - uint256 balEqRsv1 = depositValue * 1e4 / (1e4 - eulerSwapData.borrowLTV01) * asset1Scale / asset1PriceUsd; - desiredEqRsvCollateralAsset = balEqRsv1 - + depositValue * asset1Scale / 2 / asset1PriceUsd - + debtValue * asset1Scale / asset1PriceUsd - - deltaReservesValueUsd * asset1Scale / asset1PriceUsd; + uint256 balEqRsv1 = + depositValue * 1e4 / (1e4 - eulerSwapData.borrowLTV01) * asset1Scale / asset1PriceUsd; + desiredEqRsvCollateralAsset = balEqRsv1 + depositValue * asset1Scale / 2 / asset1PriceUsd + + debtValue * asset1Scale / asset1PriceUsd - deltaReservesValueUsd * asset1Scale / asset1PriceUsd; } else { // we've chosen an arbitrary amount of 3x deltaReserves and a 99% concentration to prevent over-borrowing and allow for arbitrage desiredEqRsvDebtAsset = deltaReservesValueUsd * 3 * asset1Scale / asset1PriceUsd; - uint256 balEqRsv0 = depositValue * 1e4 / (1e4 - eulerSwapData.borrowLTV01) * asset0Scale / asset0PriceUsd; - desiredEqRsvCollateralAsset = balEqRsv0 - + depositValue * asset0Scale / 2 / asset0PriceUsd - + debtValue * asset0Scale / asset0PriceUsd - - deltaReservesValueUsd * asset0Scale / asset0PriceUsd; + uint256 balEqRsv0 = + depositValue * 1e4 / (1e4 - eulerSwapData.borrowLTV01) * asset0Scale / asset0PriceUsd; + desiredEqRsvCollateralAsset = balEqRsv0 + depositValue * asset0Scale / 2 / asset0PriceUsd + + debtValue * asset0Scale / asset0PriceUsd - deltaReservesValueUsd * asset0Scale / asset0PriceUsd; } } uint256 concentrationDebtAsset = 99.3 * 1e16; @@ -557,8 +561,7 @@ contract JITpilot { // $\Delta L = \frac{\frac{HF'}{LLTV} \cdot L - C}{\frac{HF'}{LLTV} - 1}$ uint256 hfPrime = lpData[lp].hfDesired; address controllerVault = _getCurrentControllerVault(lp); - address collateralVault = - controllerVault == poolParams.vault0 ? poolParams.vault1 : poolParams.vault0; + address collateralVault = controllerVault == poolParams.vault0 ? poolParams.vault1 : poolParams.vault0; uint256 lltv = uint256(IEVault(controllerVault).LTVLiquidation(collateralVault)) * 1e18 / 1e4; uint256 collateralValue = _getPositionValue(lp, collateralVault, false); @@ -673,7 +676,7 @@ contract JITpilot { function getRebalanceThreshold(address lp) external view returns (uint256) { return lpData[lp].rebalanceThreshold; } - + /** * @dev Get rebalance desired target for an LP * @param lp LP address @@ -682,7 +685,7 @@ contract JITpilot { function getRebalanceDesired(address lp) external view returns (uint256) { return lpData[lp].rebalanceDesired; } - + /** * @dev Get all key metrics for an LP in one call * @param lp LP address @@ -691,12 +694,11 @@ contract JITpilot { * @return desired Rebalance target * @return needsRebalance Whether LP currently needs rebalancing */ - function getLPMetrics(address lp) external view returns ( - uint256 compositeScore, - uint256 threshold, - uint256 desired, - bool needsRebalance - ) { + function getLPMetrics(address lp) + external + view + returns (uint256 compositeScore, uint256 threshold, uint256 desired, bool needsRebalance) + { LPData storage data = lpData[lp]; compositeScore = this.getCompositeScore(lp); threshold = data.rebalanceThreshold; From 2f7e5864ac4db304accd40b9c90071b7744d9d37 Mon Sep 17 00:00:00 2001 From: MazyGio Date: Mon, 7 Jul 2025 04:04:42 -0500 Subject: [PATCH 5/5] update readme --- README.md | 77 +++++++++++++------------------------ public/JITpilot_output.png | Bin 0 -> 155270 bytes 2 files changed, 27 insertions(+), 50 deletions(-) create mode 100644 public/JITpilot_output.png diff --git a/README.md b/README.md index a98f554..ad66350 100644 --- a/README.md +++ b/README.md @@ -1,66 +1,43 @@ -## Foundry +# JITpilot -**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** +JITpilot is an EulerSwap liquidity pool rebalancing system which allows users to set up automated monitoring for their EulerSwap positions, and rebalance them when needed by reparametrizing their pool and letting the market arbitrage the new state. It is a work in progress and is not ready for production use. -Foundry consists of: - -- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). -- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. -- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. -- **Chisel**: Fast, utilitarian, and verbose solidity REPL. - -## Documentation - -https://book.getfoundry.sh/ +* Time-weighted metrics: JITpilot uses time-weighted metrics to mitigate the effects of volatile markets and prevent frequent rebalancing that could increase gas costs. +* EVC-friendly: JITpilot is designed to work with the EulerVaultConnector (EVC) to better integrate into the Euler ecosystem. +* Peace of mind: Rest easy; while your EulerSwap pool rakes in yield and fees, JITpilot will keep it healthy. ## Usage -### Build - -```shell -$ forge build -``` - -### Test +### Installation -```shell -$ forge test +First [install foundry](https://getfoundry.sh/) then run: +```sh +./install.sh ``` -### Format - -```shell -$ forge fmt +### Run example scripts +```sh +./devland.sh JITpilotRebalanceScenario ``` -### Gas Snapshots +If all goes well, your RPC will be available on the standard `http://127.0.0.1:8545` endpoint. It will print the logs pertaining to the EulerSwap pool rebalancing. +![alt text](image.png) -```shell -$ forge snapshot +### Setting up an LP +```solidity + JITpilot.configureLp(address _lp, uint256 _hfMin, uint256 _hfDesired); ``` +To start monitoring your EulerSwap LP position, you need to call the `configureLp` function with the following parameters: -### Anvil +* `_lp`: The address of your EulerSwap LP position. +* `_hfMin`: The minimum health factor for your LP position. +* `_hfDesired`: The desired health factor for your LP position. -```shell -$ anvil +### Monitoring and rebalancing +```solidity + JITpilot.updateMetrics(address _lp); ``` +This function will update the metrics for the given LP. It will calculate the time-weighted average of the health factor and yield, and trigger a rebalance if needed, or trigger the EulerSwap reparametrization to the original state once the desired health factor is reached. -### Deploy - -```shell -$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key -``` - -### Cast - -```shell -$ cast -``` - -### Help - -```shell -$ forge --help -$ anvil --help -$ cast --help -``` +### Testing different scenarios +This repository is built on top of [euler-devland](https://github.com/euler-xyz/euler-devland), which is a tool for testing EulerSwap scenarios. You can find more information about it [here](https://github.com/euler-xyz/euler-devland). You can craft different scenarios where rebalancing could be needed and test them with JITpilot. diff --git a/public/JITpilot_output.png b/public/JITpilot_output.png new file mode 100644 index 0000000000000000000000000000000000000000..fd08986e5892bc338e7be9a594ca840196909821 GIT binary patch literal 155270 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 TY5(p71^6h)s>+l}y$tw2lV5`G literal 0 HcmV?d00001