Skip to main content

WritableView

Struct WritableView 

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

An AccountView that has been proven to be writable.

Guarantees that is_writable() == true without re-checking.

Implementations§

Source§

impl<'info> WritableView<'info>

Source

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

Validate that the account is writable and return a capability token.

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 authority to close the account, Solana’s runtime enforces owner/writable rules at transaction commit time regardless, 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 WritableView<'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 WritableView<'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 WritableView<'info>

Source§

impl<'info> PartialEq for WritableView<'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 WritableView<'info>

Auto Trait Implementations§

§

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

§

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

§

impl<'info> Freeze for WritableView<'info>

§

impl<'info> RefUnwindSafe for WritableView<'info>

§

impl<'info> Unpin for WritableView<'info>

§

impl<'info> UnsafeUnpin for WritableView<'info>

§

impl<'info> UnwindSafe for WritableView<'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.