From b3578fc212250a2bab86b5f65b9af48afaf852a6 Mon Sep 17 00:00:00 2001 From: Joseph Caulfield Date: Mon, 15 Dec 2025 07:53:04 +0000 Subject: [PATCH 1/5] SIMD-0433: Loader V3: Set Program Data to ELF Length --- ...oader-v3-set-program-data-to-elf-length.md | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 proposals/0433-loader-v3-set-program-data-to-elf-length.md diff --git a/proposals/0433-loader-v3-set-program-data-to-elf-length.md b/proposals/0433-loader-v3-set-program-data-to-elf-length.md new file mode 100644 index 000000000..f0e54cc57 --- /dev/null +++ b/proposals/0433-loader-v3-set-program-data-to-elf-length.md @@ -0,0 +1,69 @@ +--- +simd: '0433' +title: 'Loader V3: Set Program Data to ELF Length' +authors: + - Joe Caulfield (Anza) + - Dean Little (Blueshift) +category: Standard +type: Core +status: Review +created: 2025-12-14 +feature: (fill in with feature key and github tracking issues once accepted) +--- + +## Summary + +This SIMD proposes changing the default behavior of program upgrades to resize +the program data account to the length of the ELF being deployed, refunding any +surplus lamports to a spill account. + +## Motivation + +Currently, Loader v3 program data accounts may be extended 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. + +## New Terminology + +No new terminology is introduced by this proposal. + +## Detailed Design + +The `Upgrade` instruction will be updated to automatically resize the program +data account to match the length of the ELF in the buffer being deployed. + +If the new ELF is larger than the current program data account, the upgrade will +fail. The account must first be extended to the required size via the +`ExtendProgram` instruction. + +If the new ELF is smaller than the current program data account, the account +will be retracted and surplus lamports will be refunded to the spill account. + +This change will be a feature-gated behavioral change to the existing `Upgrade` +instruction. + +## Alternatives Considered + +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`. + +## Impact + +This proposal results in a lower program footprint in Accounts DB, 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. + +## Security Considerations + +N/A + +## 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, the +change is backwards compatible. From 327c99d34e8912beb05d3bbd80587da23e29f00a Mon Sep 17 00:00:00 2001 From: Joe C Date: Thu, 18 Dec 2025 11:06:56 -0500 Subject: [PATCH 2/5] Update proposals/0433-loader-v3-set-program-data-to-elf-length.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Dean 利迪恩 <10921578+deanmlittle@users.noreply.github.com> --- proposals/0433-loader-v3-set-program-data-to-elf-length.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0433-loader-v3-set-program-data-to-elf-length.md b/proposals/0433-loader-v3-set-program-data-to-elf-length.md index f0e54cc57..77001c896 100644 --- a/proposals/0433-loader-v3-set-program-data-to-elf-length.md +++ b/proposals/0433-loader-v3-set-program-data-to-elf-length.md @@ -35,7 +35,7 @@ The `Upgrade` instruction will be updated to automatically resize the program data account to match the length of the ELF in the buffer being deployed. If the new ELF is larger than the current program data account, the upgrade will -fail. The account must first be extended to the required size via the +fail. The account must first be extended to at least the required size via the `ExtendProgram` instruction. If the new ELF is smaller than the current program data account, the account From 1667bca5d4e55785903359c17a208daf55d255ee Mon Sep 17 00:00:00 2001 From: Joseph Caulfield Date: Wed, 14 Jan 2026 00:01:00 +0000 Subject: [PATCH 3/5] bidirectional resizing --- ...oader-v3-set-program-data-to-elf-length.md | 89 +++++++++++++++---- 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/proposals/0433-loader-v3-set-program-data-to-elf-length.md b/proposals/0433-loader-v3-set-program-data-to-elf-length.md index 77001c896..3aeabb2f4 100644 --- a/proposals/0433-loader-v3-set-program-data-to-elf-length.md +++ b/proposals/0433-loader-v3-set-program-data-to-elf-length.md @@ -13,43 +13,88 @@ feature: (fill in with feature key and github tracking issues once accepted) ## Summary -This SIMD proposes changing the default behavior of program upgrades to resize -the program data account to the length of the ELF being deployed, refunding any -surplus lamports to a spill account. +This SIMD proposes changing the default behavior of program upgrades to +automatically resize the program data account to match the length of the ELF +being deployed. If the new ELF is smaller, surplus lamports are refunded to the +spill account. If the new ELF is larger, the account is extended using lamports +from the buffer account. ## Motivation -Currently, Loader v3 program data accounts may be extended 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. +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 proposals +such as SIMD-0164 and SIMD-0431. Moreover, because `ExtendProgram` is +permissionless, reducing reliance on it - or eliminating it entirely - would be +particularly attractive from both a security and workflow perspective. ## New Terminology -No new terminology is introduced by this proposal. +[SIMD-0164: ExtendProgramChecked loader-v3 instruction](https://github.com/solana-foundation/solana-improvement-documents/pull/164) +[SIMD-0430: Loader V3: Relax Program Buffer Constraints](https://github.com/solana-foundation/solana-improvement-documents/pull/430) +[SIMD-0431: Loader V3: Permissioned Extend Program](https://github.com/solana-foundation/solana-improvement-documents/pull/431) ## Detailed Design The `Upgrade` instruction will be updated to automatically resize the program -data account to match the length of the ELF in the buffer being deployed. +data account to match the length of the ELF in the buffer being deployed. This +applies in both directions: the account may grow or shrink as needed. + +### Shrinking (New ELF is Smaller) + +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 will be refunded to the spill account. + +### Growing (New ELF is Larger) + +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. The additional rent +required must have been credited to the program data account before `Upgrade` +was invoked. If not, the upgrade will fail with `InsufficientFunds`. + +Similar to shrinking, any remaining lamports after satisfying rent will be +refunded to the spill account. + +### Buffer Account Lamports -If the new ELF is larger than the current program data account, the upgrade will -fail. The account must first be extended to at least the required size via the -`ExtendProgram` instruction. +Regardless of SIMD-0430, after the current proposal, buffer accounts will no +longer be debited or credited lamports during `Upgrade`. This is true for all +ELF sizing cases - shrinking, growing, or remaining exactly the same. -If the new ELF is smaller than the current program data account, the account -will be retracted and surplus lamports will be refunded to the spill account. +As mentioned in the previous section, any additional rent exemption required +for growing an ELF region must be credited to the program data account before +`Upgrade` is invoked. + +### 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`. +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 @@ -60,7 +105,17 @@ program data address. ## Security Considerations -N/A +### 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 From 9019defc25a7c470c463ef14ee16bba28cec2313 Mon Sep 17 00:00:00 2001 From: Joe Caulfield Date: Fri, 3 Apr 2026 06:59:05 +0000 Subject: [PATCH 4/5] revise lamport accounting and add simd-0430 dep --- ...oader-v3-set-program-data-to-elf-length.md | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/proposals/0433-loader-v3-set-program-data-to-elf-length.md b/proposals/0433-loader-v3-set-program-data-to-elf-length.md index 3aeabb2f4..66449d0d1 100644 --- a/proposals/0433-loader-v3-set-program-data-to-elf-length.md +++ b/proposals/0433-loader-v3-set-program-data-to-elf-length.md @@ -16,8 +16,7 @@ feature: (fill in with feature key and github tracking issues once accepted) This SIMD proposes changing the default behavior of program upgrades to automatically resize the program data account to match the length of the ELF being deployed. If the new ELF is smaller, surplus lamports are refunded to the -spill account. If the new ELF is larger, the account is extended using lamports -from the buffer account. +spill account. If the new ELF is larger, the account is extended accordingly. ## Motivation @@ -30,16 +29,24 @@ 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 proposals -such as SIMD-0164 and SIMD-0431. Moreover, because `ExtendProgram` is -permissionless, reducing reliance on it - or eliminating it entirely - would be -particularly attractive from both a security and workflow perspective. +operational complexity and has been a recurring point of debate in other +proposals. ## New Terminology -[SIMD-0164: ExtendProgramChecked loader-v3 instruction](https://github.com/solana-foundation/solana-improvement-documents/pull/164) -[SIMD-0430: Loader V3: Relax Program Buffer Constraints](https://github.com/solana-foundation/solana-improvement-documents/pull/430) -[SIMD-0431: Loader V3: Permissioned Extend Program](https://github.com/solana-foundation/solana-improvement-documents/pull/431) +N/A + +## Dependencies + +This proposal depends on the following previously accepted proposal: + +- **[SIMD-0430]: Loader V3: Relax Program Buffer Constraints** + + Introduces the `close_buffer` flag for `DeployWithMaxDataLen` and + `Upgrade` instructions, which determines whether the buffer account is + closed after the operation + +[SIMD-0430]: https://github.com/solana-foundation/solana-improvement-documents/pull/430 ## Detailed Design @@ -56,22 +63,19 @@ rent requirement will be refunded to the spill account. ### Growing (New ELF is Larger) 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. The additional rent -required must have been credited to the program data account before `Upgrade` -was invoked. If not, the upgrade will fail with `InsufficientFunds`. - -Similar to shrinking, any remaining lamports after satisfying rent will be -refunded to the spill account. +the account will be extended to accommodate the new ELF. -### Buffer Account Lamports +When `close_buffer` is `true`, the buffer account's lamports and the program +data account's existing lamports are combined to meet the new rent-exempt +minimum. If the combined lamports are insufficient, the upgrade will fail with +`InsufficientFunds`. -Regardless of SIMD-0430, after the current proposal, buffer accounts will no -longer be debited or credited lamports during `Upgrade`. This is true for all -ELF sizing cases - shrinking, growing, or remaining exactly the same. +When `close_buffer` is `false`, the program data account's existing lamports +must already meet the new rent-exempt minimum. If not, the upgrade will fail +with `InsufficientFunds`. -As mentioned in the previous section, any additional rent exemption required -for growing an ELF region must be credited to the program data account before -`Upgrade` is invoked. +In both cases, any lamports in excess of the rent-exempt minimum are refunded +to the spill account. ### Feature Gate From 43c07c48d9e0e2972d80f02fbcc3ffd6f1ca2e42 Mon Sep 17 00:00:00 2001 From: Joe Caulfield Date: Fri, 15 May 2026 21:08:10 +0000 Subject: [PATCH 5/5] clarify sizing specifics --- ...3-loader-v3-set-program-data-to-elf-length.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/proposals/0433-loader-v3-set-program-data-to-elf-length.md b/proposals/0433-loader-v3-set-program-data-to-elf-length.md index 66449d0d1..7c5818baa 100644 --- a/proposals/0433-loader-v3-set-program-data-to-elf-length.md +++ b/proposals/0433-loader-v3-set-program-data-to-elf-length.md @@ -14,9 +14,11 @@ feature: (fill in with feature key and github tracking issues once accepted) ## Summary This SIMD proposes changing the default behavior of program upgrades to -automatically resize the program data account to match the length of the ELF -being deployed. 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. +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 @@ -51,8 +53,12 @@ This proposal depends on the following previously accepted proposal: ## Detailed Design The `Upgrade` instruction will be updated to automatically resize the program -data account to match the length of the ELF in the buffer being deployed. This -applies in both directions: the account may grow or shrink as needed. +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 (New ELF is Smaller)