Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ChewingGlass committed Nov 19, 2024
1 parent cd643ed commit 6e11f4f
Show file tree
Hide file tree
Showing 9 changed files with 310 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::{current_epoch, error::ErrorCode, state::*, TESTING};
use anchor_lang::prelude::*;
use anchor_spl::{
associated_token::AssociatedToken,
Expand All @@ -13,6 +12,8 @@ use voter_stake_registry::{
VoterStakeRegistry,
};

use crate::{current_epoch, error::ErrorCode, state::*, TESTING};

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)]
pub struct ClaimRewardsArgsV0 {
pub epoch: u64,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
use anchor_lang::prelude::*;
use anchor_spl::{
associated_token::AssociatedToken,
token::{Mint, Token, TokenAccount},
};
use circuit_breaker::{
cpi::{accounts::TransferV0, transfer_v0},
CircuitBreaker, TransferArgsV0,
};
use voter_stake_registry::{
state::{PositionV0, Registrar},
VoterStakeRegistry,
};

use crate::{current_epoch, error::ErrorCode, state::*, TESTING};

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)]
pub struct ClaimRewardsArgsV0 {
pub epoch: u64,
}

#[derive(Accounts)]
#[instruction(args: ClaimRewardsArgsV0)]
pub struct ClaimRewardsV0<'info> {
#[account(
seeds = [b"position".as_ref(), mint.key().as_ref()],
seeds::program = vsr_program.key(),
bump = position.bump_seed,
has_one = mint,
has_one = registrar,
)]
pub position: Box<Account<'info, PositionV0>>,
pub mint: Box<Account<'info, Mint>>,
#[account(
token::mint = mint,
token::authority = position_authority,
constraint = position_token_account.amount > 0
)]
pub position_token_account: Box<Account<'info, TokenAccount>>,
#[account(mut)]
pub position_authority: Signer<'info>,
pub registrar: Box<Account<'info, Registrar>>,
#[account(
has_one = registrar,
has_one = hnt_mint
)]
pub dao: Box<Account<'info, DaoV0>>,

#[account(
mut,
has_one = hnt_delegator_pool,
has_one = dao,
)]
pub sub_dao: Account<'info, SubDaoV0>,
#[account(
mut,
has_one = sub_dao,
seeds = ["delegated_position".as_bytes(), position.key().as_ref()],
bump,
)]
pub delegated_position: Account<'info, DelegatedPositionV0>,

pub hnt_mint: Box<Account<'info, Mint>>,

#[account(
seeds = ["sub_dao_epoch_info".as_bytes(), sub_dao.key().as_ref(), &args.epoch.to_le_bytes()],
bump,
constraint = sub_dao_epoch_info.rewards_issued_at.is_some() @ ErrorCode::EpochNotClosed
)]
pub sub_dao_epoch_info: Box<Account<'info, SubDaoEpochInfoV0>>,
#[account(mut)]
pub hnt_delegator_pool: Box<Account<'info, TokenAccount>>,
#[account(
init_if_needed,
payer = position_authority,
associated_token::mint = hnt_mint,
associated_token::authority = position_authority,
)]
pub delegator_ata: Box<Account<'info, TokenAccount>>,

/// CHECK: checked via cpi
#[account(
mut,
seeds = ["account_windowed_breaker".as_bytes(), hnt_delegator_pool.key().as_ref()],
seeds::program = circuit_breaker_program.key(),
bump
)]
pub delegator_pool_circuit_breaker: AccountInfo<'info>,

pub vsr_program: Program<'info, VoterStakeRegistry>,
pub system_program: Program<'info, System>,
pub circuit_breaker_program: Program<'info, CircuitBreaker>,
pub associated_token_program: Program<'info, AssociatedToken>,
pub token_program: Program<'info, Token>,
}

impl<'info> ClaimRewardsV0<'info> {
fn transfer_ctx(&self) -> CpiContext<'_, '_, '_, 'info, TransferV0<'info>> {
let cpi_accounts = TransferV0 {
from: self.hnt_delegator_pool.to_account_info(),
to: self.delegator_ata.to_account_info(),
owner: self.sub_dao.to_account_info(),
circuit_breaker: self.delegator_pool_circuit_breaker.to_account_info(),
token_program: self.token_program.to_account_info(),
};

CpiContext::new(self.circuit_breaker_program.to_account_info(), cpi_accounts)
}
}

pub fn handler(ctx: Context<ClaimRewardsV0>, args: ClaimRewardsArgsV0) -> Result<()> {
// load the vehnt information
let position = &mut ctx.accounts.position;
let registrar = &ctx.accounts.registrar;
let voting_mint_config = &registrar.voting_mints[position.voting_mint_config_idx as usize];

let delegated_position = &mut ctx.accounts.delegated_position;

// check epoch that's being claimed is over
let epoch = current_epoch(registrar.clock_unix_timestamp());
if !TESTING {
require_gt!(epoch, args.epoch, ErrorCode::EpochNotOver);
if delegated_position.is_claimed(args.epoch)? {
return Err(error!(ErrorCode::InvalidClaimEpoch));
}
}

let delegated_vehnt_at_epoch = position.voting_power(
voting_mint_config,
ctx.accounts.sub_dao_epoch_info.start_ts(),
)?;

msg!("Staked {} veHNT at start of epoch with {} total veHNT delegated to subdao and {} total rewards to subdao",
delegated_vehnt_at_epoch,
ctx.accounts.sub_dao_epoch_info.vehnt_at_epoch_start,
ctx.accounts.sub_dao_epoch_info.hnt_delegation_rewards_issued
);

// calculate the position's share of that epoch's rewards
// rewards = staking_rewards_issued * staked_vehnt_at_epoch / total_vehnt
let rewards = u64::try_from(
delegated_vehnt_at_epoch
.checked_mul(
ctx
.accounts
.sub_dao_epoch_info
.hnt_delegation_rewards_issued as u128,
)
.unwrap()
.checked_div(ctx.accounts.sub_dao_epoch_info.vehnt_at_epoch_start as u128)
.unwrap(),
)
.unwrap();

delegated_position.set_claimed(args.epoch)?;

let amount_left = ctx.accounts.hnt_delegator_pool.amount;
transfer_v0(
ctx.accounts.transfer_ctx().with_signer(&[&[
b"sub_dao",
ctx.accounts.sub_dao.dnt_mint.as_ref(),
&[ctx.accounts.sub_dao.bump_seed],
]]),
// Due to rounding down of vehnt fall rates it's possible the vehnt on the dao does not exactly match the
// vehnt remaining. It could be off by a little bit of dust.
TransferArgsV0 {
amount: std::cmp::min(rewards, amount_left),
},
)?;
Ok(())
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
use anchor_lang::{prelude::*, Discriminator};
use anchor_spl::token::{Mint, TokenAccount};
use voter_stake_registry::{
state::{LockupKind, PositionV0, Registrar},
VoterStakeRegistry,
};

use self::borsh::BorshSerialize;
use crate::{
create_account::{create_and_serialize_account_signed, AccountMaxSize},
Expand All @@ -7,13 +14,6 @@ use crate::{
state::*,
utils::*,
};
use anchor_lang::{prelude::*, Discriminator};
use anchor_spl::token::{Mint, TokenAccount};

use voter_stake_registry::{
state::{LockupKind, PositionV0, Registrar},
VoterStakeRegistry,
};

#[derive(Accounts)]
pub struct DelegateV0<'info> {
Expand Down Expand Up @@ -215,6 +215,8 @@ pub fn handler(ctx: Context<DelegateV0>) -> Result<()> {
rewards_issued_at: None,
initialized: false,
dc_onboarding_fees_paid: 0,
hnt_delegation_rewards_issued: 0,
hnt_rewards_issued: 0,
},
},
&[
Expand Down
2 changes: 2 additions & 0 deletions programs/helium-sub-daos/src/instructions/delegation/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
pub mod claim_rewards_v0;
pub mod claim_rewards_v1;
pub mod close_delegation_v0;
pub mod delegate_v0;
pub mod reset_lockup_v0;
pub mod transfer_v0;

pub use claim_rewards_v0::*;
pub use claim_rewards_v1::*;
pub use close_delegation_v0::*;
pub use delegate_v0::*;
pub use reset_lockup_v0::*;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use anchor_lang::prelude::*;
use anchor_spl::{
self,
associated_token::AssociatedToken,
token::{Mint, Token, TokenAccount},
};
use circuit_breaker::{
cpi::{accounts::InitializeAccountWindowedBreakerV0, initialize_account_windowed_breaker_v0},
CircuitBreaker, InitializeAccountWindowedBreakerArgsV0, ThresholdType as CBThresholdType,
WindowedCircuitBreakerConfigV0 as CBWindowedCircuitBreakerConfigV0,
};
use shared_utils::resize_to_fit;

use crate::{state::*, sub_dao_seeds, EPOCH_LENGTH};

#[derive(Accounts)]
pub struct InitializeHntDelegatorPoolV0<'info> {
#[account(mut)]
pub payer: Signer<'info>,
#[account(
mut,
has_one = authority,
has_one = hnt_mint
)]
pub dao: Box<Account<'info, DaoV0>>,
pub authority: Signer<'info>,
#[account(mut, has_one = dao)]
pub sub_dao: Box<Account<'info, SubDaoV0>>,
pub hnt_mint: Box<Account<'info, Mint>>,
/// CHECK: Initialized via cpi
#[account(
mut,
seeds = ["account_windowed_breaker".as_bytes(), delegator_pool.key().as_ref()],
seeds::program = circuit_breaker_program.key(),
bump
)]
pub delegator_pool_circuit_breaker: AccountInfo<'info>,
#[account(
init,
payer = payer,
seeds = ["delegator_pool".as_bytes(), hnt_mint.key().as_ref()],
bump,
token::mint = hnt_mint,
token::authority = sub_dao,
)]
pub delegator_pool: Box<Account<'info, TokenAccount>>,

pub system_program: Program<'info, System>,
pub token_program: Program<'info, Token>,
pub circuit_breaker_program: Program<'info, CircuitBreaker>,
pub associated_token_program: Program<'info, AssociatedToken>,
}

impl<'info> InitializeHntDelegatorPoolV0<'info> {
fn initialize_delegator_pool_breaker_ctx(
&self,
) -> CpiContext<'_, '_, '_, 'info, InitializeAccountWindowedBreakerV0<'info>> {
let cpi_accounts = InitializeAccountWindowedBreakerV0 {
payer: self.payer.to_account_info(),
circuit_breaker: self.delegator_pool_circuit_breaker.to_account_info(),
token_account: self.delegator_pool.to_account_info(),
owner: self.sub_dao.to_account_info(),
token_program: self.token_program.to_account_info(),
system_program: self.system_program.to_account_info(),
};
CpiContext::new(self.circuit_breaker_program.to_account_info(), cpi_accounts)
}
}

pub fn handler(ctx: Context<InitializeHntDelegatorPoolV0>) -> Result<()> {
let signer_seeds: &[&[&[u8]]] = &[sub_dao_seeds!(ctx.accounts.sub_dao)];

initialize_account_windowed_breaker_v0(
ctx
.accounts
.initialize_delegator_pool_breaker_ctx()
.with_signer(signer_seeds),
InitializeAccountWindowedBreakerArgsV0 {
authority: ctx.accounts.sub_dao.authority,
config: CBWindowedCircuitBreakerConfigV0 {
window_size_seconds: u64::try_from(EPOCH_LENGTH).unwrap(),
threshold_type: CBThresholdType::Absolute,
// Roughly 25% of the daily emissions
threshold: ctx.accounts.dao.emission_schedule[0].emissions_per_epoch / 25,
},
owner: ctx.accounts.sub_dao.key(),
},
)?;
ctx.accounts.sub_dao.hnt_delegator_pool = ctx.accounts.delegator_pool.key();

resize_to_fit(
&ctx.accounts.payer.to_account_info(),
&ctx.accounts.system_program.to_account_info(),
&ctx.accounts.sub_dao,
)?;

Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@ pub fn handler(ctx: Context<InitializeSubDaoV0>, args: InitializeSubDaoArgsV0) -
vehnt_delegated: 0,
vehnt_last_calculated_ts: Clock::get()?.unix_timestamp,
vehnt_fall_rate: 0,
delegator_pool: ctx.accounts.delegator_pool.key(),
delegator_pool: Pubkey::default(),
hnt_delegator_pool: ctx.accounts.delegator_pool.key(),
delegator_rewards_percent: args.delegator_rewards_percent,
onboarding_data_only_dc_fee: args.onboarding_data_only_dc_fee,
active_device_authority: args.active_device_authority,
Expand Down
Loading

0 comments on commit 6e11f4f

Please sign in to comment.