2026-02-21 07:48:43 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
pragma solidity ^0.8.19;
|
|
|
|
|
|
2026-03-10 23:13:57 +00:00
|
|
|
import {OptimizerInput} from "./IOptimizer.sol";
|
|
|
|
|
|
2026-02-21 07:48:43 +00:00
|
|
|
/**
|
|
|
|
|
* @title OptimizerV3Push3
|
|
|
|
|
* @notice Auto-generated from optimizer_v3.push3 via Push3→Solidity transpiler.
|
2026-03-10 23:13:57 +00:00
|
|
|
* Implements calculateParams with 8 dyadic rational inputs and 4 outputs.
|
2026-02-21 07:48:43 +00:00
|
|
|
*/
|
|
|
|
|
contract OptimizerV3Push3 {
|
|
|
|
|
/**
|
2026-03-10 23:13:57 +00:00
|
|
|
* @notice Compute liquidity parameters from 8 dyadic rational inputs.
|
|
|
|
|
* @param inputs 8-slot dyadic rational array: slot 0 = percentageStaked (top of Push3 stack),
|
|
|
|
|
* slot 1 = averageTaxRate, slots 2-7 = extended metrics (0 if unavailable).
|
|
|
|
|
* @return ci Capital inefficiency (0..1e18).
|
|
|
|
|
* @return anchorShare Fraction of non-floor ETH in anchor (0..1e18).
|
|
|
|
|
* @return anchorWidth Anchor position width in tick units.
|
|
|
|
|
* @return discoveryDepth Discovery liquidity density (0..1e18).
|
2026-02-21 07:48:43 +00:00
|
|
|
*/
|
2026-03-10 23:13:57 +00:00
|
|
|
function calculateParams(OptimizerInput[8] memory inputs)
|
|
|
|
|
public
|
|
|
|
|
pure
|
|
|
|
|
returns (uint256 ci, uint256 anchorShare, uint24 anchorWidth, uint256 discoveryDepth)
|
|
|
|
|
{
|
|
|
|
|
// Validate mantissa for percentageStaked
|
|
|
|
|
require(inputs[0].mantissa <= 1e18, "mantissa overflow");
|
|
|
|
|
|
|
|
|
|
// Validate that shift is 0 (future-only field, not yet supported)
|
|
|
|
|
for (uint256 k = 0; k < 8; k++) {
|
|
|
|
|
require(inputs[k].shift == 0, "shift not yet supported");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Decode dyadic rational inputs (mantissa * 2^(-shift); shift=0 for current inputs)
|
|
|
|
|
uint256 _d0 = uint256(inputs[0].mantissa);
|
|
|
|
|
uint256 _d1 = uint256(inputs[1].mantissa);
|
|
|
|
|
/* _d2 = uint256(inputs[2].mantissa); */
|
|
|
|
|
// Available but not used in current implementation
|
|
|
|
|
/* _d3 = uint256(inputs[3].mantissa); */
|
|
|
|
|
// Available but not used in current implementation
|
|
|
|
|
/* _d4 = uint256(inputs[4].mantissa); */
|
|
|
|
|
// Available but not used in current implementation
|
|
|
|
|
/* _d5 = uint256(inputs[5].mantissa); */
|
|
|
|
|
// Available but not used in current implementation
|
|
|
|
|
/* _d6 = uint256(inputs[6].mantissa); */
|
|
|
|
|
// Available but not used in current implementation
|
|
|
|
|
/* _d7 = uint256(inputs[7].mantissa); */
|
|
|
|
|
// Available but not used in current implementation
|
|
|
|
|
uint256 rawpct = uint256(_d0);
|
|
|
|
|
uint256 taxrate = uint256(_d1);
|
|
|
|
|
uint256 staked = uint256(((rawpct * 100) / 1000000000000000000));
|
2026-02-21 07:48:43 +00:00
|
|
|
bool b33;
|
|
|
|
|
if ((staked > 91)) {
|
|
|
|
|
uint256 deltas = uint256((100 - staked));
|
|
|
|
|
uint256 r28;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 206185567010309)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r28 = uint256(0);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r27;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 412371134020618)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r27 = uint256(1);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r26;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 618556701030927)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r26 = uint256(2);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r25;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 1030927835051546)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r25 = uint256(3);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r24;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 1546391752577319)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r24 = uint256(4);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r23;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 2164948453608247)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r23 = uint256(5);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r22;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 2783505154639175)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r22 = uint256(6);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r21;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 3608247422680412)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r21 = uint256(7);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r20;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 4639175257731958)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r20 = uint256(8);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r19;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 5670103092783505)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r19 = uint256(9);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r18;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 7216494845360824)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r18 = uint256(10);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r17;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 9278350515463917)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r17 = uint256(11);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r16;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 11855670103092783)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r16 = uint256(12);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r15;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 15979381443298969)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r15 = uint256(13);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r14;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 22164948453608247)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r14 = uint256(14);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r13;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 29381443298969072)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r13 = uint256(15);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r12;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 38144329896907216)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r12 = uint256(16);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r11;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 49484536082474226)) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r11 = uint256(17);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r10;
|
2026-03-10 23:13:57 +00:00
|
|
|
if ((taxrate <= 63917525773195876))
|
|
|
|
|
{
|
2026-02-21 07:48:43 +00:00
|
|
|
r10 = uint256(18);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r9;
|
2026-03-10 23:13:57 +00:00
|
|
|
if (
|
|
|
|
|
(
|
|
|
|
|
taxrate
|
|
|
|
|
<= 83505154639175257
|
|
|
|
|
)
|
|
|
|
|
) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r9 = uint256(19);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r8;
|
2026-03-10 23:13:57 +00:00
|
|
|
if (
|
|
|
|
|
(
|
|
|
|
|
taxrate
|
|
|
|
|
<=
|
|
|
|
|
109278350515463917
|
|
|
|
|
)
|
|
|
|
|
) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r8 = uint256(20);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r7;
|
2026-03-10 23:13:57 +00:00
|
|
|
if (
|
|
|
|
|
(
|
|
|
|
|
taxrate
|
|
|
|
|
<=
|
|
|
|
|
144329896907216494
|
|
|
|
|
)
|
|
|
|
|
) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r7 = uint256(21);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r6;
|
2026-03-10 23:13:57 +00:00
|
|
|
if (
|
|
|
|
|
(
|
|
|
|
|
taxrate
|
|
|
|
|
<=
|
|
|
|
|
185567010309278350
|
|
|
|
|
)
|
|
|
|
|
) {
|
2026-02-21 07:48:43 +00:00
|
|
|
r6 = uint256(22);
|
|
|
|
|
} else {
|
|
|
|
|
uint256 r5;
|
2026-03-10 23:13:57 +00:00
|
|
|
if (
|
|
|
|
|
(
|
|
|
|
|
taxrate
|
|
|
|
|
<=
|
|
|
|
|
237113402061855670
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
r5 = uint256(
|
|
|
|
|
23
|
|
|
|
|
);
|
2026-02-21 07:48:43 +00:00
|
|
|
} else {
|
|
|
|
|
uint256 r4;
|
2026-03-10 23:13:57 +00:00
|
|
|
if (
|
|
|
|
|
(
|
|
|
|
|
taxrate
|
|
|
|
|
<=
|
|
|
|
|
309278350515463917
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
r4 =
|
|
|
|
|
uint256(
|
|
|
|
|
24
|
|
|
|
|
);
|
2026-02-21 07:48:43 +00:00
|
|
|
} else {
|
2026-03-10 23:13:57 +00:00
|
|
|
uint256
|
|
|
|
|
r3;
|
|
|
|
|
if (
|
|
|
|
|
(
|
|
|
|
|
taxrate
|
|
|
|
|
<=
|
|
|
|
|
402061855670103092
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
r3 =
|
|
|
|
|
uint256(
|
|
|
|
|
25
|
|
|
|
|
);
|
2026-02-21 07:48:43 +00:00
|
|
|
} else {
|
2026-03-10 23:13:57 +00:00
|
|
|
uint256
|
|
|
|
|
r2;
|
|
|
|
|
if (
|
|
|
|
|
(
|
|
|
|
|
taxrate
|
|
|
|
|
<=
|
|
|
|
|
520618556701030927
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
r2
|
|
|
|
|
=
|
|
|
|
|
uint256(
|
|
|
|
|
26
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uint256
|
|
|
|
|
r1;
|
fix: Backtesting #5: Position tracking + P&L metrics (#319)
- Add PositionTracker.sol: tracks position lifecycle (open/close per
recenter), records tick ranges, liquidity, entry/exit blocks/timestamps,
token amounts (via LiquidityAmounts math), fees (proportional to
liquidity share), IL (LP exit value − HODL value at exit price), and
net P&L per position. Aggregates total fees, cumulative IL, net P&L,
rebalance count, Anchor time-in-range, and capital efficiency accumulators.
Logs with [TRACKER][TYPE] prefix; emits cumulative P&L every 500 blocks.
- Modify StrategyExecutor.sol: add IUniswapV3Pool + token0isWeth to
constructor (creates PositionTracker internally), call
tracker.notifyBlock() on every block for time-in-range, and call
tracker.recordRecenter() on each successful recenter. logSummary()
now delegates to tracker.logFinalSummary().
- Modify BacktestRunner.s.sol: pass sp.pool and token0isWeth to
StrategyExecutor constructor; log tracker address.
- forge fmt: reformat all backtesting scripts and affected src/test files
to project style (number_underscore=thousands, multiline_func_header=all).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 11:23:18 +00:00
|
|
|
if (
|
2026-03-10 23:13:57 +00:00
|
|
|
(
|
|
|
|
|
taxrate
|
|
|
|
|
<=
|
|
|
|
|
680412371134020618
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
r1
|
|
|
|
|
=
|
|
|
|
|
uint256(
|
|
|
|
|
27
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uint256
|
|
|
|
|
r0;
|
fix: Backtesting #5: Position tracking + P&L metrics (#319)
- Add PositionTracker.sol: tracks position lifecycle (open/close per
recenter), records tick ranges, liquidity, entry/exit blocks/timestamps,
token amounts (via LiquidityAmounts math), fees (proportional to
liquidity share), IL (LP exit value − HODL value at exit price), and
net P&L per position. Aggregates total fees, cumulative IL, net P&L,
rebalance count, Anchor time-in-range, and capital efficiency accumulators.
Logs with [TRACKER][TYPE] prefix; emits cumulative P&L every 500 blocks.
- Modify StrategyExecutor.sol: add IUniswapV3Pool + token0isWeth to
constructor (creates PositionTracker internally), call
tracker.notifyBlock() on every block for time-in-range, and call
tracker.recordRecenter() on each successful recenter. logSummary()
now delegates to tracker.logFinalSummary().
- Modify BacktestRunner.s.sol: pass sp.pool and token0isWeth to
StrategyExecutor constructor; log tracker address.
- forge fmt: reformat all backtesting scripts and affected src/test files
to project style (number_underscore=thousands, multiline_func_header=all).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 11:23:18 +00:00
|
|
|
if (
|
|
|
|
|
(
|
|
|
|
|
taxrate
|
2026-03-10 23:13:57 +00:00
|
|
|
<=
|
|
|
|
|
886597938144329896
|
fix: Backtesting #5: Position tracking + P&L metrics (#319)
- Add PositionTracker.sol: tracks position lifecycle (open/close per
recenter), records tick ranges, liquidity, entry/exit blocks/timestamps,
token amounts (via LiquidityAmounts math), fees (proportional to
liquidity share), IL (LP exit value − HODL value at exit price), and
net P&L per position. Aggregates total fees, cumulative IL, net P&L,
rebalance count, Anchor time-in-range, and capital efficiency accumulators.
Logs with [TRACKER][TYPE] prefix; emits cumulative P&L every 500 blocks.
- Modify StrategyExecutor.sol: add IUniswapV3Pool + token0isWeth to
constructor (creates PositionTracker internally), call
tracker.notifyBlock() on every block for time-in-range, and call
tracker.recordRecenter() on each successful recenter. logSummary()
now delegates to tracker.logFinalSummary().
- Modify BacktestRunner.s.sol: pass sp.pool and token0isWeth to
StrategyExecutor constructor; log tracker address.
- forge fmt: reformat all backtesting scripts and affected src/test files
to project style (number_underscore=thousands, multiline_func_header=all).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 11:23:18 +00:00
|
|
|
)
|
2026-03-10 23:13:57 +00:00
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
r0
|
|
|
|
|
=
|
|
|
|
|
uint256(
|
|
|
|
|
28
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
r0
|
|
|
|
|
=
|
|
|
|
|
uint256(
|
|
|
|
|
29
|
|
|
|
|
);
|
2026-02-21 07:48:43 +00:00
|
|
|
}
|
2026-03-10 23:13:57 +00:00
|
|
|
r1
|
|
|
|
|
=
|
|
|
|
|
uint256(
|
|
|
|
|
r0
|
|
|
|
|
);
|
2026-02-21 07:48:43 +00:00
|
|
|
}
|
2026-03-10 23:13:57 +00:00
|
|
|
r2
|
|
|
|
|
=
|
|
|
|
|
uint256(
|
|
|
|
|
r1
|
|
|
|
|
);
|
2026-02-21 07:48:43 +00:00
|
|
|
}
|
2026-03-10 23:13:57 +00:00
|
|
|
r3 =
|
|
|
|
|
uint256(
|
|
|
|
|
r2
|
|
|
|
|
);
|
2026-02-21 07:48:43 +00:00
|
|
|
}
|
2026-03-10 23:13:57 +00:00
|
|
|
r4 =
|
|
|
|
|
uint256(
|
|
|
|
|
r3
|
|
|
|
|
);
|
2026-02-21 07:48:43 +00:00
|
|
|
}
|
2026-03-10 23:13:57 +00:00
|
|
|
r5 = uint256(
|
|
|
|
|
r4
|
|
|
|
|
);
|
2026-02-21 07:48:43 +00:00
|
|
|
}
|
|
|
|
|
r6 = uint256(r5);
|
|
|
|
|
}
|
|
|
|
|
r7 = uint256(r6);
|
|
|
|
|
}
|
|
|
|
|
r8 = uint256(r7);
|
|
|
|
|
}
|
|
|
|
|
r9 = uint256(r8);
|
|
|
|
|
}
|
|
|
|
|
r10 = uint256(r9);
|
|
|
|
|
}
|
|
|
|
|
r11 = uint256(r10);
|
|
|
|
|
}
|
|
|
|
|
r12 = uint256(r11);
|
|
|
|
|
}
|
|
|
|
|
r13 = uint256(r12);
|
|
|
|
|
}
|
|
|
|
|
r14 = uint256(r13);
|
|
|
|
|
}
|
|
|
|
|
r15 = uint256(r14);
|
|
|
|
|
}
|
|
|
|
|
r16 = uint256(r15);
|
|
|
|
|
}
|
|
|
|
|
r17 = uint256(r16);
|
|
|
|
|
}
|
|
|
|
|
r18 = uint256(r17);
|
|
|
|
|
}
|
|
|
|
|
r19 = uint256(r18);
|
|
|
|
|
}
|
|
|
|
|
r20 = uint256(r19);
|
|
|
|
|
}
|
|
|
|
|
r21 = uint256(r20);
|
|
|
|
|
}
|
|
|
|
|
r22 = uint256(r21);
|
|
|
|
|
}
|
|
|
|
|
r23 = uint256(r22);
|
|
|
|
|
}
|
|
|
|
|
r24 = uint256(r23);
|
|
|
|
|
}
|
|
|
|
|
r25 = uint256(r24);
|
|
|
|
|
}
|
|
|
|
|
r26 = uint256(r25);
|
|
|
|
|
}
|
|
|
|
|
r27 = uint256(r26);
|
|
|
|
|
}
|
|
|
|
|
r28 = uint256(r27);
|
|
|
|
|
}
|
|
|
|
|
uint256 dup29 = uint256(r28);
|
|
|
|
|
uint256 r32;
|
|
|
|
|
if ((dup29 >= 14)) {
|
|
|
|
|
uint256 dup30 = uint256((dup29 + 1));
|
|
|
|
|
uint256 r31;
|
|
|
|
|
if ((dup30 > 29)) {
|
|
|
|
|
r31 = uint256(29);
|
|
|
|
|
} else {
|
|
|
|
|
r31 = uint256(dup30);
|
|
|
|
|
}
|
|
|
|
|
r32 = uint256(r31);
|
|
|
|
|
} else {
|
|
|
|
|
r32 = uint256(dup29);
|
|
|
|
|
}
|
|
|
|
|
uint256 effidx = uint256(r32);
|
|
|
|
|
b33 = (((((deltas * deltas) * deltas) * effidx) / 20) < 50);
|
|
|
|
|
} else {
|
|
|
|
|
b33 = false;
|
|
|
|
|
}
|
2026-03-10 23:13:57 +00:00
|
|
|
uint256 r34;
|
|
|
|
|
uint256 r35;
|
|
|
|
|
uint256 r36;
|
|
|
|
|
uint256 r37;
|
|
|
|
|
if (b33) {
|
|
|
|
|
r34 = uint256(1000000000000000000);
|
|
|
|
|
r35 = uint256(20);
|
|
|
|
|
r36 = uint256(1000000000000000000);
|
|
|
|
|
r37 = uint256(0);
|
|
|
|
|
} else {
|
|
|
|
|
r34 = uint256(300000000000000000);
|
|
|
|
|
r35 = uint256(100);
|
|
|
|
|
r36 = uint256(300000000000000000);
|
|
|
|
|
r37 = uint256(0);
|
|
|
|
|
}
|
|
|
|
|
ci = uint256(r37);
|
|
|
|
|
anchorShare = uint256(r36);
|
|
|
|
|
anchorWidth = uint24(r35);
|
|
|
|
|
discoveryDepth = uint256(r34);
|
2026-02-21 07:48:43 +00:00
|
|
|
}
|
|
|
|
|
}
|