@logswap/sdk 0.5.55 → 0.5.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/fpool.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * The other primitive. `CPoolManager` gives every position its own floor on a tick ladder;
5
5
  * `FPoolManager` gives every share the SAME floor and deletes the ladder, the accumulators and the
6
6
  * per-position accounting with it. Reading the two side by side is the fastest way to understand
7
- * either (logswap-docs:docs/multi/f-pool.md).
7
+ * either.
8
8
  *
9
9
  * **A pool is an ID, not an address.** Both primitives are singletons now, so neither has a
10
10
  * per-pool deployment — but they are addressed differently and for a reason. The C manager rides
@@ -15,7 +15,7 @@
15
15
  * **Two products, one contract.** The basket (n > 1) and the launch (n = 1, the creator alone on
16
16
  * the lever) are the same bytecode under two key fields — the KIND (what the manager promises
17
17
  * structurally) and the POLICY (the pool's policy: its roles, its gates, the terms of every harvest
18
- * and release; decisions 041, 044) — and nothing in the maths. `describeFPool` below reports
18
+ * and release) — and nothing in the maths. `describeFPool` below reports
19
19
  * which shape a given pool is, because a UI has to decide what to render.
20
20
  *
21
21
  * **The roles are the policy's, not the manager's** (F version 15). The manager holds no
@@ -34,9 +34,9 @@ import { encodeFunctionData, toFunctionSelector, type Address, type Hash, type H
34
34
  import { fPoolManagerAbi, logswapRouterAbi, padPolicyAbi, polPolicyAbi, policyRegistryAbi, privatePolicyAbi, publicPolicyAbi } from "./generated.js";
35
35
 
36
36
  /**
37
- * One contract, one ABI (decisions 039, F version 12): `harvest`, `claim`, `retire`, `regenerate`,
37
+ * One contract, one ABI (F version 12): `harvest`, `claim`, `retire`, `regenerate`,
38
38
  * `setLegs`, the names, the fee parameters are `FPoolManager`'s own code. The roles left it for
39
- * the policies in F version 15 (decisions 044): {@link fPolicyBaseAbi} is what every policy shares,
39
+ * the policies in F version 15: {@link fPolicyBaseAbi} is what every policy shares,
40
40
  * {@link privatePolicyAbi} the desk's, {@link padPolicyAbi} / {@link polPolicyAbi} / {@link publicPolicyAbi}
41
41
  * the kinds'.
42
42
  */
@@ -48,12 +48,12 @@ export { fPoolManagerAbi, padPolicyAbi, polPolicyAbi, privatePolicyAbi, publicPo
48
48
  */
49
49
  export const fPolicyBaseAbi = polPolicyAbi;
50
50
  import type { LogswapClient } from "./client.js";
51
- import { signerFor } from "./write.js";
51
+ import { fallBackUnlessRejected, signerFor } from "./write.js";
52
52
 
53
53
  const WAD = 10n ** 18n;
54
54
  const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" as const;
55
55
 
56
- /** The optional questions a policy declared at birth (decisions 044), as bits of `Pool.asks`. */
56
+ /** The optional questions a policy declared at birth, as bits of `Pool.asks`. */
57
57
  export const ASK_SWAP = 1;
58
58
  export const ASK_MINT = 2;
59
59
 
@@ -82,29 +82,29 @@ export interface FPoolState {
82
82
  /** Σ = ∫ Σ_j w_j (dx_j)², accrued even though the fee is fixed — the kernel stays calculable. */
83
83
  bigSigma: bigint;
84
84
  /**
85
- * The pool's policy (decisions 041, 044): the contract the key names, holding the pool's roles
85
+ * The pool's policy: the contract the key names, holding the pool's roles
86
86
  * and answering every question the manager does not decide itself. Read its roles with
87
87
  * {@link getFPoolRoles}; one of the deployment's four ({@link fPoolPolicyFor}) on every protocol pool.
88
88
  */
89
89
  policy: Address;
90
90
  /** Whether the policy asked to be consulted on swaps ({@link ASK_SWAP}) and mints ({@link ASK_MINT}) — the desk's policy does, no other. */
91
91
  asks: number;
92
- /** The sponsor's own label for this pool — the policy's word (decisions 049), mutable and never identity. "" when unnamed. */
92
+ /** The sponsor's own label for this pool — the policy's word, mutable and never identity. "" when unnamed. */
93
93
  name: string;
94
94
  /** The block of the last harvest / composition action: no swap runs in it. */
95
95
  restructureBlock: number;
96
- /** What the pool is — its POLICY's self-description (decisions 049); see {@link FPoolKind}. */
96
+ /** What the pool is — its POLICY's self-description; see {@link FPoolKind}. */
97
97
  kind: FPoolKind;
98
- /** False before the first seed — and between a retire and the next one (decisions 032). */
98
+ /** False before the first seed — and between a retire and the next one. */
99
99
  seeded: boolean;
100
100
  /**
101
- * The live GENERATION (decisions 032). Every retire freezes one into a bundle its shares
101
+ * The live GENERATION. Every retire freezes one into a bundle its shares
102
102
  * redeem ({@link fPoolRedeem}) and opens the next; the share id carries it
103
103
  * ({@link fPoolShareId}), so generations `0 … gen-1` are retired claims and `gen` is the pool.
104
104
  */
105
105
  gen: number;
106
106
  totalSupply: bigint;
107
- /** What the pool holds of each base — the STATE since decisions 026; the mark `x` is derived from it. */
107
+ /** What the pool holds of each base — the STATE; the mark `x` is derived from it. */
108
108
  reserves: bigint[];
109
109
  }
110
110
 
@@ -149,8 +149,8 @@ export async function getFPool(c: LogswapClient, poolId: Hex): Promise<FPoolStat
149
149
  const n = Number(p.n);
150
150
  const idx = Array.from({ length: n }, (_, i) => BigInt(i));
151
151
  const [theta, compositeX, legs, kind, name] = await Promise.all([
152
- // before the seed there is no L and no floor: θ is X by convention (the manager says so since
153
- // bd3dd87's successor; older deployments revert with DivWadFailed, so do not ask them)
152
+ // before the seed there is no L and no floor: θ is X by convention (older deployments revert
153
+ // with DivWadFailed, so do not ask them)
154
154
  p.L > 0n ? rd<bigint>("theta", [poolId]) : rd<bigint>("compositeX", [poolId]),
155
155
  rd<bigint>("compositeX", [poolId]),
156
156
  Promise.all(idx.map((i) => rd<readonly [Address, bigint, bigint, bigint]>("legOf", [poolId, i]))),
@@ -160,7 +160,7 @@ export async function getFPool(c: LogswapClient, poolId: Hex): Promise<FPoolStat
160
160
 
161
161
  const bases = legs.map((l) => l[0]);
162
162
  const weights = legs.map((l) => l[1]);
163
- const x = legs.map((l) => l[2]); // derived by the manager: x_j = ln(w_j·L / R_j) (decisions 026)
163
+ const x = legs.map((l) => l[2]); // derived by the manager: x_j = ln(w_j·L / R_j)
164
164
  const reserves = legs.map((l) => l[3]); // the state
165
165
  const { quote, Q, L, phi, theta0, bigSigma, policy, restructureBlock, seeded, gen } = p;
166
166
  const totalSupply = p.shares;
@@ -191,7 +191,7 @@ export async function getFPool(c: LogswapClient, poolId: Hex): Promise<FPoolStat
191
191
  }
192
192
 
193
193
  /**
194
- * The kind of pool — the POLICY's self-description (decisions 049: the manager knows no kind; the
194
+ * The kind of pool — the POLICY's self-description (the manager knows no kind; the
195
195
  * policy the key names is the kind, and what it promises is its code). `public`: the protocol's
196
196
  * own pool — its policy requires the collector as creator; no gate, no operator. `private`, the
197
197
  * desk: the one whose policy may gate swaps and mints, with an operator that reshapes the legs
@@ -209,7 +209,7 @@ const kindCache = new Map<string, Promise<FPoolKind>>();
209
209
 
210
210
  /**
211
211
  * What a policy IS — its `kind()` tag, read once per policy address and cached for the client's
212
- * chain: a pool's kind is its policy's word (decisions 049), never the manager's. An unknown tag
212
+ * chain: a pool's kind is its policy's word, never the manager's. An unknown tag
213
213
  * (a policy that is not one of the protocol's four shapes) throws; the app has no screen for it.
214
214
  */
215
215
  export function fPoolKindOfPolicy(c: LogswapClient, policy: Address): Promise<FPoolKind> {
@@ -227,14 +227,14 @@ export function fPoolKindOfPolicy(c: LogswapClient, policy: Address): Promise<FP
227
227
  return hit;
228
228
  }
229
229
 
230
- /** The pool's label, as its policy holds it (decisions 049). "" when unnamed. */
230
+ /** The pool's label, as its policy holds it. "" when unnamed. */
231
231
  export async function fPoolNameOf(c: LogswapClient, poolId: Hex, policy?: Address): Promise<string> {
232
232
  const p = policy ?? (await fPoolPolicyOf(c, poolId));
233
233
  const word = (await c.public.readContract({ address: p, abi: fPolicyBaseAbi, functionName: "nameOf", args: [poolId] } as never)) as Hex;
234
234
  return bytes32ToText(word);
235
235
  }
236
236
 
237
- /** The deployment's policy for a kind (decisions 044, 049): the protocol's policy that IS that kind. */
237
+ /** The deployment's policy for a kind: the protocol's policy that IS that kind. */
238
238
  export function fPoolPolicyFor(c: LogswapClient, kind: FPoolKind): Address {
239
239
  const a = c.addresses;
240
240
  const policy = kind === "public" ? a.publicPolicy : kind === "private" ? a.privatePolicy : kind === "pol" ? a.polPolicy : a.padPolicy;
@@ -255,7 +255,7 @@ export async function fPoolPolicyOf(c: LogswapClient, poolId: Hex): Promise<Addr
255
255
  }
256
256
 
257
257
  /**
258
- * A pool's roles, as its POLICY holds them (decisions 044). `creator` is immutable identity —
258
+ * A pool's roles, as its POLICY holds them. `creator` is immutable identity —
259
259
  * who was born holding the pool; `authority` is the cold key that owns it now, the creator until
260
260
  * a two-step handover; on the desk's kind the `operator` runs it (zero = the authority itself,
261
261
  * {@link fPoolOperatorOf}) and the two gates and the list are its. Every other kind has no
@@ -265,7 +265,7 @@ export interface FPoolRoles {
265
265
  policy: Address;
266
266
  creator: Address;
267
267
  authority: Address;
268
- /** The proposed next authority, until it accepts — zero when nothing is pending (decisions 020). */
268
+ /** The proposed next authority, until it accepts — zero when nothing is pending. */
269
269
  pendingAuthority: Address;
270
270
  operator: Address;
271
271
  pendingOperator: Address;
@@ -303,7 +303,7 @@ export type FPoolShape = "launch" | "basket";
303
303
 
304
304
  export interface FPoolDescription {
305
305
  shape: FPoolShape;
306
- /** The pad is the launch shape, by the kind (decisions 036). */
306
+ /** The pad is the launch shape, by the kind. */
307
307
  legs: number;
308
308
  /** True when the pool holds no quote: an all-base resting ask. base→quote is the one blocked path. */
309
309
  atFloor: boolean;
@@ -315,7 +315,7 @@ export interface FPoolDescription {
315
315
  unharvested: bigint;
316
316
  /** The most a harvest may take now by the KIND's promise: the bid, and on a pad the income. The policy may allow less — {@link FPoolRoles.maxHarvest}. */
317
317
  harvestable: bigint;
318
- /** The dead shares' banked dividend — a pad's pot, the creator's income until a rung is climbed (decisions 041). */
318
+ /** The dead shares' banked dividend — a pad's pot, the creator's income until a rung is climbed. */
319
319
  pot: bigint;
320
320
  }
321
321
 
@@ -332,7 +332,7 @@ export async function describeFPool(c: LogswapClient, s: FPoolState): Promise<FP
332
332
  ? await Promise.all([rd<bigint>("unharvested"), rd<bigint>("harvestable"), rd<bigint>("dividendOf", [s.poolId, BigInt(s.gen), DEAD_ADDRESS])])
333
333
  : [0n, 0n, 0n];
334
334
  return {
335
- shape: s.kind === "pad" ? "launch" : "basket", // the kind, not n = 1 (decisions 036)
335
+ shape: s.kind === "pad" ? "launch": "basket", // the kind, not n = 1
336
336
  legs: s.bases.length,
337
337
  atFloor: s.Q === 0n,
338
338
  unharvested,
@@ -353,7 +353,7 @@ export function fPoolShareValue(s: FPoolState): bigint {
353
353
  }
354
354
 
355
355
  // ─── swaps ────────────────────────────────────────────────────────────────────
356
- // Exact-in only (f-pool §10). Three paths; the third is the one that makes a basket a basket.
356
+ // Exact-in only. Three paths; the third is the one that makes a basket a basket.
357
357
 
358
358
  export interface FPoolSwapArgs {
359
359
  poolId: Hex;
@@ -422,7 +422,7 @@ export async function fPoolMint(
422
422
 
423
423
  /**
424
424
  * Burn shares for the pro-rata slice of every reserve. Available at any Q, and after dissolution.
425
- * By owner since contracts `c782811` (decisions 019): the account burns its own shares; an
425
+ * By owner: the account burns its own shares; an
426
426
  * operator may pass another owner's address, as on the C manager's `burnById`.
427
427
  */
428
428
  export async function fPoolBurn(
@@ -473,7 +473,7 @@ export async function fPoolPreviewZapIn(c: LogswapClient, poolId: Hex, dL: bigin
473
473
  *
474
474
  * The imbalanced part goes through the pool's own curve before anything is minted. That is not a
475
475
  * penalty: minting against a quote-only deposit would be a zero-slippage, zero-fee swap at stale
476
- * spot, paid for by the existing LPs — 27.4% in f-pool §6's worked example. Routing it through
476
+ * spot, paid for by the existing LPs. Routing it through
477
477
  * the curve deletes the subsidy and hands the fee and impact to the incumbents instead.
478
478
  */
479
479
  export async function fPoolZapIn(
@@ -532,7 +532,7 @@ export async function fPoolPreviewZapOut(
532
532
  }
533
533
 
534
534
  /**
535
- * Roll a retired generation's bundle into the pool's live one (decisions 025, 032), on the
535
+ * Roll a retired generation's bundle into the pool's live one, on the
536
536
  * router under one lock: redeem `shares` of generation `gen` in place — the legs, the quote and
537
537
  * any unpulled dividend come back — buy through the pool's own curve only what the live
538
538
  * generation's ratio lacks, mint `dL` of it to `to`, and refund the rest in kind. Quote the
@@ -592,11 +592,11 @@ export async function fPoolPreviewRollIn(
592
592
  // ─── the floor lever (authority only) ─────────────────────────────────────────
593
593
 
594
594
  /**
595
- * Remove quote, lifting θ — price-neutral, no base moves, and since decisions 028 a DIVIDEND to
595
+ * Remove quote, lifting θ — price-neutral, no base moves, and a DIVIDEND to
596
596
  * every share: the amount goes into the pool's pot and each holder's slice is settled lazily on
597
597
  * their next transfer, mint or burn, or pulled with {@link fPoolClaim}. The sponsor's own slice —
598
598
  * its shares' and the locked seed's at 0xdead — is pushed to `to` at once. On a pad
599
- * the lift stops at the seed floor θ₀ (income only); nothing else bounds it (decisions 035) — an
599
+ * the lift stops at the seed floor θ₀ (income only); nothing else bounds it — an
600
600
  * unlocked pool's authority may take Q to zero.
601
601
  */
602
602
  export async function fPoolHarvest(c: LogswapClient, a: { poolId: Hex; amount: bigint; to?: Address; account: Address }) {
@@ -604,16 +604,16 @@ export async function fPoolHarvest(c: LogswapClient, a: { poolId: Hex; amount: b
604
604
  }
605
605
 
606
606
  /**
607
- * Pull one's settled dividend (decisions 028) on a generation's shares without moving them;
607
+ * Pull one's settled dividend on a generation's shares without moving them;
608
608
  * anyone with shares. `gen` defaults to the live generation; a retired generation's harvests
609
- * stay claimable under its own id (decisions 032).
609
+ * stay claimable under its own id.
610
610
  */
611
611
  export async function fPoolClaim(c: LogswapClient, a: { poolId: Hex; gen?: bigint | number; to?: Address; account: Address }) {
612
612
  const gen = a.gen ?? (await fPoolGen(c, a.poolId));
613
613
  return writeFPool(c, a.poolId, "claim", [BigInt(gen), a.to ?? a.account], a.account);
614
614
  }
615
615
 
616
- /** A holder's dividend as of now on generation `gen` (the live one by default) — banked plus pending on the current balance (decisions 028). */
616
+ /** A holder's dividend as of now on generation `gen` (the live one by default) — banked plus pending on the current balance. */
617
617
  export async function fPoolDividendOf(c: LogswapClient, poolId: Hex, holder: Address, gen?: bigint | number): Promise<bigint> {
618
618
  const g = gen ?? (await fPoolGen(c, poolId));
619
619
  return c.public.readContract({
@@ -676,7 +676,7 @@ async function writeRouter(
676
676
  let sendArgs: unknown[] = args;
677
677
  if (pullTokens.length) {
678
678
  const { permit2SigCalls } = await import("./onboard.js");
679
- const sigCalls = await permit2SigCalls(c, pullTokens).catch(() => []);
679
+ const sigCalls = await permit2SigCalls(c, pullTokens).catch(fallBackUnlessRejected);
680
680
  if (sigCalls.length) {
681
681
  const { encodeFunctionData } = await import("viem");
682
682
  const inner = encodeFunctionData({ abi: logswapRouterAbi, functionName, args } as never);
@@ -762,7 +762,7 @@ export async function approveRouterForFPool(c: LogswapClient, account: Address)
762
762
  // a multicall that uses it.
763
763
 
764
764
  /**
765
- * The ERC-6909 id carrying generation `gen` of a pool's shares (decisions 032): bit 255 set (the
765
+ * The ERC-6909 id carrying generation `gen` of a pool's shares: bit 255 set (the
766
766
  * share flag), the pool id's top 239 bits, the generation in the low 16. Each generation's shares
767
767
  * are their own asset — a retired one is a claim on its bundle, the live one on the pool.
768
768
  */
@@ -802,7 +802,7 @@ export async function fPoolShareBalance(c: LogswapClient, poolId: Hex, owner: Ad
802
802
  } as never) as Promise<bigint>;
803
803
  }
804
804
 
805
- /** A retired generation's bundle (decisions 032): what is left to redeem — supply, quote, base per leg index. */
805
+ /** A retired generation's bundle: what is left to redeem — supply, quote, base per leg index. */
806
806
  export async function fPoolBundleOf(
807
807
  c: LogswapClient,
808
808
  poolId: Hex,
@@ -826,7 +826,7 @@ export interface FPoolClaimRow {
826
826
  dividend: bigint;
827
827
  }
828
828
 
829
- /** A holder's claims on a pool's retired generations — one row per generation still held (decisions 032). */
829
+ /** A holder's claims on a pool's retired generations — one row per generation still held. */
830
830
  export async function fPoolClaimsOf(c: LogswapClient, poolId: Hex, owner: Address): Promise<FPoolClaimRow[]> {
831
831
  const { logswapLensAbi } = await import("./generated.js");
832
832
  const rows = (await c.public.readContract({
@@ -839,7 +839,7 @@ export async function fPoolClaimsOf(c: LogswapClient, poolId: Hex, owner: Addres
839
839
  }
840
840
 
841
841
  /**
842
- * Redeem `shares` of a RETIRED generation (decisions 032): its bundle, pro rata — the base per
842
+ * Redeem `shares` of a RETIRED generation: its bundle, pro rata — the base per
843
843
  * leg and the quote — plus the owner's settled dividend. Not `burn`: nothing can move a bundle's
844
844
  * ratio, so there is no slippage to bound. The owner, or an operator of theirs.
845
845
  */
@@ -943,7 +943,7 @@ export interface FPoolCreateArgs {
943
943
  */
944
944
  kind: FPoolKind;
945
945
  /**
946
- * The pool's policy (decisions 041, 044, 049): the contract the key names, approved by the
946
+ * The pool's policy: the contract the key names, approved by the
947
947
  * registry, and the pool's kind. Defaults to the deployment's policy for `kind`
948
948
  * ({@link fPoolPolicyFor}) — the one every protocol pool names.
949
949
  */
@@ -1025,8 +1025,8 @@ export async function fPoolIdOf(c: LogswapClient, a: Omit<FPoolCreateArgs, "acco
1025
1025
  }
1026
1026
 
1027
1027
  /**
1028
- * The reserve a leg holds at a mark: `R = Lj·e^{−x}`, WAD math. The seed names RESERVES since
1029
- * decisions 029 — the sponsor states holdings and the price follows, `p = Lj / R` — so this is
1028
+ * The reserve a leg holds at a mark: `R = Lj·e^{−x}`, WAD math. The seed names RESERVES —
1029
+ * the sponsor states holdings and the price follows, `p = Lj / R` — so this is
1030
1030
  * the one conversion from a price to what the pool will hold, done here, on the way in. Float
1031
1031
  * precision (~1e-16 relative) is what a seed needs: any reserve is a legal seed, and the mark
1032
1032
  * the pool derives from it is the one the sponsor meant to within that.
@@ -1052,7 +1052,7 @@ export async function fPoolSeed(
1052
1052
  }
1053
1053
 
1054
1054
  /**
1055
- * Retire the live generation (decisions 025, 032, 035) — the raw entry (`dissolve` before F
1055
+ * Retire the live generation — the raw entry (`dissolve` before F
1056
1056
  * version 14). Allowed only at an empty bid, Q ≤ L/1e9, on every pool: the market took it, or the
1057
1057
  * operator harvested it out first ({@link fPoolRetire} does both in one transaction). The live
1058
1058
  * (S, Q, R_j) become a frozen bundle every share of this generation redeems ({@link fPoolRedeem})
@@ -1080,23 +1080,23 @@ export async function fPoolRetire(c: LogswapClient, a: { poolId: Hex; account: A
1080
1080
 
1081
1081
  /**
1082
1082
  * The harvests that empty an unlocked pool's bid, in order — what a relaunch sends before its
1083
- * `retire` (decisions 035: a retire needs an empty bid on every pool). Since F version 14 one
1083
+ * `retire` (a retire needs an empty bid on every pool). Since F version 14 one
1084
1084
  * `harvest(Q)` does it: the protocol's cut leaves the pool with the amount (with no collector
1085
1085
  * there is no cut). `[]` when the bid is already empty. Throws on a pad that still bids (its bid
1086
1086
  * empties only as the market sells it down), and when the pool's policy keeps a floor on the bid
1087
- * (`PolPolicy.keepQuote`, decisions 044): a `retire` under that policy waits for the market.
1087
+ * (`PolPolicy.keepQuote`): a `retire` under that policy waits for the market.
1088
1088
  */
1089
1089
  export async function fPoolEmptyingHarvests(c: LogswapClient, poolId: Hex): Promise<bigint[]> {
1090
1090
  const s = await getFPool(c, poolId);
1091
1091
  if (s.Q === 0n) return [];
1092
- if (s.kind === "pad") throw new Error("logswap: a pad is retired only once its bid is empty (decisions 035)");
1092
+ if (s.kind === "pad") throw new Error("logswap: a pad is retired only once its bid is empty");
1093
1093
  const { maxHarvest } = await getFPoolRoles(c, poolId, s);
1094
- if (maxHarvest < s.Q) throw new Error("logswap: the pool's policy keeps a floor on the bid — it cannot be harvested empty (decisions 044)");
1094
+ if (maxHarvest < s.Q) throw new Error("logswap: the pool's policy keeps a floor on the bid — it cannot be harvested empty");
1095
1095
  return [s.Q];
1096
1096
  }
1097
1097
 
1098
1098
  /**
1099
- * Release the dead shares' pot under the policy's terms (decisions 041, 044) — a pad's graduation.
1099
+ * Release the dead shares' pot under the policy's terms — a pad's graduation.
1100
1100
  * The manager harvests the generation's income first (the pot then holds everything the dead
1101
1101
  * shares earned), asks the policy, and applies its answer: a share to the payee it names (the pad's
1102
1102
  * creator — the pool's authority), a cut to the collector, the rest bought in as more of the
@@ -1108,7 +1108,7 @@ export async function fPoolRegenerate(c: LogswapClient, a: { poolId: Hex; to?: A
1108
1108
  }
1109
1109
 
1110
1110
  /**
1111
- * The relaunch as ONE transaction (decisions 025, 032, 035, 037): `harvest` the bid out — a
1111
+ * The relaunch as ONE transaction: `harvest` the bid out — a
1112
1112
  * dividend to every share, {@link fPoolEmptyingHarvests} — `retire` the live generation at the
1113
1113
  * empty bid, `redeem` the caller's own shares of it (when `shares` > 0), optionally `setLegs` the
1114
1114
  * next generation's composition (`legs`: a private pool's reshape — retire, admit, reweight), and
@@ -1127,7 +1127,7 @@ export async function fPoolRelaunch(
1127
1127
  shares: bigint;
1128
1128
  L0: bigint;
1129
1129
  Q0: bigint;
1130
- /** the next generation's composition (decisions 037): one weight per existing leg (0 retires it), then one per new base */
1130
+ /** the next generation's composition: one weight per existing leg (0 retires it), then one per new base */
1131
1131
  legs?: { weights: bigint[]; newBases?: Address[] };
1132
1132
  extra?: Hex[];
1133
1133
  account: Address;
@@ -1148,7 +1148,7 @@ export async function fPoolRelaunch(
1148
1148
  return writeFPool0(c, "multicall", [calls], a.account);
1149
1149
  }
1150
1150
 
1151
- /** Where a pad's seed lives (decisions 036): `seed` mints every share of a pad here itself. */
1151
+ /** Where a pad's seed lives: `seed` mints every share of a pad here itself. */
1152
1152
  export const DEAD_ADDRESS: Address = "0x000000000000000000000000000000000000dEaD";
1153
1153
  /** The manager's `MIN_SHARES`: the seed mints this much to 0xdead on every pool, the rest to the seeder — or, on a pad, to 0xdead too. */
1154
1154
  export const F_MIN_SHARES = 1000n;
@@ -1201,13 +1201,13 @@ export function fPoolLaunchCalls(
1201
1201
  if (!a.initialized) calls.push(enc("initialize", [key]));
1202
1202
  calls.push(enc("seed", [poolId, a.L0, companions[1]!, a.Q0]));
1203
1203
  // gen 0 by construction: a launch is the pool's FIRST seed — a relaunch is `fPoolRelaunch`.
1204
- // No transfer to 0xdead: on a pad `seed` mints every share there itself (decisions 036).
1204
+ // No transfer to 0xdead: on a pad `seed` mints every share there itself.
1205
1205
  if (a.openBuy) {
1206
1206
  const j = bases.indexOf(a.bases[a.openBuy.j]!);
1207
1207
  if (j < 0) throw new Error(`logswap: openBuy.j = ${a.openBuy.j} is not a leg`);
1208
1208
  calls.push(enc("swapQuoteIn", [poolId, BigInt(j), a.openBuy.amountIn, a.openBuy.minOut ?? 0n, a.account]));
1209
1209
  }
1210
- // the name, the desk's gates and its list are the POLICY's (decisions 044, 049), not the
1210
+ // the name, the desk's gates and its list are the POLICY's, not the
1211
1211
  // manager's: they cannot ride in this batch — `fPoolLaunch` and `fPoolDeskOpening` send them
1212
1212
  // right after, as the same creator
1213
1213
  calls.push(...(a.extra ?? []));
@@ -1215,8 +1215,8 @@ export function fPoolLaunchCalls(
1215
1215
  }
1216
1216
 
1217
1217
  /**
1218
- * The desk's opening posture, on its policy (decisions 044, 048): gated minting, the creator a
1219
- * minter. No appointment: the authority is the operator until one is appointed (decisions 037).
1218
+ * The desk's opening posture, on its policy: gated minting, the creator a
1219
+ * minter. No appointment: the authority is the operator until one is appointed.
1220
1220
  * Two writes to `PrivatePolicy`; the launch batch cannot carry them (they are not manager calls).
1221
1221
  */
1222
1222
  export async function fPoolDeskOpening(c: LogswapClient, a: { poolId: Hex; account: Address; policy?: Address }): Promise<Hash[]> {
@@ -1256,7 +1256,7 @@ export async function fPoolLaunch(
1256
1256
  return { hash, poolId };
1257
1257
  }
1258
1258
 
1259
- // ─── the roles, on the policy (decisions 044) ─────────────────────────────────────────────
1259
+ // ─── the roles, on the policy ─────────────────────────────────────────────
1260
1260
  //
1261
1261
  // Every write here goes to the pool's POLICY, not the manager: the manager holds no role. `policy`
1262
1262
  // may be passed when in hand (`FPoolState.policy`, `FPoolRoles.policy`); otherwise it is read once.
@@ -1276,7 +1276,7 @@ async function writePolicy(c: LogswapClient, abi: readonly unknown[], a: { poolI
1276
1276
  }
1277
1277
 
1278
1278
  /**
1279
- * Propose the next authority — step one of two (decisions 020), on the pool's policy. Nothing moves
1279
+ * Propose the next authority — step one of two, on the pool's policy. Nothing moves
1280
1280
  * until `next` accepts; proposing again (the zero address included) cancels a pending proposal.
1281
1281
  * Indexed on-chain via the policy's AuthorityProposed.
1282
1282
  */
@@ -1287,13 +1287,13 @@ export async function fPoolProposeAuthority(c: LogswapClient, a: { poolId: Hex;
1287
1287
  /**
1288
1288
  * Accept a pending proposal — step two; only the proposed address can. Indexed via the policy's
1289
1289
  * AuthoritySet. On the desk's policy this clears the operator (pending and accepted) and voids the
1290
- * seller's list (decisions 040, 044).
1290
+ * seller's list.
1291
1291
  */
1292
1292
  export async function fPoolAcceptAuthority(c: LogswapClient, a: { poolId: Hex; account: Address; policy?: Address }) {
1293
1293
  return writePolicy(c, fPolicyBaseAbi, a, "acceptAuthority", []);
1294
1294
  }
1295
1295
 
1296
- // ─── the desk's controls (PrivatePolicy; decisions 021, 044) ───────────────────────────────
1296
+ // ─── the desk's controls (PrivatePolicy) ───────────────────────────────
1297
1297
 
1298
1298
  /** Turn the mint / swap gates on or off (the authority, on the desk's policy). `burn` is never gated. */
1299
1299
  export async function fPoolSetGates(
@@ -1305,7 +1305,7 @@ export async function fPoolSetGates(
1305
1305
 
1306
1306
  /**
1307
1307
  * Add to or remove from the pool's MINTERS — who may mint, and swap (a zap in is both under one
1308
- * lock) — in one call (the authority, on the desk's policy; decisions 048). The list is keyed by
1308
+ * lock) — in one call (the authority, on the desk's policy). The list is keyed by
1309
1309
  * the authority that granted it: a handover starts the buyer with an empty one. Stamps the
1310
1310
  * block: no swap lands in it (047).
1311
1311
  */
@@ -1316,7 +1316,7 @@ export async function fPoolSetMinters(
1316
1316
  return writePolicy(c, privatePolicyAbi, a, "setMinters", [a.who, a.allowed]);
1317
1317
  }
1318
1318
 
1319
- /** Add to or remove from the pool's TAKERS — who may swap only — in one call (the authority; decisions 048). Stamps the block. */
1319
+ /** Add to or remove from the pool's TAKERS — who may swap only — in one call (the authority). Stamps the block. */
1320
1320
  export async function fPoolSetTakers(
1321
1321
  c: LogswapClient,
1322
1322
  a: { poolId: Hex; who: readonly Address[]; allowed: boolean; account: Address; policy?: Address },
@@ -1344,13 +1344,13 @@ export async function fPoolIsAllowed(c: LogswapClient, poolId: Hex, who: Address
1344
1344
  return readDesk<boolean>(c, poolId, who, "isAllowed", policy);
1345
1345
  }
1346
1346
 
1347
- /** Label the pool — the authority's own words on the pool's POLICY (decisions 049), mutable, never identity. At most 31 bytes of UTF-8. */
1347
+ /** Label the pool — the authority's own words on the pool's POLICY, mutable, never identity. At most 31 bytes of UTF-8. */
1348
1348
  export async function fPoolSetName(c: LogswapClient, a: { poolId: Hex; name: string; account: Address; policy?: Address }) {
1349
1349
  return writePolicy(c, fPolicyBaseAbi, a, "setName", [textToBytes32(a.name)]);
1350
1350
  }
1351
1351
 
1352
1352
  /**
1353
- * What the PROTOCOL says an address is — "Keyrock" — on the REGISTRY (decisions 049). Only its
1353
+ * What the PROTOCOL says an address is — "Keyrock" — on the REGISTRY. Only its
1354
1354
  * owner, the LOG authority, may write it, which is what makes it an attestation rather than a
1355
1355
  * claim anyone could make about themselves.
1356
1356
  */
@@ -1387,7 +1387,7 @@ async function registryAddress(c: LogswapClient): Promise<Address> {
1387
1387
  return registry;
1388
1388
  }
1389
1389
 
1390
- /** Who runs the pool (decisions 037): the appointed operator, or the authority until one is. */
1390
+ /** Who runs the pool: the appointed operator, or the authority until one is. */
1391
1391
  export function fPoolOperatorOf(s: Pick<FPoolRoles, "authority" | "operator">): Address {
1392
1392
  return s.operator === ZERO_ADDRESS ? s.authority : s.operator;
1393
1393
  }
@@ -1408,7 +1408,7 @@ export async function fPoolAcceptOperator(c: LogswapClient, a: { poolId: Hex; ac
1408
1408
 
1409
1409
  /**
1410
1410
  * The next generation's composition (operator; private pools only; ONLY while the pool is
1411
- * unseeded — between a retire and the seed that prices it, decisions 037). `weights` has one
1411
+ * unseeded — between a retire and the seed that prices it). `weights` has one
1412
1412
  * entry per leg the pool has ever had, in index order (0 retires a leg; indices are never reused),
1413
1413
  * then one per base in `newBases`, appended; they sum to 1e18 exactly. No value moves: the
1414
1414
  * following {@link fPoolSeed} names every reserve. A live reshape is {@link fPoolRelaunch} with
@@ -1451,7 +1451,7 @@ export interface DiscoveredFPool {
1451
1451
  weights: bigint[];
1452
1452
  phi: bigint;
1453
1453
  kind: FPoolKind;
1454
- /** The pool's policy AT BIRTH — the contract the key names (decisions 041, 044, 045). The LIVE one is {@link getFPool}'s `policy`: the registry's owner may have moved the pool (046, `PolicyMigrated`). */
1454
+ /** The pool's policy AT BIRTH — the contract the key names. The LIVE one is {@link getFPool}'s `policy`: the registry's owner may have moved the pool (046, `PolicyMigrated`). */
1455
1455
  policy: Address;
1456
1456
  /** Who was born holding the pool (immutable). The LIVE authority is the policy's — {@link getFPoolRoles}. */
1457
1457
  creator: Address;
@@ -1459,7 +1459,7 @@ export interface DiscoveredFPool {
1459
1459
  block: bigint;
1460
1460
  /** Whether `seed` has run; an unseeded pool has no floor and no float, so nothing to show. */
1461
1461
  seeded: boolean;
1462
- /** The quote the pool was born with. Zero is the launchpad's signature (launchpad.md §3). */
1462
+ /** The quote the pool was born with. Zero is the launchpad's signature. */
1463
1463
  q0: bigint;
1464
1464
  /**
1465
1465
  * The PRODUCT the pool is, by the spec's definition rather than a guess: a LAUNCH is one asset
@@ -1521,13 +1521,13 @@ export async function discoverFPools(
1521
1521
  block: l.blockNumber ?? 0n,
1522
1522
  seeded: q0 !== undefined,
1523
1523
  q0: q0 ?? 0n,
1524
- shape: kind === "pad" ? "launch" : "basket", // the policy's word, not n = 1: a mono POL is a pool (decisions 036, 049)
1524
+ shape: kind === "pad" ? "launch": "basket", // the policy's word, not n = 1: a mono POL is a pool
1525
1525
  };
1526
1526
  }),
1527
1527
  );
1528
1528
  }
1529
1529
 
1530
- // ─── the policy page: what an authority controls (decisions 044) ────────────────────────
1530
+ // ─── the policy page: what an authority controls ────────────────────────
1531
1531
  //
1532
1532
  // One policy serves every pool of its kind, so "the pools I control" is not a policy's list: it is
1533
1533
  // every pool whose policy answers `authority(poolId) == me`. Discovery from the log stream (or the
package/src/keys.ts CHANGED
@@ -25,7 +25,7 @@ export interface PoolKey {
25
25
  /**
26
26
  * The swap fee, WAD, fixed for the life of the market: `FEE_MIN` (1 bp) ≤ φ ≤ `FEE_MAX` (25%),
27
27
  * or `0n`, which selects `DEFAULT_FEE` (2 bp) at read time. Four fields since C version 4
28
- * (decisions 042): `kappa` and `alpha` left with the variance kernel, and `phiMin` — a floor with
28
+ *: `kappa` and `alpha` left with the variance kernel, and `phiMin` — a floor with
29
29
  * nothing above it — became `phi`. Every pool id changed with the shape.
30
30
  */
31
31
  phi: bigint;
package/src/liquidity.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * liquidity.ts — providing, editing and exiting a C position.
3
3
  *
4
4
  * A class is (ξ, μ, L): floor, cap, exposure. One primitive sets all three — `update` — and every
5
- * edit is a constraint on it. The vocabulary follows the geometry (decisions 009): **the verb
5
+ * edit is a constraint on it. The vocabulary follows the geometry: **the verb
6
6
  * names the axis, the direction is a signed rung count**, and only two direction-words survive,
7
7
  * because each names a wallet flow the user must see.
8
8
  *
@@ -15,7 +15,7 @@
15
15
  * └─ reprice(ξ') R pinned: L' = L·e^{ξ' − ξ}, dormant only
16
16
  * mint · burn · claim
17
17
  *
18
- * Every edit is ONE action of the router's batch (decisions 010, `actions.ts`), which is what
18
+ * Every edit is ONE action of the router's batch (`actions.ts`), which is what
19
19
  * lets it settle in kind, or in base, or in quote: `settleIn` appends the one swap that nets the
20
20
  * other side, and the batch moves a single token. `previewEdit` is the lens's `previewUpdate` —
21
21
  * the exact flows, mint fee and swept fees included — and is what an editor shows before its one
@@ -99,7 +99,7 @@ export async function mint(c: LogswapClient, a: MintArgs): Promise<Hash> {
99
99
 
100
100
  export interface CreateMarketArgs extends WriteOptions {
101
101
  key: PoolKey;
102
- /** Launch log-price. Bounded by the manager to ±46 (the price domain, decisions 012). */
102
+ /** Launch log-price. Bounded by the manager to ±46 (the price domain). */
103
103
  x0: bigint;
104
104
  /** The backstop's floor — the first mint's rung, permanent for the pool's life. */
105
105
  targetFloor: bigint;
@@ -112,7 +112,7 @@ export interface CreateMarketArgs extends WriteOptions {
112
112
 
113
113
  /**
114
114
  * Create a market ATOMICALLY: `initialize` at `x0` plus the backstop-establishing first mint in
115
- * one transaction — the canonical creation path (decisions 013, security-review H-02). The
115
+ * one transaction — the canonical creation path. The
116
116
  * two-step path let an attacker seat the PERMANENT backstop at a hostile rung between an honest
117
117
  * `initialize` and its first mint; here either both land or neither, and a front-run of the whole
118
118
  * call reverts it without moving a wei. No cap: the first mint IS the backstop and must be
@@ -140,7 +140,7 @@ export interface ZapArgs extends WriteOptions {
140
140
  /** Fund entirely from base (true) or entirely from quote (false). */
141
141
  fundWithBase: boolean;
142
142
  amountIn: bigint;
143
- /** The least the swap leg may return (contracts 7c82eed, decisions 043): the zap's own slippage bound, as `swapExactIn`'s. Required. */
143
+ /** The least the swap leg may return: the zap's own slippage bound, as `swapExactIn`'s. Required. */
144
144
  minSwapOut: bigint;
145
145
  targetFloor: bigint;
146
146
  cap?: bigint;
@@ -155,7 +155,7 @@ export interface ZapArgs extends WriteOptions {
155
155
  *
156
156
  * Routing the imbalanced part through the CURVE is the point, not an implementation detail. A
157
157
  * pro-rata deposit of one asset would be a zero-slippage, zero-fee swap at stale spot — a subsidy
158
- * paid by the incumbent LPs (`logswap-docs` §*Quote-only capital*). Paying the curve removes it.
158
+ * paid by the incumbent LPs. Paying the curve removes it.
159
159
  */
160
160
  export async function zapIn(c: LogswapClient, a: ZapArgs): Promise<Hash> {
161
161
  return sendRouterWriteWithPermits(c, {
@@ -226,7 +226,7 @@ export interface MoveArgs extends WriteOptions {
226
226
  * Reposition at constant exposure — the L-pinned parent of `floor`, `cap` and `shift`; in kind.
227
227
  *
228
228
  * **Bound it.** The router used to settle this entry with no limit, which meant a reposition that
229
- * priced differently by inclusion time could pull the whole allowance (security-review2 M-01).
229
+ * priced differently by inclusion time could pull the whole allowance.
230
230
  * The bounds are required; {@link UNBOUNDED} is an explicit, visible opt-out.
231
231
  */
232
232
  export async function move(c: LogswapClient, a: MoveArgs): Promise<Hash> {
@@ -325,7 +325,7 @@ export async function edit(c: LogswapClient, a: EditArgs & { toFloor: bigint; to
325
325
  if (settleIn === "kind") {
326
326
  settle = settleInKind(key, recipient, { ...boundsFromFlows(p.dBase, p.dQuote, a.slippageBps), ...defined(a) });
327
327
  } else {
328
- // the swept fees ride INSIDE dQuote (the manager burns by owner and nets them; decisions 018),
328
+ // the swept fees ride INSIDE dQuote (the manager burns by owner and nets them),
329
329
  // so quote's open delta after the update is dQuote itself — `fees` is reported for display only
330
330
  const otherFlow = settleIn === "base" ? p.dQuote : p.dBase; // + = owed, − = released
331
331
  const otherIsBase = settleIn === "quote";