Protocol Architecture
A comprehensive guide to building a secure and scalable liquid staking protocol on Solana. Learn about core components, state management, security considerations, and best practices.
Protocol Architecture Overview
A liquid staking protocol on Solana enables users to stake their SOL while maintaining liquidity through tokenization. This guide provides a comprehensive overview of the architecture required to build a secure, efficient, and scalable liquid staking protocol.
The diagram above illustrates the key components and their interactions within the protocol architecture.
Key Features
- •Tokenized staking (stSOL)
- •Automated validator management
- •Efficient reward distribution
- •Slashing protection
Protocol Benefits
- •Enhanced capital efficiency
- •Reduced staking complexity
- •DeFi composability
- •Risk diversification
Core Protocol Components
A liquid staking protocol consists of several core components that work together to provide secure and efficient staking services. Understanding these components and their interactions is crucial for successful implementation.
1. Stake Pool Program
The central program that manages stake accounts and coordinates all protocol operations.
Stake Pool State
1#[account]
2pub struct StakePool {
3 /// Protocol version for upgrade management
4 pub version: u8,
5
6 /// Manager authority for admin operations
7 pub manager: Pubkey,
8
9 /// Staker authority for validator management
10 pub staker: Pubkey,
11
12 /// Withdraw authority for stake accounts
13 pub withdraw_authority: Pubkey,
14
15 /// Validator list storage account
16 pub validator_list: Pubkey,
17
18 /// Reserve stake account for rebalancing
19 pub reserve_stake: Pubkey,
20
21 /// Pool token mint
22 pub pool_mint: Pubkey,
23
24 /// Manager fee account
25 pub manager_fee_account: Pubkey,
26
27 /// Total pool stake in lamports
28 pub total_lamports: u64,
29
30 /// Total supply of pool tokens
31 pub pool_token_supply: u64,
32
33 /// Last epoch stake pool was updated
34 pub last_update_epoch: u64,
35
36 /// Fee taken as a percentage of rewards
37 pub epoch_fee: Fee,
38
39 /// Fee for SOL withdrawal
40 pub sol_withdrawal_fee: Fee,
41
42 /// Fee for stake withdrawal
43 pub stake_withdrawal_fee: Fee,
44
45 /// Next epoch's fees if an update is pending
46 pub next_epoch_fee: Option<Fee>,
47
48 /// Preferred deposit validator
49 pub preferred_deposit_validator: Option<Pubkey>,
50
51 /// Preferred withdraw validator
52 pub preferred_withdraw_validator: Option<Pubkey>,
53
54 /// Emergency shutdown flag
55 pub is_emergency_shutdown: bool,
56}
2. Validator List
Manages the list of validators and their stake accounts.
Validator List
1#[account]
2pub struct ValidatorList {
3 /// Account type, must be ValidatorList currently
4 pub account_type: AccountType,
5
6 /// Maximum number of validators
7 pub max_validators: u32,
8
9 /// List of stake info for each validator
10 pub validators: Vec<ValidatorStakeInfo>,
11}
12
13#[derive(Clone, Debug, Default, PartialEq)]
14pub struct ValidatorStakeInfo {
15 /// Validator vote account address
16 pub vote_account_address: Pubkey,
17
18 /// Active stake amount
19 pub active_stake_lamports: u64,
20
21 /// Transient stake amount
22 pub transient_stake_lamports: u64,
23
24 /// Last update epoch
25 pub last_update_epoch: u64,
26
27 /// Validator status (active, delinquent, emergency, etc.)
28 pub status: ValidatorStatus,
29
30 /// Validator score for ranking
31 pub score: Option<u32>,
32}
3. Liquid Staking Token
The SPL token that represents staked SOL (stSOL).
Token Setup
1import {
2 Token,
3 TOKEN_PROGRAM_ID,
4 MintLayout,
5} from '@solana/spl-token'
6
7async function setupStakeToken(
8 connection: Connection,
9 payer: Keypair,
10 mintAuthority: PublicKey,
11 decimals: number = 9,
12) {
13 // Create mint account
14 const mintRent = await connection.getMinimumBalanceForRentExemption(
15 MintLayout.span
16 )
17 const mintAccount = Keypair.generate()
18
19 const createMintAccountIx = SystemProgram.createAccount({
20 fromPubkey: payer.publicKey,
21 newAccountPubkey: mintAccount.publicKey,
22 lamports: mintRent,
23 space: MintLayout.span,
24 programId: TOKEN_PROGRAM_ID,
25 })
26
27 const initMintIx = Token.createInitMintInstruction(
28 TOKEN_PROGRAM_ID,
29 mintAccount.publicKey,
30 decimals,
31 mintAuthority,
32 mintAuthority // Freeze authority (optional)
33 )
34
35 const tx = new Transaction()
36 .add(createMintAccountIx)
37 .add(initMintIx)
38
39 await connection.sendTransaction(tx, [payer, mintAccount])
40
41 return mintAccount.publicKey
42}
4. Fee Management
Handles protocol fees and reward distribution.
Fee Structure
1#[derive(Clone, Copy, Debug, Default, PartialEq)]
2pub struct Fee {
3 pub numerator: u64,
4 pub denominator: u64,
5}
6
7impl Fee {
8 pub fn calculate(&self, amount: u64) -> Option<u64> {
9 if self.denominator == 0 {
10 return None;
11 }
12 Some(amount
13 .checked_mul(self.numerator)?
14 .checked_div(self.denominator)?)
15 }
16
17 pub fn is_valid(&self) -> bool {
18 self.numerator <= self.denominator && self.denominator > 0
19 }
20}
21
22pub fn process_fees(
23 stake_pool: &mut StakePool,
24 reward_amount: u64,
25) -> Result<u64, ProgramError> {
26 // Calculate protocol fee
27 let fee = stake_pool.epoch_fee
28 .calculate(reward_amount)
29 .ok_or(StakePoolError::CalculationFailure)?;
30
31 // Calculate user reward
32 let user_reward = reward_amount
33 .checked_sub(fee)
34 .ok_or(StakePoolError::CalculationFailure)?;
35
36 // Update pool state
37 stake_pool.total_lamports = stake_pool.total_lamports
38 .checked_add(reward_amount)
39 .ok_or(StakePoolError::CalculationFailure)?;
40
41 Ok(user_reward)
42}
Implementation Considerations
State Management
Proper state management is crucial for maintaining protocol security and consistency. This section covers the different states your protocol can be in and how to manage transitions between them.
Diagram: Protocol state transitions and operations
1. Protocol States
Define the possible states and their characteristics.
Protocol States
1#[derive(Clone, Debug, PartialEq)]
2pub enum ProtocolState {
3 /// Initial state before protocol is fully configured
4 Uninitialized,
5
6 /// Normal operation state
7 Active,
8
9 /// Deposits and withdrawals temporarily suspended
10 Paused,
11
12 /// Emergency state with restricted operations
13 Frozen,
14}
15
16#[derive(Clone, Debug, PartialEq)]
17pub enum ValidatorState {
18 /// Validator is active and accepting stakes
19 Active,
20
21 /// Validator is temporarily delinquent
22 Delinquent,
23
24 /// Validator is being removed
25 Removing,
26
27 /// Emergency state due to slashing or other issues
28 Emergency,
29}
30
31#[derive(Clone, Debug, PartialEq)]
32pub struct ProtocolStatus {
33 /// Current protocol state
34 pub state: ProtocolState,
35
36 /// Timestamp of last state change
37 pub last_state_change: i64,
38
39 /// Authority that triggered last state change
40 pub last_state_authority: Pubkey,
41
42 /// Reason for current state
43 pub state_reason: Option<String>,
44
45 /// Emergency contact if in Frozen state
46 pub emergency_contact: Option<String>,
47}
2. State Transitions
Implement secure state transitions with proper validation.
State Transitions
1pub fn process_state_transition(
2 program_id: &Pubkey,
3 accounts: &[AccountInfo],
4 new_state: ProtocolState,
5 reason: Option<String>,
6) -> ProgramResult {
7 let account_info_iter = &mut accounts.iter();
8
9 // Get accounts
10 let stake_pool = next_account_info(account_info_iter)?;
11 let authority = next_account_info(account_info_iter)?;
12
13 // Verify authority
14 if !authority.is_signer {
15 return Err(StakePoolError::SignatureMissing.into());
16 }
17
18 // Load stake pool
19 let mut pool_data = StakePool::try_from_slice(&stake_pool.data.borrow())?;
20
21 // Verify transition is valid
22 match (pool_data.state, new_state) {
23 // Allow transition from Uninitialized to Active
24 (ProtocolState::Uninitialized, ProtocolState::Active) => {
25 verify_pool_setup(&pool_data)?;
26 },
27
28 // Allow transition from Active to Paused
29 (ProtocolState::Active, ProtocolState::Paused) => {
30 verify_authority(authority, &pool_data.manager)?;
31 },
32
33 // Allow transition from Paused to Active
34 (ProtocolState::Paused, ProtocolState::Active) => {
35 verify_authority(authority, &pool_data.manager)?;
36 verify_safe_resume(&pool_data)?;
37 },
38
39 // Allow transition to Frozen only from Paused
40 (ProtocolState::Paused, ProtocolState::Frozen) => {
41 verify_authority(authority, &pool_data.manager)?;
42 verify_emergency_conditions(&pool_data)?;
43 },
44
45 // All other transitions are invalid
46 _ => return Err(StakePoolError::InvalidStateTransition.into()),
47 }
48
49 // Update state
50 pool_data.state = new_state;
51 pool_data.last_state_change = Clock::get()?.unix_timestamp;
52 pool_data.last_state_authority = *authority.key;
53 pool_data.state_reason = reason;
54
55 // Save updated state
56 pool_data.serialize(&mut *stake_pool.data.borrow_mut())?;
57
58 // Emit state change event
59 emit!(StateChanged {
60 stake_pool: *stake_pool.key,
61 old_state: pool_data.state,
62 new_state,
63 timestamp: pool_data.last_state_change,
64 authority: *authority.key,
65 });
66
67 Ok(())
68}
3. State-Specific Operations
Implement operations that are only allowed in specific states.
State-Specific Operations
1impl StakePool {
2 pub fn verify_operation_allowed(
3 &self,
4 operation: PoolOperation,
5 ) -> ProgramResult {
6 match (self.state, operation) {
7 // Active state operations
8 (ProtocolState::Active, PoolOperation::Deposit) => Ok(()),
9 (ProtocolState::Active, PoolOperation::Withdraw) => Ok(()),
10 (ProtocolState::Active, PoolOperation::UpdateValidatorList) => Ok(()),
11
12 // Paused state operations
13 (ProtocolState::Paused, PoolOperation::EmergencyUnstake) => Ok(()),
14 (ProtocolState::Paused, PoolOperation::UpdateValidatorList) => Ok(()),
15
16 // Frozen state operations
17 (ProtocolState::Frozen, PoolOperation::EmergencyUnstake) => Ok(()),
18
19 // All other operations are not allowed
20 _ => Err(StakePoolError::OperationNotAllowed.into()),
21 }
22 }
23
24 pub fn process_operation(
25 &mut self,
26 operation: PoolOperation,
27 accounts: &[AccountInfo],
28 ) -> ProgramResult {
29 // Verify operation is allowed in current state
30 self.verify_operation_allowed(operation)?;
31
32 // Process operation
33 match operation {
34 PoolOperation::Deposit => self.process_deposit(accounts),
35 PoolOperation::Withdraw => self.process_withdraw(accounts),
36 PoolOperation::UpdateValidatorList => self.update_validator_list(accounts),
37 PoolOperation::EmergencyUnstake => self.emergency_unstake(accounts),
38 }
39 }
40}
State Management Best Practices
Security Model
Security is paramount in liquid staking protocols. This section outlines the key security considerations and implementation patterns to protect user funds and ensure protocol stability.
1. Access Control
Implement robust access control mechanisms to protect sensitive operations.
Access Control Implementation
1#[derive(Clone, Debug, PartialEq)]
2pub enum AuthorityType {
3 Manager, // Protocol admin
4 Staker, // Validator management
5 Depositor, // User deposits
6 Emergency, // Emergency operations
7}
8
9pub struct AccessControl {
10 /// Manager authority (protocol admin)
11 pub manager: Pubkey,
12
13 /// Staker authority (validator management)
14 pub staker: Pubkey,
15
16 /// Emergency authority
17 pub emergency: Pubkey,
18
19 /// Pending authority changes
20 pub pending_authorities: Option<PendingAuthorities>,
21}
22
23impl AccessControl {
24 pub fn verify_authority(
25 &self,
26 authority: &AccountInfo,
27 authority_type: AuthorityType,
28 ) -> ProgramResult {
29 // Verify authority is a signer
30 if !authority.is_signer {
31 return Err(StakePoolError::SignatureMissing.into());
32 }
33
34 // Verify authority matches expected
35 match authority_type {
36 AuthorityType::Manager => {
37 if authority.key != &self.manager {
38 return Err(StakePoolError::InvalidManagerAuthority.into());
39 }
40 }
41 AuthorityType::Staker => {
42 if authority.key != &self.staker {
43 return Err(StakePoolError::InvalidStakerAuthority.into());
44 }
45 }
46 AuthorityType::Emergency => {
47 if authority.key != &self.emergency {
48 return Err(StakePoolError::InvalidEmergencyAuthority.into());
49 }
50 }
51 _ => return Err(StakePoolError::InvalidAuthorityType.into()),
52 }
53
54 Ok(())
55 }
56
57 pub fn change_authority(
58 &mut self,
59 current_authority: &AccountInfo,
60 new_authority: Pubkey,
61 authority_type: AuthorityType,
62 require_delay: bool,
63 ) -> ProgramResult {
64 // Verify current authority
65 self.verify_authority(current_authority, authority_type.clone())?;
66
67 if require_delay {
68 // Set pending change with delay
69 self.pending_authorities = Some(PendingAuthorities {
70 authority_type,
71 new_authority,
72 effective_epoch: Clock::get()?.epoch.checked_add(2).unwrap(),
73 });
74 } else {
75 // Apply change immediately
76 match authority_type {
77 AuthorityType::Manager => self.manager = new_authority,
78 AuthorityType::Staker => self.staker = new_authority,
79 AuthorityType::Emergency => self.emergency = new_authority,
80 _ => return Err(StakePoolError::InvalidAuthorityType.into()),
81 }
82 }
83
84 Ok(())
85 }
86}
2. Secure State Management
Implement secure state transitions and data validation.
State Validation
1pub fn validate_and_update_state(
2 stake_pool: &mut StakePool,
3 validator_list: &mut ValidatorList,
4 clock: &Clock,
5) -> ProgramResult {
6 // Verify stake pool is initialized
7 if !stake_pool.is_initialized {
8 return Err(StakePoolError::InvalidState.into());
9 }
10
11 // Verify total stake matches validator stakes
12 let total_validator_stake = validator_list.validators
13 .iter()
14 .map(|v| v.active_stake_lamports)
15 .sum::<u64>();
16
17 if total_validator_stake != stake_pool.total_lamports {
18 return Err(StakePoolError::StakeTokenSupplyMismatch.into());
19 }
20
21 // Verify pool token supply matches stake
22 if stake_pool.pool_token_supply == 0 && stake_pool.total_lamports > 0 {
23 return Err(StakePoolError::InvalidState.into());
24 }
25
26 // Update epoch if needed
27 if clock.epoch > stake_pool.last_update_epoch {
28 stake_pool.last_update_epoch = clock.epoch;
29
30 // Apply any pending authority changes
31 if let Some(pending) = stake_pool.pending_authorities.take() {
32 if clock.epoch >= pending.effective_epoch {
33 match pending.authority_type {
34 AuthorityType::Manager => stake_pool.manager = pending.new_authority,
35 AuthorityType::Staker => stake_pool.staker = pending.new_authority,
36 AuthorityType::Emergency => stake_pool.emergency = pending.new_authority,
37 _ => return Err(StakePoolError::InvalidAuthorityType.into()),
38 }
39 } else {
40 stake_pool.pending_authorities = Some(pending);
41 }
42 }
43 }
44
45 Ok(())
46}
3. Slashing Protection
Implement mechanisms to protect against validator misbehavior.
Slashing Protection
1pub struct ValidatorMonitor {
2 /// Maximum consecutive missed blocks
3 pub max_consecutive_misses: u64,
4
5 /// Minimum required uptime percentage
6 pub min_uptime_percentage: u8,
7
8 /// Maximum commission percentage
9 pub max_commission: u8,
10}
11
12impl ValidatorMonitor {
13 pub fn check_validator_health(
14 &self,
15 validator: &ValidatorStakeInfo,
16 vote_account: &VoteAccountInfo,
17 ) -> Result<ValidatorStatus, StakePoolError> {
18 // Check consecutive missed blocks
19 if vote_account.consecutive_missed_blocks > self.max_consecutive_misses {
20 return Ok(ValidatorStatus::Delinquent);
21 }
22
23 // Check uptime
24 let uptime_percentage = calculate_uptime_percentage(vote_account);
25 if uptime_percentage < self.min_uptime_percentage as f64 {
26 return Ok(ValidatorStatus::Delinquent);
27 }
28
29 // Check commission hasn't increased beyond max
30 if vote_account.commission > self.max_commission {
31 return Ok(ValidatorStatus::Delinquent);
32 }
33
34 // Check for slashing events
35 if vote_account.has_been_slashed {
36 return Ok(ValidatorStatus::Emergency);
37 }
38
39 Ok(ValidatorStatus::Active)
40 }
41
42 pub fn handle_validator_emergency(
43 &self,
44 stake_pool: &mut StakePool,
45 validator: &Pubkey,
46 ) -> ProgramResult {
47 // Move stake to emergency reserve
48 stake_pool.emergency_unstake(validator)?;
49
50 // Mark validator as emergency
51 stake_pool.update_validator_status(
52 validator,
53 ValidatorStatus::Emergency,
54 )?;
55
56 // Emit emergency event
57 emit!(ValidatorEmergency {
58 stake_pool: stake_pool.pubkey(),
59 validator: *validator,
60 timestamp: Clock::get()?.unix_timestamp,
61 });
62
63 Ok(())
64 }
65}
4. Rate Limiting
Implement rate limiting to prevent abuse and ensure system stability.
Rate Limiting
1pub struct RateLimiter {
2 /// Maximum deposits per epoch
3 pub max_epoch_deposits: u64,
4
5 /// Maximum withdrawals per epoch
6 pub max_epoch_withdrawals: u64,
7
8 /// Current epoch stats
9 pub epoch_stats: EpochStats,
10}
11
12impl RateLimiter {
13 pub fn check_deposit_limit(
14 &self,
15 amount: u64,
16 ) -> ProgramResult {
17 let current_epoch_deposits = self.epoch_stats
18 .total_deposits
19 .checked_add(amount)
20 .ok_or(StakePoolError::CalculationFailure)?;
21
22 if current_epoch_deposits > self.max_epoch_deposits {
23 return Err(StakePoolError::EpochDepositLimitExceeded.into());
24 }
25
26 Ok(())
27 }
28
29 pub fn check_withdrawal_limit(
30 &self,
31 amount: u64,
32 ) -> ProgramResult {
33 let current_epoch_withdrawals = self.epoch_stats
34 .total_withdrawals
35 .checked_add(amount)
36 .ok_or(StakePoolError::CalculationFailure)?;
37
38 if current_epoch_withdrawals > self.max_epoch_withdrawals {
39 return Err(StakePoolError::EpochWithdrawalLimitExceeded.into());
40 }
41
42 Ok(())
43 }
44
45 pub fn update_epoch_stats(
46 &mut self,
47 operation: PoolOperation,
48 amount: u64,
49 ) -> ProgramResult {
50 match operation {
51 PoolOperation::Deposit => {
52 self.epoch_stats.total_deposits = self.epoch_stats
53 .total_deposits
54 .checked_add(amount)
55 .ok_or(StakePoolError::CalculationFailure)?;
56 }
57 PoolOperation::Withdraw => {
58 self.epoch_stats.total_withdrawals = self.epoch_stats
59 .total_withdrawals
60 .checked_add(amount)
61 .ok_or(StakePoolError::CalculationFailure)?;
62 }
63 _ => {}
64 }
65
66 Ok(())
67 }
68}
Critical Security Considerations
Token Economics
A well-designed token economics model is crucial for protocol sustainability. This section covers token mechanics, exchange rates, and reward distribution.
1. Token Mechanics
Implement secure token minting and burning mechanisms.
Token Management
1pub struct TokenManager {
2 /// Pool token mint
3 pub pool_mint: Pubkey,
4
5 /// Mint authority
6 pub mint_authority: Pubkey,
7
8 /// Exchange rate (stSOL/SOL)
9 pub exchange_rate: ExchangeRate,
10
11 /// Fee schedule
12 pub fees: FeeSchedule,
13}
14
15impl TokenManager {
16 pub fn mint_tokens(
17 &self,
18 amount: u64,
19 destination: &Pubkey,
20 ) -> ProgramResult {
21 // Calculate token amount based on exchange rate
22 let token_amount = self.exchange_rate
23 .sol_to_st_sol(amount)?;
24
25 // Calculate fees
26 let fees = self.fees.calculate_mint_fees(amount)?;
27 let net_amount = token_amount.checked_sub(fees)
28 .ok_or(StakePoolError::CalculationFailure)?;
29
30 // Create mint instruction
31 let mint_ix = spl_token::instruction::mint_to(
32 &spl_token::id(),
33 &self.pool_mint,
34 destination,
35 &self.mint_authority,
36 &[],
37 net_amount,
38 )?;
39
40 // Process instruction
41 invoke_signed(
42 &mint_ix,
43 &[/* account infos */],
44 &[/* seeds */],
45 )?;
46
47 // Update exchange rate
48 self.exchange_rate.update_after_mint(amount, token_amount)?;
49
50 // Emit mint event
51 emit!(TokensMinted {
52 amount,
53 token_amount,
54 fees,
55 destination: *destination,
56 exchange_rate: self.exchange_rate,
57 });
58
59 Ok(())
60 }
61
62 pub fn burn_tokens(
63 &self,
64 token_amount: u64,
65 source: &Pubkey,
66 ) -> ProgramResult {
67 // Calculate SOL amount based on exchange rate
68 let sol_amount = self.exchange_rate
69 .st_sol_to_sol(token_amount)?;
70
71 // Calculate fees
72 let fees = self.fees.calculate_burn_fees(sol_amount)?;
73 let net_amount = sol_amount.checked_sub(fees)
74 .ok_or(StakePoolError::CalculationFailure)?;
75
76 // Create burn instruction
77 let burn_ix = spl_token::instruction::burn(
78 &spl_token::id(),
79 source,
80 &self.pool_mint,
81 &self.mint_authority,
82 &[],
83 token_amount,
84 )?;
85
86 // Process instruction
87 invoke_signed(
88 &burn_ix,
89 &[/* account infos */],
90 &[/* seeds */],
91 )?;
92
93 // Update exchange rate
94 self.exchange_rate.update_after_burn(sol_amount, token_amount)?;
95
96 // Emit burn event
97 emit!(TokensBurned {
98 sol_amount,
99 token_amount,
100 fees,
101 source: *source,
102 exchange_rate: self.exchange_rate,
103 });
104
105 Ok(())
106 }
107}
2. Exchange Rate
Implement accurate exchange rate calculation and updates.
Exchange Rate
1pub struct ExchangeRate {
2 /// Total SOL (including rewards)
3 pub total_sol: u64,
4
5 /// Total stSOL supply
6 pub total_st_sol: u64,
7
8 /// Last update epoch
9 pub last_update: u64,
10}
11
12impl ExchangeRate {
13 pub fn calculate_rate(&self) -> Result<f64, ProgramError> {
14 if self.total_st_sol == 0 {
15 return Ok(1.0);
16 }
17
18 Ok(self.total_sol as f64 / self.total_st_sol as f64)
19 }
20
21 pub fn sol_to_st_sol(&self, sol_amount: u64) -> Result<u64, ProgramError> {
22 let rate = self.calculate_rate()?;
23 Ok((sol_amount as f64 / rate) as u64)
24 }
25
26 pub fn st_sol_to_sol(&self, st_sol_amount: u64) -> Result<u64, ProgramError> {
27 let rate = self.calculate_rate()?;
28 Ok((st_sol_amount as f64 * rate) as u64)
29 }
30
31 pub fn update_with_rewards(
32 &mut self,
33 rewards: u64,
34 ) -> ProgramResult {
35 // Add rewards to total SOL
36 self.total_sol = self.total_sol
37 .checked_add(rewards)
38 .ok_or(StakePoolError::CalculationFailure)?;
39
40 // Update last update epoch
41 self.last_update = Clock::get()?.epoch;
42
43 // Emit rate update event
44 emit!(ExchangeRateUpdated {
45 total_sol: self.total_sol,
46 total_st_sol: self.total_st_sol,
47 rate: self.calculate_rate()?,
48 epoch: self.last_update,
49 });
50
51 Ok(())
52 }
53}
3. Fee Structure
Implement transparent fee calculation and distribution.
Fee Management
1pub struct FeeSchedule {
2 /// Protocol fee percentage
3 pub protocol_fee: Fee,
4
5 /// Validator commission
6 pub validator_fee: Fee,
7
8 /// Treasury fee
9 pub treasury_fee: Fee,
10
11 /// Deposit fee
12 pub deposit_fee: Fee,
13
14 /// Withdrawal fee
15 pub withdrawal_fee: Fee,
16}
17
18impl FeeSchedule {
19 pub fn calculate_mint_fees(&self, amount: u64) -> Result<u64, ProgramError> {
20 // Calculate deposit fee
21 let deposit_fee = self.deposit_fee
22 .calculate(amount)
23 .ok_or(StakePoolError::CalculationFailure)?;
24
25 // Calculate protocol fee
26 let protocol_fee = self.protocol_fee
27 .calculate(amount)
28 .ok_or(StakePoolError::CalculationFailure)?;
29
30 // Sum fees
31 deposit_fee
32 .checked_add(protocol_fee)
33 .ok_or(StakePoolError::CalculationFailure.into())
34 }
35
36 pub fn calculate_burn_fees(&self, amount: u64) -> Result<u64, ProgramError> {
37 // Calculate withdrawal fee
38 let withdrawal_fee = self.withdrawal_fee
39 .calculate(amount)
40 .ok_or(StakePoolError::CalculationFailure)?;
41
42 // Calculate protocol fee
43 let protocol_fee = self.protocol_fee
44 .calculate(amount)
45 .ok_or(StakePoolError::CalculationFailure)?;
46
47 // Sum fees
48 withdrawal_fee
49 .checked_add(protocol_fee)
50 .ok_or(StakePoolError::CalculationFailure.into())
51 }
52
53 pub fn distribute_fees(
54 &self,
55 total_fees: u64,
56 ) -> ProgramResult {
57 // Calculate fee shares
58 let protocol_share = (total_fees as f64 * 0.4) as u64; // 40%
59 let validator_share = (total_fees as f64 * 0.4) as u64; // 40%
60 let treasury_share = (total_fees as f64 * 0.2) as u64; // 20%
61
62 // Transfer to fee accounts
63 transfer_to_protocol_fee_account(protocol_share)?;
64 transfer_to_validator_fee_account(validator_share)?;
65 transfer_to_treasury_account(treasury_share)?;
66
67 Ok(())
68 }
69}
4. Reward Distribution
Implement efficient reward distribution mechanisms.
Reward Distribution
1pub struct RewardDistributor {
2 /// Distribution frequency
3 pub frequency: u64,
4
5 /// Last distribution epoch
6 pub last_distribution: u64,
7
8 /// Minimum distribution amount
9 pub min_distribution: u64,
10}
11
12impl RewardDistributor {
13 pub fn distribute_rewards(
14 &mut self,
15 stake_pool: &mut StakePool,
16 epoch_info: &EpochInfo,
17 ) -> ProgramResult {
18 // Check if distribution is needed
19 if !self.should_distribute(epoch_info)? {
20 return Ok(());
21 }
22
23 // Calculate total rewards
24 let total_rewards = calculate_epoch_rewards(stake_pool)?;
25
26 // Check minimum distribution
27 if total_rewards < self.min_distribution {
28 return Ok(());
29 }
30
31 // Calculate fee shares
32 let fees = stake_pool.fee_schedule
33 .calculate_reward_fees(total_rewards)?;
34
35 let net_rewards = total_rewards
36 .checked_sub(fees)
37 .ok_or(StakePoolError::CalculationFailure)?;
38
39 // Update exchange rate
40 stake_pool.exchange_rate
41 .update_with_rewards(net_rewards)?;
42
43 // Distribute fees
44 stake_pool.fee_schedule
45 .distribute_fees(fees)?;
46
47 // Update distribution state
48 self.last_distribution = epoch_info.epoch;
49
50 // Emit distribution event
51 emit!(RewardsDistributed {
52 total_rewards,
53 fees,
54 net_rewards,
55 epoch: epoch_info.epoch,
56 });
57
58 Ok(())
59 }
60}
Economic Model Best Practices
Validator Management
Effective validator management is crucial for protocol security and performance. This section covers validator selection, monitoring, and stake rebalancing strategies.
1. Validator Selection
Implement criteria-based validator selection with scoring mechanism.
Validator Selection
1pub struct ValidatorScore {
2 /// Vote account address
3 pub vote_account: Pubkey,
4
5 /// Base score (0-100)
6 pub base_score: u8,
7
8 /// Performance metrics
9 pub performance: ValidatorPerformance,
10
11 /// Risk metrics
12 pub risk_score: ValidatorRisk,
13}
14
15#[derive(Clone, Debug)]
16pub struct ValidatorPerformance {
17 /// Uptime percentage (0-100)
18 pub uptime: u8,
19
20 /// Average skip rate
21 pub skip_rate: f64,
22
23 /// Commission percentage
24 pub commission: u8,
25
26 /// Stake concentration
27 pub stake_concentration: f64,
28
29 /// Historical performance score
30 pub historical_performance: u8,
31}
32
33impl ValidatorScore {
34 pub fn calculate_score(&self) -> u8 {
35 let mut score = self.base_score;
36
37 // Adjust for performance
38 score = score
39 .checked_mul(self.performance.uptime)
40 .unwrap_or(0)
41 .checked_div(100)
42 .unwrap_or(0);
43
44 // Penalize for high skip rate
45 if self.performance.skip_rate > 0.01 {
46 score = score.saturating_sub(10);
47 }
48
49 // Penalize for high commission
50 if self.performance.commission > 10 {
51 score = score.saturating_sub(
52 self.performance.commission.saturating_sub(10)
53 );
54 }
55
56 // Penalize for stake concentration
57 if self.performance.stake_concentration > 0.1 {
58 score = score.saturating_sub(10);
59 }
60
61 score
62 }
63}
64
65pub fn select_validators(
66 validator_list: &[ValidatorScore],
67 max_validators: usize,
68 min_score: u8,
69) -> Vec<Pubkey> {
70 let mut selected = validator_list
71 .iter()
72 .filter(|v| v.calculate_score() >= min_score)
73 .collect::<Vec<_>>();
74
75 // Sort by score descending
76 selected.sort_by(|a, b| b.calculate_score().cmp(&a.calculate_score()));
77
78 // Take top N validators
79 selected.iter()
80 .take(max_validators)
81 .map(|v| v.vote_account)
82 .collect()
83}
2. Stake Rebalancing
Implement periodic stake rebalancing to maintain optimal distribution.
Stake Rebalancing
1pub struct StakeBalance {
2 /// Target stake amount per validator
3 pub target_stake: u64,
4
5 /// Maximum stake per validator
6 pub max_stake: u64,
7
8 /// Minimum stake per validator
9 pub min_stake: u64,
10
11 /// Maximum stake move per epoch
12 pub max_stake_move: u64,
13}
14
15impl StakeBalance {
16 pub fn calculate_rebalance(
17 &self,
18 validator_list: &[ValidatorStakeInfo],
19 total_stake: u64,
20 ) -> Vec<StakeMove> {
21 let mut stake_moves = Vec::new();
22 let active_validators = validator_list.len() as u64;
23
24 // Calculate ideal distribution
25 let target_stake = total_stake
26 .checked_div(active_validators)
27 .unwrap_or(0)
28 .min(self.max_stake)
29 .max(self.min_stake);
30
31 for validator in validator_list {
32 let current_stake = validator.active_stake_lamports;
33
34 if current_stake > target_stake {
35 // Need to decrease stake
36 let decrease = (current_stake - target_stake)
37 .min(self.max_stake_move);
38
39 if decrease > 0 {
40 stake_moves.push(StakeMove {
41 validator: validator.vote_account_address,
42 amount: decrease,
43 move_type: StakeMoveType::Decrease,
44 });
45 }
46 } else if current_stake < target_stake {
47 // Need to increase stake
48 let increase = (target_stake - current_stake)
49 .min(self.max_stake_move);
50
51 if increase > 0 {
52 stake_moves.push(StakeMove {
53 validator: validator.vote_account_address,
54 amount: increase,
55 move_type: StakeMoveType::Increase,
56 });
57 }
58 }
59 }
60
61 stake_moves
62 }
63}
3. Performance Monitoring
Implement continuous validator performance monitoring.
Performance Monitoring
1pub struct ValidatorMonitor {
2 /// Performance thresholds
3 pub thresholds: MonitorThresholds,
4
5 /// Historical performance data
6 pub history: ValidatorHistory,
7}
8
9impl ValidatorMonitor {
10 pub fn update_performance(
11 &mut self,
12 validator: &Pubkey,
13 epoch_stats: &EpochStats,
14 ) -> ValidatorStatus {
15 // Calculate performance metrics
16 let uptime = calculate_uptime(epoch_stats);
17 let skip_rate = calculate_skip_rate(epoch_stats);
18 let apy = calculate_apy(epoch_stats);
19
20 // Update historical data
21 self.history.update(validator, epoch_stats);
22
23 // Check against thresholds
24 if uptime < self.thresholds.min_uptime {
25 return ValidatorStatus::Delinquent;
26 }
27
28 if skip_rate > self.thresholds.max_skip_rate {
29 return ValidatorStatus::Delinquent;
30 }
31
32 if apy < self.thresholds.min_apy {
33 return ValidatorStatus::Underperforming;
34 }
35
36 ValidatorStatus::Active
37 }
38
39 pub fn get_validator_score(&self, validator: &Pubkey) -> u8 {
40 let history = self.history.get_validator_history(validator);
41
42 let mut score = 100u8;
43
44 // Reduce score for historical delinquencies
45 score = score.saturating_sub(
46 history.delinquency_count.saturating_mul(10)
47 );
48
49 // Reduce score for underperformance
50 score = score.saturating_sub(
51 history.underperforming_epochs.saturating_mul(5)
52 );
53
54 // Bonus for consistent performance
55 if history.consecutive_good_epochs > 10 {
56 score = score.saturating_add(10);
57 }
58
59 score
60 }
61}
4. Validator Removal
Implement secure validator removal process.
Validator Removal
1pub fn remove_validator(
2 program_id: &Pubkey,
3 accounts: &[AccountInfo],
4 validator: &Pubkey,
5) -> ProgramResult {
6 let account_info_iter = &mut accounts.iter();
7
8 // Get accounts
9 let stake_pool = next_account_info(account_info_iter)?;
10 let validator_list = next_account_info(account_info_iter)?;
11 let manager = next_account_info(account_info_iter)?;
12
13 // Verify manager authority
14 verify_authority(manager, stake_pool.manager)?;
15
16 // Find validator in list
17 let validator_info = validator_list
18 .find_validator(validator)
19 .ok_or(StakePoolError::ValidatorNotFound)?;
20
21 // Ensure no active stake
22 if validator_info.active_stake_lamports > 0 {
23 return Err(StakePoolError::ValidatorNotEmpty.into());
24 }
25
26 // Remove validator
27 validator_list.remove_validator(validator)?;
28
29 // Emit removal event
30 emit!(ValidatorRemoved {
31 stake_pool: *stake_pool.key,
32 validator: *validator,
33 timestamp: Clock::get()?.unix_timestamp,
34 });
35
36 Ok(())
37}
Management Best Practices
Reward Distribution
Efficient and fair reward distribution is crucial for protocol success. This section covers reward calculation, collection, and distribution mechanisms.
1. Reward Calculation
Implement accurate reward calculation mechanisms.
Reward Calculation
1pub struct RewardCalculator {
2 /// Protocol fee percentage (0-100)
3 pub protocol_fee: u8,
4
5 /// Treasury fee percentage (0-100)
6 pub treasury_fee: u8,
7
8 /// Minimum reward for distribution
9 pub min_reward: u64,
10}
11
12impl RewardCalculator {
13 pub fn calculate_rewards(
14 &self,
15 validator_rewards: &[ValidatorReward],
16 total_stake: u64,
17 ) -> Result<RewardDistribution, ProgramError> {
18 // Sum all validator rewards
19 let total_rewards = validator_rewards
20 .iter()
21 .map(|r| r.amount)
22 .sum::<u64>();
23
24 // Calculate protocol fee
25 let protocol_fee = (total_rewards as u128)
26 .checked_mul(self.protocol_fee as u128)
27 .and_then(|r| r.checked_div(100))
28 .and_then(|r| u64::try_from(r).ok())
29 .ok_or(StakePoolError::CalculationFailure)?;
30
31 // Calculate treasury fee
32 let treasury_fee = (total_rewards as u128)
33 .checked_mul(self.treasury_fee as u128)
34 .and_then(|r| r.checked_div(100))
35 .and_then(|r| u64::try_from(r).ok())
36 .ok_or(StakePoolError::CalculationFailure)?;
37
38 // Calculate user rewards
39 let user_rewards = total_rewards
40 .checked_sub(protocol_fee)?
41 .checked_sub(treasury_fee)?;
42
43 // Calculate reward rate
44 let reward_rate = (user_rewards as f64) / (total_stake as f64);
45
46 Ok(RewardDistribution {
47 total_rewards,
48 protocol_fee,
49 treasury_fee,
50 user_rewards,
51 reward_rate,
52 })
53 }
54}
2. Reward Collection
Implement secure reward collection from validators.
Reward Collection
1pub fn collect_validator_rewards(
2 program_id: &Pubkey,
3 accounts: &[AccountInfo],
4) -> ProgramResult {
5 let account_info_iter = &mut accounts.iter();
6
7 // Get accounts
8 let stake_pool = next_account_info(account_info_iter)?;
9 let validator_list = next_account_info(account_info_iter)?;
10 let reserve_stake = next_account_info(account_info_iter)?;
11 let staker = next_account_info(account_info_iter)?;
12
13 // Verify staker authority
14 verify_authority(staker, stake_pool.staker)?;
15
16 // Collect rewards from each validator
17 let mut total_rewards = 0;
18 for validator in validator_list.validators.iter() {
19 let validator_stake = next_account_info(account_info_iter)?;
20
21 // Withdraw rewards to reserve
22 let rewards = withdraw_stake_rewards(
23 validator_stake,
24 reserve_stake,
25 )?;
26
27 total_rewards = total_rewards.checked_add(rewards)
28 .ok_or(StakePoolError::CalculationFailure)?;
29 }
30
31 // Update pool metrics
32 stake_pool.total_lamports = stake_pool.total_lamports
33 .checked_add(total_rewards)
34 .ok_or(StakePoolError::CalculationFailure)?;
35
36 stake_pool.last_reward_collection = Clock::get()?.epoch;
37
38 // Emit collection event
39 emit!(RewardsCollected {
40 stake_pool: *stake_pool.key,
41 total_rewards,
42 epoch: stake_pool.last_reward_collection,
43 });
44
45 Ok(())
46}
3. Reward Distribution
Implement efficient reward distribution to token holders.
Reward Distribution
1pub struct RewardDistributor {
2 /// Minimum distribution amount
3 pub min_distribution: u64,
4
5 /// Distribution frequency (epochs)
6 pub distribution_frequency: u64,
7
8 /// Last distribution epoch
9 pub last_distribution: u64,
10}
11
12impl RewardDistributor {
13 pub fn distribute_rewards(
14 &mut self,
15 stake_pool: &mut StakePool,
16 calculator: &RewardCalculator,
17 ) -> ProgramResult {
18 let current_epoch = Clock::get()?.epoch;
19
20 // Check if distribution is needed
21 if current_epoch.saturating_sub(self.last_distribution)
22 < self.distribution_frequency {
23 return Ok(());
24 }
25
26 // Calculate rewards
27 let distribution = calculator.calculate_rewards(
28 &stake_pool.validator_rewards,
29 stake_pool.total_lamports,
30 )?;
31
32 // Check minimum distribution
33 if distribution.user_rewards < self.min_distribution {
34 return Ok(());
35 }
36
37 // Update pool token value
38 let new_pool_tokens = (distribution.user_rewards as f64
39 * stake_pool.pool_token_supply as f64
40 / stake_pool.total_lamports as f64) as u64;
41
42 stake_pool.pool_token_supply = stake_pool.pool_token_supply
43 .checked_add(new_pool_tokens)
44 .ok_or(StakePoolError::CalculationFailure)?;
45
46 // Transfer fees
47 transfer_protocol_fee(
48 stake_pool,
49 distribution.protocol_fee,
50 )?;
51
52 transfer_treasury_fee(
53 stake_pool,
54 distribution.treasury_fee,
55 )?;
56
57 // Update distribution state
58 self.last_distribution = current_epoch;
59
60 // Emit distribution event
61 emit!(RewardsDistributed {
62 stake_pool: stake_pool.pubkey(),
63 total_rewards: distribution.total_rewards,
64 user_rewards: distribution.user_rewards,
65 new_pool_tokens,
66 epoch: current_epoch,
67 });
68
69 Ok(())
70 }
71}
4. Fee Management
Implement transparent fee collection and management.
Fee Management
1pub struct FeeManager {
2 /// Protocol fee account
3 pub protocol_fee_account: Pubkey,
4
5 /// Treasury account
6 pub treasury_account: Pubkey,
7
8 /// Fee schedule
9 pub fee_schedule: FeeSchedule,
10}
11
12impl FeeManager {
13 pub fn update_fee_schedule(
14 &mut self,
15 new_schedule: FeeSchedule,
16 authority: &AccountInfo,
17 ) -> ProgramResult {
18 // Verify fee authority
19 verify_fee_authority(authority)?;
20
21 // Validate new fees
22 if !new_schedule.is_valid() {
23 return Err(StakePoolError::InvalidFeeSchedule.into());
24 }
25
26 // Schedule fee update for next epoch
27 self.fee_schedule.next_epoch_fees = Some(new_schedule);
28 self.fee_schedule.update_epoch = Clock::get()?.epoch + 1;
29
30 // Emit fee update event
31 emit!(FeeScheduleUpdated {
32 old_schedule: self.fee_schedule.clone(),
33 new_schedule,
34 effective_epoch: self.fee_schedule.update_epoch,
35 });
36
37 Ok(())
38 }
39
40 pub fn process_fees(
41 &self,
42 amount: u64,
43 ) -> Result<FeeBreakdown, ProgramError> {
44 self.fee_schedule.calculate_fees(amount)
45 }
46}
Distribution Best Practices
Protocol Upgradeability
Implementing secure upgrade mechanisms is crucial for protocol maintenance and evolution. This section covers upgrade patterns, safety measures, and best practices.
1. Program Upgrade Authority
Implement secure program upgrade authority management.
Upgrade Authority
1pub struct UpgradeAuthority {
2 /// Current authority
3 pub current_authority: Pubkey,
4
5 /// Pending authority change
6 pub pending_authority: Option<PendingAuthority>,
7
8 /// Upgrade timelock (epochs)
9 pub upgrade_timelock: u64,
10
11 /// Last upgrade epoch
12 pub last_upgrade: u64,
13}
14
15#[derive(Clone, Debug)]
16pub struct PendingAuthority {
17 /// New authority
18 pub new_authority: Pubkey,
19
20 /// Effective epoch
21 pub effective_epoch: u64,
22
23 /// Required confirmations
24 pub required_confirmations: u8,
25
26 /// Received confirmations
27 pub confirmations: Vec<Pubkey>,
28}
29
30impl UpgradeAuthority {
31 pub fn initiate_authority_change(
32 &mut self,
33 current_authority: &AccountInfo,
34 new_authority: Pubkey,
35 required_confirmations: u8,
36 ) -> ProgramResult {
37 // Verify current authority
38 if !current_authority.is_signer {
39 return Err(StakePoolError::SignatureMissing.into());
40 }
41 if current_authority.key != &self.current_authority {
42 return Err(StakePoolError::InvalidUpgradeAuthority.into());
43 }
44
45 // Set pending change
46 self.pending_authority = Some(PendingAuthority {
47 new_authority,
48 effective_epoch: Clock::get()?.epoch + self.upgrade_timelock,
49 required_confirmations,
50 confirmations: vec![],
51 });
52
53 // Emit event
54 emit!(AuthorityChangeInitiated {
55 old_authority: self.current_authority,
56 new_authority,
57 effective_epoch: self.pending_authority.as_ref().unwrap().effective_epoch,
58 });
59
60 Ok(())
61 }
62}
2. Program Upgrade Logic
Implement secure program upgrade mechanisms.
Program Upgrade
1pub struct ProgramUpgrade {
2 /// Buffer account holding new program data
3 pub buffer_account: Pubkey,
4
5 /// Spill account for rent recovery
6 pub spill_account: Pubkey,
7
8 /// Maximum program data size
9 pub max_data_size: usize,
10}
11
12impl ProgramUpgrade {
13 pub fn upgrade_program(
14 &self,
15 program_id: &Pubkey,
16 authority: &AccountInfo,
17 buffer: &AccountInfo,
18 ) -> ProgramResult {
19 // Verify upgrade authority
20 verify_upgrade_authority(authority)?;
21
22 // Verify buffer data
23 if buffer.data_len() > self.max_data_size {
24 return Err(StakePoolError::ProgramTooLarge.into());
25 }
26
27 // Verify program version compatibility
28 verify_version_compatibility(buffer)?;
29
30 // Close existing program data
31 close_program_data(
32 program_id,
33 &self.spill_account,
34 )?;
35
36 // Deploy new program data
37 deploy_program_data(
38 program_id,
39 buffer,
40 )?;
41
42 // Emit upgrade event
43 emit!(ProgramUpgraded {
44 program_id: *program_id,
45 buffer: *buffer.key,
46 authority: *authority.key,
47 timestamp: Clock::get()?.unix_timestamp,
48 });
49
50 Ok(())
51 }
52}
3. State Migration
Implement secure state migration during upgrades.
State Migration
1pub struct StateMigration {
2 /// Old state version
3 pub old_version: u8,
4
5 /// New state version
6 pub new_version: u8,
7
8 /// Migration handlers
9 pub migration_handlers: Vec<MigrationHandler>,
10}
11
12impl StateMigration {
13 pub fn migrate_state(
14 &self,
15 old_state: &[u8],
16 new_state: &mut [u8],
17 ) -> ProgramResult {
18 // Verify version compatibility
19 if self.old_version >= self.new_version {
20 return Err(StakePoolError::InvalidVersionUpgrade.into());
21 }
22
23 // Apply migrations in sequence
24 let mut current_state = old_state.to_vec();
25
26 for handler in &self.migration_handlers {
27 if handler.from_version == self.old_version
28 && handler.to_version <= self.new_version {
29 // Apply migration
30 current_state = handler.migrate(¤t_state)?;
31 }
32 }
33
34 // Verify final state
35 if current_state.len() > new_state.len() {
36 return Err(StakePoolError::StateTooLarge.into());
37 }
38
39 // Copy migrated state
40 new_state[..current_state.len()].copy_from_slice(¤t_state);
41
42 Ok(())
43 }
44}
4. Safety Measures
Implement upgrade safety measures and validation.
Upgrade Safety
1pub struct UpgradeSafety {
2 /// Minimum delay between upgrades (epochs)
3 pub min_upgrade_delay: u64,
4
5 /// Required test cases
6 pub required_tests: Vec<TestCase>,
7
8 /// Required approvals
9 pub required_approvals: u8,
10}
11
12impl UpgradeSafety {
13 pub fn verify_upgrade_safety(
14 &self,
15 program_id: &Pubkey,
16 buffer: &AccountInfo,
17 current_epoch: u64,
18 ) -> ProgramResult {
19 // Check upgrade delay
20 let last_upgrade = get_last_upgrade_epoch(program_id)?;
21 if current_epoch.saturating_sub(last_upgrade) < self.min_upgrade_delay {
22 return Err(StakePoolError::UpgradeDelayNotMet.into());
23 }
24
25 // Run test cases
26 for test in &self.required_tests {
27 test.run(buffer)?;
28 }
29
30 // Verify approvals
31 let approvals = get_upgrade_approvals(program_id)?;
32 if approvals.len() < self.required_approvals as usize {
33 return Err(StakePoolError::InsufficientApprovals.into());
34 }
35
36 // Verify state compatibility
37 verify_state_compatibility(program_id, buffer)?;
38
39 Ok(())
40 }
41}
Upgrade Best Practices
Emergency Procedures
Implementing robust emergency procedures is crucial for protocol safety. This section covers emergency handling, fund recovery, and incident response procedures.
1. Emergency Shutdown
Implement secure emergency shutdown mechanisms.
Emergency Shutdown
1pub struct EmergencyShutdown {
2 /// Emergency authority
3 pub emergency_authority: Pubkey,
4
5 /// Shutdown state
6 pub shutdown_state: ShutdownState,
7
8 /// Shutdown reason
9 pub shutdown_reason: Option<String>,
10
11 /// Recovery procedures
12 pub recovery_procedures: Vec<RecoveryProcedure>,
13}
14
15#[derive(Clone, Debug, PartialEq)]
16pub enum ShutdownState {
17 /// Normal operation
18 Active,
19
20 /// Deposits paused
21 DepositsPaused,
22
23 /// All operations paused
24 FullShutdown,
25
26 /// Recovery mode
27 Recovery,
28}
29
30impl EmergencyShutdown {
31 pub fn initiate_shutdown(
32 &mut self,
33 authority: &AccountInfo,
34 state: ShutdownState,
35 reason: Option<String>,
36 ) -> ProgramResult {
37 // Verify emergency authority
38 if !authority.is_signer {
39 return Err(StakePoolError::SignatureMissing.into());
40 }
41 if authority.key != &self.emergency_authority {
42 return Err(StakePoolError::InvalidEmergencyAuthority.into());
43 }
44
45 // Update shutdown state
46 self.shutdown_state = state;
47 self.shutdown_reason = reason;
48
49 // Emit shutdown event
50 emit!(EmergencyShutdownInitiated {
51 state,
52 reason: self.shutdown_reason.clone(),
53 timestamp: Clock::get()?.unix_timestamp,
54 });
55
56 Ok(())
57 }
58}
2. Fund Recovery
Implement secure fund recovery procedures.
Fund Recovery
1pub struct FundRecovery {
2 /// Recovery authority
3 pub recovery_authority: Pubkey,
4
5 /// Recovery vault
6 pub recovery_vault: Pubkey,
7
8 /// Recovery delay (epochs)
9 pub recovery_delay: u64,
10
11 /// Recovery approvers
12 pub required_approvers: Vec<Pubkey>,
13}
14
15impl FundRecovery {
16 pub fn initiate_recovery(
17 &mut self,
18 accounts: &[AccountInfo],
19 amount: u64,
20 ) -> ProgramResult {
21 let account_info_iter = &mut accounts.iter();
22
23 // Get accounts
24 let stake_pool = next_account_info(account_info_iter)?;
25 let authority = next_account_info(account_info_iter)?;
26 let vault = next_account_info(account_info_iter)?;
27
28 // Verify recovery authority
29 verify_recovery_authority(authority)?;
30
31 // Create recovery instruction
32 let recovery = RecoveryInstruction {
33 amount,
34 source: *stake_pool.key,
35 destination: *vault.key,
36 effective_epoch: Clock::get()?.epoch + self.recovery_delay,
37 approvals: vec![],
38 };
39
40 // Store recovery instruction
41 self.pending_recoveries.push(recovery);
42
43 // Emit recovery event
44 emit!(FundRecoveryInitiated {
45 amount,
46 source: *stake_pool.key,
47 destination: *vault.key,
48 effective_epoch: recovery.effective_epoch,
49 });
50
51 Ok(())
52 }
53
54 pub fn approve_recovery(
55 &mut self,
56 recovery_id: u64,
57 approver: &AccountInfo,
58 ) -> ProgramResult {
59 // Verify approver
60 if !self.required_approvers.contains(approver.key) {
61 return Err(StakePoolError::InvalidRecoveryApprover.into());
62 }
63
64 // Add approval
65 let recovery = self.pending_recoveries
66 .get_mut(recovery_id as usize)
67 .ok_or(StakePoolError::InvalidRecoveryId)?;
68
69 recovery.approvals.push(*approver.key);
70
71 // Check if enough approvals
72 if recovery.approvals.len() >= self.required_approvers.len() {
73 // Execute recovery
74 self.execute_recovery(recovery_id)?;
75 }
76
77 Ok(())
78 }
79}
3. Slashing Event Handling
Implement procedures for handling validator slashing events.
Slashing Handler
1pub struct SlashingHandler {
2 /// Slashing threshold (percentage)
3 pub slashing_threshold: u8,
4
5 /// Emergency unstake threshold
6 pub emergency_unstake_threshold: u8,
7
8 /// Recovery pool
9 pub recovery_pool: Pubkey,
10}
11
12impl SlashingHandler {
13 pub fn handle_slashing_event(
14 &mut self,
15 validator: &Pubkey,
16 slash_amount: u64,
17 total_stake: u64,
18 ) -> ProgramResult {
19 // Calculate slash percentage
20 let slash_percentage = (slash_amount as f64 / total_stake as f64 * 100.0) as u8;
21
22 if slash_percentage >= self.emergency_unstake_threshold {
23 // Emergency unstake all funds
24 self.emergency_unstake(validator)?;
25 } else if slash_percentage >= self.slashing_threshold {
26 // Partial unstake
27 self.partial_unstake(
28 validator,
29 slash_amount.saturating_mul(2), // Extra safety margin
30 )?;
31 }
32
33 // Move slashed amount to recovery pool
34 self.move_to_recovery_pool(
35 validator,
36 slash_amount,
37 )?;
38
39 // Update validator status
40 self.update_validator_status(
41 validator,
42 ValidatorStatus::Slashed,
43 )?;
44
45 // Emit slashing event
46 emit!(ValidatorSlashed {
47 validator: *validator,
48 slash_amount,
49 slash_percentage,
50 timestamp: Clock::get()?.unix_timestamp,
51 });
52
53 Ok(())
54 }
55}
4. Communication Protocol
Implement emergency communication procedures.
Emergency Communication
1pub struct EmergencyComm {
2 /// Emergency contacts
3 pub emergency_contacts: Vec<EmergencyContact>,
4
5 /// Communication channels
6 pub channels: Vec<CommChannel>,
7
8 /// Message templates
9 pub message_templates: HashMap<EmergencyType, String>,
10}
11
12impl EmergencyComm {
13 pub fn broadcast_emergency(
14 &self,
15 emergency_type: EmergencyType,
16 details: &EmergencyDetails,
17 ) -> ProgramResult {
18 // Get message template
19 let template = self.message_templates
20 .get(&emergency_type)
21 .ok_or(StakePoolError::TemplateNotFound)?;
22
23 // Format message
24 let message = format_emergency_message(
25 template,
26 details,
27 )?;
28
29 // Broadcast to all channels
30 for channel in &self.channels {
31 channel.broadcast(&message)?;
32 }
33
34 // Notify emergency contacts
35 for contact in &self.emergency_contacts {
36 if contact.notify_for.contains(&emergency_type) {
37 contact.notify(&message)?;
38 }
39 }
40
41 // Log communication
42 emit!(EmergencyBroadcast {
43 emergency_type,
44 message: message.clone(),
45 channels: self.channels.len() as u8,
46 contacts_notified: self.emergency_contacts.len() as u8,
47 timestamp: Clock::get()?.unix_timestamp,
48 });
49
50 Ok(())
51 }
52}
Critical Safety Measures
Protocol Monitoring
Implementing comprehensive monitoring is crucial for protocol health and security. This section covers monitoring systems, metrics collection, and alerting mechanisms.
1. Health Monitoring
Implement comprehensive health monitoring systems.
Health Monitor
1pub struct HealthMonitor {
2 /// Health check interval (slots)
3 pub check_interval: u64,
4
5 /// Health metrics
6 pub metrics: HealthMetrics,
7
8 /// Alert thresholds
9 pub thresholds: AlertThresholds,
10
11 /// Last check timestamp
12 pub last_check: i64,
13}
14
15#[derive(Clone, Debug)]
16pub struct HealthMetrics {
17 /// Total stake
18 pub total_stake: u64,
19
20 /// Active validators
21 pub active_validators: u32,
22
23 /// Average stake rate
24 pub avg_stake_rate: f64,
25
26 /// Protocol uptime
27 pub uptime_percentage: f64,
28
29 /// Error rate
30 pub error_rate: f64,
31}
32
33impl HealthMonitor {
34 pub fn check_protocol_health(
35 &mut self,
36 stake_pool: &StakePool,
37 validator_list: &ValidatorList,
38 ) -> ProgramResult {
39 let current_slot = Clock::get()?.slot;
40
41 // Check if it's time for health check
42 if current_slot.saturating_sub(self.last_check) < self.check_interval {
43 return Ok(());
44 }
45
46 // Update metrics
47 self.metrics.total_stake = stake_pool.total_lamports;
48 self.metrics.active_validators = validator_list.validators.len() as u32;
49 self.metrics.avg_stake_rate = calculate_stake_rate(stake_pool)?;
50 self.metrics.uptime_percentage = calculate_uptime(stake_pool)?;
51 self.metrics.error_rate = calculate_error_rate(stake_pool)?;
52
53 // Check thresholds
54 if self.metrics.active_validators < self.thresholds.min_validators {
55 self.emit_alert(AlertType::LowValidatorCount)?;
56 }
57
58 if self.metrics.error_rate > self.thresholds.max_error_rate {
59 self.emit_alert(AlertType::HighErrorRate)?;
60 }
61
62 if self.metrics.uptime_percentage < self.thresholds.min_uptime {
63 self.emit_alert(AlertType::LowUptime)?;
64 }
65
66 // Update last check timestamp
67 self.last_check = current_slot;
68
69 Ok(())
70 }
71}
2. Performance Monitoring
Implement performance monitoring and optimization.
Performance Monitor
1pub struct PerformanceMonitor {
2 /// Performance metrics
3 pub metrics: PerformanceMetrics,
4
5 /// Historical data
6 pub history: MetricsHistory,
7
8 /// Alert system
9 pub alerts: AlertSystem,
10}
11
12impl PerformanceMonitor {
13 pub fn collect_metrics(
14 &mut self,
15 stake_pool: &StakePool,
16 epoch_info: &EpochInfo,
17 ) -> ProgramResult {
18 // Collect validator metrics
19 for validator in &stake_pool.validator_list.validators {
20 let metrics = ValidatorMetrics {
21 stake_amount: validator.stake_lamports,
22 commission: validator.commission,
23 skip_rate: calculate_skip_rate(validator)?,
24 vote_credits: validator.credits_observed,
25 performance_score: calculate_performance_score(validator)?,
26 };
27
28 self.metrics.validator_metrics.insert(
29 validator.vote_account_address,
30 metrics,
31 );
32 }
33
34 // Calculate protocol metrics
35 self.metrics.total_rewards = calculate_total_rewards(stake_pool)?;
36 self.metrics.apy = calculate_apy(stake_pool, epoch_info)?;
37 self.metrics.stake_utilization = calculate_stake_utilization(stake_pool)?;
38
39 // Update historical data
40 self.history.update(self.metrics.clone())?;
41
42 // Check for performance issues
43 self.check_performance_issues()?;
44
45 Ok(())
46 }
47
48 fn check_performance_issues(&self) -> ProgramResult {
49 // Check APY trend
50 if self.history.is_apy_declining()? {
51 self.alerts.emit(
52 AlertType::DecliningAPY,
53 "Protocol APY is showing a declining trend",
54 )?;
55 }
56
57 // Check stake utilization
58 if self.metrics.stake_utilization < 0.8 {
59 self.alerts.emit(
60 AlertType::LowStakeUtilization,
61 "Stake utilization is below target",
62 )?;
63 }
64
65 // Check validator performance
66 for (validator, metrics) in &self.metrics.validator_metrics {
67 if metrics.skip_rate > 0.01 {
68 self.alerts.emit(
69 AlertType::HighSkipRate,
70 &format!("High skip rate for validator {}", validator),
71 )?;
72 }
73 }
74
75 Ok(())
76 }
77}
3. Alert System
Implement comprehensive alerting mechanisms.
Alert System
1pub struct AlertSystem {
2 /// Alert configurations
3 pub config: AlertConfig,
4
5 /// Alert handlers
6 pub handlers: Vec<Box<dyn AlertHandler>>,
7
8 /// Alert history
9 pub history: AlertHistory,
10}
11
12impl AlertSystem {
13 pub fn emit(
14 &self,
15 alert_type: AlertType,
16 message: &str,
17 ) -> ProgramResult {
18 // Create alert
19 let alert = Alert {
20 alert_type,
21 message: message.to_string(),
22 timestamp: Clock::get()?.unix_timestamp,
23 severity: self.config.get_severity(alert_type),
24 };
25
26 // Store in history
27 self.history.add(alert.clone())?;
28
29 // Handle based on severity
30 match alert.severity {
31 Severity::Critical => {
32 // Notify all handlers immediately
33 for handler in &self.handlers {
34 handler.handle_alert(&alert)?;
35 }
36
37 // Trigger emergency procedures if configured
38 if self.config.auto_emergency_shutdown {
39 self.trigger_emergency_shutdown(&alert)?;
40 }
41 }
42 Severity::High => {
43 // Notify all handlers
44 for handler in &self.handlers {
45 handler.handle_alert(&alert)?;
46 }
47 }
48 Severity::Medium => {
49 // Notify only if threshold reached
50 if self.history.check_threshold(&alert)? {
51 for handler in &self.handlers {
52 handler.handle_alert(&alert)?;
53 }
54 }
55 }
56 Severity::Low => {
57 // Log only
58 self.log_alert(&alert)?;
59 }
60 }
61
62 Ok(())
63 }
64}
4. Metrics Collection
Implement comprehensive metrics collection and analysis.
Metrics Collection
1pub struct MetricsCollector {
2 /// Collection interval
3 pub interval: u64,
4
5 /// Metrics storage
6 pub storage: MetricsStorage,
7
8 /// Analysis engine
9 pub analyzer: MetricsAnalyzer,
10}
11
12impl MetricsCollector {
13 pub fn collect_protocol_metrics(
14 &mut self,
15 stake_pool: &StakePool,
16 epoch_info: &EpochInfo,
17 ) -> ProgramResult {
18 // Collect basic metrics
19 let basic_metrics = BasicMetrics {
20 total_stake: stake_pool.total_lamports,
21 active_validators: stake_pool.validator_list.len() as u32,
22 total_rewards: stake_pool.total_rewards,
23 pool_token_supply: stake_pool.pool_token_supply,
24 };
25
26 // Collect performance metrics
27 let performance_metrics = PerformanceMetrics {
28 apy: calculate_apy(stake_pool, epoch_info)?,
29 stake_utilization: calculate_stake_utilization(stake_pool)?,
30 reward_distribution_efficiency: calculate_reward_efficiency(stake_pool)?,
31 validator_performance: collect_validator_metrics(stake_pool)?,
32 };
33
34 // Collect health metrics
35 let health_metrics = HealthMetrics {
36 error_rate: calculate_error_rate(stake_pool)?,
37 uptime: calculate_uptime(stake_pool)?,
38 response_times: collect_response_times(stake_pool)?,
39 system_load: collect_system_metrics()?,
40 };
41
42 // Store metrics
43 self.storage.store(
44 basic_metrics,
45 performance_metrics,
46 health_metrics,
47 )?;
48
49 // Analyze metrics
50 self.analyzer.analyze_metrics()?;
51
52 // Generate reports
53 self.generate_reports()?;
54
55 Ok(())
56 }
57}