diff --git a/api/src/error.rs b/api/src/error.rs index a0fdbf9..e3d8ee0 100644 --- a/api/src/error.rs +++ b/api/src/error.rs @@ -23,6 +23,10 @@ pub enum OreError { ToleranceOverflow = 7, #[error("The maximum supply has been reached")] MaxSupply = 8, + #[error("This account cannot be closed because it's the top staker")] + CannotClose = 9, + #[error("This account cannot be crowned because its last stake was too recent")] + CannotCrown = 10, } impl From for ProgramError { diff --git a/program/src/close.rs b/program/src/close.rs index d92bb20..052f87d 100644 --- a/program/src/close.rs +++ b/program/src/close.rs @@ -1,4 +1,8 @@ -use ore_api::{loaders::*, state::Proof}; +use ore_api::{ + error::OreError, + loaders::*, + state::{Config, Proof}, +}; use solana_program::{ account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, pubkey::Pubkey, system_program, @@ -20,13 +24,21 @@ pub fn process_close<'a, 'info>( _data: &[u8], ) -> ProgramResult { // Load accounts - let [signer, proof_info, system_program] = accounts else { + let [signer, config_info, proof_info, system_program] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); }; load_signer(signer)?; + load_config(config_info, false)?; load_proof(proof_info, signer.key, true)?; load_program(system_program, system_program::id())?; + // Validate the account is not the crowned top staker. + let config_data = config_info.data.borrow(); + let config = Config::try_from_bytes(&config_data)?; + if config.top_staker.eq(proof_info.key) { + return Err(OreError::CannotClose.into()); + } + // Validate balance is zero let proof_data = proof_info.data.borrow(); let proof = Proof::try_from_bytes(&proof_data)?;