Skip to main content

ReadonlyView

Struct ReadonlyView 

Source
pub struct ReadonlyView<'info> { /* private fields */ }
Expand description

An AccountView proven to be a non-signer, non-writable read-only account. Useful for cross-program reads where you explicitly want to prevent accidental mutation attempts.

Implementations§

Source§

impl<'info> ReadonlyView<'info>

Source

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

Validate that the account is neither a signer nor writable.

Source

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

Access the underlying AccountView.

Source

pub fn into_view(self) -> AccountView<'info>

Consume and return the inner AccountView.

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

Source

pub const SYSTEM_PROGRAM_ID: Address

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 or closed. The caller must ensure no concurrent mutation occurs.

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 original_data_len(&self) -> usize

Original data length captured by the entrypoint for this invocation.

Solana reserves the four bytes at header offset 4 for this value. It must remain unchanged across local resizes and CPI so every resize is checked against one invocation-wide baseline.

Source

pub fn resize_delta(&self) -> i32

Difference between the current and original data length.

Source

pub fn lamports(&self) -> u64

Current lamport balance.

Source

pub fn is_data_empty(&self) -> bool

Whether the account data is empty (data_len == 0).

Source

pub fn set_lamports(&self, lamports: u64)

Set the lamport balance.

Source

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

Check whether this account is owned by the given program.

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 by the current owner program.

Source

pub fn is_borrowed(&self) -> bool

Whether the account data is currently borrowed (shared or exclusive).

Source

pub fn is_borrowed_mut(&self) -> bool

Whether the account data is exclusively (mutably) borrowed.

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 borrow 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 borrow tracking.

§Safety

The caller must ensure no other borrows (shared or exclusive) are active.

Source

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

Try to obtain a shared borrow of the account data.

Returns Err(AccountBorrowFailed) if the data is exclusively borrowed.

Source

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

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

Returns Err(AccountBorrowFailed) if the data is already borrowed.

Source

pub fn segment_ref<T: Pod>( &self, offset: u32, size: u32, ) -> Result<Ref<'_, T>, ProgramError>

Project a typed segment from account data with native borrow tracking.

Source

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

Acquire a shared segment borrow without size/bounds validation.

§Safety

The caller must have already verified:

  • offset + size_of::<T>() does not overflow
  • offset + size_of::<T>() <= data_len()
  • no exclusive borrow overlapping [offset, offset + size_of::<T>()) is live for the returned reference’s lifetime (this method performs no borrow tracking)
Source

pub fn segment_mut<T: Pod>( &self, offset: u32, size: u32, ) -> Result<RefMut<'_, T>, ProgramError>

Project a mutable typed segment from account data with native borrow tracking.

Source

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

Acquire an exclusive segment borrow without size/bounds/writable validation.

§Safety

The caller must have already verified:

  • The account is writable
  • offset + size_of::<T>() does not overflow
  • offset + size_of::<T>() <= data_len()
  • no other borrow (shared or exclusive) overlapping [offset, offset + size_of::<T>()) is live for the returned reference’s lifetime (this method performs no borrow tracking)
Source

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

Explicit raw typed read of the account buffer.

§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.

§Safety

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

Source

pub fn check_resize(&self, new_len: usize) -> Result<(), ProgramError>

Check every precondition of resize without changing the account: the account must be writable, no data borrow may be live, and new_len may exceed the entry-time length by at most MAX_PERMITTED_DATA_INCREASE. A no-op resize to the current length always passes.

Callers that move lamports before resizing (rent top-ups) run this first so a refused resize cannot leave the transfer behind.

Source

pub fn resize(&self, new_len: usize) -> Result<(), ProgramError>

Resize the account data to new_len bytes, zeroing any newly exposed region.

Returns Err(InvalidRealloc) if the new length exceeds the permitted increase from the original allocation.

When the account grows, the bytes in [old_len, new_len) are zero-filled. The Solana loader zeroes the realloc reserve once at the start of an instruction, but a shrink-then-grow within a single instruction can re-expose previously written bytes; zeroing on growth makes that impossible. Use resize_raw for the hot path when the caller will overwrite the grown region in full and has measured the saved memset.

Source

pub fn resize_raw(&self, new_len: usize) -> Result<(), ProgramError>

Resize without zero-filling the newly exposed region.

Same bounds check as resize but skips the zero-fill on growth. Prefer resize unless the caller immediately overwrites the entire grown region; otherwise stale bytes from an earlier shrink within the same instruction can leak into the new region.

Source

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

Resize without bounds checking or zero-filling.

§Safety

The caller must guarantee that the account is writable, no data borrow is live, and new_len.saturating_sub(original_data_len) <= MAX_PERMITTED_DATA_INCREASE. The caller is also responsible for any zero-fill of the grown region (see resize for why that matters).

Source

pub fn close(&self) -> ProgramResult

Close the account: zero lamports and data, reassign owner to the System Program.

Fails with AccountBorrowFailed if any data borrow (shared or exclusive) is outstanding: closing memsets the entire data region, which would mutate memory a live Ref/RefMut still points at. Use close_unchecked only when the caller can prove no borrow is live.

§Caveat

This low-level routine does not verify the caller has ownership or application authority to close the account. Writability and outstanding data borrows are checked locally. Solana’s runtime also enforces account modification rules, but higher-level APIs (e.g. hopper_runtime::AccountView::close_to) should pre-check those rules. See account.rs::close_to for the safe wrapper.

Source

pub unsafe fn close_unchecked(&self)

Close without borrow checks.

§Safety

The caller must ensure no active borrows exist.

Source

pub fn account_ptr(&self) -> *const RuntimeAccount

Raw pointer to the RuntimeAccount header.

Source

pub fn require_signer(&self) -> ProgramResult

Validate that this account is a signer, returning a typed error.

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 disc(&self) -> u8

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

Returns 0 if the account has no data.

Source

pub fn version(&self) -> u8

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

Returns 0 if the account has fewer than 2 bytes.

Source

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

Read the 8-byte layout_id from the Hopper account header (bytes 4..12 of account data, per the canonical header format).

Returns None if the account has fewer than 12 bytes.

Source

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

Verify that this account has the given discriminator.

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_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 read_owner(&self) -> Address

Read the owner address as a copy (32-byte value).

Unlike owner() (which is unsafe due to reference invalidation if assign() is called), this returns a copy that is always safe. Costs 32 bytes of stack space but eliminates aliasing hazards.

Source

pub fn flags(&self) -> u8

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

Bit layout:

  • bit 0: is_signer
  • bit 1: is_writable
  • bit 2: executable
  • bit 3: has data (data_len > 0)

Use with expect_flags() for single-instruction multi-check:

ⓘ
// Require: signer + writable + has data
account.expect_flags(0b1011)?;
Source

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

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

required is a bitmask of flags that must be set. See flags().

Source

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

Fast fused signer/writable predicate over the packed header word.

Answers “are the requested signer/writable bytes both set” with a single 4-byte header read and one masked compare ((header_u32 & mask) == expected), never touching data_len, unlike flags, which also folds in the has-data bit via is_data_empty(). need_signer/need_writable are compile-time literals at every call site and this is #[inline(always)], so mask and expected fold to constants and the whole check is one and plus one cmp.

Behaviourally identical to today’s flags()-based signer/writable gate: the loader serializes is_signer/is_writable as exactly 0 or 1, so for those bytes “equals the expected 1 pattern” and “byte non-zero” coincide. Callers that need the precise per-condition error must fall back to require_signer/require_writable on a false return (see hopper_runtime::AccountView::expect_signer_writable).

Trait Implementations§

Source§

impl<'info> Clone for ReadonlyView<'info>

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> Deref for ReadonlyView<'info>

Source§

type Target = AccountView<'info>

The resulting type after dereferencing.
Source§

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

Dereferences the value.
Source§

impl<'info> Eq for ReadonlyView<'info>

Source§

impl<'info> PartialEq for ReadonlyView<'info>

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl<'info> StructuralPartialEq for ReadonlyView<'info>

Auto Trait Implementations§

§

impl<'info> !Send for ReadonlyView<'info>

§

impl<'info> !Sync for ReadonlyView<'info>

§

impl<'info> Freeze for ReadonlyView<'info>

§

impl<'info> RefUnwindSafe for ReadonlyView<'info>

§

impl<'info> Unpin for ReadonlyView<'info>

§

impl<'info> UnsafeUnpin for ReadonlyView<'info>

§

impl<'info> UnwindSafe for ReadonlyView<'info>

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.