💰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
Connect Wallet
User connects Phantom wallet to the platform
Platform requests limited permissions (betting only)
No private keys ever leave the user's device
Browse Fights
View upcoming live fights
See fighter stats and historical performance
Check current betting odds
Place Bet
Select a fighter (Left or Right)
Enter bet amount in $ARENAI
Review odds and potential payout
Sign transaction via Phantom wallet
Watch Fight
Fight streams live on Pump.fun
Real-time updates on bet status
See community betting percentages
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
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
Research Fighters
Check historical performance
Review fighting styles
Look for favourable matchups
Manage Bankroll
Never bet more than you can afford to lose
Consider odds and risk/reward
Diversify across multiple fights
Watch for Value
Sometimes underdog bets offer better value
Community sentiment can skew odds
Early bets before pool grows
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

