Add recovery procedure documentation and automated recovery script for when the VWAP bootstrap fails partway through (e.g. second recenter reverts due to insufficient price movement). - Add "Recovery from failed mid-sequence bootstrap" section to docs/mainnet-bootstrap.md with diagnosis steps and manual recovery - Create scripts/recover-bootstrap.sh to automate diagnosis and retry - Add warning comments in BootstrapVWAPPhase2.s.sol, DeployBase.sol, and bootstrap-common.sh referencing the recovery procedure Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
64 lines
2.6 KiB
Solidity
64 lines
2.6 KiB
Solidity
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
pragma solidity ^0.8.19;
|
|
|
|
import { LiquidityManager } from "../src/LiquidityManager.sol";
|
|
import "forge-std/Script.sol";
|
|
|
|
/**
|
|
* @title BootstrapVWAPPhase2
|
|
* @notice Second phase of the VWAP bootstrap for Base mainnet deployments.
|
|
*
|
|
* Run this script >= 60 seconds after DeployBase (or DeployBaseMainnet/DeployBaseSepolia)
|
|
* finishes. The first recenter() sets lastRecenterTime; the 60-second cooldown must
|
|
* elapse before this second recenter() can succeed.
|
|
*
|
|
* What this does:
|
|
* - Calls liquidityManager.recenter() a second time.
|
|
* - At this point cumulativeVolume == 0 (bootstrap path) and the seed buy has
|
|
* generated ethFee > 0, so recenter() records the VWAP anchor.
|
|
* - Asserts cumulativeVolume > 0 to confirm bootstrap success.
|
|
*
|
|
* WARNING: If this script reverts (e.g. "amplitude not reached" due to
|
|
* insufficient price movement from the seed buy), the LiquidityManager is
|
|
* left in a partially bootstrapped state with positions deployed but
|
|
* cumulativeVolume == 0. See docs/mainnet-bootstrap.md "Recovery from
|
|
* failed mid-sequence bootstrap" for the recovery procedure, or run
|
|
* scripts/recover-bootstrap.sh to diagnose and retry automatically.
|
|
*
|
|
* Usage:
|
|
* export LM_ADDRESS=<deployed LiquidityManager address>
|
|
*
|
|
* # Option A — env-var key (CI/CD):
|
|
* export PRIVATE_KEY=0x<hex-private-key>
|
|
* forge script script/BootstrapVWAPPhase2.s.sol --tc BootstrapVWAPPhase2 \
|
|
* --fork-url $BASE_RPC --broadcast
|
|
*
|
|
* # Option B — .secret seed-phrase file (local):
|
|
* echo "<seed phrase>" > .secret
|
|
* forge script script/BootstrapVWAPPhase2.s.sol --tc BootstrapVWAPPhase2 \
|
|
* --fork-url $BASE_RPC --broadcast
|
|
*/
|
|
contract BootstrapVWAPPhase2 is Script {
|
|
function run() public {
|
|
address lmAddress = vm.envAddress("LM_ADDRESS");
|
|
LiquidityManager lm = LiquidityManager(payable(lmAddress));
|
|
|
|
// PRIVATE_KEY=0 / empty silently falls back to .secret (0 is an invalid secp256k1 key).
|
|
uint256 privateKey = vm.envOr("PRIVATE_KEY", uint256(0));
|
|
if (privateKey == 0) {
|
|
string memory seedPhrase = vm.readFile(".secret");
|
|
privateKey = vm.deriveKey(seedPhrase, 0);
|
|
}
|
|
vm.startBroadcast(privateKey);
|
|
|
|
console.log("Running VWAP bootstrap phase 2 on LiquidityManager:", lmAddress);
|
|
|
|
lm.recenter();
|
|
|
|
uint256 cumVol = lm.cumulativeVolume();
|
|
require(cumVol > 0, "VWAP bootstrap failed: cumulativeVolume is still 0");
|
|
console.log("VWAP bootstrapped successfully. cumulativeVolume:", cumVol);
|
|
|
|
vm.stopBroadcast();
|
|
}
|
|
}
|