-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathcompute_instant_unstake.rs
110 lines (96 loc) · 3.32 KB
/
compute_instant_unstake.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use crate::{
constants::TVC_MAINNET_ACTIVATION_EPOCH,
errors::StewardError,
maybe_transition,
utils::{get_validator_list, get_validator_stake_info_at_index, state_checks},
Config, StewardStateAccount, StewardStateEnum,
};
use anchor_lang::prelude::*;
use spl_pod::solana_program::feature::Feature;
use validator_history::{ClusterHistory, ValidatorHistory};
#[derive(Accounts)]
pub struct ComputeInstantUnstake<'info> {
pub config: AccountLoader<'info, Config>,
#[account(
mut,
seeds = [StewardStateAccount::SEED, config.key().as_ref()],
bump
)]
pub state_account: AccountLoader<'info, StewardStateAccount>,
/// CHECK: We check it is the correct vote account in the handler
pub validator_history: AccountLoader<'info, ValidatorHistory>,
#[account(address = get_validator_list(&config)?)]
/// CHECK: We check against the Config
pub validator_list: AccountInfo<'info>,
#[account(
seeds = [ClusterHistory::SEED],
seeds::program = validator_history::id(),
bump
)]
pub cluster_history: AccountLoader<'info, ClusterHistory>,
pub maybe_tvc_feature_account: Option<AccountInfo<'info>>,
}
pub fn handler(ctx: Context<ComputeInstantUnstake>, validator_list_index: usize) -> Result<()> {
let config = ctx.accounts.config.load()?;
let mut state_account = ctx.accounts.state_account.load_mut()?;
let validator_history = ctx.accounts.validator_history.load()?;
let cluster = ctx.accounts.cluster_history.load()?;
let validator_list = &ctx.accounts.validator_list;
let clock = Clock::get()?;
let epoch_schedule = EpochSchedule::get()?;
let tvc_activation_epoch = {
if let Some(tvc_feature_account) = ctx.accounts.maybe_tvc_feature_account.as_ref() {
let activation_slot = Feature::from_account_info(tvc_feature_account)?.activated_at;
if let Some(activation_slot) = activation_slot {
epoch_schedule.get_epoch(activation_slot)
} else {
TVC_MAINNET_ACTIVATION_EPOCH
}
} else {
TVC_MAINNET_ACTIVATION_EPOCH
}
};
// Transitions to Idle before doing compute_instant_unstake if RESET_TO_IDLE is set
if let Some(event) = maybe_transition(
&mut state_account.state,
&clock,
&config.parameters,
&epoch_schedule,
)? {
emit!(event);
return Ok(());
}
state_checks(
&clock,
&config,
&state_account,
&ctx.accounts.validator_list,
Some(StewardStateEnum::ComputeInstantUnstake),
)?;
let validator_stake_info =
get_validator_stake_info_at_index(validator_list, validator_list_index)?;
require!(
validator_stake_info.vote_account_address == validator_history.vote_account,
StewardError::ValidatorNotInList
);
if let Some(instant_unstake) = state_account.state.compute_instant_unstake(
&clock,
&epoch_schedule,
&validator_history,
validator_list_index,
&cluster,
&config,
tvc_activation_epoch,
)? {
emit!(instant_unstake);
}
if let Some(event) = maybe_transition(
&mut state_account.state,
&clock,
&config.parameters,
&epoch_schedule,
)? {
emit!(event);
}
Ok(())
}