From c694dba2a25b64d772db39cdcd53d9415db096d2 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Wed, 1 Oct 2025 15:59:38 -0700 Subject: [PATCH] cleanup --- api/src/consts.rs | 2 +- api/src/state/miner.rs | 1 + api/src/state/round.rs | 3 +++ program/src/checkpoint.rs | 11 +++++------ program/src/deploy.rs | 3 ++- program/src/reset.rs | 25 +++++++++++++++++++------ 6 files changed, 31 insertions(+), 14 deletions(-) diff --git a/api/src/consts.rs b/api/src/consts.rs index 0704c6c..2628004 100644 --- a/api/src/consts.rs +++ b/api/src/consts.rs @@ -95,4 +95,4 @@ pub const DENOMINATOR_BPS: u64 = 10_000; pub const BOOST_RESERVE_TOKEN: Pubkey = pubkey!("Gce36ZUsBDJsoLrfCBxUB5Sfq2DsGunofStvxFx6rBiD"); /// The fee paid to bots if they checkpoint a user. -pub const CHECKPOINT_FEE: u64 = 10_000; // 0.00001 SOL +pub const CHECKPOINT_FEE: u64 = 100_000; // 0.0001 SOL diff --git a/api/src/state/miner.rs b/api/src/state/miner.rs index 53c04c3..60f5d53 100644 --- a/api/src/state/miner.rs +++ b/api/src/state/miner.rs @@ -23,6 +23,7 @@ pub struct Miner { pub checkpoint_id: u64, /// The amount of SOL this miner has had refunded and may claim. + #[deprecated] pub refund_sol: u64, /// The amount of SOL this miner can claim. diff --git a/api/src/state/round.rs b/api/src/state/round.rs index 05ff69d..bce3b85 100644 --- a/api/src/state/round.rs +++ b/api/src/state/round.rs @@ -16,6 +16,9 @@ pub struct Round { /// The hash of the end slot, provided by solana, used for random number generation. pub slot_hash: [u8; 32], + /// The count of miners on each square. + pub count: [u64; 25], + /// The slot at which claims for this round account end. pub expires_at: u64, diff --git a/program/src/checkpoint.rs b/program/src/checkpoint.rs index fe4ae18..3c39666 100644 --- a/program/src/checkpoint.rs +++ b/program/src/checkpoint.rs @@ -2,8 +2,6 @@ use ore_api::prelude::*; use solana_program::rent::Rent; use steel::*; -// TODO Bot fees - /// Checkpoints a miner's rewards. pub fn process_checkpoint(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { // Load accounts. @@ -36,7 +34,7 @@ pub fn process_checkpoint(accounts: &[AccountInfo<'_>], _data: &[u8]) -> Program // Ensure round is not expired. if clock.slot >= round.expires_at { // In this case, the miner forfeits any potential rewards and their checkpoint is recorded. - miner.checkpoint_id = round.id; + miner.checkpoint_id = miner.round_id; return Ok(()); } @@ -116,7 +114,8 @@ pub fn process_checkpoint(accounts: &[AccountInfo<'_>], _data: &[u8]) -> Program miner_info.send(bot_fee, &signer_info); } - // Assert round has sufficient funds for rent. + // Assert round has sufficient funds for rent + debts. + // TODO Debts let account_size = 8 + std::mem::size_of::(); let required_rent = Rent::get()?.minimum_balance(account_size); assert!( @@ -127,8 +126,8 @@ pub fn process_checkpoint(accounts: &[AccountInfo<'_>], _data: &[u8]) -> Program let account_size = 8 + std::mem::size_of::(); let required_rent = Rent::get()?.minimum_balance(account_size); assert!( - miner_info.lamports() >= required_rent, - "Miner does not have sufficient funds for rent" + miner_info.lamports() >= required_rent + miner.checkpoint_fee + miner.rewards_sol, + "Miner does not have sufficient funds for rent and rewards" ); Ok(()) diff --git a/program/src/deploy.rs b/program/src/deploy.rs index ddf5122..77070e9 100644 --- a/program/src/deploy.rs +++ b/program/src/deploy.rs @@ -153,6 +153,7 @@ pub fn process_deploy(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResul // Update board round.deployed[square_id] += amount; round.total_deployed += amount; + round.count[square_id] += 1; // Update total amount total_amount += amount; @@ -165,7 +166,7 @@ pub fn process_deploy(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResul } } - // Pay checkpoint fee. + // Top up checkpoint fee. if miner.checkpoint_fee == 0 { miner.checkpoint_fee = CHECKPOINT_FEE; miner_info.collect(CHECKPOINT_FEE, &signer_info)?; diff --git a/program/src/reset.rs b/program/src/reset.rs index bdd797d..259c323 100644 --- a/program/src/reset.rs +++ b/program/src/reset.rs @@ -6,7 +6,7 @@ use steel::*; pub fn process_reset(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { // Load accounts. let clock = Clock::get()?; - let [signer_info, board_info, config_info, fee_collector_info, mint_info, round_info, round_next_info, treasury_info, treasury_tokens_info, system_program, token_program, ore_program, slot_hashes_sysvar] = + let [signer_info, board_info, config_info, fee_collector_info, mint_info, round_info, round_next_info, top_miner_info, treasury_info, treasury_tokens_info, system_program, token_program, ore_program, slot_hashes_sysvar] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); @@ -67,7 +67,7 @@ pub fn process_reset(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul start_slot: board.start_slot, end_slot: board.end_slot, winning_square: winning_square as u64, - top_miner: round.top_miner, + top_miner: Pubkey::default(), num_winners: 0, total_deployed: round.total_deployed, total_vaulted: round.total_vaulted, @@ -107,6 +107,7 @@ pub fn process_reset(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul // Mint 1 ORE for the winning miner. let mint_amount = MAX_SUPPLY.saturating_sub(mint.supply()).min(ONE_ORE); + round.top_miner_reward = mint_amount; mint_to_signed( mint_info, treasury_tokens_info, @@ -151,6 +152,17 @@ pub fn process_reset(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul treasury.motherlode += motherlode_mint_amount; } + // Validate top miner. + // TODO Safety checks here. + let top_miner_sample = round.top_miner_sample(r, winning_square); + let top_miner = top_miner_info + .as_account::(&ore_api::ID)? + .assert(|m| m.round_id == round.id)? + .assert(|m| { + m.cumulative[winning_square] >= top_miner_sample + && top_miner_sample < m.cumulative[winning_square] + m.deployed[winning_square] + })?; + // Emit event. program_log( &[board_info.clone(), ore_program.clone()], @@ -160,8 +172,8 @@ pub fn process_reset(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul start_slot: board.start_slot, end_slot: board.end_slot, winning_square: winning_square as u64, - top_miner: Pubkey::default(), // Unknown - num_winners: 0, // Unknown + top_miner: top_miner.authority, + num_winners: round.count[winning_square], total_deployed: round.total_deployed, total_vaulted: round.total_vaulted, total_winnings: round.total_winnings, @@ -182,12 +194,13 @@ pub fn process_reset(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul ore_program, signer_info, &ore_api::ID, - &[ROUND, &(board.round_id + 1).to_le_bytes()], + &[ROUND, &board.round_id.to_le_bytes()], )?; let round_next = round_next_info.as_account_mut::(&ore_api::ID)?; - round_next.id = board.round_id + 1; + round_next.id = board.round_id; round_next.deployed = [0; 25]; round_next.slot_hash = [0; 32]; + round_next.count = [0; 25]; round_next.expires_at = board.end_slot + ONE_WEEK_SLOTS; round_next.rent_payer = *signer_info.key; round_next.motherlode = 0;