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

FIX + TESTS (STEWARD): Update Parameters #43

Merged
merged 9 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ test-ledger
**/targets
**/credentials
**/config
**/*.env
**/*.env
/scripts
2 changes: 1 addition & 1 deletion programs/steward/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ Administrators can:
| `instant_unstake_epoch_progress` | 0.90 | Point in epoch progress before instant unstake can be computed |
| `instant_unstake_inputs_epoch_progress` | 0.50 | Inputs to “Compute Instant Unstake” need to be updated past this point in epoch progress |
| `num_epochs_between_scoring` | 10 | Cycle length - Number of epochs to run the Monitor->Rebalance loop |
| `minimum_stake_lamports` | 5,000,000,000 | Minimum number of stake lamports for a validator to be considered for the pool |
| `minimum_stake_lamports` | 5,000,000,000,000 (5000 SOL) | Minimum number of stake lamports for a validator to be considered for the pool |
| `minimum_voting_epochs` | 5 | Minimum number of consecutive epochs a validator has to vote before it can be considered for the pool |

## Code and Tests
Expand Down
21 changes: 19 additions & 2 deletions programs/steward/src/instructions/initialize_config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anchor_lang::{prelude::*, solana_program::program::invoke};

use crate::{utils::StakePool, Config, Staker};
use crate::{utils::StakePool, Config, Staker, UpdateParametersArgs};

#[derive(Accounts)]
pub struct InitializeConfig<'info> {
Expand Down Expand Up @@ -39,11 +39,28 @@ pub struct InitializeConfig<'info> {
pub signer: Signer<'info>,
}

pub fn handler(ctx: Context<InitializeConfig>, authority: Pubkey) -> Result<()> {
pub fn handler(
ctx: Context<InitializeConfig>,
authority: Pubkey,
update_parameters_args: &UpdateParametersArgs,
) -> Result<()> {
let mut config = ctx.accounts.config.load_init()?;
config.stake_pool = ctx.accounts.stake_pool.key();
config.authority = authority;

// Set Initial Parameters
let max_slots_in_epoch = EpochSchedule::get()?.slots_per_epoch;
let current_epoch = Clock::get()?.epoch;

let initial_parameters = config.parameters.get_valid_updated_parameters(
update_parameters_args,
current_epoch,
max_slots_in_epoch,
)?;

config.parameters = initial_parameters;

// Set the staker account
ctx.accounts.staker.bump = ctx.bumps.staker;
invoke(
&spl_stake_pool::instruction::set_staker(
Expand Down
12 changes: 10 additions & 2 deletions programs/steward/src/instructions/update_parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,17 @@ pub fn handler(
ctx: Context<UpdateParameters>,
update_parameters_args: &UpdateParametersArgs,
) -> Result<()> {
let mut parameters = ctx.accounts.config.load_mut()?.parameters;
let mut config = ctx.accounts.config.load_mut()?;
let max_slots_in_epoch = EpochSchedule::get()?.slots_per_epoch;
let current_epoch = Clock::get()?.epoch;
parameters.update(update_parameters_args, current_epoch, max_slots_in_epoch)?;

let new_parameters = config.parameters.get_valid_updated_parameters(
update_parameters_args,
current_epoch,
max_slots_in_epoch,
)?;

config.parameters = new_parameters;

Ok(())
}
8 changes: 6 additions & 2 deletions programs/steward/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ pub mod steward {

// Initializes Config and Staker accounts. Must be called before any other instruction
// Requires Pool to be initialized
pub fn initialize_config(ctx: Context<InitializeConfig>, authority: Pubkey) -> Result<()> {
instructions::initialize_config::handler(ctx, authority)
pub fn initialize_config(
ctx: Context<InitializeConfig>,
authority: Pubkey,
update_parameters_args: UpdateParametersArgs,
) -> Result<()> {
instructions::initialize_config::handler(ctx, authority, &update_parameters_args)
}

/// Creates state account
Expand Down
17 changes: 9 additions & 8 deletions programs/steward/src/state/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
errors::StewardError,
};

#[derive(BorshSerialize, BorshDeserialize, Debug, Default)]
#[derive(BorshSerialize, BorshDeserialize, Debug, Default, Clone)]
pub struct UpdateParametersArgs {
// Scoring parameters
pub mev_commission_range: Option<u16>,
Expand Down Expand Up @@ -101,13 +101,13 @@ pub struct Parameters {
}

impl Parameters {
/// Update parameters that are present in the args struct and validates them
pub fn update(
&mut self,
/// Merges the updated parameters with the current parameters and validates them
pub fn get_valid_updated_parameters(
self,
args: &UpdateParametersArgs,
current_epoch: u64,
slots_per_epoch: u64,
) -> Result<()> {
) -> Result<Parameters> {
// Updates parameters and validates them
let UpdateParametersArgs {
mev_commission_range,
Expand All @@ -130,7 +130,7 @@ impl Parameters {
minimum_voting_epochs,
} = *args;

let mut new_parameters = *self;
let mut new_parameters = self;

if let Some(mev_commission_range) = mev_commission_range {
new_parameters.mev_commission_range = mev_commission_range;
Expand Down Expand Up @@ -209,9 +209,10 @@ impl Parameters {
new_parameters.minimum_voting_epochs = minimum_voting_epochs;
}

// Validation will throw an error if any of the parameters are invalid
new_parameters.validate(current_epoch, slots_per_epoch)?;
*self = new_parameters;
Ok(())

Ok(new_parameters)
}

/// Validate reasonable bounds on parameters
Expand Down
35 changes: 34 additions & 1 deletion tests/src/steward_fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use jito_steward::{
constants::{MAX_VALIDATORS, SORTED_INDEX_DEFAULT, STAKE_POOL_WITHDRAW_SEED},
utils::StakePool,
Config, Delegation, Parameters, Staker, StewardState, StewardStateAccount, StewardStateEnum,
UpdateParametersArgs,
};
use solana_program_test::*;
use solana_sdk::{
Expand Down Expand Up @@ -231,7 +232,29 @@ impl TestFixture {
}
}

pub async fn initialize_config(&self) {
pub async fn initialize_config(&self, parameters: Option<UpdateParametersArgs>) {
// Default parameters from JIP
let update_parameters_args = parameters.unwrap_or(UpdateParametersArgs {
mev_commission_range: Some(0), // Set to pass validation, where epochs starts at 0
epoch_credits_range: Some(0), // Set to pass validation, where epochs starts at 0
commission_range: Some(0), // Set to pass validation, where epochs starts at 0
scoring_delinquency_threshold_ratio: Some(0.85),
instant_unstake_delinquency_threshold_ratio: Some(0.70),
mev_commission_bps_threshold: Some(1000),
commission_threshold: Some(5),
historical_commission_threshold: Some(50),
num_delegation_validators: Some(200),
scoring_unstake_cap_bps: Some(750),
instant_unstake_cap_bps: Some(10),
stake_deposit_unstake_cap_bps: Some(10),
instant_unstake_epoch_progress: Some(0.90),
compute_score_slot_range: Some(1000),
instant_unstake_inputs_epoch_progress: Some(0.50),
num_epochs_between_scoring: Some(10),
minimum_stake_lamports: Some(5_000_000_000),
minimum_voting_epochs: Some(0), // Set to pass validation, where epochs starts at 0
});

let instruction = Instruction {
program_id: jito_steward::id(),
accounts: jito_steward::accounts::InitializeConfig {
Expand All @@ -245,6 +268,7 @@ impl TestFixture {
.to_account_metas(None),
data: jito_steward::instruction::InitializeConfig {
authority: self.keypair.pubkey(),
update_parameters_args,
}
.data(),
};
Expand Down Expand Up @@ -579,6 +603,15 @@ pub fn new_vote_account(
}
}

pub fn closed_vote_account() -> Account {
Account {
lamports: 0,
data: vec![0; VoteState::size_of()],
owner: anchor_lang::system_program::ID, // Close the account
..Account::default()
}
}

// TODO write a function to serialize any account with T: AnchorSerialize
pub fn serialized_validator_list_account(
validator_list: ValidatorList,
Expand Down
1 change: 1 addition & 0 deletions tests/tests/steward/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod test_algorithms;
mod test_integration;
mod test_parameters;
mod test_spl_passthrough;
mod test_state_methods;
mod test_state_transitions;
Expand Down
38 changes: 30 additions & 8 deletions tests/tests/steward/test_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use anchor_lang::{
use jito_steward::{
constants::{MAX_VALIDATORS, SORTED_INDEX_DEFAULT},
utils::{StakePool, ValidatorList},
Config, Delegation, StewardStateAccount, StewardStateEnum,
Config, Delegation, StewardStateAccount, StewardStateEnum, UpdateParametersArgs,
};
use solana_program_test::*;
use solana_sdk::{
Expand Down Expand Up @@ -36,7 +36,7 @@ async fn test_compute_delegations() {
let fixture = TestFixture::new().await;
let ctx = &fixture.ctx;
fixture.initialize_stake_pool().await;
fixture.initialize_config().await;
fixture.initialize_config(None).await;
fixture.initialize_steward_state().await;

let clock: Clock = fixture.get_sysvar().await;
Expand Down Expand Up @@ -173,7 +173,7 @@ async fn test_compute_scores() {
let fixture = TestFixture::new().await;
let ctx = &fixture.ctx;
fixture.initialize_stake_pool().await;
fixture.initialize_config().await;
fixture.initialize_config(None).await;
fixture.initialize_steward_state().await;

let epoch_credits = vec![(0, 1, 0), (1, 2, 1), (2, 3, 2), (3, 4, 3), (4, 5, 4)];
Expand Down Expand Up @@ -422,7 +422,28 @@ async fn test_compute_instant_unstake() {
let fixture = TestFixture::new().await;
let ctx = &fixture.ctx;
fixture.initialize_stake_pool().await;
fixture.initialize_config().await;
fixture
.initialize_config(Some(UpdateParametersArgs {
mev_commission_range: Some(0), // Set to pass validation, where epochs starts at 0
epoch_credits_range: Some(0), // Set to pass validation, where epochs starts at 0
commission_range: Some(0), // Set to pass validation, where epochs starts at 0
scoring_delinquency_threshold_ratio: Some(0.85),
instant_unstake_delinquency_threshold_ratio: Some(0.70),
mev_commission_bps_threshold: Some(1000),
commission_threshold: Some(5),
historical_commission_threshold: Some(50),
num_delegation_validators: Some(200),
scoring_unstake_cap_bps: Some(750),
instant_unstake_cap_bps: Some(10),
stake_deposit_unstake_cap_bps: Some(10),
instant_unstake_epoch_progress: Some(0.0), // So that we don't have to increase the slots
compute_score_slot_range: Some(1000),
instant_unstake_inputs_epoch_progress: Some(0.50),
num_epochs_between_scoring: Some(10),
minimum_stake_lamports: Some(5_000_000_000),
minimum_voting_epochs: Some(0), // Set to pass validation, where epochs starts at 0
}))
.await;
fixture.initialize_steward_state().await;

let epoch_credits = vec![(0, 1, 0), (1, 2, 1), (2, 3, 2), (3, 4, 3), (4, 5, 4)];
Expand All @@ -435,6 +456,7 @@ async fn test_compute_instant_unstake() {

let clock: Clock = fixture.get_sysvar().await;
let epoch_schedule: EpochSchedule = fixture.get_sysvar().await;

fixture.ctx.borrow_mut().set_account(
&vote_account,
&new_vote_account(Pubkey::new_unique(), vote_account, 100, Some(epoch_credits)).into(),
Expand Down Expand Up @@ -635,7 +657,7 @@ async fn test_idle() {
let fixture = TestFixture::new().await;
let ctx = &fixture.ctx;
fixture.initialize_stake_pool().await;
fixture.initialize_config().await;
fixture.initialize_config(None).await;
fixture.initialize_steward_state().await;

let clock: Clock = fixture.get_sysvar().await;
Expand Down Expand Up @@ -771,7 +793,7 @@ async fn test_rebalance_increase() {
.advance_num_epochs(epoch_schedule.first_normal_epoch - clock.epoch, 10)
.await;
fixture.initialize_stake_pool().await;
fixture.initialize_config().await;
fixture.initialize_config(None).await;
fixture.initialize_steward_state().await;

let mut steward_config: Config = fixture
Expand Down Expand Up @@ -1009,7 +1031,7 @@ async fn test_rebalance_decrease() {
.advance_num_epochs(epoch_schedule.first_normal_epoch - clock.epoch, 10)
.await;
fixture.initialize_stake_pool().await;
fixture.initialize_config().await;
fixture.initialize_config(None).await;
fixture.initialize_steward_state().await;

let mut steward_config: Config = fixture
Expand Down Expand Up @@ -1311,7 +1333,7 @@ async fn test_rebalance_other_cases() {
.advance_num_epochs(epoch_schedule.first_normal_epoch - clock.epoch, 10)
.await;
fixture.initialize_stake_pool().await;
fixture.initialize_config().await;
fixture.initialize_config(None).await;
fixture.initialize_steward_state().await;

let mut steward_config: Config = fixture
Expand Down
Loading