Remove Accounts `is_executable` Flag Checks
- Idea
- Draft
- Review
- Accept
- Implement
- Active
Decision brief
Why this proposal matters
Remove all checks of accounts is_executable flag which can throw errors in the runtime.
Proposal at a glance
What changes
- Setting of the is_executable flag during program deployment in loader-v3
- Calculation of the account hashes
- Minimization of snapshots
Stakeholder map
Who is affected
Builders & client teams Medium impact
The only consensus relevant change is that it will become possible (for everybody) to donate funds to program accounts. That however is expected not to break any existing programs.
Action requirement unknownValidators & operators Medium impact
Setting of the is_executable flag during program deployment in loader-v3
Action requirement unknownUsers & 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
0616093b2952Summary
Remove all checks of accounts is_executable flag which can throw errors in
the runtime.
Motivation
Currently, a program account which satisfies the following conditions can be invoked / executed:
- Has the
is_executableflag set - Is owned by a loader
- Contains a successfully verified ELF, contains the address of a program data account which does or is a built-in program
The second condition can be used as a performance optimization to filter out accounts which definitely do not contain programs and the third condition alone would be sufficient to guarantee correct execution. The first condition is however is not only useless, it is downright deceptive and entangled with the confusing proxy account workaround in loader-v3.
Originally, the is_executable flag meant that a program was deployed and
finalized, which effectively renders its program account read-only forever,
as the is_executable can not be cleared / reset.
With the introduction of the upgradeable loader (loader-v3), instead of
removing the first condition back then, a workaround was created: The program
account became a proxy account which has the is_executable flag set and then
points to the actual program data account which does not have the
is_executable flag set. Meaning the is_executable flag now neither does
reliably indicate that an account contains a program (as the program data
account does not have the flag set), nor does it indicate that a program is
finalized (as the program account has it set while the program remains
upgradeable).
Removing the first condition not only removes some redundant error checks from the runtime and confusion for future maintainers, but more importantly enables us to deploy loader-v4 which is upgradeable like loader-v3 but without the need for proxy accounts.
New Terminology
None.
Detailed Design
This proposal aims to unblock loader-v4 with minimal impact on the ecosystem by
only removing checks of the is_executable flag. A complete removal of the
flag can be addressed in a subsequent proposal. Thus, the following must remain
unaffected for now:
- Setting of the
is_executableflag during program deployment in loader-v3 - Calculation of the account hashes
- Minimization of snapshots
- Serialization of instruction accounts
is_executableflag for dapps - CPI ignores changes made by the caller to instruction accounts which have
the
is_executableflag set
These checks of the is_executable flag must be removed:
ExecutableLamportChangeduring execution (transaction succeeds instead)
These checks of the is_executable flag do not influence whether transactions
fail or succeed because they are all covered by other checks. Thus, only the
thrown error codes will change, which does not affect consensus. Nevertheless,
they should still be removed because all implementations should aim to produce
the same error codes:
during transaction loading:
InvalidProgramForExecution(fallthrough toUnsupportedProgramIdduring execution)AccountNotExecutable(fallthrough toUnsupportedProgramIdduring execution)- Meaning the transaction loading checks are effectively deferred until execution, which gives users more complete transaction logs.
in the
Upgradeinstruction of loader-v3:AccountNotExecutable(fallthrough toIncorrectProgramIdorInvalidAccountData, depending on the owner)
during execution:
AccountNotExecutable(fallthrough toUnsupportedProgramIdduring execution)IncorrectProgramId(fallthrough toUnsupportedProgramIdduring execution)ExecutableDataModified(fallthrough toExternalAccountDataModifiedduring execution)ExecutableModified(is unreachable, as it is overshadowed by owner and writability checks)ModifiedProgramId(is unreachable, as it is overshadowed by owner and writability checks)
Similarly the following checks during execution, unrelated to the
is_executable flag, but related to whether an account contains a program or
not, should be changed to throw UnsupportedProgramId instead:
InvalidAccountDatafor programs which are closed, in visibility delay, failed verification or not owned by a loaderIncorrectProgramIdfor unrecognized built-in programs
All in all, the following error messages related to invocation of program
accounts will be coalesced into UnsupportedProgramId, but some of them will
remain in use in other circumstances unrelated to program execution:
InvalidProgramForExecutionAccountNotExecutableInvalidAccountDataIncorrectProgramIdUnsupportedProgramId
Alternatives Considered
None.
Impact
Error codes of these conditions, which are rarely triggered, will change.
The only consensus relevant change is that it will become possible (for everybody) to donate funds to program accounts. That however is expected not to break any existing programs.
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 #162 · merged SIMD-0162: Remove Accounts isexecutable Flag Checks 15 comments and reviews · Jan 19, 2026Some of them (such as InvalidAccountData) can still be produced by other built-in / core programs, e.g. program management instructions.
GitHub ↗Okay sounds good. No change needed here imo, then.
GitHub ↗Loader-v4 will get its own SIMD explaining it in full detail.
GitHub ↗It looks like there's consensus here. If no one objects within the next week, I'll merge this on 25 November.
GitHub ↗I'm confused why this was left in because by allowing executable accounts to be written, it becomes important that any changes to executable accounts are handled properly. Without this change, not only does CPI ignore changes made my the caller, it also ignores changes made by the callee. In the latter case, when the caller returns, the runtime will fail the transaction because it will think that the caller tried to revert the callee changes. Also imagine if during a CPI, both the caller and callee program sent a lamport to an executable account from a non executable writable account. The caller sends the lamport first, then when the callee is cpi'd it hasn't seen the lamport change so when
GitHub ↗Sorry for the ambiguous formulation. What is meant is not that isexecutable flag can be set (you can not change the isexecutable flag inside the VM anyway), instead it means that CPI behavior was dependent on the state of the isexecutable for instruction accounts, and we do not change any of that in this SIMD ("the following must remain unaffected for now").
GitHub ↗We had to leave it in because direct mapping would break otherwise. We can only remove it after activating and cleaning up the feature gate of direct mapping.
GitHub ↗Sorry for the ambiguous formulation. What is meant is not that isexecutable flag can be set (you can not change the isexecutable flag inside the VM anyway) I think the SIMD was clear. I wasn't thinking you meant that the isexecutable flag can be set. I meant that other fields in executable accounts can be modified now but this CPI behavior would cause surprising errors when executable accounts are modified in otherwise valid ways (e.g. adding lamports as you noted in the impact section) We had to leave it in because direct mapping would break otherwise. We can only remove it after activating and cleaning up the feature gate of direct mapping. Surely there was some way to make it work before
GitHub ↗Provenance
Evidence & technical details
Rollout or chain data, source revisions, freshness and integrity. 1
Provenance
Evidence & technical details
Rollout or chain data, source revisions, freshness and integrity.SIMD
Deployment Status
FXs1zh47QbNnhXcnB6YiAQoJ4sGB91tKF3UFHLcKT7PMExact source revision
Sources & integrity
- Proposal document pinned_commit_blob
0616093b2952ed6de52c4a27d66aadd11d48d4f9 - simd-document document · current · Sep 11, 2026
0616093b2952ed6de52c4a27d66aadd11d48d4f9
One or more sources are unavailable.
simd.watch community discussion · SIMD-0162
Powered by Giscus · Sign in with GitHub to comment
Community comments load when this section approaches the viewport.