Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
f0ca287
Added Cross-Chain Execution docs
andreiblt1304 Jan 14, 2025
8c4045b
Removed some info and added page to sidebars.js
andreiblt1304 Jan 14, 2025
d8c1948
Renamed file and added separate category
andreiblt1304 Jan 14, 2025
00040de
Typo fix
andreiblt1304 Jan 14, 2025
4d2092c
Removed example page
andreiblt1304 Jan 14, 2025
f7aae1c
Added description for main SCs
andreiblt1304 Jan 14, 2025
68a68c2
Renamed title for to-sovereign file
andreiblt1304 Jan 14, 2025
5af921e
Renamed title for from-sovereign file
andreiblt1304 Jan 14, 2025
6f7c324
Made first Cross-Chain execution page more clear
andreiblt1304 Jan 14, 2025
b9f9346
Updated photos
andreiblt1304 Jan 14, 2025
fbf6d13
Fixes after review
andreiblt1304 Jan 14, 2025
dccc49c
Typos
andreiblt1304 Jan 14, 2025
463a9f5
Fixes after review
andreiblt1304 Jan 15, 2025
902bfa1
Added Header-Verifier documentation
andreiblt1304 Jan 15, 2025
eef67bb
Updated diagrams
andreiblt1304 Jan 15, 2025
9ecd4a6
More fixes
andreiblt1304 Jan 15, 2025
f6a9cfc
Fix after review
andreiblt1304 Jan 16, 2025
0f981e1
Spell checker
andreiblt1304 Jan 16, 2025
0c1cc40
Fixes after review
andreiblt1304 Jan 17, 2025
19a4028
Merge branch 'development' into cross-execution
andreiblt1304 Feb 5, 2025
5eec40f
Modified introduction
andreiblt1304 Feb 5, 2025
41d3cae
Modified introduction
andreiblt1304 Feb 5, 2025
d7eaea7
Moved the ESDT-Safe contract at the top
andreiblt1304 Feb 5, 2025
12ad601
Modified from-sovereign docs
andreiblt1304 Feb 5, 2025
0f7fcfa
Fix after review
andreiblt1304 Feb 7, 2025
d12a4ce
Typo
andreiblt1304 Feb 7, 2025
f6f0c9d
Modified Introduction
andreiblt1304 Mar 24, 2025
e58de5b
Merge branch 'main' into cross-execution
andreiblt1304 Mar 25, 2025
85b7d90
Fixes after review
andreiblt1304 Mar 25, 2025
65f8605
Added new section for the mvx-esdt-safe sc
andreiblt1304 Mar 25, 2025
9db337c
Added the note with the source code at the end
andreiblt1304 Mar 25, 2025
1eba345
Added Sov-ESDT-Safe and Header-Verifier pages
andreiblt1304 Mar 25, 2025
3d74d6c
Added link for header-verifier sc
andreiblt1304 Mar 25, 2025
cec0f03
Added correct SC name
andreiblt1304 Mar 25, 2025
ca9df47
Modified sov-esdt-safe docs
andreiblt1304 Mar 26, 2025
f243c1a
Removed old files
andreiblt1304 Mar 26, 2025
049e7b6
Docs review and fixes
andreiblt1304 Mar 26, 2025
ca53b1e
Fixes after review
andreiblt1304 Mar 27, 2025
69fb629
Fixes after review
andreiblt1304 Apr 14, 2025
7dc73b4
Merge branch 'development' into cross-execution
andreiblt1304 Apr 14, 2025
3b299f4
Merge branch 'development' into cross-execution
andreiblt1304 Apr 17, 2025
fea654e
Merge pull request #1033 from multiversx/cross-execution
andreiblt1304 Apr 28, 2025
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
54 changes: 54 additions & 0 deletions docs/sovereign/cross-chain-execution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Introduction

When we take a look at the blockchain industry, we observe a segregated ecosystem lacking cohesion, interoperability and teamwork. The vision lead to the Blockchain Revolution, knows as “Web3” — a new era of the internet that is user-centered, emphasizing data ownership and decentralized trust.

Sovereign Chains will dismantle the barriers between isolated blockchain networks by allowing smart contracts to seamlessly interact across different Sovereign Chains and the main MultiversX chain.
This cross-chain interoperability is crucial for fostering an environment where decentralized apps (dApps) can utilize functionalities or assets from across the ecosystem.

## What is Cross-Chain Execution?

Cross-Chain execution is the ability of a smart contracts or a decentralized applications on one blockchain to invoke actions on another blockchain. This feature allows for smart contract execution or transfer of funds from one chain to another, enabling developers to build applications that are chain agnostic.

## Cross-Chain Execution within Sovereign Chains

Since a Sovereign Chain is a separate blockchain with a different rule-set from the MultiversX blockchain, there has to be a way of communication between them. The interaction is being done by Smart Contracts, the Sovereign Bridge Service and Nodes.

> The MultiversX blockchain will be referred as the _MultiversX Mainchain_ in the further sections.

![To Sovereign](../../static/sovereign/to-sovereign.png)

When a transaction starts from the MultiversX Mainchain, either from a wallet or a smart contract, it goes through the `Mvx-ESDT-Safe` smart contract. The Observer nodes monitor the events that the deposit transaction emits and then the Sovereign Nodes notarize the state changes inside the Sovereign Chain. This notarization means the end of a Cross-Chain transfer.

![From Sovereign](../../static/sovereign/from-sovereign.png)



When the transaction is generated from the Sovereign Chain, the `Sov-ESDT-Safe` smart contract must be used. This smart contract will generate events and from that point, the sovereign nodes, at the end of the round, will read all the outgoing operations (plus all the unconfirmed operations), then these are signed by all the validators, then send to the bridge service, which will make the transaction on main chain

This is a high-level description of the whole process, the smart contracts that take place in it are far more detailed and have a lot of specific scenarios and behaviours. The current Sovereign Chain suite consists of four main contracts, here is the high-level description for some of the cross chain smart contracts:

## Mvx-ESDT-Safe & Sov-ESDT-Safe
The two contracts have the same role: to facilitate a cross-chain execution depending on what side the process starts. The reason for the prefix of `Sov` and `Mvx` is to show where the smart contract is deployed, `Sov` means that the contract is deployed on a Sovereign Chain and `Mvx` that is deployed on the MultiversX Mainchain. There will be an in-depth description of each smart contract in the upcoming modules ([`Mvx-ESDT-Safe`](mvx-esdt-safe.md) and [`Sov-ESDT-Safe`](sov-esdt-safe.md)). The description will consist of flows for the cross-chain interactions, important modules and endpoints.

## Fee-Market
Since every Sovereign Chain will have a customizable fee logic, it was paramount that this configuration had to be separated into a different contract. The rules set inside this contract are:
* fee per transferred token
* fee per gas unit
* users whitelist to bypass the fee

This contract is also present in the MultiversX Mainchain and in any Sovereign Chain.

## Header-Verifier
Any cross-chain transaction that happens inside a Sovereign Chain is called and *operation*. The main role of this contract is to verify operations. They have to be signed by the validators of the Sovereign Chain. If the operation is successfully verified it will be registered and then can be executed by the `Mvx-ESDT-Safe` smart contract. All the *BLS keys* of the validators will be stored inside this contract. The in-depth description of how those _operations_ are registered can be found in the [`Header-Verifier`](header-verifier.md) module.

:::note
The source for the smart contracts can be found at the official [MultiversX Sovereign Chain SCs repository](https://github.com/multiversx/mx-sovereign-sc).
:::

## Sovereign Bridge Service
This feature facilitates the execution of outgoing operations. This service is an application that receives Sovereign operations. After that, it will call the `execute_operation` endpoint from the `Mvx-ESDT-Safe` smart contract. The registration and execution of operations looks like this:

- For N operations there is only one [register transaction](from-sovereign.md#registering-a-set-of-operations) inside the Header-Verifier smart contract.
- N transactions for the [execution](from-sovereign.md#executing-an-operation) of N operations inside the ESDT-Safe smart contract, one execution transaction per operation.

> There can be one or more services deployed in the network at the same time.
53 changes: 53 additions & 0 deletions docs/sovereign/header-verifier.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Header-Verifier

As mentioned in the [Introduction](cross-chain-execution.md) the `Header-Verifier` smart contract is responsible to verify signatures, store the *BLS Keys* of the validators and register incoming *Operations*.

## Registering a set of *Operations*
```rust
#[endpoint(registerBridgeOps)]
fn register_bridge_operations(
&self,
signature: BlsSignature<Self::Api>,
bridge_operations_hash: ManagedBuffer,
operations_hashes: MultiValueEncoded<ManagedBuffer>,
)
```

Any *Operation* before being executed has to be registered in this smart contract. The reason behind this is that the hash will be verified and it will be locked until the operation is executed by the `Mvx-ESDT-Safe` contract.

The registering endpoint operates as follows:
1. Verifies that `bridge_operations_hash` is not found in the `hash_of_hashes_history` storage mapper, otherwise it will return an error.
2. Verifies that the hash of all `operations_hashes` matches the `bridge_operations_hash`, otherwise, the endpoint will return an error.
3. All `operations_hashes` are stored in the smart contract's storage with the status `OperationsHashStatus::NotLocked`.
4. The `bridge_operations_hash` is added to the `hash_of_hashes_history` storage mapper.

## Locking *Operations*
```rust
#[endpoint(lockOperationHash)]
fn lock_operation_hash(&self, hash_of_hashes: ManagedBuffer, operation_hash: ManagedBuffer)
```

The Header-Verifier has a system in place for locking *Operation* hashes. Locking those registered hashes prevents any unwanted behaviour when executing or removing an *Operation* hash. Remember that the execution of *Operations* can only be done by the `Mvx-ESDT-Safe` smart contract. This endpoint when called will follow this flow:

1. Check if the caller is the `Mvx-ESDT-Safe` smart contract.
2. Check if the *Operation* is registered.
3. If the hash is not locked set the status in the storage as locked or else return panic.

:::note
The hash can be in two different states: `OperationHashStatus::NotLocked` or `OperationHashStatus::Locked`
:::

## Removing *Operations*
```rust
#[endpoint(removeExecutedHash)]
fn remove_executed_hash(&self, hash_of_hashes: &ManagedBuffer, operation_hash: &ManagedBuffer)
```

After registering and executing an *Operation* the status of the hash associated to it must be removed from the Header-Verifier's internal storage. This endpoint will be called by the `Mvx-ESDT-Safe` smart contract after the execution of the *Operation* is successful. The steps are pretty clear:

1. Check if the caller is the `Mvx-ESDT-Safe` smart contract.
2. Remove the status of the hash from storage.

:::note
The source code for this contract can be found [here](https://github.com/multiversx/mx-sovereign-sc/blob/main/header-verifier/src/lib.rs).
:::
190 changes: 190 additions & 0 deletions docs/sovereign/mvx-esdt-safe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# Mvx-ESDT-Safe
![To Sovereign](../../static/sovereign/to-sovereign.png)

The ability to transfer tokens from the Main Chain to any Sovereign Chain is essential, since every Sovereign can connect to the Main MultiversX Chain. As a result, the customizable Sovereign can leverage any token available on the default network. Another great feature is the possibility of executing smart contracts inside the Sovereign Chain through this contract.

This contract has three main modules: [`deposit`](#deposit), [`execute_operation`](#executing-an-operation) and [`register_token`](#registering-tokens).


## Deposit
### Main Chain deposit to Sovereign Chain transfer flow
1. User deposits the tokens he wishes to transfer in the `Mvx-ESDT-Safe` contract deployed on the Main Chain.
2. An observer is monitoring the Main Chain.
3. Sovereign network receives extended shard header.
4. Incoming transactions processor handles and processes the new transaction.

### Deposit Endpoint
```rust
#[payable("*")]
#[endpoint]
fn deposit(
&self,
to: ManagedAddress,
optional_transfer_data: OptionalValueTransferDataTuple<Self::Api>,
)
```

One key aspect of cross chain transfers from MultiversX Main Chain to a Sovereign Chain is being able to transfer tokens and also execute a smart contract call within single transaction. The `#[payable("*")]` annotation means that the endpoint can receive any tokens that will transferred. If those tokens are from a Sovereign Chain they will be burned otherwise they will be saved in the Smart Contract`s account. The checks enabled for the transfer of tokens are the following:

- If the token is whitelisted or not blacklisted, in that case the tokens can be transferred.
- If the fee is enabled, the smart contract assures that the fee is paid.
- If there are maximum 10 transfers in the transaction.

If the deposit also includes the `optional_transfer_data` parameter it will also have some extra checks regarding the cross-chain execution of endpoints:

- The gas limit must be under the specified limit.
- The endpoint that has to be executed is not blacklisted.


At the end of the `deposit` endpoint, all the extra tokens will be refunded to the caller and an event will be emitted since the bridging process is complete.


```rust
#[event("deposit")]
fn deposit_event(
&self,
#[indexed] dest_address: &ManagedAddress,
#[indexed] tokens: &MultiValueEncoded<MultiValue3<TokenIdentifier, u64, EsdtTokenData>>,
event_data: OperationData<Self::Api>,
)
```

This log event will emit the destination address and the tokens which will be transferred to the Sovereign Chain.

:::note
The source code for the endpoint can be found [here](https://github.com/multiversx/mx-sovereign-sc/blob/main/mvx-esdt-safe/src/deposit.rs).
:::

## Executing an Operation

```rust
#[endpoint(executeBridgeOps)]
fn execute_operations(
&self,
hash_of_hashes: ManagedBuffer,
operation: Operation<Self::Api>
)
```
- `hash_of_hashes`: hash of all hashes of the operations that were sent in a round
- `operation`: the details of the cross-chain execution

To ensure that the cross-chain execution is will be successful, the following checks must be passed:

1. Calculate the hash of the *Operation* received as a parameter.
2. Verify that the given *Operation’s* hash is registered by the Header-Verifier smart contract.
3. Mint tokens or get them from the account.
4. Distribute the tokens.
5. Emit confirmation event or fail event if needed.

As the 2nd point specifies, the `Header-Verifier` smart contract plays an important role in the cross-chain execution mechanism. In the [`Header-Verifier`](header-verifier.md) section there will also be a description for the important endpoints within this contract.

:::note
The source code for the endpoint can be found [here](https://github.com/multiversx/mx-sovereign-sc/blob/main/mvx-esdt-safe/src/execute.rs).
:::

## Important Endpoint Related Structures
This subsection outlines the key data structures that enable robust cross-chain operations. It details how an *Operation* is composed of its destination address, one or more token transfers defined by `OperationEsdtPayment`, and the contextual metadata provided by `OperationData`. Additionally, `TransferData` specifies the parameters needed for executing remote smart contract calls, collectively ensuring precise control over cross-chain interactions.
```rust
#[derive(TopEncode, TopDecode, NestedEncode, NestedDecode, TypeAbi, ManagedVecItem, Clone)]
pub struct Operation<M: ManagedTypeApi> {
pub to: ManagedAddress<M>,
pub tokens: ManagedVec<M, OperationEsdtPayment<M>>,
pub data: OperationData<M>,
}
```

- `to`: specifies the destination of the *Operation*
- `tokens`: represents one or more token transfers associated with the operation
- `data`: encapsulates additional instructions or parameters that guide the execution of the operation

```rust
pub struct OperationEsdtPayment<M: ManagedTypeApi> {
pub token_identifier: TokenIdentifier<M>,
pub token_nonce: u64,
pub token_data: EsdtTokenData<M>,
}
```

This struct describes a single token transfer action within an *Operation*. Each Operation can have one or more of such payments, with that enabling the transfer of a variety of tokens during a cross-chain transaction.

- `token_identifier`: used for the identification of the token
- `token_nonce`: if the token is Non-Fungible or Semi-Fungible, it will have a custom nonce, if not the value will be 0
- `token_data`: a structure holding metadata and other token properties

```rust
pub struct OperationData<M: ManagedTypeApi> {
pub op_nonce: TxId,
pub op_sender: ManagedAddress<M>,
pub opt_transfer_data: Option<TransferData<M>>,
}
```

`OperationData` encapsulates the needed information for the *Operation* that needs to be executed. This isn’t just another data definition, we’ve already seen data-related fields elsewhere. Instead, it centralizes the contextual information that *Operation* needs before, during, and after execution.

- `op_nonce`: is used for the identification of each *Operation*
- `op_sender`: represents the original sender of the *Operation*
- `opt_transfer_data`: an optional `TransferData` field, when present, contains details about the cross-chain execution of another Smart Contract

```rust
pub struct TransferData<M: ManagedTypeApi> {
pub gas_limit: GasLimit,
pub function: ManagedBuffer<M>,
pub args: ManagedVec<M, ManagedBuffer<M>>,
}
```

`TransferData` represents the description of the remote execution of another Smart Contract.

- `gas_limit`: specifies the needed gas for the execution of all other endpoints.
- `function`: the name of the endpoint that will be executed.
- `args`: the arguments for the calls.

:::note
The source code for structures can be found [here](https://github.com/multiversx/mx-sovereign-sc/blob/main/common/structs/src/operation.rs).
:::

## Registering tokens
As mentioned at the start of this section, in the scope a Sovereign Chain, a token that already exists inside the MultiversX Mainchain can be leveraged within the custom blockchain. It has to be firstly registered inside the `Mvx-ESDT-Safe` smart contract. The `register_token` module has the role of registering any token that will be later used inside the Sovereign Chain.

### Register any token

```rust
#[payable("EGLD")]
#[endpoint(registerToken)]
fn register_token(
&self,
sov_token_id: TokenIdentifier,
token_type: EsdtTokenType,
token_display_name: ManagedBuffer,
token_ticker: ManagedBuffer,
num_decimals: usize,
)
```

This endpoint is how an user from a Sovereign Chain registers a token on the MultiversX Mainchain. Every token registration costs 0.05 EGLD, that's why the endpoint is `payable`.
The endpoint check if the token was not registered before and if it has a prefix.

> Every token that was created in a Sovereign Chain has a prefix. Example: `sov-TOKEN-123456`.

If everything is in order, the `Mvx-ESDT-Safe` smart contract will initiate an asynchronous call to the `issue_and_set_all_roles` endpoint from the _ESDTSystemSC_. When the system smart contract finishes the issue transaction, the callback inside the `Mvx-ESDT-Safe` smart contract will trigger and register the mapping of token identifier inside the token mappers:

* `sovereign_to_multiversx_token_id_mapper(sov_token_id)` -> mvx_token_id
* `multiversx_to_sovereign_token_id_mapper(mvx_token_id)` -> sov_token_id

> After the execution of this endpoint, the `Mvx-ESDT-Safe` smart contract will have in its storage a pair of token identifiers. **Example**: `sov-TOKEN-123456` is the corresponding sovereign identifier for the `TOKEN-123456` identifier from the MultiversX Mainchain. You can view this feature as creating copies of MultiversX Mainchain tokens inside the Sovereign Chain.

### Register the native token
Since a Sovereign Chain is a separate blockchain from the MultiversX Mainchain, it has to have a its own native token. Registering the native token is a straightforward process of just one endpoint call.

```rust
#[payable("EGLD")]
#[only_owner]
#[endpoint(registerNativeToken)]
fn register_native_token(&self, token_ticker: ManagedBuffer, token_name: ManagedBuffer)
```

The owner will have to call the `register_native_token` from the `Mvx-ESDT-Safe` smart contract in order to register the token identifier that will be used inside the Sovereign Chain as the native one. There can only be one native token so the endpoint firstly checks if if was not already registered. The fee amount for registering is the same as registering any token, 0.05 EGLD. The parameters include the `token_ticker` and `token_name`. The endpoint then initiates an asynchronous call to the _ESDTSystemSC_ to `issue_and_set_all_roles`. The newly created token is always fungible and has 18 decimals. After the issue call is finished the callback inside the `Mvx-ESDT-Safe` smart contract inserts the newly issued token identifier inside its storage.

:::note
The source code for this module can be found [here](https://github.com/multiversx/mx-sovereign-sc/blob/main/mvx-esdt-safe/src/register_token.rs).
:::
Loading
Loading