fix: fix: Fitness metric should measure ETH only, not token value (#670)
Replace _positionEthValue() with _positionEthOnly() in FitnessEvaluator.t.sol. The new function returns only the WETH component of each position (amount0 if token0isWeth, else amount1), ignoring KRK token value entirely. This prevents evolution from gaming the fitness metric by inflating KRK price through position placement — the score now reflects actual ETH reserves only. Also removes the now-unused FullMath import. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3f435f8459
commit
defa1bfb6c
1 changed files with 10 additions and 24 deletions
|
|
@ -43,7 +43,6 @@ import { UUPSUpgradeable } from "@openzeppelin/proxy/utils/UUPSUpgradeable.sol";
|
||||||
import { IERC20 } from "@openzeppelin/token/ERC20/IERC20.sol";
|
import { IERC20 } from "@openzeppelin/token/ERC20/IERC20.sol";
|
||||||
import { IUniswapV3Factory } from "@uniswap-v3-core/interfaces/IUniswapV3Factory.sol";
|
import { IUniswapV3Factory } from "@uniswap-v3-core/interfaces/IUniswapV3Factory.sol";
|
||||||
import { IUniswapV3Pool } from "@uniswap-v3-core/interfaces/IUniswapV3Pool.sol";
|
import { IUniswapV3Pool } from "@uniswap-v3-core/interfaces/IUniswapV3Pool.sol";
|
||||||
import { FullMath } from "@aperture/uni-v3-lib/FullMath.sol";
|
|
||||||
import { LiquidityAmounts } from "@aperture/uni-v3-lib/LiquidityAmounts.sol";
|
import { LiquidityAmounts } from "@aperture/uni-v3-lib/LiquidityAmounts.sol";
|
||||||
import { TickMath } from "@aperture/uni-v3-lib/TickMath.sol";
|
import { TickMath } from "@aperture/uni-v3-lib/TickMath.sol";
|
||||||
import { UniswapHelpers } from "../src/helpers/UniswapHelpers.sol";
|
import { UniswapHelpers } from "../src/helpers/UniswapHelpers.sol";
|
||||||
|
|
@ -561,8 +560,9 @@ contract FitnessEvaluator is Test {
|
||||||
// ─── Score computation ────────────────────────────────────────────────────
|
// ─── Score computation ────────────────────────────────────────────────────
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice Compute lm_eth_total = free ETH + free WETH + sum(position ETH values).
|
* @notice Compute lm_eth_total = free ETH + free WETH + sum(WETH in each position).
|
||||||
* Mirrors AttackRunner._logSnapshot's lm_eth_total calculation.
|
* Only counts real ETH reserves — KRK token value is excluded to prevent
|
||||||
|
* evolution from gaming the metric by inflating token price through positioning.
|
||||||
*/
|
*/
|
||||||
function _computeLmEthTotal() internal view returns (uint256) {
|
function _computeLmEthTotal() internal view returns (uint256) {
|
||||||
(uint160 sqrtPriceX96,,,,,,) = pool.slot0();
|
(uint160 sqrtPriceX96,,,,,,) = pool.slot0();
|
||||||
|
|
@ -576,16 +576,16 @@ contract FitnessEvaluator is Test {
|
||||||
|
|
||||||
return lmEthFree
|
return lmEthFree
|
||||||
+ lmWethFree
|
+ lmWethFree
|
||||||
+ _positionEthValue(sqrtPriceX96, fLo, fHi, fLiq)
|
+ _positionEthOnly(sqrtPriceX96, fLo, fHi, fLiq)
|
||||||
+ _positionEthValue(sqrtPriceX96, aLo, aHi, aLiq)
|
+ _positionEthOnly(sqrtPriceX96, aLo, aHi, aLiq)
|
||||||
+ _positionEthValue(sqrtPriceX96, dLo, dHi, dLiq);
|
+ _positionEthOnly(sqrtPriceX96, dLo, dHi, dLiq);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice ETH-equivalent value of a Uniswap V3 position at the current price.
|
* @notice WETH-only component of a Uniswap V3 position at the current price.
|
||||||
* Copied verbatim from AttackRunner._positionEthValue.
|
* Ignores KRK token value entirely — counts only the actual ETH backing.
|
||||||
*/
|
*/
|
||||||
function _positionEthValue(
|
function _positionEthOnly(
|
||||||
uint160 sqrtPriceX96,
|
uint160 sqrtPriceX96,
|
||||||
int24 tickLower,
|
int24 tickLower,
|
||||||
int24 tickUpper,
|
int24 tickUpper,
|
||||||
|
|
@ -601,21 +601,7 @@ contract FitnessEvaluator is Test {
|
||||||
(uint256 amount0, uint256 amount1) =
|
(uint256 amount0, uint256 amount1) =
|
||||||
LiquidityAmounts.getAmountsForLiquidity(sqrtPriceX96, sqrtRatioAX96, sqrtRatioBX96, liquidity);
|
LiquidityAmounts.getAmountsForLiquidity(sqrtPriceX96, sqrtRatioAX96, sqrtRatioBX96, liquidity);
|
||||||
|
|
||||||
uint256 ethAmount = token0isWeth ? amount0 : amount1;
|
return token0isWeth ? amount0 : amount1;
|
||||||
uint256 krkAmount = token0isWeth ? amount1 : amount0;
|
|
||||||
|
|
||||||
if (krkAmount == 0 || sqrtPriceX96 == 0) return ethAmount;
|
|
||||||
|
|
||||||
uint256 krkInEth;
|
|
||||||
if (token0isWeth) {
|
|
||||||
// token0=WETH, token1=KRK: 1 KRK = 2^192 / sqrtP^2 WETH
|
|
||||||
krkInEth = FullMath.mulDiv(FullMath.mulDiv(krkAmount, 1 << 96, sqrtPriceX96), 1 << 96, sqrtPriceX96);
|
|
||||||
} else {
|
|
||||||
// token0=KRK, token1=WETH: 1 KRK = sqrtP^2 / 2^192 WETH
|
|
||||||
krkInEth = FullMath.mulDiv(FullMath.mulDiv(krkAmount, sqrtPriceX96, 1 << 96), sqrtPriceX96, 1 << 96);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ethAmount + krkInEth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Utilities ────────────────────────────────────────────────────────────
|
// ─── Utilities ────────────────────────────────────────────────────────────
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue