Check PRIVATE_KEY env var first in BootstrapVWAPPhase2.s.sol, DeployBase.sol,
and BaseDeploy.sol; fall back to .secret seed-phrase file when unset.
This allows CI/CD environments to inject keys via environment variables
while preserving the existing local .secret workflow unchanged.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- docs/mainnet-bootstrap.md: fix Step 4c to use SwapRouter02 7-field
struct (no deadline field); the 8-field ABI was for SwapRouter v1 but
the address is SwapRouter02
- docs/mainnet-bootstrap.md: correct Step 1 to no longer falsely claim
that pre-bootstrap transactions succeed when Forge aborts on simulation
failure; Step 1 now reflects the try/catch behaviour added below
- docs/mainnet-bootstrap.md: Step 6 drops --private-key flag (Foundry
ignores it when vm.startBroadcast(privateKey) is called internally)
and documents that the .secret seed-phrase file must be present
- docs/mainnet-bootstrap.md: remove no-op `export LM_ADDRESS="$LM_ADDRESS"`
- docs/mainnet-bootstrap.md: cite exact line range (101-145) in
Troubleshooting workaround instead of informal marker description
- onchain/script/DeployBase.sol: wrap liquidityManager.recenter() and
seed buy in try/catch so a fresh-pool TWAP revert skips the inline
bootstrap with a warning rather than aborting the entire simulation
- onchain/script/DeployBase.sol: fix --fork-url to --rpc-url in the
post-deploy console.log hint
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add docs/mainnet-bootstrap.md with the full two-phase bootstrap
sequence: pool init, 300 s TWAP warm-up wait, first recenter + seed
buy (exact cast commands), 60 s cooldown wait, second recenter via
BootstrapVWAPPhase2.s.sol, and verification/troubleshooting steps.
Update the inline bootstrap comment in DeployBase.sol to warn that the
attempt always reverts on a fresh pool and direct operators to the new
runbook.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- DeployBase.sol: remove broken inline second recenter() (would always
revert with 'recenter cooldown' in same Forge broadcast); replace with
operator instructions to run the new BootstrapVWAPPhase2.s.sol script
at least 60 s after deployment
- BootstrapVWAPPhase2.s.sol: new script for the second VWAP bootstrap
recenter on Base mainnet deployments
- StrategyExecutor.sol: update stale docstring that still described the
removed recenterAccess bypass; reflect permissionless model with vm.warp
- TestBase.sol: remove vestigial recenterCaller parameter from all four
setupEnvironment* functions (parameter was silently ignored after
setRecenterAccess was removed); update all callers across six test files
- bootstrap-common.sh: fix misleading retry recenter in
seed_application_state() — add evm_increaseTime 61 before evm_mine so
the recenter cooldown actually clears and the retry can succeed
All 210 tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SPDX license:
- Restore GPL-3.0-or-later SPDX header to DeployBase.sol (removed by
the em-dash sed fix in an earlier commit).
SeedSwapper deduplication:
- Extract SeedSwapper into onchain/script/DeployCommon.sol — a single
canonical definition shared by both deploy scripts. This eliminates
duplicate Foundry artifacts (previously both DeployLocal.sol and
DeployBase.sol produced a SeedSwapper artifact, causing ambiguity for
verification and coverage tools).
- Remove inline SeedSwapper and redundant IWETH9 import from
DeployLocal.sol and DeployBase.sol; add `import "./DeployCommon.sol"`.
SeedSwapper hardening (in DeployCommon.sol):
- Replace magic-literal price sentinels with named constants
SQRT_PRICE_LIMIT_MIN / SQRT_PRICE_LIMIT_MAX.
- Wrap both weth.transfer() calls with require() so a non-standard
WETH9 false-return is caught rather than silently ignored.
- Add post-swap WETH sweep in executeSeedBuy(): if the price limit is
reached before the full input is spent, the residual WETH balance is
returned to `recipient` instead of being stranded in the contract.
bootstrap-common.sh:
- Normalise cumulativeVolume output through `cast to-dec` before the
string comparison, guarding against a future change in cast output
format (decimal vs hex).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Deploy scripts (DeployLocal.sol and DeployBase.sol) now execute a
seed buy + double-recenter sequence before handing control to users:
1. Temporarily grant deployer recenterAccess (via self as feeDestination)
2. Fund LM with a small amount and call recenter() -> places thin positions
3. SeedSwapper executes a small buy, generating a non-zero WETH fee
4. Second recenter() hits the cumulativeVolume==0 bootstrap path with
ethFee>0 -> _recordVolumeAndPrice fires -> cumulativeVolume>0
5. Revoke recenterAccess and restore the real feeDestination
After deployment, cumulativeVolume>0, so the bootstrap path is
unreachable by external users and cannot be front-run by an attacker
inflating the initial VWAP anchor with a whale buy.
Also adds:
- tools/deploy-optimizer.sh: verification step checks cumulativeVolume>0
after a fresh local deployment
- test_vwapBootstrappedBySeedTrade() in VWAPFloorProtection.t.sol:
confirms the deploy sequence (recenter + buy + recenter) leaves
cumulativeVolume>0 and getVWAP()>0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OptimizerV3Push3 is an equivalence-proof contract with only isBullMarket().
It cannot serve as an ERC1967Proxy implementation because it has no initialize()
or getLiquidityParams(). The CI bootstrap was failing because the proxy
deployment reverted when calling initialize() on the Push3 implementation.
Switch deploy scripts to Optimizer.sol (the base UUPS contract) which has the
full interface required by ERC1967Proxy and LiquidityManager.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>