mirror of
https://github.com/d0zingcat/ore.git
synced 2026-06-04 23:26:47 +00:00
@@ -31,20 +31,20 @@ pub const ONE_MINUTE: i64 = 60;
|
|||||||
pub const EPOCH_MINUTES: i64 = 1;
|
pub const EPOCH_MINUTES: i64 = 1;
|
||||||
|
|
||||||
/// The duration of a program epoch, in seconds.
|
/// The duration of a program epoch, in seconds.
|
||||||
pub const EPOCH_DURATION: i64 = ONE_MINUTE.saturating_mul(EPOCH_MINUTES);
|
pub const EPOCH_DURATION: i64 = ONE_MINUTE * EPOCH_MINUTES;
|
||||||
|
|
||||||
/// The maximum token supply (21 million).
|
/// The maximum token supply (21 million).
|
||||||
pub const MAX_SUPPLY: u64 = ONE_ORE.saturating_mul(21_000_000);
|
pub const MAX_SUPPLY: u64 = ONE_ORE * 21_000_000;
|
||||||
|
|
||||||
/// The target quantity of ORE to be mined per epoch.
|
/// The target quantity of ORE to be mined per epoch.
|
||||||
pub const TARGET_EPOCH_REWARDS: u64 = ONE_ORE.saturating_mul(EPOCH_MINUTES as u64);
|
pub const TARGET_EPOCH_REWARDS: u64 = ONE_ORE * EPOCH_MINUTES as u64;
|
||||||
|
|
||||||
/// The maximum quantity of ORE that can be mined per epoch.
|
/// The maximum quantity of ORE that can be mined per epoch.
|
||||||
/// Inflation rate ≈ 1 ORE / min (min 0, max 8)
|
/// Inflation rate ≈ 1 ORE / min (min 0, max 8)
|
||||||
pub const MAX_EPOCH_REWARDS: u64 = TARGET_EPOCH_REWARDS.saturating_mul(BUS_COUNT as u64);
|
pub const MAX_EPOCH_REWARDS: u64 = TARGET_EPOCH_REWARDS * BUS_COUNT as u64;
|
||||||
|
|
||||||
/// The quantity of ORE each bus is allowed to issue per epoch.
|
/// The quantity of ORE each bus is allowed to issue per epoch.
|
||||||
pub const BUS_EPOCH_REWARDS: u64 = MAX_EPOCH_REWARDS.saturating_div(BUS_COUNT as u64);
|
pub const BUS_EPOCH_REWARDS: u64 = MAX_EPOCH_REWARDS / BUS_COUNT as u64;
|
||||||
|
|
||||||
/// The number of bus accounts, for parallelizing mine operations.
|
/// The number of bus accounts, for parallelizing mine operations.
|
||||||
pub const BUS_COUNT: usize = 8;
|
pub const BUS_COUNT: usize = 8;
|
||||||
|
|||||||
@@ -289,9 +289,7 @@ pub fn load_mint<'a, 'info>(
|
|||||||
return Err(ProgramError::UninitializedAccount);
|
return Err(ProgramError::UninitializedAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if Mint::unpack_unchecked(&info.data.borrow()).is_err() {
|
Mint::unpack(&info.data.borrow())?;
|
||||||
return Err(ProgramError::InvalidAccountData);
|
|
||||||
}
|
|
||||||
|
|
||||||
if is_writable && !info.is_writable {
|
if is_writable && !info.is_writable {
|
||||||
return Err(ProgramError::InvalidAccountData);
|
return Err(ProgramError::InvalidAccountData);
|
||||||
@@ -322,8 +320,7 @@ pub fn load_token_account<'a, 'info>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let account_data = info.data.borrow();
|
let account_data = info.data.borrow();
|
||||||
let account = spl_token::state::Account::unpack_unchecked(&account_data)
|
let account = spl_token::state::Account::unpack(&account_data)?;
|
||||||
.or(Err(ProgramError::InvalidAccountData))?;
|
|
||||||
|
|
||||||
if account.mint.ne(&mint) {
|
if account.mint.ne(&mint) {
|
||||||
return Err(ProgramError::InvalidAccountData);
|
return Err(ProgramError::InvalidAccountData);
|
||||||
|
|||||||
@@ -99,28 +99,26 @@ pub fn process_mine<'a, 'info>(
|
|||||||
let difficulty = difficulty.saturating_sub(MIN_DIFFICULTY);
|
let difficulty = difficulty.saturating_sub(MIN_DIFFICULTY);
|
||||||
let mut reward = config
|
let mut reward = config
|
||||||
.base_reward_rate
|
.base_reward_rate
|
||||||
.saturating_mul(2u64.saturating_pow(difficulty));
|
.checked_mul(2u64.checked_pow(difficulty).unwrap())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Apply staking multiplier.
|
// Apply staking multiplier.
|
||||||
// If user has greater than or equal to the max stake on the network, they receive 2x multiplier.
|
// If user has greater than or equal to the max stake on the network, they receive 2x multiplier.
|
||||||
// Any stake less than this will receives between 1x and 2x multipler. The multipler is only active
|
// Any stake less than this will receives between 1x and 2x multipler. The multipler is only active
|
||||||
// if the miner's last stake deposit was more than one minute ago.
|
// if the miner's last stake deposit was more than one minute ago.
|
||||||
if config.max_stake.gt(&0)
|
let t = clock.unix_timestamp;
|
||||||
&& proof
|
if config.max_stake.gt(&0) && proof.last_stake_at.saturating_add(ONE_MINUTE).le(&t) {
|
||||||
.last_stake_at
|
|
||||||
.saturating_add(ONE_MINUTE)
|
|
||||||
.le(&clock.unix_timestamp)
|
|
||||||
{
|
|
||||||
let staking_reward = proof
|
let staking_reward = proof
|
||||||
.balance
|
.balance
|
||||||
.min(config.max_stake)
|
.min(config.max_stake)
|
||||||
.saturating_mul(reward)
|
.checked_mul(reward)
|
||||||
.saturating_div(config.max_stake);
|
.unwrap()
|
||||||
reward = reward.saturating_add(staking_reward);
|
.checked_div(config.max_stake)
|
||||||
|
.unwrap();
|
||||||
|
reward = reward.checked_add(staking_reward).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reject spam transactions.
|
// Reject spam transactions.
|
||||||
let t = clock.unix_timestamp;
|
|
||||||
let t_target = proof.last_hash_at.saturating_add(ONE_MINUTE);
|
let t_target = proof.last_hash_at.saturating_add(ONE_MINUTE);
|
||||||
let t_spam = t_target.saturating_sub(TOLERANCE);
|
let t_spam = t_target.saturating_sub(TOLERANCE);
|
||||||
if t.lt(&t_spam) {
|
if t.lt(&t_spam) {
|
||||||
@@ -130,11 +128,15 @@ pub fn process_mine<'a, 'info>(
|
|||||||
// Apply liveness penalty.
|
// Apply liveness penalty.
|
||||||
let t_liveness = t_target.saturating_add(TOLERANCE);
|
let t_liveness = t_target.saturating_add(TOLERANCE);
|
||||||
if t.gt(&t_liveness) {
|
if t.gt(&t_liveness) {
|
||||||
reward = reward.saturating_sub(
|
reward = reward
|
||||||
reward
|
.checked_sub(
|
||||||
.saturating_mul(t.saturating_sub(t_liveness) as u64)
|
reward
|
||||||
.saturating_div(ONE_MINUTE as u64),
|
.checked_mul(t.checked_sub(t_liveness).unwrap() as u64)
|
||||||
);
|
.unwrap()
|
||||||
|
.checked_div(ONE_MINUTE as u64)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit payout amount to whatever is left in the bus
|
// Limit payout amount to whatever is left in the bus
|
||||||
@@ -143,9 +145,9 @@ pub fn process_mine<'a, 'info>(
|
|||||||
let reward_actual = reward.min(bus.rewards);
|
let reward_actual = reward.min(bus.rewards);
|
||||||
|
|
||||||
// Update balances
|
// Update balances
|
||||||
bus.theoretical_rewards = bus.theoretical_rewards.saturating_add(reward);
|
bus.theoretical_rewards = bus.theoretical_rewards.checked_add(reward).unwrap();
|
||||||
bus.rewards = bus.rewards.saturating_sub(reward_actual);
|
bus.rewards = bus.rewards.checked_sub(reward_actual).unwrap();
|
||||||
proof.balance = proof.balance.saturating_add(reward_actual);
|
proof.balance = proof.balance.checked_add(reward_actual).unwrap();
|
||||||
|
|
||||||
// Hash recent slot hash into the next challenge to prevent pre-mining attacks
|
// Hash recent slot hash into the next challenge to prevent pre-mining attacks
|
||||||
proof.last_hash = hash.h;
|
proof.last_hash = hash.h;
|
||||||
@@ -156,10 +158,7 @@ pub fn process_mine<'a, 'info>(
|
|||||||
.0;
|
.0;
|
||||||
|
|
||||||
// Update time trackers
|
// Update time trackers
|
||||||
proof.last_hash_at = proof
|
proof.last_hash_at = t.max(t_target);
|
||||||
.last_hash_at
|
|
||||||
.saturating_add(ONE_MINUTE)
|
|
||||||
.max(clock.unix_timestamp);
|
|
||||||
|
|
||||||
// Update lifetime stats
|
// Update lifetime stats
|
||||||
proof.total_hashes = proof.total_hashes.saturating_add(1);
|
proof.total_hashes = proof.total_hashes.saturating_add(1);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ pub fn process_stake<'a, 'info>(
|
|||||||
// Update proof balance
|
// Update proof balance
|
||||||
let mut proof_data = proof_info.data.borrow_mut();
|
let mut proof_data = proof_info.data.borrow_mut();
|
||||||
let proof = Proof::try_from_bytes_mut(&mut proof_data)?;
|
let proof = Proof::try_from_bytes_mut(&mut proof_data)?;
|
||||||
proof.balance = proof.balance.saturating_add(amount);
|
proof.balance = proof.balance.checked_add(amount).unwrap();
|
||||||
|
|
||||||
// Update deposit timestamp
|
// Update deposit timestamp
|
||||||
let clock = Clock::get().or(Err(ProgramError::InvalidAccountData))?;
|
let clock = Clock::get().or(Err(ProgramError::InvalidAccountData))?;
|
||||||
|
|||||||
Reference in New Issue
Block a user