/* Sybilhunt — "Who are Sybils" page. window-mounted. Uses kit-components primitives. */ function WReveal({ children, delay = 0, y = 24 }) { const ref = React.useRef(null); const [shown, setShown] = React.useState(false); React.useEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting) { setShown(true); io.unobserve(el); } }); }, { threshold: 0.16 }); io.observe(el); return () => io.disconnect(); }, []); return (
{children}
); } function WCountUp({ to, prefix = '', suffix = '', dur = 1500, decimals = 0 }) { const ref = React.useRef(null); const [val, setVal] = React.useState(0); React.useEffect(() => { const el = ref.current; if (!el) return; let raf, started = false; const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting && !started) { started = true; const t0 = performance.now(); const tick = (t) => { const p = Math.min(1, (t - t0) / dur); const eased = 1 - Math.pow(1 - p, 3); setVal(to * eased); if (p < 1) raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); } }); }, { threshold: 0.5 }); io.observe(el); return () => { io.disconnect(); cancelAnimationFrame(raf); }; }, [to, dur]); const fmt = (n) => Number(n).toLocaleString('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); return {prefix}{fmt(val)}{suffix}; } function WNav({ onClick, active, children }) { return ( ); } function WhoHeader() { const go = (page) => { window.location.href = page; }; return (
go('index.html')} />
); } // ── Content data ───────────────────────────────────────────── const WHO_TRAITS = [ { t: 'One operator, many wallets', d: 'A single person (or a small team) controls dozens to thousands of addresses, each dressed up to look like an independent, ordinary user.' }, { t: 'Manufactured activity', d: 'Wallets are drip-fed identical amounts, run the same swaps, bridge on the same days — just enough on-chain history to pass an eligibility filter.' }, { t: 'Built to farm rewards', d: 'The goal isn\u2019t to use the product. It\u2019s to multiply one person\u2019s share of an airdrop, a grants pool, or an incentive program.' }, ]; // Arbitrum airdrop — X-explore / WuBlockchain report, Mar 2023 const ARB_HEADLINE = [ { v: , label: 'ARB tokens claimed by Sybils', tone: 'coral', sub: '≈ 21.8% of the entire airdrop' }, { v: , label: 'Sybil addresses identified', tone: 'coral', sub: 'out of 624,136 wallets analyzed' }, { v: , label: 'Sybil communities', tone: 'default', sub: 'coordinated wallet clusters' }, { v: , label: 'multi-account addresses', tone: 'default', sub: '≈ 47.96% of tokens — 557M ARB' }, ]; const ARB_METHODS = [ { tag: 'Via exchanges', addrs: '2,997', detail: 'addresses withdrew tiny, near-identical amounts from Binance (0.00114–0.00116 ETH, ~$2) over a 5-day window — then behaved in lockstep.', accent: 'var(--coral-300)' }, { tag: 'Via bridges', addrs: '1,114', detail: 'addresses crossed to Arbitrum through the HOP bridge with fixed ~0.0025 ETH (~$4) deposits, and together collected 1.08M ARB.', accent: 'var(--cyan-300)' }, { tag: 'Via smart contracts', addrs: '9,483', detail: 'donor addresses funded thousands of wallets through the Disperse contract — one seed paid 1,274 airdrop wallets — netting 10.98M ARB.', accent: 'var(--gold-400)' }, { tag: 'Single actors', addrs: '198–202', detail: 'wallets run by one attacker earned 174,375 and 204,250 ARB by staying active after the snapshot and mirroring behaviour across Optimism.', accent: 'var(--signal-400)' }, ]; function WhoApp() { const go = (page) => { window.location.href = page; }; return (
{/* Hero */}
Who are Sybils

One person, pretending to be a crowd

A Sybil is a single actor who operates many wallets or accounts at once to impersonate a whole community of real users. When a project distributes rewards “per person,” the Sybil quietly collects dozens — or thousands — of shares that were meant for everyone else.

{/* Traits */}
{WHO_TRAITS.map((c, i) => (
{String(i + 1).padStart(2, '0')}
{c.t}

{c.d}

))}
{/* Case study intro */}
Case study · Arbitrum airdrop, March 2023

What a real Sybil attack looks like

When Arbitrum launched the ARB token, analysts at X-explore and WuBlockchain ran the entire recipient list through a community-detection model. What they found is the clearest public picture of Sybil farming to date.

{/* Headline stats — infographic */}
{ARB_HEADLINE.map((s, i) => (
{s.v}
{s.label}
{s.sub}
))}
{/* Share bar visualization */}
How the airdrop was split

Nearly half of every ARB address belonged to a same-person cluster, and more than one in five tokens went to a confirmed Sybil — value drained straight out of the pool intended for real users.

{/* Methods */}
How they hid

Four tricks used to dodge detection

{ARB_METHODS.map((m, i) => (
{m.tag}
{m.addrs}
addresses

{m.detail}

))}
{/* Why it matters + CTA */}
go('index.html')} />

Case-study figures: X-explore & WuBlockchain analysis of the Arbitrum airdrop, March 2023. © 2026 Sybilhunt.

go('index.html')}>← Back to home
); } function LegendDot({ color, label }) { return (
{label}
); } function ShareBar() { const ref = React.useRef(null); const [go, setGo] = React.useState(false); React.useEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver((es) => es.forEach((e) => { if (e.isIntersecting) { setGo(true); io.unobserve(el); } }), { threshold: 0.4 }); io.observe(el); return () => io.disconnect(); }, []); const seg = (w, c, delay) => ({ width: go ? w : '0%', background: c, height: '100%', transition: `width 1100ms var(--ease-out) ${delay}ms` }); return (
); } ReactDOM.createRoot(document.getElementById('root')).render();