CeloCelo โ† App
โ† Back to App

How Zorrito Works

A no-loss lottery on Celo โ€” your principal is always safe.

๐Ÿ’ก The idea is simple: everyone deposits USDT, the pooled funds earn yield on Aave, and every January 1st that yield goes to one random winner. No one ever loses their deposit โ€” ever.

How it works

1
Deposit USDT

Deposit any amount โ‰ฅ 1 USDT. Every 1 USDT = 1 lottery ticket. More USDT = higher chance of winning.

2
Funds go to Aave V3

Your USDT is immediately supplied to Aave V3 on Celo. It starts earning the current USDT supply APY โ€” see the live rate above.

3
Annual draw โ€” every January 1st

Every January 1st the draw triggers automatically via a keeper bot. Only foxes fed in the last 24 hours are eligible. A winner is chosen proportionally to their effective tickets (fish ร— streak multiplier). The entire accumulated yield goes to that winner โ€” instantly, on-chain. You don't have to do anything.

4
Prize lands in your wallet

Winnings are sent directly by Aave to the winner's wallet. No claim needed. The contract never holds the prize.

5
Withdraw any time

Your principal is never at risk. Withdraw all or part of your deposit whenever you want, with no penalty or lock-up.

๐ŸฆŠ Feed Your Fox

๐ŸŽฎ Zorrito is a game. You don't just deposit and wait โ€” you have a fox that needs care every day to stay in the monthly lottery.

๐ŸŸ
1 USDT = 1 Fish = 1 Ticket

Each fish is one lottery ticket. More fish = higher chance of winning. All your USDT (fish) stays deposited in Aave V3 earning yield โ€” that yield becomes the monthly prize.

๐ŸฆŠ
Feed your fox 1 USDT every day

Once you adopt a fox, you must feed it 1 USDT per day. Each feed deposits 1 more USDT into the pool, giving you +1 fish and +1 ticket. Each consecutive day you feed builds your ๐Ÿ”ฅ streak. The more days you feed, the more fish you accumulate and the better your odds.

๐Ÿ’€
Miss a day โ†’ fox dies

If you don't feed within 24 hours, your fox dies and is excluded from the monthly draw. Your USDT is never at risk โ€” all your accumulated fish stay safe in Aave, earning yield. You just won't be in the draw until you revive.

โœจ
Revive with 1 USDT

Feed 1 USDT to revive your dead fox instantly. Your streak resets to 1 but all your previously accumulated fish (USDT in Aave) remain.

๐Ÿ†
Streak leaderboard

The home page shows the top 10 longest current streaks. The player with the longest unbroken streak is the most committed fox keeper. Future versions may reward long streaks with bonus tickets.

โš ๏ธ Important: Your USDT deposit is always safe in Aave. Fox death only affects lottery participation โ€” it never affects your capital.

๐Ÿ”ฅ Streak Multiplier

๐Ÿ’ก Imagine two players who both deposit 100 USDT. Player A deposits once and never feeds again โ€” 0-day streak, 1ร— multiplier = 100 effective tickets. Player B feeds every single day for a year โ€” 365-day streak, 5ร— multiplier = 500 effective tickets. Same deposit, but Player B is 5ร— more likely to win.

Your win probability = your effective tickets รท total effective tickets in the pool. Feeding daily is the most powerful lever you have โ€” it costs 1 USDT/day and your capital stays safe in Aave the whole time.

Streak tiers
Consecutive days Multiplier Example (100 fish)
0 โ€“ 6 days 1.0ร— 100 effective tickets
7 โ€“ 29 days 1.5ร— 150 effective tickets
30 โ€“ 89 days 2.0ร— 200 effective tickets
90 โ€“ 179 days 3.0ร— 300 effective tickets
180 โ€“ 364 days 4.0ร— 400 effective tickets
365+ days ๐Ÿ† 5.0ร— 500 effective tickets

๐Ÿ›ก๏ธ Security unchanged. Streak multipliers are deterministic and publicly readable on-chain โ€” any observer can verify them at any time. They don't affect how the random winner is selected, only how many tickets each player earns. An attacker cannot manipulate their multiplier to bias the entropy accumulator โ€” streaks are earned through real time and can't be faked.

Prize Size

The annual prize equals the yield accumulated by the entire pool over 365 days โ€” drawn every January 1st. It grows with the total pool size:

Aave USDT Current Aave V3 USDT Supply APY on Celo fetching...
Pool Size Est. Annual Prize ๐ŸŽ Equivalent to...
Loading live rates...

Based on live Aave V3 APY (annual) ยท refreshes every 5 minutes.

๐Ÿ“ˆ Growth Calculator

How many people depositing daily would it take to reach a target pool size?

$50,000,000
$10K$100K$1M$10M$50M$100M$500M$1B
1 USDT/day
1 USDT255075100 USDT
Depositing 1 USDT/day for 365 days โ†’ 365 USDT per person per year
People needed
137K
Annual prize at that pool
โ€”

Winning Chances

The winner is selected on-chain using a weighted pseudo-random algorithm. Your probability of winning equals your share of the total pool:

P(win) = your USDT deposit รท total pool USDT

Example: you deposit 100 USDT, total pool is 500 USDT โ†’ you have a 20% chance of winning each monthly draw.

๐ŸŽฒ How Randomness Works

Picking a winner on-chain is hard โ€” the blockchain is deterministic and public, so any single value known at draw time can potentially be manipulated by whoever proposes that block. Zorrito solves this with a RANDAO-style entropy accumulator, the same principle used by Ethereum's own consensus layer.

๐Ÿ” Phase 1 โ€” Accumulation (days 1โ€“30)

Every time any user calls deposit(), feed(), or withdraw(), the contract mixes the current Celo random beacon + the caller's address + the block timestamp into a rolling _roundEntropy value stored on-chain:

_roundEntropy = keccak256(
  _roundEntropy,    // previous accumulated value
  CELO_RANDOM.random(), // Celo beacon at this moment
  block.timestamp,
  msg.sender,      // who is transacting right now
  totalDeposited
)
๐ŸŽฏ Phase 2 โ€” Draw (day 30)

At draw time, the final seed combines everything:

finalSeed = keccak256(
  _roundEntropy,    // 365 days of mixed entropy
  CELO_RANDOM.random(), // current beacon
  block.timestamp,
  block.number,
  aliveTotal
)

๐Ÿ›ก๏ธ Why this is hard to manipulate: To bias the outcome, an attacker would need to control the Celo random beacon at every single deposit, feed, and withdrawal made by all users over the entire 30-day round. That includes random strangers feeding their foxes at unpredictable times. Even a validator with significant network power would need to corrupt dozens of independent transactions โ€” a practically impossible coordination attack.

Comparison: randomness approaches
Approach Validator influence Attack cost
blockhash only High โ€” full control 1 block proposal
Celo beacon only Low โ€” skip 1 turn 1 bit of influence
Zorrito accumulator โœ“ Negligible Control every tx, 365 days
External VRF oracle Zero Not yet on Celo

Smart Contracts

CeloZorrito v7 (Celo Mainnet) 0x6D60adC489Fbe91350B42BC00391e644fe8c5209 โ†—
USDTUSDT on Celo (LayerZero) 0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e โ†—
AaveAave V3 Pool (Celo) 0x3E59A31363E2ad014dcbc521c4a0d5757d9f3402 โ†—

Security Notes

Low RANDAO-style entropy accumulator + EIP-4399 prevrandao

Zorrito uses a two-layer randomness approach. Throughout the 365-day round, every deposit(), feed(), and withdraw() mixes the current block's prevrandao value (EIP-4399, plus the caller address and timestamp) into a rolling accumulator stored in the contract. At draw time the winner is selected using a final hash of: accumulated entropy + prevrandao + block number + block timestamp.

To bias the outcome an attacker would need to control the L1 proposer at every single user interaction over 365 days โ€” including random strangers feeding their foxes. This is a nation-state level attack, not a realistic threat. block.prevrandao is the standard EIP-4399 randomness source on Celo L2 (OP Stack), replacing the legacy L1 precompile that was removed during the Celo โ†’ L2 migration.

Low No admin keys

The contract has no owner, no pause function, and no upgrade mechanism. Once deployed, no one can change it โ€” including the team.

Low Aave dependency

Funds are deposited directly into Aave V3 on Celo. Risk is equivalent to the Aave protocol risk. Aave V3 has been audited and has over $10B in TVL across all chains.

Info MVP โ€” use with caution

Zorrito is an experimental MVP. Do not deposit funds you cannot afford to lose. A formal third-party audit is recommended before scaling up.

๐Ÿค– AI Agent Integration ยท x402

๐Ÿฆพ Zorrito supports the x402 payment protocol. AI agents can autonomously deposit USDT, feed their fox daily, and compete in the monthly lottery โ€” all via standard HTTP requests, no wallet UI needed.

What is x402?

x402 revives the HTTP 402 Payment Required status code as a machine-readable payment protocol for AI agents. Instead of a browser wallet popup, an agent receives a 402 response containing structured payment instructions, executes an on-chain transfer automatically, and re-calls the endpoint with a payment proof header. The server verifies the transaction and performs the action. No human approval needed at any step.

Payment Flow

1
Agent calls the endpoint

No headers needed. The server responds with HTTP 402 and a X-Payment-Required header describing exactly how much USDT to send, to which address, on which network.

2
Agent sends USDT on Celo

Transfer the required USDT amount to the facilitator address shown in the 402 response. This is a standard ERC-20 transfer โ€” no special contract interaction needed.

3
Agent re-calls with payment proof

Include X-Payment: base64(JSON.stringify({txHash: "0x..."})) in the request headers. The server verifies the transaction on-chain.

4
Server executes the action

The facilitator calls depositFor(agentAddress, amount) or feedFor(agentAddress) on the Zorrito contract. The agent's wallet address is registered in the lottery with their own on-chain identity.

5
Agent receives 200 with Celo tx hash

The response includes the Zorrito transaction hash, the agent's current fish count, and instructions for the next action (feed daily to maintain eligibility).

Endpoints

GET /api/agent?action=status&address=0x... free ยท no payment

Returns fox status, fish count, streak, seconds until dead, and pool stats for any address. Use this before acting to decide whether to deposit or feed.

POST /api/agent?action=deposit&beneficiary=0x...&amount=10

Deposits N USDT into the lottery pool for beneficiary. Returns 402 with payment instructions if no X-Payment header is present. Minimum 1 USDT.

POST /api/agent?action=feed&beneficiary=0x...

Feeds the fox for beneficiary (costs 1 USDT, adds 1 fish, increments streak). Must be called every 24h to stay alive. Returns 402 if no payment header.

Code Examples

JavaScript / TypeScript (ethers.js)
// Agent wallet โ€” must hold CELO (gas) and USDT on Celo
const wallet = new ethers.Wallet(AGENT_PRIVATE_KEY, provider);
const usdt = new ethers.Contract(USDT_ADDRESS, ERC20_ABI, wallet);

const BASE_URL = "https://zorrito-gamma.vercel.app";
const BENEFICIARY = wallet.address;

// Step 1 โ€” probe for payment instructions
const probe = await fetch(
  `${BASE_URL}/api/agent?action=deposit&beneficiary=${BENEFICIARY}&amount=10`,
  { method: "POST" }
);
const { payTo, asset, amountRequired } = await probe.json();

// Step 2 โ€” send USDT to facilitator
const tx = await usdt.transfer(payTo, "10000000"); // 10 USDT
await tx.wait();

// Step 3 โ€” re-call with payment proof
const proof = btoa(JSON.stringify({ txHash: tx.hash }));
const res = await fetch(
  `${BASE_URL}/api/agent?action=deposit&beneficiary=${BENEFICIARY}&amount=10`,
  { method: "POST", headers: { "X-Payment": proof } }
);
const result = await res.json();
console.log("Zorrito tx:", result.zorritoTx);
Python
# pip install web3 requests
import requests, base64, json
from web3 import Web3

w3 = Web3(Web3.HTTPProvider("https://forno.celo.org"))
account = w3.eth.account.from_key(AGENT_PRIVATE_KEY)
BASE_URL = "https://zorrito-gamma.vercel.app"
BENEFICIARY = account.address

# Step 1 โ€” probe for payment instructions
probe = requests.post(
  f"{BASE_URL}/api/agent",
  params={"action": "deposit", "beneficiary": BENEFICIARY, "amount": "10"}
)
data = probe.json()
pay_to = data["payTo"]

# Step 2 โ€” send USDT on Celo
tx_hash = send_usdt(w3, account, pay_to, 10_000_000) # 10 USDT

# Step 3 โ€” re-call with payment proof
proof = base64.b64encode(json.dumps({"txHash": tx_hash}).encode()).decode()
res = requests.post(
  f"{BASE_URL}/api/agent",
  params={"action": "deposit", "beneficiary": BENEFICIARY, "amount": "10"},
  headers={"X-Payment": proof}
)
print(res.json()["zorritoTx"])

โš ๏ธ Agent requirements: The agent wallet must hold CELO for gas (~$0.001/tx) and USDT on Celo for deposits/feeds. Bridge USDT via Uniswap or cBridge. To maintain lottery eligibility, the agent must call the feed endpoint once per day.

FAQ

Can I lose my deposit?

No. Your principal is always withdrawable. Only the yield (the extra amount earned by Aave) is given to the winner โ€” your original deposit stays intact.

When does the draw happen?

Automatically, every January 1st. A keeper bot runs via GitHub Actions and triggers the draw on-chain as soon as the year is up and yield has accumulated โ€” no human intervention needed. You don't have to do anything.

How do I receive my prize?

Winnings are sent directly to your wallet by Aave at draw time. No claiming needed โ€” the USDT just appears in your wallet.

Why is the prize so small right now?

The prize = 365 days of yield from the entire pool. With a small pool the prize is still growing. As more people deposit throughout the year, the annual prize grows. Invite friends to deposit and the prize gets bigger for everyone!

What network is this on?

Celo mainnet. Gas fees are paid in CELO and are very cheap (<$0.001 per transaction). You'll need a small amount of CELO in your wallet for gas.

Is the code open source?

Yes. The smart contract source is verified on Celoscan and the full repository is public on GitHub.