Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
bb6fb7d
feat: cbETH/WETH LP bootstrap — proposal 014 + backend handbook
anajuliabit Aug 21, 2026
6aae0e4
docs: tighten the LP balancer backend handbook
anajuliabit Aug 21, 2026
ced701f
docs: re-measure venue economics, flip the stake conclusion
anajuliabit Aug 21, 2026
97bc330
docs: drop yield projections from the handbook
anajuliabit Aug 21, 2026
c2a6819
chore: drop .markdownlint-cli2.yaml
anajuliabit Aug 21, 2026
030c351
feat: fold the total-allocation parameter into proposal 011 (WETH/cbBTC)
anajuliabit Aug 24, 2026
c6005d7
chore: restore addresses/8453.json byte-for-byte
anajuliabit Aug 24, 2026
31a831d
fix(lp-v2-setup): close allocation-validation review nits
anajuliabit Aug 24, 2026
0fd67f8
fix(lp-v2-setup): close allocation-validation review nits
anajuliabit Aug 24, 2026
45675ee
WIP do not keep
anajuliabit Aug 24, 2026
ea474bb
fix(lp-v2-setup): close allocation-validation review nits
anajuliabit Aug 24, 2026
51840b1
fix(lp-v2-setup): close allocation-validation review nits
anajuliabit Aug 24, 2026
9b3ec97
fix(lp-v2-setup): restore integration test with review nits
anajuliabit Aug 24, 2026
1759bb2
fix(lp-v2-setup): restore proposal and close allocation-validation nits
anajuliabit Aug 24, 2026
d315bac
feat: register MAMO_LP_REBALANCER as the backend hot key
anajuliabit Aug 24, 2026
b32cedd
fix(tenderly): stop pinning the harness to chain id 8453
anajuliabit Aug 24, 2026
fa3fbd7
fix(tenderly): give a custom-chain-id vnet an address book
anajuliabit Aug 24, 2026
8a23617
fix(tenderly): resolve addresses + hoist params out of prank argument…
anajuliabit Aug 24, 2026
41db44d
docs(tenderly): record the green harness run as a staging vnet manifest
anajuliabit Aug 24, 2026
e18d9da
feat(011): read the per-run inputs from the environment
anajuliabit Aug 25, 2026
dbdb5bd
chore: record the Base mainnet LPAutoBalancerV2 deployment
anajuliabit Aug 25, 2026
7412b72
feat: test deployment path with an EOA admin
anajuliabit Aug 25, 2026
7bc1ef0
chore: fmt DeployLPAutoBalancerV2Test with the CI-pinned forge nightly
anajuliabit Sep 2, 2026
33b03a6
fix(lpv2): repoint to the 10-tick-spacing WETH/cbBTC pool
anajuliabit Aug 27, 2026
6c6904d
chore: record the redeployed test pair (new-factory NFPM)
anajuliabit Aug 28, 2026
3eeac91
test(lpv2): re-pin fork to 50_600_000 past the redeployed test pair
anajuliabit Sep 2, 2026
e681142
test(lpv2): restore the DO_* env flags after the env-input test
anajuliabit Sep 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions addresses/8453.json
Original file line number Diff line number Diff line change
Expand Up @@ -410,18 +410,38 @@
"isContract": true
},
{
"addr": "0x70aCDF2Ad0bf2402C957154f944c19Ef4e1cbAE1",
"addr": "0x42d4a22CaD0F5a49681a5715cE994Af73A43B76b",
"name": "WETH_CBBTC_CL_POOL",
"isContract": true
},
{
"addr": "0x41b2126661C673C2beDd208cC72E85DC51a5320a",
"addr": "0x61E0B10423a0009C3f83ab4313813d29437d0817",
"name": "WETH_CBBTC_CL_GAUGE",
"isContract": true
},
{
"addr": "0xe1f8cd9AC4e4A65F54f38a5CdAfCA44f6dD68b53",
"name": "AERODROME_SLIPSTREAM_NFPM_V2",
"isContract": true
},
{
"addr": "0xBCF85224fc0756B9Fa45aA7892530B47e10b6433",
"name": "CHAINLINK_L2_SEQUENCER_UPTIME_FEED",
"isContract": true
},
{
"addr": "0xd4669fCee3BE73b51438ad1f1debEB3505Eab308",
"name": "MAMO_LP_REBALANCER",
"isContract": false
},
{
"addr": "0x6E5d79C41a358BE46D919c87F03683E9D8f48c36",
"name": "MAMO_LP_AUTO_BALANCER_V2_TEST",
"isContract": true
},
{
"addr": "0xEA05B89CA6045f65E5040519354aBca93b695425",
"name": "MAMO_LP_COMPOUND_MODULE_TEST",
"isContract": true
}
]
1 change: 1 addition & 0 deletions docs/LP_AUTO_BALANCER_V2.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,5 +167,6 @@ cooldownRemaining, deviationGateOpen, rebalanceInFlight, rebalanceStartedAt
| [`CONTEXT.md`](../CONTEXT.md) | canonical vocabulary |
| [backend spec](superpowers/specs/2026-07-03-lp-auto-balancer-v2-backend-spec.md) | operational contract for `lp_balancer_sweep`: reads/writes, decision math, CoW lifecycle, error table, monitoring, launch checklist |
| [setup runbook](LP_AUTO_BALANCER_V2_WETH_CBBTC_SETUP.md) | phase-1 WETH/cbBTC deployment: 011 proposal, deferred checker steps, handover |
| [backend handbook](LP_AUTO_BALANCER_V2_BACKEND_HANDBOOK.md) | operating the WETH/cbBTC position: venue facts, the 011 total-allocation parameter, venue mechanics, backend process shape, preflight + go-live |
| [dual-position design](superpowers/specs/2026-06-17-lp-auto-balancer-v2-dual-position-design.md) | why dual-position/no-swap; original design record |
| [swap-rebalance design](superpowers/specs/2026-07-02-lp-auto-balancer-v2-swap-rebalance-design.md) | two-phase swap path design + review residuals R1–R6 |
393 changes: 393 additions & 0 deletions docs/LP_AUTO_BALANCER_V2_BACKEND_HANDBOOK.md

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions docs/LP_AUTO_BALANCER_V2_WETH_CBBTC_SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ This is the step-by-step to stand up the **first** managed position: a **WETH/cb

| Thing | Address |
| --- | --- |
| WETH/cbBTC Slipstream CL pool (`tickSpacing = 100`) | `0x70aCDF2Ad0bf2402C957154f944c19Ef4e1cbAE1` |
| CL gauge (rewardToken = AERO) | `0x41b2126661C673C2beDd208cC72E85DC51a5320a` |
| **Slipstream NonfungiblePositionManager** (the one the gauge accepts) | `0x827922686190790b37229fd06084350E74485b72` |
| WETH/cbBTC Slipstream CL pool (`tickSpacing = 10`) | `0x42d4a22CaD0F5a49681a5715cE994Af73A43B76b` |
| CL gauge (rewardToken = AERO) | `0x61E0B10423a0009C3f83ab4313813d29437d0817` |
| **Slipstream NonfungiblePositionManager** (the one the gauge accepts) | `0xe1f8cd9AC4e4A65F54f38a5CdAfCA44f6dD68b53` |
| WETH (**token0**) | `0x4200000000000000000000000000000000000006` |
| cbBTC (**token1**) | `0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf` |
| AERO | `0x940181a94A35A4569E4529A3CDfB74e38FD98631` |
Expand All @@ -35,22 +35,22 @@ This is the step-by-step to stand up the **first** managed position: a **WETH/cb
| feeCollector (drop sink) | `DROP_AUTOMATION` (from `addresses/8453.json`) |

> **Two gotchas, both confirmed on-chain:**
> 1. The position manager the **gauge accepts** is `0x827922…`, registered in `addresses/8453.json` as **`UNISWAP_V3_POSITION_MANAGER_AERODROME`** — **not** `AERODROME_POSITION_MANAGER` (`0xc741be…`, a different address). Deploy and mint against `0x827922…` / `UNISWAP_V3_POSITION_MANAGER_AERODROME`.
> 1. The position manager the **gauge accepts** is `0xe1f8cd…`, registered in `addresses/8453.json` as **`AERODROME_SLIPSTREAM_NFPM_V2`** — **not** `AERODROME_POSITION_MANAGER` (`0xc741be…`, a different address). Deploy and mint against `0xe1f8cd…` / `AERODROME_SLIPSTREAM_NFPM_V2`.
> 2. Token order is by address: **WETH = token0, cbBTC = token1** (`0x42…` < `0xcb…`). Every `token0`/`token1`/`oracle0`/`oracle1`/`amount0`/`amount1` field follows this order.

---

## Phase 0 — Deploy `LPAutoBalancerV2`

Deploy via `script/DeployLPAutoBalancerV2.s.sol` (`deployLPAutoBalancerV2(Addresses)` / `run()`) — it reads `F-MAMO` (admin+guardian), `UNISWAP_V3_POSITION_MANAGER_AERODROME`, `AERO`, passes `manager_ = rebalancer_ = address(0)`, and records `MAMO_LP_AUTO_BALANCER_V2`. Or deploy via the FPS proposal's `deploy()` (Phase B). Constructor (6 args, **no swap router / no quoter**):
Deploy via `script/DeployLPAutoBalancerV2.s.sol` (`deployLPAutoBalancerV2(Addresses)` / `run()`) — it reads `F-MAMO` (admin+guardian), `AERODROME_SLIPSTREAM_NFPM_V2`, `AERO`, passes `manager_ = rebalancer_ = address(0)`, and records `MAMO_LP_AUTO_BALANCER_V2`. Or deploy via the FPS proposal's `deploy()` (Phase B). Constructor (6 args, **no swap router / no quoter**):

```solidity
new LPAutoBalancerV2(
admin_ = F_MAMO_SAFE, // DEFAULT_ADMIN_ROLE
manager_ = MANAGER_EOA, // MANAGER_ROLE (bounds tuning within caps); may be address(0)
rebalancer_ = address(0), // grant LATER, in Phase C (do NOT wire the backend key at deploy)
guardian_ = GUARDIAN_EOA_OR_SAFE, // pause()
positionManager_ = 0x827922686190790b37229fd06084350E74485b72, // Slipstream NFPM
positionManager_ = 0xe1f8cd9AC4e4A65F54f38a5CdAfCA44f6dD68b53, // Slipstream NFPM
aero_ = 0x940181a94A35A4569E4529A3CDfB74e38FD98631
);
```
Expand Down Expand Up @@ -83,8 +83,8 @@ Withdraw liquidity from the Phase-A NFTs and swap the proceeds into **WETH + cbB
End state: the Safe holds `X` WETH + `Y` cbBTC (small phase-1 size — keep TVL-at-risk low while proving the rebalancer).

### B2. Mint the initial WETH/cbBTC CL position
Mint via the Slipstream NFPM (`0x827922…`), recipient = **Safe**:
- `token0 = WETH`, `token1 = cbBTC`, `tickSpacing = 100`.
Mint via the Slipstream NFPM (`0xe1f8cd…`), recipient = **Safe**:
- `token0 = WETH`, `token1 = cbBTC`, `tickSpacing = 10`.
- Initial range: centered on current spot, width a multiple of `tickSpacing` and **≥ 2·tickSpacing = 200** (the contract rejects narrower — see B4). A wider initial range (e.g. a few thousand ticks) is fine; the agent re-ranges later.
- `amount0Desired / amount1Desired` = the WETH/cbBTC from B1; set sane `amount{0,1}Min`.

Expand All @@ -94,27 +94,27 @@ Record the returned `tokenId` → call it `INIT_TOKEN_ID`.
Safe transfers the position NFT into `LPAutoBalancerV2` **via the position manager** (its `onERC721Received` only accepts the NFPM as `msg.sender`):

```
INFPM(0x827922…).safeTransferFrom(SAFE, MAMO_LP_AUTO_BALANCER_V2, INIT_TOKEN_ID)
INFPM(0xe1f8cd…).safeTransferFrom(SAFE, MAMO_LP_AUTO_BALANCER_V2, INIT_TOKEN_ID)
```

### B4. `registerPosition(config)` — Safe (`DEFAULT_ADMIN_ROLE`)
Call `registerPosition` with the `ManagedPositionV2` config. The contract **validates** the config and reverts if any of these fail — get them right:

- `mainTokenId = INIT_TOKEN_ID` and the NFT is **already held** by the contract (B3 done first).
- `pool = 0x70aCDF…` and **`pool.token0()/token1()/tickSpacing()` must equal** `token0=WETH`, `token1=cbBTC`, `tickSpacing=100` (`PoolMismatch` otherwise).
- `pool = 0x42d4a2…` and **`pool.token0()/token1()/tickSpacing()` must equal** `token0=WETH`, `token1=cbBTC`, `tickSpacing=10` (`PoolMismatch` otherwise).
- `gauge = 0x41b2…` and **`gauge.rewardToken()` must equal `AERO`** (`GaugeRewardMismatch` otherwise).
- `oracle0 = ETH/USD (0x71041d…)`, `oracle1 = BTC/USD (0x64c911…)` — both must return a **fresh, non-zero** answer at call time. Each leg is bounded SEPARATELY: `maxOracleDelay0` for `oracle0`, `maxOracleDelay1` for `oracle1` (constructor seeds `DEFAULT_MAX_ORACLE_DELAY` = 1h, hard cap `MAX_ORACLE_DELAY` = 1 day). Proposal 011 arms both at 3600s — 3x the feeds' ~20-minute heartbeat.
- `minWidth ≥ 2·tickSpacing = 200`, `minWidth % 100 == 0`, `maxWidth ≥ minWidth` (`WidthTooNarrow` / `InvalidWidth`).
- `minWidth ≥ 2·tickSpacing = 20`, `minWidth % 10 == 0`, `maxWidth ≥ minWidth` (`WidthTooNarrow` / `InvalidWidth`).
- `maxRebalanceLossBps ≤ MAX_LOSS_CAP_BPS`, `maxTickDeviation > 0`, `maxCenterDeviation > 0`, `twapWindow > 0`.
- `feeCollector = DROP_AUTOMATION`.

Suggested phase-1 config values (conservative; manager can tune within caps later):

| Field | Value | Note |
| --- | --- | --- |
| `pool` | `0x70aCDF…` | WETH/cbBTC |
| `pool` | `0x42d4a2…` | WETH/cbBTC |
| `token0 / token1` | WETH / cbBTC | address order |
| `tickSpacing` | `100` | |
| `tickSpacing` | `10` | |
| `gauge` | `0x41b2…` | rewardToken == AERO |
| `feeCollector` | `DROP_AUTOMATION` | drop sink |
| `oracle0 / oracle1` | ETH/USD / BTC/USD | 8-dec feeds |
Expand Down
Loading
Loading