Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add a limit to y #509

Merged
merged 4 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 5 additions & 19 deletions staking/app/StakeConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,8 +418,7 @@ export class StakeConnection {
[wasm.PositionState.LOCKED, wasm.PositionState.LOCKING].includes(
stakeAccount.stakeAccountPositionsWasm.getPositionState(
el.index,
BigInt(currentEpoch.toString()),
this.config.unlockingDuration
BigInt(currentEpoch.toString())
)
)
)
Expand Down Expand Up @@ -1060,13 +1059,10 @@ export class StakeConnection {

const time = new BN(Date.now() / 1000);
const currentEpoch = time.div(this.config.epochDuration);
const unlockingDuration = this.config.unlockingDuration;
const currentEpochBI = BigInt(currentEpoch.toString());

const lockedBalanceSummary = positionAccountWasm.getLockedBalanceSummary(
currentEpochBI,
unlockingDuration
);
const lockedBalanceSummary =
positionAccountWasm.getLockedBalanceSummary(currentEpochBI);

const epochOfFirstStake: BN = positionAccountJs.positions.reduce(
(prev: BN | undefined, curr) => {
Expand Down Expand Up @@ -1250,15 +1246,11 @@ export class StakeAccount {
);

const currentEpoch = unixTime.div(this.config.epochDuration);
const unlockingDuration = this.config.unlockingDuration;
const currentEpochBI = BigInt(currentEpoch.toString());

const unvestedBN = new BN(unvestedBalance.toString());
const lockedSummaryBI =
this.stakeAccountPositionsWasm.getLockedBalanceSummary(
currentEpochBI,
unlockingDuration
);
this.stakeAccountPositionsWasm.getLockedBalanceSummary(currentEpochBI);

let lockingBN = new BN(lockedSummaryBI.locking.toString());
let lockedBN = new BN(lockedSummaryBI.locked.toString());
Expand Down Expand Up @@ -1372,11 +1364,9 @@ export class StakeAccount {

public getVoterWeight(unixTime: BN): PythBalance {
let currentEpoch = unixTime.div(this.config.epochDuration);
let unlockingDuration = this.config.unlockingDuration;

const voterWeightBI = this.stakeAccountPositionsWasm.getVoterWeight(
BigInt(currentEpoch.toString()),
unlockingDuration,
BigInt(
this.votingAccountMetadataWasm.getCurrentAmountLocked(
BigInt(currentEpoch.toString())
Expand Down Expand Up @@ -1430,11 +1420,7 @@ export class StakeAccount {
}

private addUnlockingPeriod(unixTime: BN) {
return unixTime.add(
this.config.epochDuration.mul(
new BN(this.config.unlockingDuration).add(new BN(1))
)
);
return unixTime.add(this.config.epochDuration.mul(new BN(2)));
}

public getNetExcessGovernanceAtVesting(unixTime: BN): BN {
Expand Down
7 changes: 2 additions & 5 deletions staking/integration-tests/src/staking/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ use {
},
anchor_spl::token::spl_token,
integrity_pool::utils::{
clock::{
EPOCH_DURATION,
UNLOCKING_DURATION,
},
clock::EPOCH_DURATION,
types::frac64,
},
litesvm::types::TransactionResult,
Expand Down Expand Up @@ -59,7 +56,7 @@ pub fn init_config_account(svm: &mut litesvm::LiteSVM, payer: &Keypair, pyth_tok
governance_authority: payer.pubkey(),
pyth_token_mint,
pyth_governance_realm: MAINNET_REALM_ID,
unlocking_duration: UNLOCKING_DURATION,
unlocking_duration: 1,
epoch_duration: EPOCH_DURATION,
freeze: false,
pda_authority: payer.pubkey(),
Expand Down
4 changes: 2 additions & 2 deletions staking/integration-tests/src/utils/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ use integrity_pool::utils::types::{
// 100 PYTH tokens
pub const STAKED_TOKENS: frac64 = 100 * FRAC_64_MULTIPLIER;

// 10% yield per epoch
pub const YIELD: frac64 = FRAC_64_MULTIPLIER / 10;
// 1% yield per epoch
pub const YIELD: frac64 = FRAC_64_MULTIPLIER / 100;
12 changes: 12 additions & 0 deletions staking/integration-tests/tests/initialize_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use {
integrity_pool::{
error::IntegrityPoolError,
state::pool::PoolConfig,
utils::types::FRAC_64_MULTIPLIER,
},
solana_sdk::{
program_error::ProgramError,
Expand Down Expand Up @@ -101,4 +102,15 @@ fn test_update_y() {
IntegrityPoolError::InvalidRewardProgramAuthority,
0
);

assert_anchor_program_error!(
update_y(
&mut svm,
&payer,
&reward_program_authority,
FRAC_64_MULTIPLIER / 100 + 1
),
IntegrityPoolError::InvalidY,
0
);
}
7 changes: 3 additions & 4 deletions staking/integration-tests/tests/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ use {
integrity_pool::{
state::pool::PoolData,
utils::{
clock::UNLOCKING_DURATION,
constants::MAX_PUBLISHERS,
types::FRAC_64_MULTIPLIER,
},
Expand Down Expand Up @@ -334,7 +333,7 @@ fn sanity_check_publisher(
for i in 0..positions.get_position_capacity() {
if let Some(position) = positions.read_position(i).unwrap() {
let position_state = position
.get_current_position(get_current_epoch(svm), UNLOCKING_DURATION)
.get_current_position(get_current_epoch(svm))
.unwrap();
if matches!(position, Position {
target_with_parameters: TargetWithParameters::IntegrityPool { publisher: p, .. },
Expand Down Expand Up @@ -518,7 +517,7 @@ fn test_stability(props: StabilityTestProps) {
for i in 0..positions.get_position_capacity() {
if let Some(position) = positions.read_position(i).unwrap() {
let position_state = position
.get_current_position(get_current_epoch(&mut svm), UNLOCKING_DURATION)
.get_current_position(get_current_epoch(&mut svm))
.unwrap();
if matches!(position, Position {
target_with_parameters: TargetWithParameters::IntegrityPool { publisher: p, .. },
Expand Down Expand Up @@ -682,7 +681,7 @@ fn test_stability(props: StabilityTestProps) {
for i in 0..positions.get_position_capacity() {
if let Some(position) = positions.read_position(i).unwrap() {
let position_state = position
.get_current_position(get_current_epoch(&mut svm), UNLOCKING_DURATION)
.get_current_position(get_current_epoch(&mut svm))
.unwrap();
if matches!(
position,
Expand Down
2 changes: 2 additions & 0 deletions staking/programs/integrity-pool/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ pub enum IntegrityPoolError {
#[msg("Delegation fee must not be greater than 100%")]
InvalidDelegationFee,
InvalidPublisher,
#[msg("Y should not be greater than 1%")]
InvalidY,
}
12 changes: 6 additions & 6 deletions staking/programs/integrity-pool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ use {
TargetWithParameters,
},
utils::{
clock::{
get_current_epoch,
UNLOCKING_DURATION,
},
clock::get_current_epoch,
constants::{
MAX_PUBLISHERS,
POOL_CONFIG,
Expand Down Expand Up @@ -39,6 +36,8 @@ pub mod integrity_pool {
pyth_token_mint: Pubkey,
y: frac64,
) -> Result<()> {
require_gte!(FRAC_64_MULTIPLIER / 100, y, IntegrityPoolError::InvalidY);

let pool_config = &mut ctx.accounts.pool_config;
pool_config.pool_data = ctx.accounts.pool_data.key();
pool_config.reward_program_authority = reward_program_authority;
Expand All @@ -52,6 +51,8 @@ pub mod integrity_pool {
}

pub fn update_y(ctx: Context<UpdateY>, y: frac64) -> Result<()> {
require_gte!(FRAC_64_MULTIPLIER / 100, y, IntegrityPoolError::InvalidY);

ctx.accounts.pool_config.y = y;
Ok(())
}
Expand Down Expand Up @@ -177,8 +178,7 @@ pub mod integrity_pool {
.read_position(position_index.into())?
.ok_or(IntegrityPoolError::ThisCodeShouldBeUnreachable)?;

let position_state =
position.get_current_position(get_current_epoch()?, UNLOCKING_DURATION)?;
let position_state = position.get_current_position(get_current_epoch()?)?;
pool_data.remove_delegation(
publisher.key,
&ctx.accounts.stake_account_positions.key(),
Expand Down
8 changes: 2 additions & 6 deletions staking/programs/integrity-pool/src/state/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ use {
crate::{
error::IntegrityPoolError,
utils::{
clock::{
time_to_epoch,
UNLOCKING_DURATION,
},
clock::time_to_epoch,
constants::{
MAX_EVENTS,
MAX_PUBLISHERS,
Expand Down Expand Up @@ -142,8 +139,7 @@ impl PoolData {
break;
}

let position_state =
position.get_current_position(event.epoch, UNLOCKING_DURATION)?;
let position_state = position.get_current_position(event.epoch)?;

match position_state {
PositionState::LOCKED | PositionState::PREUNLOCKING => {}
Expand Down
1 change: 0 additions & 1 deletion staking/programs/integrity-pool/src/utils/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use {
};

pub const EPOCH_DURATION: u64 = 60 * 60 * 24 * 7; // 1 week
pub const UNLOCKING_DURATION: u8 = 1; // 1 epoch

/// Computes Pyth clock.
/// Right now it's just the current Unix timestamp divided by the epoch duration.
Expand Down
15 changes: 1 addition & 14 deletions staking/programs/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,12 @@ pub mod staking {
/// Creates a global config for the program
use super::*;


pub fn init_config(ctx: Context<InitConfig>, global_config: GlobalConfig) -> Result<()> {
let config_account = &mut ctx.accounts.config_account;
config_account.bump = ctx.bumps.config_account;
config_account.governance_authority = global_config.governance_authority;
config_account.pyth_token_mint = global_config.pyth_token_mint;
config_account.pyth_governance_realm = global_config.pyth_governance_realm;
config_account.unlocking_duration = global_config.unlocking_duration;
config_account.epoch_duration = global_config.epoch_duration;
config_account.freeze = global_config.freeze;
config_account.pda_authority = global_config.pda_authority;
Expand Down Expand Up @@ -227,7 +225,6 @@ pub mod staking {
stake_account_custody.amount,
unvested_balance,
current_epoch,
config.unlocking_duration,
)?;

if let Some(target_account) = maybe_target_account {
Expand Down Expand Up @@ -262,7 +259,6 @@ pub mod staking {

stake_account_positions.merge_target_positions(
current_epoch,
config.unlocking_duration,
&mut stake_account_metadata.next_index,
target_with_parameters,
)?;
Expand Down Expand Up @@ -322,7 +318,7 @@ pub mod staking {
.checked_sub(amount)
.ok_or_else(|| error!(ErrorCode::AmountBiggerThanPosition))?;

match current_position.get_current_position(current_epoch, config.unlocking_duration)? {
match current_position.get_current_position(current_epoch)? {
PositionState::LOCKED => {
// If remaining amount is 0 keep only 1 position
if remaining_amount == 0 {
Expand Down Expand Up @@ -434,7 +430,6 @@ pub mod staking {
remaining_balance,
unvested_balance,
current_epoch,
config.unlocking_duration,
)
.is_err()
{
Expand All @@ -457,7 +452,6 @@ pub mod staking {
ctx.accounts.stake_account_custody.amount,
unvested_balance,
current_epoch,
config.unlocking_duration,
)
.is_err()
{
Expand Down Expand Up @@ -500,7 +494,6 @@ pub mod staking {
stake_account_custody.amount,
unvested_balance,
current_epoch,
config.unlocking_duration,
)?;

let epoch_of_snapshot: u64;
Expand Down Expand Up @@ -573,7 +566,6 @@ pub mod staking {
voter_record.voter_weight = compute_voter_weight(
stake_account_positions,
epoch_of_snapshot,
config.unlocking_duration,
governance_target.get_current_amount_locked(epoch_of_snapshot)?,
MAX_VOTER_WEIGHT,
)?;
Expand Down Expand Up @@ -688,7 +680,6 @@ pub mod staking {
config.pyth_token_list_time,
)?,
current_epoch,
config.unlocking_duration,
)?;

// Check that there aren't any positions (i.e., staked tokens) in the source account.
Expand Down Expand Up @@ -743,7 +734,6 @@ pub mod staking {
config.pyth_token_list_time,
)?,
current_epoch,
config.unlocking_duration,
)?;

utils::risk::validate(
Expand All @@ -757,7 +747,6 @@ pub mod staking {
config.pyth_token_list_time,
)?,
current_epoch,
config.unlocking_duration,
)?;

// Delete current request
Expand Down Expand Up @@ -817,15 +806,13 @@ pub mod staking {
let next_index = &mut ctx.accounts.stake_account_metadata.next_index;

let current_epoch = get_current_epoch(&ctx.accounts.config)?;
let unlocking_duration = ctx.accounts.config.unlocking_duration;

let SlashedAmounts {
total_slashed,
locked_slashed,
preunlocking_slashed,
} = stake_account_positions.slash_positions(
current_epoch,
unlocking_duration,
next_index,
ctx.accounts.stake_account_custody.amount,
publisher.key,
Expand Down
4 changes: 3 additions & 1 deletion staking/programs/staking/src/state/global_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ pub struct GlobalConfig {
pub governance_authority: Pubkey,
pub pyth_token_mint: Pubkey,
pub pyth_governance_realm: Pubkey,
// unlocking_duration is deprecated, but we need to keep it for account structure
pub unlocking_duration: u8,
pub epoch_duration: u64, // epoch duration in seconds
pub freeze: bool,
pub pda_authority: Pubkey, /* Authority that can authorize the transfer of locked
pub pda_authority: Pubkey, /* Authority that can authorize the transfer of
* locked
* tokens */
pub governance_program: Pubkey, // Governance program id

Expand Down
Loading
Loading