Skip to content

Commit

Permalink
add change delegate function
Browse files Browse the repository at this point in the history
  • Loading branch information
kstepanovdev committed Jul 16, 2024
1 parent 6c76333 commit 38af58e
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 3 deletions.
40 changes: 40 additions & 0 deletions programs/rewards/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ pub enum RewardsInstruction {
#[account(3, signer, name = "deposit_authority")]
#[account(4, writable, name = "reward_pool", desc = "The address of the reward pool")]
CloseMining,

/// Changes delegate mining account
#[account(0, writable, name = "reward_pool", desc = "The address of the reward pool")]
#[account(1, writable, name = "mining", desc = "The address of the mining account which belongs to the user and stores info about user's rewards")]
#[account(2, signer, name = "deposit_authority", desc = "The address of the Staking program's Registrar, which is PDA and is responsible for signing CPIs")]
#[account(3, signer, name = "mining_owner", desc = "The end user the mining accounts belongs to")]
#[account(4, writable, name = "old_delegate_mining", desc = "The address of the old delegate mining account")]
#[account(5, writable, name = "new_delegate_mining", desc = "The address of the new delegate mining account")]
ChangeDelegate {
/// Amount of staked tokens
staked_amount: u64,
},
}

/// Creates 'InitializePool' instruction.
Expand Down Expand Up @@ -376,3 +388,31 @@ pub fn close_mining(

Instruction::new_with_borsh(*program_id, &RewardsInstruction::CloseMining, accounts)
}

/// Creates 'Distribute Rewards" instruction.
#[allow(clippy::too_many_arguments)]
pub fn change_delegate(
program_id: &Pubkey,
reward_pool: &Pubkey,
mining: &Pubkey,
deposit_authority: &Pubkey,
mining_owner: &Pubkey,
old_delegate_mining: &Pubkey,
new_delegate_mining: &Pubkey,
staked_amount: u64,
) -> Instruction {
let accounts = vec![
AccountMeta::new(*reward_pool, false),
AccountMeta::new(*mining, false),
AccountMeta::new_readonly(*deposit_authority, true),
AccountMeta::new_readonly(*mining_owner, true),
AccountMeta::new(*old_delegate_mining, false),
AccountMeta::new(*new_delegate_mining, false),
];

Instruction::new_with_borsh(
*program_id,
&RewardsInstruction::ChangeDelegate { staked_amount },
accounts,
)
}
88 changes: 88 additions & 0 deletions programs/rewards/src/instructions/change_delegate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use crate::{
asserts::get_delegate_mining,
state::{Mining, RewardPool},
utils::{assert_and_deserialize_pool_and_mining, AccountLoader},
};
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
program_pack::Pack, pubkey::Pubkey,
};

/// Instruction context
pub struct ChangeDelegateContext<'a, 'b> {
reward_pool: &'a AccountInfo<'b>,
mining: &'a AccountInfo<'b>,
deposit_authority: &'a AccountInfo<'b>,
mining_owner: &'a AccountInfo<'b>,
old_delegate_mining: &'a AccountInfo<'b>,
new_delegate_mining: &'a AccountInfo<'b>,
}

impl<'a, 'b> ChangeDelegateContext<'a, 'b> {
/// New instruction context
pub fn new(
program_id: &Pubkey,
accounts: &'a [AccountInfo<'b>],
) -> Result<ChangeDelegateContext<'a, 'b>, ProgramError> {
let account_info_iter = &mut accounts.iter().enumerate();

let reward_pool = AccountLoader::next_with_owner(account_info_iter, program_id)?;
let mining = AccountLoader::next_with_owner(account_info_iter, program_id)?;
let deposit_authority = AccountLoader::next_signer(account_info_iter)?;
let mining_owner = AccountLoader::next_signer(account_info_iter)?;
let old_delegate_mining = AccountLoader::next_with_owner(account_info_iter, program_id)?;
let new_delegate_mining = AccountLoader::next_with_owner(account_info_iter, program_id)?;

Ok(ChangeDelegateContext {
reward_pool,
mining,
deposit_authority,
mining_owner,
old_delegate_mining,
new_delegate_mining,
})
}

/// Process instruction
#[allow(clippy::too_many_arguments)]
pub fn process(&self, program_id: &Pubkey, staked_amount: u64) -> ProgramResult {
let (mut reward_pool, mut mining) = assert_and_deserialize_pool_and_mining(
program_id,
self.mining_owner.key,
self.reward_pool,
self.mining,
self.deposit_authority,
)?;

// if new_delegate_mining.is_none that means that new_delegate == self
let mut new_delegate_mining = get_delegate_mining(self.new_delegate_mining, self.mining)?;
// if old_delegate_mining.is_none that means that old_delegate == self
let mut old_delegate_mining = get_delegate_mining(self.old_delegate_mining, self.mining)?;

reward_pool.change_delegate(
&mut mining,
new_delegate_mining.as_mut(),
old_delegate_mining.as_mut(),
staked_amount,
)?;

RewardPool::pack(reward_pool, *self.reward_pool.data.borrow_mut())?;
Mining::pack(mining, *self.mining.data.borrow_mut())?;

if let Some(new_delegate_mining) = new_delegate_mining {
Mining::pack(
new_delegate_mining,
*self.new_delegate_mining.data.borrow_mut(),
)?;
}

if let Some(old_delegate_mining) = old_delegate_mining {
Mining::pack(
old_delegate_mining,
*self.old_delegate_mining.data.borrow_mut(),
)?;
}

Ok(())
}
}
2 changes: 2 additions & 0 deletions programs/rewards/src/instructions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Program instructions
mod change_delegate;
mod claim;
mod close_mining;
mod deposit_mining;
Expand All @@ -10,6 +11,7 @@ mod initialize_mining;
mod initialize_pool;
mod withdraw_mining;

pub use change_delegate::*;
pub use claim::*;
pub use close_mining::*;
pub use deposit_mining::*;
Expand Down
10 changes: 7 additions & 3 deletions programs/rewards/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
use crate::{
instruction::RewardsInstruction,
instructions::{
ClaimContext, CloseMiningContext, DepositMiningContext, DistributeRewardsContext,
ExtendStakeContext, FillVaultContext, InitializeMiningContext, InitializePoolContext,
WithdrawMiningContext,
ChangeDelegateContext, ClaimContext, CloseMiningContext, DepositMiningContext,
DistributeRewardsContext, ExtendStakeContext, FillVaultContext, InitializeMiningContext,
InitializePoolContext, WithdrawMiningContext,
},
};
use borsh::BorshDeserialize;
Expand Down Expand Up @@ -93,5 +93,9 @@ pub fn process_instruction(
msg!("RewardsInstruction: CloseAccount");
CloseMiningContext::new(program_id, accounts)?.process()
}
RewardsInstruction::ChangeDelegate { staked_amount } => {
msg!("RewardsInstruction: ChangeDelegate");
ChangeDelegateContext::new(program_id, accounts)?.process(program_id, staked_amount)
}
}
}
26 changes: 26 additions & 0 deletions programs/rewards/src/state/reward_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,32 @@ impl RewardPool {

Ok(())
}

pub fn change_delegate(
&mut self,
mining: &mut Mining,
new_delegate_mining: Option<&mut Mining>,
old_delegate_mining: Option<&mut Mining>,
staked_amount: u64,
) -> ProgramResult {
mining.refresh_rewards(&self.calculator)?;

if let Some(old_delegate_mining) = old_delegate_mining {
old_delegate_mining.stake_from_others = old_delegate_mining
.stake_from_others
.safe_sub(staked_amount)?;
self.total_share = self.total_share.safe_sub(staked_amount)?;
}

if let Some(new_delegate_mining) = new_delegate_mining {
new_delegate_mining.stake_from_others = new_delegate_mining
.stake_from_others
.safe_add(staked_amount)?;
self.total_share = self.total_share.safe_add(staked_amount)?;
}

Ok(())
}
}

impl Sealed for RewardPool {}
Expand Down

0 comments on commit 38af58e

Please sign in to comment.