Skip to content

Commit 9962332

Browse files
lang: Make stack frames slimmer on ATA creation (otter-sec#3065)
1 parent d054d7d commit 9962332

7 files changed

Lines changed: 140 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ The minor version will be incremented upon a breaking change and the patch versi
2121
- idl: Make safety comment checks fail silently when program path env is not set ([#3045](https://github.com/coral-xyz/anchor/pull/3045)).
2222
- idl: Avoid interference from rust tests during IDL generation ([#3058](https://github.com/coral-xyz/anchor/pull/3058)).
2323
- lang: Fix `align` repr support in `declare-program!` ([#3056](https://github.com/coral-xyz/anchor/pull/3056)).
24+
- lang: Make stack frames slimmer on ATA creation ([#3065](https://github.com/coral-xyz/anchor/pull/3065)).
2425

2526
### Breaking
2627

lang/syn/src/codegen/accounts/constraints.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -624,17 +624,19 @@ fn generate_constraint_init_group(
624624
if !#if_needed || owner_program == &anchor_lang::solana_program::system_program::ID {
625625
#payer_optional_check
626626

627-
let cpi_program = associated_token_program.to_account_info();
628-
let cpi_accounts = ::anchor_spl::associated_token::Create {
629-
payer: #payer.to_account_info(),
630-
associated_token: #field.to_account_info(),
631-
authority: #owner.to_account_info(),
632-
mint: #mint.to_account_info(),
633-
system_program: system_program.to_account_info(),
634-
token_program: #token_program.to_account_info(),
635-
};
636-
let cpi_ctx = anchor_lang::context::CpiContext::new(cpi_program, cpi_accounts);
637-
::anchor_spl::associated_token::create(cpi_ctx)?;
627+
::anchor_spl::associated_token::create(
628+
anchor_lang::context::CpiContext::new(
629+
associated_token_program.to_account_info(),
630+
::anchor_spl::associated_token::Create {
631+
payer: #payer.to_account_info(),
632+
associated_token: #field.to_account_info(),
633+
authority: #owner.to_account_info(),
634+
mint: #mint.to_account_info(),
635+
system_program: system_program.to_account_info(),
636+
token_program: #token_program.to_account_info(),
637+
}
638+
)
639+
)?;
638640
}
639641
let pa: #ty_decl = #from_account_info_unchecked;
640642
if #if_needed {

tests/misc/programs/misc-optional/src/context.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,3 +693,54 @@ pub struct TestAssociatedTokenWithTokenProgramConstraint<'info> {
693693
/// CHECK: ignore
694694
pub associated_token_token_program: Option<AccountInfo<'info>>,
695695
}
696+
697+
#[derive(Accounts)]
698+
pub struct InitManyAssociatedTokenAccounts<'info> {
699+
#[account(
700+
init,
701+
payer = user,
702+
mint::authority = user,
703+
mint::decimals = 9,
704+
)]
705+
pub mint: Account<'info, Mint>,
706+
#[account(
707+
init,
708+
payer = user,
709+
associated_token::authority = user,
710+
associated_token::mint = mint,
711+
)]
712+
pub ata1: Account<'info, TokenAccount>,
713+
#[account(
714+
init,
715+
payer = user,
716+
associated_token::authority = system_program,
717+
associated_token::mint = mint,
718+
)]
719+
pub ata2: Account<'info, TokenAccount>,
720+
#[account(
721+
init,
722+
payer = user,
723+
associated_token::authority = token_program,
724+
associated_token::mint = mint,
725+
)]
726+
pub ata3: Account<'info, TokenAccount>,
727+
#[account(
728+
init,
729+
payer = user,
730+
associated_token::authority = associated_token_program,
731+
associated_token::mint = mint,
732+
)]
733+
pub ata4: Account<'info, TokenAccount>,
734+
#[account(
735+
init,
736+
payer = user,
737+
associated_token::authority = mint,
738+
associated_token::mint = mint,
739+
)]
740+
pub ata5: Account<'info, TokenAccount>,
741+
#[account(mut)]
742+
pub user: Signer<'info>,
743+
pub system_program: Program<'info, System>,
744+
pub token_program: Program<'info, Token>,
745+
pub associated_token_program: Program<'info, AssociatedToken>,
746+
}

tests/misc/programs/misc-optional/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,4 +395,11 @@ pub mod misc_optional {
395395
) -> Result<()> {
396396
Ok(())
397397
}
398+
399+
#[allow(unused_variables)]
400+
pub fn test_init_many_associated_token_accounts(
401+
_ctx: Context<InitManyAssociatedTokenAccounts>,
402+
) -> Result<()> {
403+
Ok(())
404+
}
398405
}

tests/misc/programs/misc/src/context.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ pub struct TestOnlyTokenProgramConstraint<'info> {
601601
token::token_program = token_token_program
602602
)]
603603
pub token: Account<'info, TokenAccount>,
604+
/// CHECK: ignore
604605
pub token_token_program: AccountInfo<'info>,
605606
}
606607

@@ -751,3 +752,54 @@ pub struct TestUsedIdentifiers<'info> {
751752
/// CHECK: ignore
752753
pub test4: AccountInfo<'info>,
753754
}
755+
756+
#[derive(Accounts)]
757+
pub struct InitManyAssociatedTokenAccounts<'info> {
758+
#[account(
759+
init,
760+
payer = user,
761+
mint::authority = user,
762+
mint::decimals = 9,
763+
)]
764+
pub mint: Account<'info, Mint>,
765+
#[account(
766+
init,
767+
payer = user,
768+
associated_token::authority = user,
769+
associated_token::mint = mint,
770+
)]
771+
pub ata1: Account<'info, TokenAccount>,
772+
#[account(
773+
init,
774+
payer = user,
775+
associated_token::authority = system_program,
776+
associated_token::mint = mint,
777+
)]
778+
pub ata2: Account<'info, TokenAccount>,
779+
#[account(
780+
init,
781+
payer = user,
782+
associated_token::authority = token_program,
783+
associated_token::mint = mint,
784+
)]
785+
pub ata3: Account<'info, TokenAccount>,
786+
#[account(
787+
init,
788+
payer = user,
789+
associated_token::authority = associated_token_program,
790+
associated_token::mint = mint,
791+
)]
792+
pub ata4: Account<'info, TokenAccount>,
793+
#[account(
794+
init,
795+
payer = user,
796+
associated_token::authority = mint,
797+
associated_token::mint = mint,
798+
)]
799+
pub ata5: Account<'info, TokenAccount>,
800+
#[account(mut)]
801+
pub user: Signer<'info>,
802+
pub system_program: Program<'info, System>,
803+
pub token_program: Program<'info, Token>,
804+
pub associated_token_program: Program<'info, AssociatedToken>,
805+
}

tests/misc/programs/misc/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,4 +385,11 @@ pub mod misc {
385385
) -> Result<()> {
386386
Ok(())
387387
}
388+
389+
#[allow(unused_variables)]
390+
pub fn test_init_many_associated_token_accounts(
391+
_ctx: Context<InitManyAssociatedTokenAccounts>,
392+
) -> Result<()> {
393+
Ok(())
394+
}
388395
}

tests/misc/tests/misc/misc.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2451,6 +2451,15 @@ const miscTest = (
24512451
assert.deepStrictEqual(dataAccount.data, array2d);
24522452
});
24532453

2454+
it("Can initialize 5 associated token accounts in one instruction", async () => {
2455+
const mint = anchor.web3.Keypair.generate();
2456+
await program.methods
2457+
.testInitManyAssociatedTokenAccounts()
2458+
.accounts({ mint: mint.publicKey, user: provider.wallet.publicKey })
2459+
.signers([mint])
2460+
.rpc();
2461+
});
2462+
24542463
describe("Can validate PDAs derived from other program ids", () => {
24552464
it("With bumps using create_program_address", async () => {
24562465
const [firstPDA, firstBump] =

0 commit comments

Comments
 (0)