OpenZeppelin / OpenZeppelin/stellar-contracts
Protocol 28: get_validated_context_by_id won't compile once soroban-sdk moves to 28.x (missing ContractExecutable::ExternalRef arm)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 95
- Forks
- 68
- Avg merge
- 4d 42m
- Merged PRs (30d)
- 20
Description
get_validated_context_by_id in packages/accounts/src/smart_account/storage.rs (lines ~288-301) matches Context exhaustively over its 3 top-level variants, but the two CreateContract* arms only destructure executable: ContractExecutable::Wasm(wasm), with no arm and no wildcard for the other ContractExecutable variants:
let required_type = match context.clone() {
Context::Contract(ContractContext { contract, .. }) => {
ContextRuleType::CallContract(contract)
}
Context::CreateContractHostFn(CreateContractHostFnContext {
executable: ContractExecutable::Wasm(wasm),
..
}) => ContextRuleType::CreateContract(wasm),
Context::CreateContractWithCtorHostFn(CreateContractWithConstructorHostFnContext {
executable: ContractExecutable::Wasm(wasm),
..
}) => ContextRuleType::CreateContract(wasm),
};
This compiles today because the crate pins soroban-sdk = "27.0.2" (pre-Protocol 28), where ContractExecutable doesn't yet have the ExternalRef variant reachable here. Protocol 28 (CAP-85) adds CONTRACT_EXECUTABLE_EXTERNAL_REF / ContractExecutable::ExternalRef — see the official upgrade guide, which calls out this exact function shape under "Breaking changes":
custom account contracts that parse the authorization context and are not updated for the new executable type will be unable to authorize contract creation that uses an external executable reference
For this specific match, the effect is sharper than "unable to authorize at runtime" — it's a compile error, the day this crate's own soroban-sdk pin moves to 28.x.
Reproduced, not just read
Copied the exact match shape into a minimal standalone crate and compiled it against both versions:
Against soroban-sdk = "27.0.2" (current pin): compiles clean.
#![no_std]
use soroban_sdk::auth::{Context, ContractContext, ContractExecutable, CreateContractHostFnContext, CreateContractWithConstructorHostFnContext};
use soroban_sdk::Env;
pub fn check(_e: &Env, context: Context) -> u32 {
match context {
Context::Contract(ContractContext { .. }) => 1,
Context::CreateContractHostFn(CreateContractHostFnContext {
executable: ContractExecutable::Wasm(_wasm),
..
}) => 2,
Context::CreateContractWithCtorHostFn(CreateContractWithConstructorHostFnContext {
executable: ContractExecutable::Wasm(_wasm),
..
}) => 3,
}
}
Against soroban-sdk = "28.0.0-rc.1" (Protocol 28, currently the published pre-release): fails with E0004:
error[E0004]: non-exhaustive patterns: `soroban_sdk::auth::Context::CreateContractHostFn(CreateContractHostFnContext { executable: soroban_sdk::ContractExecutable::ExternalRef(_), .. })` and `soroban_sdk::auth::Context::CreateContractWithCtorHostFn(CreateContractWithConstructorHostFnContext { executable: soroban_sdk::ContractExecutable::ExternalRef(_), .. })` not covered
--> src/lib.rs:6:11
|
6 | match context {
| ^^^^^^^ patterns ... not covered
Only the Cargo.toml dependency line differs between the two runs ("27.0.2" vs "28.0.0-rc.1"); everything else — including the match shape — is identical to what's in storage.rs today. Happy to open a PR with a soroban-sdk = "28.0.0-rc.1" line in a branch if that's the easiest way to confirm on your end.
Severity, stated plainly
Not exploitable today — soroban-sdk is pinned at 27.0.2, and ExternalRef doesn't exist at that pin. This is a heads-up for whenever the crate's soroban-sdk dependency moves to 28.x for Protocol 28 support (mainnet vote September 16, 2026): the bump itself won't compile until this match gets a third arm (or a wildcard) for ContractExecutable::ExternalRef.
Duplicate check
Searched ContractExecutable ExternalRef non-exhaustive, CreateContractHostFn Protocol 28, and get_validated_context_by_id across this repo's issues (open + closed) — nothing existing.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/accounts/src/smart_account/storage.rs around get_validated_context_by_id and inspect the ContractExecutable match arms. Compare the current soroban-sdk dependency in Cargo.toml with the Protocol 28 behavior, then run the relevant Rust checks against the updated SDK. Done means the crate compiles with the new executable variant handled appropriately without breaking existing authorization context handling.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- blockchain
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100