I run an independent testnet validator (shadowoftime, val_id 267, PR #942 in this repo) and over the past few weeks I built a Network Audit page on MonadPulse to surface decentralization, hosting, stake-cluster, and delegation-rotation patterns. Posting here because some of the methodology choices benefit from being challenged by people closer to the protocol than I am.
- Audit page: https://monadpulse.xyz/audit.html (toggle Testnet / Mainnet)
- Source: GitHub - ShadowOfTime1/monadpulse: Independent open-source analytics platform for Monad — live blocks, validators, staking, gas, alerts. Testnet + Mainnet. · GitHub
Data sources
peers.tomlfrom a testnet validator and a mainnet observer node I run on the same server (cryptographically-signed peer registry — every operator publishes their own IP via name records)- Staking precompile (
get_validator,get_execution_valset) for live stake, consensus_stake, commission, and active-set membership - Local block-header DB for proposer attribution and 7-day production windows
stake_eventstable (~17-day history, used for tenure and rotation cadence)- ip-api.com batch endpoint for country / ASN / ISP / datacenter classification
The methodology block at the bottom of the page lists every source, refresh cadence, and accuracy caveat (ip-api country accuracy ~85%, city ~55%, etc.).
Findings I’d like a second pair of eyes on
1. Country vs ASN concentration tells different stories on the two networks.
On testnet, country HHI is 1195 by validator count and 1168 stake-weighted — a small negative delta, suggesting heavy stake spreads slightly wider than counts. ASN-level: 48 unique ASNs across 198 registered validators, with Hetzner (21.7%), MEVSPACE (12.6%) and OVH (12.1%) hosting roughly half. On mainnet the gap inverts and widens: country HHI 1072 → 1131 (+59) and ASN HHI 701 → 847 (+146) when stake-weighted. Heavy stake on mainnet clusters tighter than counts suggest. I’d value a sanity check on whether the ±30 colour threshold I use makes sense at this scale (DOJ ±100 antitrust standards barely register at HHI 700–1200 ranges).
2. /24 co-location surface.
16 distinct /24 subnets host two or more registered testnet validators — about 50 validators sharing a rack with at least one peer. The largest single /24 holds 9 validators on MEVSPACE in Warsaw. I’m calling this the correlated-failure surface; would welcome critique on whether “≥2 in the same /24” is the right granularity, or if /29 would be more honest.
3. Block-production distribution in the rotation pool is strictly bimodal.
Of 259 testnet validators currently eligible for rotation, the 7-day proposing histogram is 63 idle / 0 mid-low / 0 mid / 83 / 113 active. Both middle buckets are empty. I read this as expected behaviour (rotation either places a validator in the active set or it doesn’t), but worth confirming I’m not mis-bucketing the boundary.
4. Tenure is clipped to the stake_events horizon (~17 days).
Validators that joined before the horizon are surfaced as “≥17d” rather than true tenure. I flag this on the page, but a better proxy (e.g. earliest Reward event from an archive node) would be welcome — I just haven’t wired that source in yet.
Disclosure
I’m a participant in the set I’m measuring. The audit pipeline has no allowlist for my own validator: the same buckets, thresholds, and cluster heuristic apply to val_id 267 as to everyone else. The conflict-of-interest note is duplicated inside the page in two places (the queue-tenure block and the methodology footer) so it can’t be screenshotted out of context.
What I’m asking for
- Whether the ±30 stake-weighted HHI delta colour threshold is defensible for HHI values in the 700–1200 range, or whether a different scale-aware rule would be better.
- Whether
≥3 members of the same /24, none with a validator-info entryis the right definition for the “anonymous cluster” callout — currently produces 0 hits on testnet, which feels suspiciously clean given the PR backlog in this repo. - Pointers to similar work on Solana / Cosmos / Eth I should be borrowing methodology from.
Happy to expose additional raw fields from the audit endpoint if it helps anyone reproduce a number, or to open issues on the repo for specific corrections.