Skip to main content
Technical proposal SIMD-0433 Review

Loader V3: Set Program Data to ELF Length

  1. Idea
  2. Draft
  3. Review
  4. Accept
  5. Implement
  6. Active

Decision brief

Why this proposal matters

This SIMD proposes changing the default behavior of program upgrades to automatically resize the program data account so that its ELF region matches the length of the ELF being deployed. The total account size remains the program data metadata header plus the ELF length. If the new ELF is smaller, surplus lamports are refunded to the spill account. If the new ELF is larger, the account is extended accordingly.

Source-backed reading aid · source language: EN

Proposal at a glance

What changes

  • Deallocate the buffer account for garbage collection.
  • Apply the buffer's lamports to the program data's new rent requirement, if necessary.
  • Sweep the remaining buffer lamports to the spill account.

Stakeholder map

Who is affected

Builders & client teams Medium impact

Developers who over-provision program data accounts with additional free space will see that space reclaimed during upgrade. Anyone who intentionally over-provisions and expects that additional space to survive across upgrades will no longer be able to do so.…

Action may be required
Validators & operators Medium impact

From an API and tooling perspective, interface-wise, the change is backwards compatible. However, rent and space management behavior has changed according to the Impact section above. Developers should double-check the spill accounts they'll use on upgrade to take advantage of potential rent refunds.

Action may be required
Users & stakers Impact unknown

No proposal-specific evidence was found for this group.

Action requirement unknown
Governance & ecosystem Medium impact

Additionally, this proposal incentivizes developers to upgrade to newer, more performant libraries and SDKs, and enables the recovery of surplus lamports, including those accidentally sent to the program data address.

Action may be required

Exact source revision

Full proposal document

Source-language document. Technical identifiers and evidence remain unchanged. eac20f2994dd

Summary

This SIMD proposes changing the default behavior of program upgrades to automatically resize the program data account so that its ELF region matches the length of the ELF being deployed. The total account size remains the program data metadata header plus the ELF length. If the new ELF is smaller, surplus lamports are refunded to the spill account. If the new ELF is larger, the account is extended accordingly.

Motivation

Currently, Loader v3 program data accounts may be extended via the ExtendProgram instruction, but cannot be retracted. As program sizes decrease due to SDK improvements such as Pinocchio, this limitation results in program data accounts remaining larger than necessary, with no mechanism to reclaim the rent paid for unused bytes. This unnecessarily increases rent costs and program loading overhead.

Additionally, upgrading a program to a larger ELF requires issuing a separate ExtendProgram instruction prior to Upgrade. This additional step increases operational complexity and has been a recurring point of debate in other proposals.

New Terminology

N/A

Detailed Design

The Upgrade instruction will be updated to automatically resize the program data account so that its ELF region matches the length of the ELF in the buffer being deployed. The program data account retains its existing metadata header (UpgradeableLoaderState::ProgramData, containing the slot and upgrade authority), so the resulting account size is PROGRAMDATA_METADATA_SIZE + elf_length. This applies in both directions: the account may grow or shrink as needed.

Shrinking: If the new ELF is smaller than the current program data account's ELF region, the account will be retracted to the new size. Surplus lamports from the reduced rent requirement for the program data account will be refunded to the spill account.

Growing: If the new ELF is larger than the current program data account's ELF region, the account will be extended to accommodate the new ELF. New lamports for the increased rent requirement are expected to be either credited to the program data account or available in the buffer account prior to the execution of the Upgrade instruction. If the available lamports are insufficient to satisfy the new rent requirement, the upgrade will fail with InsufficientFunds.

Buffer Accounts

Currently, the Upgrade instruction will:

  • Deallocate the buffer account for garbage collection.
  • Apply the buffer's lamports to the program data's new rent requirement, if necessary.
  • Sweep the remaining buffer lamports to the spill account.

This behavior is unchanged by this proposal. For any proposals that may modify the behavior of buffer account closure, the same lamport requirements detailed in the Growing paragraph apply.

Feature Gate

This change will be a feature-gated behavioral change to the existing Upgrade instruction.

Alternatives Considered

Shrinking Only

An earlier version of this proposal only supported shrinking, requiring the ExtendProgram instruction to be called before upgrading to a larger ELF. This approach was rejected in favor of bidirectional resizing to simplify upgrade workflows and reduce the number of instructions required.

Separate Lamport Withdrawal

An alternative approach would be to add a new WithdrawExcessLamports instruction, similar to the instruction of the same name in the Token-2022 program. This would allow the program's upgrade authority to claim excess lamports after the auto-resizing from Upgrade. This was rejected in favor of automatically refunding surplus lamports to the spill account during the upgrade itself.

Impact

Developers who over-provision program data accounts with additional free space will see that space reclaimed during upgrade. Anyone who intentionally over-provisions and expects that additional space to survive across upgrades will no longer be able to do so. However, those who accidentally over-provision, or those who are forced to do so - via minimum extension requirements, for example - will be able to reclaim part of their rent deposit.

Additionally, this proposal incentivizes developers to upgrade to newer, more performant libraries and SDKs, and enables the recovery of surplus lamports, including those accidentally sent to the program data address.

For validators/contributors: this proposal should result in a lower program footprint in Accounts DB.

Security Considerations

CPI Account Growth Limit

When invoking the Upgrade instruction via CPI, the 10 KiB per-instruction account growth limit still applies. If the new ELF requires the program data account to grow by more than 10 KiB, the upgrade will fail when called via CPI.

Programs requiring larger growth must either:

  • Perform the upgrade at the top level of the transaction, or
  • Split the growth across multiple instructions using ExtendProgram before upgrading

Backwards Compatibility

This change modifies an existing Loader v3 instruction and therefore requires a feature gate for consensus safety.

From an API and tooling perspective, interface-wise, the change is backwards compatible. However, rent and space management behavior has changed according to the Impact section above. Developers should double-check the spill accounts they'll use on upgrade to take advantage of potential rent refunds.

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 #433 · merged SIMD-0433: Loader V3: Set Program Data to ELF Length 35 comments and reviews · Jul 31, 2026
@Lichtso

I know you want to decouple from SIMD-0430, but we still need to define what to do if the buffer is passed as read-only.

GitHub ↗
@buffalojoec

I think it's tricky to add such a comment, since the program current requires the buffer to be writable. We aren't changing that requirement here, and I believe any SIMDs that do should specify what the implications are for a read-only buffer. In other words, I'd rather amend SIMD-0430. What do you think?

GitHub ↗
@buffalojoec

I took it out on purpose, but I'm fine with including it, since we've done this for other program-related SIMDs like SIMD-0123.

GitHub ↗
@buffalojoec

@Lichtso as briefly mentioned in https://github.com/solana-foundation/solana-improvement-documents/discussions/588, the Upgrade instruction is allowed via CPI, unlike other programdata-modifying instructions like ExtendProgram and Write. Could you elaborate why we felt Upgrade was safe to whitelist for CPI, and does that logic still hold after this SIMD is implemented? The key aspect is that currently, Upgrade does not resize the programdata at all. It asserts the account is large enough and then simply copies from the buffer account directly. After this change, it will also resize the programdata. I'd like to know if there is some reason why this would be dangerous in CPI.

GitHub ↗
@Lichtso

if there is some reason why this would be dangerous in CPI. That upgrade now also resizes is benign IMO, even in the CPI case. Could you elaborate why we felt Upgrade was safe to whitelist for CPI https://github.com/solana-labs/solana/pull/14449 and does that logic still hold after this SIMD is implemented? Think so. This SIMD would not change anything about that.

GitHub ↗
@buffalojoec

Think so. This SIMD would not change anything about that. Considering the logic in that PR was "we need Upgrade for something", I would agree with you.

GitHub ↗
@simd-botbot

✅ Merge successful! buffalojoec(https://github.com/buffalojoec)'s PR has been merged.

GitHub ↗

simd.watch community discussion · SIMD-0433

Powered by Giscus · Sign in with GitHub to comment

Community comments load when this section approaches the viewport.

Provenance

Evidence & technical details

Rollout or chain data, source revisions, freshness and integrity.
2

SIMD

Deployment Status

Document lifecycleReview
CategoryCore protocol

Feature Gate not yet created

Exact source revision

Sources & integrity

  • Proposal document pinned_commit_blob
    eac20f2994dd064482d96f178a4bbc0f4e358fd0
  • simd-document document · stale · Oct 28, 2026
    eac20f2994dd064482d96f178a4bbc0f4e358fd0

One or more sources are unavailable.