anchor_lang/traits.rs
1#[cfg(feature = "compat")]
2use pinocchio::account::{Ref, RefMut};
3use {
4 crate::require,
5 core::ops::Deref,
6 pinocchio::{
7 account::{AccountView, NOT_BORROWED},
8 address::Address,
9 instruction::InstructionAccount,
10 },
11 solana_program_error::{ProgramError, ProgramResult},
12};
13
14/// Zero-cost CPI handle that borrows an anchor account at the Rust level.
15///
16/// Obtained via [`AnchorAccount::cpi_handle`] (shared borrow) or by erasing a
17/// [`CpiHandleMut`] produced from [`AnchorAccount::cpi_handle_mut`].
18/// Handles participate in raw `AccountView` borrow validation before CPI by
19/// default. Wrappers with their own borrow-state discipline may opt out when
20/// the CPI account meta guarantees the callee cannot mutate the account.
21///
22/// Deliberately does NOT implement `Deref<Target = AccountView>` to
23/// prevent accidental use with pinocchio's checked invoke builders.
24#[derive(Clone, Copy)]
25pub struct CpiHandle<'a> {
26 view: &'a AccountView,
27 writable: bool,
28 borrow_check: bool,
29 relax_readonly_borrow: bool,
30}
31
32/// Typed mutable CPI handle for API-facing CPI account structs.
33///
34/// This carries the exclusive-borrow provenance at construction time, then
35/// erases into [`CpiHandle`] for invocation.
36#[derive(Clone, Copy)]
37pub struct CpiHandleMut<'a> {
38 view: &'a AccountView,
39 borrow_check: bool,
40}
41
42pub(crate) struct CpiBorrowGuard {
43 borrow_state: *mut u8,
44 restore_to: u8,
45}
46
47impl<'a> CpiHandle<'a> {
48 #[inline(always)]
49 pub fn readonly(view: &'a AccountView) -> Self {
50 Self::readonly_with_borrow_check(view, true)
51 }
52
53 #[inline(always)]
54 pub(crate) fn readonly_with_borrow_check(view: &'a AccountView, borrow_check: bool) -> Self {
55 Self::readonly_with_flags(view, borrow_check, false)
56 }
57
58 #[inline(always)]
59 pub(crate) fn readonly_with_flags(
60 view: &'a AccountView,
61 borrow_check: bool,
62 relax_readonly_borrow: bool,
63 ) -> Self {
64 Self {
65 view,
66 writable: false,
67 borrow_check,
68 relax_readonly_borrow,
69 }
70 }
71
72 #[inline(always)]
73 pub fn writable(view: &'a mut AccountView) -> Self {
74 Self::writable_with_borrow_check(view, true)
75 }
76
77 #[inline(always)]
78 pub(crate) fn writable_with_borrow_check(view: &'a AccountView, borrow_check: bool) -> Self {
79 Self {
80 view,
81 writable: true,
82 borrow_check,
83 relax_readonly_borrow: false,
84 }
85 }
86
87 /// The account's on-chain address.
88 ///
89 /// Returns a reference with the inner `'a` lifetime so callers can
90 /// build `InstructionAccount<'a>` values without tying the result to
91 /// the borrow of `&self`.
92 #[inline(always)]
93 pub fn address(&self) -> &'a Address {
94 self.view.address()
95 }
96
97 /// Whether this handle was obtained via `cpi_handle_mut`.
98 #[inline(always)]
99 pub fn is_writable(&self) -> bool {
100 self.writable
101 }
102
103 /// Whether the underlying account is a signer on the transaction.
104 #[inline(always)]
105 pub fn is_signer(&self) -> bool {
106 self.view.is_signer()
107 }
108
109 /// Erase to a readonly CPI handle.
110 ///
111 /// Used by `#[account_meta(duplicate_readonly)]` so a `CpiHandle` or
112 /// `CpiHandleMut` field can emit a second readonly meta/handle pair.
113 #[inline(always)]
114 pub fn into_readonly(self) -> CpiHandle<'a> {
115 Self::readonly_with_flags(self.view, self.borrow_check, self.relax_readonly_borrow)
116 }
117
118 /// Access the underlying `AccountView` for CPI account construction.
119 ///
120 /// Restricted to the crate so external code cannot extract the view
121 /// and pass it to pinocchio's checked invoke.
122 #[inline(always)]
123 pub(crate) fn account_view(&self) -> &'a AccountView {
124 self.view
125 }
126
127 #[inline(always)]
128 pub(crate) fn requires_borrow_check(&self) -> bool {
129 self.borrow_check
130 }
131
132 #[inline(always)]
133 pub(crate) fn enter_cpi(&self) -> Option<CpiBorrowGuard> {
134 if !self.writable && self.relax_readonly_borrow {
135 let borrow_state = self.view.account_ptr().cast_mut().cast::<u8>();
136 // Mutable Slab wrappers pin the runtime borrow state at `0` while
137 // the wrapper is alive. For readonly CPIs that state is too
138 // strong: the callee only needs shared borrows, and readonly metas
139 // prevent writes. Downgrade to a single shared borrow for the CPI
140 // and restore the exclusive marker afterwards.
141 unsafe { *borrow_state = NOT_BORROWED - 1 };
142 Some(CpiBorrowGuard {
143 borrow_state,
144 restore_to: 0,
145 })
146 } else {
147 None
148 }
149 }
150}
151
152impl<'a> CpiHandleMut<'a> {
153 #[inline(always)]
154 pub fn writable(view: &'a mut AccountView) -> Self {
155 Self::writable_with_borrow_check(view, true)
156 }
157
158 #[inline(always)]
159 pub(crate) fn without_borrow_check(view: &'a AccountView) -> Self {
160 Self::writable_with_borrow_check(view, false)
161 }
162
163 #[inline(always)]
164 fn writable_with_borrow_check(view: &'a AccountView, borrow_check: bool) -> Self {
165 Self { view, borrow_check }
166 }
167
168 /// The account's on-chain address.
169 #[inline(always)]
170 pub fn address(&self) -> &'a Address {
171 self.view.address()
172 }
173
174 /// Mutable handles always erase to writable CPI handles.
175 #[inline(always)]
176 pub fn is_writable(&self) -> bool {
177 true
178 }
179
180 /// Whether the underlying account is a signer on the transaction.
181 #[inline(always)]
182 pub fn is_signer(&self) -> bool {
183 self.view.is_signer()
184 }
185
186 /// Erase to a readonly [`CpiHandle`].
187 ///
188 /// Used by `#[account_meta(duplicate_readonly)]` so a writable field can
189 /// still emit a second readonly meta/handle pair.
190 #[inline(always)]
191 pub fn into_readonly(self) -> CpiHandle<'a> {
192 CpiHandle::readonly_with_borrow_check(self.view, self.borrow_check)
193 }
194}
195
196impl<'a> From<CpiHandleMut<'a>> for CpiHandle<'a> {
197 #[inline(always)]
198 fn from(handle: CpiHandleMut<'a>) -> Self {
199 Self {
200 view: handle.view,
201 writable: true,
202 borrow_check: handle.borrow_check,
203 relax_readonly_borrow: false,
204 }
205 }
206}
207
208impl Drop for CpiBorrowGuard {
209 fn drop(&mut self) {
210 unsafe { *self.borrow_state = self.restore_to };
211 }
212}
213
214pub(crate) fn enter_cpi<'a>(handles: &[CpiHandle<'a>]) -> alloc::vec::Vec<CpiBorrowGuard> {
215 let mut guards = alloc::vec::Vec::new();
216 for handle in handles {
217 if let Some(guard) = handle.enter_cpi() {
218 guards.push(guard);
219 }
220 }
221 guards
222}
223
224/// Converts a CPI accounts struct into instruction metadata and handles.
225///
226/// Implemented by generated CPI accounts structs. Each field maps to an
227/// [`InstructionAccount`] (address + writable/signer flags) and an erased
228/// [`CpiHandle`] for the actual invocation.
229pub trait ToCpiAccounts<'a> {
230 /// Produce instruction account metadata for the CPI instruction.
231 fn to_instruction_accounts(&self) -> alloc::vec::Vec<InstructionAccount<'a>>;
232
233 /// Collect all CPI handles for the invocation.
234 fn to_cpi_handles(&self) -> alloc::vec::Vec<CpiHandle<'a>>;
235
236 /// Parallel to [`to_instruction_accounts`]: `true` at each index where an
237 /// optional field was `None` and a program-id sentinel meta was emitted.
238 ///
239 /// The CPI invoker may skip a matching handle only for these indices.
240 /// Required accounts whose address equals the callee program id must be
241 /// `false` here so they still require a handle.
242 fn optional_account_sentinel_flags(&self) -> alloc::vec::Vec<bool>;
243}
244
245pub trait AnchorAccount: Deref<Target = Self::Data> + Sized {
246 type Data;
247
248 /// Whether this account wrapper requires the transaction account meta to
249 /// be marked as a signer in generated clients and CPI account structs.
250 const IS_SIGNER: bool = false;
251
252 /// Minimum account data length for this type. When > 0, PDA
253 /// verification can skip `sol_curve_validate_point`: a non-empty
254 /// account was created via CreateAccount/Allocate (which requires
255 /// signing), and `invoke_signed` already includes the curve check.
256 ///
257 /// Non-empty wrappers override this with their schema-specific minimum.
258 /// UncheckedAccount / zero-data wrappers leave it at `0` (forces the curve
259 /// check).
260 const MIN_DATA_LEN: usize = 0;
261
262 /// Whether readonly CPI handles borrowed from a mutable wrapper need their
263 /// runtime borrow marker temporarily relaxed during CPI entry.
264 ///
265 /// Wrappers that keep an exclusive marker alive after `load_mut()` (for
266 /// example `Account<T>` / `Slab<H, T>` and `SerializedAccount<T, S>`)
267 /// override this so derive-generated readonly CPI accounts can preserve
268 /// compatibility without reopening writable aliasing.
269 const RELAX_READONLY_CPI_BORROW_FROM_MUT: bool = false;
270
271 fn load(view: AccountView) -> core::result::Result<Self, ProgramError>;
272
273 /// Load an account for mutable access.
274 ///
275 /// # Safety
276 ///
277 /// No other live `&mut` to the same account data may exist while the
278 /// returned value is alive. In derive-generated code the bitvec
279 /// duplicate-account check enforces this; direct callers must uphold
280 /// it themselves.
281 ///
282 /// Default impl validates `is_writable` and delegates to `load()`.
283 /// Data-carrying wrappers (`Account<T>`, `BorshAccount<T>`, `Slab<H, T>`)
284 /// override to use `borrow_unchecked_mut` for write provenance.
285 /// `Signer` overrides with a fused `is_signer` + `is_writable` check.
286 #[inline(always)]
287 unsafe fn load_mut(view: AccountView) -> core::result::Result<Self, ProgramError> {
288 if !view.is_writable() {
289 return Err(crate::ErrorCode::ConstraintMut.into());
290 }
291 Self::load(view)
292 }
293
294 /// Like [`load_mut`], but called right after
295 /// `AccountInitialize::create_and_initialize`. Owner, discriminator,
296 /// and min-length checks are tautologies on this path, so data-carrying
297 /// wrappers override to skip them. Default forwards to [`load_mut`].
298 ///
299 /// # Safety
300 ///
301 /// Same as [`load_mut`]: no other live `&mut` to the same account data.
302 ///
303 /// [`load_mut`]: Self::load_mut
304 #[inline(always)]
305 unsafe fn load_mut_after_init(view: AccountView) -> core::result::Result<Self, ProgramError> {
306 Self::load_mut(view)
307 }
308
309 fn account(&self) -> &AccountView;
310
311 fn exit(&mut self) -> ProgramResult {
312 Ok(())
313 }
314
315 /// v1-compatible alias for the account address.
316 #[cfg(feature = "compat")]
317 #[inline(always)]
318 fn key(&self) -> crate::solana_program::pubkey::Pubkey {
319 *self.account().address()
320 }
321
322 /// Obtain a read-only CPI handle for this account.
323 ///
324 /// The handle borrows `self`, preventing mutable typed access while
325 /// it is alive. The handle's `is_writable` flag is `false`.
326 #[inline(always)]
327 fn cpi_handle(&self) -> CpiHandle<'_> {
328 CpiHandle::readonly(self.account())
329 }
330
331 /// Obtain a writable CPI handle for this account.
332 ///
333 /// The handle borrows `self` mutably, preventing any typed access
334 /// while it is alive.
335 ///
336 /// # Panics
337 ///
338 /// Panics if the underlying account is not marked writable in
339 /// the transaction.
340 #[inline(always)]
341 fn cpi_handle_mut(&mut self) -> CpiHandleMut<'_> {
342 self.try_cpi_handle_mut()
343 .expect("cpi_handle_mut called on a read-only account")
344 }
345
346 /// Fallible variant of [`cpi_handle_mut`](Self::cpi_handle_mut).
347 ///
348 /// Returns [`ProgramError::InvalidArgument`] when the underlying account
349 /// is not marked writable in the transaction.
350 #[inline(always)]
351 fn try_cpi_handle_mut(&mut self) -> Result<CpiHandleMut<'_>, ProgramError> {
352 require!(self.account().is_writable(), ProgramError::InvalidArgument);
353 Ok(CpiHandleMut::writable_with_borrow_check(
354 self.account(),
355 true,
356 ))
357 }
358}
359
360/// Account wrapper capability for `#[account(realloc = ...)]`.
361///
362/// The derive emits a call to this trait instead of deciding realloc safety
363/// from syntactic type names. That lets rustc resolve aliases and wrapper
364/// forwards normally: unsupported wrappers simply do not implement the trait.
365pub trait AccountRealloc: AnchorAccount {
366 fn realloc_account(
367 &mut self,
368 new_space: usize,
369 payer: AccountView,
370 zero: bool,
371 ) -> ProgramResult;
372}
373
374/// Account wrapper capability for `#[account(close = ...)]`.
375///
376/// The derive emits a call to this trait instead of deciding close support
377/// from syntactic type names. That lets rustc resolve aliases and wrapper
378/// forwards normally: unsupported wrappers (notably `UncheckedAccount`)
379/// simply do not implement the trait.
380#[diagnostic::on_unimplemented(
381 message = "`#[account(close = ...)]` is not supported on `UncheckedAccount`",
382 note = "use a typed account wrapper or close the raw account manually"
383)]
384pub trait AccountClose: AnchorAccount {
385 fn close(&mut self, destination: AccountView) -> ProgramResult;
386}
387
388/// Account-like value that can be passed into a CPI account struct.
389///
390/// This is the v2 equivalent of v1's `ToAccountInfo` for CPI construction:
391/// callers get a [`CpiHandle`] instead of cloning an `AccountInfo`.
392pub trait ToCpiHandle {
393 fn to_cpi_handle(&self) -> CpiHandle<'_>;
394}
395
396/// Account-like value that can be passed into a writable CPI account slot.
397pub trait ToCpiHandleMut {
398 fn try_to_cpi_handle_mut(&mut self) -> Result<CpiHandleMut<'_>, ProgramError>;
399
400 #[inline(always)]
401 fn to_cpi_handle_mut(&mut self) -> CpiHandleMut<'_> {
402 self.try_to_cpi_handle_mut()
403 .expect("to_cpi_handle_mut called on a read-only account")
404 }
405}
406
407impl<T: ToCpiHandle + ?Sized> ToCpiHandle for &T {
408 #[inline(always)]
409 fn to_cpi_handle(&self) -> CpiHandle<'_> {
410 (*self).to_cpi_handle()
411 }
412}
413
414impl<T: ToCpiHandle + ?Sized> ToCpiHandle for &mut T {
415 #[inline(always)]
416 fn to_cpi_handle(&self) -> CpiHandle<'_> {
417 (**self).to_cpi_handle()
418 }
419}
420
421impl<T: ToCpiHandleMut + ?Sized> ToCpiHandleMut for &mut T {
422 #[inline(always)]
423 fn try_to_cpi_handle_mut(&mut self) -> Result<CpiHandleMut<'_>, ProgramError> {
424 (**self).try_to_cpi_handle_mut()
425 }
426}
427
428impl ToCpiHandle for CpiHandle<'_> {
429 #[inline(always)]
430 fn to_cpi_handle(&self) -> CpiHandle<'_> {
431 *self
432 }
433}
434
435impl ToCpiHandle for CpiHandleMut<'_> {
436 #[inline(always)]
437 fn to_cpi_handle(&self) -> CpiHandle<'_> {
438 (*self).into()
439 }
440}
441
442impl ToCpiHandleMut for CpiHandleMut<'_> {
443 #[inline(always)]
444 fn try_to_cpi_handle_mut(&mut self) -> Result<CpiHandleMut<'_>, ProgramError> {
445 Ok(*self)
446 }
447}
448
449impl ToCpiHandle for AccountView {
450 #[inline(always)]
451 fn to_cpi_handle(&self) -> CpiHandle<'_> {
452 CpiHandle::readonly(self)
453 }
454}
455
456impl ToCpiHandleMut for AccountView {
457 #[inline(always)]
458 fn try_to_cpi_handle_mut(&mut self) -> Result<CpiHandleMut<'_>, ProgramError> {
459 require!(self.is_writable(), ProgramError::InvalidArgument);
460 Ok(CpiHandleMut::writable(self))
461 }
462}
463
464/// Account-like value that can provide its on-chain address.
465///
466/// This is intentionally implemented blanketly for every [`AnchorAccount`]:
467/// `AnchorAccount::account()` already exposes the underlying `AccountView`,
468/// so boxed and typed account wrappers can all be used uniformly as address
469/// field references in generated constraint code.
470pub trait AccountAddress {
471 fn account_address(&self) -> &Address;
472}
473
474impl<T: AnchorAccount> AccountAddress for T {
475 #[inline(always)]
476 fn account_address(&self) -> &Address {
477 self.account().address()
478 }
479}
480
481impl<T: AccountAddress> AccountAddress for Option<T> {
482 #[inline(always)]
483 fn account_address(&self) -> &Address {
484 self.as_ref()
485 .expect("optional account is None")
486 .account_address()
487 }
488}
489
490/// v1-compatible utility methods for raw remaining-account views.
491#[cfg(feature = "compat")]
492pub trait AccountViewCompat {
493 fn key(&self) -> crate::solana_program::pubkey::Pubkey;
494
495 fn data_is_empty(&self) -> bool;
496
497 fn try_data_len(&self) -> Result<usize, ProgramError>;
498
499 fn try_borrow_data(&self) -> Result<Ref<'_, [u8]>, ProgramError>;
500
501 fn try_borrow_mut_data(&mut self) -> Result<RefMut<'_, [u8]>, ProgramError>;
502}
503
504#[cfg(feature = "compat")]
505impl AccountViewCompat for AccountView {
506 #[inline(always)]
507 fn key(&self) -> crate::solana_program::pubkey::Pubkey {
508 *self.address()
509 }
510
511 #[inline(always)]
512 fn data_is_empty(&self) -> bool {
513 self.data_len() == 0
514 }
515
516 #[inline(always)]
517 fn try_data_len(&self) -> Result<usize, ProgramError> {
518 Ok(self.data_len())
519 }
520
521 #[inline(always)]
522 fn try_borrow_data(&self) -> Result<Ref<'_, [u8]>, ProgramError> {
523 self.try_borrow()
524 }
525
526 #[inline(always)]
527 fn try_borrow_mut_data(&mut self) -> Result<RefMut<'_, [u8]>, ProgramError> {
528 self.try_borrow_mut()
529 }
530}
531
532/// Lamports related utility methods for accounts.
533pub trait Lamports: AsRef<AccountView> {
534 /// Get the lamports of the account.
535 #[inline(always)]
536 fn get_lamports(&self) -> u64 {
537 self.as_ref().lamports()
538 }
539
540 /// Add lamports to the account.
541 ///
542 /// This method is useful for transferring lamports from a PDA.
543 ///
544 /// # Requirements
545 ///
546 /// 1. The account must be marked `mut`.
547 /// 2. The total lamports before the transaction must equal the total
548 /// lamports after the transaction.
549 ///
550 /// See [`Lamports::sub_lamports`] for subtracting lamports.
551 #[inline(always)]
552 fn add_lamports(&self, amount: u64) -> Result<&Self, ProgramError> {
553 let mut view = *self.as_ref();
554 view.set_lamports(
555 self.get_lamports()
556 .checked_add(amount)
557 .ok_or(ProgramError::ArithmeticOverflow)?,
558 );
559 Ok(self)
560 }
561
562 /// Subtract lamports from the account.
563 ///
564 /// This method is useful for transferring lamports from a PDA.
565 ///
566 /// # Requirements
567 ///
568 /// 1. The account must be owned by the executing program.
569 /// 2. The account must be marked `mut`.
570 /// 3. The total lamports before the transaction must equal the total
571 /// lamports after the transaction.
572 ///
573 /// See [`Lamports::add_lamports`] for adding lamports.
574 #[inline(always)]
575 fn sub_lamports(&self, amount: u64) -> Result<&Self, ProgramError> {
576 let mut view = *self.as_ref();
577 view.set_lamports(
578 self.get_lamports()
579 .checked_sub(amount)
580 .ok_or(ProgramError::ArithmeticOverflow)?,
581 );
582 Ok(self)
583 }
584}
585
586impl<T: AsRef<AccountView>> Lamports for T {}
587
588/// Declares which program owns accounts of this data type.
589///
590/// For your own program's types, `#[account]` generates this automatically
591/// from the program's declared ID.
592///
593/// External crates implement this with their program's address:
594/// ```ignore
595/// impl Owner for TokenAccountData {
596/// const OWNER: Address = Token::ID;
597/// }
598/// ```
599pub trait Owner {
600 const OWNER: Address;
601}
602
603/// Declares the on-chain address for a program marker type.
604///
605/// `Address` is re-exported from `pinocchio`, which itself re-exports
606/// `solana_address::Address`. That means built-in markers such as
607/// `Token::id()` and `System::id()` can be passed directly to modern Solana
608/// instruction APIs that use `Address` or compatibility aliases named
609/// `Pubkey`.
610pub trait Id {
611 fn id() -> Address;
612 /// Well-known base58 program address for IDL emission. Empty string
613 /// signals "no address to advertise in the IDL" — consumed by
614 /// `IdlAccountType::__IDL_ADDRESS` on `Program<T>` and converted to
615 /// `None` there.
616 const IDL_ADDRESS: &'static str = "";
617}
618
619/// Declares multiple valid on-chain addresses for an interface program marker.
620pub trait Ids {
621 fn ids() -> &'static [Address];
622}
623
624pub trait Discriminator {
625 const DISCRIMINATOR: &'static [u8];
626}
627
628/// Client-side account deserialization. Mirrors v1 anchor-lang's trait so
629/// `anchor-client` can fetch raw account bytes and decode them into the
630/// user's `#[account]` struct. Generated account impls expect `buf` to start
631/// at the full account bytes, including the reserved discriminator prefix. The
632/// `#[account]` macro emits two impl bodies:
633///
634/// - Borsh mode (`#[account(borsh)]`): check disc, run `BorshDeserialize`.
635/// - Pod mode (default): check disc, `bytemuck::pod_read_unaligned` on
636/// the post-disc bytes.
637///
638/// Not used by the on-chain account wrappers (`BorshAccount` / `Slab`),
639/// which read directly from `AccountView` borrows; this is purely the
640/// off-chain client helper.
641pub trait AccountDeserialize: Sized {
642 /// Verify the leading discriminator and decode. Generated impls perform
643 /// the discriminator check; the default forwards to
644 /// `try_deserialize_unchecked`.
645 fn try_deserialize(buf: &mut &[u8]) -> Result<Self, ProgramError> {
646 Self::try_deserialize_unchecked(buf)
647 }
648
649 /// Decode without verifying the discriminator. Generated account impls
650 /// still skip over the reserved discriminator region before decoding the
651 /// payload, but they do not check the prefix bytes. Used during
652 /// initialization when the bytes are zero or otherwise not yet stamped
653 /// with the disc.
654 fn try_deserialize_unchecked(buf: &mut &[u8]) -> Result<Self, ProgramError>;
655}
656
657/// Wrapper-level init: creates the on-chain account and returns a loaded
658/// `Self`. `Slab<H, T>` and `BorshAccount<T>` get this automatically;
659/// custom wrappers implement it directly.
660pub trait AccountInitialize: Sized {
661 type Params<'a>: Default;
662
663 fn create_and_initialize<'a>(
664 payer: &AccountView,
665 account: &AccountView,
666 space: usize,
667 owner: &Address,
668 params: &Self::Params<'a>,
669 signer_seeds: Option<&[&[u8]]>,
670 payer_signer_seeds: Option<&[&[u8]]>,
671 ) -> Result<Self, ProgramError>;
672}
673
674/// Marker for account wrappers that may be allocated with an explicit
675/// foreign owner through `#[account(init, owner = ...)]`.
676///
677/// Typed account wrappers intentionally do not implement this: their init
678/// paths stamp and load Anchor-owned data, so they must stay owned by the
679/// current program. `UncheckedAccount` is the escape hatch for allocating
680/// bytes that a foreign program will initialize or validate later.
681pub trait ForeignOwnerInit: AccountInitialize {}
682
683// ---------------------------------------------------------------------------
684// Extensible constraint system
685// ---------------------------------------------------------------------------
686
687/// Trait implemented by each constraint marker type for every account
688/// type it applies to. Each method defaults to `Ok(())`, so CHECK-only
689/// constraints only need to override `check`, INIT-only constraints
690/// only override `init`, etc.
691///
692/// # Lifecycle mapping
693///
694/// | `#[account(...)]` spelling | Methods called |
695/// |----------------------------------------------------|-----------------------|
696/// | `ns::key = v` (non-init field) | `check` |
697/// | `init, ns::key = v` | `init` |
698/// | `init_if_needed, ns::key = v` (creating) | `init`, then `check` |
699/// | `init_if_needed, ns::key = v` (already exists) | `check` |
700/// | `update(ns::key = v)` | `update` (post-validation) |
701/// | Any of the above | `exit` (exit phase) |
702///
703/// There is deliberately **no blanket `impl<T: AccountConstraint<A>>
704/// AccountConstraint<Option<A>> for T`** mirroring the `Box<T>` forwarder
705/// in `accounts/boxed.rs`. Constraint calls on `Option<Field>` are emitted
706/// by the derive inline as `if let Some(ref inner) = self.maybe_x { …
707/// inline call … }` — they never dispatch through a blanket impl.
708///
709/// # Extending with third-party constraints
710///
711/// Any crate can define new constraint markers and implement
712/// `AccountConstraint<SomeAccount>` for them. The derive routes
713/// `ns::key = v`, `init`/`init_if_needed`-paired constraints, and the
714/// `update(...)` wrapper through the appropriate method.
715///
716/// ```ignore
717/// pub mod my_ns {
718/// use anchor_lang::AccountConstraint;
719/// use pinocchio::program_error::ProgramError;
720///
721/// pub struct MinBalanceConstraint;
722///
723/// impl AccountConstraint<MyAccount> for MinBalanceConstraint {
724/// type Value = u64;
725/// fn check(account: &MyAccount, min: &u64) -> Result<(), ProgramError> {
726/// if account.account().lamports() < *min {
727/// return Err(ProgramError::InsufficientFunds);
728/// }
729/// Ok(())
730/// }
731/// }
732/// }
733///
734/// #[derive(Accounts)]
735/// pub struct MyInstruction {
736/// #[account(mut, my_ns::min_balance = 1_000_000)]
737/// pub data: MyAccount,
738/// }
739/// ```
740pub trait AccountConstraint<A> {
741 /// The expected value type for this constraint. This is the type of
742 /// the RHS expression in `#[account(namespace::key = <expr>)]`.
743 ///
744 /// Common choices:
745 /// - `Address` for address comparisons (default for most constraints)
746 /// - `AccountView` for constraints that need the full account view
747 /// - `u8` / `u64` for numeric constraints
748 type Value;
749
750 /// Creation hook. Invoked on `init` and on the create branch of
751 /// `init_if_needed` — whenever the account is being freshly
752 /// produced by this instruction — after `AccountInitialize::
753 /// create_and_initialize` has run. Mutable access so the
754 /// constraint can stamp additional state.
755 #[inline(always)]
756 fn init(_account: &mut A, _value: &Self::Value) -> core::result::Result<(), ProgramError> {
757 Ok(())
758 }
759
760 /// Runtime validation. Invoked on non-init fields and on the
761 /// already-exists branch of `init_if_needed`. Read-only.
762 #[inline(always)]
763 fn check(_account: &A, _value: &Self::Value) -> core::result::Result<(), ProgramError> {
764 Ok(())
765 }
766
767 /// Mutating hook. Invoked only when the constraint is written
768 /// inside an `update(...)` wrapper, e.g.
769 /// `#[account(update(my_ns::field = value))]`. Intended for
770 /// constraints that set / rewrite on-chain state rather than
771 /// validating it. Runs after `try_accounts` has finished all
772 /// account validations, but before the instruction handler.
773 #[inline(always)]
774 fn update(_account: &mut A, _value: &Self::Value) -> core::result::Result<(), ProgramError> {
775 Ok(())
776 }
777
778 /// Exit hook. Called during `AccountsExit::exit_accounts()` for
779 /// every constraint attached to the field, regardless of how the
780 /// field was introduced. Use for state that must be flushed on a
781 /// successful instruction.
782 #[inline(always)]
783 fn exit(_account: &mut A, _value: &Self::Value) -> core::result::Result<(), ProgramError> {
784 Ok(())
785 }
786}
787
788pub struct Nested<T>(pub T);
789
790impl<T> Deref for Nested<T> {
791 type Target = T;
792 fn deref(&self) -> &T {
793 &self.0
794 }
795}
796
797impl<T> core::ops::DerefMut for Nested<T> {
798 fn deref_mut(&mut self) -> &mut T {
799 &mut self.0
800 }
801}
802
803#[doc(hidden)]
804impl<T: crate::IdlAccountType> crate::IdlAccountType for Nested<T> {
805 const __IDL_ACCOUNT_ENTRY: Option<&'static str> = T::__IDL_ACCOUNT_ENTRY;
806 const __IDL_TYPE_DEF: Option<&'static str> = T::__IDL_TYPE_DEF;
807 fn __idl_account_entry() -> Option<&'static str> {
808 T::__idl_account_entry()
809 }
810 fn __idl_type_def() -> Option<&'static str> {
811 T::__idl_type_def()
812 }
813 fn __register_idl_deps(
814 accounts: &mut ::alloc::vec::Vec<&'static str>,
815 types: &mut ::alloc::vec::Vec<&'static str>,
816 ) {
817 T::__register_idl_deps(accounts, types);
818 }
819}