Static web app tracking reward accrual for the Interfold Initial Ciphernode Rewards Program (IPP-001): 12,000,000 FOLD over six biweekly epochs from the mainnet launch block, split per epoch by Fibonacci weights (1:1:2:3:5:8) in proportion to each node operator's ticket-block accrual (credited tickets × blocks, max 8 credits per operator).
Live app (GitHub Pages) · Proposal text (IPFS)
tools/track.mjs— zero-dependency Node ≥18 script. Replays the Ethereum mainnet event log from the launch block (T0 = 25,786,382, theInterfoldcontract deployment) through the head block, reconstructs the per-block "active" state of every registered ciphernode, and computes per-operator ticket-block accrual and estimated payouts for each epoch. Writesstate.jsonat the repo root.index.html/app.js/styles.css— fully static frontend that rendersstate.json. Styling follows the Interfold site theme tokens (--if-*) used by governance.theinterfold.com.tools/ens.mjs+tools/crypto.mjs— forward-confirmed ENS reverse resolution (self-contained keccak256/namehash, no dependencies); resolved names are stored instate.json(ensmap + per-rowensfields) and shown in the tables.tools/safe.mjs— builds per-epoch Safe transaction-builder payloads for completed epochs intopayouts/epoch-N.safe.json: oneapprove(voteEscrow, total)on FOLD followed by onecreateLockFor(value, operator)per recipient (IPP-001 §3 settlement). The format matches the Safe Transaction Builder import format, so a file can be uploaded directly at app.safe.global (Foundation Safe, Ethereum Mainnet) for review, simulation, and signing. The frontend's "Download Safe payload" button serves these files.tools/pin.mjs— pins the IPP-001 settlement artifacts to IPFS via Pinata so each epoch's 48-hour dispute sheet (IPP-001 §3) is immutable and citable. Per completed epoch it pinspayouts/epoch-N.settlement.md(a human-readable sheet: epoch bounds, pool, per-operator entitlements) and the Safe payload; it also pinsstate.jsonwhenever its content changes. CIDs are recorded inpinnings.json, and the frontend links each pinned sheet + the latest snapshot. Auth is via a GitHub secret:PINATA_JWT(a Pinata Developer JWT, recommended) — or, as a fallback,PINATA_API_KEY+PINATA_API_USER(legacy API key). Pinning is best-effort: if the secret is unset or Pinata errors, the run logs and continues (the state refresh is unaffected). See IPFS pinning below..github/workflows/refresh.yml— runstrack.mjsthree times a day on a schedule (and on demand), commits the newstate.json+payouts/+pinnings.json, pins the artifacts, and GitHub Pages serves the result. No server, no build step.
Registered (between CiphernodeAdded and CiphernodeRemoved) ∧
bond ≥ requiredCiphernodeBond × ciphernodeBondActiveBps / 10000 ∧
ticketBalance / ticketPrice ≥ minTicketBalance ∧ not banned
(NodeBanUpdated). Eligibility parameters are replayed from
ConfigurationUpdated events, so historical blocks use the parameters that
were in force then.
The default operator identity is the bond owner of record, evaluated per
block from BondOwnerSet history (a node whose owner changed accrues to the
owner of record at each block). Foundation common-control determinations
(IPP-001 §3) merge operators on top of this default; the 8-credit cap then
applies to the merged group. Determinations are recorded in each epoch's
Foundation settlement sheet, which remains authoritative — this tracker shows
recomputable estimates under default attribution.
| Contract | Address |
|---|---|
| Interfold | 0x28cF63B459e6218C69EA97ea7D90541cf648c715 |
| CiphernodeRegistry | 0xC927A5B2d8F68697bC28C0670df05178c93df2d7 |
| BondingRegistry | 0x0ec90465095C21830BEcED07e032809A2Bd2915F |
| SlashingManager | 0x753109Ee36Dc65cC178875AddA30C6433e5bEEe4 |
| InterfoldTicketToken (tFOLD) | 0xC0B5b49a3949eC4B520eF21BaCFE16e3695F3B5D |
Source: deployment manifest.
RPC_URL=https://your-archive-rpc node tools/track.mjs
python3 -m http.server 8080 # then open http://localhost:8080The RPC must be an archive endpoint on Ethereum mainnet (the tracker reads
blocks and logs from T0 forward). Block-boundary discovery uses a handful of
eth_getBlockByNumber binary searches; the rest is eth_getLogs — cheap
enough for a hosted free tier at the current registration volume.
Each completed epoch's settlement sheet (the artifact IPP-001 §3 pins for its
48-hour dispute window) is pinned to IPFS so it is immutable and citable, along
with the full state.json snapshot. CIDs land in pinnings.json and the page
links them ("Snapshot (IPFS)" in the header, "Settlement sheet ↗" on each
settled epoch card).
To enable it, add a repository secret:
PINATA_JWT(recommended) — a Pinata Developer JWT (PDJ). Create it in the Pinata dashboard under Account management → API keys → Developer JWTs (grant it pinning permission). The workflow uses it asAuthorization: Bearer <jwt>against Pinata's v3 upload API.- Or the legacy pair
PINATA_API_KEY+PINATA_API_USER(your API key and its account user id) — used with the v1pinByStringendpoint.
Pinning runs after each refresh and is best-effort: if the secret is unset
or Pinata is unavailable, tools/pin.mjs logs and exits cleanly, so the state
refresh and Pages deploy are never blocked. Re-pin behavior: state.json is
re-pinned only when its content changes; each epoch's sheet and Safe payload are
pinned exactly once (on the first refresh after the epoch completes).
- Create the repo and push this directory to
main. - Add a repository secret
RPC_URLwith an archive-node mainnet RPC URL (e.g. an Alchemy key with archive access). - (Optional) Add
PINATA_JWT(orPINATA_API_KEY+PINATA_API_USER) to enable IPFS pinning of settlement sheets. Without it, the tracker works fully; only the IPFS links are omitted. - Settings → Pages → Source: Deploy from a branch →
main// (root). - The scheduled workflow refreshes
state.jsonthree times a day; the page picks it up on the next load.
- Estimates under default bond-owner attribution; the Foundation's per-epoch settlement sheet (with common-control determinations) is authoritative.
- Epoch boundaries are timestamp-driven (14 days from T0); accrual is per block, so in-progress epochs show partial ticket-blocks and payouts scale with the epoch's realized denominator.
- The tracker intentionally does not model the NodeReleaseRegistry readiness
gate or the admission-policy waiting period from the on-chain
isActiveflag (both are launch-window plumbing that resolved within minutes of registration in practice); it implements the IPP-001 predicate directly.