Skip to content

Commit 8eff6b6

Browse files
author
Edward (Mike's assistant)
committed
fix(transfer-hook): update Quasar programs for new UncheckedAccount API
The Quasar master branch (commit 37a531dc) replaced the registry version of `solana-account-view`, changing `AccountView::try_borrow_mut` from `&self` to `&mut self`. It also dropped the `alloc` Cargo feature on `quasar-lang`, renamed `BufCpiCall` to `DynCpiCall`, and rejects all-zero multi-byte instruction discriminators at compile time. This commit migrates all 7 broken transfer-hook examples to compile and run against the current API: - hello-world, counter, transfer-cost, transfer-switch: replaced the invalid `account as *const UncheckedAccount as *mut UncheckedAccount` cast (which tried to cast a value, not a reference) with `&mut account as *mut UncheckedAccount`. - whitelist, account-data-as-seed: converted account structs from `&'info mut UncheckedAccount` field syntax (which the Quasar derive macro no longer accepts) to owned `UncheckedAccount` fields, updated handler signatures from `&Foo` to `&mut Foo`, and applied the same pointer-cast fix. - allow-block-list-token: same `&'info` -> owned conversion across all instruction modules; removed the `alloc` feature dependency from Cargo.toml (upstream `quasar-lang` master no longer exposes it); rewrote two `BufCpiCall` call sites to use `DynCpiCall` (the new variable-length CPI builder); changed the all-zero `init_mint` instruction discriminator to a non-zero value. All 7 projects now pass `quasar build` and `cargo test`.
1 parent 70c45d2 commit 8eff6b6

15 files changed

Lines changed: 161 additions & 181 deletions

File tree

tokens/token-extensions/transfer-hook/account-data-as-seed/quasar/src/lib.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,21 @@ mod quasar_transfer_hook_account_data_as_seed {
4646
// ---------------------------------------------------------------------------
4747

4848
#[derive(Accounts)]
49-
pub struct InitializeExtraAccountMetaList<'info> {
49+
pub struct InitializeExtraAccountMetaList {
5050
#[account(mut)]
51-
pub payer: &'info Signer,
51+
pub payer: Signer,
5252
/// ExtraAccountMetaList PDA: ["extra-account-metas", mint]
5353
#[account(mut)]
54-
pub extra_account_meta_list: &'info mut UncheckedAccount,
55-
pub mint: &'info UncheckedAccount,
54+
pub extra_account_meta_list: UncheckedAccount,
55+
pub mint: UncheckedAccount,
5656
/// Counter PDA: ["counter", payer_key]
5757
#[account(mut)]
58-
pub counter_account: &'info mut UncheckedAccount,
59-
pub system_program: &'info Program<System>,
58+
pub counter_account: UncheckedAccount,
59+
pub system_program: Program<System>,
6060
}
6161

6262
#[inline(always)]
63-
pub fn handle_initialize_extra_account_meta_list(accounts: &InitializeExtraAccountMetaList) -> Result<(), ProgramError> {
63+
pub fn handle_initialize_extra_account_meta_list(accounts: &mut InitializeExtraAccountMetaList) -> Result<(), ProgramError> {
6464
// ExtraAccountMetaList with 1 extra account.
6565
// ExtraAccountMeta for a PDA with seeds [Literal("counter"), AccountData(0, 32, 32)]:
6666
// The AccountData seed resolves the owner pubkey from account_index=0
@@ -94,8 +94,8 @@ pub fn handle_initialize_extra_account_meta_list(accounts: &InitializeExtraAccou
9494

9595
accounts.system_program
9696
.create_account(
97-
accounts.payer,
98-
&*accounts.extra_account_meta_list,
97+
&accounts.payer,
98+
&accounts.extra_account_meta_list,
9999
lamports,
100100
meta_list_size,
101101
&crate::ID,
@@ -104,7 +104,7 @@ pub fn handle_initialize_extra_account_meta_list(accounts: &InitializeExtraAccou
104104

105105
// Write TLV data
106106
let view = unsafe {
107-
&mut *(accounts.extra_account_meta_list as *const UncheckedAccount as *mut UncheckedAccount
107+
&mut *(&mut accounts.extra_account_meta_list as *mut UncheckedAccount
108108
as *mut AccountView)
109109
};
110110
let mut data = view.try_borrow_mut()?;
@@ -151,8 +151,8 @@ pub fn handle_initialize_extra_account_meta_list(accounts: &InitializeExtraAccou
151151

152152
accounts.system_program
153153
.create_account(
154-
accounts.payer,
155-
&*accounts.counter_account,
154+
&accounts.payer,
155+
&accounts.counter_account,
156156
counter_lamports,
157157
counter_size,
158158
&crate::ID,
@@ -168,21 +168,21 @@ pub fn handle_initialize_extra_account_meta_list(accounts: &InitializeExtraAccou
168168
// ---------------------------------------------------------------------------
169169

170170
#[derive(Accounts)]
171-
pub struct TransferHook<'info> {
172-
pub source_token: &'info UncheckedAccount,
173-
pub mint: &'info UncheckedAccount,
174-
pub destination_token: &'info UncheckedAccount,
175-
pub owner: &'info UncheckedAccount,
176-
pub extra_account_meta_list: &'info UncheckedAccount,
171+
pub struct TransferHook {
172+
pub source_token: UncheckedAccount,
173+
pub mint: UncheckedAccount,
174+
pub destination_token: UncheckedAccount,
175+
pub owner: UncheckedAccount,
176+
pub extra_account_meta_list: UncheckedAccount,
177177
/// Counter PDA resolved by Token-2022 using account data seeds
178178
#[account(mut)]
179-
pub counter_account: &'info mut UncheckedAccount,
179+
pub counter_account: UncheckedAccount,
180180
}
181181

182182
#[inline(always)]
183-
pub fn handle_transfer_hook(accounts: &TransferHook) -> Result<(), ProgramError> {
183+
pub fn handle_transfer_hook(accounts: &mut TransferHook) -> Result<(), ProgramError> {
184184
let view = unsafe {
185-
&mut *(accounts.counter_account as *const UncheckedAccount as *mut UncheckedAccount
185+
&mut *(&mut accounts.counter_account as *mut UncheckedAccount
186186
as *mut AccountView)
187187
};
188188
let mut data = view.try_borrow_mut()?;

tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ check-cfg = ['cfg(target_os, values("solana"))']
1313
crate-type = ["cdylib", "lib"]
1414

1515
[features]
16-
alloc = ["quasar-lang/alloc"]
16+
# Removed `alloc` feature — the upstream `quasar-lang` master no longer
17+
# exposes it, and nothing in this crate depends on alloc.
1718
client = []
1819
debug = []
1920

tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/attach_to_mint.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ use crate::constants::*;
66
use crate::instructions::init_mint::Token2022;
77

88
#[derive(Accounts)]
9-
pub struct AttachToMint<'info> {
9+
pub struct AttachToMint {
1010
#[account(mut)]
11-
pub payer: &'info Signer,
11+
pub payer: Signer,
1212
#[account(mut)]
13-
pub mint: &'info UncheckedAccount,
13+
pub mint: UncheckedAccount,
1414
#[account(mut)]
15-
pub extra_metas_account: &'info mut UncheckedAccount,
16-
pub system_program: &'info Program<System>,
17-
pub token_program: &'info Program<Token2022>,
15+
pub extra_metas_account: UncheckedAccount,
16+
pub system_program: Program<System>,
17+
pub token_program: Program<Token2022>,
1818
}
1919

2020
#[inline(always)]
21-
pub fn handle_attach_to_mint(accounts: &AttachToMint) -> Result<(), ProgramError> {
21+
pub fn handle_attach_to_mint(accounts: &mut AttachToMint) -> Result<(), ProgramError> {
2222
let mint_key = accounts.mint.to_account_view().address();
2323
let payer_key = accounts.payer.to_account_view().address();
2424
let token_prog = accounts.token_program.to_account_view().address();
@@ -79,8 +79,8 @@ pub fn handle_attach_to_mint(accounts: &AttachToMint) -> Result<(), ProgramError
7979

8080
accounts.system_program
8181
.create_account(
82-
accounts.payer,
83-
&*accounts.extra_metas_account,
82+
&accounts.payer,
83+
&accounts.extra_metas_account,
8484
lamports,
8585
meta_list_size,
8686
&crate::ID,
@@ -89,7 +89,7 @@ pub fn handle_attach_to_mint(accounts: &AttachToMint) -> Result<(), ProgramError
8989

9090
// Write ExtraAccountMeta TLV data
9191
let view = unsafe {
92-
&mut *(accounts.extra_metas_account as *const UncheckedAccount as *mut UncheckedAccount
92+
&mut *(&mut accounts.extra_metas_account as *mut UncheckedAccount
9393
as *mut AccountView)
9494
};
9595
let mut data = view.try_borrow_mut()?;

tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/change_mode.rs

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use quasar_lang::cpi::{BufCpiCall, InstructionAccount};
1+
use quasar_lang::cpi::DynCpiCall;
22
use quasar_lang::prelude::*;
33
use quasar_lang::sysvars::Sysvar;
44

@@ -7,17 +7,17 @@ use crate::instructions::init_mint::Token2022;
77
use crate::state::mode_to_metadata_value;
88

99
#[derive(Accounts)]
10-
pub struct ChangeMode<'info> {
10+
pub struct ChangeMode {
1111
#[account(mut)]
12-
pub authority: &'info Signer,
12+
pub authority: Signer,
1313
#[account(mut)]
14-
pub mint: &'info UncheckedAccount,
15-
pub token_program: &'info Program<Token2022>,
16-
pub system_program: &'info Program<System>,
14+
pub mint: UncheckedAccount,
15+
pub token_program: Program<Token2022>,
16+
pub system_program: Program<System>,
1717
}
1818

1919
#[inline(always)]
20-
pub fn handle_change_mode(accounts: &ChangeMode, mode: u8, threshold: u64) -> Result<(), ProgramError> {
20+
pub fn handle_change_mode(accounts: &mut ChangeMode, mode: u8, threshold: u64) -> Result<(), ProgramError> {
2121
let mode_value = mode_to_metadata_value(mode);
2222
let token_prog = accounts.token_program.to_account_view().address();
2323
let mint_key = accounts.mint.to_account_view().address();
@@ -52,7 +52,7 @@ pub fn handle_change_mode(accounts: &ChangeMode, mode: u8, threshold: u64) -> Re
5252
if min_balance > current_lamports {
5353
let diff = min_balance - current_lamports;
5454
accounts.system_program
55-
.transfer(accounts.authority, &*accounts.mint, diff)
55+
.transfer(&accounts.authority, &accounts.mint, diff)
5656
.invoke()?;
5757
}
5858

@@ -65,7 +65,7 @@ fn emit_update_field(
6565
token_prog: &Address,
6666
mint_key: &Address,
6767
auth_key: &Address,
68-
ctx: &ChangeMode<'_>,
68+
ctx: &ChangeMode,
6969
key: &[u8],
7070
value: &[u8],
7171
) -> Result<(), ProgramError> {
@@ -86,24 +86,18 @@ fn emit_update_field(
8686
buf[pos..pos + value.len()].copy_from_slice(value);
8787
pos += value.len();
8888

89-
BufCpiCall::new(
90-
token_prog,
91-
[
92-
InstructionAccount::writable(mint_key),
93-
InstructionAccount::readonly_signer(auth_key),
94-
],
95-
[
96-
ctx.mint.to_account_view(),
97-
ctx.authority.to_account_view(),
98-
],
99-
buf,
100-
pos,
101-
)
102-
.invoke()
89+
let _ = (mint_key, auth_key);
90+
let mut cpi = DynCpiCall::<2, MAX_META_IX>::new(token_prog);
91+
// mint: writable, not signer
92+
cpi.push_account(ctx.mint.to_account_view(), false, true)?;
93+
// authority: signer, not writable
94+
cpi.push_account(ctx.authority.to_account_view(), true, false)?;
95+
cpi.set_data(&buf[..pos])?;
96+
cpi.invoke()
10397
}
10498

10599
/// Check if the mint's metadata already contains a "threshold" key.
106-
fn has_threshold_in_metadata(ctx: &ChangeMode<'_>) -> Result<bool, ProgramError> {
100+
fn has_threshold_in_metadata(ctx: &ChangeMode) -> Result<bool, ProgramError> {
107101
let mint_view = ctx.mint.to_account_view();
108102
let data = mint_view.try_borrow()?;
109103

tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_config.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ use crate::constants::CONFIG_SEED;
66
use crate::state::{write_config, CONFIG_SIZE};
77

88
#[derive(Accounts)]
9-
pub struct InitConfig<'info> {
9+
pub struct InitConfig {
1010
#[account(mut)]
11-
pub payer: &'info Signer,
11+
pub payer: Signer,
1212
#[account(mut)]
13-
pub config: &'info mut UncheckedAccount,
14-
pub system_program: &'info Program<System>,
13+
pub config: UncheckedAccount,
14+
pub system_program: Program<System>,
1515
}
1616

1717
#[inline(always)]
18-
pub fn handle_init_config(accounts: &InitConfig) -> Result<(), ProgramError> {
18+
pub fn handle_init_config(accounts: &mut InitConfig) -> Result<(), ProgramError> {
1919
let (config_pda, bump) = Address::find_program_address(&[CONFIG_SEED], &crate::ID);
2020

2121
if accounts.config.to_account_view().address() != &config_pda {
@@ -31,16 +31,16 @@ pub fn handle_init_config(accounts: &InitConfig) -> Result<(), ProgramError> {
3131

3232
accounts.system_program
3333
.create_account(
34-
accounts.payer,
35-
&*accounts.config,
34+
&accounts.payer,
35+
&accounts.config,
3636
lamports,
3737
CONFIG_SIZE,
3838
&crate::ID,
3939
)
4040
.invoke_signed(&seeds)?;
4141

4242
let view = unsafe {
43-
&mut *(accounts.config as *const UncheckedAccount as *mut UncheckedAccount
43+
&mut *(&mut accounts.config as *mut UncheckedAccount
4444
as *mut AccountView)
4545
};
4646
let mut data = view.try_borrow_mut()?;

0 commit comments

Comments
 (0)