Skip to main content

ExternalAccount

Struct ExternalAccount 

Source
pub struct ExternalAccount<'info, T: ExternalZeroCopy> { /* private fields */ }
Expand description

Validated handle to a known external account.

This wrapper is intentionally transparent over AccountView. It proves the adapter’s ExternalZeroCopy::validate contract, but it does not imply a Hopper header is present. Use ExternalAccount::data or adapter helper methods to read bytes, and keep raw AccountView/UncheckedAccount for accounts that truly have no known schema.

Implementations§

Source§

impl<'info, T: ExternalZeroCopy> ExternalAccount<'info, T>

Source

pub unsafe fn new_unchecked(view: &'info AccountView<'info>) -> Self

Wrap an account that has already been validated by T.

§Safety

Caller must have verified T::validate(view) for this account.

Source

pub fn try_new(view: &'info AccountView<'info>) -> Result<Self, ProgramError>

Validate and bind a known external account.

Source

pub fn as_account(&self) -> &'info AccountView<'info>

The underlying account view.

Source

pub fn key(&self) -> &Address

The account public key.

Source

pub fn owner(&self) -> Address

The owning program, copied out of the account header.

Source

pub fn data_len(&self) -> usize

Current external account data length.

Source

pub fn data(&self) -> Result<Ref<'info, [u8]>, ProgramError>

Borrow the external account bytes after adapter validation.

Source

pub fn with_data<R, F>(&self, f: F) -> Result<R, ProgramError>
where F: FnOnce(&[u8]) -> Result<R, ProgramError>,

Borrow the bytes for the duration of a closure.

Source

pub fn view(&self) -> Result<T::View<'info>, ProgramError>

Borrow and decode the adapter’s typed zero-copy view.

Source

pub fn with_view<R, F>(&self, f: F) -> Result<R, ProgramError>
where F: FnOnce(T::View<'info>) -> Result<R, ProgramError>,

Borrow the typed zero-copy view for the duration of a closure.

Source

pub fn checked<P>(self) -> Result<ExternalChecked<'info, T, P>, ProgramError>
where P: ExternalProof<T>,

Verify an adapter-specific proof and carry its token with the account.

Source

pub fn require_owner(&self, owner: &Address) -> Result<&Self, ProgramError>

Require a specific owner in fluent external-account code.

Source

pub fn lens<V: ExternalLensValue, const OFFSET: usize>( &self, ) -> Result<ExternalLens<'info, V, OFFSET>, ProgramError>

Borrow a checked offset lens into this external account’s bytes.

Source

pub fn snapshot_hash(&self) -> Result<Sha256Hash, ProgramError>

Hash the external account bytes for CPI/oracle consistency checks.

Source

pub fn assert_snapshot(&self, expected: &Sha256Hash) -> ProgramResult

Verify the external account bytes still match a previous snapshot.

Source

pub fn assert_unchanged_after<R, F>(&self, f: F) -> Result<R, ProgramError>
where F: FnOnce() -> Result<R, ProgramError>,

Run a closure and verify this external account is unchanged afterward.

Source§

impl<'info, T> ExternalAccount<'info, T>
where T: ExplainExternal,

Source

pub fn explain<S: ExternalExplainSink>(&self, sink: &mut S) -> ProgramResult

Emit structured external explain fields through the supplied sink.

Source§

impl<'info, T> ExternalAccount<'info, T>

Source

pub fn resolve(&self) -> Result<T::Resolved<'info>, ProgramError>

Resolve this external account into an owner-selected view family.

Source§

impl<'info> ExternalAccount<'info, SplTokenAccount>

Source§

impl<'info> ExternalAccount<'info, SplMint>

Source

pub fn checked_decimals( &self, expected: u8, ) -> Result<CheckedMintDecimals<'info>, ProgramError>

Methods from Deref<Target = AccountView<'info>>§

Source

pub fn address(&self) -> &Address

The account’s public key.

Source

pub unsafe fn owner(&self) -> &Address

The owning program’s address.

§Safety

The returned reference is invalidated if the account is assigned to a new owner. The caller must ensure no concurrent mutation.

Source

pub fn read_owner(&self) -> Address

Read the owner address as a copy (safe, no aliasing hazard).

Source

pub fn owned_by(&self, program: &Address) -> bool

Whether this account is owned by the given program.

Source

pub fn is_signer(&self) -> bool

Whether this account signed the transaction.

Source

pub fn is_writable(&self) -> bool

Whether this account is writable in the transaction.

Source

pub fn executable(&self) -> bool

Whether this account contains an executable program.

Source

pub fn data_len(&self) -> usize

Current data length in bytes.

Source

pub fn lamports(&self) -> u64

Current lamport balance.

Source

pub fn is_data_empty(&self) -> bool

Whether the account data is empty.

Source

pub fn try_set_lamports(&self, lamports: u64) -> ProgramResult

Try to set the lamport balance.

Backends such as solana-program enforce lamport borrow rules at runtime. Use this in framework code so borrow conflicts return a ProgramError instead of panicking.

Source

pub fn set_lamports(&self, lamports: u64) -> ProgramResult

Set the lamport balance.

Source

pub fn try_borrow(&self) -> Result<Ref<'_, [u8]>, ProgramError>

Try to obtain a shared borrow of the account data.

Source

pub fn try_borrow_mut(&self) -> Result<RefMut<'_, [u8]>, ProgramError>

Try to obtain an exclusive (mutable) borrow of the account data.

Touch-map note: this RAW byte surface does not stamp the touch log, segment leases route their exclusive borrows through here and would smear every narrow lease into a whole-account record, destroying the map’s field precision. The TYPED whole-account surfaces (load_mut / load_compact_mut) record instead.

Ambient-gate note: under a bound strict_writes context this raw whole-account write borrow is governed, the instruction-ambient gate refuses it unless the declared policy covers the full data range, closing the historical “raw borrow bypasses the write policy” surface. With no gate installed the check is one load and branch. Segment leases use the crate-internal ungated variant because they gate the exact range themselves; the migration crank uses it under its own check_migratable authorization (a whole-layout transform, distinct from the byte-range gate; see the crate-private try_borrow_mut_ungated helper.

Source

pub fn segment_ref<'a, T: Pod>( &'a self, borrows: &'a mut SegmentBorrowRegistry, abs_offset: u32, size: u32, ) -> Result<SegRef<'a, T>, ProgramError>

Project a typed segment from this account with segment-level borrow tracking.

The runtime validates the requested byte range, registers a leased read borrow in the provided instruction-scoped registry, and returns a SegRef<T> that releases the lease on drop. This replaces the earlier “instruction-sticky” behaviour: the registry entry is now tied to the returned guard’s lifetime, so sequential patterns like let x = segment_ref…; drop(x); let y = segment_ref…; work exactly the way Rust callers expect.

On the native backend (Solana), the inner Ref<T> uses the flat {ptr, state} representation, no dummy slice guard, no intermediate Ref<[u8]>.

The explicit 'a lifetime binds the returned SegRef<'a, T> to the shorter of &self (the account) and &mut borrows (the registry). Either outliving the other would let the guard dangle.

Source

pub fn segment_mut<'a, T: Pod>( &'a self, borrows: &'a mut SegmentBorrowRegistry, abs_offset: u32, size: u32, ) -> Result<SegRefMut<'a, T>, ProgramError>

Project a mutable typed segment. Mirror of Self::segment_ref; the returned SegRefMut<T> carries both the account-level exclusive borrow guard and the segment-registry lease, so dropping it is a full release, no lingering entries.

Under a bound strict_writes context the instruction-ambient gate checks this EXACT byte range against the declared write policy, so direct segment access outside a Context is governed too (the Context methods enforce the same installed policy before delegating to the ungated internal variant, paying the check once).

Source

pub fn split_segments_mut<'a, T: Pod, const N: usize>( &'a self, borrows: &'a mut SegmentBorrowRegistry, ranges: [(u32, u32); N], ) -> Result<SegmentsMut<'a, T, N>, ProgramError>

Borrow several disjoint byte ranges of one account as independent typed &mut guards at the same time.

This is the ergonomic answer to “I need mutable access to two fields of the same account simultaneously”. A single segment_mut call exclusively borrows the registry for the returned guard’s lifetime, so two segment_mut calls cannot coexist. split_segments_mut registers all N ranges up front, proving pairwise disjointness once through the borrow registry, and returns an array of N guards that live together and each release their lease on drop.

Every range is (abs_offset, size) where size == size_of::<T>(). Overlapping ranges are rejected with AccountBorrowFailed; an out-of-bounds or wrong-size range is rejected with InvalidArgument / AccountDataTooSmall, and any already-claimed leases from the batch are rolled back before returning.

ⓘ
// Mutate balance and nonce of the same vault at once.
let [mut bal, mut nonce] =
    vault.split_segments_mut::<WireU64, 2>(ctx.borrows_mut(),
        [(BALANCE_OFF, 8), (NONCE_OFF, 8)])?;
bal.set(bal.get() + amount);
nonce.set(nonce.get() + 1);
Source

pub fn segment_ref_const<'a, T: Pod>( &'a self, borrows: &'a mut SegmentBorrowRegistry, segment: Segment, ) -> Result<SegRef<'a, T>, ProgramError>

Project a typed segment described by a compile-time crate::Segment.

This is the “const-driven” access form the Hopper design demands: the offset and size come from a const SEG: Segment = ...; declaration generated by #[hopper::state] or written by hand, so the call collapses to a single ptr + const_offset add on Solana SBF. No runtime string lookup, no dynamic map, no search.

segment.offset is the absolute offset from the start of account data (i.e. past the Hopper header already folded in). Construct it via Segment::new(offset, size) or Segment::body(body_offset, size), the latter adds HopperHeader::SIZE for you.

ⓘ
const BALANCE: Segment = Segment::body(0, 8);
let mut balance = vault.segment_ref_const::<u64>(&mut borrows, BALANCE)?;
Source

pub fn segment_mut_const<'a, T: Pod>( &'a self, borrows: &'a mut SegmentBorrowRegistry, segment: Segment, ) -> Result<SegRefMut<'a, T>, ProgramError>

Mutable const-Segment access. See Self::segment_ref_const for the contract, this is the exclusive variant.

Source

pub fn segment_ref_typed<'a, T: Pod, const OFFSET: u32>( &'a self, borrows: &'a mut SegmentBorrowRegistry, _segment: TypedSegment<T, OFFSET>, ) -> Result<SegRef<'a, T>, ProgramError>

Project a typed segment described by a crate::TypedSegment.

This is the tightest form of segment access Hopper exposes: both the type T and the offset are compile-time constants baked into the crate::TypedSegment marker, so the call collapses to a single ptr + literal_offset add with a literal size in the bounds check. The marker argument is a zero-sized token, free to pass around.

ⓘ
const BALANCE: TypedSegment<WireU64, { HopperHeader::SIZE as u32 }>
    = TypedSegment::new();
let bal = vault.segment_ref_typed(&mut borrows, BALANCE)?;
Source

pub fn segment_mut_typed<'a, T: Pod, const OFFSET: u32>( &'a self, borrows: &'a mut SegmentBorrowRegistry, _segment: TypedSegment<T, OFFSET>, ) -> Result<SegRefMut<'a, T>, ProgramError>

Mutable typed-segment access. See Self::segment_ref_typed for the contract, this is the exclusive variant.

Source

pub fn load<T: LayoutContract + Pod>(&self) -> Result<Ref<'_, T>, ProgramError>

Load a typed layout after validating the account header.

This is the canonical “validate then project” path:

  1. Check disc, version, and layout_id match T
  2. Verify data length >= T::SIZE
  3. Return zero-copy reference into account data

The returned reference begins at T::TYPE_OFFSET. Body-only layouts project past the Hopper header; header-inclusive layouts project the full account struct from byte 0.

§Example
ⓘ
let vault = account.load::<Vault>()?;
Source

pub fn with<T, R, F>(&self, f: F) -> Result<R, ProgramError>
where T: LayoutContract + Pod, F: FnOnce(&T) -> Result<R, ProgramError>,

Borrow a typed layout for the duration of a closure.

This is the ergonomic safe path for read-only handlers: Hopper still validates the header and holds the data borrow guard, while user code gets a plain &T inside the closure.

Source

pub fn load_mut<T: LayoutContract + Pod>( &self, ) -> Result<RefMut<'_, T>, ProgramError>

Load a mutable typed layout after validating the account header.

Same as load() but provides a mutable reference for in-place state updates. Changes write directly to account data.

§Example
ⓘ
let mut vault = account.load_mut::<Vault>()?;
vault.balance = vault.balance.checked_add(amount)?;
Source

pub fn with_mut<T, R, F>(&self, f: F) -> Result<R, ProgramError>

Mutably borrow a typed layout for the duration of a closure.

This keeps the zero-copy borrow guard scoped to the closure while making common updates read like direct state mutation.

Source

pub fn load_compact<T: CompactLayout>(&self) -> Result<Ref<'_, T>, ProgramError>

Load a Tier-1 compact layout: [disc:u8][zero-copy body].

The hot path is check_len_exact + check_disc + project-body-at-byte-1. Unlike load there is no 16-byte header, no layout_id read, and no schema-epoch comparison. Layout identity is a program-level fact (the Tier-2 registry), not a per-account one.

§Example
ⓘ
let vault = account.load_compact::<Vault>()?;
Source

pub fn load_compact_mut<T: CompactLayout>( &self, ) -> Result<RefMut<'_, T>, ProgramError>

Mutable Tier-1 compact load. See load_compact.

Source

pub fn with_compact<T, R, F>(&self, f: F) -> Result<R, ProgramError>
where T: CompactLayout, F: FnOnce(&T) -> Result<R, ProgramError>,

Borrow a compact layout for the duration of a closure (read-only).

Source

pub fn with_compact_mut<T, R, F>(&self, f: F) -> Result<R, ProgramError>

Mutably borrow a compact layout for the duration of a closure.

Source

pub fn init_compact<T: CompactLayout>(&self) -> ProgramResult

Initialise a compact account by stamping the discriminator byte.

Writes T::DISC at byte 0; the body is left as-is (callers typically follow with load_compact_mut to populate it). Requires the account to be writable and exactly T::COMPACT_LEN bytes long.

Source

pub fn load_compact_dynamic<T: CompactDynamicLayout>( &self, ) -> Result<Ref<'_, T>, ProgramError>

Tier-1 compact dynamic load: validate the discriminator and the minimum length, then project the fixed head at COMPACT_BODY_OFFSET.

Unlike load_compact, the account may be longer than the fixed head: the trailing bytes are the dynamic tail, left untouched here and accessed through the generated tail_* helpers. This is the [disc:u8][fixed_head][tail] analogue of load’s tolerance of a headered dynamic tail.

§Example
ⓘ
let head = account.load_compact_dynamic::<Market>()?;   // fixed head
let data = account.try_borrow()?;
let tail = Market::tail_read(&data)?;                   // dynamic tail
Source

pub fn load_compact_dynamic_mut<T: CompactDynamicLayout>( &self, ) -> Result<RefMut<'_, T>, ProgramError>

Mutable Tier-1 compact-dynamic load of the fixed head. See load_compact_dynamic.

Source

pub fn with_compact_dynamic<T, R, F>(&self, f: F) -> Result<R, ProgramError>

Borrow a compact-dynamic fixed head for the duration of a closure.

Source

pub fn with_compact_dynamic_mut<T, R, F>(&self, f: F) -> Result<R, ProgramError>

Mutably borrow a compact-dynamic fixed head for the duration of a closure.

Source

pub fn init_compact_dynamic<T: CompactDynamicLayout>(&self) -> ProgramResult

Initialise a compact-dynamic account: stamp T::DISC at byte 0 and, if the account was allocated with room for a tail, zero the tail’s u32 length prefix so a fresh account reads as an empty tail rather than uninitialized bytes (fail-closed init).

Requires the account to be writable and at least T::MIN_LEN bytes (discriminator + fixed head). The tail region may be larger to reserve growth headroom.

Source

pub unsafe fn raw_ref<T: Pod>(&self) -> Result<Ref<'_, T>, ProgramError>

Explicit raw typed read of the account buffer.

This bypasses Hopper layout validation and segment tracking, but it still respects the account-level borrow rules enforced by try_borrow().

§Safety

Caller must uphold the invariants documented for this unsafe API before invoking it.

Source

pub unsafe fn raw_mut<T: Pod>(&self) -> Result<RefMut<'_, T>, ProgramError>

Explicit raw typed write of the account buffer.

This bypasses Hopper layout validation and segment tracking, but it still enforces writability and the account-level exclusive borrow rules.

§Safety

Caller must uphold the invariants documented for this unsafe API before invoking it.

Source

pub fn load_cross_program<T: LayoutContract + Pod>( &self, ) -> Result<Ref<'_, T>, ProgramError>

Load a cross-program layout without ownership checks.

Validates the layout contract but does not check that the account is owned by this program. Use for cross-program reads where the account is owned by another program and you need a typed, zero-copy view of its data.

Full contract validation ensures ABI compatibility: if the other program changes its layout identity or schema epoch, this fails rather than silently misinterpreting bytes.

§Example
ⓘ
let other_vault = foreign_account.load_cross_program::<OtherVault>()?;
Source

pub fn layout_info(&self) -> Option<LayoutInfo>

Read runtime layout metadata from this account’s header.

Returns None if the account data is too short for a Hopper header. This is useful for runtime inspection, manager tooling, and schema checking when the concrete layout type is not known at compile time.

Source

pub fn extension_range<T: LayoutContract>( &self, ) -> Result<Range<usize>, ProgramError>

Return the extension-region byte range for a layout that declares one.

Callers can apply the returned range to a borrowed data slice when they want to inspect or mutate extension bytes explicitly.

Source

pub fn extension_bytes<T: LayoutContract>( &self, ) -> Result<Ref<'_, [u8]>, ProgramError>

Borrow the extension/tail region declared by a layout contract.

Source

pub fn extension_bytes_mut<T: LayoutContract>( &self, ) -> Result<RefMut<'_, [u8]>, ProgramError>

Mutably borrow the extension/tail region declared by a layout contract.

Source

pub fn zero_range(&self, start: usize, len: usize) -> ProgramResult

Zero the byte range [start, start + len), checked against the instruction-ambient write policy over exactly that range.

This is the precise-authority spelling of “clear these bytes.” The naive alternative, take a whole-account try_borrow_mut and slice, demands authority over every byte of the account, so a narrow but entirely legitimate declaration (a tail(seq) grant zero-filling the tail it just grew) would be refused by its own policy. Gating the exact range keeps the refusal honest: it fires when the bytes being cleared are outside the declaration, and not before.

An empty range is a no-op and requires no authority.

Source

pub fn zero_appended(&self, previous_len: usize) -> ProgramResult

Zero the bytes a grow just appended: [previous_len, data_len).

Authorized by the transition dimension, not the byte-range one, deliberately, and this is the whole reason it is a separate method from zero_range:

  • The bytes did not exist when the policy was declared. Clearing them cannot destroy, reveal, or corrupt any state a byte-range declaration protects, so requiring a declared range over them would refuse the framework’s own realloc_zero lifecycle on every narrow declaration (mut(seg) + realloc) while protecting nothing.
  • The authority to create them was already checked: resize consults check_account_transition, and an account carrying no declared data authority cannot resize in the first place. Same check here, so this method can never reach an account the instruction has no data authority over.
  • It is strictly narrower than the pre-existing body: a caller cannot name an offset, only “whatever the grow added.”

Writes into the PRE-EXISTING body remain governed by the byte-range policy through every other surface.

Source

pub fn init_layout<T: LayoutContract>(&self) -> ProgramResult

Initialize an account with the given layout contract header.

Writes the disc, version, layout_id, and zeroes flags/reserved. Call this when creating a new account before writing field data.

Source

pub fn require_signer(&self) -> ProgramResult

Validate that this account is a signer.

Source

pub fn require_writable(&self) -> ProgramResult

Validate that this account is writable.

Source

pub fn require_owned_by(&self, program: &Address) -> ProgramResult

Validate that this account is owned by the given program.

Source

pub fn require_payer(&self) -> ProgramResult

Validate signer + writable (common “payer” pattern).

Source

pub fn check_signer(&self) -> Result<&Self, ProgramError>

Chainable signer check.

Source

pub fn check_writable(&self) -> Result<&Self, ProgramError>

Chainable writable check.

Source

pub fn check_owned_by(&self, program: &Address) -> Result<&Self, ProgramError>

Chainable ownership check.

Source

pub fn check_owned_by_any( &self, programs: &[&Address], ) -> Result<&Self, ProgramError>

Chainable check that this account’s owner is one of programs.

Accepts an account from any of several programs, most commonly an SPL Token or Token-2022 mint / token account, and rejects every other owner. This is check_owned_by generalized to a set; an empty programs slice always rejects.

Source

pub fn check_disc(&self, expected: u8) -> Result<&Self, ProgramError>

Chainable discriminator check.

Source

pub fn check_has_data(&self) -> Result<&Self, ProgramError>

Chainable non-empty data check.

Source

pub fn check_executable(&self) -> Result<&Self, ProgramError>

Chainable executable check.

Source

pub fn check_address(&self, expected: &Address) -> Result<&Self, ProgramError>

Chainable address check.

Source

pub fn check_data_len(&self, min_len: usize) -> Result<&Self, ProgramError>

Chainable minimum data length check.

Source

pub fn check_version(&self, expected: u8) -> Result<&Self, ProgramError>

Chainable version check.

Source

pub fn check_layout<T: LayoutContract>(&self) -> Result<&Self, ProgramError>

Chainable full layout contract check (disc + version + layout_id + size).

Source

pub fn proof(&self) -> AccountProof<'_>

Start a proof-carrying validation chain for this account.

Source

pub fn disc(&self) -> u8

Read the Hopper account discriminator (first byte of data).

Source

pub fn version(&self) -> u8

Read the Hopper account version (second byte of data).

Source

pub fn layout_id(&self) -> Option<&[u8; 8]>

Read the 8-byte layout_id from the Hopper account header (bytes 4..12).

Source

pub fn require_disc(&self, expected: u8) -> ProgramResult

Verify that this account has the given discriminator.

Source

pub fn flags(&self) -> u8

Pack the account’s boolean flags into a single byte.

Bit layout: bit 0 = signer, bit 1 = writable, bit 2 = executable, bit 3 = has data.

Delegates to the native backend, which extracts signer/writable/ executable from one packed-u32 header read instead of three separate byte loads.

Source

pub fn expect_flags(&self, required: u8) -> ProgramResult

Check that the account’s flags contain all required bits.

Source

pub fn expect_signer_writable( &self, need_signer: bool, need_writable: bool, ) -> ProgramResult

Fused signer/writable validation (the generated-context hot path).

Validates both requirements with a single packed-flags read and one masked compare, the same shape a hand-rolled header & MASK == MASK check compiles to, since need_signer / need_writable are compile-time literals at every macro call site and this function is #[inline(always)]. On mismatch it falls back to the individual checks so the error stays precise (MissingRequiredSignature vs Immutable); the fallback runs only on the failure path, where compute cost is irrelevant.

Source

pub fn resize(&self, new_len: usize) -> ProgramResult

Resize the account data, zeroing any newly exposed region on growth.

See hopper_native::AccountView::resize for why zero-on-growth is the safe default. Use resize_raw for the hot path when the caller overwrites the grown region in full.

Source

pub fn resize_raw(&self, new_len: usize) -> ProgramResult

Resize the account data without zero-filling the grown region.

Source

pub unsafe fn assign(&self, new_owner: &Address)

Assign a new owner.

§Safety

The caller must ensure the account is writable and that ownership transfer is authorized.

Source

pub fn close(&self) -> ProgramResult

Close the account: zero lamports and data.

Source

pub fn close_to( &self, destination: &AccountView<'_>, program_id: &Address, ) -> ProgramResult

Close the account, transferring remaining lamports to destination.

Idiomatic Solana close pattern: move all lamports to the destination account, then zero this account’s data so the runtime garbage-collects it at the end of the transaction.

§Preconditions (enforced)

Per Solana’s account modification rules (only the owning program can debit lamports or mutate data on a writable account), this method requires:

  • self must be writable, otherwise the runtime will reject the commit anyway, but we fail fast here rather than let the transaction progress through an invalid state.
  • self must be owned by program_id, the program that is executing this instruction. Without this check the safe API would silently encourage patterns that only Solana’s post-instruction verifier catches.
  • destination must be writable, receiving lamports requires write permission on the credit side.

A same-address recipient is rejected. Borrow conflicts, both lamport policies, and credit overflow are checked before data or balances change, including when the caller catches a returned error.

Source

pub fn close_to_unchecked(&self, destination: &AccountView<'_>) -> ProgramResult

Unchecked variant of Self::close_to.

Retained for the rare caller that has already verified the preconditions (e.g. inside a validated #[hopper::context] binding). It omits the owner and destination-writable checks; callers must establish both. Source writability, active data borrows, distinct addresses, checked credit arithmetic, and installed policies still apply.

“Unchecked” waives only those two preconditions. The ambient write gate is not a precondition a caller can pre-verify; it is the instruction’s installed policy, and closing an account both zeroes its data and ends its presence, so the same transition rule as close / close_to applies here (the lamport moves are separately governed by the gated try_set_lamports funnel below).

Source

pub fn check_borrow(&self) -> Result<(), ProgramError>

Check that the account can be shared-borrowed.

Source

pub fn check_borrow_mut(&self) -> Result<(), ProgramError>

Check that the account can be exclusively borrowed.

Source

pub unsafe fn borrow_unchecked(&self) -> &[u8]

Borrow account data without tracking.

§Safety

The caller must ensure no mutable borrow is active.

Source

pub unsafe fn borrow_unchecked_mut(&self) -> &mut [u8] ⓘ

Mutably borrow account data without tracking.

§Safety

The caller must ensure no other borrows are active.

Source

pub unsafe fn resize_unchecked(&self, new_len: usize)

Resize without bounds checking.

§Safety

The caller must guarantee the new length is within the permitted increase.

Source

pub unsafe fn close_unchecked(&self)

Close without borrow checks.

§Safety

The caller must ensure no active borrows exist.

Trait Implementations§

Source§

impl<'info, T: ExternalZeroCopy> Clone for ExternalAccount<'info, T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'info, T: ExternalZeroCopy> Copy for ExternalAccount<'info, T>

Source§

impl<T: ExternalZeroCopy> Debug for ExternalAccount<'_, T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'info, T: ExternalZeroCopy> Deref for ExternalAccount<'info, T>

Source§

type Target = AccountView<'info>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &AccountView<'info>

Dereferences the value.

Auto Trait Implementations§

§

impl<'info, T> !Send for ExternalAccount<'info, T>

§

impl<'info, T> !Sync for ExternalAccount<'info, T>

§

impl<'info, T> Freeze for ExternalAccount<'info, T>
where PhantomData<T>: Freeze,

§

impl<'info, T> RefUnwindSafe for ExternalAccount<'info, T>

§

impl<'info, T> Unpin for ExternalAccount<'info, T>
where PhantomData<T>: Unpin,

§

impl<'info, T> UnsafeUnpin for ExternalAccount<'info, T>

§

impl<'info, T> UnwindSafe for ExternalAccount<'info, T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.