From bcba77eb7c5c6ff0dca89d2b43b94093f2020a53 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Fri, 5 Jul 2024 15:25:49 +0000 Subject: [PATCH] Disallow closing the top stake account --- api/src/error.rs | 4 ++++ program/src/close.rs | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) 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)?;