Steroid

A fully transparent, on-chain economic timing game built with smart-contract-enforced fairness.

Steroid

Created At

ETHGlobal Buenos Aires

Project Description

Steroid is a fully transparent, on-chain economic strategy game where players compete in a real-time timing challenge powered by smart-contract-enforced fairness. The game transforms historically opaque “last-in-wins” mechanics into a trustless coordination experiment with perfect information, predictable rules, and no operator control.

Players enter the game by making a deposit, which acts as their stake. Every new deposit is automatically and evenly redistributed among all earlier players, allowing them to progressively reach a predefined ROI target (e.g., 130%). Once a player’s ROI threshold is met, they can withdraw their profits at any time. Because all accounting happens on-chain, every user sees their real-time progress, remaining ROI, total deposits, and all incoming distributions. Games run on a countdown timer. Each time a new player joins, the timer resets, extending the game’s lifetime. If the timer ever reaches zero, the game ends immediately. At that moment, all unfulfilled deposits—from players who did not reach their ROI—are collected into a “soft pool,” and the last player to deposit before the timer expired wins the entire jackpot. This creates a high-intensity strategy loop where users must decide when to join, when to exit, and when to risk becoming the final entrant.

All rules are enforced by immutable smart contracts. There is no custody, no admin access to funds, and no hidden mechanics. Players have complete, real-time visibility into the entire state: number of participants, deposit amounts, remaining time, ROI progress, and jackpot growth. Risk and reward are fully transparent.

Users can also host their own games by making the first deposit and selecting configuration parameters like the ROI target, timer duration, and fee (2–10%). Hosts receive a portion of the fee from every withdrawal. If no one else joins, the host simply wins back their own deposit; if players do join and the host fails to reach ROI before the game ends, the host risks losing their initial stake like any other player.

Running on a private EVM Saga Chainlet enables Steroid to either be entirely gasless or introducing extra revenue source. All state transitions are recorded on-chain, preserving trustlessness and verifiability.

How it's Made

  1. Frontend

The Steroid frontend is built with Next.js (App Router) and TypeScript, using React 19, Tailwind CSS, and a set of custom and Radix UI components. Its purpose is to deliver a smooth, web-native interface for interacting with the on-chain game logic, viewing game states, managing wallets, and handling top-ups through Coinbase’s onramp.

The app is organized into a standard Next.js structure. Static assets live in public/, while the main application code is in src/. The app/ directory contains pages, layout, and API routes; UI components are grouped by domain under components/. Utility logic—authentication, CDP integration, hooks, constants—lives in lib/ and utils/.

Wallet authentication and user identity are handled through the Coinbase Developer Platform (CDP). Embedded wallets allow users to interact with the chainlet without installing extensions or managing private keys. All global providers—theme, auth, wallet—are wired together in app/layout.tsx, ensuring consistent state throughout the app. Real-time game data is fetched via a combination of backend API requests, ethers.js contract reads, and event listeners.

The frontend includes partial implementation of Coinbase’s fiat → crypto onramp. The underlying API logic and integration hooks are in place (lib/onramp-api.ts), but the final UI wasn’t completed before the hackathon deadline.

Key components include FundWallet.tsx for wallet top-ups, page.tsx for the main game list, and CDP utilities such as cdp-auth.ts. Sensitive configuration values (API keys, RPC URLs) are loaded from .env.

Development uses standard Next.js workflows (npm run dev, npm run build, npm start). Much of the non-critical UI scaffolding was accelerated using Lovable.dev AI and GitHub Copilot. All business-critical logic remains hand-written and reviewed manually.

  1. Backend

The backend is implemented with NestJS, using TypeScript and a modular architecture to handle authentication, game metadata, Coinbase integration, contract listeners, and database operations. It exposes a REST API consumed by the frontend and orchestrates on-chain, off-chain, and external service interactions.

The backend uses Drizzle ORM for data modeling and migrations. Schema definitions are in db/schema.ts, with migrations in db/migrations/. Contract ABIs and Typechain bindings live under common/contracts, powering all smart-contract interactions.

Each feature domain is encapsulated in its own NestJS module. Key modules include:

games/ — Core game endpoints and logic

contracts-interaction/ — Write/read operations against Game and GameFactory contracts

contract-listener/ — Event listeners consuming blockchain events from the Saga chainlet

coinbase/ — Fiat onramp and CDP API integration

filecoin/ — Filecoin uploads via Synapse SDK

saga/ — Internal orchestration layer for multi-step flows

The Filecoin module handles decentralized storage, leveraging the Synapse SDK to upload and pin game metadata (titles, descriptions, visuals, and configuration parameters). This separation keeps all game metadata tamper-resistant and persistent.

A lightweight internal SAGA orchestration (not related to the Saga blockchain) is included for handling multi-step operations that may involve the database, Filecoin, Coinbase, and the chainlet. Compensation logic ensures that partially completed flows can be rolled back cleanly.

The backend runs via Docker/Docker-Compose in production. Development includes watchers, live reload, test suites, and database migrations through standard scripts (npm run start:dev, npm run migrate, etc.). Sensitive values like API keys and RPC endpoints are defined in .env and loaded through a centralized env.ts.

  1. Smart Contracts

The smart-contract layer is implemented in Solidity, using Hardhat for local development and Foundry for deployment and testing. The system follows a scalable pattern using minimal proxy clones.

At the top level:

GameFactory.sol is the upgradeable master contract responsible for deploying new game instances via clones. Each Game instance is initialized with fixed settings—ROI target, token type, duration, fee percentage—and seeded with the host’s initial deposit.

Game.sol is the isolated contract that manages all gameplay mechanics: tracking bets, redistributing deposits, enforcing ROI thresholds, resetting timers, and resolving jackpots.

Gameplay Mechanics

Every bet is stored as a snapshot, keeping the amount, bettor address, and ROI requirement.

New deposits are redistributed across earlier, unfulfilled players. If only one bettor hasn’t reached their ROI threshold, they receive 100% of the next deposit.

A global countdown timer resets with each deposit. When it expires, the last bettor becomes eligible to claim the jackpot.

Withdrawals are allowed once a bettor’s required ROI threshold is met. If the timer expires first, any unqualified bets are absorbed into the jackpot pool.

Fees (2–10%) are applied to withdrawals and jackpot claims, then split evenly between the platform and the game’s creator. Fees accumulate in the factory contract and can be withdrawn by the owner.

Core Functions

createGame() deploys a new clone and initializes it with parameters.

placeBet() handles deposits, updates snapshots, increments the pool, and resets the timer.

withdrawBet() releases funds to players who achieved their ROI.

claimJackpot() transfers the remaining pool to the last bettor after reserving required ROI payouts.

setMaster() updates the implementation used for future clones.

Development & Testing

Game-level logic is tested across ETH and ERC20 scenarios using Hardhat scripts and Foundry tests. The test suite confirms ROI calculations, fee splits, jackpot resolution, and proxy behavior. Deployment to the Saga chainlet uses a custom deployment script tied to chainlet RPC endpoints.

Why Saga Chainlet

Running on a private Saga EVM chainlet gives Steroid several advantages:

Gasless execution, critical for a game with many rapid interactions

An isolated environment without congestion from other apps

Full compatibility with existing EVM tooling

Extremely fast deployment and iteration cycles

A future-proof architecture aligned with Saga's interoperability roadmap

This allows Steroid to operate like a real-time game rather than a traditional blockchain dApp.

background image mobile

Join the mailing list

Get the latest news and updates

Steroid | ETHGlobal