Decentralized storage platform with ZK proofs verified on Arbitrum



Cloudy is a decentralized storage platform that settles on Arbitrum with zk proofs verified on-chain
Cloudy is a storage platform that connects people who need data kept safe with people who have spare disk space to rent out. The data itself lives with an open network of providers, while the agreement between them (price, payments, proofs, penalties) lives in smart contracts on Arbitrum. Users don't have to trust a provider: on-chain challenges and the compensation and incentive systems do that job.
How it works
Upload. The data owner encrypts a file on their own device, splits it into redundant shards and places a storage order on Arbitrum, priced in USDG.
Match. Orders and provider offers meet in an on-chain order book. Each matching provider takes one shard, checks it against the order, and locks USDG collateral to accept the contract.
Prove. Arbitrum regularly challenges providers on random pieces of the data. Each answers with one zk proof (an SP1 STARK over a keccak Merkle tree, wrapped in Groth16), generated in about a minute and verified on-chain at a fixed cost, whatever the file size.
Retrieve. The owner downloads from several providers at once, for free.
Enforce. A provider that won't deliver can be challenged on-chain to publish the data. A provider that fails to prove or serve the data loses collateral to the data owner.
Incentive. Providers that deliver data fast earn a larger share of each payment, which keeps downloads fast and makes withholding data unprofitable.
Resilience. Thanks to Reed-Solomon erasure coding, any one third of the providers can rebuild the whole file, so data survives even if two thirds of them lose their data.
Who uses it
Data owners: individuals, businesses, apps, RWA issuers and AI agents that need files stored with guarantees. They use the web app in a browser, or Cloudy Node.
Providers: anyone with spare disk space and a GPU, who earns USDG for hosting. They use Cloudy Node.
Other smart contracts: any contract on Arbitrum can read whether a file is stored validly and act on it. For example, a sample RWA token only mints while its documents are safely stored.
Components
Component | Role | Who uses it |
|---|---|---|
Cloudy contracts | Run the order book, payments, proof checks, incentives and penalties on Arbitrum, and publish storage status | Cloudy Node, the web app and other smart contracts |
Cloudy Node | Rents and hosts storage, and generates the zk proofs for providers | Data owners, providers |
Web app | Rents storage straight from the browser, with nothing to install | Data owners |
Relay network | Helps browsers and nodes reach providers behind routers, and forwards encrypted traffic only when a direct connection fails | Cloudy Node and the web app, in the background |
Sample RWA contract | Mints tokens only while their documents are stored validly | RWA issuers (example) |
Link | |
|---|---|
Website and web app | |
Cloudy Node, Windows | |
Cloudy Node, Ubuntu 24.04 | |
GitHub |
Contract | Address on Arbitrum Sepolia | Note |
|---|---|---|
CloudyMarket | https://sepolia.arbiscan.io/address/0x62e4826b9a1631e60e72f133d8254287225d0bf5 | |
CloudyMarket, proofs part | https://sepolia.arbiscan.io/address/0xa0ada0fd16d87e922c182211365f3b544088756f | |
CloudyMarket, retrieval part | https://sepolia.arbiscan.io/address/0x72170c942979356a8a433e010487228e09e699f9 | |
RwaToken (sample) | https://sepolia.arbiscan.io/address/0x416269255368833beda91d5bef87c15fa47cd699 | |
USDG (testnet) | https://sepolia.arbiscan.io/address/0xFFC95faa3d63Cde504a05B567C600B78C0b41892 | Used by Cloudy; issued by Paxos |
SP1 Groth16 verifier v6.1.0 | https://sepolia.arbiscan.io/address/0xb69f2584CBcFf99a58C4e7002E8b89Af54a6f4e2 | Used by Cloudy; official deployment by Succinct |
First storage platform verified on Arbitrum. Storage proofs, payments and penalties all settle on Arbitrum, so apps can rely on off-chain data the way they rely on on-chain state. Any contract can check a file's storage status in its own transaction, and users pay in USDG on the chain they already use, with no bridge, no second chain and no extra token.
Fast, cheap zk storage proofs. Each check is answered by one compact zk proof (an SP1 STARK wrapped in Groth16), made in about a minute on a single GPU and verified on-chain at a small fixed cost, however large the data. Frequent checks stay cheap, which keeps storage affordable and lets anyone with a GPU become a provider.
Others: Merkle-proof systems such as Filecoin PDP pay on-chain gas for every sampled piece, and zk designs built on Poseidon2 hashing, such as Codex, make the data owner hash for days (about 76 h for 1 TB, versus under 2 h with Cloudy's keccak).
Compensation system for data owners. A provider that fails to keep or serve the data loses USDG collateral to the data owner, enforced by the contract. Owners are assured of compensation, and providers have real money at stake to keep data safe.
Fast retrieval, enforced on-chain. Providers that deliver fastest earn more, and a provider that withholds data can be forced to publish it on-chain. Owners get their data back quickly whenever they need it, for free, and no provider can hold it hostage.
Others: only about 13% of Filecoin retrievals succeeded in a 2024 measurement, and Storj, Sia and Shelby charge for every read.
Survives provider loss. Reed-Solomon erasure coding lets any one third of the providers rebuild the file, so data stays recoverable even if most providers disappear or lose it, for no more than 3× storage.
At a glance
Cloudy | Existing systems | |
|---|---|---|
Where proofs are verified | On Arbitrum, by SP1's official audited verifier | None of 17 surveyed networks verifies or slashes on Arbitrum |
Who receives the penalty | The data owner, in the same transaction | None of 12 systems checked pays the owner. Filecoin PDP: the provider only loses that period's payment |
Catching a provider that dropped 1% of the data | 14.9% per check; about 80% over 30 days (10 checks) | Filecoin PDP: 4.9% per day; 77.9% over 30 days (30 daily checks) |
On-chain cost of a proof | One 356-byte proof, about 247k gas in the verifier, whatever the sample count or data size | Plain Merkle proofs (PDP-style): about 26k gas per sample |
Hash the user's machine must compute | keccak: a 1 TB file's tree in the browser in about 16 min to 1.8 h | Poseidon2-based designs (e.g. Codex): about 76 h for the same tree |
Trusted setup | SP1's shared setup, 18 contributors including Offchain Labs | EthStorage ran its own ceremony with 287 participants |
Reads | Free for the owner; fastest third paid double; withholding challengeable on-chain | Filecoin: ~13% retrieval success (2024); Walrus best-effort; Storj, Sia, Shelby charge per read |
What it is for: the full life of a storage contract, from upload to proofs, payouts and penalties.
How it works:

What it is for: lets data owners and providers agree on a price on-chain, and turns each agreement into a storage contract only once the provider has the right data.
How it works:

Providers post offers on-chain: a minimum price in USDG per TB per month, free capacity, a maximum duration and a price tolerance, with auto-match on or off.
The data owner sets a price, or picks Market price, which fills in a price enough current offers accept, plus a chosen slippage.
The order goes on-chain with each shard's hash (its keccak Merkle root), and the owner's USDG is locked in escrow.
The owner's software sends all shards at once, one to each of the best-priced matching providers: cheapest offer first, earliest offer on a tie.
Each provider checks its shard against the on-chain hash and, if it matches, locks USDG collateral together with a first proof. That slot is now a running contract.
A slot that is not matched before its deadline goes to the next provider in line. The owner can cancel unmatched slots at any time and get that money back in full.
The order book panel shows offers, waiting orders, the market price (the volume-weighted price of the last 24 hours of matches) and a chart of matched prices.
What it is for: one app, desktop or command line, on Windows or Ubuntu, for both renting storage and hosting it.
How it works (becoming a provider):
Install Cloudy Node, create or import a wallet with one password, and confirm 3 of the 12 recovery words.
Choose a storage folder and its capacity, and turn Hosting on.
Post an offer. With Auto-match on, the node takes matching orders by itself.
From then on the node works in the background: it receives shards, checks their hashes, matches slots, proves every check, answers download requests and challenges, and withdraws its collateral when a contract ends.
The Host screen shows the storage used, contract history, earnings and alerts, next to the order book.
As a renter, the node does what the web app does, with faster uploads and downloads. Under the hood, the Linux prover runs inside WSL2 on Windows. The node keeps only the upper levels of each shard's Merkle tree, so shards of hundreds of GB fit in memory. It hashes on 8 threads (a 1 GiB shard drops from 16.5 s to 2.2 s) and saves the tree next to the shard, so restarts and proofs never re-hash the whole shard. Several providers on one machine share one GPU through a queue.
What it is for: challenges every provider, at every check, to prove with a zk proof that it still holds the exact bytes it was paid to keep.
How it works:

Each order has its own schedule: a check every tenth of its duration (between 5 minutes and 3 days), with a submission window of 1/72 of that (between 4.5 minutes and 1 hour). A 1-hour testnet order is checked every 5 minutes.
When a challenge opens, the Arbitrum block hash is recorded as its seed, so nobody can know the questions in advance.
The seed picks the challenge: 16 random 32-byte pieces from the provider's dataset, which is all the contracts it holds for that owner on that schedule.
Inside the SP1 zkVM, the provider's node proves that those exact bytes hash up to the shard hashes recorded at order time, then wraps the proof in Groth16. The result is 356 bytes and takes about a minute on one GPU.
The provider answers the challenge by submitting the proof within the window. SP1's verifier on Arbitrum checks it, and the payment for every contract in the dataset is released.
No valid proof within the window counts as a miss (see 5.7).
One proof covers the whole dataset, so the on-chain cost does not grow with the number of files.
What it is for: forces a provider that holds data but won't serve it to hand it over, on-chain.
How it works:

During a download, the owner's software asks the provider for a piece off-chain, up to 3 times, 30 seconds apart.
If no correct answer comes back, it opens a challenge on Arbitrum for that piece (up to 4 KB). The owner's gas is refunded in USDG in the same transaction, at the provider's expense.
The provider must publish the exact bytes with a Merkle proof on-chain before the deadline: a third of the order's check interval, between 3 minutes and 24 hours. The owner then reads them from the chain.
No correct answer in time counts as a miss (see 5.7).
A cooldown between two challenges to the same provider keeps the cost it can be forced to bear bounded.
What it is for: pays providers for storing data and rewards them for serving it fast.
How it works:
When the order is placed, the owner's USDG for every slot is locked in escrow.
Each time a provider passes a check, that check's payment is split: 75% goes to the provider at once and 25% goes into a reward pool for that check.
After each download, the owner's software signs a receipt (EIP-712, no gas) that gives speed points to the providers that delivered first.
Providers submit their latest receipt together with their next proof.
Once the check is settled, the pool is split equally among the third of the order's providers with the most points. Each of them earns double what a provider that never delivers earns.
What it is for: makes a failing provider pay the data owner.
How it works:

A miss is a failed storage challenge (a missing or wrong proof) or an unanswered retrieval challenge.
Once the window has closed, anyone can report a miss. The web app's Claim compensation button does it for the owner.
A first miss within the last 10 checks sends 30% of the provider's collateral, plus that check's payment, to the owner. Until the provider passes its next check, the file shows as not stored validly.
A second miss within 10 checks sends all the remaining collateral and all unpaid escrow to the owner, and the provider's contract ends.
When a contract ends, the provider can only withdraw its collateral once every check is settled, so its own node first reports any miss nobody reported. The owner is paid even if they never claim.
Nothing is burned and nothing goes to a protocol treasury.
What it is for: fast, free downloads for the data owner.
How it works:
The owner's software reads the providers of the order from the contract itself, with no network lookup.
It requests shards from all of them at once, each request carrying the hash of a random piece to check.
A provider whose answer does not match is dropped and can be challenged on-chain (see 5.5).
As soon as one third of the shards have arrived, the file is rebuilt and decrypted, and the other requests are cancelled. When the original shards arrive first, no decoding is needed.
The owner pays nothing per read and has no limits.
What it is for: lets an owner share a file with anyone, for free.
How it works:
The owner marks the file public, which publishes its decryption key on-chain.
Anyone with the file's public link, in the web app or with Cloudy Node, downloads it the same parallel way, for free.
The data stays encrypted at the providers. Public reads earn no speed points, because anyone can create new readers at no cost.
What it is for: keeps file contents private from providers and relays, and keeps files recoverable.
How it works:
Each file gets a random key and is encrypted on the user's device, in 1 MiB chunks with AES-256-GCM and a key commitment. The list of files is encrypted too.
The encrypted file is split with systematic Reed-Solomon coding over GF(2^16) into 3 to 24 shards (a multiple of 3), any one third of which rebuild it. The total stored size is always 3× the file.
Each shard's keccak Merkle root is recorded as its hash in the order.
The file key is wrapped for its owner with post-quantum hybrid encryption (HPKE X-Wing). The owner's root key comes from the Cloudy Node wallet, or from a separate 12-word phrase for MetaMask users of the web app.
On a new machine, one password and the 12 words restore the wallet and every file.
The same Rust code runs in the node and, compiled to WebAssembly, in the browser, where a 64 MiB file is prepared in about 1.3 s across several threads.
What it is for: lets anyone host from home, behind a router, with no public IP and no open ports.
How it works:

Nodes connect over iroh (QUIC with NAT traversal) through an always-on relay. Browsers talk to provider nodes directly over WebRTC data channels, using a relay only for signaling and, when needed, STUN/TURN, and they authenticate each provider by the node key it published in its on-chain offer. Relays are interchangeable: nodes and the web app load the relay list at runtime, a new relay is set up with one command on any Ubuntu or Debian host with a domain name, and relays only ever see encrypted traffic.
What it is for: lets any Arbitrum contract base its own decisions on whether a file is safely stored.
How it works:
Any contract calls storageStatus(orderId) in its own transaction. It returns whether the file is stored validly (the contract is active, and every provider holding a shard still has collateral locked and passed its latest check), how many shards are valid versus how many are needed, when storage ends, and how much collateral is at risk.
The sample RWA token links each token to documents stored on Cloudy, such as a prospectus, an audit report or a custody attestation, and to a minimum remaining storage time.
On every mint, it checks each linked document inside the same transaction.
If a document is not stored validly or expires too soon, the mint reverts and names that document. Once the document is stored validly again, minting works.
Layer | Technology |
|---|---|
Chain | Arbitrum (live on Arbitrum Sepolia) |
Smart contracts | Rust on Arbitrum Stylus (main implementation); Solidity twin with the same ABI (Foundry). The market contract is split into three parts behind one address to stay within the contract size limit. |
Proof verification | SP1 Groth16 verifier v6.1.0, the official deployment on Arbitrum (audited by Veridise), called directly |
Storage proofs | SP1 zkVM 6.8.1: a STARK over a keccak Merkle tree, wrapped in Groth16 on BN254. GPU proving with CUDA. |
Hashing | keccak256 everywhere: Merkle trees, sampling, integrity checks, content addresses (CID with a keccak-256 multihash) |
Payments | USDG (Paxos) with EIP-2612 permit and EIP-3009; gas in ETH, paid by each sender, with no relayer or paymaster |
Speed receipts | EIP-712 signatures |
Encryption | AES-256-GCM streaming with key commitment; HPKE X-Wing (ML-KEM-768 + X25519) for key sharing; BIP-39/BIP-44 wallets |
Erasure coding | Systematic Reed-Solomon over GF(2^16) (reed-solomon-simd), n = 3k |
Networking | iroh 1.x (QUIC, relay, NAT traversal); WebRTC (webrtc-rs in the node, the browser's own WebRTC); coturn for STUN/TURN; Cloudy's own signaling service |
Cloudy Node | Rust core shared by both roles and both editions (CLI and desktop); Tauri 2 desktop app for Windows and Ubuntu 24.04; SQLite; prover in WSL2 on Windows |
Web app | SvelteKit 2 + Svelte 5 + TypeScript; viem; Rust SDK compiled to WebAssembly in web workers (multi-threaded, COOP/COEP); hosted on Cloudflare Pages |
Testing | Rust unit and integration tests, Foundry tests with Rust-generated differential vectors, Playwright UI tests, end-to-end scenarios on a Nitro devnode, a real desktop-app flow through tauri-driver, and live runs on Arbitrum Sepolia |
An archive for Arbitrum's batch blobs, which Ethereum prunes after about 18 days, served through the same API as an Ethereum beacon node so Arbitrum nodes can use it as a fallback source.
An RWA contract that is itself the data owner, so compensation flows into the token's treasury.
Relays built into Cloudy Node, so providers with a public address can relay for others.
Access from AI assistants.
A manipulation-resistant randomness source in place of the block hash.
Built from scratch in hackathon timeframe
No fund raised at the moment