mirror of
https://github.com/d0zingcat/ore.git
synced 2026-05-14 07:26:51 +00:00
sniper fee duration
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ pub fn process_initialize(accounts: &[AccountInfo<'_>], _data: &[u8]) -> Program
|
||||
let config = config_info.as_account_mut::<Config>(&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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user