Smart Contracts
Overview
Money Race is powered by Sui Move smart contracts deployed as the money_race_v2 module. All core protocol logic—room management, periodic deposits, and proportional reward distribution—is handled on-chain with 100% gasless transactions for users.
Key Characteristics:
🔐 Non-custodial — Users control funds via PlayerPosition NFTs
🆓 Gasless — Backend sponsors all gas fees (users pay zero SUI)
📊 Proportional — Rewards based on consistency, NO penalties
🏦 Vault-based — Separate principal and reward balances
Contract Architecture

Design Pattern: Object-centric architecture where Room and Vault are shared objects, while PlayerPosition is an owned NFT giving users exclusive control over their participation.
Core Structs
1. AdminCap
Admin capability object for privileged operations:
Used for:
Starting rooms (
start_room())Finalizing rooms (
finalize_room())
2. Room
The savings room object (shared):
Status Lifecycle:
Period Calculation:
Examples:
3. Vault
Holds all deposited funds (shared):
Balance Flow (Testnet Simulation):
Mainnet (Future):
4. PlayerPosition
User's participation NFT (owned by player):
Key Fields:
deposited_count— Used to calculate proportional share (deposited_count / total_weight)last_period— Prevents double-depositing in same periodclaimed— Ensures one-time claim only
Constants
Room Status
Strategy IDs
Yield Rates (Testnet Simulation)
Note: Basis points (bps) where 100 bps = 1%. Testnet simulates yield by moving principal to reward pool. Mainnet will integrate real DeFi protocols.
Entry Functions
create_room()
Create a new savings room:
Creates:
Room object (shared)
Vault object (shared)
Emits: RoomCreated event
Example:
start_room()
Admin starts the room (moves from OPEN to ACTIVE):
Requirements:
Caller must have AdminCap
Room status must be OPEN
join_room()
Join room and make first deposit (period 0):
Requirements:
Room status must be ACTIVE
Current period must be 0 (first period)
Coin amount must equal
room.deposit_amount
Effects:
Deposit added to vault.principal
PlayerPosition NFT created and transferred to user
room.total_weightincreases by 1accrue_yield()called to simulate yield
Emits: PlayerJoined event
deposit()
Make periodic deposit (periods 1+):
Requirements:
Room status must be ACTIVE
Current period < total_periods
Current period > player.last_period (prevents double deposit)
Coin amount must equal
room.deposit_amount
Effects:
Deposit added to vault.principal
player.deposited_countincreases by 1player.last_periodupdated to current periodroom.total_weightincreases by 1accrue_yield()called to simulate yield
Emits: DepositMade event
finalize_room()
Admin finalizes room (moves from ACTIVE to FINISHED):
Requirements:
Caller must have AdminCap
Room status must be ACTIVE
room.total_weight> 0 (at least one deposit made)
Effects:
Final
accrue_yield()calledRoom status set to FINISHED
claim_all()
Claim proportional principal + reward:
Requirements:
Room status must be FINISHED
player.claimedmust be false (one-time claim)
Proportional Distribution Formula:
Effects:
Two Coin transfers to player.owner:
principal_coin (proportional principal)
reward_coin (proportional yield)
player.claimedset to trueroom.total_weightdecreased by player.deposited_count
Emits: RewardsClaimed event
Example:
Internal Functions
current_period()
Calculate which period the room is currently in:
accrue_yield()
Simulate external yield (testnet only):
Testnet Simulation: Yield is simulated by moving principal to reward pool, creating a zero-sum environment for demo purposes.
Mainnet: This function will integrate with real Sui DeFi protocols (Scallop, Navi, Cetus, Turbos, Kriya, Aftermath) to generate genuine external yield, keeping principal 100% intact.
Events
RoomCreated
PlayerJoined
DepositMade
YieldAccrued
RewardsClaimed
Security Features
✅ Object Ownership Model
PlayerPosition is owned by user (non-custodial)
Room and Vault are shared objects (transparent state)
✅ Access Control
AdminCap required for privileged operations
PlayerPosition ownership verified on-chain
✅ Balance Safety
Proper
Balance<USDC>handling withbalance::split()andbalance::join()No direct coin manipulation
✅ Double-Deposit Prevention
player.last_periodprevents depositing twice in same period
✅ One-Time Claim
player.claimedboolean ensures single claim only
✅ Time-Based Logic
Clock object used for accurate period calculation
No reliance on block timestamps
✅ Safe Math
All arithmetic uses u64 with proper overflow checks
Proportional distribution using integer division
Gasless Transactions
Money Race is 100% gasless for users.
How it works:
User signs transaction with their wallet/zkLogin
Backend adds sponsor signature using Gas Station pattern
Backend pays gas in SUI
User only needs USDC, zero SUI required
Sponsored Operations:
create_room()→ Gasless ✅join_room()→ Gasless ✅deposit()→ Gasless ✅claim_all()→ Gasless ✅
Backend Implementation:
Testnet vs Mainnet
Yield Source
Simulated (moves principal to reward)
Real (external DeFi protocols)
Principal
Reduced by yield simulation
100% intact
Protocols
None (simulation only)
Scallop, Navi, Cetus, Turbos, Kriya, Aftermath
APY
Fixed (4%/8%/15%)
Variable (market rates)
accrue_yield()
Cuts from principal
Adds from DeFi protocols
Example Flow
Complete User Journey:
Contract Deployment
Package ID (Testnet):
Module Name:
View on Sui Explorer: https://suiexplorer.com/object/0x0e5bb307c15081e2159f2a3a4d4aa509bd0ed1cda6338accf4189e734c5f122c?network=testnet
Last updated

