fix: Backtesting #3: Replay historical Swap/Mint/Burn events against shadow pool (#317)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
openhands 2026-02-27 06:12:03 +00:00
parent 00037dc713
commit 896fffb2e8
2 changed files with 378 additions and 1 deletions

View file

@ -5,11 +5,13 @@ import { Script } from "forge-std/Script.sol";
import { console2 } from "forge-std/console2.sol";
import { MockToken } from "./MockToken.sol";
import { ShadowPool, ShadowPoolDeployer } from "./ShadowPoolDeployer.sol";
import { EventReplayer } from "./EventReplayer.sol";
/**
* @title BacktestRunner
* @notice Entry point for backtesting. Deploys a UniswapV3 shadow pool that mirrors the
* AERO/WETH 1% pool configuration, initialised at the price from the event cache.
* AERO/WETH 1% pool configuration, initialised at the price from the event cache,
* then replays all Swap/Mint/Burn events from the cache against the shadow pool.
*
* Usage:
* forge script script/backtesting/BacktestRunner.s.sol \
@ -86,6 +88,9 @@ contract BacktestRunner is Script {
// Deploy factory + pool and initialise at the resolved price.
ShadowPool memory sp = ShadowPoolDeployer.deploy(address(tokenA), address(tokenB), sqrtPriceX96);
// Deploy the event replayer with the canonical token ordering from the pool.
EventReplayer replayer = new EventReplayer(sp.pool, MockToken(sp.token0), MockToken(sp.token1));
vm.stopBroadcast();
// Query pool state (view calls, no broadcast needed).
@ -98,10 +103,24 @@ contract BacktestRunner is Script {
console2.log("Pool: ", address(sp.pool));
console2.log("Token0: ", sp.token0);
console2.log("Token1: ", sp.token1);
console2.log("Replayer: ", address(replayer));
console2.log("Fee tier: ", uint256(ShadowPoolDeployer.SHADOW_FEE));
console2.log("Tick spacing: ", int256(tickSpacing));
console2.log("sqrtPriceX96: ", uint256(slot0SqrtPrice));
console2.log("Initial tick: ", int256(tick));
console2.log("Liquidity: ", uint256(liquidity));
// -----------------------------------------------------------------------
// Event replay (runs as local simulation no broadcast required).
// Each pool.mint / pool.swap / pool.burn call executes against the shadow
// pool; vm.roll + vm.warp advance block state to match historical timing.
// -----------------------------------------------------------------------
try vm.envString("BACKTEST_EVENTS_FILE") returns (string memory eventsFile) {
if (bytes(eventsFile).length > 0) {
console2.log("\n=== Starting Event Replay ===");
console2.log("Events file: ", eventsFile);
replayer.replay(eventsFile);
}
} catch {}
}
}