Cómo funciona
Zorrito
Ahorro premiado sin pérdida de capital, sobre Stellar.
Cómo funciona
Tu depósito va directo a Blend y empieza a generar al instante. No hay mínimo. Cada XLM, y cada segundo que está adentro, suma chances.
El capital de todos se presta en Blend, el mercado de crédito de Stellar. El interés que pagan los que piden prestado se acumula como premio.
Al vencer el plazo (una semana; 10 minutos en el pozo de prueba), cualquiera puede cerrarla. El premio y las chances de cada uno quedan congelados en ese instante.
El contrato fija de antemano qué número aleatorio de drand va a decidir: uno que todavía no existe. Cuando drand lo publica, cualquiera lo trae y el contrato verifica la firma antes de elegir.
El premio va entero a la wallet del ganador en la misma transacción. Todos los demás siguen con exactamente lo que pusieron, y una ronda nueva ya está corriendo.
🎯 Cómo se calculan las chances
Tu peso en el sorteo es cuánto pusiste por cuánto tiempo estuvo adentro durante la ronda. Es la misma proporción con la que tu plata generó el premio: quien más aportó al rendimiento, más chances tiene de llevárselo.
Ejemplo: dos personas con 100 XLM. Una entra el lunes, la otra el sábado. La primera tiene 6 veces más chances, porque su plata generó 6 veces más. Entrar a último momento con mucha plata casi no suma, y eso es a propósito: no hay forma de "comprar" el sorteo sobre la hora.
Retirar no borra lo ya devengado. Si tuviste plata adentro tres días y la sacás, esos tres días siguen contando para el sorteo de esa ronda.
🔥 La racha diaria
Una vez por día (UTC) podés marcar "Ahorré hoy". Cada día seguido suma peso a la ronda en curso, y cada día suma más que el anterior:
Como 1+2+…+7 = 28, los siete días seguidos suman exactamente una ronda entera de peso: quien marca todos los días duplica sus chances respecto de alguien con la misma plata que no marca ninguno. Saltear un día vuelve al día 1. El bono es de la ronda en que se marca; la ronda siguiente arranca de cero, como todo lo demás.
| Días seguidos | Peso extra acumulado | Chances vs. no marcar |
|---|---|---|
| 1 | 3,6 % de una ronda | ×1,04 |
| 3 | 21 % | ×1,21 |
| 5 | 54 % | ×1,54 |
| 7 🏆 | 100 % | ×2 |
🤝 Referidos
Tu link de invitación es tu dirección. Quien entra con él, en su primer depósito, te declara como referente, y desde ese momento pesás como si tuvieras el 10 % de su capital, mientras esté adentro. Si retira, el bono baja con él.
El tope de la mitad de tu propio capital es lo que hace que no convenga inventarse referidos: sin plata propia adentro no hay bono, y con plata propia el bono nunca vale más que la mitad de ella. Traer amigos suma; traer cuentas vacías no.
🎲 Cómo funciona el azar
Elegir un ganador on-chain es difícil: la cadena es determinística y pública, así que cualquier valor que se conozca al momento del sorteo puede ser influido por quien arma el bloque. Zorrito no usa nada de la cadena como fuente de azar. Usa drand, un beacon de aleatoriedad público operado por unas 20 organizaciones (Cloudflare, Protocol Labs, EPFL, Kudelski, entre otras) que publica un número firmado cada 3 segundos.
Al cerrar la ronda, el contrato calcula qué ronda de drand corresponde a 10 minutos en el futuro y la guarda. En ese momento nadie, ni drand, sabe qué valor va a tener. También congela el premio, el peso total y una entropía acumulada de todos los depósitos de la ronda.
Cuando drand publica esa ronda, cualquiera trae la firma. El contrato verifica con BLS12-381, en el propio Soroban, que la firma es válida para esa ronda exacta y para la clave pública de drand que tiene guardada. Si no verifica, no sortea. Si verifica, la semilla es:
ganador = el que cae en semilla mod peso_total
Comparación de enfoques
| Enfoque | Quién puede influir | Estado |
|---|---|---|
| Timestamp o hash del ledger | El validador que arma el bloque | Descartado |
| Commit-reveal con un keeper | El keeper, si se calla la revelación | Descartado: liveness |
| Oráculo VRF | El operador del oráculo | No hay uno en Stellar |
| drand + verificación BLS on-chain ✓ | Nadie por debajo de la mayoría de drand | Es lo que corre |
La verificación BLS12-381 dentro del contrato es posible porque Stellar la agregó como función nativa del host en el Protocolo 22. Zorrito la usa para verificar firmas de drand quicknet: un pairing_check entre la firma, el hash del mensaje, el generador de G2 y la clave pública del grupo.
🤖 Nadie tiene que estar
Cerrar la ronda y traer la firma son acciones que cualquiera puede hacer: no hay roles ni claves privilegiadas. El que las hace solo paga la fee. Hoy las dispara un keeper que corre como función serverless, y también cada visita a la app que encuentra una ronda vencida o un sorteo pendiente. Si el keeper desaparece, el pozo no se traba: el primero que abre la app lo destraba.
Y si drand dejara de publicar, lo único que no pasaría es el sorteo. El capital se retira igual, en cualquier momento, con o sin sorteo pendiente.
🧪 Probalo sin esperar una semana
El pozo de la home corre en mainnet con rondas semanales. Para ver el ciclo entero en minutos hay un pozo de prueba en testnet, con rondas de 10 minutos y XLM de prueba: zorritostellar.vercel.app/test. Es el mismo contrato, el mismo Blend (su pool de testnet) y el mismo drand. XLM de testnet gratis en el laboratorio de Stellar.
🌊 Blend: de dónde sale el premio
Blend es el protocolo de préstamos de Stellar. El pozo deposita el capital de todos como Supply en un pool de Blend v2 (Fixed en mainnet, TestnetV2 en testnet): una posición que presta y cobra interés pero que no se usa como colateral, así que no tiene deuda y no puede ser liquidada.
- El interés lo pagan los que piden prestado en el pool. El APY que muestra la app es el que Blend está pagando ahora.
- El contrato habla con Blend por su cuenta, a través de un adapter propio. Nadie tiene la llave de esa posición: solo el pozo puede depositar y retirar.
- El premio es la diferencia entre lo que hay en Blend y el capital depositado. Si el pool no generó, el premio es 0 y nadie pierde.
📈 Hecho para un millón de cuentas
Sortear entre muchos participantes con pesos distintos es caro si hay que recorrerlos. Zorrito guarda los pesos en un Fenwick tree sobre el storage del contrato, con capacidad para 220 cuentas (algo más de un millón). Depositar, retirar y sortear tocan siempre ~20 entradas, sin importar si hay 2 participantes o 1.000.000.
El tiempo se resuelve con álgebra, no con recorridos: el peso de cada cuenta es depósito × T − b, donde b se ajusta en cada movimiento. Así el peso de todos avanza con el reloj sin que nadie tenga que actualizarlo.
🛠 Stack técnico
| Contratos | Rust + Soroban (soroban-sdk 27). Tres contratos: el pozo, el adapter de Blend y un mock de rendimiento para tests. 58 tests, incluida la verificación BLS con claves propias, la racha, los referidos y el pozo operando contra el bytecode real de Blend. |
| Azar | drand quicknet (bls-unchained-g1-rfc9380), verificado on-chain con las funciones BLS12-381 del host de Stellar. Descompresión de puntos en el cliente con @noble/curves. |
| Rendimiento | Blend v2, reserva XLM: pool Fixed en mainnet, TestnetV2 en testnet. Integrado con contractimport! de los WASM oficiales. |
| Web | Next.js 16, Tailwind 4, @stellar/stellar-sdk 17, Stellar Wallets Kit (Freighter, xBull, Lobstr). Desplegada en Vercel. |
| Keeper | Función serverless en Vercel (/api/keeper), disparada por cron y por cada visita. Permissionless: cualquiera puede correr otro. |
📋 Contratos
Ver en stellar.expert ↗
Ver en stellar.expert ↗
Ver en stellar.expert ↗
Ver en drand ↗
Código abierto: github.com/artugrande/zorrito. Los tests, los scripts de deploy y este mismo sitio están ahí.
🛡️ Seguridad y riesgos, sin maquillaje
El azar viene de drand y se verifica en el contrato. No hay clave de admin en el pozo: ningún rol puede pausar, cambiar el sorteo ni tocar fondos. El adapter tiene un admin que solo sirve para fijar, una única vez, quién es el pozo.
Retirar no necesita permiso, no tiene penalidad y funciona aunque haya un sorteo pendiente, aunque el keeper esté caído y aunque drand deje de publicar.
El capital está prestado. Si el pool de Blend tiene casi toda su liquidez tomada, un retiro puede fallar hasta que alguien devuelva o deposite. Es el riesgo real de "nadie pierde": no se pierde capital, pero puede haber que esperar. Blend lo mitiga con tasas que suben con la utilización.
Un bug en Blend afecta al pozo como a cualquier prestamista. Blend v2 está auditado y es el protocolo de crédito con más uso en Stellar, pero el riesgo no es cero.
Si drand no publica, no hay sorteo hasta que vuelva. El capital se retira igual. drand lleva años publicando cada 3 segundos con más de 20 operadores.
Las entradas persistentes vencen si nadie las extiende. El contrato extiende las suyas en cada uso; para cuentas inactivas durante meses hace falta que alguien las extienda (cualquiera puede). Pendiente de automatizar en el keeper.
Construido desde cero durante el hackathon. El pozo de mainnet tiene un tope de capital fijo en el contrato justamente por esto: limita cuánto puede haber adentro hasta que una auditoría diga que se puede subir. No pongas plata que no puedas perder.
❓ Preguntas
No. El sorteo reparte solo el interés que generó el pozo. Tu depósito es tuyo y lo retirás cuando quieras. Lo único que puede pasar es tener que esperar si Blend está sin liquidez en ese momento.
Nada, y no perdés nada. Es la misma plata que tenías, pero con una chance de premio cada ronda en vez de un interés chico. Si preferís el interés seguro, Blend está ahí directo.
Porque el peso es plata por tiempo, no solo plata. Alguien con menos plata que entró antes puede pesar más. Y aun con más peso, es un sorteo: más chances no es certeza.
Sí. Cada sorteo emite un evento con la ronda de drand, la firma y el peso total. Con eso y los depósitos de la ronda, cualquiera recomputa la semilla y el ganador.
Nada malo. Se cierra cuando alguien la cierra, y hasta entonces el pozo sigue generando. El keeper y cada visita a la app la cierran solas.
Porque no necesita trustline: cualquier cuenta de Stellar ya lo tiene, y eso saca un paso del camino de entrada. El contrato es agnóstico: se construye con cualquier token que Blend acepte como reserva, y un pozo en USDC es el mismo código con otro token.
Podés, pero no te suman: el bono de referidos vale como mucho la mitad de tu propio capital, y sin capital vale cero.
