@logswap/sdk 0.5.46 → 0.5.48

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/dist/fpool.js 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
@@ -30,24 +30,24 @@
30
30
  * `addresses.router`.
31
31
  */
32
32
  import { encodeFunctionData, toFunctionSelector } from "viem";
33
- import { fPoolManagerAbi, logswapRouterAbi, padHookAbi, polHookAbi, privateHookAbi, publicHookAbi } from "./generated.js";
33
+ import { fPoolManagerAbi, logswapRouterAbi, padPolicyAbi, polPolicyAbi, privatePolicyAbi, publicPolicyAbi } from "./generated.js";
34
34
  /**
35
35
  * One contract, one ABI (decisions 039, F version 12): `harvest`, `claim`, `retire`, `regenerate`,
36
36
  * `setLegs`, the names, the fee parameters are `FPoolManager`'s own code. The roles left it for
37
- * the hooks in F version 15 (decisions 044): {@link fHookBaseAbi} is what every hook shares,
38
- * {@link privateHookAbi} the desk's, {@link padHookAbi} / {@link polHookAbi} / {@link publicHookAbi}
37
+ * the policies in F version 15 (decisions 044): {@link fPolicyBaseAbi} is what every policy shares,
38
+ * {@link privatePolicyAbi} the desk's, {@link padPolicyAbi} / {@link polPolicyAbi} / {@link publicPolicyAbi}
39
39
  * the kinds'.
40
40
  */
41
- export { fPoolManagerAbi, padHookAbi, polHookAbi, privateHookAbi, publicHookAbi };
41
+ export { fPoolManagerAbi, padPolicyAbi, polPolicyAbi, privatePolicyAbi, publicPolicyAbi };
42
42
  /**
43
- * What every protocol hook shares (`FHookBase`): the roles and their handover, `harvestCut`,
44
- * `maxHarvest`. `polHookAbi` is a superset of it and carries nothing that collides, so it stands
45
- * in for the base — a call through it to any of the four hooks decodes the base's functions.
43
+ * What every protocol policy shares (`FPolicyBase`): the roles and their handover, `harvestCut`,
44
+ * `maxHarvest`. `polPolicyAbi` is a superset of it and carries nothing that collides, so it stands
45
+ * in for the base — a call through it to any of the four policies decodes the base's functions.
46
46
  */
47
- export const fHookBaseAbi = polHookAbi;
47
+ export const fPolicyBaseAbi = polPolicyAbi;
48
48
  const WAD = 10n ** 18n;
49
49
  const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
50
- /** The optional questions a hook declared at birth (decisions 044), as bits of `Pool.asks`. */
50
+ /** The optional questions a policy declared at birth (decisions 044), as bits of `Pool.asks`. */
51
51
  export const ASK_SWAP = 1;
52
52
  export const ASK_MINT = 2;
53
53
  /** Read a basket pool whole. Batched — viem multicalls these when the transport allows. */
@@ -61,7 +61,7 @@ export async function getFPool(c, poolId) {
61
61
  args,
62
62
  });
63
63
  // `getPool` returns the whole scalar struct in one call — the singleton's shape makes what used
64
- // to be a dozen getters a single read. No role in it since F version 15: those are the hook's.
64
+ // to be a dozen getters a single read. No role in it since F version 15: those are the policy's.
65
65
  const p = await rd("getPool", [poolId]);
66
66
  // A pool that was never created reads as an all-zero struct rather than reverting, so the
67
67
  // absence has to be named here or every caller mistakes "no such pool" for "a pool holding
@@ -83,7 +83,7 @@ export async function getFPool(c, poolId) {
83
83
  const weights = legs.map((l) => l[1]);
84
84
  const x = legs.map((l) => l[2]); // derived by the manager: x_j = ln(w_j·L / R_j) (decisions 026)
85
85
  const reserves = legs.map((l) => l[3]); // the state
86
- const { quote, Q, L, phi, theta0, bigSigma, hook, restructureBlock, seeded, gen } = p;
86
+ const { quote, Q, L, phi, theta0, bigSigma, policy, restructureBlock, seeded, gen } = p;
87
87
  const totalSupply = p.shares;
88
88
  return {
89
89
  poolId,
@@ -98,7 +98,7 @@ export async function getFPool(c, poolId) {
98
98
  theta,
99
99
  compositeX,
100
100
  bigSigma,
101
- hook,
101
+ policy,
102
102
  asks: Number(p.asks),
103
103
  name: bytes32ToText(p.name),
104
104
  restructureBlock: Number(restructureBlock),
@@ -118,16 +118,16 @@ export function fPoolKindOf(n) {
118
118
  throw new Error(`logswap: unknown pool kind ${n}`);
119
119
  return k;
120
120
  }
121
- /** The deployment's hook for a kind (decisions 044): what a key of that kind names. */
122
- export function fPoolHookFor(c, kind) {
121
+ /** The deployment's policy for a kind (decisions 044): what a key of that kind names. */
122
+ export function fPoolPolicyFor(c, kind) {
123
123
  const a = c.addresses;
124
- const hook = kind === "public" ? a.publicHook : kind === "private" ? a.privateHook : kind === "pol" ? a.polHook : a.padHook;
125
- if (!hook)
126
- throw new Error(`logswap: this deployment carries no ${kind} hook`);
127
- return hook;
124
+ const policy = kind === "public" ? a.publicPolicy : kind === "private" ? a.privatePolicy : kind === "pol" ? a.polPolicy : a.padPolicy;
125
+ if (!policy)
126
+ throw new Error(`logswap: this deployment carries no ${kind} policy`);
127
+ return policy;
128
128
  }
129
- /** The hook a pool named in its key — one read; {@link getFPool} carries it too. */
130
- export async function fPoolHookOf(c, poolId) {
129
+ /** The policy a pool named in its key — one read; {@link getFPool} carries it too. */
130
+ export async function fPoolPolicyOf(c, poolId) {
131
131
  const p = (await c.public.readContract({
132
132
  address: c.addresses.fPoolManager,
133
133
  abi: fPoolManagerAbi,
@@ -136,28 +136,28 @@ export async function fPoolHookOf(c, poolId) {
136
136
  }));
137
137
  if (/^0x0{40}$/i.test(p.quote))
138
138
  throw new Error(`logswap: no F pool with id ${poolId}`);
139
- return p.hook;
139
+ return p.policy;
140
140
  }
141
- /** Read a pool's roles from its hook. `state` saves the `getPool` round trip when already in hand. */
141
+ /** Read a pool's roles from its policy. `state` saves the `getPool` round trip when already in hand. */
142
142
  export async function getFPoolRoles(c, poolId, state) {
143
143
  const s = state ?? (await getFPool(c, poolId));
144
- const rdHook = (abi, functionName) => c.public.readContract({ address: s.hook, abi, functionName, args: [poolId] });
144
+ const rdPolicy = (abi, functionName) => c.public.readContract({ address: s.policy, abi, functionName, args: [poolId] });
145
145
  const [creator, authority, pendingAuthority, maxHarvest] = await Promise.all([
146
- rdHook(fHookBaseAbi, "creator"),
147
- rdHook(fHookBaseAbi, "authority"),
148
- rdHook(fHookBaseAbi, "pendingAuthority"),
149
- rdHook(fHookBaseAbi, "maxHarvest"),
146
+ rdPolicy(fPolicyBaseAbi, "creator"),
147
+ rdPolicy(fPolicyBaseAbi, "authority"),
148
+ rdPolicy(fPolicyBaseAbi, "pendingAuthority"),
149
+ rdPolicy(fPolicyBaseAbi, "maxHarvest"),
150
150
  ]);
151
151
  const desk = s.kind === "private";
152
152
  const [operator, pendingOperator, gateMint, gateSwap] = desk
153
153
  ? await Promise.all([
154
- rdHook(privateHookAbi, "operator"),
155
- rdHook(privateHookAbi, "pendingOperator"),
156
- rdHook(privateHookAbi, "gateMint"),
157
- rdHook(privateHookAbi, "gateSwap"),
154
+ rdPolicy(privatePolicyAbi, "operator"),
155
+ rdPolicy(privatePolicyAbi, "pendingOperator"),
156
+ rdPolicy(privatePolicyAbi, "gateMint"),
157
+ rdPolicy(privatePolicyAbi, "gateSwap"),
158
158
  ])
159
159
  : [ZERO_ADDRESS, ZERO_ADDRESS, false, false];
160
- return { hook: s.hook, creator, authority, pendingAuthority, operator, pendingOperator, gateMint, gateSwap, maxHarvest };
160
+ return { policy: s.policy, creator, authority, pendingAuthority, operator, pendingOperator, gateMint, gateSwap, maxHarvest };
161
161
  }
162
162
  export async function describeFPool(c, s) {
163
163
  const rd = (functionName, args = [s.poolId]) => c.public.readContract({
@@ -606,7 +606,7 @@ export function sortFPoolLegs(bases, ...companions) {
606
606
  const idx = bases.map((_, i) => i).sort((a, b) => (bases[a].toLowerCase() < bases[b].toLowerCase() ? -1 : 1));
607
607
  return { bases: idx.map((i) => bases[i]), companions: companions.map((arr) => idx.map((i) => arr[i])) };
608
608
  }
609
- /** The key as the manager hashes it: legs sorted, the kind's hook filled in when none is named. */
609
+ /** The key as the manager hashes it: legs sorted, the kind's policy filled in when none is named. */
610
610
  export function fPoolKeyOf(c, a) {
611
611
  const { bases, companions } = sortFPoolLegs(a.bases, a.weights);
612
612
  return {
@@ -615,7 +615,7 @@ export function fPoolKeyOf(c, a) {
615
615
  weights: companions[0],
616
616
  phi: a.phi,
617
617
  kind: F_KIND[a.kind],
618
- hook: a.hook ?? fPoolHookFor(c, a.kind),
618
+ policy: a.policy ?? fPoolPolicyFor(c, a.kind),
619
619
  creator: a.creator,
620
620
  salt: a.salt ?? ZERO_SALT,
621
621
  };
@@ -674,7 +674,7 @@ export async function fPoolSeed(c, a) {
674
674
  * operator harvested it out first ({@link fPoolRetire} does both in one transaction). The live
675
675
  * (S, Q, R_j) become a frozen bundle every share of this generation redeems ({@link fPoolRedeem})
676
676
  * or rolls ({@link fPoolRollIn}), forever; the pool is unseeded until the next {@link fPoolSeed},
677
- * which opens generation `gen + 1` under the same id, hook, roles, gates and lists.
677
+ * which opens generation `gen + 1` under the same id, policy, roles, gates and lists.
678
678
  */
679
679
  export async function fPoolRetireRaw(c, a) {
680
680
  return writeFPool(c, a.poolId, "retire", [], a.account);
@@ -698,8 +698,8 @@ export async function fPoolRetire(c, a) {
698
698
  * `retire` (decisions 035: a retire needs an empty bid on every pool). Since F version 14 one
699
699
  * `harvest(Q)` does it: the protocol's cut leaves the pool with the amount (with no collector
700
700
  * there is no cut). `[]` when the bid is already empty. Throws on a pad that still bids (its bid
701
- * empties only as the market sells it down), and when the pool's hook keeps a floor on the bid
702
- * (`PolHook.keepQuote`, decisions 044): a `retire` under that hook waits for the market.
701
+ * empties only as the market sells it down), and when the pool's policy keeps a floor on the bid
702
+ * (`PolPolicy.keepQuote`, decisions 044): a `retire` under that policy waits for the market.
703
703
  */
704
704
  export async function fPoolEmptyingHarvests(c, poolId) {
705
705
  const s = await getFPool(c, poolId);
@@ -709,16 +709,16 @@ export async function fPoolEmptyingHarvests(c, poolId) {
709
709
  throw new Error("logswap: a pad is retired only once its bid is empty (decisions 035)");
710
710
  const { maxHarvest } = await getFPoolRoles(c, poolId, s);
711
711
  if (maxHarvest < s.Q)
712
- throw new Error("logswap: the pool's hook keeps a floor on the bid — it cannot be harvested empty (decisions 044)");
712
+ throw new Error("logswap: the pool's policy keeps a floor on the bid — it cannot be harvested empty (decisions 044)");
713
713
  return [s.Q];
714
714
  }
715
715
  /**
716
- * Release the dead shares' pot under the hook's terms (decisions 041, 044) — a pad's graduation.
716
+ * Release the dead shares' pot under the policy's terms (decisions 041, 044) — a pad's graduation.
717
717
  * The manager harvests the generation's income first (the pot then holds everything the dead
718
- * shares earned), asks the hook, and applies its answer: a share to the payee it names (the pad's
718
+ * shares earned), asks the policy, and applies its answer: a share to the payee it names (the pad's
719
719
  * creator — the pool's authority), a cut to the collector, the rest bought in as more of the
720
- * float the pool owns, a slice of every reserve burned. The hook refuses under its rung's
721
- * threshold (`PadHook.NotGraduated`). Whoever runs the pool.
720
+ * float the pool owns, a slice of every reserve burned. The policy refuses under its rung's
721
+ * threshold (`PadPolicy.NotGraduated`). Whoever runs the pool.
722
722
  */
723
723
  export async function fPoolRegenerate(c, a) {
724
724
  return writeFPool(c, a.poolId, "regenerate", [a.to ?? a.account], a.account);
@@ -730,7 +730,7 @@ export async function fPoolRegenerate(c, a) {
730
730
  * next generation's composition (`legs`: a private pool's reshape — retire, admit, reweight), and
731
731
  * `seed` it with what came back — the manager's `multicall`, one sender throughout, the same
732
732
  * pool. The operator's when one is appointed and the seed's inventory is its own; by default the
733
- * authority's. The hook, its roles, gates, allowlist and the name carry over; anything else goes
733
+ * authority's. The policy, its roles, gates, allowlist and the name carry over; anything else goes
734
734
  * in `extra`, pre-encoded against {@link fPoolManagerAbi}. The seed names reserves (decisions
735
735
  * 029): `r0` outright — one per leg of the NEXT table, 0 for a retired leg — or `x0` marks
736
736
  * against the next table's `weights`.
@@ -767,9 +767,9 @@ export function fPoolLaunchCalls(poolId, a) {
767
767
  if (given.length !== a.bases.length)
768
768
  throw new Error(`logswap: ${given.length} reserves for ${a.bases.length} legs`);
769
769
  const { bases, companions } = sortFPoolLegs(a.bases, a.weights, given);
770
- if (!a.hook)
771
- throw new Error("logswap: fPoolLaunchCalls needs the key's hook — fPoolLaunch fills it from the deployment");
772
- 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 };
770
+ if (!a.policy)
771
+ throw new Error("logswap: fPoolLaunchCalls needs the key's policy — fPoolLaunch fills it from the deployment");
772
+ 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 };
773
773
  const enc = (functionName, args) => encodeFunctionData({ abi: fPoolManagerAbi, functionName, args });
774
774
  const calls = [];
775
775
  if (!a.initialized)
@@ -785,21 +785,21 @@ export function fPoolLaunchCalls(poolId, a) {
785
785
  }
786
786
  if (a.name)
787
787
  calls.push(enc("setName", [poolId, textToBytes32(a.name)]));
788
- // the desk's gates and list are the HOOK's (decisions 044), not the manager's: they cannot ride
788
+ // the desk's gates and list are the POLICY's (decisions 044), not the manager's: they cannot ride
789
789
  // in this batch — `fPoolDeskOpening` sends them right after, as the same creator
790
790
  calls.push(...(a.extra ?? []));
791
791
  return calls;
792
792
  }
793
793
  /**
794
- * The desk's opening posture, on its hook (decisions 044): gated minting, the creator listed. No
794
+ * The desk's opening posture, on its policy (decisions 044): gated minting, the creator listed. No
795
795
  * appointment: the authority is the operator until one is appointed (decisions 037). Two writes
796
- * to `PrivateHook`; the launch batch cannot carry them (they are not manager calls).
796
+ * to `PrivatePolicy`; the launch batch cannot carry them (they are not manager calls).
797
797
  */
798
798
  export async function fPoolDeskOpening(c, a) {
799
- const hook = a.hook ?? fPoolHookFor(c, "private");
799
+ const policy = a.policy ?? fPoolPolicyFor(c, "private");
800
800
  return [
801
- await fPoolSetGates(c, { poolId: a.poolId, gateMint: true, gateSwap: false, account: a.account, hook }),
802
- await fPoolSetAllowed(c, { poolId: a.poolId, who: [a.account], allowed: true, account: a.account, hook }),
801
+ await fPoolSetGates(c, { poolId: a.poolId, gateMint: true, gateSwap: false, account: a.account, policy }),
802
+ await fPoolSetAllowed(c, { poolId: a.poolId, who: [a.account], allowed: true, account: a.account, policy }),
803
803
  ];
804
804
  }
805
805
  /**
@@ -821,20 +821,20 @@ export async function fPoolDeskOpening(c, a) {
821
821
  */
822
822
  export async function fPoolLaunch(c, a) {
823
823
  const poolId = await fPoolIdOf(c, a);
824
- const calls = fPoolLaunchCalls(poolId, { ...a, hook: a.hook ?? fPoolHookFor(c, a.kind) });
824
+ const calls = fPoolLaunchCalls(poolId, { ...a, policy: a.policy ?? fPoolPolicyFor(c, a.kind) });
825
825
  const hash = await writeFPool0(c, "multicall", [calls], a.account);
826
826
  return { hash, poolId };
827
827
  }
828
- // ─── the roles, on the hook (decisions 044) ─────────────────────────────────────────────
828
+ // ─── the roles, on the policy (decisions 044) ─────────────────────────────────────────────
829
829
  //
830
- // Every write here goes to the pool's HOOK, not the manager: the manager holds no role. `hook`
831
- // may be passed when in hand (`FPoolState.hook`, `FPoolRoles.hook`); otherwise it is read once.
832
- /** A write keyed by poolId, on the pool's hook. */
833
- async function writeHook(c, abi, a, functionName, args) {
830
+ // Every write here goes to the pool's POLICY, not the manager: the manager holds no role. `policy`
831
+ // may be passed when in hand (`FPoolState.policy`, `FPoolRoles.policy`); otherwise it is read once.
832
+ /** A write keyed by poolId, on the pool's policy. */
833
+ async function writePolicy(c, abi, a, functionName, args) {
834
834
  const wallet = requireWallet(c);
835
- const hook = a.hook ?? (await fPoolHookOf(c, a.poolId));
835
+ const policy = a.policy ?? (await fPoolPolicyOf(c, a.poolId));
836
836
  const { request } = await c.public.simulateContract({
837
- address: hook,
837
+ address: policy,
838
838
  abi,
839
839
  functionName,
840
840
  args: [a.poolId, ...args],
@@ -843,39 +843,39 @@ async function writeHook(c, abi, a, functionName, args) {
843
843
  return wallet.writeContract(request);
844
844
  }
845
845
  /**
846
- * Propose the next authority — step one of two (decisions 020), on the pool's hook. Nothing moves
846
+ * Propose the next authority — step one of two (decisions 020), on the pool's policy. Nothing moves
847
847
  * until `next` accepts; proposing again (the zero address included) cancels a pending proposal.
848
- * Indexed on-chain via the hook's AuthorityProposed.
848
+ * Indexed on-chain via the policy's AuthorityProposed.
849
849
  */
850
850
  export async function fPoolProposeAuthority(c, a) {
851
- return writeHook(c, fHookBaseAbi, a, "proposeAuthority", [a.next]);
851
+ return writePolicy(c, fPolicyBaseAbi, a, "proposeAuthority", [a.next]);
852
852
  }
853
853
  /**
854
- * Accept a pending proposal — step two; only the proposed address can. Indexed via the hook's
855
- * AuthoritySet. On the desk's hook this clears the operator (pending and accepted) and voids the
854
+ * Accept a pending proposal — step two; only the proposed address can. Indexed via the policy's
855
+ * AuthoritySet. On the desk's policy this clears the operator (pending and accepted) and voids the
856
856
  * seller's list (decisions 040, 044).
857
857
  */
858
858
  export async function fPoolAcceptAuthority(c, a) {
859
- return writeHook(c, fHookBaseAbi, a, "acceptAuthority", []);
859
+ return writePolicy(c, fPolicyBaseAbi, a, "acceptAuthority", []);
860
860
  }
861
- // ─── the desk's controls (PrivateHook; decisions 021, 044) ───────────────────────────────
862
- /** Turn the mint / swap gates on or off (the authority, on the desk's hook). `burn` is never gated. */
861
+ // ─── the desk's controls (PrivatePolicy; decisions 021, 044) ───────────────────────────────
862
+ /** Turn the mint / swap gates on or off (the authority, on the desk's policy). `burn` is never gated. */
863
863
  export async function fPoolSetGates(c, a) {
864
- return writeHook(c, privateHookAbi, a, "setGates", [a.gateMint, a.gateSwap]);
864
+ return writePolicy(c, privatePolicyAbi, a, "setGates", [a.gateMint, a.gateSwap]);
865
865
  }
866
866
  /**
867
- * Add to or remove from the pool's list, in one call (the authority, on the desk's hook). The list
867
+ * Add to or remove from the pool's list, in one call (the authority, on the desk's policy). The list
868
868
  * is keyed by the authority that granted it: a handover starts the buyer with an empty one.
869
869
  */
870
870
  export async function fPoolSetAllowed(c, a) {
871
- return writeHook(c, privateHookAbi, a, "setAllowed", [a.who, a.allowed]);
871
+ return writePolicy(c, privatePolicyAbi, a, "setAllowed", [a.who, a.allowed]);
872
872
  }
873
873
  /** Whether `who` is on the pool's list under its current authority (consulted only while a gate is on). */
874
- export async function fPoolIsAllowed(c, poolId, who, hook) {
875
- const address = hook ?? (await fPoolHookOf(c, poolId));
874
+ export async function fPoolIsAllowed(c, poolId, who, policy) {
875
+ const address = policy ?? (await fPoolPolicyOf(c, poolId));
876
876
  return (await c.public.readContract({
877
877
  address,
878
- abi: privateHookAbi,
878
+ abi: privatePolicyAbi,
879
879
  functionName: "isAllowed",
880
880
  args: [poolId, who],
881
881
  }));
@@ -914,16 +914,16 @@ export function fPoolOperatorOf(s) {
914
914
  return s.operator === ZERO_ADDRESS ? s.authority : s.operator;
915
915
  }
916
916
  /**
917
- * Propose the operator (the authority, on the desk's hook) — the hot key that runs the pool:
917
+ * Propose the operator (the authority, on the desk's policy) — the hot key that runs the pool:
918
918
  * `harvest`, `retire`, `regenerate`, `setLegs`. Two-step: the proposed address takes the role with
919
919
  * {@link fPoolAcceptOperator}. The zero address clears at once — the role returns to the authority.
920
920
  */
921
921
  export async function fPoolAppointOperator(c, a) {
922
- return writeHook(c, privateHookAbi, a, "appointOperator", [a.operator]);
922
+ return writePolicy(c, privatePolicyAbi, a, "appointOperator", [a.operator]);
923
923
  }
924
924
  /** The proposed operator takes the role. */
925
925
  export async function fPoolAcceptOperator(c, a) {
926
- return writeHook(c, privateHookAbi, a, "acceptOperator", []);
926
+ return writePolicy(c, privatePolicyAbi, a, "acceptOperator", []);
927
927
  }
928
928
  /**
929
929
  * The next generation's composition (operator; private pools only; ONLY while the pool is
@@ -989,7 +989,7 @@ export async function discoverFPools(c, opts = {}) {
989
989
  weights: [...a.weights],
990
990
  phi: a.phi,
991
991
  kind: fPoolKindOf(a.kind),
992
- hook: a.hook,
992
+ policy: a.policy,
993
993
  creator: a.creator,
994
994
  block: l.blockNumber ?? 0n,
995
995
  seeded: q0 !== undefined,
@@ -998,28 +998,28 @@ export async function discoverFPools(c, opts = {}) {
998
998
  };
999
999
  });
1000
1000
  }
1001
- /** The hook's terms for one pool, by its kind. */
1002
- export async function getFPoolPolicy(c, s, roles) {
1003
- const rd = (abi, functionName, args = []) => c.public.readContract({ address: s.hook, abi, functionName, args });
1004
- const harvestCut = await rd(fHookBaseAbi, "harvestCut");
1001
+ /** The policy's terms for one pool, by its kind. */
1002
+ export async function getFPoolRules(c, s, roles) {
1003
+ const rd = (abi, functionName, args = []) => c.public.readContract({ address: s.policy, abi, functionName, args });
1004
+ const harvestCut = await rd(fPolicyBaseAbi, "harvestCut");
1005
1005
  switch (s.kind) {
1006
1006
  case "pad": {
1007
1007
  const [rung, creatorShare, protocolShare, burnPerRung, pot] = await Promise.all([
1008
- rd(padHookAbi, "rung", [s.poolId]),
1009
- rd(padHookAbi, "creatorShare"),
1010
- rd(padHookAbi, "protocolShare"),
1011
- rd(padHookAbi, "burnPerRung"),
1008
+ rd(padPolicyAbi, "rung", [s.poolId]),
1009
+ rd(padPolicyAbi, "creatorShare"),
1010
+ rd(padPolicyAbi, "protocolShare"),
1011
+ rd(padPolicyAbi, "burnPerRung"),
1012
1012
  fPoolDividendOf(c, s.poolId, DEAD_ADDRESS, s.gen),
1013
1013
  ]);
1014
- const threshold = await rd(padHookAbi, "threshold", [rung]);
1014
+ const threshold = await rd(padPolicyAbi, "threshold", [rung]);
1015
1015
  return { kind: "pad", harvestCut, rung: Number(rung), threshold, pot, creatorShare, protocolShare, burnPerRung };
1016
1016
  }
1017
1017
  case "pol": {
1018
- const [keepQuote, minQuoteAtSeed] = await Promise.all([rd(polHookAbi, "keepQuote"), rd(polHookAbi, "minQuoteAtSeed")]);
1018
+ const [keepQuote, minQuoteAtSeed] = await Promise.all([rd(polPolicyAbi, "keepQuote"), rd(polPolicyAbi, "minQuoteAtSeed")]);
1019
1019
  return { kind: "pol", harvestCut, keepQuote, minQuoteAtSeed };
1020
1020
  }
1021
1021
  case "public": {
1022
- const curated = await rd(publicHookAbi, "curated");
1022
+ const curated = await rd(publicPolicyAbi, "curated");
1023
1023
  return { kind: "public", harvestCut, curated };
1024
1024
  }
1025
1025
  case "private": {
@@ -1029,19 +1029,19 @@ export async function getFPoolPolicy(c, s, roles) {
1029
1029
  }
1030
1030
  }
1031
1031
  /**
1032
- * Every F pool `who` is the AUTHORITY of, across the four hooks — the policy page's list. Pools
1032
+ * Every F pool `who` is the AUTHORITY of, across the four policies — the policy page's list. Pools
1033
1033
  * `who` created and handed over are not here (the buyer's page shows them); pools handed TO
1034
1034
  * `who` are. `pools` may be passed (from the indexer, say) to skip the log scan.
1035
1035
  */
1036
1036
  export async function fPoolsControlledBy(c, who, opts = {}) {
1037
1037
  const pools = opts.pools ?? (await discoverFPools(c, { fromBlock: opts.fromBlock }));
1038
- const authorities = await Promise.all(pools.map((p) => c.public.readContract({ address: p.hook, abi: fHookBaseAbi, functionName: "authority", args: [p.poolId] })));
1038
+ const authorities = await Promise.all(pools.map((p) => c.public.readContract({ address: p.policy, abi: fPolicyBaseAbi, functionName: "authority", args: [p.poolId] })));
1039
1039
  const mine = pools.filter((_, i) => authorities[i].toLowerCase() === who.toLowerCase());
1040
1040
  return Promise.all(mine.map(async (pool) => {
1041
1041
  const state = await getFPool(c, pool.poolId);
1042
1042
  const roles = await getFPoolRoles(c, pool.poolId, state);
1043
- const policy = await getFPoolPolicy(c, state, roles);
1044
- return { pool, roles, state, policy };
1043
+ const rules = await getFPoolRules(c, state, roles);
1044
+ return { pool, roles, state, rules };
1045
1045
  }));
1046
1046
  }
1047
1047
  /**