Skip to content
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
3 changes: 2 additions & 1 deletion .github/workflows/anchor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ jobs:
- uses: heyAyushh/setup-anchor@v4.999
with:
anchor-version: 1.0.0
solana-cli-version: stable
# setup-anchor resolves tags like stable by querying GitHub API for latest release which can fail with 429 errors
solana-cli-version: 3.1.14
- name: Install Surfpool
run: curl -sL https://run.surfpool.run/ | bash
- name: Display Versions
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/native.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ jobs:
- name: Setup Solana Stable
uses: heyAyushh/setup-solana@v5.9
with:
solana-cli-version: stable
# setup-anchor resolves tags like stable by querying GitHub API for latest release which can fail with 429 errors
solana-cli-version: 3.1.14
- name: Build and Test with Stable
run: |
source build_and_test.sh
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/pinocchio.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ jobs:
- name: Setup Solana Stable
uses: heyAyushh/setup-solana@v5.9
with:
solana-cli-version: stable
# setup-anchor resolves tags like stable by querying GitHub API for latest release which can fail with 429 errors
solana-cli-version: 3.1.14
- name: Build and Test with Stable
run: |
source build_and_test.sh
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/quasar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ jobs:
- name: Setup Solana Stable
uses: heyAyushh/setup-solana@v5.9
with:
solana-cli-version: stable
# setup-anchor resolves tags like stable by querying GitHub API for latest release which can fail with 429 errors
solana-cli-version: 3.1.14
- name: Install Quasar CLI
# Pinned to quasar rev 3d6fb0d8 (the HEAD this migration was written
# against, immediately after PRs #195 + #196). The next merged PR
Expand Down
13 changes: 10 additions & 3 deletions .github/workflows/solana-asm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ jobs:
failed_projects: ${{ steps.set-failed.outputs.failed_projects }}
steps:
- uses: actions/checkout@v4
# The previous `npm install --global pnpm` step picked up a pnpm release that
# treats ignored build scripts (bufferutil, utf-8-validate) as a hard error and
# fails `pnpm install --frozen-lockfile`. The other workflows (anchor, native,
# pinocchio, typescript) use pnpm/action-setup@v4, which pins a known-good pnpm
# release (10.33.0 at time of writing) that only warns. Match that here.
- uses: pnpm/action-setup@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
Expand Down Expand Up @@ -180,15 +186,16 @@ jobs:
# Make the script executable
chmod +x build_and_test.sh

# Install pnpm
npm install --global pnpm
# pnpm is installed by pnpm/action-setup@v4 above. Avoid `npm install --global pnpm`
# here because that resolves to pnpm 10+, which errors on ignored build scripts.

# Install sbpf assembler
cargo install --git https://github.com/blueshift-gg/sbpf.git
- name: Setup Solana Stable
uses: heyAyushh/setup-solana@v5.9
with:
solana-cli-version: stable
# setup-anchor resolves tags like stable by querying GitHub API for latest release which can fail with 429 errors
solana-cli-version: 3.1.14
- name: Build and Test with Stable
run: |
source build_and_test.sh
Expand Down
12 changes: 10 additions & 2 deletions compression/cnft-burn/quasar/src/instructions/burn_cnft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ pub fn handle_burn_cnft(accounts: &mut BurnCnft, data: &[u8], remaining: Remaini
ix_data[0..8].copy_from_slice(&BURN_DISCRIMINATOR);
ix_data[8..116].copy_from_slice(&data[0..108]);

// Collect remaining accounts (proof nodes) into a stack buffer
// Collect remaining accounts (proof nodes) into a stack buffer.
//
// `remaining.iter()` yields `Result<RemainingAccount, _>` in newer
// quasar-lang. Reach the inner `AccountView` via the unchecked accessor
// — this CPI only reads proof addresses and views, never touching the
// accounts' data, so the aliasing/borrow invariants are upheld.
let placeholder = accounts.system_program.to_account_view().clone();
let mut proof_views: [AccountView; MAX_PROOF_NODES] =
core::array::from_fn(|_| placeholder.clone());
Expand All @@ -52,7 +57,10 @@ pub fn handle_burn_cnft(accounts: &mut BurnCnft, data: &[u8], remaining: Remaini
if proof_count >= MAX_PROOF_NODES {
break;
}
proof_views[proof_count] = result?;
let account = result?;
// SAFETY: We only read the AccountView's address and pass an immutable
// view to the bubblegum CPI as a proof node; no aliased data access.
proof_views[proof_count] = unsafe { account.as_account_view_unchecked() }.clone();
proof_count += 1;
}

Expand Down
11 changes: 9 additions & 2 deletions compression/cnft-vault/quasar/src/instructions/withdraw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ pub fn handle_withdraw_cnft(accounts: &mut Withdraw, data: &[u8], remaining: Rem

let ix_data = build_transfer_data(&data[0..TRANSFER_ARGS_LEN]);

// Collect proof nodes
// Collect proof nodes.
//
// `remaining.iter()` yields `Result<RemainingAccount, _>` in newer
// quasar-lang. Reach the inner `AccountView` via the unchecked accessor
// — we only read addresses/views to forward to the bubblegum CPI as
// proof nodes; no aliased data access.
let placeholder = accounts.system_program.to_account_view().clone();
let mut proof_views: [AccountView; MAX_PROOF_NODES] =
core::array::from_fn(|_| placeholder.clone());
Expand All @@ -59,7 +64,9 @@ pub fn handle_withdraw_cnft(accounts: &mut Withdraw, data: &[u8], remaining: Rem
if proof_count >= MAX_PROOF_NODES {
break;
}
proof_views[proof_count] = result?;
let account = result?;
// SAFETY: Only reads address and forwards an immutable view to CPI.
proof_views[proof_count] = unsafe { account.as_account_view_unchecked() }.clone();
proof_count += 1;
}

Expand Down
11 changes: 9 additions & 2 deletions compression/cnft-vault/quasar/src/instructions/withdraw_two.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ pub fn handle_withdraw_two_cnfts(accounts: &mut WithdrawTwo, data: &[u8], remain
];
let signer = Signer::from(&seeds as &[Seed]);

// Collect all remaining accounts (proof1 ++ proof2)
// Collect all remaining accounts (proof1 ++ proof2).
//
// `remaining.iter()` yields `Result<RemainingAccount, _>` in newer
// quasar-lang. Reach the inner `AccountView` via the unchecked accessor
// — we only read addresses/views to forward to the bubblegum CPIs as
// proof nodes; no aliased data access.
let placeholder = accounts.system_program.to_account_view().clone();
let mut all_proofs: [AccountView; MAX_PROOF_NODES * 2] =
core::array::from_fn(|_| placeholder.clone());
Expand All @@ -74,7 +79,9 @@ pub fn handle_withdraw_two_cnfts(accounts: &mut WithdrawTwo, data: &[u8], remain
if total_proofs >= MAX_PROOF_NODES * 2 {
break;
}
all_proofs[total_proofs] = result?;
let account = result?;
// SAFETY: Only reads address and forwards an immutable view to CPI.
all_proofs[total_proofs] = unsafe { account.as_account_view_unchecked() }.clone();
total_proofs += 1;
}

Expand Down
11 changes: 9 additions & 2 deletions compression/cutils/quasar/src/instructions/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ pub fn handle_verify(accounts: &mut Verify, data: &[u8], remaining: RemainingAcc
ix_data[40..72].copy_from_slice(&leaf_hash);
ix_data[72..76].copy_from_slice(&index.to_le_bytes());

// Collect proof nodes
// Collect proof nodes.
//
// `remaining.iter()` yields `Result<RemainingAccount, _>` in newer
// quasar-lang. Reach the inner `AccountView` via the unchecked accessor
// — we only read addresses/views to forward to the compression CPI as
// proof nodes; no aliased data access.
let placeholder = accounts.compression_program.to_account_view().clone();
let mut proof_views: [AccountView; MAX_PROOF_NODES] =
core::array::from_fn(|_| placeholder.clone());
Expand All @@ -64,7 +69,9 @@ pub fn handle_verify(accounts: &mut Verify, data: &[u8], remaining: RemainingAcc
if proof_count >= MAX_PROOF_NODES {
break;
}
proof_views[proof_count] = result?;
let account = result?;
// SAFETY: Only reads address and forwards an immutable view to CPI.
proof_views[proof_count] = unsafe { account.as_account_view_unchecked() }.clone();
proof_count += 1;
}

Expand Down
8 changes: 7 additions & 1 deletion tokens/pda-mint-authority/quasar/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,14 @@ pub struct MintTokens {
#[account(mut)]
pub payer: Signer,
/// The PDA mint whose authority is itself.
///
/// Typed as `InterfaceAccount<Mint>` rather than `Account<Mint>` because
/// newer quasar-lang requires `T: Discriminator` when combining `address =`
/// with `Account<T>` (it reads `T::BUMP_OFFSET`). SPL `Mint` doesn't
/// implement `Discriminator`; `InterfaceAccount` takes the generic
/// existing-account verifier path that doesn't need it.
#[account(mut, address = MintPda::seeds())]
pub mint: Account<Mint>,
pub mint: InterfaceAccount<Mint>,
/// Recipient token account (must already exist).
#[account(mut)]
pub token_account: Account<Token>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,15 @@ pub struct DepositLiquidity {
pub pool_authority: UncheckedAccount,
/// Depositor (must be signer to authorise transfers).
pub depositor: Signer,
/// LP mint at the LiquidityMintPda.
///
/// Typed as `InterfaceAccount<Mint>` rather than `Account<Mint>` because
/// newer quasar-lang requires `T: Discriminator` when combining `address =`
/// with `Account<T>` (it reads `T::BUMP_OFFSET`). SPL `Mint` doesn't
/// implement `Discriminator`; `InterfaceAccount` takes the generic
/// existing-account verifier path that doesn't need it.
#[account(mut, address = LiquidityMintPda::seeds(amm.address(), mint_a.address(), mint_b.address()))]
pub mint_liquidity: Account<Mint>,
pub mint_liquidity: InterfaceAccount<Mint>,
pub mint_a: Account<Mint>,
pub mint_b: Account<Mint>,
/// Pool's token A vault.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ pub struct WithdrawLiquidity {
#[account(address = PoolAuthorityPda::seeds(amm.address(), mint_a.address(), mint_b.address()))]
pub pool_authority: UncheckedAccount,
pub depositor: Signer,
/// LP mint at the LiquidityMintPda.
///
/// Typed as `InterfaceAccount<Mint>` rather than `Account<Mint>` because
/// newer quasar-lang requires `T: Discriminator` when combining `address =`
/// with `Account<T>` (it reads `T::BUMP_OFFSET`). SPL `Mint` doesn't
/// implement `Discriminator`; `InterfaceAccount` takes the generic
/// existing-account verifier path that doesn't need it.
#[account(mut, address = LiquidityMintPda::seeds(amm.address(), mint_a.address(), mint_b.address()))]
pub mint_liquidity: Account<Mint>,
pub mint_liquidity: InterfaceAccount<Mint>,
#[account(mut)]
pub mint_a: Account<Mint>,
#[account(mut)]
Expand Down
Loading