← All posts

Enable ZK: Privacy-Preserving Humanitarian Aid on Aleo

Β·12 min read
Web3Zero-KnowledgeAleoHumanitarian Aid

How HumanityLink distributes humanitarian cash as private on-chain value β€” the architecture, the money flow, and the interfaces people actually use.

Humanitarian assistance has been shifting from in-kind distribution toward direct cash for over a decade. The World Food Programme (WFP) alone went from 3 million cash recipients in 2010 to 9.3 million by 2015, and the trend has continued since. Cash is generally cheaper to deliver than goods, and it lets people buy what they actually need rather than what a procurement cycle guessed at.

Settling that cash on a blockchain isn't new either. A public ledger creates one specific problem that paper vouchers never had.

Donors need an audit trail. Every dollar traceable from the funding wire to the shop counter. This isn't bureaucratic friction β€” it's the condition of being funded at all, and it's a reasonable thing to demand.

Beneficiaries need the opposite. Publish a transaction history for an aid population and you have built a targeting database: who received assistance, how much they hold, which shops they visit, when they're carrying value. For undocumented migrants, refugees, or anyone in a contested area, that's not a privacy inconvenience. It's a safety problem.

These two requirements look contradictory. Zero-knowledge proofs are the reason they aren't.

Access control means data is hidden from people who haven't been granted access. That's an arrangement. It lasts as long as the arrangement does β€” until a policy changes, a database leaks, or a government asks.

Encryption is different. The sensitive fields are ciphertext on-chain. Opening them takes a key, not a permission, and each key opens only what it was issued for. The aggregate counters stay public: total issued, total spent, total off-ramped.

The ledger can be fully open. A donor verifies the totals without ever seeing a beneficiary.

The split

Enable ZK is built on Aleo, a Layer-1 where program state is explicitly either private (encrypted records, readable only by the owner's key) or public (on-chain mappings visible to everyone). The system uses that split deliberately.

Private: beneficiary identity is a pseudonymous address. Balances are encrypted records. Individual payments and peer-to-peer transfers move through transfer_private β€” amounts and counterparties hidden.

Public: that a transaction occurred, and the aggregate counters β€” total issued, total spent, total off-ramped, total transferred peer-to-peer, total merchant purchases.

The practical consequence, from three different vantage points: a merchant processing a payment sees an amount and an approval, never the recipient's identity, balance, or history. The NGO decrypts its own programme data through its view key, for its own programme only. The public β€” donors, auditors, journalists β€” sees aggregate flow, which is exactly what accountability actually requires. Nobody has ever needed to know which refugee bought rice on Tuesday in order to verify that a grant was spent as intended.

The system, end to end

Figure 1: System Architecture

Figure 1 shows the system architecture: four clients, one backend, three service planes.

The clients are the three human-facing surfaces plus a public landing site: an NGO dashboard for programme staff, a merchant point-of-sale app, and WhatsApp β€” which is the beneficiary's entire interface, with voice synthesis for users who can't comfortably read.

All four converge on a single backend, and that concentration is the design. The backend is the only component that touches private keys, generates zero-knowledge proofs, and writes to the chain. No end-user device ever holds a key or proves anything, which is what makes the rest of the user experience possible.

The three dashed groups underneath separate concerns that are easy to conflate. Storage is ordinary infrastructure β€” a Postgres database per network and object storage for photos. On-chain is the privacy layer: the Aleo network itself, plus delegated proving, which is how proof generation gets done without a phone attempting it. Value rails are the chains that carry dollars in and out β€” Ethereum for the on-ramp, Stellar for the cash-out, with MoneyGram at the end of it.

Proof generation is the one place where physics intrudes on the design. An Aleo proof for a payment takes up to about thirty seconds, and that number is why proving is delegated to a service rather than attempted on a mid-range Android handset, and why the point-of-sale app is built around a waiting screen rather than an instant confirmation.

A QR code is the wallet

The privacy model would be worthless if the system demanded that its users understand it.

A beneficiary's wallet is a QR code, delivered over WhatsApp or handed out as a printed sticker. No app install, no seed phrase, no crypto knowledge, no smartphone required for the sticker path.

Everything a beneficiary does happens in a chat thread. The returning-user card packs the essentials into a single bubble β€” their platform ID, which network they're on, their balance with the local-currency equivalent, and a link to their QR. A menu offers the five things they might want: show my QR, check my balance, my details, transfers, report a problem. Commands work as plain text too, in English or Spanish, accent- and case-insensitive, because a list-picker menu is not universally available and a fallback that always works matters more than a polished one that sometimes doesn't.

The merchant side is a point-of-sale app.

Figure 2: Screenshots Mobile App for Merchants

Figure 2 shows screenshots of the mobile app the merchants are using. Scanning a beneficiary's QR opens a purpose chooser, and its three options map one-to-one onto on-chain transitions. Buy Goods is an ordinary purchase. Off-Ramp to Cash is the beneficiary converting aid to physical currency at the counter. Buy from Beneficiary is the interesting one β€” the merchant purchasing produce, crafts, or services from the beneficiary, paid out of the merchant's own balance. That flow exists so aid money keeps circulating in the local economy instead of draining straight out of it on first use.

The NGO's dashboard is the third surface: register beneficiaries, issue aid singly or in bulk, whitelist merchants, pause the programme, watch the flows, export reports.

The design principle underneath all of it: simple for users, controlled behind the scenes. Every piece of cryptographic and blockchain complexity is absorbed by the backend. Every programmatic control β€” merchant whitelisting, issuance authority, the pause switch, off-ramp limits β€” is enforced on-chain, where the rules hold independently of any backend behaviour.

The aid is real money

One design decision shapes everything downstream: there is no aid-specific token. Aid is denominated in USDCx, a USDC-backed stablecoin on Aleo, held as ordinary private token records.

This is the difference between digital cash and a digital voucher. A voucher is a restriction wearing the costume of money β€” spendable only where and on what the issuer permits, worthless outside the programme. Real stablecoin value can be spent at any approved merchant, transferred to another beneficiary, and converted to physical cash. That last property is what makes the whole thing an aid instrument rather than a closed-loop store credit.

The life of one aid dollar

Figure 3: Money Flow

Figure 3 illustrates the full money flow: six steps, five actors, and two distinct ways value turns into cash.

The NGO issues aid to a beneficiary β€” a private USDCx record, drawn from the programme's pool. From there the money can move sideways before it exits: beneficiary to beneficiary, straight from WhatsApp, which matters because households share, lend, and settle debts among themselves whether or not a system anticipates it. It can be spent at a merchant's point of sale. Or the merchant can run it the other way and buy goods from the beneficiary, paying from their own balance.

Steps one through four all settle privately on Aleo. Only the aggregate counters move in public.

The last two steps are the two cash-out paths, and they're genuinely different. A beneficiary converts at a merchant β€” the merchant hands over local currency across the counter and takes the USDCx. A merchant converts through the off-ramp pipeline, ending at a MoneyGram cash pickup. One is a local, human transaction; the other is a four-network settlement.

Everything that moves value is idempotent by construction. Bulk issuance carries a request ID recorded on-chain in a nullifier mapping, so a re-broadcast batch cannot mint twice regardless of what any backend believes; the vault on the Ethereum side keys each inbound transfer the same way. The chain is the source of truth throughout β€” the merchant whitelist check on every payment re-reads it directly rather than trusting a cached copy.

Getting money in

HumanityLink funds the programme: fiat becomes USDC at an exchange, lands in an Ethereum vault contract deployed per NGO, and is bridged to Aleo through Circle's xReserve. End to end it takes roughly three to four minutes β€” about twenty-five seconds for Ethereum confirmation, then a couple of minutes for the relayer to mint USDCx on the far side.

The vault is deliberately minimal, roughly 240 lines of Solidity. It holds no reserve and has no deposit flow: every dollar that arrives is bridged in full on the next orchestrator pass, so the contract holds funds only briefly in transit and has almost no state to attack. The destination Aleo address is fixed at construction and cannot be changed, which bounds what a compromised operator key can do β€” it can trigger a bridge, never redirect one. Minting on the Aleo side is handled by the bridge relayer via data baked into the vault at deployment, so there is no off-chain mint endpoint in the system at all.

Getting money out

Figure 4: Cash out at MoneyGram

Figure 4 shows the cash out process: turning a merchant's balance into physical cash takes three chains, and each hop solves exactly one problem.

Aleo provides the privacy β€” but has no fiat rails. Ethereum is where Circle's xReserve redeems USDCx back into canonical USDC. Stellar is the chain MoneyGram's cash-pickup anchor operates on, reached through Circle's cross-chain transfer protocol.

The merchant's Aleo balance is burned, attested across to Ethereum and onward to Stellar, and a MoneyGram withdrawal is opened; the merchant completes identity verification through a link delivered over WhatsApp and receives a reference number they can take to any MoneyGram counter. Realistically the whole pipeline takes half an hour, most of it waiting on cross-chain attestation.

The dashed return line in the diagram is the part worth noticing. The on-chain ledger entry that clears a merchant's pending balance runs after the cash payout succeeds, not before. If anything fails partway, the chain still records the merchant as owed, and the next night's run picks them up. Each merchant has their own dedicated bridge keys across all three chains, so nothing pools and nothing is shared.

Every hop is Circle-attested burn-and-mint β€” no wrapped assets, no liquidity pools β€” which reduces bridge risk to Circle's attestation service rather than to somebody's multisig.

Who is allowed to issue

Aid enters circulation through issuance, so issuance is the control point that matters most.

Two Leo programs are deployed per NGO: a core aid contract and a bulk-issuance companion that exists because of a hard platform limit β€” a Leo function caps at sixteen outputs, so the core contract can serve at most four recipients per call, while the companion batches up to fifteen.

Authorisation runs in two layers. The aid program trusts exactly one minter: the bulk program. The bulk program in turn trusts an explicit, named set of caller keys. Both checks run in the on-chain finalize step before any child mint executes, so trust points in exactly one direction and every batch has a verified origin.

Each NGO deploys its own instance of both programs, and the admin authority is set at deployment to whoever deployed it β€” which is what lets one codebase serve many organisations with no per-tenant changes. The programs are permanently non-upgradeable by assertion. Any change means a fresh deployment, and the admin-transfer function refuses both the burn address and the current admin as targets, so the authority cannot be stranded.

Private balances are UTXOs

One last piece of the model is worth explaining, because it surprises people arriving from account-based chains.

On Aleo, a private balance is not an account whose number goes up and down. It's a set of discrete encrypted records β€” structurally Bitcoin's UTXO model with the contents hidden. A transfer consumes whole input records and produces new ones: one for the recipient, one in change back to the sender. Nothing is edited in place, and a spent record is marked by a nullifier, which is what prevents double-spending without revealing which record moved.

Two consequences follow. Records accumulate β€” every issuance received, every payment accepted, every change output adds one, so an active merchant's wallet grows indefinitely and takes longer to scan each time. And a wallet can hold ten dollars while being unable to pay five, if the balance sits in twenty fifty-cent records and no single admissible input covers the amount.

The answer is a background consolidation service that sweeps every wallet on a fixed interval and merges fragmented records down toward a target count. Because it runs continuously, the merge almost never has to happen inline during a payment β€” which is what keeps a purchase at a single proof and roughly thirty seconds, rather than two proofs and a minute.

Where it is

Enable ZK is running in pilots with two NGOs in Colombia. Aid flows end to end: fiat in through a per-NGO vault contract, private issuance on Aleo, spending at whitelisted merchants, peer-to-peer circulation between beneficiaries, and merchant cash-out through MoneyGram.

The broader point is that the privacy-versus-auditability tension in humanitarian cash is not a philosophical trade-off to be argued about. It's an engineering problem with a solution that exists today: encrypt what identifies a person, publish what proves the money moved, and let both properties hold at once.


Project info: blockstatsolutions.com/projects/humanitylink Project landing page: enable-zk.humanity.link/en

If you work in humanitarian cash and voucher assistance, or you build privacy infrastructure and want to compare notes β€” I'd like to hear from you.