fix: Red-team: replace ethPerToken with exact total-LM-ETH metric (#539)
Replace the ethPerToken metric (free balance / adjusted supply) with total LM ETH (free + WETH + position-locked) using a forge script with exact Uni V3 integer math. Collapses 4+ RPC calls and Python float approximation into a single forge script call using LiquidityAmounts + TickMath. Also updates red-team prompt, report format, memory extraction, and adds roadmap items for #536-#538 (backtesting pipeline, Push3 evolution). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9832b454df
commit
0ddc1ccd80
3 changed files with 242 additions and 100 deletions
59
onchain/script/LmTotalEth.s.sol
Normal file
59
onchain/script/LmTotalEth.s.sol
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "@uniswap-v3-core/interfaces/IUniswapV3Factory.sol";
|
||||
import "@uniswap-v3-core/interfaces/IUniswapV3Pool.sol";
|
||||
import "forge-std/Script.sol";
|
||||
|
||||
import "uni-v3-lib/LiquidityAmounts.sol";
|
||||
import "uni-v3-lib/TickMath.sol";
|
||||
|
||||
interface ILM {
|
||||
function positions(uint8 stage) external view returns (uint128 liquidity, int24 tickLower, int24 tickUpper);
|
||||
}
|
||||
|
||||
interface IWETH {
|
||||
function balanceOf(address) external view returns (uint256);
|
||||
}
|
||||
|
||||
/// @title LmTotalEth
|
||||
/// @notice Read-only script: prints total ETH controlled by LiquidityManager
|
||||
/// (free ETH + free WETH + ETH locked in all 3 Uni V3 positions).
|
||||
/// @dev forge script script/LmTotalEth.s.sol --rpc-url $RPC_URL
|
||||
/// Env: LM, WETH, POOL
|
||||
contract LmTotalEth is Script {
|
||||
function run() external view {
|
||||
address lm = vm.envAddress("LM");
|
||||
address weth = vm.envAddress("WETH");
|
||||
address pool = vm.envAddress("POOL");
|
||||
|
||||
// Free balances
|
||||
uint256 freeEth = lm.balance;
|
||||
uint256 freeWeth = IWETH(weth).balanceOf(lm);
|
||||
|
||||
// Current sqrtPrice from pool
|
||||
(uint160 sqrtPriceX96,,,,,,) = IUniswapV3Pool(pool).slot0();
|
||||
|
||||
// Determine which token is WETH (token0 or token1)
|
||||
bool wethIsToken0 = IUniswapV3Pool(pool).token0() == weth;
|
||||
|
||||
// Sum ETH in all 3 positions: FLOOR=0, ANCHOR=1, DISCOVERY=2
|
||||
uint256 positionEth = 0;
|
||||
for (uint8 stage = 0; stage < 3; stage++) {
|
||||
(uint128 liquidity, int24 tickLower, int24 tickUpper) = ILM(lm).positions(stage);
|
||||
if (liquidity == 0) continue;
|
||||
|
||||
uint160 sqrtA = TickMath.getSqrtRatioAtTick(tickLower);
|
||||
uint160 sqrtB = TickMath.getSqrtRatioAtTick(tickUpper);
|
||||
|
||||
(uint256 amount0, uint256 amount1) = LiquidityAmounts.getAmountsForLiquidity(sqrtPriceX96, sqrtA, sqrtB, liquidity);
|
||||
|
||||
positionEth += wethIsToken0 ? amount0 : amount1;
|
||||
}
|
||||
|
||||
uint256 total = freeEth + freeWeth + positionEth;
|
||||
|
||||
// Output as plain number for easy bash consumption
|
||||
console2.log(total);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue