Stricter ABI and Runtime Constraints
- Idea
- Draft
- Review
- Accept
- Implement
- Active
Decision brief
Why this proposal matters
Removing pitfalls and foot-guns from the ABI (including syscalls) and runtime.
Proposal at a glance
What changes
- Readonly data (0x100000000..0x200000000)
- Stack (0x200000000..0x300000000)
- Heap (0x300000000..0x400000000)
Stakeholder map
Who is affected
Builders & client teams Medium impact
Programs which used the SDKs account realloc function, which is now deprecated, should upgrade in order to avoid the read-before-write access to uninitialized memory.
Action may be requiredValidators & operators Medium impact
Programs which used the SDKs account realloc function, which is now deprecated, should upgrade in order to avoid the read-before-write access to uninitialized memory.
Action may be requiredUsers & stakers Impact unknown
No proposal-specific evidence was found for this group.
Action requirement unknownGovernance & ecosystem Impact unknown
No proposal-specific evidence was found for this group.
Action requirement unknownExact source revision
Full proposal document
f1f6c8b05dc2Summary
Removing pitfalls and foot-guns from the ABI (including syscalls) and runtime.
Motivation
There are a couple of interactions between dApps and the virtual machine which are currently allowed but make no sense and are even dangerous for dApps:
- CPI verification
- Allows accidentally using
AccountInfostructures which the program runtime never serialized AccountInfostructures can be overwritten by CPI during CPI, causing complex side effects
- Allows accidentally using
- Syscall alignment requirements
- In ABI v0 the account input region has no alignment guarantees (it is 1 byte aligned) and ABI v1 has 8 byte alignment. However, there are some syscalls such as the reading of sysvars which require 16 byte alignment.
- VM memory access
- Bad read accesses to account payload go unnoticed as long as they stay within the reserved address space, even if they leave the actual account payload
- Bad write accesses to account payload go unnoticed as long as the original value is restored
- Syscall slice parameters
- Bad read and write accesses which span nonsensical ranges go unnoticed
Furthermore, at the moment all validator implementations have to copy (and compare) data in and out of the virtual memory of the virtual machine. There are four possible account data copy paths:
- Serialization: Copy from program runtime (host) to virtual machine (guest)
- CPI call edge: Copy from virtual machine (guest) to program runtime (host)
- CPI return edge: Copy from program runtime (host) to virtual machine (guest)
- Deserialization: Copy from virtual machine (guest) to program runtime (host)
By restricting the allowed behavior of dApps we enable the validator to map account payload data directly, avoiding copies and compares.
Alternatives Considered
None.
New Terminology
VM memory regions
The memory regions are (in ABI v0 and v1):
- Readonly data (
0x100000000..0x200000000) - Stack (
0x200000000..0x300000000) - Heap (
0x300000000..0x400000000) - Instruction meta data
- Account meta data
- Account payload address space
- Instruction payload and program key
The payload address space of an account is the range in the serialized input
region (0x400000000..0x500000000) which covers the payload and optionally the
10 KiB resize padding (if not a loader-v1 program), but not the accounts
metadata.
Detailed Design
Syscall parameters
- The following pointers must be on the stack or heap,
meaning their virtual address is inside
0x200000000..0x400000000, otherwiseSyscallError::InvalidPointermust be thrown:- The destination address of all sysvar related syscalls
- The pointer in the array of
&[AccountInfo]/SolAccountInfo* - The
AccountInfo::datafield, which is aRefCell<&[u8]>insol_invoke_signed_rust - The
AccountInfo::lamportsfield, which is aRefCell<&u64>insol_invoke_signed_rust
- The following pointers must point to what was originally serialized in the
input regions by the program runtime,
otherwise
SyscallError::InvalidPointermust be thrown:AccountInfo::key/SolAccountInfo::keyAccountInfo::owner/SolAccountInfo::ownerAccountInfo::lamports/SolAccountInfo::lamportsAccountInfo::data::ptr/SolAccountInfo::data
VM memory access
Memory accesses (both by the program and by syscalls) which span across memory mapping regions are considered access violations. Accesses to multiple regions (e.g. by memcpy syscalls) have to be split into multiple separate accesses, one for each region.
For all memory accesses to the payload address space of an account which is flagged as writable and owned by the currently executed program, check that:
- The access is completely within the maximum account length,
otherwise
InstructionError::InvalidReallocmust be thrown. - The access is completely within the rest of the account growth budget of the
transaction, otherwise
InstructionError::InvalidReallocmust be thrown. - The access is completely within the current length of the account, otherwise extend the account with zeros to the maximum allowed by the previous two checks.
For loads / read accesses to the payload address space of an account check that:
- The access is completely within the current length of the account,
otherwise
InstructionError::AccountDataTooSmallmust be thrown.
For stores / write accesses to the payload address space of an account check that:
- The account is flagged as writable,
otherwise
InstructionError::ReadonlyDataModifiedmust be thrown - The account is owned by the currently executed program,
otherwise
InstructionError::ExternalAccountDataModifiedmust be thrown.
Impact
These restrictions have been extensively tested by replay against MNB. Most of the dApps devs whose dApps would fail have been contacted and had their dApps fixed already.
Programs which used the SDKs account realloc function, which is now deprecated, should upgrade in order to avoid the read-before-write access to uninitialized memory.
Security Considerations
None.
Evidence graph
Related proposals and rollout
One or more sources are unavailable.
Upstream review record
Upstream discussion & review
GitHub review is editorial context, not evidence of on-chain support, voting, or outcome.
PR #219 · merged SIMD-0219: Stricter ABI and Runtime Constraints 25 comments and reviews · Jan 12, 2026It is describing the current state: You can write to readonly accounts, as long as you write the existing value before the instruction ends. But, I can make it more clear that this only applies to account payload data.
GitHub ↗Likely yes, though it is kind of an implementation detail, as in we can't make a SIMD for it as that would be empty.
GitHub ↗- The access is completely within the current length of the account, otherwise InstructionError::AccountDataTooSmall must be thrown. shouldn't this also apply here?
GitHub ↗No, because the way reallocations / growing of accounts currently works in ABIv1 is that a program first writes beyond the end of the account, and then at the next CPI or the end of the instruction communicates the change of the account length to the program runtime.
GitHub ↗The access is completely within the current length of the account, otherwise extend the account with zeros to the maximum allowed by the previous two checks. Just to clarify, the way things are gonna be after this SIMD, assuming 10KB of realloc growth is allowed under the budget: - Loads into the realloc growth region without a preceding Store into said region is disallowed, and will result in an AccountDataTooSmall. - A Store into anywhere in the realloc growth region will result in logical zero-filling of the entire 10KB of realloc growth region, and a subsequent Load into anywhere in the entire 10KB of realloc growth region, whether lower or higher than the preceding Store in VM address s
GitHub ↗Yes that is correct. It essentially switches from eager to lazy initialization of the realloc padding. Also, the realloc padding will not have its own region but be part of the account payload region.
GitHub ↗It looks like there's wide approval for this. I will merge the SIMD next Friday to give time for any final objections.
GitHub ↗Hello all and thank you for the approvals
GitHub ↗Provenance
Evidence & technical details
Rollout or chain data, source revisions, freshness and integrity. 2
Provenance
Evidence & technical details
Rollout or chain data, source revisions, freshness and integrity.SIMD
Deployment Status
C37iaPi6VE4CZDueU1vL8y6pGp5i8amAbEsF31xzz723Exact source revision
Sources & integrity
- Proposal document pinned_commit_blob
f1f6c8b05dc205552d3c290a854a438392701107 - simd-document document · stale · Oct 16, 2026
f1f6c8b05dc205552d3c290a854a438392701107
One or more sources are unavailable.
simd.watch community discussion · SIMD-0219
Powered by Giscus · Sign in with GitHub to comment
Community comments load when this section approaches the viewport.