@logswap/sdk 0.5.47 → 0.5.49

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
@@ -14,15 +14,15 @@
14
14
  *
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
- * structurally) and the HOOK (the pool's policy: its roles, its gates, the terms of every harvest
17
+ * structurally) and the POLICY (the pool's policy: its roles, its gates, the terms of every harvest
18
18
  * and release; decisions 041, 044) — 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
- * **The roles are the hook's, not the manager's** (F version 15). The manager holds no
22
- * authority, operator, gate or list: it asks the pool's hook `may(who, action)` and acts on the
23
- * answer. So `getFPool` carries the hook and what it declared, {@link getFPoolRoles} reads the
24
- * roles FROM the hook, and every role write — the handover, the operator, the gates, the list —
25
- * is a write to the hook ({@link fPoolProposeAuthority}, {@link fPoolSetGates}, …).
21
+ * **The roles are the policy's, not the manager's** (F version 15). The manager holds no
22
+ * authority, operator, gate or list: it asks the pool's policy `may(who, action)` and acts on the
23
+ * answer. So `getFPool` carries the policy and what it declared, {@link getFPoolRoles} reads the
24
+ * roles FROM the policy, and every role write — the handover, the operator, the gates, the list —
25
+ * is a write to the policy ({@link fPoolProposeAuthority}, {@link fPoolSetGates}, …).
26
26
  *
27
27
  * **Zaps live on the ROUTER, not here.** Permit2 is AllowanceTransfer mode, whose standing
28
28
  * allowance is keyed by spender, so a second router would cost the user an allowance per token
@@ -31,28 +31,28 @@
31
31
  */
32
32
 
33
33
  import { encodeFunctionData, toFunctionSelector, type Address, type Hash, type Hex } from "viem";
34
- import { fPoolManagerAbi, logswapRouterAbi, padHookAbi, polHookAbi, privateHookAbi, publicHookAbi } from "./generated.js";
34
+ import { fPoolManagerAbi, logswapRouterAbi, padPolicyAbi, polPolicyAbi, privatePolicyAbi, publicPolicyAbi } from "./generated.js";
35
35
 
36
36
  /**
37
37
  * One contract, one ABI (decisions 039, 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 hooks in F version 15 (decisions 044): {@link fHookBaseAbi} is what every hook shares,
40
- * {@link privateHookAbi} the desk's, {@link padHookAbi} / {@link polHookAbi} / {@link publicHookAbi}
39
+ * the policies in F version 15 (decisions 044): {@link fPolicyBaseAbi} is what every policy shares,
40
+ * {@link privatePolicyAbi} the desk's, {@link padPolicyAbi} / {@link polPolicyAbi} / {@link publicPolicyAbi}
41
41
  * the kinds'.
42
42
  */
43
- export { fPoolManagerAbi, padHookAbi, polHookAbi, privateHookAbi, publicHookAbi };
43
+ export { fPoolManagerAbi, padPolicyAbi, polPolicyAbi, privatePolicyAbi, publicPolicyAbi };
44
44
  /**
45
- * What every protocol hook shares (`FHookBase`): the roles and their handover, `harvestCut`,
46
- * `maxHarvest`. `polHookAbi` is a superset of it and carries nothing that collides, so it stands
47
- * in for the base — a call through it to any of the four hooks decodes the base's functions.
45
+ * What every protocol policy shares (`FPolicyBase`): the roles and their handover, `harvestCut`,
46
+ * `maxHarvest`. `polPolicyAbi` is a superset of it and carries nothing that collides, so it stands
47
+ * in for the base — a call through it to any of the four policies decodes the base's functions.
48
48
  */
49
- export const fHookBaseAbi = polHookAbi;
49
+ export const fPolicyBaseAbi = polPolicyAbi;
50
50
  import type { LogswapClient } from "./client.js";
51
51
 
52
52
  const WAD = 10n ** 18n;
53
53
  const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" as const;
54
54
 
55
- /** The optional questions a hook declared at birth (decisions 044), as bits of `Pool.asks`. */
55
+ /** The optional questions a policy declared at birth (decisions 044), as bits of `Pool.asks`. */
56
56
  export const ASK_SWAP = 1;
57
57
  export const ASK_MINT = 2;
58
58
 
@@ -83,10 +83,10 @@ export interface FPoolState {
83
83
  /**
84
84
  * The pool's policy (decisions 041, 044): the contract the key names, holding the pool's roles
85
85
  * and answering every question the manager does not decide itself. Read its roles with
86
- * {@link getFPoolRoles}; one of the deployment's four ({@link fPoolHookFor}) on every protocol pool.
86
+ * {@link getFPoolRoles}; one of the deployment's four ({@link fPoolPolicyFor}) on every protocol pool.
87
87
  */
88
- hook: Address;
89
- /** Whether the hook asked to be consulted on swaps ({@link ASK_SWAP}) and mints ({@link ASK_MINT}) — the desk's hook does, no other. */
88
+ policy: Address;
89
+ /** Whether the policy asked to be consulted on swaps ({@link ASK_SWAP}) and mints ({@link ASK_MINT}) — the desk's policy does, no other. */
90
90
  asks: number;
91
91
  /** The sponsor's own label for this pool, mutable and never identity. "" when unnamed. */
92
92
  name: string;
@@ -120,11 +120,11 @@ export async function getFPool(c: LogswapClient, poolId: Hex): Promise<FPoolStat
120
120
  } as never) as Promise<T>;
121
121
 
122
122
  // `getPool` returns the whole scalar struct in one call — the singleton's shape makes what used
123
- // to be a dozen getters a single read. No role in it since F version 15: those are the hook's.
123
+ // to be a dozen getters a single read. No role in it since F version 15: those are the policy's.
124
124
  const p = await rd<{
125
125
  quote: Address;
126
126
  phi: bigint;
127
- hook: Address;
127
+ policy: Address;
128
128
  kind: number;
129
129
  seeded: boolean;
130
130
  gen: number;
@@ -160,7 +160,7 @@ export async function getFPool(c: LogswapClient, poolId: Hex): Promise<FPoolStat
160
160
  const weights = legs.map((l) => l[1]);
161
161
  const x = legs.map((l) => l[2]); // derived by the manager: x_j = ln(w_j·L / R_j) (decisions 026)
162
162
  const reserves = legs.map((l) => l[3]); // the state
163
- const { quote, Q, L, phi, theta0, bigSigma, hook, restructureBlock, seeded, gen } = p;
163
+ const { quote, Q, L, phi, theta0, bigSigma, policy, restructureBlock, seeded, gen } = p;
164
164
  const totalSupply = p.shares;
165
165
 
166
166
  return {
@@ -176,7 +176,7 @@ export async function getFPool(c: LogswapClient, poolId: Hex): Promise<FPoolStat
176
176
  theta,
177
177
  compositeX,
178
178
  bigSigma,
179
- hook,
179
+ policy,
180
180
  asks: Number(p.asks),
181
181
  name: bytes32ToText(p.name),
182
182
  restructureBlock: Number(restructureBlock),
@@ -190,13 +190,13 @@ export async function getFPool(c: LogswapClient, poolId: Hex): Promise<FPoolStat
190
190
 
191
191
  /**
192
192
  * The kind of pool (decisions 036, 038, 044) — what the manager promises structurally, whatever
193
- * the pool's hook answers. `public`: the protocol's own pool — its hook requires the collector as
194
- * creator; no gate, no operator. `private`, the desk: the one kind whose hook may gate swaps and
193
+ * the pool's policy answers. `public`: the protocol's own pool — its policy requires the collector as
194
+ * creator; no gate, no operator. `private`, the desk: the one kind whose policy may gate swaps and
195
195
  * mints, with an operator that reshapes the legs between generations. `pol`, a treasury's pool
196
196
  * or a basket: composition and access fixed at birth. `pad`, a launch: a POL whose harvest is
197
- * income only whatever its hook says and whose seed the contract minted to 0xdead — one asset,
197
+ * income only whatever its policy says and whose seed the contract minted to 0xdead — one asset,
198
198
  * open to all. private → pol → pad is the ladder of rigidity; public is a pol held by the
199
- * protocol. Every rate, role and gate is the hook's.
199
+ * protocol. Every rate, role and gate is the policy's.
200
200
  */
201
201
  export type FPoolKind = "public" | "private" | "pol" | "pad";
202
202
  /** The key's enum values. */
@@ -208,35 +208,35 @@ export function fPoolKindOf(n: number | bigint): FPoolKind {
208
208
  return k;
209
209
  }
210
210
 
211
- /** The deployment's hook for a kind (decisions 044): what a key of that kind names. */
212
- export function fPoolHookFor(c: LogswapClient, kind: FPoolKind): Address {
211
+ /** The deployment's policy for a kind (decisions 044): what a key of that kind names. */
212
+ export function fPoolPolicyFor(c: LogswapClient, kind: FPoolKind): Address {
213
213
  const a = c.addresses;
214
- const hook = kind === "public" ? a.publicHook : kind === "private" ? a.privateHook : kind === "pol" ? a.polHook : a.padHook;
215
- if (!hook) throw new Error(`logswap: this deployment carries no ${kind} hook`);
216
- return hook;
214
+ const policy = kind === "public" ? a.publicPolicy : kind === "private" ? a.privatePolicy : kind === "pol" ? a.polPolicy : a.padPolicy;
215
+ if (!policy) throw new Error(`logswap: this deployment carries no ${kind} policy`);
216
+ return policy;
217
217
  }
218
218
 
219
- /** The hook a pool named in its key — one read; {@link getFPool} carries it too. */
220
- export async function fPoolHookOf(c: LogswapClient, poolId: Hex): Promise<Address> {
219
+ /** The policy a pool named in its key — one read; {@link getFPool} carries it too. */
220
+ export async function fPoolPolicyOf(c: LogswapClient, poolId: Hex): Promise<Address> {
221
221
  const p = (await c.public.readContract({
222
222
  address: c.addresses.fPoolManager!,
223
223
  abi: fPoolManagerAbi,
224
224
  functionName: "getPool",
225
225
  args: [poolId],
226
- } as never)) as { quote: Address; hook: Address };
226
+ } as never)) as { quote: Address; policy: Address };
227
227
  if (/^0x0{40}$/i.test(p.quote)) throw new Error(`logswap: no F pool with id ${poolId}`);
228
- return p.hook;
228
+ return p.policy;
229
229
  }
230
230
 
231
231
  /**
232
- * A pool's roles, as its HOOK holds them (decisions 044). `creator` is immutable identity —
232
+ * A pool's roles, as its POLICY holds them (decisions 044). `creator` is immutable identity —
233
233
  * who was born holding the pool; `authority` is the cold key that owns it now, the creator until
234
234
  * a two-step handover; on the desk's kind the `operator` runs it (zero = the authority itself,
235
235
  * {@link fPoolOperatorOf}) and the two gates and the list are its. Every other kind has no
236
236
  * operator and no gate: those fields read zero / false.
237
237
  */
238
238
  export interface FPoolRoles {
239
- hook: Address;
239
+ policy: Address;
240
240
  creator: Address;
241
241
  authority: Address;
242
242
  /** The proposed next authority, until it accepts — zero when nothing is pending (decisions 020). */
@@ -245,31 +245,31 @@ export interface FPoolRoles {
245
245
  pendingOperator: Address;
246
246
  gateMint: boolean;
247
247
  gateSwap: boolean;
248
- /** The hook's own ceiling on a harvest now — the manager's `harvestable` narrowed by the hook's rule. */
248
+ /** The policy's own ceiling on a harvest now — the manager's `harvestable` narrowed by the policy's rule. */
249
249
  maxHarvest: bigint;
250
250
  }
251
251
 
252
- /** Read a pool's roles from its hook. `state` saves the `getPool` round trip when already in hand. */
253
- export async function getFPoolRoles(c: LogswapClient, poolId: Hex, state?: Pick<FPoolState, "hook" | "kind">): Promise<FPoolRoles> {
252
+ /** Read a pool's roles from its policy. `state` saves the `getPool` round trip when already in hand. */
253
+ export async function getFPoolRoles(c: LogswapClient, poolId: Hex, state?: Pick<FPoolState, "policy" | "kind">): Promise<FPoolRoles> {
254
254
  const s = state ?? (await getFPool(c, poolId));
255
- const rdHook = <T>(abi: readonly unknown[], functionName: string) =>
256
- c.public.readContract({ address: s.hook, abi, functionName, args: [poolId] } as never) as Promise<T>;
255
+ const rdPolicy = <T>(abi: readonly unknown[], functionName: string) =>
256
+ c.public.readContract({ address: s.policy, abi, functionName, args: [poolId] } as never) as Promise<T>;
257
257
  const [creator, authority, pendingAuthority, maxHarvest] = await Promise.all([
258
- rdHook<Address>(fHookBaseAbi, "creator"),
259
- rdHook<Address>(fHookBaseAbi, "authority"),
260
- rdHook<Address>(fHookBaseAbi, "pendingAuthority"),
261
- rdHook<bigint>(fHookBaseAbi, "maxHarvest"),
258
+ rdPolicy<Address>(fPolicyBaseAbi, "creator"),
259
+ rdPolicy<Address>(fPolicyBaseAbi, "authority"),
260
+ rdPolicy<Address>(fPolicyBaseAbi, "pendingAuthority"),
261
+ rdPolicy<bigint>(fPolicyBaseAbi, "maxHarvest"),
262
262
  ]);
263
263
  const desk = s.kind === "private";
264
264
  const [operator, pendingOperator, gateMint, gateSwap] = desk
265
265
  ? await Promise.all([
266
- rdHook<Address>(privateHookAbi, "operator"),
267
- rdHook<Address>(privateHookAbi, "pendingOperator"),
268
- rdHook<boolean>(privateHookAbi, "gateMint"),
269
- rdHook<boolean>(privateHookAbi, "gateSwap"),
266
+ rdPolicy<Address>(privatePolicyAbi, "operator"),
267
+ rdPolicy<Address>(privatePolicyAbi, "pendingOperator"),
268
+ rdPolicy<boolean>(privatePolicyAbi, "gateMint"),
269
+ rdPolicy<boolean>(privatePolicyAbi, "gateSwap"),
270
270
  ])
271
271
  : [ZERO_ADDRESS, ZERO_ADDRESS, false, false];
272
- return { hook: s.hook, creator, authority, pendingAuthority, operator, pendingOperator, gateMint, gateSwap, maxHarvest };
272
+ return { policy: s.policy, creator, authority, pendingAuthority, operator, pendingOperator, gateMint, gateSwap, maxHarvest };
273
273
  }
274
274
 
275
275
  /** Which of the two products a pool is configured as — a pad is a launch, anything else a basket/pool. A UI has to choose what to render. */
@@ -287,7 +287,7 @@ export interface FPoolDescription {
287
287
  * from the first wei after it.
288
288
  */
289
289
  unharvested: bigint;
290
- /** The most a harvest may take now by the KIND's promise: the bid, and on a pad the income. The hook may allow less — {@link FPoolRoles.maxHarvest}. */
290
+ /** 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}. */
291
291
  harvestable: bigint;
292
292
  /** The dead shares' banked dividend — a pad's pot, the creator's income until a rung is climbed (decisions 041). */
293
293
  pot: bigint;
@@ -870,11 +870,11 @@ export interface FPoolCreateArgs {
870
870
  kind: FPoolKind;
871
871
  /**
872
872
  * The pool's policy (decisions 041, 044): the contract the key names, approved by the protocol
873
- * for the kind. Defaults to the deployment's hook for `kind` ({@link fPoolHookFor}) — the one
873
+ * for the kind. Defaults to the deployment's policy for `kind` ({@link fPoolPolicyFor}) — the one
874
874
  * every protocol pool names.
875
875
  */
876
- hook?: Address;
877
- /** Who is born holding the pool: immutable identity, the pool's first authority (the hook records it). */
876
+ policy?: Address;
877
+ /** Who is born holding the pool: immutable identity, the pool's first authority (the policy records it). */
878
878
  creator: Address;
879
879
  /**
880
880
  * The differentiator, and nothing else. Identity is the key's hash, so one sponsor cannot run
@@ -909,7 +909,7 @@ export function sortFPoolLegs<T>(bases: Address[], ...companions: T[][]): { base
909
909
  return { bases: idx.map((i) => bases[i]!), companions: companions.map((arr) => idx.map((i) => arr[i]!)) };
910
910
  }
911
911
 
912
- /** The key as the manager hashes it: legs sorted, the kind's hook filled in when none is named. */
912
+ /** The key as the manager hashes it: legs sorted, the kind's policy filled in when none is named. */
913
913
  export function fPoolKeyOf(c: LogswapClient, a: Omit<FPoolCreateArgs, "account">) {
914
914
  const { bases, companions } = sortFPoolLegs(a.bases, a.weights);
915
915
  return {
@@ -918,7 +918,7 @@ export function fPoolKeyOf(c: LogswapClient, a: Omit<FPoolCreateArgs, "account">
918
918
  weights: companions[0]!,
919
919
  phi: a.phi,
920
920
  kind: F_KIND[a.kind],
921
- hook: a.hook ?? fPoolHookFor(c, a.kind),
921
+ policy: a.policy ?? fPoolPolicyFor(c, a.kind),
922
922
  creator: a.creator,
923
923
  salt: a.salt ?? ZERO_SALT,
924
924
  };
@@ -984,7 +984,7 @@ export async function fPoolSeed(
984
984
  * operator harvested it out first ({@link fPoolRetire} does both in one transaction). The live
985
985
  * (S, Q, R_j) become a frozen bundle every share of this generation redeems ({@link fPoolRedeem})
986
986
  * or rolls ({@link fPoolRollIn}), forever; the pool is unseeded until the next {@link fPoolSeed},
987
- * which opens generation `gen + 1` under the same id, hook, roles, gates and lists.
987
+ * which opens generation `gen + 1` under the same id, policy, roles, gates and lists.
988
988
  */
989
989
  export async function fPoolRetireRaw(c: LogswapClient, a: { poolId: Hex; account: Address }) {
990
990
  return writeFPool(c, a.poolId, "retire", [], a.account);
@@ -1010,25 +1010,25 @@ export async function fPoolRetire(c: LogswapClient, a: { poolId: Hex; account: A
1010
1010
  * `retire` (decisions 035: a retire needs an empty bid on every pool). Since F version 14 one
1011
1011
  * `harvest(Q)` does it: the protocol's cut leaves the pool with the amount (with no collector
1012
1012
  * there is no cut). `[]` when the bid is already empty. Throws on a pad that still bids (its bid
1013
- * empties only as the market sells it down), and when the pool's hook keeps a floor on the bid
1014
- * (`PolHook.keepQuote`, decisions 044): a `retire` under that hook waits for the market.
1013
+ * empties only as the market sells it down), and when the pool's policy keeps a floor on the bid
1014
+ * (`PolPolicy.keepQuote`, decisions 044): a `retire` under that policy waits for the market.
1015
1015
  */
1016
1016
  export async function fPoolEmptyingHarvests(c: LogswapClient, poolId: Hex): Promise<bigint[]> {
1017
1017
  const s = await getFPool(c, poolId);
1018
1018
  if (s.Q === 0n) return [];
1019
1019
  if (s.kind === "pad") throw new Error("logswap: a pad is retired only once its bid is empty (decisions 035)");
1020
1020
  const { maxHarvest } = await getFPoolRoles(c, poolId, s);
1021
- if (maxHarvest < s.Q) throw new Error("logswap: the pool's hook keeps a floor on the bid — it cannot be harvested empty (decisions 044)");
1021
+ 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)");
1022
1022
  return [s.Q];
1023
1023
  }
1024
1024
 
1025
1025
  /**
1026
- * Release the dead shares' pot under the hook's terms (decisions 041, 044) — a pad's graduation.
1026
+ * Release the dead shares' pot under the policy's terms (decisions 041, 044) — a pad's graduation.
1027
1027
  * The manager harvests the generation's income first (the pot then holds everything the dead
1028
- * shares earned), asks the hook, and applies its answer: a share to the payee it names (the pad's
1028
+ * shares earned), asks the policy, and applies its answer: a share to the payee it names (the pad's
1029
1029
  * creator — the pool's authority), a cut to the collector, the rest bought in as more of the
1030
- * float the pool owns, a slice of every reserve burned. The hook refuses under its rung's
1031
- * threshold (`PadHook.NotGraduated`). Whoever runs the pool.
1030
+ * float the pool owns, a slice of every reserve burned. The policy refuses under its rung's
1031
+ * threshold (`PadPolicy.NotGraduated`). Whoever runs the pool.
1032
1032
  */
1033
1033
  export async function fPoolRegenerate(c: LogswapClient, a: { poolId: Hex; to?: Address; account: Address }) {
1034
1034
  return writeFPool(c, a.poolId, "regenerate", [a.to ?? a.account], a.account);
@@ -1041,7 +1041,7 @@ export async function fPoolRegenerate(c: LogswapClient, a: { poolId: Hex; to?: A
1041
1041
  * next generation's composition (`legs`: a private pool's reshape — retire, admit, reweight), and
1042
1042
  * `seed` it with what came back — the manager's `multicall`, one sender throughout, the same
1043
1043
  * pool. The operator's when one is appointed and the seed's inventory is its own; by default the
1044
- * authority's. The hook, its roles, gates, allowlist and the name carry over; anything else goes
1044
+ * authority's. The policy, its roles, gates, allowlist and the name carry over; anything else goes
1045
1045
  * in `extra`, pre-encoded against {@link fPoolManagerAbi}. The seed names reserves (decisions
1046
1046
  * 029): `r0` outright — one per leg of the NEXT table, 0 for a retired leg — or `x0` marks
1047
1047
  * against the next table's `weights`.
@@ -1120,8 +1120,8 @@ export function fPoolLaunchCalls(
1120
1120
  const given = "r0" in a ? a.r0 : a.x0.map((x, j) => fPoolReserveAt((a.weights[j]! * a.L0) / WAD, x));
1121
1121
  if (given.length !== a.bases.length) throw new Error(`logswap: ${given.length} reserves for ${a.bases.length} legs`);
1122
1122
  const { bases, companions } = sortFPoolLegs(a.bases, a.weights, given);
1123
- if (!a.hook) throw new Error("logswap: fPoolLaunchCalls needs the key's hook — fPoolLaunch fills it from the deployment");
1124
- const key = { quote: a.quote, bases, weights: companions[0]!, phi: a.phi, kind: F_KIND[a.kind], hook: a.hook, creator: a.creator, salt: a.salt ?? ZERO_SALT };
1123
+ if (!a.policy) throw new Error("logswap: fPoolLaunchCalls needs the key's policy — fPoolLaunch fills it from the deployment");
1124
+ const key = { quote: a.quote, bases, weights: companions[0]!, phi: a.phi, kind: F_KIND[a.kind], policy: a.policy, creator: a.creator, salt: a.salt ?? ZERO_SALT };
1125
1125
  const enc = (functionName: string, args: unknown[]) =>
1126
1126
  encodeFunctionData({ abi: fPoolManagerAbi, functionName, args } as never) as Hex;
1127
1127
  const calls: Hex[] = [];
@@ -1135,22 +1135,22 @@ export function fPoolLaunchCalls(
1135
1135
  calls.push(enc("swapQuoteIn", [poolId, BigInt(j), a.openBuy.amountIn, a.openBuy.minOut ?? 0n, a.account]));
1136
1136
  }
1137
1137
  if (a.name) calls.push(enc("setName", [poolId, textToBytes32(a.name)]));
1138
- // the desk's gates and list are the HOOK's (decisions 044), not the manager's: they cannot ride
1138
+ // the desk's gates and list are the POLICY's (decisions 044), not the manager's: they cannot ride
1139
1139
  // in this batch — `fPoolDeskOpening` sends them right after, as the same creator
1140
1140
  calls.push(...(a.extra ?? []));
1141
1141
  return calls;
1142
1142
  }
1143
1143
 
1144
1144
  /**
1145
- * The desk's opening posture, on its hook (decisions 044): gated minting, the creator listed. No
1145
+ * The desk's opening posture, on its policy (decisions 044): gated minting, the creator listed. No
1146
1146
  * appointment: the authority is the operator until one is appointed (decisions 037). Two writes
1147
- * to `PrivateHook`; the launch batch cannot carry them (they are not manager calls).
1147
+ * to `PrivatePolicy`; the launch batch cannot carry them (they are not manager calls).
1148
1148
  */
1149
- export async function fPoolDeskOpening(c: LogswapClient, a: { poolId: Hex; account: Address; hook?: Address }): Promise<Hash[]> {
1150
- const hook = a.hook ?? fPoolHookFor(c, "private");
1149
+ export async function fPoolDeskOpening(c: LogswapClient, a: { poolId: Hex; account: Address; policy?: Address }): Promise<Hash[]> {
1150
+ const policy = a.policy ?? fPoolPolicyFor(c, "private");
1151
1151
  return [
1152
- await fPoolSetGates(c, { poolId: a.poolId, gateMint: true, gateSwap: false, account: a.account, hook }),
1153
- await fPoolSetAllowed(c, { poolId: a.poolId, who: [a.account], allowed: true, account: a.account, hook }),
1152
+ await fPoolSetGates(c, { poolId: a.poolId, gateMint: true, gateSwap: false, account: a.account, policy }),
1153
+ await fPoolSetAllowed(c, { poolId: a.poolId, who: [a.account], allowed: true, account: a.account, policy }),
1154
1154
  ];
1155
1155
  }
1156
1156
 
@@ -1176,22 +1176,22 @@ export async function fPoolLaunch(
1176
1176
  a: FPoolLaunchArgs & ({ r0: bigint[] } | { x0: bigint[] }),
1177
1177
  ): Promise<{ hash: Hash; poolId: Hex }> {
1178
1178
  const poolId = await fPoolIdOf(c, a);
1179
- const calls = fPoolLaunchCalls(poolId, { ...a, hook: a.hook ?? fPoolHookFor(c, a.kind) });
1179
+ const calls = fPoolLaunchCalls(poolId, { ...a, policy: a.policy ?? fPoolPolicyFor(c, a.kind) });
1180
1180
  const hash = await writeFPool0(c, "multicall", [calls], a.account);
1181
1181
  return { hash, poolId };
1182
1182
  }
1183
1183
 
1184
- // ─── the roles, on the hook (decisions 044) ─────────────────────────────────────────────
1184
+ // ─── the roles, on the policy (decisions 044) ─────────────────────────────────────────────
1185
1185
  //
1186
- // Every write here goes to the pool's HOOK, not the manager: the manager holds no role. `hook`
1187
- // may be passed when in hand (`FPoolState.hook`, `FPoolRoles.hook`); otherwise it is read once.
1186
+ // Every write here goes to the pool's POLICY, not the manager: the manager holds no role. `policy`
1187
+ // may be passed when in hand (`FPoolState.policy`, `FPoolRoles.policy`); otherwise it is read once.
1188
1188
 
1189
- /** A write keyed by poolId, on the pool's hook. */
1190
- async function writeHook(c: LogswapClient, abi: readonly unknown[], a: { poolId: Hex; hook?: Address; account: Address }, functionName: string, args: unknown[]) {
1189
+ /** A write keyed by poolId, on the pool's policy. */
1190
+ async function writePolicy(c: LogswapClient, abi: readonly unknown[], a: { poolId: Hex; policy?: Address; account: Address }, functionName: string, args: unknown[]) {
1191
1191
  const wallet = requireWallet(c);
1192
- const hook = a.hook ?? (await fPoolHookOf(c, a.poolId));
1192
+ const policy = a.policy ?? (await fPoolPolicyOf(c, a.poolId));
1193
1193
  const { request } = await c.public.simulateContract({
1194
- address: hook,
1194
+ address: policy,
1195
1195
  abi,
1196
1196
  functionName,
1197
1197
  args: [a.poolId, ...args],
@@ -1201,50 +1201,50 @@ async function writeHook(c: LogswapClient, abi: readonly unknown[], a: { poolId:
1201
1201
  }
1202
1202
 
1203
1203
  /**
1204
- * Propose the next authority — step one of two (decisions 020), on the pool's hook. Nothing moves
1204
+ * Propose the next authority — step one of two (decisions 020), on the pool's policy. Nothing moves
1205
1205
  * until `next` accepts; proposing again (the zero address included) cancels a pending proposal.
1206
- * Indexed on-chain via the hook's AuthorityProposed.
1206
+ * Indexed on-chain via the policy's AuthorityProposed.
1207
1207
  */
1208
- export async function fPoolProposeAuthority(c: LogswapClient, a: { poolId: Hex; next: Address; account: Address; hook?: Address }) {
1209
- return writeHook(c, fHookBaseAbi, a, "proposeAuthority", [a.next]);
1208
+ export async function fPoolProposeAuthority(c: LogswapClient, a: { poolId: Hex; next: Address; account: Address; policy?: Address }) {
1209
+ return writePolicy(c, fPolicyBaseAbi, a, "proposeAuthority", [a.next]);
1210
1210
  }
1211
1211
 
1212
1212
  /**
1213
- * Accept a pending proposal — step two; only the proposed address can. Indexed via the hook's
1214
- * AuthoritySet. On the desk's hook this clears the operator (pending and accepted) and voids the
1213
+ * Accept a pending proposal — step two; only the proposed address can. Indexed via the policy's
1214
+ * AuthoritySet. On the desk's policy this clears the operator (pending and accepted) and voids the
1215
1215
  * seller's list (decisions 040, 044).
1216
1216
  */
1217
- export async function fPoolAcceptAuthority(c: LogswapClient, a: { poolId: Hex; account: Address; hook?: Address }) {
1218
- return writeHook(c, fHookBaseAbi, a, "acceptAuthority", []);
1217
+ export async function fPoolAcceptAuthority(c: LogswapClient, a: { poolId: Hex; account: Address; policy?: Address }) {
1218
+ return writePolicy(c, fPolicyBaseAbi, a, "acceptAuthority", []);
1219
1219
  }
1220
1220
 
1221
- // ─── the desk's controls (PrivateHook; decisions 021, 044) ───────────────────────────────
1221
+ // ─── the desk's controls (PrivatePolicy; decisions 021, 044) ───────────────────────────────
1222
1222
 
1223
- /** Turn the mint / swap gates on or off (the authority, on the desk's hook). `burn` is never gated. */
1223
+ /** Turn the mint / swap gates on or off (the authority, on the desk's policy). `burn` is never gated. */
1224
1224
  export async function fPoolSetGates(
1225
1225
  c: LogswapClient,
1226
- a: { poolId: Hex; gateMint: boolean; gateSwap: boolean; account: Address; hook?: Address },
1226
+ a: { poolId: Hex; gateMint: boolean; gateSwap: boolean; account: Address; policy?: Address },
1227
1227
  ) {
1228
- return writeHook(c, privateHookAbi, a, "setGates", [a.gateMint, a.gateSwap]);
1228
+ return writePolicy(c, privatePolicyAbi, a, "setGates", [a.gateMint, a.gateSwap]);
1229
1229
  }
1230
1230
 
1231
1231
  /**
1232
- * Add to or remove from the pool's list, in one call (the authority, on the desk's hook). The list
1232
+ * Add to or remove from the pool's list, in one call (the authority, on the desk's policy). The list
1233
1233
  * is keyed by the authority that granted it: a handover starts the buyer with an empty one.
1234
1234
  */
1235
1235
  export async function fPoolSetAllowed(
1236
1236
  c: LogswapClient,
1237
- a: { poolId: Hex; who: readonly Address[]; allowed: boolean; account: Address; hook?: Address },
1237
+ a: { poolId: Hex; who: readonly Address[]; allowed: boolean; account: Address; policy?: Address },
1238
1238
  ) {
1239
- return writeHook(c, privateHookAbi, a, "setAllowed", [a.who, a.allowed]);
1239
+ return writePolicy(c, privatePolicyAbi, a, "setAllowed", [a.who, a.allowed]);
1240
1240
  }
1241
1241
 
1242
1242
  /** Whether `who` is on the pool's list under its current authority (consulted only while a gate is on). */
1243
- export async function fPoolIsAllowed(c: LogswapClient, poolId: Hex, who: Address, hook?: Address): Promise<boolean> {
1244
- const address = hook ?? (await fPoolHookOf(c, poolId));
1243
+ export async function fPoolIsAllowed(c: LogswapClient, poolId: Hex, who: Address, policy?: Address): Promise<boolean> {
1244
+ const address = policy ?? (await fPoolPolicyOf(c, poolId));
1245
1245
  return (await c.public.readContract({
1246
1246
  address,
1247
- abi: privateHookAbi,
1247
+ abi: privatePolicyAbi,
1248
1248
  functionName: "isAllowed",
1249
1249
  args: [poolId, who],
1250
1250
  } as never)) as boolean;
@@ -1288,17 +1288,17 @@ export function fPoolOperatorOf(s: Pick<FPoolRoles, "authority" | "operator">):
1288
1288
  }
1289
1289
 
1290
1290
  /**
1291
- * Propose the operator (the authority, on the desk's hook) — the hot key that runs the pool:
1291
+ * Propose the operator (the authority, on the desk's policy) — the hot key that runs the pool:
1292
1292
  * `harvest`, `retire`, `regenerate`, `setLegs`. Two-step: the proposed address takes the role with
1293
1293
  * {@link fPoolAcceptOperator}. The zero address clears at once — the role returns to the authority.
1294
1294
  */
1295
- export async function fPoolAppointOperator(c: LogswapClient, a: { poolId: Hex; operator: Address; account: Address; hook?: Address }) {
1296
- return writeHook(c, privateHookAbi, a, "appointOperator", [a.operator]);
1295
+ export async function fPoolAppointOperator(c: LogswapClient, a: { poolId: Hex; operator: Address; account: Address; policy?: Address }) {
1296
+ return writePolicy(c, privatePolicyAbi, a, "appointOperator", [a.operator]);
1297
1297
  }
1298
1298
 
1299
1299
  /** The proposed operator takes the role. */
1300
- export async function fPoolAcceptOperator(c: LogswapClient, a: { poolId: Hex; account: Address; hook?: Address }) {
1301
- return writeHook(c, privateHookAbi, a, "acceptOperator", []);
1300
+ export async function fPoolAcceptOperator(c: LogswapClient, a: { poolId: Hex; account: Address; policy?: Address }) {
1301
+ return writePolicy(c, privatePolicyAbi, a, "acceptOperator", []);
1302
1302
  }
1303
1303
 
1304
1304
  /**
@@ -1346,9 +1346,9 @@ export interface DiscoveredFPool {
1346
1346
  weights: bigint[];
1347
1347
  phi: bigint;
1348
1348
  kind: FPoolKind;
1349
- /** The pool's policy — the hook the key names (decisions 041, 044). */
1350
- hook: Address;
1351
- /** Who was born holding the pool (immutable). The LIVE authority is the hook's — {@link getFPoolRoles}. */
1349
+ /** The pool's policy — the contract the key names (decisions 041, 044, 045). */
1350
+ policy: Address;
1351
+ /** Who was born holding the pool (immutable). The LIVE authority is the policy's — {@link getFPoolRoles}. */
1352
1352
  creator: Address;
1353
1353
  /** The block the pool was initialized in — its age, for annualising realized income. */
1354
1354
  block: bigint;
@@ -1398,7 +1398,7 @@ export async function discoverFPools(
1398
1398
  return logs.map((l) => {
1399
1399
  const a = l.args as {
1400
1400
  poolId: Hex; quote: Address; creator: Address; bases: readonly Address[];
1401
- weights: readonly bigint[]; phi: bigint; kind: number; hook: Address;
1401
+ weights: readonly bigint[]; phi: bigint; kind: number; policy: Address;
1402
1402
  };
1403
1403
  const q0 = q0Of.get(a.poolId.toLowerCase());
1404
1404
  return {
@@ -1408,7 +1408,7 @@ export async function discoverFPools(
1408
1408
  weights: [...a.weights],
1409
1409
  phi: a.phi,
1410
1410
  kind: fPoolKindOf(a.kind),
1411
- hook: a.hook,
1411
+ policy: a.policy,
1412
1412
  creator: a.creator,
1413
1413
  block: l.blockNumber ?? 0n,
1414
1414
  seeded: q0 !== undefined,
@@ -1420,49 +1420,49 @@ export async function discoverFPools(
1420
1420
 
1421
1421
  // ─── the policy page: what an authority controls (decisions 044) ────────────────────────
1422
1422
  //
1423
- // One hook serves every pool of its kind, so "the pools I control" is not a hook's list: it is
1424
- // every pool whose hook answers `authority(poolId) == me`. Discovery from the log stream (or the
1425
- // indexer), then one `authority` read per pool on its hook — viem multicalls them.
1423
+ // One policy serves every pool of its kind, so "the pools I control" is not a policy's list: it is
1424
+ // every pool whose policy answers `authority(poolId) == me`. Discovery from the log stream (or the
1425
+ // indexer), then one `authority` read per pool on its policy — viem multicalls them.
1426
1426
 
1427
1427
  /** A pool an authority controls, with what the policy page shows of it. */
1428
1428
  export interface FPoolControlled {
1429
1429
  pool: DiscoveredFPool;
1430
1430
  roles: FPoolRoles;
1431
1431
  state: FPoolState;
1432
- /** The hook's numbers for this pool's kind — a pad's rung and threshold, a POL's floors, the desk's list flags. */
1433
- policy: FPoolPolicy;
1432
+ /** The policy's numbers for this pool's kind — a pad's rung and threshold, a POL's floors, the desk's list flags. */
1433
+ rules: FPoolRules;
1434
1434
  }
1435
1435
 
1436
- /** What a pool's hook says about it, by kind: the terms a buyer reads before entering. */
1437
- export type FPoolPolicy =
1436
+ /** What a pool's policy says about it, by kind: the terms a buyer reads before entering. */
1437
+ export type FPoolRules =
1438
1438
  | { kind: "pad"; harvestCut: bigint; rung: number; threshold: bigint; pot: bigint; creatorShare: bigint; protocolShare: bigint; burnPerRung: bigint }
1439
1439
  | { kind: "pol"; harvestCut: bigint; keepQuote: bigint; minQuoteAtSeed: bigint }
1440
1440
  | { kind: "public"; harvestCut: bigint; curated: boolean }
1441
1441
  | { kind: "private"; harvestCut: bigint; gateMint: boolean; gateSwap: boolean; operator: Address };
1442
1442
 
1443
- /** The hook's terms for one pool, by its kind. */
1444
- export async function getFPoolPolicy(c: LogswapClient, s: Pick<FPoolState, "poolId" | "hook" | "kind" | "gen">, roles?: FPoolRoles): Promise<FPoolPolicy> {
1443
+ /** The policy's terms for one pool, by its kind. */
1444
+ export async function getFPoolRules(c: LogswapClient, s: Pick<FPoolState, "poolId" | "policy" | "kind" | "gen">, roles?: FPoolRoles): Promise<FPoolRules> {
1445
1445
  const rd = <T>(abi: readonly unknown[], functionName: string, args: readonly unknown[] = []) =>
1446
- c.public.readContract({ address: s.hook, abi, functionName, args } as never) as Promise<T>;
1447
- const harvestCut = await rd<bigint>(fHookBaseAbi, "harvestCut");
1446
+ c.public.readContract({ address: s.policy, abi, functionName, args } as never) as Promise<T>;
1447
+ const harvestCut = await rd<bigint>(fPolicyBaseAbi, "harvestCut");
1448
1448
  switch (s.kind) {
1449
1449
  case "pad": {
1450
1450
  const [rung, creatorShare, protocolShare, burnPerRung, pot] = await Promise.all([
1451
- rd<bigint>(padHookAbi, "rung", [s.poolId]),
1452
- rd<bigint>(padHookAbi, "creatorShare"),
1453
- rd<bigint>(padHookAbi, "protocolShare"),
1454
- rd<bigint>(padHookAbi, "burnPerRung"),
1451
+ rd<bigint>(padPolicyAbi, "rung", [s.poolId]),
1452
+ rd<bigint>(padPolicyAbi, "creatorShare"),
1453
+ rd<bigint>(padPolicyAbi, "protocolShare"),
1454
+ rd<bigint>(padPolicyAbi, "burnPerRung"),
1455
1455
  fPoolDividendOf(c, s.poolId, DEAD_ADDRESS, s.gen),
1456
1456
  ]);
1457
- const threshold = await rd<bigint>(padHookAbi, "threshold", [rung]);
1457
+ const threshold = await rd<bigint>(padPolicyAbi, "threshold", [rung]);
1458
1458
  return { kind: "pad", harvestCut, rung: Number(rung), threshold, pot, creatorShare, protocolShare, burnPerRung };
1459
1459
  }
1460
1460
  case "pol": {
1461
- const [keepQuote, minQuoteAtSeed] = await Promise.all([rd<bigint>(polHookAbi, "keepQuote"), rd<bigint>(polHookAbi, "minQuoteAtSeed")]);
1461
+ const [keepQuote, minQuoteAtSeed] = await Promise.all([rd<bigint>(polPolicyAbi, "keepQuote"), rd<bigint>(polPolicyAbi, "minQuoteAtSeed")]);
1462
1462
  return { kind: "pol", harvestCut, keepQuote, minQuoteAtSeed };
1463
1463
  }
1464
1464
  case "public": {
1465
- const curated = await rd<boolean>(publicHookAbi, "curated");
1465
+ const curated = await rd<boolean>(publicPolicyAbi, "curated");
1466
1466
  return { kind: "public", harvestCut, curated };
1467
1467
  }
1468
1468
  case "private": {
@@ -1473,7 +1473,7 @@ export async function getFPoolPolicy(c: LogswapClient, s: Pick<FPoolState, "pool
1473
1473
  }
1474
1474
 
1475
1475
  /**
1476
- * Every F pool `who` is the AUTHORITY of, across the four hooks — the policy page's list. Pools
1476
+ * Every F pool `who` is the AUTHORITY of, across the four policies — the policy page's list. Pools
1477
1477
  * `who` created and handed over are not here (the buyer's page shows them); pools handed TO
1478
1478
  * `who` are. `pools` may be passed (from the indexer, say) to skip the log scan.
1479
1479
  */
@@ -1485,7 +1485,7 @@ export async function fPoolsControlledBy(
1485
1485
  const pools = opts.pools ?? (await discoverFPools(c, { fromBlock: opts.fromBlock }));
1486
1486
  const authorities = await Promise.all(
1487
1487
  pools.map((p) =>
1488
- c.public.readContract({ address: p.hook, abi: fHookBaseAbi, functionName: "authority", args: [p.poolId] } as never) as Promise<Address>,
1488
+ c.public.readContract({ address: p.policy, abi: fPolicyBaseAbi, functionName: "authority", args: [p.poolId] } as never) as Promise<Address>,
1489
1489
  ),
1490
1490
  );
1491
1491
  const mine = pools.filter((_, i) => authorities[i]!.toLowerCase() === who.toLowerCase());
@@ -1493,8 +1493,8 @@ export async function fPoolsControlledBy(
1493
1493
  mine.map(async (pool) => {
1494
1494
  const state = await getFPool(c, pool.poolId);
1495
1495
  const roles = await getFPoolRoles(c, pool.poolId, state);
1496
- const policy = await getFPoolPolicy(c, state, roles);
1497
- return { pool, roles, state, policy };
1496
+ const rules = await getFPoolRules(c, state, roles);
1497
+ return { pool, roles, state, rules };
1498
1498
  }),
1499
1499
  );
1500
1500
  }