Add externally managed contract executable type #1969
Replies: 1 comment 1 reply
-
|
Thanks for posting this. I think another alternative that might be suggested is a direct ability for a contract to 'inherit' the executable of another contract directly. However, I think the proposed approach has several benefits compared to the direct inheritance approach:
Some small design notes:
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Problem
The factory pattern is commonly used in smart contract protocols to deploy many contract instances that share the same WASM (a "fleet" of contracts). When that shared WASM needs to be upgraded, the admin must submit a separate upgrade transaction for every instance. This is fine for small fleets, but for large ones it is expensive and creates a window during the rollout where some instances run the old WASM and some run the new.
Because some upgrades carry security fixes, or are not backwards-compatible with the previous version, there is incentive for the upgrade to apply atomically across the entire fleet.
Ecosystems that manage reusable code via proxies, such as Ethereum, achieve this with the beacon proxy pattern.
Stellar has no equivalent today. Each contract instance defines its own WASM hash, and we intentionally do not expose the proxy primitives (
fallback()ordelegatecall) that beacon implementations rely on. This discussion proposes fixing this by extending the contract executable definition to support references to an updatable WASM hash.Proposal
We would like to extend the contract instance executable definition to include an external reference variant:
A contract can manage WASM entries via a new ScVal ledger key type
ScVal::LedgerKeyWasmRef(Symbol)and a new host function that validateswasm_hashexists as a code entry:A contract can switch its executable to an external reference or update it's external reference via a new host function:
A factory contract can deploy contracts with an externally referenced WASM with the new host functions:
Diagrams
Legend:
Resolving an ExternalRef Contract during a contract invocation
sequenceDiagram actor U as Caller participant H as Host participant L as Ledger U->>H: invoke Follower.transfer(...) H->>L: read Follower instance L-->>H: executable = ExternalRef{ Manager, "token" } H->>L: read reserved entry (Manager, WasmRef("token")) L-->>H: wasm_hash H->>L: read ContractCode(wasm_hash) L-->>H: wasm code Note over H: instantiate VM, run transfer(...) H-->>U: result of transfer(...)Manager upgrading a WASM it controls
sequenceDiagram actor Op as Admin participant M as Manager participant H as Host participant L as Ledger Op->>M: upgrade("token", new_hash) M->>M: governance checks (require_auth(admin), timelock, ...) M->>H: set_contract_wasm_ref("token", new_hash) H->>H: assert ContractCode(new_hash) exists H->>L: write (Manager, WasmRef("token")) = new_hash H->>H: emit wasm_ref_updated(Manager, "token", old_hash, new_hash) H-->>M: ok Note over L: every Follower with ExternalRef{ Manager, "token" }<br/>resolves to new_hash on its next callFactory deploying a new follower contract
sequenceDiagram actor U as Deployer participant Fa as Factory participant H as Host participant L as Ledger U->>Fa: deploy(salt) Fa->>H: create_contract_with_external_ref(deployer, Manager, "token", salt) H->>H: derive Follower address from (deployer, salt) H->>L: read (Manager, WasmRef("token")) L-->>H: wasm_hash H->>H: assert ContractCode(wasm_hash) exists H->>L: write Follower instance, executable = ExternalRef{ Manager, "token" } H-->>Fa: Follower address Fa-->>U: Follower address Note over H,L: the _and_constructor variant also loads the code<br/>and runs the Follower's constructor against itAlternatives
ExternalRef { contract: Address, key: Val }. This is the simplest protocol change, but potentially the easiest to go wrong as no additional host functions are added that can validate things like "this entry holds a deployed WASM hash".Questions
extend_current_contract_instance_and_code_ttl, what gets extended?Beta Was this translation helpful? Give feedback.
All reactions