Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 28f1ba9

Browse files
authored
token-2022: Add freeze / thaw through StateWithExtensions (#2848)
1 parent 5b0e0c1 commit 28f1ba9

File tree

3 files changed

+115
-8
lines changed

3 files changed

+115
-8
lines changed

token/program-2022/src/processor.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -882,19 +882,23 @@ impl Processor {
882882
let authority_info = next_account_info(account_info_iter)?;
883883
let authority_info_data_len = authority_info.data_len();
884884

885-
let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
886-
if freeze && source_account.is_frozen() || !freeze && !source_account.is_frozen() {
885+
let mut source_account_data = source_account_info.data.borrow_mut();
886+
let mut source_account =
887+
StateWithExtensionsMut::<Account>::unpack(&mut source_account_data)?;
888+
if freeze && source_account.base.is_frozen() || !freeze && !source_account.base.is_frozen()
889+
{
887890
return Err(TokenError::InvalidState.into());
888891
}
889-
if source_account.is_native() {
892+
if source_account.base.is_native() {
890893
return Err(TokenError::NativeNotSupported.into());
891894
}
892-
if !cmp_pubkeys(mint_info.key, &source_account.mint) {
895+
if !cmp_pubkeys(mint_info.key, &source_account.base.mint) {
893896
return Err(TokenError::MintMismatch.into());
894897
}
895898

896-
let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
897-
match mint.freeze_authority {
899+
let mint_data = mint_info.data.borrow();
900+
let mint = StateWithExtensions::<Mint>::unpack(&mint_data)?;
901+
match mint.base.freeze_authority {
898902
COption::Some(authority) => Self::validate_owner(
899903
program_id,
900904
&authority,
@@ -905,13 +909,13 @@ impl Processor {
905909
COption::None => Err(TokenError::MintCannotFreeze.into()),
906910
}?;
907911

908-
source_account.state = if freeze {
912+
source_account.base.state = if freeze {
909913
AccountState::Frozen
910914
} else {
911915
AccountState::Initialized
912916
};
913917

914-
Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
918+
source_account.pack_base();
915919

916920
Ok(())
917921
}

token/program-2022/tests/freeze.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#![cfg(feature = "test-bpf")]
2+
3+
mod program_test;
4+
use {
5+
program_test::{TestContext, TokenContext},
6+
solana_program_test::tokio,
7+
solana_sdk::{signature::Signer, signer::keypair::Keypair},
8+
spl_token_2022::state::AccountState,
9+
};
10+
11+
#[tokio::test]
12+
async fn basic() {
13+
let mut context = TestContext::new().await;
14+
context.init_token_with_freezing_mint(vec![]).await.unwrap();
15+
let TokenContext {
16+
freeze_authority,
17+
token,
18+
alice,
19+
..
20+
} = context.token_context.unwrap();
21+
let freeze_authority = freeze_authority.unwrap();
22+
23+
let account = Keypair::new();
24+
let account = token
25+
.create_auxiliary_token_account(&account, &alice.pubkey())
26+
.await
27+
.unwrap();
28+
let state = token.get_account_info(&account).await.unwrap();
29+
assert_eq!(state.base.state, AccountState::Initialized);
30+
31+
token
32+
.freeze_account(&account, &freeze_authority)
33+
.await
34+
.unwrap();
35+
let state = token.get_account_info(&account).await.unwrap();
36+
assert_eq!(state.base.state, AccountState::Frozen);
37+
38+
token
39+
.thaw_account(&account, &freeze_authority)
40+
.await
41+
.unwrap();
42+
let state = token.get_account_info(&account).await.unwrap();
43+
assert_eq!(state.base.state, AccountState::Initialized);
44+
}

token/rust/src/token.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,44 @@ where
481481
.await
482482
}
483483

484+
/// Freeze a token account
485+
pub async fn freeze_account<S2: Signer>(
486+
&self,
487+
account: &Pubkey,
488+
authority: &S2,
489+
) -> TokenResult<T::Output> {
490+
self.process_ixs(
491+
&[instruction::freeze_account(
492+
&self.program_id,
493+
account,
494+
&self.pubkey,
495+
&authority.pubkey(),
496+
&[],
497+
)?],
498+
&[authority],
499+
)
500+
.await
501+
}
502+
503+
/// Thaw / unfreeze a token account
504+
pub async fn thaw_account<S2: Signer>(
505+
&self,
506+
account: &Pubkey,
507+
authority: &S2,
508+
) -> TokenResult<T::Output> {
509+
self.process_ixs(
510+
&[instruction::thaw_account(
511+
&self.program_id,
512+
account,
513+
&self.pubkey,
514+
&authority.pubkey(),
515+
&[],
516+
)?],
517+
&[authority],
518+
)
519+
.await
520+
}
521+
484522
/// Set transfer fee
485523
pub async fn set_transfer_fee<S2: Signer>(
486524
&self,
@@ -538,4 +576,25 @@ where
538576
)
539577
.await
540578
}
579+
580+
/// Withdraw withheld tokens from mint
581+
pub async fn withdraw_withheld_tokens_from_mint<S2: Signer>(
582+
&self,
583+
destination: &Pubkey,
584+
authority: &S2,
585+
) -> TokenResult<T::Output> {
586+
self.process_ixs(
587+
&[
588+
transfer_fee::instruction::withdraw_withheld_tokens_from_mint(
589+
&self.program_id,
590+
&self.pubkey,
591+
destination,
592+
&authority.pubkey(),
593+
&[],
594+
)?,
595+
],
596+
&[authority],
597+
)
598+
.await
599+
}
541600
}

0 commit comments

Comments
 (0)