Skip to content

Feat/mechanism v08 - #4

Merged
codeForEatingEverything merged 169 commits into
mainfrom
feat/mechanism-v08
Oct 24, 2026
Merged

codeForEatingEverything merged 169 commits into
mainfrom
feat/mechanism-v08

Conversation

@codeForEatingEverything

Copy link
Copy Markdown
Owner

No description provided.

codeForEatingEverything and others added 30 commits October 23, 2026 23:55
Appended after the existing rows so Monad and HyperEVM keep their index and bytes. 12 s slots: 600-block windows (25 on the demo grid), 50,400-block max pause. The table is part of the core's init code, so the core address changes; Sepolia deploys on its own salt until Monad and HyperEVM are redeployed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s for Ethereum and Sepolia

Ethereum counts as a mainnet (guardian multisig, no demo or daily grid), Sepolia as a testnet; window checks require 600 blocks on both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chain 1 needs GUARDIAN_MEMBERS and refuses the demo and daily grids; Sepolia refuses mocks, needs GRAD_11155111, and gets the 600-block window on the daily grid.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…_FILE

So scripts/deploy-testnet.sh can run them on its staging copy like the other steps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WETH, USDC and wstETH on Sepolia, verified on chain and on a fork. The seven-row chain table gets TESTNET_SALT_NEXT (0xc0f3) so Sepolia can deploy without touching the live 0xc0f2 deployments on Monad and HyperEVM.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
RPC (SEPOLIA_RPC override), strikes at about 90% of value (0.93 WETH per wstETH, 2100 USDC per WETH, 2200 USDC per wstETH), small seed units, 24-order Router batches, --skip-simulation for Amsterdam code pricing, and fork-read retries for flaky public RPCs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…olia

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ss steps

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sending ETH to wstETH stakes and wraps in one call; the amount comes from getStETHByWstETH and respects the gas reserve together with the WETH wrap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Monad testnet keeps config.staging.json, Sepolia writes config.sepolia.json, scanning logs through an archive RPC because publicnode prunes old logs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ket and SeatLP tokens

Two new steps after vaults (market, seatlp), so a fresh testnet gets the C/R secondary market and the seat LP receipts that Monad and HyperEVM got by hand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t / seatlp steps

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
viem's default Sepolia RPC rejects more than 1,000 blocks, and publicnode keeps only ~10,000 blocks of logs, so scans from deployBlock use 1,000-block chunks against an archive RPC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… file stay absent

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An LST lent against its own native coin (shMON/WMON, wstETH/WETH) is pegged, every other pair main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… for an undeployed chain

A bare poolId stays main, so Monad and HyperEVM behave as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pairs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… archive log scan

CRE_CHAINS lists Monad testnet (config.staging.json) and Sepolia (config.sepolia.json, 30M report gas, 1,000-block scans through an archive RPC); a chain without a deployments file is skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
codeForEatingEverything and others added 29 commits October 24, 2026 03:09
…lizes Selling pools

SeatRegistry._split pays the holder shareBps(m): SHARE_BEFORE_BPS (7000) while the
market is not graduated, the deploy-time seatShareBps (3500) after. The constructor
signature is unchanged so Deploy.s.sol and its CREATE2 address derivation keep working.
KeeperReceiver._tick calls closeWindow on Selling pools as on Closing ones (autoSell end).

Periphery only; no core invariant touched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g pools

PoolCreated and pool() decode the key with bandBps and cadence (plus
strikeIndex in the event). Status gains Selling (4, still needs
closeWindow) and Closed moves to 5, so Selling pools stay in the
workflow's pool list until they close.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…web src/components)

Create market now validates buy-back prices against the 1% log grid
(strikeAt / strikeIndexOf from the SDK), offers the neighbouring grid
prices, defaults the price range to the pair's standard band
(1.5 / 8 / 15% by asset class), drops the fee tier (v0.8 fees are fixed)
and adds the auto-sell option. Pool ids include band and cadence; the
order read follows the v0.8 Order layout (flags field); the demo chain
snaps plan strikes to the grid and checks created pools the same way.

Part 1/3 of: feat(web): v0.8 PoolKey, 1% log grid and auto-sell in create market

Files: apps/web/src/components/more/CreateMarketCard.tsx

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…web src/lib)

Part 2/3 of: feat(web): v0.8 PoolKey, 1% log grid and auto-sell in create market

Files: apps/web/src/lib/data.ts, apps/web/src/lib/demo/chain.ts, apps/web/src/lib/grid.ts, apps/web/src/lib/proActions.ts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…web test)

Part 3/3 of: feat(web): v0.8 PoolKey, 1% log grid and auto-sell in create market

Files: apps/web/test/more.test.tsx

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eb src/app)

Specials (decision A): lists European pools that can lend the asset,
with the 120% margin per unit, the Thursday return deadline and the
overdue rule (no buy-in, margin forfeited, short repay gets asset first
then K plus margin share); lend/return stay disabled until the
deployment carries the Specials address. An auto-sell pool past its
window reads as selling defaulted collateral with claims later.
Vault copy says withdrawals are paid in the loan token and vaults lend
only into auto-sell markets. Tests cover grid vectors, standard bands,
Specials math and the selling phase.

Part 1/4 of: feat(web): Specials page, selling status and quote-only vault copy

Files: apps/web/src/app/specials/page.tsx

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eb src/components)

Part 2/4 of: feat(web): Specials page, selling status and quote-only vault copy

Files: apps/web/src/components/earn/EarnScreen.tsx, apps/web/src/components/earn/VaultDrawer.tsx, apps/web/src/components/layout/nav.ts, apps/web/src/components/specials/SpecialsScreen.tsx

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eb src/lib)

Part 3/4 of: feat(web): Specials page, selling status and quote-only vault copy

Files: apps/web/src/lib/specials.ts, apps/web/src/lib/window.ts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eb test)

Part 4/4 of: feat(web): Specials page, selling status and quote-only vault copy

Files: apps/web/test/shell.test.tsx, apps/web/test/v08-web.test.tsx

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ee in spend

v0.8 (spec 4.4): the fixed 8-week run is gone. A market leaves bootstrap
for good once it has a seat holder or its weekly volume (marketStats
volume over the expiries of the last 7 days) reaches EXIT_WEEKLY_VOLUME,
a deploy parameter (0 = seats only); the process exits when every market
is done or at END_AT. Spend counts OrderFilled quoteAmount + fee, units
are sized so cost + the 0.015% buyer fee fit the batch budget, and the
order() tuple is read with the new flags field.

Part 1/2 of: feat(bootstrap-mm): per-market exit by seat or weekly volume, buyer fee in spend

Files: services/bootstrap-mm/src/bot.ts, services/bootstrap-mm/src/index.ts, services/bootstrap-mm/src/rules.ts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ee in spend

Part 2/2 of: feat(bootstrap-mm): per-market exit by seat or weekly volume, buyer fee in spend

Files: services/bootstrap-mm/test/bot.test.ts, services/bootstrap-mm/test/rules.test.ts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…src/lib)

The SDK now has Status.Selling between Closing and Closed; the status
label table is indexed by status, so it gains the Selling entry, the
lifecycle phase names it, and pool state treats it as closing (claims
wait for the sale).

Part 1/2 of: fix(web): follow the v0.8 Status enum (Selling = 4, Closed = 5)

Files: apps/web/src/lib/format.ts, apps/web/src/lib/view.ts, apps/web/src/lib/window.ts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…test)

Part 2/2 of: fix(web): follow the v0.8 Status enum (Selling = 4, Closed = 5)

Files: apps/web/test/v08-web.test.tsx

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-inclusive escrow

Strikes per chain move to the canonical log-grid indices of spec 2.7
(Monad USD/extra -384, LST -11; HyperEVM USD 434, extra -453; Sepolia
LST -7, USD 769, extra 773), exported as *_STRIKE_N plus the matching K
in *_STRIKE_LOW/HIGH. GRAD rows' second column is now the per-expiry
graduation fee: 4 base units of USDC, 1e12 wei of the native coin.
Preflight funds each buy with buyEscrow (cost + 0.015% fee + 2 wei per
batch of ttl); the offline test's expected needs follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Binding the Specials periphery added locals to Deploy.run and the
script stopped compiling (stack too deep). The registry precompute moves
into _registries and the config inputs into a scoped block; behaviour is
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (Confluere.sol)

Decision B (2026-10-24). When a pool created with PoolOptions.autoSell
finishes its abandonment auction with defaulted asset left, closeWindow
places a competitive SELL for all of it into the same market's next
expiry pool of the same tier (strike, band, cadence) at
limit = K x AUTOSELL_DISCOUNT_BPS / 10_000 for AUTOSELL_TTL settlements.
The order is owned by the core (FLAG_AUTOSELL; nobody can cancel it,
purge can clear it when dead) and linked back through linkedPool; its
units stay in the old pool's assetBal, marked autoSellUnits. Fills move
the asset to the new pool and credit the old pool's quoteBal with the
net proceeds (spread share and trade fee charged like any seller); the
R minted to the core is never repaid and takes the new pool's normal
window. The old pool waits in Status.Selling (claims wait) until the
order leaves the book by any path (filled, ttl out, evicted, purged),
which closes it; anything unsold is paid in kind as before. closeWindow
on a Selling pool ends a dead order (ttl used, or the target stopped
trading), so Selling always ends by the target's expiry. No target
pool, a target no longer trading, or a full book of better sells: the
pool just closes. At a pool's close the core burns any R it holds and
moves that R's share of the auction surplus to C holders (choice B2).
closeWindow returns true once the pool leaves Closing (Selling or
Closed).

CoreLib.insert splits out tryInsert (no BookFull revert).

Events: AutoSellPlaced(poolId, targetPoolId, orderId, units, limit),
AutoSellEnded(poolId, unitsLeft); WindowClosed is emitted when the pool
reaches Closed. PoolView gains autoSellPool, autoSellOrder,
autoSellUnits.

Tests: AutoSell.t.sol (placement, owner is core, fill credits net,
claims wait, ttl out in kind, partial then expire, no target, full
book, eviction, paused target, closeWindow and purge end a dead order,
core R burned with its surplus to lenders, off by default); the
invariant suite runs pool 0 with autoSell and adds
invariant_noStrandedFunds (3d).

Invariants: 1 (autoSell units counted in the source pool, not as sell
escrow), 2 (new R minted against the moved asset), 3d (new), 4 (the
source pool's asset leaves only against quote at P*), 7 (bookkeeping
only, no transfer).

Part 1/7 of: feat(core): sell defaulted collateral into the next expiry (autoSell)

Files: contracts/src/Confluere.sol

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (IConfluere.sol)

Part 2/7 of: feat(core): sell defaulted collateral into the next expiry (autoSell)

Files: contracts/src/interfaces/IConfluere.sol

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (OrderSet.sol)

Part 3/7 of: feat(core): sell defaulted collateral into the next expiry (autoSell)

Files: contracts/src/libraries/OrderSet.sol

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (State.sol)

Part 4/7 of: feat(core): sell defaulted collateral into the next expiry (autoSell)

Files: contracts/src/libraries/State.sol

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (libraries/logic)

Part 5/7 of: feat(core): sell defaulted collateral into the next expiry (autoSell)

Files: contracts/src/libraries/logic/ClearingLogic.sol, contracts/src/libraries/logic/WindowLogic.sol

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (tests invariant)

Part 6/7 of: feat(core): sell defaulted collateral into the next expiry (autoSell)

Files: contracts/test/invariant/Handler.sol, contracts/test/invariant/Invariants.t.sol

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (tests unit)

Part 7/7 of: feat(core): sell defaulted collateral into the next expiry (autoSell)

Files: contracts/test/unit/AutoSell.t.sol

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… init code

VaultFactory embedded the Vault init code and grew to 25.7 KB, so it could not
be deployed. The constructor now fixes keccak256(type(Vault).creationCode) and
create() takes the init code, checks it against that hash and deploys with
CREATE2 at the same address as before (salt keccak(sender, salt)). Deploy and
CreateVaults pass the code; new test rejects other bytecode. Factory 1.7 KB.

No §2.11 invariant touched (periphery only).

Part 1/3 of: fix(vault): keep VaultFactory under EIP-170 with a hash-checked Vault init code

Files: contracts/script/CreateVaults.s.sol, contracts/script/Deploy.s.sol

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… init code

Part 2/3 of: fix(vault): keep VaultFactory under EIP-170 with a hash-checked Vault init code

Files: contracts/src/periphery/VaultFactory.sol

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… init code (tests unit)

Part 3/3 of: fix(vault): keep VaultFactory under EIP-170 with a hash-checked Vault init code

Files: contracts/test/unit/Periphery.t.sol

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check_ncPricingRule compares a reference 3x3 cross with NC demand priced in
ahead of competitive buys: the recross price never falls below the
competitive-only price, stays between the filling marginal limits, and NC
volume stays within half the competitive-only volume (§2.11 NC cap).
Left uncommitted in the tree by the core agent; committed in the final pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…row split

The short-margin forfeiture and closeRemaining sizing (decision A) move from the
body of closeWindow into _closeSharedPot, so the shared pot and _splitEscrow are
two separate internal functions. Behaviour unchanged.

Invariants (§2.11): touches the window-close accounting of #1 (pool solvency)
and #7 (pull refunds) without changing them; all forge tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s slow_

The 13-scalar check_ncPricingRule failed to compile in the unoptimized Halmos
profile (stack too deep); its inputs are now four packed fields plus demand.
It and check_ncCapHalf time out the solver within the default budget, so both
move to the slow_ prefix (like the z3-lemma properties) and the check_ suite
runs green: 7/7.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An anvil child that exited at once (port taken) stays a zombie until reaped and
still passes kill -0, so the loop waited the full 30 s and printed the timeout
message instead of "anvil failed to start". Also check its process state.
e2e-guard.test.sh passes again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codeForEatingEverything
codeForEatingEverything merged commit 4704a41 into main Oct 24, 2026
2 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant