Search projects, hackathons, sponsors and tech

    ← All projects

    Halo

    Households hedge their own grocery inflation against an index built from receipts they already scan.

    Demo

    About

    Halo turns the receipts people already scan into a grocery-price index, and lets the households who feel inflation first take the other side of it. The gap is this. Inflation hedges exist — inflation-linked bonds, commodity futures, real estate — and every one of them needs a brokerage account, margin, a minimum size, or expertise. None of them reach someone buying rice. And to pay out when groceries get dearer you need a number: the official CPI is monthly, it lags, and in some countries it is politically exposed. For a corner shop in Lagos there is no online price to scrape at all. We did not start this weekend. We built Halo at ETHGlobal Buenos Aires last year as a mini app inside World App, where it was a top-10 finalist. A year later it is three mini apps — World App, MiniPay on Celo, and LINE on Kaia — with 417,000 users and 1,173,623 receipts. That is a real price, at a real shop, on a real date, from the people who actually paid it. What we built this weekend is the market layer. A household pays ¥1,200 and is paid the difference, up to ¥4,000, if rice rises more than 5% over three months. To them it is not a derivative; it is cover on the rice. Behind it: a matched-model index (same product, same shop, two periods — not a category average, which falls in the month you most need cover because shoppers switch to cheaper brands); an optimistic oracle that commits its rules before it sees the data, publishes the full leaf set under bond, and can be disputed; a Uniswap v4 hook that freezes the pool through the challenge window and prices its fee off the clock; and an ENSv2 name that re-reads that oracle and refuses a signed value one basis point off. The part we are proudest of is what it refuses to do. When the corpus is too thin the gateway will not publish a number — it returns the exact integrity floors it missed. A number that cannot say "I don't know" is not a number anyone should settle money against.

    How it's made

    Uniswap v4 — HaloHook, at 0xb8fd9d54093820e43Ca21B223468b78624198Ac4 on Sepolia. The address ends 8Ac4 because the low 14 bits are the permission set it declares; the deploy mines a CREATE2 salt until it lands on one. beforeSwap freezes the pool through the oracle's challenge window — a v4 pool is permissionless, so a hook is the only thing that can stop a race to front-run settlement. The dynamic fee is priced off the clock alone (flat until 7 days out, then linear to 200bp, returned with OVERRIDE_FEE_FLAG) so there is no input an attacker controls. afterSwap takes a 10bp backstop in the unspecified currency as ERC-6909 claims rather than transfers. beforeAddLiquidity and beforeRemoveLiquidity freeze too — leaving removals open would let whoever saw the data withdraw first. Two live pools on Sepolia, identical but for when they close: feeFor returns 500 and 11,642 pips, and the same 100 tUSD swap returns 99,750,349 against 98,639,473. The pools' own sqrtPriceX96 differ in the same direction. ENSv2, on Sepolia. halo is registered to us on the v2 ETHRegistry with HaloResolver attached, and our own UserRegistry subname registry deployed through VerifiableFactory hangs underneath. jp is minted to us; ng is delegated to a partner holding ROLE_SET_RESOLVER and nothing else — we hold zero roles on it and cannot point it back. findResolver offsets make the tree checkable: rice.jp.halo.eth resolves at offset 5, inheriting from jp rather than from halo at 8. The resolver implements ENSIP-10 and EIP-3668, and for a finalised epoch its callback re-reads HaloIndexOracle and reverts GatewayDisagreesWithOracle rather than trusting its own signature. World ID. The index's integrity model is counted in people — one observation per person per item, floors of 3 people per item and 30 per series — and all of that is worth exactly as much as a person is expensive to create. We were keying a person on their wallet address, which is free. A person is now an orb-level World ID nullifier, so two wallets belonging to one verified human collapse into one. Orb only: device attests a phone, not a person. Coverage is partial, so every epoch publishes verifiedPeople beside people. The stack is Hono on Cloudflare Workers, Postgres through Hyperdrive, a React mini app, and Foundry for the contracts. 119 contract tests, 317 API tests. Two bugs worth naming. The publication bond was computed in the wrong unit — every unit test passed because the stub used matching units, and only an integration test caught that a million dollars at risk asked for two millionths of an ether. And the matched-model index did not filter source = 'vision', so synthetic demo rows could have reached a figure that settles money on chain; the fix is in the committed rulesHash, because what data is admitted is the most load-bearing rule there is.