⛓️Onchain program

The onchain program takes in mints and pools, and will calculate the most optimal arbitrage trade between them and execute the trades.

If you want maximum flexibility, you can write your own bot and just call the onchain program from there. This allow you to do whatever customization you want but still utilize the onchain program to get maximum arb opportunity.

Demo bot: https://github.com/Cetipoo/solana-onchain-arbitrage-bot

Current supported DEX:

  • Raydium

  • Raydium CPMM

  • Raydium CLMM

  • Pumpfun Swap

  • Meteora DLMM

  • Meteora Dynamic Pool

  • Meteora Dynamic Pool V2

  • Orca whirlpool

  • Solfi

  • Vertigo

NOTE: It's recommended to include this address lookup table as it has all the fixed keys needed: 4sKLJ1Qoudh8PJyqBeuKocYdsZvxTcRShUt9aKqwhgvC

NOTE: It's recommended to use at least 250_000 compute unit limit when only amm pools/dlmm, and at least 450_000 compute unit limit with other pools. Ideally you may want 600_000 - 700_000 to be able to hit the big arbs and not being limited by compute unit. Using merge mint will need a bit more CU than just one mint.

Here's a simplified Rust example for how to interact with the program. You can include multiple X mints with their according pools here.

You can also check https://github.com/Cetipoo/solana-onchain-arbitrage-bot to see how to extract all the keys for each pool type.

pub fn generate_onchain_swap_multiple_mints_instruction(
    wallet: &Pubkey,
    base_mint: &Pubkey,
    wallet_base_account: &Pubkey,
    token_program: &Pubkey,
    system_program: &Pubkey,
    associated_token_program: &Pubkey,
    token_pools: &[(
        Pubkey, // X mint
        Pubkey, // Token program ID
        Pubkey, // Wallet X account
        Vec<(
            Pubkey, // Raydium program ID
            Pubkey, // V9: Base mint
            Pubkey, // Raydium authority
            // Raydium pools
            Pubkey, // Raydium AMM account
            Pubkey, // Raydium token X vault
            Pubkey, // Raydium base vault
        )>,
        Vec<(
            Pubkey, // Raydium CP program ID
            Pubkey, // V9: Base mint
            Pubkey, // Raydium CP authority
            // Raydium CP pools
            Pubkey, // Raydium CP pool
            Pubkey, // Raydium CP amm config
            Pubkey, // Raydium CP token X vault
            Pubkey, // Raydium CP base vault
            Pubkey, // Raydium CP observation
        )>,
        Vec<(
            Pubkey, // Pump program ID
            Pubkey, // V9: Base mint
            Pubkey, // Pump global config
            Pubkey, // Pump authority
            Pubkey, // Pump fee wallet
            // Pump pools
            Pubkey, // Pump pool
            Pubkey, // Pump token X account
            Pubkey, // Pump base account
            Pubkey, // Pump fee token wallet
            Pubkey, // Pump coin creator vault
            Pubkey, // Pump coin creator vault authority
        )>,
        Vec<(
            Pubkey,         // DLMM program ID
            Pubkey,         // V9: Base mint
            Pubkey,         // DLMM event authority
            Option<Pubkey>, // DLMM memo program v2 (Only needed for Token 2022)
            // DLMM pairs
            Pubkey,           // DLMM pair account
            Pubkey,           // DLMM token X vault
            Pubkey,           // DLMM base vault
            Pubkey,           // DLMM oracle
            Vec<AccountMeta>, // Bin array accounts
        )>,
        Vec<(
            Pubkey,         // Whirlpool program ID
            Pubkey,         // V9: Base mint
            Pubkey,         // Whirlpool memo program v2
            // Whirlpool pools
            Pubkey,           // Whirlpool pool
            Pubkey,           // Whirlpool oracle
            Pubkey,           // Whirlpool token X vault
            Pubkey,           // Whirlpool token base vault
            Vec<AccountMeta>, // Whirlpool tick array accounts
        )>,
        Vec<(
            Pubkey,         // Raydium CLMM program ID
            Pubkey,         // V9: Base mint
            Option<Pubkey>, // Raydium CLMM memo program v2 (Only needed for Token 2022)
            // Raydium CLMM pools
            Pubkey,           // Raydium CLMM pool
            Pubkey,           // Raydium CLMM amm config
            Pubkey,           // Raydium CLMM observation state
            Pubkey,           // Raydium CLMM bitmap extension
            Pubkey,           // Raydium CLMM token X vault
            Pubkey,           // Raydium CLMM token base vault
            Vec<AccountMeta>, // Raydium CLMM tick array accounts
        )>,
        Vec<(
            Pubkey, // Meteora program ID
            Pubkey, // V9: Base mint
            Pubkey, // Meteora vault program ID
            // Meteora pools
            Pubkey, // Meteora pool
            Pubkey, // Meteora pool token X vault
            Pubkey, // Meteora pool token base vault
            Pubkey, // Meteora pool token X token vault
            Pubkey, // Meteora pool token base token vault
            Pubkey, // Meteora pool token X lp mint
            Pubkey, // Meteora pool token base lp mint
            Pubkey, // Meteora pool token X pool lp
            Pubkey, // Meteora pool token base pool lp
            Pubkey, // Meteora pool admin token fee X
            Pubkey, // Meteora pool admin token fee base
        )>,
        Vec<(
            Pubkey, // Solfi program ID
            Pubkey, // V9: Base mint
            Pubkey, // Sysvar instructions
            // Solfi pools
            Pubkey, // Solfi pool
            Pubkey, // Solfi token X vault
            Pubkey, // Solfi token base vault
        )>,
        Vec<(
            Pubkey, // DAMM V2 program ID
            Pubkey, // V9: Base mint
            Pubkey, // Event authority
            Pubkey, // Pool authority
            // DAMM V2 pools
            Pubkey, // DAMM V2 pool
            Pubkey, // DAMM V2 token X vault
            Pubkey, // DAMM V2 token base vault
        )>,
        Vec<(
            Pubkey, // Vertigo program ID
            Pubkey, // V9: Base mint
            // Vertigo pools
            Pubkey, // Vertigo pool
            Pubkey, // Vertigo pool owner
            Pubkey, // Vertigo token X vault
            Pubkey, // Vertigo token base vault
        )>,
    )],
    program_id: &Pubkey,
    minimum_profit: u64,
    compute_unit_limit: u32,
    no_failure_mode: bool,
    use_flashloan: bool,
) -> Instruction {
    let fee_collector = if use_flashloan {
        Pubkey::from_str("6AGB9kqgSp2mQXwYpdrV4QVV8urvCaDS35U1wsLssy6H").unwrap()
    } else {
        let fee_accounts = [
            Pubkey::from_str("GPpkDpzCDmYJY5qNhYmM14c7rct1zmkjWc2CjR5g7RZ1").unwrap(),
            Pubkey::from_str("J6c7noBHvWju4mMA3wXt3igbBSp2m9ATbA6cjMtAUged").unwrap(),
            Pubkey::from_str("BjsfwxDu7GX7RRW6oSRTpMkASdXAgCcHnXEcatqSfuuY").unwrap(),
        ];
        fee_accounts[rand::random::<usize>() % fee_accounts.len()]
    };
    let mut accounts = vec![
        AccountMeta::new(*wallet, true),
        AccountMeta::new_readonly(*base_mint, false),
        AccountMeta::new(fee_collector, false),
        AccountMeta::new(*wallet_base_account, false),
        AccountMeta::new_readonly(*token_program, false),
        AccountMeta::new_readonly(*system_program, false),
        AccountMeta::new_readonly(*associated_token_program, false),
    ];

    // Add flashloan accounts if enabled
    if use_flashloan {
        accounts.push(AccountMeta::new_readonly(
            Pubkey::from_str("5LFpzqgsxrSfhKwbaFiAEJ2kbc9QyimjKueswsyU4T3o").unwrap(),
            false,
        ));
        let token_pda = derive_vault_token_account(
            &Pubkey::from_str("MEViEnscUm6tsQRoGd9h6nLQaQspKj7DB2M5FwM3Xvz").unwrap(),
            base_mint,
        );
        accounts.push(AccountMeta::new(token_pda.0, false));
    }

    // Detect mixed mode by checking if any pool has a USDC base mint
    let usdc_mint = Pubkey::from_str("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v").unwrap();
    let mut has_usdc_base = false;

    // Check all pools to see if any have USDC as base mint
    for (
        _,
        _,
        _,
        raydium_pools,
        raydium_cp_pools,
        pump_pools,
        dlmm_pairs,
        whirlpool_pools,
        raydium_clmm_pools,
        meteora_pools,
        solfi_pools,
        dammv2_pools,
        vertigo_pools,
    ) in token_pools.iter()
    {
        // Check Raydium pools
        for (_, pool_base_mint, _, _, _, _) in raydium_pools.iter() {
            if *pool_base_mint == usdc_mint {
                has_usdc_base = true;
                break;
            }
        }

        // Check Raydium CP pools
        for (_, pool_base_mint, _, _, _, _, _, _) in raydium_cp_pools.iter() {
            if *pool_base_mint == usdc_mint {
                has_usdc_base = true;
                break;
            }
        }

        // Check Pump pools
        for (_, pool_base_mint, _, _, _, _, _, _, _, _, _) in pump_pools.iter() {
            if *pool_base_mint == usdc_mint {
                has_usdc_base = true;
                break;
            }
        }

        // Check DLMM pairs
        for (_, pool_base_mint, _, _, _, _, _, _, _) in dlmm_pairs.iter() {
            if *pool_base_mint == usdc_mint {
                has_usdc_base = true;
                break;
            }
        }

        // Check Whirlpool pools
        for (_, pool_base_mint, _, _, _, _, _, _) in whirlpool_pools.iter() {
            if *pool_base_mint == usdc_mint {
                has_usdc_base = true;
                break;
            }
        }

        // Check Raydium CLMM pools
        for (_, pool_base_mint, _, _, _, _, _, _, _, _) in raydium_clmm_pools.iter() {
            if *pool_base_mint == usdc_mint {
                has_usdc_base = true;
                break;
            }
        }

        // Check Meteora pools
        for (_, pool_base_mint, _, _, _, _, _, _, _, _, _, _, _, _) in meteora_pools.iter() {
            if *pool_base_mint == usdc_mint {
                has_usdc_base = true;
                break;
            }
        }

        // Check Solfi pools
        for (_, pool_base_mint, _, _, _, _) in solfi_pools.iter() {
            if *pool_base_mint == usdc_mint {
                has_usdc_base = true;
                break;
            }
        }

        // Check DAMM V2 pools
        for (_, pool_base_mint, _, _, _, _, _) in dammv2_pools.iter() {
            if *pool_base_mint == usdc_mint {
                has_usdc_base = true;
                break;
            }
        }

        // Check Vertigo pools
        for (_, pool_base_mint, _, _, _, _) in vertigo_pools.iter() {
            if *pool_base_mint == usdc_mint {
                has_usdc_base = true;
                break;
            }
        }

        if has_usdc_base {
            break;
        }
    }

    // If mixed mode is detected, add the required accounts
    if has_usdc_base {
        // Add mixed mode accounts
        let wallet_usdc_account = get_associated_token_address(wallet, &usdc_mint);
        let raydium_program_id =
            Pubkey::from_str("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8").unwrap();
        let raydium_authority =
            Pubkey::from_str("5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1").unwrap();
        let sysvar_instructions = solana_program::sysvar::instructions::id();

        // Raydium SOL/USDC pool accounts (mainnet)
        let raydium_sol_usdc_pool =
            Pubkey::from_str("58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2").unwrap();
        let raydium_usdc_vault =
            Pubkey::from_str("HLmqeL62xR1QoZ1HKKbXRrdN1p3phKpxRMb2VVopvBBz").unwrap();
        let raydium_sol_vault =
            Pubkey::from_str("DQyrAcCrDXQ7NeoqGgDCZwBvWDcYmFCjSb9JtteuvPpz").unwrap();

        accounts.push(AccountMeta::new_readonly(usdc_mint, false));
        accounts.push(AccountMeta::new(wallet_usdc_account, false));
        accounts.push(AccountMeta::new_readonly(raydium_program_id, false));
        accounts.push(AccountMeta::new_readonly(raydium_authority, false));
        accounts.push(AccountMeta::new_readonly(sysvar_instructions, false));
        accounts.push(AccountMeta::new(raydium_sol_usdc_pool, false));
        accounts.push(AccountMeta::new(raydium_usdc_vault, false));
        accounts.push(AccountMeta::new(raydium_sol_vault, false));
    }

    // Add token mint accounts and their pools
    for (
        x_mint,
        token_program_id,
        wallet_x_account,
        raydium_pools,
        raydium_cp_pools,
        pump_pools,
        dlmm_pairs,
        whirlpool_pools,
        raydium_clmm_pools,
        meteora_pools,
        solfi_pools,
        dammv2_pools,
        vertigo_pools,
    ) in token_pools.iter()
    {
        // Add mint info
        accounts.push(AccountMeta::new_readonly(*x_mint, false));
        accounts.push(AccountMeta::new_readonly(*token_program_id, false));
        accounts.push(AccountMeta::new(*wallet_x_account, false));

        // Add Raydium pools
        for (program_id, pool_base_mint, authority, pool, x_vault, base_vault) in
            raydium_pools.iter()
        {
            accounts.push(AccountMeta::new_readonly(*program_id, false));
            accounts.push(AccountMeta::new_readonly(*pool_base_mint, false)); // V9: Add base mint
            accounts.push(AccountMeta::new_readonly(*authority, false));
            accounts.push(AccountMeta::new(*pool, false));
            accounts.push(AccountMeta::new(*x_vault, false));
            accounts.push(AccountMeta::new(*base_vault, false));
        }

        // Add Raydium CP pools
        for (
            program_id,
            pool_base_mint,
            authority,
            pool,
            amm_config,
            x_vault,
            base_vault,
            observation,
        ) in raydium_cp_pools.iter()
        {
            accounts.push(AccountMeta::new_readonly(*program_id, false));
            accounts.push(AccountMeta::new_readonly(*pool_base_mint, false)); // V9: Add base mint
            accounts.push(AccountMeta::new_readonly(*authority, false));
            accounts.push(AccountMeta::new(*pool, false));
            accounts.push(AccountMeta::new_readonly(*amm_config, false));
            accounts.push(AccountMeta::new(*x_vault, false));
            accounts.push(AccountMeta::new(*base_vault, false));
            accounts.push(AccountMeta::new(*observation, false));
        }

        // Add Pump pools
        for (
            program_id,
            pool_base_mint,
            global_config,
            authority,
            fee_wallet,
            pool,
            x_account,
            base_account,
            fee_token_wallet,
            coin_creator_vault,
            coin_creator_vault_authority,
        ) in pump_pools.iter()
        {
            accounts.push(AccountMeta::new_readonly(*program_id, false));
            accounts.push(AccountMeta::new_readonly(*pool_base_mint, false)); // V9: Add base mint
            accounts.push(AccountMeta::new_readonly(*global_config, false));
            accounts.push(AccountMeta::new_readonly(*authority, false));
            accounts.push(AccountMeta::new(*fee_wallet, false));
            accounts.push(AccountMeta::new(*pool, false));
            accounts.push(AccountMeta::new(*x_account, false));
            accounts.push(AccountMeta::new(*base_account, false));
            accounts.push(AccountMeta::new(*fee_token_wallet, false));
            accounts.push(AccountMeta::new(*coin_creator_vault, false));
            accounts.push(AccountMeta::new_readonly(
                *coin_creator_vault_authority,
                false,
            ));
            let pump_program_id = Pubkey::from_str("pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA").unwrap();
            let (global_volume_accumulator, _) = Pubkey::find_program_address(
                &[b"global_volume_accumulator"],
                &pump_program_id,
            );
            let (user_volume_accumulator, _) = Pubkey::find_program_address(
                &[b"user_volume_accumulator", wallet.as_ref()],
                &pump_program_id,
            );
            accounts.push(AccountMeta::new(global_volume_accumulator, false));
            accounts.push(AccountMeta::new(user_volume_accumulator, false));
        }

        // Add DLMM pairs
        for (
            program_id,
            pool_base_mint,
            event_authority,
            memo_program,
            pair,
            x_vault,
            base_vault,
            oracle,
            bin_arrays,
        ) in dlmm_pairs.iter()
        {
            accounts.push(AccountMeta::new_readonly(*program_id, false));
            accounts.push(AccountMeta::new_readonly(*pool_base_mint, false)); // V9: Add base mint
            accounts.push(AccountMeta::new_readonly(*event_authority, false));
            if memo_program.is_some() {
                accounts.push(AccountMeta::new_readonly(memo_program.unwrap(), false));
            }
            accounts.push(AccountMeta::new(*pair, false));
            accounts.push(AccountMeta::new(*x_vault, false));
            accounts.push(AccountMeta::new(*base_vault, false));
            accounts.push(AccountMeta::new(*oracle, false));
            accounts.extend(bin_arrays.clone());
        }

        // Add Whirlpool pools
        for (
            program_id,
            pool_base_mint,
            memo_program,
            pool,
            oracle,
            x_vault,
            base_vault,
            tick_arrays,
        ) in whirlpool_pools.iter()
        {
            accounts.push(AccountMeta::new_readonly(*program_id, false));
            accounts.push(AccountMeta::new_readonly(*pool_base_mint, false)); // V9: Add base mint
            accounts.push(AccountMeta::new_readonly(MEMO_PROGRAM.clone(), false));
            accounts.push(AccountMeta::new(*pool, false));
            accounts.push(AccountMeta::new(*oracle, false)); // Oracle NEEDS to be writable for Whirlpool
            accounts.push(AccountMeta::new(*x_vault, false));
            accounts.push(AccountMeta::new(*base_vault, false));
            accounts.extend(tick_arrays.clone());
        }

        // Add Raydium CLMM pools
        for (
            program_id,
            pool_base_mint,
            memo_program,
            pool,
            amm_config,
            observation_state,
            bitmap_extension,
            x_vault,
            base_vault,
            tick_arrays,
        ) in raydium_clmm_pools.iter()
        {
            accounts.push(AccountMeta::new_readonly(*program_id, false));
            accounts.push(AccountMeta::new_readonly(*pool_base_mint, false)); // V9: Add base mint
            if memo_program.is_some() {
                accounts.push(AccountMeta::new_readonly(memo_program.unwrap(), false));
            }
            accounts.push(AccountMeta::new(*pool, false));
            accounts.push(AccountMeta::new_readonly(*amm_config, false));
            accounts.push(AccountMeta::new(*observation_state, false));
            accounts.push(AccountMeta::new(*bitmap_extension, false));
            accounts.push(AccountMeta::new(*x_vault, false));
            accounts.push(AccountMeta::new(*base_vault, false));
            accounts.extend(tick_arrays.clone());
        }

        // Add Meteora pools
        for (
            program_id,
            pool_base_mint,
            vault_program_id,
            pool,
            x_vault,
            base_vault,
            x_token_vault,
            base_token_vault,
            x_lp_mint,
            base_lp_mint,
            x_pool_lp,
            base_pool_lp,
            x_admin_fee,
            base_admin_fee,
        ) in meteora_pools.iter()
        {
            accounts.push(AccountMeta::new_readonly(*program_id, false));
            accounts.push(AccountMeta::new_readonly(*pool_base_mint, false)); // V9: Add base mint
            accounts.push(AccountMeta::new_readonly(*vault_program_id, false));
            accounts.push(AccountMeta::new(*pool, false));
            accounts.push(AccountMeta::new(*x_vault, false));
            accounts.push(AccountMeta::new(*base_vault, false));
            accounts.push(AccountMeta::new(*x_token_vault, false));
            accounts.push(AccountMeta::new(*base_token_vault, false));
            accounts.push(AccountMeta::new(*x_lp_mint, false));
            accounts.push(AccountMeta::new(*base_lp_mint, false));
            accounts.push(AccountMeta::new(*x_pool_lp, false));
            accounts.push(AccountMeta::new(*base_pool_lp, false));
            accounts.push(AccountMeta::new(*x_admin_fee, false));
            accounts.push(AccountMeta::new(*base_admin_fee, false));
        }

        // Add Solfi pools
        for (program_id, pool_base_mint, sysvar_instructions, pool, x_vault, base_vault) in
            solfi_pools.iter()
        {
            accounts.push(AccountMeta::new_readonly(*program_id, false));
            accounts.push(AccountMeta::new_readonly(*pool_base_mint, false)); // V9: Add base mint
            accounts.push(AccountMeta::new_readonly(*sysvar_instructions, false));
            accounts.push(AccountMeta::new(*pool, false));
            accounts.push(AccountMeta::new(*x_vault, false));
            accounts.push(AccountMeta::new(*base_vault, false));
        }

        // Add DAMM V2 pools
        for (
            program_id,
            pool_base_mint,
            event_authority,
            pool_authority,
            pool,
            x_vault,
            base_vault,
        ) in dammv2_pools.iter()
        {
            accounts.push(AccountMeta::new_readonly(*program_id, false));
            accounts.push(AccountMeta::new_readonly(*pool_base_mint, false)); // V9: Add base mint
            accounts.push(AccountMeta::new_readonly(*event_authority, false));
            accounts.push(AccountMeta::new_readonly(*pool_authority, false));
            accounts.push(AccountMeta::new(*pool, false));
            accounts.push(AccountMeta::new(*x_vault, false));
            accounts.push(AccountMeta::new(*base_vault, false));
        }

        // Add Vertigo pools
        for (program_id, pool_base_mint, pool, pool_owner, x_vault, base_vault) in
            vertigo_pools.iter()
        {
            accounts.push(AccountMeta::new_readonly(*program_id, false));
            accounts.push(AccountMeta::new_readonly(*pool_base_mint, false)); // V9: Add base mint
            accounts.push(AccountMeta::new(*pool, false));
            accounts.push(AccountMeta::new_readonly(*pool_owner, false));
            accounts.push(AccountMeta::new(*x_vault, false));
            accounts.push(AccountMeta::new(*base_vault, false));
        }
    }

    // Create instruction data
    let mut data = vec![28u8];
    data.extend_from_slice(&minimum_profit.to_le_bytes());
    data.extend_from_slice(&compute_unit_limit.to_le_bytes());
    data.extend_from_slice(if no_failure_mode { &[1] } else { &[0] });
    data.extend_from_slice(&0u16.to_le_bytes()); // reserved
    data.extend_from_slice(if use_flashloan { &[1] } else { &[0] });

    Instruction {
        program_id: *program_id,
        accounts,
        data,
    }
}


pub fn derive_vault_token_account(program_id: &Pubkey, mint: &Pubkey) -> (Pubkey, u8) {
    Pubkey::find_program_address(&[b"vault_token_account", mint.as_ref()], program_id)
}

Additional fee account

The onchain program supports charging additional fees on top of the bot fee itself. This allows you to build customized bot and charge your users yourself.

To do so you need to change two things when constructing the instruction.

  1. Add your addtional fee account. Note this need to be the same token mint as base mint. aka if base mint is WSOL your additional fee acount also need to be WSOL account.

  2. Change the additional_fee_bp arg. The number is in base point. For example if you set 500, it means you will charge 5% of the profit yourself, onchain program will take 15%, and user will get 80% of the whole profit.

    let additional_fee_collector = Pubkey::from_str("XXX").unwrap();
    let mut accounts = vec![
        // Fixed accounts (0-6)
        AccountMeta::new_readonly(*wallet, true), // 0. Wallet (signer)
        AccountMeta::new_readonly(*base_mint, false), // 1. SOL mint
        AccountMeta::new(fee_collector, false),   // 2. Fee collector
        AccountMeta::new(additional_fee_collector, false), // 2.5 Additional fee account
        AccountMeta::new(*wallet_base_account, false), // 3. Wallet SOL account
        AccountMeta::new_readonly(*token_program, false), // 4. Token program
        AccountMeta::new_readonly(*system_program, false), // 5. System program
        AccountMeta::new_readonly(*associated_token_program, false), // 6. Associated Token program
    ];
...
...
    // Create instruction data
    let mut data = vec![28u8];
    data.extend_from_slice(&minimum_profit.to_le_bytes());
    data.extend_from_slice(&compute_unit_limit.to_le_bytes());
    data.extend_from_slice(if no_failure_mode { &[1] } else { &[0] });
    // Example of 5% additional fee
    let additional_fee_bp = 500u16;
    data.extend_from_slice(&additional_fee_bp.to_le_bytes()); 
    data.extend_from_slice(if use_flashloan { &[1] } else { &[0] });

Last updated