Smart Contract Architecture
Overview
The Flip.is smart contract is built on the Solana blockchain using the Anchor framework. It implements a secure, scalable, and verifiably fair coin flip gaming system with support for multiple tokens and automated treasury management.
Contract Address
Program ID: 472RXUv8zUX7zm4LprxNsFQvAZYEpSGaY9EUE4akCvG6
Core Components
Account Structures
Global Account
This account maintains platform-wide settings:
#[account]
#[derive(InitSpace, Debug)]
pub struct Global {
pub admin_authority: Pubkey,
pub fee_reciever: Pubkey,
pub initialized: bool
}
Key fields:
admin_authority
: Administrator wallet with special permissionsfee_reciever
: Wallet designated for fee collectioninitialized
: Prevents multiple initializations
CoinFlipGame Account
Each game instance is represented by a CoinFlipGame account:
#[account]
#[derive(InitSpace, Debug)]
pub struct CoinFlipGame {
creator: Pubkey,
creator_selection: bool,
oposite: Pubkey,
available_opposite: bool,
betting_amount: u64,
is_sol: bool,
token_mint: Pubkey,
start_time: i64,
is_finished: bool,
index: u16
}
Key fields:
creator
: Game creator's wallet addresscreator_selection
: Creator's choice (heads/tails)oposite
: Opponent's wallet addressavailable_opposite
: Indicates if game is joinablebetting_amount
: Stake amount in lamports/tokensis_sol
: Differentiates between SOL and SPL token gamestoken_mint
: SPL token mint address (if applicable)start_time
: Game creation timestampis_finished
: Game completion statusindex
: Unique game identifier
Core Instructions
1. Initialize
pub fn initialize(ctx: Context<Initialize>, params: GlobalSettingsInput) -> Result<()>
Platform initialization process:
Verifies no existing initialization
Creates global configuration account
Sets up administrative controls
Establishes fee structure
Required accounts:
authority
: Admin signerglobal
: Platform configuration PDAsystem_program
: Solana system program
2. Create Game
pub fn create_game(ctx: Context<InitGame>, params: GameParams) -> Result<()>
Game creation workflow:
Validates parameters and accounts
Creates game PDA
Handles token/SOL deposits
Initializes VRF request
Emits creation event
Required accounts:
global
: Platform configurationfee_reciever
: Fee collection walletcreator
: Game creatornew_game
: Game account PDAtreasury
: Platform treasuryrandom
: VRF accountToken program (for SPL games)
3. Join Game
pub fn join_opposite(ctx: Context<JoinGame>, params: IndexParam) -> Result<()>
Game joining process:
Validates game availability
Processes opponent's deposit
Updates game state
Emits join event
Required accounts:
global
: Platform configurationfee_reciever
: Fee collectioncreator
: Original game creatorplayer
: Joining playercoin_flip_game
: Target game account
Security Features
Access Control
Program-derived addresses (PDAs)
Signer verification
Authority checks
State validation
Fund Safety
Escrow-based holding
Atomic transactions
Automatic refunds
Balance verification
Token Support
Supported Tokens
pub const TOKEN_LIST: [&'static str; 4] = [
"So11111111111111111111111111111111111111112", // SOL/wSOL
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC
"Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", // USDT
"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263" // Bonk
];
Native SOL Handling
pub fn sol_transfer<'a>(
from_account: AccountInfo<'a>,
to_account: AccountInfo<'a>,
system_program: AccountInfo<'a>,
amount: u64
) -> Result<()>
SPL Token Support
pub fn token_transfer<'a>(
from_ata: AccountInfo<'a>,
to_ata: AccountInfo<'a>,
authority: AccountInfo<'a>,
token_program: AccountInfo<'a>,
amount: u64
) -> Result<()>
Random Number Generation
The contract uses Orao VRF for secure random number generation:
// Request Generation
orao_solana_vrf::cpi::request(cpi_ctx, params.force)?;
// Result Verification
let randomness = current_state(&rand_acc);
let rand: u64 = randomness % 2;
Security measures:
On-chain verification
Tamper-proof results
Transparent process
Error Handling
#[error_code]
pub enum ContractError {
#[msg("Invalid Global Authority")]
InvalidGlobalAuthority,
#[msg("Global is already initialized")]
AlreadyInitialized,
#[msg("Already exist opposite")]
AlreadyReadyGame,
#[msg("Global is not initialized")]
InvalidGlobal,
#[msg("Invalid fee reciever")]
InvalidFeeReciever,
#[msg("Game is not ready to start.")]
InvalidGame,
#[msg("Invalid Math.")]
InvalidMath,
#[msg("Invalid Token. Please check token")]
InvalidToken,
#[msg("Failed to get random number.")]
FailedToGetRandomNumber,
#[msg("Invalid betting amount.")]
InvalidBettingAmount,
}
Events
InitEvent
#[event]
pub struct InitEvent {
pub creator: Pubkey,
pub creator_selection: bool,
pub available_opposite: bool,
pub betting_amount: u64,
pub is_sol: bool,
pub token_mint: Pubkey,
pub start_time: i64,
pub game_pda: Pubkey,
pub is_finished: bool,
pub index: u16
}
JoinEvent
#[event]
pub struct JoinEvent {
pub opposite: Pubkey,
pub creator_selection: bool,
pub available_opposite: bool,
pub game_pda: Pubkey,
}
HandleEvent
#[event]
pub struct HandleEvent {
pub result: bool,
pub selelction: bool,
pub creator: Pubkey,
pub opposite: Pubkey,
pub game_pda: Pubkey,
}
Contract Optimization
Space Optimization
Minimal account sizes
Efficient data structures
Optimal PDA seeds
Performance Considerations
Minimized CPI calls
Efficient token handling
Optimized account lookups
Testing and Deployment
Test Scripts
Located in scripts/ directory:
Integration tests
Unit tests
Simulation tests
Deployment Process
Program deployment
Global initialization
Authority setup
Token configuration
Last updated