💰Betting System

Solana-Powered Betting Platform

Our betting system is built on the Solana blockchain, offering transparent, provably fair, and instant betting on AI robot fights.


🎰 How Betting Works

User Flow

  1. Connect Wallet

    • User connects Phantom wallet to the platform

    • Platform requests limited permissions (betting only)

    • No private keys ever leave the user's device

  2. Browse Fights

    • View upcoming live fights

    • See fighter stats and historical performance

    • Check current betting odds

  3. Place Bet

    • Select a fighter (Left or Right)

    • Enter bet amount in $ARENAI

    • Review odds and potential payout

    • Sign transaction via Phantom wallet

  4. Watch Fight

    • Fight streams live on Pump.fun

    • Real-time updates on bet status

    • See community betting percentages

  5. Receive Payout

    • Claim your payout if your fighter wins

    • $ARENAI deposited directly to your wallet

    • Transaction confirmed on Solana blockchain


💰 Odds Calculation

Dynamic Odds System

Odds are calculated based on the betting pool distribution:

// Total pool for a fight
totalPool = leftBets + rightBets

// Payout multiplier
leftOdds = totalPool / leftBets
rightOdds = totalPool / rightBets

// House edge (5%)
houseEdge = 0.05
actualPayoutMultiplier = odds * (1 - houseEdge)

Example

Fight: Morpheus vs NeoNode

Metric
Left (Morpheus)
Right (NeoNode)

Total Bets

100 ARENAI

50 ARENAI

Odds

1.50x

3.00x

After House Edge

1.43x

2.85x

Scenario 1: You bet 10 ARENAI on Morpheus (Left)

  • If Morpheus wins: You receive 14.3 ARENAI(profit: 4.3 ARENAI)

  • If NeoNode wins: You lose 10 ARENAI

Scenario 2: You bet 10 ARENAIon NeoNode (Right)

  • If NeoNode wins: You receive 28.5 ARENAI(profit: 18.5 ARENAI)

  • If Morpheus wins: You lose 10 ARENAI


⛓️ Smart Contract Architecture

Contract Structure

use anchor_lang::prelude::*;
use anchor_spl::token::{Token, TokenAccount};

#[program]
pub mod robot_fight_betting {
    use super::*;

    // Initialize a new fight
    pub fn create_fight(
        ctx: Context<CreateFight>,
        fight_id: String,
        left_fighter: String,
        right_fighter: String,
    ) -> Result<()> {
        let fight = &mut ctx.accounts.fight;
        fight.fight_id = fight_id;
        fight.left_fighter = left_fighter;
        fight.right_fighter = right_fighter;
        fight.status = FightStatus::Open;
        fight.left_pool = 0;
        fight.right_pool = 0;
        fight.total_bets = 0;
        Ok(())
    }

    // Place a bet
    pub fn place_bet(
        ctx: Context<PlaceBet>,
        amount: u64,
        side: Side,
    ) -> Result<()> {
        require!(
            ctx.accounts.fight.status == FightStatus::Open,
            ErrorCode::FightNotOpen
        );

        // Transfer SOL from bettor to pool
        let transfer_ix = anchor_lang::solana_program::system_instruction::transfer(
            &ctx.accounts.bettor.key(),
            &ctx.accounts.pool.key(),
            amount,
        );
        
        anchor_lang::solana_program::program::invoke(
            &transfer_ix,
            &[
                ctx.accounts.bettor.to_account_info(),
                ctx.accounts.pool.to_account_info(),
            ],
        )?;

        // Record bet
        let bet = &mut ctx.accounts.bet;
        bet.fight_id = ctx.accounts.fight.key();
        bet.bettor = ctx.accounts.bettor.key();
        bet.amount = amount;
        bet.side = side;
        bet.odds = calculate_odds(&ctx.accounts.fight, side);
        bet.timestamp = Clock::get()?.unix_timestamp;

        // Update fight pools
        let fight = &mut ctx.accounts.fight;
        match side {
            Side::Left => fight.left_pool += amount,
            Side::Right => fight.right_pool += amount,
        }
        fight.total_bets += 1;

        Ok(())
    }

    // Close fight and declare winner
    pub fn close_fight(
        ctx: Context<CloseFight>,
        winner: Side,
    ) -> Result<()> {
        require!(
            ctx.accounts.fight.status == FightStatus::Open,
            ErrorCode::FightAlreadyClosed
        );

        let fight = &mut ctx.accounts.fight;
        fight.status = FightStatus::Closed;
        fight.winner = Some(winner);

        Ok(())
    }

    // Claim payout
    pub fn claim_payout(ctx: Context<ClaimPayout>) -> Result<()> {
        let bet = &ctx.accounts.bet;
        let fight = &ctx.accounts.fight;

        require!(
            fight.status == FightStatus::Closed,
            ErrorCode::FightNotClosed
        );

        require!(
            bet.side == fight.winner.unwrap(),
            ErrorCode::BetLost
        );

        require!(
            !bet.claimed,
            ErrorCode::AlreadyClaimed
        );

        // Calculate payout
        let total_pool = fight.left_pool + fight.right_pool;
        let winning_pool = match bet.side {
            Side::Left => fight.left_pool,
            Side::Right => fight.right_pool,
        };

        let house_edge = 0.05;
        let payout = (bet.amount * total_pool / winning_pool)
            * (1.0 - house_edge) as u64;

        // Transfer payout
        **ctx.accounts.pool.to_account_info().try_borrow_mut_lamports()? -= payout;
        **ctx.accounts.bettor.to_account_info().try_borrow_mut_lamports()? += payout;

        // Mark as claimed
        let bet = &mut ctx.accounts.bet;
        bet.claimed = true;
        bet.payout = payout;

        Ok(())
    }
}

#[derive(Accounts)]
pub struct CreateFight<'info> {
    #[account(init, payer = admin, space = 8 + 256)]
    pub fight: Account<'info, Fight>,
    #[account(mut)]
    pub admin: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct PlaceBet<'info> {
    #[account(init, payer = bettor, space = 8 + 128)]
    pub bet: Account<'info, Bet>,
    #[account(mut)]
    pub fight: Account<'info, Fight>,
    #[account(mut)]
    pub bettor: Signer<'info>,
    #[account(mut)]
    pub pool: SystemAccount<'info>,
    pub system_program: Program<'info, System>,
}

#[account]
pub struct Fight {
    pub fight_id: String,
    pub left_fighter: String,
    pub right_fighter: String,
    pub status: FightStatus,
    pub winner: Option<Side>,
    pub left_pool: u64,
    pub right_pool: u64,
    pub total_bets: u32,
}

#[account]
pub struct Bet {
    pub fight_id: Pubkey,
    pub bettor: Pubkey,
    pub amount: u64,
    pub side: Side,
    pub odds: f64,
    pub payout: u64,
    pub claimed: bool,
    pub timestamp: i64,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, PartialEq)]
pub enum FightStatus {
    Open,
    Live,
    Closed,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, PartialEq, Copy)]
pub enum Side {
    Left,
    Right,
}

#[error_code]
pub enum ErrorCode {
    #[msg("Fight is not open for betting")]
    FightNotOpen,
    #[msg("Fight is already closed")]
    FightAlreadyClosed,
    #[msg("Fight is not closed yet")]
    FightNotClosed,
    #[msg("Bet lost")]
    BetLost,
    #[msg("Payout already claimed")]
    AlreadyClaimed,
}

Contract Deployment

Mainnet Address: [CONTRACT_ADDRESS_HERE]

Program ID: RoboFight... (Solana Program ID)


🎮 Live Betting Experience

Real-Time Updates

During live fights, users see:

  • Current betting pool sizes

  • Live odds updates

  • Community betting percentages

  • Fight status updates

WebSocket Events

// Subscribe to fight updates
ws.on('fight:odds_update', (data) => {
  console.log('New odds:', data.leftOdds, data.rightOdds);
});

ws.on('bet:placed', (data) => {
  console.log('New bet:', data.amount, 'SOL on', data.side);
});

ws.on('fight:ended', (data) => {
  console.log('Winner:', data.winner);
  console.log('Your payout:', data.userPayout);
});

💡 Tips for Bettors

Strategy Guide

  1. Research Fighters

    • Check historical performance

    • Review fighting styles

    • Look for favourable matchups

  2. Manage Bankroll

    • Never bet more than you can afford to lose

    • Consider odds and risk/reward

    • Diversify across multiple fights

  3. Watch for Value

    • Sometimes underdog bets offer better value

    • Community sentiment can skew odds

    • Early bets before pool grows

  4. Understand the AI

    • AI behaviour is consistent but adaptive

    • Some matchups favour certain styles

    • No "rigged" fights - pure AI vs AI

Common Mistakes to Avoid

  • ❌ Chasing losses with larger bets

  • ❌ Betting on every fight (be selective)

  • ❌ Ignoring fighter statistics

  • ❌ Following the crowd blindly

  • ❌ Betting more than 5-10% of bankroll per fight


🔗 Integration Guide

For Developers

// Connect wallet
const connectWallet = async () => {
  const { solana } = window;
  if (solana?.isPhantom) {
    const response = await solana.connect();
    return response.publicKey.toString();
  }
};

// Place bet
const placeBet = async (fightId, side, amount) => {
  const response = await fetch('/api/bet/create', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ fightId, side, amount })
  });
  
  const { transaction } = await response.json();
  const signedTx = await window.solana.signTransaction(transaction);
  
  return await connection.sendRawTransaction(signedTx.serialize());
};

📱 Mobile Experience

The betting platform is fully responsive:

  • Native wallet integration (Phantom mobile)

  • Touch-optimized UI

  • Push notifications for bet results

  • QR code support for quick wallet connection


🌐 Supported Wallets

  • Phantom (Recommended)

  • ⏳ Solflare (Coming Soon)

  • ⏳ Backpack (Coming Soon)


Last updated