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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ The minor version will be incremented upon a breaking change and the patch versi
- idl: Fix `address` constraint not resolving constants that have numbers in their identifiers ([#4144](https://github.com/solana-foundation/anchor/pull/4144)).
- lang: Fix constant nested string generation in `declare_program!` ([#4158](https://github.com/solana-foundation/anchor/pull/4158)).
- idl: Fix `local_file` method not found for `proc_macro2::Span` error ([#4187](https://github.com/solana-foundation/anchor/pull/4187)).
- lang: Relax duplicate mutable account constraint to only check types that serialize on exit (`Account`, `LazyAccount`, `InterfaceAccount`, `Migration`) ([#4202](https://github.com/solana-foundation/anchor/pull/4202)).

### Breaking

Expand Down
6 changes: 3 additions & 3 deletions bench/BINARY_SIZE.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ The programs and their tests are located in [/tests/bench](https://github.com/co

Solana version: 2.3.0

| Program | Binary Size | - |
| ------- | ----------- | ----------------------- |
| bench | 1,015,624 | 🟢 **-111,216 (9.87%)** |
| Program | Binary Size | - |
| ------- | ----------- | ------------------------ |
| bench | 932,992 | 🟢 **-193,848 (17.20%)** |

### Notable changes

Expand Down
114 changes: 57 additions & 57 deletions bench/COMPUTE_UNITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,93 +18,93 @@ Solana version: 2.3.0

| Instruction | Compute Units | - |
| --------------------------- | ------------- | --------------------- |
| accountInfo1 | 760 | 🔴 **+75 (10.95%)** |
| accountInfo2 | 1,180 | 🔴 **+127 (12.06%)** |
| accountInfo4 | 1,952 | 🔴 **+202 (11.54%)** |
| accountInfo8 | 3,530 | 🔴 **+395 (12.60%)** |
| accountInfo1 | 702 | 🔴 **+17 (2.48%)** |
| accountInfo2 | 1,115 | 🔴 **+62 (5.89%)** |
| accountInfo4 | 1,921 | 🔴 **+171 (9.77%)** |
| accountInfo8 | 3,480 | 🔴 **+345 (11.00%)** |
| accountEmptyInit1 | 4,770 | 🟢 **-145 (2.95%)** |
| accountEmpty1 | 773 | 🟢 **-1 (0.13%)** |
| accountEmpty1 | 738 | 🟢 **-36 (4.65%)** |
| accountEmptyInit2 | 8,487 | 🟢 **-306 (3.48%)** |
| accountEmpty2 | 1,173 | 🟢 **-1 (0.09%)** |
| accountEmpty2 | 1,138 | 🟢 **-36 (3.07%)** |
| accountEmptyInit4 | 15,915 | 🟢 **-833 (4.97%)** |
| accountEmpty4 | 1,960 | 🟢 **-2 (0.10%)** |
| accountEmpty4 | 1,923 | 🟢 **-39 (1.99%)** |
| accountEmptyInit8 | 30,779 | 🟢 **-1,578 (4.88%)** |
| accountEmpty8 | 3,539 | 🟢 **-9 (0.25%)** |
| accountEmpty8 | 3,500 | 🟢 **-48 (1.35%)** |
| accountSizedInit1 | 4,864 | 🟢 **-155 (3.09%)** |
| accountSized1 | 820 | 🟢 **-2 (0.24%)** |
| accountSized1 | 786 | 🟢 **-36 (4.38%)** |
| accountSizedInit2 | 8,654 | 🟢 **-327 (3.64%)** |
| accountSized2 | 1,236 | 🟢 **-4 (0.32%)** |
| accountSized2 | 1,198 | 🟢 **-42 (3.39%)** |
| accountSizedInit4 | 16,236 | 🟢 **-918 (5.35%)** |
| accountSized4 | 2,070 | 🟢 **-12 (0.58%)** |
| accountSized4 | 2,031 | 🟢 **-51 (2.45%)** |
| accountSizedInit8 | 31,363 | 🟢 **-1,650 (5.00%)** |
| accountSized8 | 3,731 | 🟢 **-31 (0.82%)** |
| accountSized8 | 3,694 | 🟢 **-68 (1.81%)** |
| accountUnsizedInit1 | 4,967 | 🟢 **-160 (3.12%)** |
| accountUnsized1 | 854 | 🟢 **-20 (2.29%)** |
| accountUnsized1 | 814 | 🟢 **-60 (6.86%)** |
| accountUnsizedInit2 | 8,841 | 🟢 **-410 (4.43%)** |
| accountUnsized2 | 1,281 | 🟢 **-45 (3.39%)** |
| accountUnsized2 | 1,240 | 🟢 **-86 (6.49%)** |
| accountUnsizedInit4 | 16,559 | 🟢 **-819 (4.71%)** |
| accountUnsized4 | 2,134 | 🟢 **-97 (4.35%)** |
| accountUnsized4 | 2,093 | 🟢 **-138 (6.19%)** |
| accountUnsizedInit8 | 31,985 | 🟢 **-1,976 (5.82%)** |
| accountUnsized8 | 3,837 | 🟢 **-198 (4.91%)** |
| accountUnsized8 | 3,797 | 🟢 **-238 (5.90%)** |
| boxedAccountEmptyInit1 | 4,864 | 🟢 **-143 (2.86%)** |
| boxedAccountEmpty1 | 864 | - |
| boxedAccountEmpty1 | 831 | 🟢 **-33 (3.82%)** |
| boxedAccountEmptyInit2 | 8,604 | 🟢 **-302 (3.39%)** |
| boxedAccountEmpty2 | 1,285 | 🟢 **-1 (0.08%)** |
| boxedAccountEmpty2 | 1,253 | 🟢 **-33 (2.57%)** |
| boxedAccountEmptyInit4 | 16,075 | 🟢 **-827 (4.89%)** |
| boxedAccountEmpty4 | 2,112 | 🟢 **-3 (0.14%)** |
| boxedAccountEmpty4 | 2,077 | 🟢 **-38 (1.80%)** |
| boxedAccountEmptyInit8 | 31,026 | 🟢 **-1,565 (4.80%)** |
| boxedAccountEmpty8 | 3,797 | 🟢 **-4 (0.11%)** |
| boxedAccountSizedInit1 | 4,952 | 🟢 **-151 (2.96%)** |
| boxedAccountSized1 | 913 | 🔴 **+1 (0.11%)** |
| boxedAccountSized1 | 877 | 🟢 **-35 (3.84%)** |
| boxedAccountSizedInit2 | 8,756 | 🟢 **-319 (3.52%)** |
| boxedAccountSized2 | 1,351 | 🟢 **-4 (0.30%)** |
| boxedAccountSized2 | 1,318 | 🟢 **-37 (2.73%)** |
| boxedAccountSizedInit4 | 16,355 | 🟢 **-859 (4.99%)** |
| boxedAccountSized4 | 2,218 | 🟢 **-13 (0.58%)** |
| boxedAccountSized4 | 2,185 | 🟢 **-46 (2.06%)** |
| boxedAccountSizedInit8 | 31,562 | 🟢 **-1,959 (5.84%)** |
| boxedAccountSized8 | 3,984 | 🟢 **-23 (0.57%)** |
| boxedAccountUnsizedInit1 | 5,044 | 🟢 **-158 (3.04%)** |
| boxedAccountUnsized1 | 943 | 🟢 **-21 (2.18%)** |
| boxedAccountUnsized1 | 907 | 🟢 **-57 (5.91%)** |
| boxedAccountUnsizedInit2 | 8,916 | 🟢 **-335 (3.62%)** |
| boxedAccountUnsized2 | 1,386 | 🟢 **-48 (3.35%)** |
| boxedAccountUnsized2 | 1,352 | 🟢 **-82 (5.72%)** |
| boxedAccountUnsizedInit4 | 16,651 | 🟢 **-891 (5.08%)** |
| boxedAccountUnsized4 | 2,270 | 🟢 **-97 (4.10%)** |
| boxedAccountUnsized4 | 2,234 | 🟢 **-133 (5.62%)** |
| boxedAccountUnsizedInit8 | 32,130 | 🟢 **-2,023 (5.92%)** |
| boxedAccountUnsized8 | 4,063 | 🟢 **-194 (4.56%)** |
| boxedInterfaceAccountMint1 | 1,128 | 🔴 **+18 (1.62%)** |
| boxedInterfaceAccountMint2 | 1,523 | 🟢 **-11 (0.72%)** |
| boxedInterfaceAccountMint4 | 2,307 | 🟢 **-63 (2.66%)** |
| boxedInterfaceAccountMint1 | 1,090 | 🟢 **-20 (1.80%)** |
| boxedInterfaceAccountMint2 | 1,486 | 🟢 **-48 (3.13%)** |
| boxedInterfaceAccountMint4 | 2,268 | 🟢 **-102 (4.30%)** |
| boxedInterfaceAccountMint8 | 3,907 | 🟢 **-157 (3.86%)** |
| boxedInterfaceAccountToken1 | 1,255 | 🔴 **+9 (0.72%)** |
| boxedInterfaceAccountToken2 | 1,765 | 🟢 **-29 (1.62%)** |
| boxedInterfaceAccountToken4 | 2,779 | 🟢 **-99 (3.44%)** |
| boxedInterfaceAccountToken1 | 1,217 | 🟢 **-29 (2.33%)** |
| boxedInterfaceAccountToken2 | 1,728 | 🟢 **-66 (3.68%)** |
| boxedInterfaceAccountToken4 | 2,740 | 🟢 **-138 (4.79%)** |
| boxedInterfaceAccountToken8 | 4,839 | 🟢 **-229 (4.52%)** |
| interfaceAccountMint1 | 1,145 | 🔴 **+19 (1.69%)** |
| interfaceAccountMint2 | 1,533 | 🟢 **-29 (1.86%)** |
| interfaceAccountMint4 | 2,313 | 🟢 **-119 (4.89%)** |
| interfaceAccountMint1 | 1,105 | 🟢 **-21 (1.87%)** |
| interfaceAccountMint2 | 1,490 | 🟢 **-72 (4.61%)** |
| interfaceAccountMint4 | 2,268 | 🟢 **-164 (6.74%)** |
| interfaceAccountMint8 | 3,835 | 🟢 **-328 (7.88%)** |
| interfaceAccountToken1 | 1,279 | 🔴 **+11 (0.87%)** |
| interfaceAccountToken2 | 1,792 | 🟢 **-57 (3.08%)** |
| interfaceAccountToken4 | 2,825 | 🟢 **-172 (5.74%)** |
| interface1 | 918 | 🔴 **+40 (4.56%)** |
| interface2 | 1,064 | 🔴 **+41 (4.01%)** |
| interface4 | 1,345 | 🔴 **+44 (3.38%)** |
| interface8 | 1,912 | 🔴 **+45 (2.41%)** |
| program1 | 934 | 🔴 **+44 (4.94%)** |
| program2 | 1,084 | 🔴 **+49 (4.73%)** |
| program4 | 1,373 | 🔴 **+60 (4.57%)** |
| program8 | 1,956 | 🔴 **+77 (4.10%)** |
| signer1 | 923 | 🔴 **+49 (5.61%)** |
| signer2 | 1,272 | 🔴 **+99 (8.44%)** |
| signer4 | 1,957 | 🔴 **+198 (11.26%)** |
| signer8 | 3,332 | 🔴 **+391 (13.29%)** |
| systemAccount1 | 945 | 🔴 **+34 (3.73%)** |
| systemAccount2 | 1,304 | 🔴 **+69 (5.59%)** |
| systemAccount4 | 2,009 | 🔴 **+138 (7.38%)** |
| systemAccount8 | 3,424 | 🔴 **+271 (8.59%)** |
| uncheckedAccount1 | 931 | 🔴 **+49 (5.56%)** |
| uncheckedAccount2 | 1,263 | 🔴 **+101 (8.69%)** |
| uncheckedAccount4 | 1,911 | 🔴 **+195 (11.36%)** |
| uncheckedAccount8 | 3,207 | 🔴 **+374 (13.20%)** |
| interfaceAccountToken1 | 1,237 | 🟢 **-31 (2.44%)** |
| interfaceAccountToken2 | 1,749 | 🟢 **-100 (5.41%)** |
| interfaceAccountToken4 | 2,775 | 🟢 **-222 (7.41%)** |
| interface1 | 883 | 🔴 **+5 (0.57%)** |
| interface2 | 1,029 | 🔴 **+6 (0.59%)** |
| interface4 | 1,308 | 🔴 **+7 (0.54%)** |
| interface8 | 1,873 | 🔴 **+6 (0.32%)** |
| program1 | 899 | 🔴 **+9 (1.01%)** |
| program2 | 1,049 | 🔴 **+14 (1.35%)** |
| program4 | 1,336 | 🔴 **+23 (1.75%)** |
| program8 | 1,917 | 🔴 **+38 (2.02%)** |
| signer1 | 888 | 🔴 **+14 (1.60%)** |
| signer2 | 1,237 | 🔴 **+64 (5.46%)** |
| signer4 | 1,920 | 🔴 **+161 (9.15%)** |
| signer8 | 3,293 | 🔴 **+352 (11.97%)** |
| systemAccount1 | 910 | 🟢 **-1 (0.11%)** |
| systemAccount2 | 1,269 | 🔴 **+34 (2.75%)** |
| systemAccount4 | 1,972 | 🔴 **+101 (5.40%)** |
| systemAccount8 | 3,385 | 🔴 **+232 (7.36%)** |
| uncheckedAccount1 | 896 | 🔴 **+14 (1.59%)** |
| uncheckedAccount2 | 1,227 | 🔴 **+65 (5.59%)** |
| uncheckedAccount4 | 1,875 | 🔴 **+159 (9.27%)** |
| uncheckedAccount8 | 3,171 | 🔴 **+338 (11.93%)** |

### Notable changes

Expand Down
16 changes: 11 additions & 5 deletions docs/content/docs/references/account-constraints.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,14 @@ Examples: [Github](https://github.com/solana-developers/anchor-examples/tree/mai

### `#[account(dup)]`

Description: By default, Anchor will prevents duplicate mutable accounts to avoid potential security issues and unintended behavior.
The `dup` constraint explicitly allows this for cases where it's intentional and safe.
Description: By default, Anchor prevents duplicate mutable accounts to avoid
potential security issues and unintended behavior. The `dup` constraint
explicitly allows this for cases where it's intentional and safe.

**Note**: This constraint only applies to mutable accounts (`mut`). Readonly accounts naturally allow duplicates without requiring the `dup` constraint.
**Note**: This constraint only applies to mutable account (`mut`) types that
serialize on exit. Other types like `UncheckedAccount`, `Signer`,
`SystemAccount`, `AccountLoader`, `Program`, and `Interface` naturally allow
duplicates as they don't serialize data on exit.

```rust title="attribute"
#[account(mut, dup)]
Expand Down Expand Up @@ -330,7 +334,8 @@ Description: Create or validate close authority extension on the mint account.

### `#[account(extensions::permanent_delegate::*)]`

Description: Create or validate permanent delegate extension on the mint account.
Description: Create or validate permanent delegate extension on the mint
account.

```rust title="attribute"
#[account(
Expand Down Expand Up @@ -362,7 +367,8 @@ Description: Create or validate group pointer extension on the mint account.

### `#[account(extensions::group_member_pointer::*)]`

Description: Create or validate group member pointer extension on the mint account.
Description: Create or validate group member pointer extension on the mint
account.

```rust title="attribute"
#[account(
Expand Down
4 changes: 3 additions & 1 deletion lang/derive/accounts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ use syn::parse_macro_input;
/// Allows the same mutable account to be passed multiple times within the same instruction context.<br>
/// By default, Anchor will prevents duplicate mutable accounts to avoid potential security issues and unintended behavior.<br>
/// The <code>dup</code> constraint explicitly allows this for cases where it's intentional and safe.<br>
/// This constraint only applies to mutable accounts (<code>mut</code>). Readonly accounts naturally allow duplicates without requiring the <code>dup</code> constraint.<br>
/// This constraint only applies to mutable account (`mut`) types that serialize on exit. Other types like <br>
/// `UncheckedAccount`, `Signer`, `SystemAccount`, `AccountLoader`, `Program`, `Interface` and Readonly accounts <br>
/// naturally allow duplicates as they don't serialize data on exit.<br>
/// Example:
/// <pre><code>
/// #[account(mut)]
Expand Down
13 changes: 10 additions & 3 deletions lang/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,13 @@ pub trait AccountsExit<'info>: ToAccountMetas + ToAccountInfos<'info> {
}
}

/// Returns the pubkeys of mutable accounts that serialize on exit.
/// Used by the duplicate mutable account validation to check across
/// composite (nested) account struct boundaries.
pub trait DuplicateMutableAccountKeys {
fn duplicate_mutable_account_keys(&self) -> Vec<Pubkey>;
}

/// The close procedure to initiate garabage collection of an account, allowing
/// one to retrieve the rent exemption.
pub trait AccountsClose<'info>: ToAccountInfos<'info> {
Expand Down Expand Up @@ -493,9 +500,9 @@ pub mod prelude {
require_keys_neq, require_neq,
solana_program::bpf_loader_upgradeable::UpgradeableLoaderState, source,
system_program::System, zero_copy, AccountDeserialize, AccountSerialize, Accounts,
AccountsClose, AccountsExit, AnchorDeserialize, AnchorSerialize, Discriminator, Id,
InitSpace, Key, Lamports, Owner, Owners, ProgramData, Result, Space, ToAccountInfo,
ToAccountInfos, ToAccountMetas,
AccountsClose, AccountsExit, AnchorDeserialize, AnchorSerialize, Discriminator,
DuplicateMutableAccountKeys, Id, InitSpace, Key, Lamports, Owner, Owners, ProgramData,
Result, Space, ToAccountInfo, ToAccountInfos, ToAccountMetas,
};
// Re-export the crate as anchor_lang for declare_program! macro
pub use crate as anchor_lang;
Expand Down
Loading
Loading