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

Disable CloseAccount for non-native token accounts #127

Merged
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
14 changes: 7 additions & 7 deletions token/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
use solana_sdk::{
decode_error::DecodeError,
info,
program_error::{PrintProgramError, ProgramError},
decode_error::DecodeError,
};
use thiserror::Error;

Expand Down Expand Up @@ -42,12 +42,12 @@ pub enum TokenError {
/// Instruction does not support native tokens
#[error("Instruction does not support native tokens")]
NativeNotSupported,
/// Instruction does not support non-native tokens
#[error("Instruction does not support non-native tokens")]
NonNativeNotSupported,
/// Invalid instruction
#[error("Invalid instruction")]
InvalidInstruction,
/// Non-native account can only be closed if its balance is zero
#[error("Non-native account can only be closed if its balance is zero")]
NonNativeHasBalance,
}
impl From<TokenError> for ProgramError {
fn from(e: TokenError) -> Self {
Expand Down Expand Up @@ -83,10 +83,10 @@ impl PrintProgramError for TokenError {
TokenError::NativeNotSupported => {
info!("Error: Instruction does not support native tokens")
}
TokenError::InvalidInstruction => info!("Error: Invalid instruction"),
TokenError::NonNativeHasBalance => {
info!("Non-native account can only be closed if its balance is zero")
TokenError::NonNativeNotSupported => {
info!("Error: Instruction does not support non-native tokens")
}
TokenError::InvalidInstruction => info!("Error: Invalid instruction"),
}
}
}
Expand Down
60 changes: 9 additions & 51 deletions token/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use crate::{
option::COption,
};
use solana_sdk::{
account_info::AccountInfo, entrypoint::ProgramResult, info, program_error::ProgramError,
account_info::next_account_info, pubkey::Pubkey,
account_info::next_account_info, account_info::AccountInfo, entrypoint::ProgramResult, info,
program_error::ProgramError, pubkey::Pubkey,
};
use std::mem::size_of;

Expand Down Expand Up @@ -425,8 +425,8 @@ impl State {
let mut source_data = source_account_info.data.borrow_mut();
let source_account: &mut Account = Self::unpack(&mut source_data)?;

if !source_account.is_native && source_account.amount != 0 {
return Err(TokenError::NonNativeHasBalance.into());
if !source_account.is_native {
return Err(TokenError::NonNativeNotSupported.into());
}

Self::validate_owner(
Expand Down Expand Up @@ -2053,19 +2053,12 @@ mod tests {
)
);

// initialize and mint to account
// initialize non-native account
do_process_instruction(
initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
vec![&mut account_account, &mut mint_account, &mut owner_account],
)
.unwrap();
do_process_instruction(
initialize_mint(&program_id, &mint_key, Some(&account_key), None, 42, 2).unwrap(),
vec![&mut mint_account, &mut account_account, &mut owner_account],
)
.unwrap();
let account: &mut Account = State::unpack(&mut account_account.data).unwrap();
assert_eq!(account.amount, 42);

// initialize native account
do_process_instruction(
Expand All @@ -2083,9 +2076,9 @@ mod tests {
assert!(account.is_native);
assert_eq!(account.amount, 2);

// close account with balance
// close non-native account
assert_eq!(
Err(TokenError::NonNativeHasBalance.into()),
Err(TokenError::NonNativeNotSupported.into()),
do_process_instruction(
close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
vec![
Expand All @@ -2095,41 +2088,7 @@ mod tests {
],
)
);

// empty account
do_process_instruction(
burn(&program_id, &account_key, &owner_key, &[], 42).unwrap(),
vec![&mut account_account, &mut owner_account],
)
.unwrap();

// wrong owner
assert_eq!(
Err(TokenError::OwnerMismatch.into()),
do_process_instruction(
close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
vec![
&mut account_account,
&mut account3_account,
&mut owner2_account,
],
)
);

// close account
do_process_instruction(
close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
vec![
&mut account_account,
&mut account3_account,
&mut owner_account,
],
)
.unwrap();
let account: &mut Account = State::unpack_unchecked(&mut account_account.data).unwrap();
assert_eq!(account_account.lamports, 0);
assert_eq!(account.amount, 0);
assert_eq!(account3_account.lamports, 44);
assert_eq!(account_account.lamports, 42);

// close native account
do_process_instruction(
Expand All @@ -2143,9 +2102,8 @@ mod tests {
.unwrap();
let account: &mut Account = State::unpack_unchecked(&mut account2_account.data).unwrap();
assert!(account.is_native);
assert_eq!(account_account.lamports, 0);
assert_eq!(account.amount, 0);
assert_eq!(account3_account.lamports, 46);
assert_eq!(account3_account.lamports, 4);
}

#[test]
Expand Down