Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New SC upgrade logic documentation #776

Merged
merged 1 commit into from
Dec 21, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions docs/developers/developer-reference/upgrading-smart-contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,35 @@ title: Upgrading smart contracts

[comment]: # (mx-abstract)

## Introduction
## Sirius Mainnet Release - Version 1.6.0

:::important
The new Sirius Mainnet version 1.6.0 brings a significant update to how smart contracts can be upgraded. This release introduces a dedicated `upgrade` function, replacing the previous usage of the `init` function during contract upgrades. This change enhances the upgrade process and provides a clearer separation of concerns between contract initialization and subsequent upgrades.
**Note: Contracts deployed before version 1.6.0 will continue to function as before. The change in upgrade behavior applies only when upgrading the code of the contract. Existing contracts deployed only with an init function will still operate correctly without modifications.**
:::

Please take note of the following important information to ensure a smooth transition.

For contracts developed on or after version 1.6.0, developers should ensure that the `upgrade` function is implemented to handle the necessary upgrade logic. The `init` function will no longer be called during contract upgrades.

Let's look at an example of a simple Adder SC.

```rust
#[init]
fn init(&self, initial_value: u64) {
// Save the initial value in storage only if it is empty.
self.sum().set_if_empty(initial_value);
}

#[upgrade]
fn upgrade(&self, new_value: u64) {
self.sum().set(new_value);
}
```

Let's assume we deploy the contract with the argument **1u64**, and then we upgrade it using the argument **2u64**. If before the new release, after upgrading the SC, we would have the value **1u64** in storage (as the `init` function would have been called, which saves the value in the storage only when it is empty), with the new release, the new value in the storage would be **2u64**.

## Deep diving into the Smart Contract Upgrade Process

Upgrading a smart contract is a relatively easy process, but its implications are not exactly obvious. To upgrade a smart contract, simply run the following command:

Expand All @@ -18,7 +46,7 @@ mxpy --verbose contract upgrade SC_ADDRESS --recall-nonce \

Replace SC_ADDRESS, PEM_PATH and WASM_PATH accordingly. Also, if you want to use testnet/mainnet, also change the proxy and chain ID.

This will replace the given SC's code with the one from the provided file, but that is not all. Additionally, it will run the new code's `init` function. So, if your `init` function has any arguments, the command has to be run by also giving said arguments:
This will replace the given SC's code with the one from the provided file, but that is not all. Additionally, it will run the new code's `upgrade` function. So, if your `upgrade` function has any arguments, the command has to be run by also giving said arguments:

```
mxpy --verbose contract upgrade SC_ADDRESS --recall-nonce \
Expand All @@ -28,13 +56,13 @@ mxpy --verbose contract upgrade SC_ADDRESS --recall-nonce \
--send --proxy=https://devnet-gateway.multiversx.com --chain=D
```

You might've seen in many of the MultiversX contracts, we use the `set_if_empty` method in init, instead of plain `set`. This is so we don't accidentally overwrite an important config value during the upgrade process.
You might've seen in many of the MultiversX contracts, we often use the `set_if_empty` method in `init` and `upgrade` functions, instead of plain `set`. This is so we don't accidentally overwrite an important config value during the upgrade process.

[comment]: # (mx-context-auto)

## What about the old contract's storage?

Storage is kept intact, except for the changes the `init` function might do during upgrade.
Storage is kept intact, except for the changes the `upgrade` function might do during upgrade.

[comment]: # (mx-context-auto)

Expand Down
Loading