The contracts, indexers and keepers behind Antigravity's on-chain game
Antigravity wanted a token game that unfolds in journeys, on a chain most Web3 tooling skips. We designed the system, wrote its contracts, the indexers that feed its apps and the keepers that run its timed actions, and led the team that built the apps.
- Client
- Antigravity
- Service
- Blockchain
- When
- 2024
- Team
- Mihir, Pratham Chudasama, Angel Lakra
- Status
- Live
The problem
Antigravity is an on-chain game told in journeys. Players register, mine the game's tokens by putting in PLS or other tokens priced in dollars, mint FuelCell NFTs and win lotteries. What players can do changes as each journey moves through its phases. The client wanted the game on PulseChain, with a second deployment on Base.
The rules changed every phase, so every contract had to agree on the state of the game. A contract could be correct on its own and still show a player the wrong state. It could also leave a player waiting on an action that another part of the system was meant to trigger. With tokens and prizes moving between players, that gap would cost them money.
What we built
We put the current journey and phase behind one contract, the phase manager. The phase manager works out the phase from the time since launch, so no transaction is needed to move the game forward. The minting, treasury and jackpot contracts all ask the phase manager what is allowed now.
Keepers run what does need a transaction. Keepers are off-chain jobs that announce lottery results, pay out treasury yield and fire the game's scheduled events. We built indexers that turn contract events into player and game data, so the apps and the keepers read the same game data.

Saturn model: "Saturn" by Freemodels, CC BY 4.0.
The lotteries carry the main tradeoff. Picking every winner on-chain would cost gas for each winner. Instead the keeper picks the winners off-chain from a verifiable random number. The keeper publishes the full list and posts one Merkle root to the jackpot contract. Each winner claims with a proof. Players rely on the keeper to run the draw. So every input is public: anyone can check the random number, the list and the root.
Before the parameters went into the contracts, we modeled the economy in Python. The model runs FuelCell minting, treasury yield, jackpots, the trading pool and the game's own spending account through many journeys of simulated trading. The team could see where the token supply would end up before committing to the parameters.
What was hard
Chainlink's randomness service did not run on PulseChain, and the hosted Graph did not index PulseChain either. We deployed the randomness contract on Base and ran the draw across the two chains. The randomness contract refuses a new request while one is still open. It also stops serving a random number once the number is older than a set number of blocks. The keeper skips a number equal to the one its last draw used.
For indexing, we self-hosted a Graph node configured for PulseChain. We also built a second indexing path with Ponder, so the apps had their data on either chain.
The game also had to change between journeys without losing what players held. Every journey contract is an upgradeable proxy whose storage layout is kept apart from its logic. New logic could ship between journeys without touching existing state. We backed the changes with unit tests on the journey contracts and fuzz and integration tests on the mining contracts. We also made fixes from each audit round and from Slither and Aderyn reports.
The result
Antigravity has been live on PulseChain and Base since 2024. Through the game, the client raised more than $300k. The game's token peaked at about $100M market cap, fully diluted. More than 1,000 participants, counted as unique wallet addresses, interacted with the game's contracts.
Built with
| Contracts | Solidity, Foundry |
|---|---|
| Upgrades | UUPS proxies, with storage layouts kept apart from the logic |
| Randomness | Chainlink VRF, on Base |
| Indexing | Ponder, and a self-hosted Graph node for PulseChain |
| Keepers | TypeScript, viem |
| Economy model | Python, pandas, Plotly |
| Apps | Next.js, wagmi, three.js |
| Chains | PulseChain, Base |