@sm-lab/recipes 0.2.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cl-activate-CPqr6v_D.mjs","names":["makeRewards","makeRewardsTree"],"sources":["../src/recipes/operator-info.ts","../src/recipes/chain.ts","../src/recipes/address-changes.ts","../src/encode.ts","../src/recipes/vetting.ts","../src/recipes/validators.ts","../src/recipes/penalties.ts","../src/recipes/bond.ts","../src/recipes/set-gate.ts","../src/recipes/rewards.ts","../src/cl-mock.ts","../src/recipes/cl-activate.ts"],"sourcesContent":["import type { Hex } from '@sm-lab/receipts';\nimport { contract, type Ctx } from '../context';\n\n/** Decoded NodeOperator (abitype: uint32/uint8 → number, address → Hex, bool → boolean). */\nexport interface OperatorInfo {\n totalAddedKeys: number;\n totalWithdrawnKeys: number;\n totalDepositedKeys: number;\n totalVettedKeys: number;\n stuckValidatorsCount: number;\n depositableValidatorsCount: number;\n targetLimit: number;\n targetLimitMode: number;\n totalExitedKeys: number;\n enqueuedCount: number;\n managerAddress: Hex;\n proposedManagerAddress: Hex;\n rewardAddress: Hex;\n proposedRewardAddress: Hex;\n extendedManagerPermissions: boolean;\n usedPriorityQueue: boolean;\n}\n\n/** Typed read of a node operator's on-chain record. (Port of `NodeOperators.operatorInfo`.) */\nexport async function operatorInfo(ctx: Ctx, opts: { noId: bigint }): Promise<OperatorInfo> {\n const m = contract(ctx, 'module');\n const op = await ctx.client.readContract({\n ...m,\n functionName: 'getNodeOperator',\n args: [opts.noId],\n });\n return op as OperatorInfo;\n}\n","import type { Hex } from '@sm-lab/receipts';\nimport type { Ctx } from '../context';\n\n/** Advance fork time by `seconds` and mine a block (evm_increaseTime + evm_mine). */\nexport async function warpBy(ctx: Ctx, seconds: number | bigint): Promise<void> {\n await ctx.client.increaseTime({ seconds: Number(seconds) });\n await ctx.client.mine({ blocks: 1 });\n}\n\n/**\n * Warp fork time to an absolute unix timestamp and mine a block\n * (evm_setNextBlockTimestamp + evm_mine). The absolute counterpart of `warpBy` — used by\n * `submitRewards`'s consensus-frame wait. Over RPC, `setNextBlockTimestamp` + `mine` reproduces\n * Foundry's `vm.warp(ts)` (the post-warp `block.timestamp` settles automatically after mining).\n */\nexport async function warpTo(ctx: Ctx, timestamp: number | bigint): Promise<void> {\n await ctx.client.setNextBlockTimestamp({ timestamp: BigInt(timestamp) });\n await ctx.client.mine({ blocks: 1 });\n}\n\n/** Take an anvil state snapshot; returns the snapshot id (evm_snapshot). */\nexport function snapshot(ctx: Ctx): Promise<Hex> {\n return ctx.client.snapshot();\n}\n\n/** Revert the fork to a snapshot id (evm_revert). */\nexport async function revert(ctx: Ctx, id: Hex): Promise<void> {\n await ctx.client.revert({ id });\n}\n","import type { Hex } from '@sm-lab/receipts';\nimport { actAs } from '../act-as';\nimport { contract, type Ctx } from '../context';\n\n/** Propose a new manager address for an operator (signed by the current manager). */\nexport async function proposeManager(\n ctx: Ctx,\n opts: { noId: bigint; proposed: Hex },\n): Promise<void> {\n const m = contract(ctx, 'module');\n const op = await ctx.client.readContract({\n ...m,\n functionName: 'getNodeOperator',\n args: [opts.noId],\n });\n await actAs(ctx, op.managerAddress, (from) =>\n ctx.client.writeContract({\n ...m,\n functionName: 'proposeNodeOperatorManagerAddressChange',\n args: [opts.noId, opts.proposed],\n account: from,\n chain: null,\n }),\n );\n}\n\n/** Confirm the proposed manager address (signed by the proposed manager). */\nexport async function confirmManager(ctx: Ctx, opts: { noId: bigint }): Promise<void> {\n const m = contract(ctx, 'module');\n const op = await ctx.client.readContract({\n ...m,\n functionName: 'getNodeOperator',\n args: [opts.noId],\n });\n await actAs(ctx, op.proposedManagerAddress, (from) =>\n ctx.client.writeContract({\n ...m,\n functionName: 'confirmNodeOperatorManagerAddressChange',\n args: [opts.noId],\n account: from,\n chain: null,\n }),\n );\n}\n\n/** Propose a new reward address (signed by the MANAGER, per the on-chain access rule). */\nexport async function proposeReward(\n ctx: Ctx,\n opts: { noId: bigint; proposed: Hex },\n): Promise<void> {\n const m = contract(ctx, 'module');\n const op = await ctx.client.readContract({\n ...m,\n functionName: 'getNodeOperator',\n args: [opts.noId],\n });\n await actAs(ctx, op.managerAddress, (from) =>\n ctx.client.writeContract({\n ...m,\n functionName: 'proposeNodeOperatorRewardAddressChange',\n args: [opts.noId, opts.proposed],\n account: from,\n chain: null,\n }),\n );\n}\n\n/** Confirm the proposed reward address (signed by the proposed reward address). */\nexport async function confirmReward(ctx: Ctx, opts: { noId: bigint }): Promise<void> {\n const m = contract(ctx, 'module');\n const op = await ctx.client.readContract({\n ...m,\n functionName: 'getNodeOperator',\n args: [opts.noId],\n });\n await actAs(ctx, op.proposedRewardAddress, (from) =>\n ctx.client.writeContract({\n ...m,\n functionName: 'confirmNodeOperatorRewardAddressChange',\n args: [opts.noId],\n account: from,\n chain: null,\n }),\n );\n}\n","import { toHex } from 'viem';\nimport type { Hex } from '@sm-lab/receipts';\n\n/** A node-operator id packed as the on-chain `bytes8(uint64)` (big-endian). */\nexport function nodeOperatorIdBytes(noId: bigint): Hex {\n return toHex(noId, { size: 8 });\n}\n\n/** A key count packed as the on-chain `bytes16(uint128)` (big-endian). */\nexport function keyCountBytes(count: bigint): Hex {\n return toHex(count, { size: 16 });\n}\n","import { actAs } from '../act-as';\nimport { contract, type Ctx } from '../context';\nimport { keyCountBytes, nodeOperatorIdBytes } from '../encode';\n\n/** Set an operator's vetted-keys count (StakingRouter-gated). `vettedKeys` is the new absolute count. */\nexport async function unvet(ctx: Ctx, opts: { noId: bigint; vettedKeys: bigint }): Promise<void> {\n const m = contract(ctx, 'module');\n await actAs(ctx, ctx.addresses.stakingRouter, (from) =>\n ctx.client.writeContract({\n ...m,\n functionName: 'decreaseVettedSigningKeysCount',\n args: [nodeOperatorIdBytes(opts.noId), keyCountBytes(opts.vettedKeys)],\n account: from,\n chain: null,\n }),\n );\n}\n\n/** Set an operator's exited-keys count (StakingRouter-gated). `exitedKeys` is the new absolute total. */\nexport async function exit(ctx: Ctx, opts: { noId: bigint; exitedKeys: bigint }): Promise<void> {\n const m = contract(ctx, 'module');\n await actAs(ctx, ctx.addresses.stakingRouter, (from) =>\n ctx.client.writeContract({\n ...m,\n functionName: 'updateExitedValidatorsCount',\n args: [nodeOperatorIdBytes(opts.noId), keyCountBytes(opts.exitedKeys)],\n account: from,\n chain: null,\n }),\n );\n}\n","import { actAs } from '../act-as';\nimport { contract, type Ctx } from '../context';\n\n/** One withdrawn-validator record for `reportRegularWithdrawnValidators`. */\nexport interface WithdrawnValidatorInfo {\n nodeOperatorId: bigint;\n keyIndex: bigint;\n exitBalance: bigint;\n slashingPenalty: bigint;\n isSlashed: boolean;\n}\n\n/** Report a validator slashing for an operator's key (Verifier-gated). `keyIndex` is the storage index. */\nexport async function slash(ctx: Ctx, opts: { noId: bigint; keyIndex: bigint }): Promise<void> {\n const m = contract(ctx, 'module');\n await actAs(ctx, ctx.addresses.Verifier, (from) =>\n ctx.client.writeContract({\n ...m,\n functionName: 'reportValidatorSlashing',\n args: [opts.noId, opts.keyIndex],\n account: from,\n chain: null,\n }),\n );\n}\n\n/** Report a regular validator withdrawal for one key (Verifier-gated). isSlashed = slashingPenalty > 0. */\nexport async function withdraw(\n ctx: Ctx,\n opts: { noId: bigint; keyIndex: bigint; exitBalance: bigint; slashingPenalty?: bigint },\n): Promise<void> {\n const m = contract(ctx, 'module');\n const slashingPenalty = opts.slashingPenalty ?? 0n;\n const info: WithdrawnValidatorInfo = {\n nodeOperatorId: opts.noId,\n keyIndex: opts.keyIndex,\n exitBalance: opts.exitBalance,\n slashingPenalty,\n isSlashed: slashingPenalty > 0n,\n };\n await actAs(ctx, ctx.addresses.Verifier, (from) =>\n ctx.client.writeContract({\n ...m,\n functionName: 'reportRegularWithdrawnValidators',\n args: [[info]],\n account: from,\n chain: null,\n }),\n );\n}\n","import { maxUint256, toHex } from 'viem';\nimport type { Hex } from '@sm-lab/receipts';\nimport { actAs, roleMember } from '../act-as';\nimport { contract, type Ctx } from '../context';\nimport { REPORT_GENERAL_DELAYED_PENALTY_ROLE, SETTLE_GENERAL_DELAYED_PENALTY_ROLE } from '../roles';\n\n/** Report a general delayed penalty against an operator (penalty-reporter role). */\nexport async function reportPenalty(\n ctx: Ctx,\n opts: { noId: bigint; amount: bigint; penaltyType?: Hex; details?: string },\n): Promise<void> {\n const m = contract(ctx, 'module');\n const reporter = await roleMember(ctx, m, REPORT_GENERAL_DELAYED_PENALTY_ROLE);\n const penaltyType = opts.penaltyType ?? toHex(1n, { size: 32 });\n const details = opts.details ?? 'fork-penalty';\n await actAs(ctx, reporter, (from) =>\n ctx.client.writeContract({\n ...m,\n functionName: 'reportGeneralDelayedPenalty',\n args: [opts.noId, penaltyType, opts.amount, details],\n account: from,\n chain: null,\n }),\n );\n}\n\n/** Cancel a previously-reported general delayed penalty (penalty-reporter role). */\nexport async function cancelPenalty(\n ctx: Ctx,\n opts: { noId: bigint; amount: bigint },\n): Promise<void> {\n const m = contract(ctx, 'module');\n const reporter = await roleMember(ctx, m, REPORT_GENERAL_DELAYED_PENALTY_ROLE);\n await actAs(ctx, reporter, (from) =>\n ctx.client.writeContract({\n ...m,\n functionName: 'cancelGeneralDelayedPenalty',\n args: [opts.noId, opts.amount],\n account: from,\n chain: null,\n }),\n );\n}\n\n/**\n * Settle (process) an operator's general delayed penalty (penalty-settler role).\n * The `maxAmount` option is the per-operator settlement cap passed as the contract's 2nd array arg (confusingly named `bondLockNonces` in the ABI); the default `maxUint256` settles the penalty fully.\n */\nexport async function settlePenalty(\n ctx: Ctx,\n opts: { noId: bigint; maxAmount?: bigint },\n): Promise<void> {\n const m = contract(ctx, 'module');\n const settler = await roleMember(ctx, m, SETTLE_GENERAL_DELAYED_PENALTY_ROLE);\n await actAs(ctx, settler, (from) =>\n ctx.client.writeContract({\n ...m,\n functionName: 'settleGeneralDelayedPenalty',\n args: [[opts.noId], [opts.maxAmount ?? maxUint256]],\n account: from,\n chain: null,\n }),\n );\n}\n\n/** Compensate (pay off) an operator's general delayed penalty — signed by the operator manager. */\nexport async function compensatePenalty(ctx: Ctx, opts: { noId: bigint }): Promise<void> {\n const m = contract(ctx, 'module');\n const op = await ctx.client.readContract({\n ...m,\n functionName: 'getNodeOperator',\n args: [opts.noId],\n });\n await actAs(ctx, op.managerAddress, (from) =>\n ctx.client.writeContract({\n ...m,\n functionName: 'compensateGeneralDelayedPenalty',\n args: [opts.noId],\n account: from,\n chain: null,\n }),\n );\n}\n","import { actAs } from '../act-as';\nimport { contract, type Ctx } from '../context';\n\n/** Top up an operator's bond with ETH (permissionless `depositETH`), signed by the manager. */\nexport async function addBond(ctx: Ctx, opts: { noId: bigint; amount: bigint }): Promise<void> {\n const m = contract(ctx, 'module');\n const acc = contract(ctx, 'Accounting');\n const op = await ctx.client.readContract({\n ...m,\n functionName: 'getNodeOperator',\n args: [opts.noId],\n });\n await actAs(ctx, op.managerAddress, (from) =>\n ctx.client.writeContract({\n ...acc,\n functionName: 'depositETH',\n args: [opts.noId],\n account: from,\n value: opts.amount,\n chain: null,\n }),\n );\n}\n\n/**\n * Charge a penalty against an operator's bond (creating bond debt if uncovered). `Accounting.penalize`\n * is module-only, so we impersonate the module address. Returns whether the penalty was fully covered.\n */\nexport async function createBondDebt(\n ctx: Ctx,\n opts: { noId: bigint; amount: bigint },\n): Promise<{ penaltyCovered: boolean }> {\n const moduleAddress = contract(ctx, 'module').address;\n const acc = contract(ctx, 'Accounting');\n return actAs(ctx, moduleAddress, async (from) => {\n const { result, request } = await ctx.client.simulateContract({\n ...acc,\n functionName: 'penalize',\n args: [opts.noId, opts.amount],\n account: from,\n });\n await ctx.client.writeContract({ ...request, chain: null });\n return { penaltyCovered: result };\n });\n}\n","import {\n buildAddressesTree,\n ipfsOptionsFromEnv,\n pinJsonToIpfs,\n shouldAttemptPin,\n} from '@sm-lab/merkle';\nimport { curatedGateAbi, vettedGateAbi } from '@sm-lab/receipts';\nimport type { Hex } from '@sm-lab/receipts';\nimport { actAs, roleMember } from '../act-as';\nimport { resolveGate, type Ctx, type GateSelector } from '../context';\nimport { DEFAULT_ADMIN_ROLE, SET_TREE_ROLE } from '../roles';\n\nexport interface SetGateAddrsOptions {\n /** Whitelisted addresses to encode into the gate's merkle tree. */\n addresses: Hex[];\n /**\n * Gate selector passed to resolveGate. csm: 'ics' (default) | 'idvtc'; cm:\n * 'po'|'pto'|'pgo'|'do'|'eeo'|'iodc'|'iodcp' (default 'po') or a gate index; any: a raw 0x… address.\n */\n selector?: GateSelector | string;\n /** Skip IPFS pinning by supplying a precomputed cid (hermetic tests do this). */\n cid?: string;\n}\n\nexport interface SetGateAddrsResult {\n treeRoot: Hex;\n treeCid: string;\n}\n\n/** Default gate selector per module: cm → 'po' (CuratedGates[0]); csm → 'ics' (VettedGate). */\nfunction defaultSelector(ctx: Ctx): string {\n return ctx.module === 'cm' ? 'po' : 'ics';\n}\n\n/**\n * Build a gate addresses tree (OZ ['address'], via @sm-lab/merkle) and install it on the gate\n * (`setTreeParams(root, cid)`), impersonating the gate admin. The cid is pinned to IPFS\n * (env-configured: a local @sm-lab/ipfs or Pinata) unless `cid` is supplied.\n *\n * Module-agnostic (port of fork.just `set-gate-addrs` + `update-gate-tree`, both selector-driven):\n * the csm VettedGate and cm CuratedGate share a byte-identical grantRole/setTreeParams/getRoleMember\n * surface, so the only per-module differences are the resolved address, the default selector, and\n * which gate ABI carries the fragments.\n */\nexport async function setGateAddrs(\n ctx: Ctx,\n opts: SetGateAddrsOptions,\n): Promise<SetGateAddrsResult> {\n const selector = opts.selector ?? defaultSelector(ctx);\n // Both gate ABIs carry a byte-identical grantRole/setTreeParams/getRoleMember surface, so we use\n // the module's own ABI at runtime but pin the compile-time type to one constituent (viem can't\n // infer a union abi). Only those three fragments are ever called — sound for either gate.\n const abi = (ctx.module === 'cm' ? curatedGateAbi : vettedGateAbi) as typeof vettedGateAbi;\n const gate = { address: resolveGate(ctx, selector), abi } as const;\n const tree = buildAddressesTree(opts.addresses);\n const treeRoot = tree.root as Hex;\n const treeCid = opts.cid ?? (await pinTree(tree.dump(), selector));\n const admin = await roleMember(ctx, gate, DEFAULT_ADMIN_ROLE);\n\n await actAs(ctx, admin, async (from) => {\n await ctx.client.writeContract({\n ...gate,\n functionName: 'grantRole',\n args: [SET_TREE_ROLE, admin],\n account: from,\n chain: null,\n });\n await ctx.client.writeContract({\n ...gate,\n functionName: 'setTreeParams',\n args: [treeRoot, treeCid],\n account: from,\n chain: null,\n });\n });\n\n return { treeRoot, treeCid };\n}\n\nasync function pinTree(dump: unknown, selector: string): Promise<string> {\n // Guard BEFORE any network call so hermetic tests (no IPFS env) never hit the wire.\n if (!shouldAttemptPin()) {\n throw new Error(\n '@sm-lab/recipes: could not pin the gate tree — set IPFS_API_URL (a local @sm-lab/ipfs) or PINATA_* credentials, or pass opts.cid',\n );\n }\n return pinJsonToIpfs(dump, `gate-${selector}`, ipfsOptionsFromEnv());\n}\n","import { makeRewards as makeRewardsTree, shouldAttemptPin, type TreeDump } from '@sm-lab/merkle';\nimport { encodeAbiParameters, keccak256, parseAbiParameters, parseEther, toBytes } from 'viem';\nimport {\n feeDistributorAbi,\n feeOracleAbi,\n hashConsensusAbi,\n lidoAbi,\n type Hex,\n} from '@sm-lab/receipts';\nimport { actAs } from '../act-as';\nimport { contract, type Ctx } from '../context';\nimport { randomSeed } from '../random';\nimport { operatorInfo } from './operator-info';\nimport { warpTo } from './chain';\n\n/** Reward draw bounds (mirrors `mock-rewards.mjs`): per active key, in wei. */\nconst REWARD_MIN_WEI = 100_000_000_000_000_000n; // 0.1 ETH\nconst REWARD_MAX_WEI = 200_000_000_000_000_000n; // 0.2 ETH\nconst REWARD_SPAN = REWARD_MAX_WEI - REWARD_MIN_WEI; // 1e17\n/** type(uint64).max — padding id for a lone real operator (FeeDistributor non-empty-proof rule). */\nconst PAD_NO_ID = (1n << 64n) - 1n;\n/** Empty-tree sentinel root: 32 zero bytes. */\nconst ZERO_ROOT = `0x${'00'.repeat(32)}` as Hex;\n\nexport interface RewardsReport {\n /** tree.root, or ZERO_ROOT when there are no leaves. */\n treeRoot: Hex;\n /** pinned (or opts.treeCid); '' when treeRoot is zero. */\n treeCid: string;\n /** pinned (or opts.logCid); '' when treeRoot is zero. */\n logCid: string;\n /** Sum of all per-operator distributed rewards this frame. */\n distributed: bigint;\n /** Always 0n in the mock (matches the source). */\n rebate: bigint;\n /** In-memory OZ tree dump (uint256-as-string → JSON-safe) for tests / re-pin. Undefined when empty. */\n treeDump?: TreeDump;\n /** Cumulative leaves AFTER carry-forward + this frame's deltas, EXCLUDING the pad. */\n cumulatives: Map<bigint, bigint>;\n}\n\nexport interface MakeRewardsOptions {\n /** Injectable seed → deterministic per-key reward draw. Omit for fresh randomness. */\n seed?: Hex;\n /** Carry-forward input: the previous cumulative tree as a Map (or [noId, shares][]). */\n previousCumulatives?: Map<bigint, bigint> | [bigint, bigint][];\n /** Hermetic escape hatch: skip pinning the tree, use this cid. */\n treeCid?: string;\n /** Hermetic escape hatch: skip pinning the log, use this cid. */\n logCid?: string;\n /** Injectable clock (unix seconds) for the report log's block_timestamp. Defaults Date.now()/1000. */\n now?: number;\n}\n\n/**\n * Build the cumulative FeeDistributor rewards tree off on-chain operator state and a seeded mock\n * reward per active key, pin the tree + report log to IPFS (guarded), and return a typed in-memory\n * `RewardsReport`. Port of `mock-rewards.mjs` — but the OUTPUT path stays bigint-typed (no bare\n * `JSON.stringify` of bigints), and the per-key draw is fully seeded (no `Math.random`) so tests can\n * pin `treeRoot`/`distributed`.\n *\n * Carry-forward is via `opts.previousCumulatives` only (option (a) of the design). The pure\n * carry-forward logic — carry every prior leaf forward except the pad, then add this frame's deltas —\n * is identical no matter where the prior Map came from, so the fork path chains calls:\n * `makeRewards(ctx, { previousCumulatives: prev.cumulatives })`.\n * TODO(6f?): on-chain `treeRoot()` → `treeCid()` → IPFS fetch of the prior tree as a default source.\n */\nexport async function makeRewards(ctx: Ctx, opts: MakeRewardsOptions = {}): Promise<RewardsReport> {\n // The all-bigint seeded draw deliberately diverges from the source's lossy\n // `BigInt(Math.floor(Math.random() * Number(REWARD_SPAN)))`: we keccak-hash the seed (32-byte\n // random when omitted, via the shared `randomSeed`) so the draw is reproducible and full-precision.\n const seed = opts.seed ?? randomSeed();\n\n const m = contract(ctx, 'module');\n const count = (await ctx.client.readContract({\n ...m,\n functionName: 'getNodeOperatorsCount',\n })) as bigint;\n\n // --- read every operator (parallel; independent reads), then draw seeded rewards per active key.\n // REUSE operatorInfo (typed; uint32 already decodes to `number` — no Number() casts). The draw is\n // keyed on `noId` so it is order-independent; we still walk in ascending noId for stable output. ---\n const ids = Array.from({ length: Number(count) }, (_, i) => BigInt(i));\n const infos = await Promise.all(ids.map((noId) => operatorInfo(ctx, { noId })));\n\n const reportOperators: Record<string, { distributed_rewards: bigint }> = {};\n const frameDeltas = new Map<bigint, bigint>();\n let distributed = 0n;\n\n for (const [i, noId] of ids.entries()) {\n const info = infos[i]!;\n const activeKeys = info.totalDepositedKeys - info.totalWithdrawnKeys;\n if (activeKeys <= 0) continue;\n\n let opDistributed = 0n;\n for (let k = 0; k < activeKeys; k++) {\n opDistributed += REWARD_MIN_WEI + seededUint(seed, `reward:${noId}:${k}`, REWARD_SPAN);\n }\n reportOperators[noId.toString()] = { distributed_rewards: opDistributed };\n frameDeltas.set(noId, opDistributed);\n distributed += opDistributed;\n }\n\n const rebate = 0n;\n\n // --- carry-forward: prior cumulatives (pad excluded) + this frame's deltas ---\n const cumulatives = new Map<bigint, bigint>();\n for (const [noId, shares] of normalizePrevious(opts.previousCumulatives)) {\n if (noId !== PAD_NO_ID) cumulatives.set(noId, shares);\n }\n for (const [noId, delta] of frameDeltas) {\n cumulatives.set(noId, (cumulatives.get(noId) ?? 0n) + delta);\n }\n\n // --- build leaves; pad a lone real operator (FeeDistributor rejects empty proofs) ---\n const leaves = [...cumulatives.entries()].map(\n ([noId, shares]) => [noId, shares] as [bigint, bigint],\n );\n if (leaves.length === 1) leaves.push([PAD_NO_ID, 0n]);\n\n if (leaves.length === 0) {\n // Empty report: no tree, no pin. submitRewards treats ZERO_ROOT as a graceful skip.\n return { treeRoot: ZERO_ROOT, treeCid: '', logCid: '', distributed, rebate, cumulatives };\n }\n\n // Guard before the IPFS pin so hermetic tests with no IPFS env and no escape cids fail loudly\n // instead of hitting the wire. Mirrors `setGateAddrs.pinTree`. Sits AFTER the empty-report return\n // so an empty fork never needs IPFS configured.\n // shouldAttemptPin() is true by default (local-first); it returns false ONLY when\n // IPFS_API_URL points at real Pinata with no credentials. That is the canonical \"not configured\"\n // state tests can set to trigger this guard.\n const needsPin = opts.treeCid === undefined || opts.logCid === undefined;\n if (needsPin && !shouldAttemptPin()) {\n throw new Error(\n '@sm-lab/recipes: could not pin the rewards tree/log — set IPFS_API_URL (a local @sm-lab/ipfs) or PINATA_* credentials, or pass opts.treeCid + opts.logCid',\n );\n }\n\n // The report log (faithful-but-minimal mock shape) — bigints nested in operators[*] are\n // serialized by merkle's makeRewardsTree (bigintReplacer) before pinning.\n const blockTimestamp = opts.now ?? Math.floor(Date.now() / 1000);\n const log = {\n blockstamp: { block_timestamp: blockTimestamp },\n distributable: distributed,\n distributed_rewards: distributed,\n rebate_to_protocol: rebate,\n operators: reportOperators,\n };\n\n // Delegate pin and tree build to merkle's makeRewards. It returns a JSON-safe treeDump\n // (bigint leaf values serialized as decimal strings) — no local tree build needed.\n // When escape-hatch cids are both set, skip upload entirely (noUpload: true).\n // Otherwise let merkle handle the pin — it uses the same shouldAttemptPin() path guarded above.\n let treeRoot: Hex;\n let treeCid: string;\n let logCid: string;\n let treeDump: TreeDump;\n\n if (opts.treeCid !== undefined && opts.logCid !== undefined) {\n // Both escape-hatch cids supplied: still need to build the tree for treeRoot + treeDump.\n const result = await makeRewardsTree(leaves, { noUpload: true });\n treeRoot = result.treeRoot as Hex;\n treeDump = result.treeDump;\n treeCid = opts.treeCid;\n logCid = opts.logCid;\n } else if (opts.treeCid !== undefined) {\n // tree cid supplied, only pin the log\n const result = await makeRewardsTree(leaves, { log, noUpload: false });\n treeRoot = result.treeRoot as Hex;\n treeDump = result.treeDump;\n treeCid = opts.treeCid;\n logCid = result.logCid ?? '';\n } else if (opts.logCid !== undefined) {\n // log cid supplied, only pin the tree\n const result = await makeRewardsTree(leaves, { noUpload: false });\n treeRoot = result.treeRoot as Hex;\n treeDump = result.treeDump;\n treeCid = result.treeCid ?? '';\n logCid = opts.logCid;\n } else {\n // No escape-hatch cids: delegate both to merkle\n const result = await makeRewardsTree(leaves, { log });\n treeRoot = result.treeRoot as Hex;\n treeDump = result.treeDump;\n treeCid = result.treeCid ?? '';\n logCid = result.logCid ?? '';\n }\n\n return { treeRoot, treeCid, logCid, distributed, rebate, treeDump, cumulatives };\n}\n\n/** Deterministic uint in `[0, span)` from `keccak256(toBytes(\\`${seed}:${label}\\`)) % span`. */\nfunction seededUint(seed: Hex, label: string, span: bigint): bigint {\n return BigInt(keccak256(toBytes(`${seed}:${label}`))) % span;\n}\n\n/** Normalize the carry-forward input (Map or entries) to an iterable of [noId, shares]. */\nfunction normalizePrevious(\n prev: MakeRewardsOptions['previousCumulatives'],\n): Iterable<[bigint, bigint]> {\n if (!prev) return [];\n return prev instanceof Map ? prev.entries() : prev;\n}\n\n// --- submitRewards (port of OracleReport.s.sol:submitRewards) -------------------------------------\n\nconst ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' as const;\n\n/**\n * The `IFeeOracle.ReportData` struct as ONE tuple parameter — components in declaration order\n * (verified against `fixtures/receipts/src/abi/FeeOracle.ts`). `abi.encode(data)` for a single\n * struct == ABI-encoding one tuple parameter (head/tail offsets for the dynamic `string` fields);\n * passing the tuple type as a single param to `encodeAbiParameters` reproduces it. Do NOT flatten\n * into 9 top-level params — that drops the tuple offset and changes the hash. This is the exact\n * reportHash transcription trap.\n */\nconst REPORT_DATA_PARAMS = parseAbiParameters(\n '(uint256 consensusVersion, uint256 refSlot, bytes32 treeRoot, string treeCid, string logCid, uint256 distributed, uint256 rebate, bytes32 strikesTreeRoot, string strikesTreeCid)',\n);\n\n/** The 9-field oracle ReportData tuple (bigints for the uint256 fields). */\ninterface ReportData {\n consensusVersion: bigint;\n refSlot: bigint;\n treeRoot: Hex;\n treeCid: string;\n logCid: string;\n distributed: bigint;\n rebate: bigint;\n strikesTreeRoot: Hex;\n strikesTreeCid: string;\n}\n\nexport interface SubmitRewardsResult {\n /** false when treeRoot is zero (a legitimate empty-report skip). */\n submitted: boolean;\n /** present when submitted: the consensus frame's refSlot. */\n refSlot?: bigint;\n /** echo of report.treeRoot when submitted. */\n treeRoot?: Hex;\n /** the keccak256(abi.encode(data)) reached consensus on. */\n reportHash?: Hex;\n /** the consensus members that submitted (fast-lane, or the getMembers fallback). */\n members?: Hex[];\n}\n\n/**\n * Submit a `RewardsReport` (from `makeRewards`) on-chain: fund the FeeDistributor, warp to the next\n * consensus frame, build the `ReportData` tuple, reach consensus across the fast-lane members (with\n * a `getMembers` fallback), and submit the report data. Port of `OracleReport.s.sol:submitRewards`.\n *\n * Fork-only in practice (it WRITES + warps); the hermetic tests assert the call sequence, the funding\n * literals, the warp arguments, and the reportHash, not real frame advancement.\n *\n * A zero-root report (no active keys this frame) is a graceful no-op: returns `{ submitted: false }`\n * with no reads/writes, so `submitRewards(ctx, await makeRewards(ctx))` composes on an empty fork.\n */\nexport async function submitRewards(ctx: Ctx, report: RewardsReport): Promise<SubmitRewardsResult> {\n if (report.treeRoot === ZERO_ROOT) return { submitted: false };\n\n const feeDistributor = { address: ctx.addresses.FeeDistributor as Hex, abi: feeDistributorAbi };\n const oracle = { address: ctx.addresses.FeeOracle as Hex, abi: feeOracleAbi };\n const hashConsensus = { address: ctx.addresses.HashConsensus as Hex, abi: hashConsensusAbi };\n const lido = { address: ctx.addresses.lido, abi: lidoAbi };\n\n // --- 1. Fund the FeeDistributor with stETH shares if it cannot cover this frame ---\n const pending = (await ctx.client.readContract({\n ...feeDistributor,\n functionName: 'pendingSharesToDistribute',\n })) as bigint;\n if (pending < report.distributed + report.rebate) {\n const neededShares = report.distributed + report.rebate - pending;\n // X = getPooledEthByShares(neededShares); submit value = X + 1 ether; setBalance = X + 2 ether\n // (matches the source's `neededEth = X + 1 ether; _setBalance(fd, neededEth + 1 ether)`).\n // Inline the impersonation (not actAs) so the funding survives — actAs would clobber the\n // balance back to 100 ETH, which can be < the needed amount for large rewards.\n const x = (await ctx.client.readContract({\n ...lido,\n functionName: 'getPooledEthByShares',\n args: [neededShares],\n })) as bigint;\n const submitValue = x + parseEther('1');\n const fd = feeDistributor.address;\n await ctx.client.setBalance({ address: fd, value: x + parseEther('2') });\n await ctx.client.impersonateAccount({ address: fd });\n try {\n await ctx.client.writeContract({\n ...lido,\n functionName: 'submit',\n args: [ZERO_ADDRESS],\n value: submitValue,\n account: fd,\n chain: null,\n });\n } finally {\n await ctx.client.stopImpersonatingAccount({ address: fd });\n }\n }\n\n // --- 2. Warp to the next valid consensus frame (_waitForNextRefSlot) — all bigint math ---\n const [slotsPerEpoch, secondsPerSlot, genesisTime] = (await ctx.client.readContract({\n ...hashConsensus,\n functionName: 'getChainConfig',\n })) as [bigint, bigint, bigint];\n const [initialEpoch, epochsPerFrame] = (await ctx.client.readContract({\n ...hashConsensus,\n functionName: 'getFrameConfig',\n })) as [bigint, bigint, bigint];\n\n const ts = (await ctx.client.getBlock()).timestamp;\n const epoch = (ts - genesisTime) / secondsPerSlot / slotsPerEpoch;\n if (epoch < initialEpoch) {\n await warpTo(ctx, genesisTime + 1n + initialEpoch * slotsPerEpoch * secondsPerSlot);\n }\n\n const [frameRefSlot] = (await ctx.client.readContract({\n ...hashConsensus,\n functionName: 'getCurrentFrame',\n })) as [bigint, bigint];\n const frameStart =\n genesisTime + (frameRefSlot + slotsPerEpoch * epochsPerFrame + 1n) * secondsPerSlot;\n const ts2 = (await ctx.client.getBlock()).timestamp;\n if (frameStart > ts2) {\n await warpTo(ctx, frameStart);\n }\n\n // Re-read the frame AFTER the warp: the report must carry the now-current refSlot, not the\n // pre-warp one (the warp deliberately advances a full frame past `frameRefSlot`). The source\n // reads getCurrentFrame() again right after `_waitForNextRefSlot()` (OracleReport.s.sol:46);\n // inlining the wait must not drop that second read, or submitReport/submitReportData land on a\n // stale refSlot and HashConsensus reverts.\n const [refSlot] = (await ctx.client.readContract({\n ...hashConsensus,\n functionName: 'getCurrentFrame',\n })) as [bigint, bigint];\n\n // --- 3. Build ReportData (mock strikes values) + reportHash ---\n const consensusVersion = (await ctx.client.readContract({\n ...oracle,\n functionName: 'getConsensusVersion',\n })) as bigint;\n const data: ReportData = {\n consensusVersion,\n refSlot,\n treeRoot: report.treeRoot,\n treeCid: report.treeCid,\n logCid: report.logCid,\n distributed: report.distributed,\n rebate: report.rebate,\n strikesTreeRoot: strikesTreeRoot(refSlot),\n strikesTreeCid: `mock-strikes-${refSlot}`,\n };\n const hash = reportHash(data);\n\n // --- 4. Members with fast-lane → getMembers fallback (the Fixtures.sol fallback the .s.sol omits) ---\n let [members] = (await ctx.client.readContract({\n ...hashConsensus,\n functionName: 'getFastLaneMembers',\n })) as [Hex[], bigint[]];\n if (members.length === 0) {\n [members] = (await ctx.client.readContract({\n ...hashConsensus,\n functionName: 'getMembers',\n })) as [Hex[], bigint[]];\n }\n if (members.length === 0) {\n throw new Error('@sm-lab/recipes: no consensus members to reach quorum');\n }\n\n // --- 5. Reach consensus from every member, then submit the report data as members[0] ---\n // Sequential is REQUIRED, not a missed parallelization: actAs impersonates one account at a time\n // (impersonate → write → stop), and impersonation is global fork state — running these in parallel\n // would interleave the start/stop of different members. Matches the source's sequential loop.\n for (const member of members) {\n // eslint-disable-next-line no-await-in-loop -- sequential by necessity (impersonation is global state)\n await actAs(ctx, member, (from) =>\n ctx.client.writeContract({\n ...hashConsensus,\n functionName: 'submitReport',\n args: [refSlot, hash, consensusVersion],\n account: from,\n chain: null,\n }),\n );\n }\n\n const contractVersion = (await ctx.client.readContract({\n ...oracle,\n functionName: 'getContractVersion',\n })) as bigint;\n await actAs(ctx, members[0]!, (from) =>\n ctx.client.writeContract({\n ...oracle,\n functionName: 'submitReportData',\n args: [data, contractVersion],\n account: from,\n chain: null,\n }),\n );\n\n return { submitted: true, refSlot, treeRoot: report.treeRoot, reportHash: hash, members };\n}\n\n/** keccak256(abi.encode(data)) — encode the 9-field struct as ONE tuple param (see REPORT_DATA_PARAMS). */\nfunction reportHash(data: ReportData): Hex {\n return keccak256(encodeAbiParameters(REPORT_DATA_PARAMS, [data]));\n}\n\n/**\n * Mock strikes root: `keccak256(abi.encode(\"mock-strikes\", refSlot))` — TWO top-level params\n * (`string`, `uint256`), NOT a tuple. Matches the source's `abi.encode(a, b)`.\n */\nfunction strikesTreeRoot(refSlot: bigint): Hex {\n return keccak256(\n encodeAbiParameters(parseAbiParameters('string, uint256'), ['mock-strikes', refSlot]),\n );\n}\n","/**\n * cl-mock bridge — a thin `fetch` client that POSTs one validator to a running\n * `@sm-lab/cl` (`/admin/validators`). Mirrors the discipline of `tools/merkle/src/ipfs.ts`:\n * trailing-slash-stripped URL join, explicit `as` cast for the response (no DOM lib), and a\n * throw carrying status + the mock's `errors[]`. Ctx-agnostic — takes a `clMockUrl: string`, not\n * the whole `Ctx`, so it stays trivially unit-testable.\n */\n\nimport type { Hex } from '@sm-lab/receipts';\n\nexport interface SetValidatorInput {\n pubkey: Hex;\n /** Only status clActivate sets; cl-mock's full union lives in the app, not here. */\n status: 'active_ongoing';\n /** Serialized to a gwei integer string on the wire; omitted when undefined. */\n effectiveBalanceGwei?: bigint;\n}\n\ninterface ClMockResponse {\n accepted: number;\n errors: string[];\n}\n\n/**\n * POST one validator to a running `@sm-lab/cl` `/admin/validators`. Surfaces the mock's\n * `errors[]` and throws unless the single item was accepted.\n *\n * cl-mock returns 200 (clean), 207 (partial — only when `errors.length > 0` AND `accepted > 0`,\n * which is impossible for a single item), or 400 (all rejected, no `accepted` field). For one\n * item the realistic failure is 400, caught by the `!res.ok` clause. The `(accepted ?? 0) < 1`\n * guard is defensive belt-and-braces for a synthetic accepted:0 / missing-`accepted` body the mock\n * never actually emits — the `?? 0` is load-bearing, since a bare `accepted < 1` is `false` for\n * `undefined` and would let such a body through as a silent success.\n */\nexport async function setClValidator(clMockUrl: string, input: SetValidatorInput): Promise<void> {\n const url = `${clMockUrl.replace(/\\/+$/, '')}/admin/validators`;\n const body = JSON.stringify({\n pubkey: input.pubkey,\n status: input.status,\n ...(input.effectiveBalanceGwei !== undefined\n ? { effective_balance: input.effectiveBalanceGwei.toString() }\n : {}),\n });\n\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n });\n\n const json = (await res.json().catch(() => undefined)) as ClMockResponse | undefined;\n if (!res.ok || !json || (json.accepted ?? 0) < 1) {\n const errs = json?.errors?.length ? ` — ${json.errors.join('; ')}` : '';\n throw new Error(\n `@sm-lab/recipes: cl-mock rejected validator (${res.status} ${res.statusText})${errs}`,\n );\n }\n}\n","import type { Hex } from '@sm-lab/receipts';\nimport type { Ctx } from '../context';\nimport { setClValidator } from '../cl-mock';\nimport { getKeyBalance, getPubkey } from './reads';\n\nconst GWEI_PER_ETH = 1_000_000_000n;\nconst BASE_ETH_GWEI = 32n * GWEI_PER_ETH; // base 32 ETH, in gwei (32_000_000_000n)\n\nexport interface ClActivateResult {\n pubkey: Hex;\n status: 'active_ongoing';\n effectiveBalanceGwei: bigint;\n}\n\n/**\n * Read a key's pubkey + allocated balance on-chain, then mark it `active_ongoing` on a running\n * cl-mock with effective balance = 32 ETH + allocated balance, in gwei. Port of\n * `cl-mock.just:cl-activate`. Diverges from the Solidity helper's integer-ETH truncation\n * (`balances[0] / 1 ether`) by keeping full gwei precision (cl-mock stores `effective_balance`\n * in gwei) — the spec-blessed divergence.\n */\nexport async function clActivate(\n ctx: Ctx,\n opts: { noId: bigint; keyIndex: bigint },\n): Promise<ClActivateResult> {\n if (!ctx.clMockUrl) {\n throw new Error('@sm-lab/recipes: clActivate needs ctx.clMockUrl (a running cl-mock)');\n }\n // Sequential, not Promise.all: pubkey first so an empty key throws \"no key found\" before any\n // balance read (deterministic errors; no balance read on the empty-pubkey path).\n const pubkey = await getPubkey(ctx, opts);\n const allocWei = await getKeyBalance(ctx, opts);\n // BigInt `/` floors sub-gwei dust (allocWei >= 0 so floor == truncation toward zero).\n const effectiveBalanceGwei = BASE_ETH_GWEI + allocWei / GWEI_PER_ETH;\n await setClValidator(ctx.clMockUrl, {\n pubkey,\n status: 'active_ongoing',\n effectiveBalanceGwei,\n });\n return { pubkey, status: 'active_ongoing', effectiveBalanceGwei };\n}\n"],"mappings":"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"}
package/dist/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+ export { };