Skip to content

Commit

Permalink
Merge branch 'development' into extend-sdk-nesdtjs-docs
Browse files Browse the repository at this point in the history
# Conflicts:
#	docs/developers/meta/sc-meta-cli.md
  • Loading branch information
bogdan-rosianu committed Feb 7, 2024
2 parents 6e10a95 + 45c945e commit 66b660f
Show file tree
Hide file tree
Showing 97 changed files with 3,656 additions and 555 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deploy-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
- uses: actions/checkout@v2
with:
ref: main
fetch-depth: 0
- name: Use Node.js
uses: actions/setup-node@v1
with:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
- uses: actions/checkout@v2
with:
ref: development
fetch-depth: 0
- name: Use Node.js
uses: actions/setup-node@v1
with:
Expand Down
2 changes: 1 addition & 1 deletion docs/developers/data/composite-values.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: Composite Values
---
[comment]: # (mx-abstract)

We often need to group simple values into more complex ones, without splitting them into [several arguments](/developers/data/multi-value).
We often need to group simple values into more complex ones, without splitting them into [several arguments](/developers/data/multi-values).

Here too we opted for an encoding that is, above all, very easy to read.

Expand Down
52 changes: 52 additions & 0 deletions docs/developers/developer-reference/storage-mappers.md
Original file line number Diff line number Diff line change
Expand Up @@ -1113,3 +1113,55 @@ fn list_per_user_pair(&self, first_addr: &ManagedAddress, second_addr: &ManagedA
```

Using the correct mapper for your situation can greatly decrease gas costs and complexity, so always remember to carefully evaluate your use-case.

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

## Accessing a value at an address

Because of the way the storage mappers are structured, it is very easy to access a "remote" value, meaning a value stored
under a key at a different address than the current one.

If a developer wanted, for example, to iterate over another contract's `SetMapper`, instead of retrieving the values through
a call to an endpoint and then iterating, one could simply create a new `SetMapper` with a specific `address` parameter
(the address of the contract where the remote storage is located) and the `exact key` used by the storage they wish to access.
Afterwards, it acts like a "local" storage mapper, so the `iter` function can be called easily to accomplish the task.

:::important important
This feature only works `intra-shard`.

Also note that a remote value found under a key at an address can only be `read`, not modified.
:::

Let's take this example:
```rust title=contract_to_be_called/lib.rs
#[storage_mapper("my_remote_mapper")]
fn my_set_mapper(&self) -> SetMapper<u32>
```

This is a simple `SetMapper` registered under the address of `contract_to_be_called`, and the value stored will be registered under the key provided, `my_remote_mapper`. If we wanted to iterate over the values of `my_set_mapper` intra-shard, we could write:

```rust title=caller_contract/lib.rs
// the address of the contract containing the storage (contract_to_be_called)
#[storage_mapper("contract_address")]
fn contract_address(&self) -> SingleValueMapper<ManagedAddress>;

#[endpoint]
fn my_endpoint(&self) -> u32 {
let mut sum = 0u32;
let address = self.contract_address().get();

// by creating the mapper with the address of the sc and exact storage key
// we get access to the value stored under that key
let mapper: SetMapper<u32, _> =
SetMapper::new_from_address(address, StorageKey::from("my_remote_mapper"));
for number in mapper.iter() {
sum += number
}

sum
}
```

Calling `my_endpoint` will return the sum of the values stored in `contract_to_be_called`'s SetMapper.

By specifying the expected type, storage key and address, the value can be read and used inside our logic.
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

0 comments on commit 66b660f

Please sign in to comment.