Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
41 changes: 32 additions & 9 deletions lang/attribute/program/src/declare_program/mods/parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,17 +133,40 @@ fn gen_instruction(idl: &Idl) -> proc_macro2::TokenStream {
let name = format_ident!("{}", acc.name);
let signer = acc.signer;
let writable = acc.writable;
quote! {
#name: {
let acc = accs.next().ok_or_else(|| ProgramError::NotEnoughAccountKeys)?;
if acc.is_signer != #signer {
return Err(ProgramError::InvalidAccountData.into());
let optional = acc.optional;
if optional {
// For optional accounts, the program ID is used as a placeholder when missing
let program_id = get_canonical_program_id();
quote! {
#name: {
let acc = accs.next().ok_or_else(|| ProgramError::NotEnoughAccountKeys)?;
// Check if this is a placeholder (program_id used for missing optional accounts)
if acc.pubkey == #program_id {
None
} else {
if acc.is_signer != #signer {
return Err(ProgramError::InvalidAccountData.into());
}
if acc.is_writable != #writable {
return Err(ProgramError::InvalidAccountData.into());
}
Some(acc.pubkey)
}
}
if acc.is_writable != #writable {
return Err(ProgramError::InvalidAccountData.into());
}
} else {
quote! {
#name: {
let acc = accs.next().ok_or_else(|| ProgramError::NotEnoughAccountKeys)?;
if acc.is_signer != #signer {
return Err(ProgramError::InvalidAccountData.into());
}
if acc.is_writable != #writable {
return Err(ProgramError::InvalidAccountData.into());
}

acc.pubkey
}

acc.pubkey
}
}
}
Expand Down
45 changes: 45 additions & 0 deletions tests/declare-program/idls/optional.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"address": "GjYjDUDpPNhE72Gw7ktmP81QqzZhx4LYPfFawrk3ucDA",
"metadata": {
"name": "anchor_1_0_0_rc_2_optional_bug",
"version": "0.1.0",
"spec": "0.1.0",
"description": "Created with Anchor"
},
"instructions": [
{
"name": "initialize",
"discriminator": [
175,
175,
109,
31,
13,
152,
155,
237
],
"accounts": [
{
"name": "optional_account",
"optional": true
}
],
"args": []
}
],
"errors": [
{
"code": 6000,
"name": "CustomError",
"msg": "Custom error message"
}
],
"constants": [
{
"name": "SEED",
"type": "string",
"value": "\"anchor\""
}
]
}
4 changes: 4 additions & 0 deletions tests/declare-program/programs/declare-program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ declare_program!(external_legacy);
// https://github.com/raydium-io/raydium-idl/blob/6123104304ebcb42be175cc297a2c221ac96bb96/raydium_clmm/amm_v3.json
declare_program!(amm_v3);

// Compilation check for optional accounts
// https://github.com/solana-foundation/anchor/issues/4179
declare_program!(optional);
Comment thread
acheroncrypto marked this conversation as resolved.
Outdated

#[program]
pub mod declare_program {
use super::*;
Expand Down