-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: reintroduce upgradable contract examples (#41)
Description =========== This PR serves two purposes: - Adjusts ink-examples to align with integration test repositories. - Fixes the previous URL check failure from Ink-docs. For more context, please refer to Ink-docs PR 273. Impact ====== This PR addresses markdown-link-check issue in Ink-docs: use-ink/ink-docs#273 * fix: update set-code-hash path in ci * fix: adjust ci for upgradable-contracts directory Description =========== - Added environment variable UPGRADEABLE_CONTRACTS. - Adjusted ci to process contracts under the upgradeable-contracts directory. - Removed unnecessary foo, bar feature flags from the CI steps as they were not present in Cargo.toml files
- Loading branch information
Showing
12 changed files
with
394 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Upgradeable Contracts | ||
|
||
There are different ways a contract can be upgraded in ink! | ||
|
||
This folder illustrates some of the common and best practices to achieve upgradeability in your contracts. | ||
|
||
## [`set-code-hash`](set-code-hash/) | ||
|
||
ink! provides an ability to replace the code under the given contract's address. | ||
This is exactly what `set_code_hash()` function does. | ||
|
||
However, developers needs to be mindful of storage compatibility. | ||
You can read more about storage compatibility on [use.ink](https://use.ink/basics/upgradeable-contracts#replacing-contract-code-with-set_code_hash) | ||
|
||
## [Delegator](delegator/) | ||
|
||
Delegator patter is based around a low level cross contract call function `delegate_call`. | ||
It allows a contract to delegate its execution to some on-chain uploaded code. | ||
|
||
It is different from a traditional cross-contract call | ||
because the call is delegate to the **code**, not the contract. | ||
|
||
Similarly, the storage compatibility issue is also applicable here. | ||
However, there are certain nuances associated with using `delegate_call`. | ||
|
||
First of all, as demonstrated in the example, if the delegated code intends to mutate the caller's storage, | ||
a developer needs to be mindful. If the delegated code modifies layout-full storage | ||
(i.e. it contains at least non-`Lazy`, non-`Mapping` field), the `.set_tail_call(true)` flag of `CallFlags` needs to be specified and the storage layouts must match. | ||
This is due to the way ink! execution call stack is operated | ||
(see [Stack Exchange Answer](https://substrate.stackexchange.com/a/3352/3098) for more explanation). | ||
|
||
If the delegated code only modifies `Lazy` or `Mapping` field, the keys must be identical and `.set_tail_call(true)` is optional. | ||
This is because `Lazy` and `Mapping` interact with the storage directly instead of loading and flushing storage states. | ||
|
||
If your storage is completely layoutless (it only contains `Lazy` and `Mapping` fields), the order of fields and layout do not need to match for the same reason as mentioned above. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Ignore build artifacts from the local tests sub-crate. | ||
/target/ | ||
|
||
# Ignore backup files creates by cargo fmt. | ||
**/*.rs.bk | ||
|
||
# Remove Cargo.lock when creating an executable, leave it for libraries | ||
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
[package] | ||
name = "delegator" | ||
version = "4.3.0" | ||
authors = ["Parity Technologies <[email protected]>"] | ||
edition = "2021" | ||
publish = false | ||
|
||
[dependencies] | ||
ink = { version = "4.3", default-features = false } | ||
delegatee = { path = "delegatee", default-features = false, features = ["ink-as-dependency"] } | ||
|
||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } | ||
scale-info = { version = "2.9", default-features = false, features = ["derive"], optional = true } | ||
|
||
[dev-dependencies] | ||
ink_e2e = { version = "4.3" } | ||
|
||
[lib] | ||
path = "lib.rs" | ||
|
||
[features] | ||
default = ["std"] | ||
std = [ | ||
"ink/std", | ||
"scale/std", | ||
"scale-info/std", | ||
] | ||
ink-as-dependency = [] | ||
e2e-tests = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Ignore build artifacts from the local tests sub-crate. | ||
/target/ | ||
|
||
# Ignore backup files creates by cargo fmt. | ||
**/*.rs.bk | ||
|
||
# Remove Cargo.lock when creating an executable, leave it for libraries | ||
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
[package] | ||
name = "updated_incrementer" | ||
name = "delegatee" | ||
version = "4.3.0" | ||
authors = ["Parity Technologies <[email protected]>"] | ||
edition = "2021" | ||
|
@@ -9,7 +9,7 @@ publish = false | |
ink = { version = "4.3", default-features = false } | ||
|
||
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } | ||
scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true } | ||
scale-info = { version = "2.9", default-features = false, features = ["derive"], optional = true } | ||
|
||
[lib] | ||
path = "lib.rs" | ||
|
@@ -22,3 +22,6 @@ std = [ | |
"scale-info/std", | ||
] | ||
ink-as-dependency = [] | ||
e2e-tests = [] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#![cfg_attr(not(feature = "std"), no_std, no_main)] | ||
|
||
#[ink::contract] | ||
pub mod delegatee { | ||
use ink::storage::{ | ||
traits::ManualKey, | ||
Mapping, | ||
}; | ||
#[ink(storage)] | ||
pub struct Delegatee { | ||
addresses: Mapping<AccountId, i32, ManualKey<0x23>>, | ||
counter: i32, | ||
// Uncommenting below line will break storage compatibility. | ||
// flag: bool, | ||
} | ||
|
||
impl Delegatee { | ||
/// When using the delegate call. You only upload the code of the delegatee | ||
/// contract. However, the code and storage do not get initialized. | ||
/// | ||
/// Because of this. The constructor actually never gets called. | ||
#[allow(clippy::new_without_default)] | ||
#[ink(constructor)] | ||
pub fn new() -> Self { | ||
unreachable!( | ||
"Constructors are not called when upgrading using `set_code_hash`." | ||
) | ||
} | ||
|
||
/// Increments the current value. | ||
#[ink(message)] | ||
pub fn inc(&mut self) { | ||
self.counter += 2; | ||
} | ||
|
||
/// Adds current value of counter to the `addresses` | ||
#[ink(message)] | ||
pub fn append_address_value(&mut self) { | ||
let caller = self.env().caller(); | ||
self.addresses.insert(caller, &self.counter); | ||
} | ||
} | ||
} |
Oops, something went wrong.