fix: No recovery path if VWAP bootstrap fails mid-sequence (#644)

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>
This commit is contained in:
openhands 2026-03-19 22:24:05 +00:00
parent 9cfffa5cea
commit fbe8384342
5 changed files with 291 additions and 0 deletions

View file

@ -234,6 +234,72 @@ cast balance $LM_ADDRESS --rpc-url $BASE_RPC
---
## Recovery from failed mid-sequence bootstrap
If the bootstrap fails partway through (e.g., the second `recenter()` in Step 6 reverts due to insufficient price movement / "amplitude not reached"), the LiquidityManager is left in a partially bootstrapped state:
- **Positions deployed** — the first `recenter()` placed anchor, floor, and discovery positions
- **`cumulativeVolume == 0`** — the VWAP anchor was never recorded
- **`feeDestination` set** — `DeployBase.sol` sets this before any recenter attempt
- **`recenter()` is permissionless** — no access control to revoke; anyone can call it
### Diagnosing the state
```bash
# Check if VWAP bootstrap completed (0 = not yet bootstrapped)
cast call $LM_ADDRESS "cumulativeVolume()(uint256)" --rpc-url $BASE_RPC
# Check current feeDestination
cast call $LM_ADDRESS "feeDestination()(address)" --rpc-url $BASE_RPC
# Check if feeDestination is locked (true = cannot be changed)
cast call $LM_ADDRESS "feeDestinationLocked()(bool)" --rpc-url $BASE_RPC
# Check if positions exist (non-zero liquidity = positions deployed)
cast call $LM_ADDRESS "positions(uint256)(int24,int24,uint128)" 1 --rpc-url $BASE_RPC
```
### Recovery steps
1. **Identify the failure cause** — check the revert reason from Step 6. Common causes:
- `"amplitude not reached."` — the seed buy did not move the price enough ticks for `recenter()` to accept the movement as significant
- `"price deviated from oracle"` — TWAP history is still insufficient
- `"recenter cooldown"` — 60 s has not elapsed since the last recenter
2. **Fix the root cause:**
- For amplitude issues: execute a larger seed buy (Step 4 with more ETH) to generate more price movement and anchor fees
- For TWAP issues: wait longer for oracle history to accumulate
- For cooldown: simply wait 60 s
3. **Retry the second recenter** — re-run Step 6 (`BootstrapVWAPPhase2.s.sol`) or call `recenter()` directly:
```bash
cast send $LM_ADDRESS "recenter()" --rpc-url $BASE_RPC --private-key $DEPLOYER_KEY
```
4. **Verify** — confirm `cumulativeVolume > 0` (Step 7)
5. **If `feeDestination` needs correction** (e.g., was never set or was set to the wrong address):
```bash
# Only works if feeDestinationLocked is false
cast send $LM_ADDRESS \
"setFeeDestination(address)" <CORRECT_FEE_DEST_ADDRESS> \
--rpc-url $BASE_RPC \
--private-key $DEPLOYER_KEY
```
### Automated recovery
A helper script automates the diagnosis and retry:
```bash
# Diagnose and retry bootstrap
scripts/recover-bootstrap.sh --rpc-url $BASE_RPC --private-key $DEPLOYER_KEY --lm $LM_ADDRESS
```
See `scripts/recover-bootstrap.sh --help` for all options.
---
## Troubleshooting
### `forge script` aborts before broadcast due to recenter() revert