From 5551ce1c7fbd506df60e736c5c5ba81ed7aac2e4 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Fri, 18 Jul 2025 11:43:24 -0700 Subject: [PATCH] sniper fee duration --- api/src/consts.rs | 3 +++ api/src/instruction.rs | 4 +--- api/src/sdk.rs | 22 +++++----------------- api/src/state/config.rs | 3 +++ program/src/initialize.rs | 1 + program/src/reset.rs | 2 +- program/src/swap.rs | 35 ++++++++++++++++------------------- 7 files changed, 30 insertions(+), 40 deletions(-) diff --git a/api/src/consts.rs b/api/src/consts.rs index b054fc4..668457e 100644 --- a/api/src/consts.rs +++ b/api/src/consts.rs @@ -67,6 +67,9 @@ pub const DENOMINATOR_BPS: u64 = 10_000; /// Window to submit hashes, in slots. pub const INITIAL_BLOCK_DURATION: u64 = 1500; +/// Window to submit hashes, in slots. +pub const INITIAL_SNIPER_FEE_DURATION: u64 = 100; + /// Window to submit hashes, in slots. pub const MINING_WINDOW: u64 = 1500; diff --git a/api/src/instruction.rs b/api/src/instruction.rs index a0d1c89..3d91fd7 100644 --- a/api/src/instruction.rs +++ b/api/src/instruction.rs @@ -54,9 +54,7 @@ pub struct Initialize {} #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] -pub struct Log { - pub block_id: [u8; 8], -} +pub struct Log {} #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] diff --git a/api/src/sdk.rs b/api/src/sdk.rs index b714600..11b7855 100644 --- a/api/src/sdk.rs +++ b/api/src/sdk.rs @@ -2,16 +2,13 @@ use spl_associated_token_account::get_associated_token_address; use steel::*; use crate::{ - consts::{BLOCK, MINT_ADDRESS, TREASURY_ADDRESS}, + consts::{MARKET, MINT_ADDRESS, TREASURY_ADDRESS}, instruction::*, state::*, }; -pub fn log(signer: Pubkey, block_id: u64, msg: &[u8]) -> Instruction { - let mut data = Log { - block_id: block_id.to_le_bytes(), - } - .to_bytes(); +pub fn log(signer: Pubkey, msg: &[u8]) -> Instruction { + let mut data = Log {}.to_bytes(); data.extend_from_slice(msg); Instruction { program_id: crate::ID, @@ -20,17 +17,8 @@ pub fn log(signer: Pubkey, block_id: u64, msg: &[u8]) -> Instruction { } } -pub fn program_log( - block_id: u64, - accounts: &[AccountInfo], - msg: &[u8], -) -> Result<(), ProgramError> { - invoke_signed( - &log(*accounts[0].key, block_id, msg), - accounts, - &crate::ID, - &[BLOCK, &block_id.to_le_bytes()], - ) +pub fn program_log(accounts: &[AccountInfo], msg: &[u8]) -> Result<(), ProgramError> { + invoke_signed(&log(*accounts[0].key, msg), accounts, &crate::ID, &[MARKET]) } pub fn mine(signer: Pubkey, authority: Pubkey, id: u64, nonce: u64) -> Instruction { diff --git a/api/src/state/config.rs b/api/src/state/config.rs index 3fedf25..63ad89c 100644 --- a/api/src/state/config.rs +++ b/api/src/state/config.rs @@ -13,6 +13,9 @@ pub struct Config { // The block duration in slots. pub block_duration: u64, + // The duration in slots for which the sniper fee is applied. + pub sniper_fee_duration: u64, + // The address that receives fees. pub fee_collector: Pubkey, diff --git a/program/src/initialize.rs b/program/src/initialize.rs index 4fc285d..6507e9e 100644 --- a/program/src/initialize.rs +++ b/program/src/initialize.rs @@ -44,6 +44,7 @@ pub fn process_initialize(accounts: &[AccountInfo<'_>], _data: &[u8]) -> Program let config = config_info.as_account_mut::(&ore_api::ID)?; config.admin = *signer_info.key; config.block_duration = INITIAL_BLOCK_DURATION; + config.sniper_fee_duration = INITIAL_SNIPER_FEE_DURATION; config.fee_collector = *signer_info.key; config.fee_rate = FEE_LAMPORTS; diff --git a/program/src/reset.rs b/program/src/reset.rs index 787b06c..41f9c85 100644 --- a/program/src/reset.rs +++ b/program/src/reset.rs @@ -69,7 +69,7 @@ pub fn process_reset(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul } } - // Burn vault liquidity. + // Burn all ORE in market liquidity vault. let burn_amount = vault.amount(); burn_signed( vault_info, diff --git a/program/src/swap.rs b/program/src/swap.rs index 199f08c..74ee3c0 100644 --- a/program/src/swap.rs +++ b/program/src/swap.rs @@ -68,7 +68,7 @@ pub fn process_swap(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult } // Set the sniper fee based on time since the market began. - let fee_rate = calculate_sniper_fee(&clock, block); + let fee_rate = calculate_sniper_fee(block, &clock, config); market.fee.rate = fee_rate; // Execute the swap @@ -105,7 +105,7 @@ pub fn process_swap(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult miner.total_hashpower -= swap_event.base_to_transfer; block.total_hashpower -= swap_event.base_to_transfer; - // Trasnfer ORE from market to signer. + // Transfer ORE from market to signer. transfer_signed( market_info, vault_info, @@ -123,35 +123,32 @@ pub fn process_swap(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult // Emit event. program_log( - block.id, - &[block_info.clone(), ore_program.clone()], + &[market_info.clone(), ore_program.clone()], &swap_event.to_bytes(), )?; Ok(()) } -fn calculate_sniper_fee(clock: &Clock, block: &Block) -> u64 { +fn calculate_sniper_fee(block: &Block, clock: &Clock, config: &Config) -> u64 { let elapsed_slots = clock.slot.saturating_sub(block.start_slot); - - if elapsed_slots >= 100 { + if elapsed_slots >= config.sniper_fee_duration { return 0; } - - // Linear decay from 5000 bps (50%) to 0 bps over 100 slots - // Using formula: y = mx + b - // Where: - // - x is elapsed_slots (0 to 100) - // - y is fee_bps (5000 to 0) - // - m = -50 (slope) - // - b = 5000 (y-intercept) - - let remaining_fee = 5000 - (elapsed_slots * 50); - remaining_fee + let fee_bps = 5000 * (config.sniper_fee_duration - elapsed_slots) / config.sniper_fee_duration; + fee_bps } #[test] fn test_sniper_fees() { + let config = Config { + sniper_fee_duration: 100, + fee_rate: 0, + fee_collector: Pubkey::default(), + admin: Pubkey::default(), + block_duration: 0, + }; + let mut clock = Clock { slot: 0, epoch_start_timestamp: 0, @@ -174,7 +171,7 @@ fn test_sniper_fees() { for i in 0..200 { clock.slot = i; - let fee = calculate_sniper_fee(&clock, &block); + let fee = calculate_sniper_fee(&block, &clock, &config); println!("Slot {}: {} bps fee", i, fee); }