diff --git a/static/img/contract-storage.png b/static/img/contract-storage.png new file mode 100644 index 0000000000..c9c7e8ae0d Binary files /dev/null and b/static/img/contract-storage.png differ diff --git a/versioned_docs/version-5.x/faq/migrating-from-ink-4-to-5.md b/versioned_docs/version-5.x/faq/migrating-from-ink-4-to-5.md new file mode 100644 index 0000000000..bbfb9e3cbd --- /dev/null +++ b/versioned_docs/version-5.x/faq/migrating-from-ink-4-to-5.md @@ -0,0 +1,521 @@ +--- +title: Migrating from ink! 4.x to 5.0 +slug: /faq/migrating-from-ink-4-to-5 +--- + + + +We've made a couple of breaking changes from ink! 4.x to ink! 5.0. +On this page we outline how you can migrate existing clients and +contracts from 4.x to 5.0. + +This release addresses the majority of issues raised in [the OpenZeppelin +security review](https://blog.openzeppelin.com/security-review-ink-cargo-contract). +In particular, we addressed the proxy selector clashing attack. + +You can find the full changelog of the 5.0 release [here](https://github.com/paritytech/ink/blob/master/CHANGELOG.md). + +:::caution +This migration guide only considers your code base! Not your storage data! + +If you have an existing contract on-chain you might not be able to just +upgrade the code on-chain, you possibly also have to migrate your storage data. + +The relevant change that you have to take into consideration is +[#1897](https://github.com/paritytech/ink/pull/1897). +A data migration may be required when your contract reads data from storage and truncates +the data when decoding it. +We've described this in more detail below, in the section +["Fail when decoding from storage and not all bytes consumed"](#fail-when-decoding-from-storage-and-not-all-bytes-consumed). +::: + +## How to upgrade + +* Change the dependency versions of `ink` and `ink_e2e` in your contracts `Cargo.toml` to `5`. +* Update your local `cargo-contract` installation to 4.0. +* Read through this page. + +## Compatibility + +The following chains are in production and support ink! 5.0: + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+
+ + + +
+
+ +### `cargo-contract` 4.0 + +Together with ink! 5.0 we've released `cargo-contract` 4.0. + +:::info +You have to use `cargo-contract` >= 4.0 for ink! 5.0 contracts! + +You can upgrade via: + +```rust +cargo install cargo-contract --version ^4 +``` +::: + +Make sure that e.g. your CI also uses at least `cargo-contract` 4.0 with ink! v5.0. +If you have wrapper scripts around `cargo-contract`, you should +ensure that this version is enforced, otherwise users will get an error. + +### Substrate + +The same requirements as for ink! 4.0 hold. + +* `pallet-contracts` >= `polkadot-v0.9.37`. +* `substrate-contracts-node` >= `v0.24.0` + +#### How do I find out which Polkadot version a chain is running on? + +You can query the `contracts::palletVersion()` via the chain state RPCs. It has to +be `>= 9` for ink! 5.0 to be compatible. + +You can use e.g. the [polakdot.js app](https://polkadot.js.org/apps/) to do this: +Developer » Chain State » `contracts` » `palletVersion()` » Click on the `+` on the right. + +
+ +
+ +### Tooling + +* `cargo-contract` >= v4.0 +* Stable Rust >= 1.75 + +### Dependencies + +Same as for ink! 4.0. + +* `scale` >= 3 +* `scale-info` >= 2.6 + +### Frontend Libraries + +Same as for ink! 4.0: `polkadot-js/api` and `polkadot-js/api-contract` >= 9.10.2. + +## Important Changes + +### `scale` dependencies were moved to `ink` entrance crate + +This change was done to ensure that you always use the correct scale dependency versions +with an ink! version. The relevant PR is [#1890](https://github.com/paritytech/ink/pull/1890). + +We removed the requirement for contracts to have direct dependencies on `parity-scale-codec` +and `scale-info` in their `Cargo.toml`. +You can now remove those dependencies from your contracts `Cargo.toml`: + +```diff +ink = { version = "4.3", default-features = false } +-scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +-scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } +``` + +Both crates have been re-exported from the `ink` umbrella crate: `ink::scale_info` and `ink::scale`. + +We created a convenience macro to derive the re-exported traits `ink::scale::Encode`, +`ink::scale::Decode` and `ink::scale_info::TypeInfo`. + +```rust +// Previously +#[scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(::scale_info::TypeInfo))] +pub enum Error {} + + +// Now +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum Error {} +``` + +The documentation of the macro can be found [here](https://docs.rs/ink/5.0.0-rc/ink/attr.scale_derive.html). + +### Wildcard selectors: only one other message is allowed in the contract besides the wildcard selector + +Following [our security review by OpenZeppelin](https://blog.openzeppelin.com/security-review-ink-cargo-contract), +we've tightened the usage of wildcard selectors. +With ink! 5.0 we allow only exactly one other contract message with a well-known reserved +selector to be defined. In ink! 4.x, more than one other message was allowed. + +Read more in [the PR](https://github.com/paritytech/ink/pull/1708) and [IIP-2: Limit contracts with a wildcard selector to one other message](https://github.com/paritytech/ink/issues/1676). + +The proposal is to restrict contracts with a wildcard selector to only have one other message +with a reserved/well-known selector. This guarantees that there are no selector clashes, +either by chance or malicious intent, and that the Proxy will only handle messages intended for it. + +If a contract uses a wildcard selector `#[ink(message, payable, selector = _)]` it _MAY_ define one +other message. This message _MUST_ use the reserved selector `@`. +This selector _MUST_ only be used in conjunction with a wildcard selector. + +```rust +/// Handles any message with no matching selector in this proxy contract +#[ink(message, selector = _)] +pub fn fallback(&self) { + // forward call to the "logic" contract which actually executes the call +} + +#[ink::scale_derive(Decode)] +pub enum ProxyMessage { + UpgradeContract(Hash), +} + +/// One other message allowed to handle messages. +/// Fails to compile unless `@` is used as the selector. +#[ink(message, selector = @)] +pub fn handler(&self, msg: ProxyMessage) { + match msg { + ProxyMessage(hash) => { } + } +} + +/// An additional message. Fails to compile when uncommented. +// #[ink(message)] +// pub fn additional_message(&self, msg: ProxyMessage) { +// match msg { +// ProxyMessage(hash) => ... +// } +// } +``` + +### Events 2.0 + +In prior ink! versions, events were defined inside the `#[ink::contract]` macro. +With ink! 5.0 we decouple events from the `#[ink::contract]` macro, +allowing events to be shared between contracts. +We've updated [the Events documentation page](/5.x/basics/events) accordingly. + +The syntax of defining events within the main `#[ink::contract]` macro will continue to work, +no code changes in existing contracts are required to update to the new syntax. + +:::caution +The topic calculation changed in general, so also for events that are declared inside the +`#[ink::contract]` macro! + +This is a breaking change for any client code which uses topics to filter events. + +Please see [#1827](https://github.com/paritytech/ink/pull/1827) for details. +::: + +#### Custom signature topics + +In [#2031](https://github.com/paritytech/ink/pull/2031) we introduced an +optional attribute `signature_topic` to the `#[ink::event]` and `#[ink(event)]` macros. +It can be used to specify the signature topic for a specific event manually, instead of the +automatic topic calculation. + +### No more unchecked arithmetic + +Unchecked arithmetic operations in a contract are no longer supported for arithmetic +safety reasons. Compiling a contract that contains those will fail gracefully. + +If you haven't already done, you now need to handle overflows that could occur. +Rust supports different possibilities of doing so (saturating, "wrap around", +and unchecked arithmetic operations) . +See [this](https://doc.rust-lang.org/book/ch03-02-data-types.html#scalar-types) section +of the Rust Programming Language for a thorough explanation on how to do safe arithmetic +operations in Rust. + +This change was introduced in [#1831](https://github.com/paritytech/ink/pull/1831). + +### Fail when decoding from storage and not all bytes consumed + +If a contract previously relied on successful decoding which does not consume all bytes, +then recompiling with a version of ink! which includes this change will cause that contract +to trap at runtime when attempting to decode. + +A simple example would be if a storage cell contains some bytes which were in the first place +an encoded `u32`. If the contract attempts to decode those into a `u8` +this would previously have succeeded, now the contract would trap. + +Here's a code example of behavior that previously worked for ink! 4.x, but +would error now: + +```rust +let key = 0u32; +let value = [0x42; 32]; +ink::env::set_contract_storage(&key, &value); + +// Only attempt to read the first byte (the `u8`) of the storage value data +let _loaded_value: Option = ink::env::get_contract_storage(&key) + .map_err(|e| format!("get_contract_storage failed: {:?}", e))?; +``` + +We introduced this change in [#1897](https://github.com/paritytech/ink/pull/1897). + +### [ink_e2e] API Changes + +#### Builder API + +In [#1917](https://github.com/paritytech/ink/pull/1917) we reworked the E2E API with +a builder API. +`instantiate`, `call` and `upload` will now return a builder instance. You can +specify optional arguments with builder methods, and submit the call for on-chain +execution with the `.submit()` method, or dry-run it with `dry_run()`. + +```rust +let contract = client + .instantiate("flipper", &ink_e2e::alice(), &mut constructor) + .submit() + .await + .expect("instantiate failed"); +let mut call = contract.call::(); + +let get = call.get(); +let get_res = client.call(&ink_e2e::bob(), &get).dry_run().await; +assert!(matches!(get_res.return_value(), false)); +``` + +#### Extra gas margin + +As part of [#1917](https://github.com/paritytech/ink/pull/1917) we added the possibility +to specify a gas margin (in percentage) as part of the on-chain call. + +There are cases when gas estimates may not necessarily be accurate enough due to the complexity +of the smart contract logic that adds additional overhead and gas consumption. +Therefore, it is helpful to allow to specify an extra portion of the gas to be added to the +limit (i.e. 5%, 10%). + +The method `.extra_gas_portion(margin: u64)` method is part of the builder API: + +* [`ink_e2e::InstantiateBuilder::extra_gas_portion`](https://docs.rs/ink_e2e/5.0.0-rc/ink_e2e/struct.InstantiateBuilder.html#method.extra_gas_portion) +* [`ink_e2e::CallBuilder::extra_gas_portion`](https://docs.rs/ink_e2e/5.0.0-rc/ink_e2e/struct.CallBuilder.html#method.extra_gas_portion) + +#### Improved `call()` API + +We removed the `build_message()` function with its unhandy callback. + +```rust +// Previously +let first_insert = ink_e2e::build_message::(contract_id) + .call(|contract| contract.insert_balance(1_000)); + +// Now +let first_insert = ink_e2e::build_message::(contract_id) + .call().insert_balance(1_000)); +``` + +See [#1782](https://github.com/paritytech/ink/pull/1782) for more details. + +### New Data Structure: `StorageVec` + +We've added a `Vec`-like data structure, built on top of Mapping. + +This allows to retrieve elements from a vector and grow it without +having to load and push all elements. +For `Vec`, the cost of reading or writing a single element grows linearly corresponding +to the number of elements in the vector (its length). Additionally, the maximum capacity +of the whole vector is limited by the size of [ink!'s static buffer](https://github.com/paritytech/ink/blob/master/ARCHITECTURE.md#communication-with-the-pallet) +used during ABI encoding and decoding (default 16 KiB). +`StorageVec` on the other hand allows to access each element individually. + +With a `Vec` it's possible to e.g. introduce a security issue in your contract +where an attacker can fill the `Vec`, making it very costly for other users to +access it or write to it. + +You can find verbatim documentation on `StorageVec` [here](/5.x/datastructures/storagevec). +The page explains when to use `StorageVec` and when not. +The Rust docs can be found [here](https://docs.rs/ink/5.0.0-rc/ink/storage/struct.StorageVec.html). + +### Fallible methods for `Lazy`, `Mapping`, `StorageVec` + +In [#1910](https://github.com/paritytech/ink/pull/1910) we added `try_*` methods for +reading and writing `Lazy` and `Mapping` values to and from storage. +The try methods correspond to `Mapping::{insert, get, take}`, `Lazy::{set, get}`. +For `StorageVec::{peek, get, set, pop, push}` we added `try_*` methods in +[#1995](https://github.com/paritytech/ink/pull/1995). + +Please see the individual Rust docs for these new methods: + +* [`StorageVec`](https://docs.rs/ink/5.0.0-rc/ink/storage/struct.StorageVec.html) +* [`Lazy`](https://docs.rs/ink/5.0.0-rc/ink/storage/struct.Lazy.html) +* [`Mapping`](https://docs.rs/ink/5.0.0-rc/ink/storage/struct.Mapping.html). For `Mapping`, the encoded size of the key is also accounted for. + +You should use the `try_*` methods for dynamically sized values, unless you made sure +otherwise they will fit into the static buffer. The [static buffer in ink!](https://github.com/paritytech/ink/blob/master/ARCHITECTURE.md#communication-with-the-pallet) +is 16 kB by default. + +We added a lint to `cargo-contract` 4.0 that will detect +potentially unsafe uses of methods for which there are safer alternatives: +[`non_fallible_api`](https://use.ink/5.x/linter/rules/non_fallible_api). + +### Chain Extension API changed + Support for multiple chain extensions + +With [#1958](https://github.com/paritytech/ink/pull/1958) we added support for interacting with +multiple chain extensions from ink!. This is a breaking change. + +You can now e.g. have a contract that utilizes a PSP22 chain extension together with one +for random numbers. + +The syntax for chain extensions changed slightly: + +```diff +-#[ink(extension = 0xfecb)] ++#[ink(function = 0xfecb)] +fn foo() {} +``` + +The argument type changed from `u32` to `u16`: + +```diff +-/// `#[ink(extension = N: u32)]` +-Extension, ++/// `#[ink(function = N: u16)]` ++Function, +``` + +A migration in most cases should just be to rename `#[ink(extension = …)]` to +`#[ink(function = …)]`. + +We added an example contract that illustrates the usage of multiple chain extensions +in one contract: +[`combined-extension`](https://github.com/paritytech/ink/tree/master/integration-tests/combined-extension). + +## Interesting New Features + +### End-To-End testing with a chain snapshot + +With ink! 5.0 we introduce the possibility of running your tests against the +fork (i.e. snapshot) of a live chain. + +See [this page](/5.x/basics/contract-testing/chain-snapshot) in our documentation for details. + +### New lints + +The new lints are: +* [`no_main`](/5.x/linter/rules/no_main): enforces `no_main` for contracts. +* [`primitive_topic`](/5.x/linter/rules/primitive_topic): no number types are allowed as event topics. +* [`storage_never_freed`](/5.x/linter/rules/storage_never_freed): what is written into storage can be removed again. +* [`strict_balance_equality`](/5.x/linter/rules/strict_balance_equality): detects usage of strict balance equality checks, a common smart contract vulnerability. +* [`non_fallible_api`](/5.x/linter/rules/non_fallible_api): detects the usage of potentially unsafe methods for which there are safer alternatives. + +With `cargo-contract` 4.0 we added a couple new lints for common smart contract issues +and best practices. +You can run the linter via `cargo contract build --lint`. + +Details on each lint can be found [here](/5.x/linter/overview). + +### New `cargo-contract` commands + +We added a bunch of helpful new commands to `cargo-contract` 4.0. +For all these commands you can also supply the `--help` cli flag to get more +info (e.g. `cargo contract storage --help`). + +* `cargo contract verify`: contract verification ([#1404](https://github.com/paritytech/cargo-contract/pull/1404), [#1306](https://github.com/paritytech/cargo-contract/pull/1306)) +* `cargo contract info` now outputs the language of the deployed contract, using a heuristic ([#1329](https://github.com/paritytech/cargo-contract/pull/1329)) +* `cargo contract info --binary`: outputs the on-chain Wasm of the contract ([#1311](https://github.com/paritytech/cargo-contract/pull/1311/)) +* `cargo contract info --all`: displays all addresses of deployed contracts on a particular chain ([#1319](https://github.com/paritytech/cargo-contract/pull/1319)) +* `cargo contract storage`: displays the storage of an on-chain contract ([#1395](https://github.com/paritytech/cargo-contract/pull/1395), [#1414](https://github.com/paritytech/cargo-contract/pull/1414)) + +
+ +
+ +### Alternative off-chain E2E testing backend support: DRink! + +DRink! is a toolbox for ink! developers that allows for testing your contracts +without any running node. + +It has a number of features that are pretty great: + +- deploy and call your contracts synchronously, _without any delays_ related to block production or networking. +- enhanced debugging and call tracing. +- supports _arbitrary runtime_ configurations, including custom chain extensions and runtime calls. +- full control over runtime state, including block number, timestamp, etc. + +See the [DRink!](https://github.com/inkdevhub/drink) page for more details. + +### Contract Verification + +We added a bunch of helpful documentation and `cargo-contract` commands for +contract verification. [Read more here](/5.x/basics/verification/contract-verification). + +### We improved the contract example illustrating upgradeable contracts via `delegate_call` + +See [here](https://github.com/paritytech/ink/tree/master/integration-tests/upgradeable-contracts) +for the contract example. + +### We made `set_code_hash` generic + +The `self.env().set_code_hash()` method now accepts the `Hash` environment type instead +of a concrete `[u8; 32]`. + +```rust +// Previously +pub fn set_code(&mut self, code_hash: [u8; 32]) { + ink::env::set_code_hash(&code_hash).unwrap_or_else(|err| {}); +} + +// Now +pub fn set_code(&mut self, code_hash: Hash) { + self.env().set_code_hash(&code_hash).unwrap_or_else(|err| {}); +} +``` + +More details in [#1906](https://github.com/paritytech/ink/pull/1906). + +### Buffer size can be customized + +With [#1869](https://github.com/paritytech/ink/pull/1869) we added a possibility +of setting a custom static buffer size for ink! to use. + +ink! uses a static buffer for interacting with pallet-contracts, i.e. to move data +between `pallet-contracts` and a smart contract. The advantage of a static buffer +is that no gas-expensive heap allocations are necessary, all allocations are done +using simple pointer arithmetic. + +The default static buffer size is 16 kB, which is enough for on-chain smart +contracts. However, the [Phala Network](https://phala.network/) parachain on Polkadot +allows the deployment of ink! contracts off-chain. Hence, for their chain certain high +computation contracts might require a larger buffer size. + +### Stabilized `call_runtime` + +We stabilized `call_runtime` in [#1749](https://github.com/paritytech/ink/pull/1749). +It can be used to call a runtime dispatchable from an ink! contract. + +You can find a contract example and a comparison with chain extensions +[here](https://github.com/paritytech/ink/tree/master/integration-tests/call-runtime). +We've added an example of how to end-to-end test +`call_runtime` [here](https://github.com/paritytech/ink/tree/master/integration-tests/e2e-call-runtime). diff --git a/versioned_sidebars/version-5.x-sidebars.json b/versioned_sidebars/version-5.x-sidebars.json index a94f83840b..bac80a6534 100644 --- a/versioned_sidebars/version-5.x-sidebars.json +++ b/versioned_sidebars/version-5.x-sidebars.json @@ -124,6 +124,7 @@ ], "FAQ": [ "faq/faq", + "faq/migrating-from-ink-4-to-5", "faq/migrating-from-ink-3-to-4" ], "Brand Assets": [