feat(affiliates): add gas rebate 71 for July 2026 - #4964
Conversation
droplet-rl
left a comment
There was a problem hiding this comment.
Approved.
Verified against the artifact rather than the description:
- Contiguity —
fromBlock25433939 = rebate 70'stoBlock(25433938) + 1. No gap, no overlap. Span 222,355 blocks ≈ 30.9 days, consistent with a full July. - Payout map integrity — 489 entries, matches
countVoters. All keys well-formed0x+40 hex, no case-insensitive duplicates, no zero/negative values. Range 0.000169–0.031848 ETH. - Total — sum of
shareholderPayout= 3.442967924213756, declaredtotalRebateAmount= 3.4429679242137565 (delta 4.4e-16, float repr only). Matches the audit's 3442967924213756578 wei. - Contract —
0x004395edb43EFca9885CEdad51EC9fAf93Bd34ac, same VotingV2 as rebate 70. - Exclusion list — size 115 / SHA-256
9ddde4ac…is byte-identical to the list used for rebate 70, so no silent list drift. Confirmed invoterGasRebateV2Utils.tsthat excluded addresses aredeleted fromshareholderPayoutWeibeforetotalRebateWeiis summed, so the 0.5035 ETH excluded rebate is genuinely withheld and the 489 payees are post-exclusion. - Audit — validation passed, 0 validation failures, 0 anomalies, 1 provider error recovered by 1 retry, 0 splits.
- CI green across all six CircleCI jobs.
Two non-blocking notes:
- The PR description says this is the "first full month with the delegate exclusion list applied." Rebate 70's audit carries the same list size and hash, so the list wasn't new here — 70 was just a half-month window (107,588 blocks), so "first full month" is fair, but the list itself predates this run.
Rebate_71.audit.mdembeds the generator's local path (/home/ubuntu/ghq/...). Harmless, but it leaks a workstation layout into a public repo and adds diff noise across runs. Worth emitting a repo-relative path in a future tooling pass.
The one input I can't independently verify is the 115-address exclusion list itself — it isn't checked into the repo, so the audit's SHA-256 is the only provenance. Consistency with rebate 70 is the strongest signal available from here.
droplet-rl
left a comment
There was a problem hiding this comment.
Approving — artifact verified independently.
Checks performed
shareholderPayouthas 489 entries, matchescountVoters: 489; no duplicate addresses, no zero/contract address, all well-formed.- Sum of payouts equals
totalRebateAmountto float precision (Δ 4.4e-16, accumulation only).totalRebateAmount: 3.4429679242137565is the exact nearest double to the audited3442967924213756578wei, so the payout total round-trips to the audited wei. - Block range is exactly July 2026 UTC: block 25433939 = 2026-07-01T00:00:11Z, verified on mainnet.
- Contiguous with Rebate 70 (
toBlock 25433938= 2026-06-30T23:59:59Z →fromBlock 25433939). No gap. - Exclusion list SHA-256
9ddde4ac…is byte-identical to Rebate 70's, so the same 115-address list was applied. - Audit reconciles: eligible reveals 160952 − matched commits 153966 = 6986 = boundary commits recovered. Same shape as Rebate 69 (94764 − 76499 = 18265).
- Validation passed, 0 validation failures, 0 splits, 0 anomalies. 1 provider error / 1 retry across 2180 query attempts is unremarkable.
- No secrets in either file; audit records only the
CUSTOM_NODE_URLboolean. - All CI green.
Non-blocking, but worth acting on before Rebate 72
toBlock: 25656293 is one block past July — its timestamp is 2026-08-01T00:00:11Z. The last July block is 25656292 (2026-07-31T23:59:59Z).
This is the auto-derivation path (Override to block configured: false, first run since Rebate 66 not to pin blocks manually). findBlockNumberAtTimestamp is approximate by design: it returns the last block with timestamp < target + higherLimitMax, and higherLimitMax defaults to 15s. Month-end targets 23:59:59, so the window extends to 00:00:14 of the next month and picks up the first block or two of it.
No impact on this payout — block 25656293 contains zero VotingV2 logs, so the numbers above stand as computed.
The forward risk is the overlap. Next month's fromBlock targets 2026-08-01T00:00:00Z with the same +15s window, which selects block 25656293 as well — the same block this rebate already covers. getBlockRanges/queryFilter are inclusive at both ends and nothing asserts fromBlock === previousRebate.toBlock + 1, so a non-empty boundary block would get rebated twice, silently. It happens to be empty this month; that won't hold every month.
Suggested: run Rebate 72 with OVERRIDE_FROM_BLOCK=25656294. Longer term, a contiguity assertion against the previous Rebate_<N>.json at write time would make this fail closed rather than double-pay.
Summary
Validation
packages/affiliates/gas-rebate/rebates/Rebate_71.jsonwithjq -eand confirmed the payout map sums to the reported total.