Skip to content

Commit

Permalink
Merge pull request #45 from FuelLabs/src-10-native-bridge
Browse files Browse the repository at this point in the history
SRC-10; Native Bridge Standard
  • Loading branch information
bitzoic authored Jan 11, 2024
2 parents 96a223c + b16db31 commit 68fd4f5
Show file tree
Hide file tree
Showing 7 changed files with 244 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ If you don't find what you're looking for, feel free to create an issue and prop
### Bridge

- [SRC-8; Bridged Asset](./standards/src8-bridged-asset/) defines the metadata required for an asset bridged to the Fuel Network.
- [SRC-10; Native Bridge Standard](./standards/src10-native-bridge/) defines the standard API for the Native Bridge between the Fuel Chain and the canonical base chain.

### Documentation

- [SRC-2; Inline Documentation](./standards/src2-inline-docs/) defines how to document your Sway files.


## Using a standard

To import a standard the following should be added to the project's `Forc.toml` file under `[dependencies]` with the most recent release:
Expand Down
1 change: 1 addition & 0 deletions standards/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ members = [
"src5-ownership",
"src6-vault",
"src7-metadata",
"src10-native-bridge",
"src20-token",
]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions standards/src10-native-bridge/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "src10.sw"
license = "Apache-2.0"
name = "src10"
123 changes: 123 additions & 0 deletions standards/src10-native-bridge/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset=".docs/src-10-logo-dark-theme.png">
<img alt="SRC-10 logo" width="400px" src=".docs/src-10-logo-light-theme.png">
</picture>
</p>

# Abstract

The following standard allows for the implementation of a standard API for Native Bridges using the Sway Language. The standardized design has the bridge contract send a message to the origin chain to register which token it accepts to prevent a loss of funds.

# Motivation

A standard interface for bridges intends to provide a safe and efficient bridge between the settlement or canonical chain and the Fuel Network.

# Prior Art

The standard is centered on Fuel’s [Bridge Architecture](https://github.com/FuelLabs/fuel-bridge/blob/main/docs/ARCHITECTURE.md). Fuel's bridge system is built on a message protocol that allows to send (and receive) messages between entities located in two different blockchains.

The following standard takes reference from the [FungibleBridge](https://github.com/FuelLabs/fuel-bridge/blob/3971081850e7961d9b649edda4cad8a848ee248e/packages/fungible-token/bridge-fungible-token/src/interface.sw#L22) ABI defined in the fuel-bridge repository.

# Specification

The following functions MUST be implemented to follow the SRC-10; Native Bridge Standard:

## Required Functions

### - `fn register_token(token_address: b256, gateway_contract: b256)`

The `register_token()` function compiles a message to be sent back to the canonical chain to register a token to be bridged. The `gateway_contract` contract on the canonical chain receives the `token_address` token address in the message such that when `token_addess` tokens are deposited on the canonical chain they are reported to prevent loss of funds.

> **NOTE:*** Trying to deposit tokens to a contract ID that does not exist or does not implement the Fuel Messaging Portal would mean permanent loss of funds.
- This function MUST send a message on the canonical chain to the `gateway_contract` contract, registering the specified `token_address` token that exists on the canonical chain.

### - `fn process_message(message_index: u64)`

The `process_message()` function accepts incoming deposit messages from the canonical chain and issues the corresponding bridged asset.

- This function MUST parse a message at the given `message_index` index.
- This function SHALL mint a token that follows the [SRC-8; Bridged Asset Standard](https://github.com/FuelLabs/sway-standards/tree/master/standards/src_8).
- This function SHALL issue a refund if there is an error in the bridging process.

### - `fn withdraw(to_address: b256, sub_id: SubId, gateway_contract: b256)`

The `withdraw()` function accepts and burns a bridged Native Asset on Fuel and sends a message to the `gateway_contract` contract on the canonical chain to release the originally deposited tokens to the `to_address` address.

- This function SHALL send a message to the `gateway_contract` contract to release the bridged tokens to the `to_address` address on the canonical chain.
- This function MUST ensure the `sha256(contract_id(), sub_id)` digest matches the asset's `AssetId` sent in the transaction.
- This function SHALL burn all tokens sent in the transaction.

### - `fn claim_refund(to_address: b256, token_address: b256, token_id: b256, gateway_contract: b256)`

The `claim_refund()` function is called if something goes wrong in the bridging process and an error occurs. It sends a message to the `gateway_contract` contract on the canonical chain to release the `token_address` token with token id `token_id` to the `to_address` address.

- This function SHALL send a message to the `gateway_contract` contract to release the `token_address` token with id `token_id` to the `to_address` address on the canonical chain.
- This function MUST ensure a refund was issued.

## Required Data Types

### `MessageData`

The following describes a struct that encapsulates various message metadata to a single type. There MUST be the following fields in the `MessageData` struct:

#### - amount: `u256`

The `amount` field MUST represent the number of tokens.

#### - from: `b256`

The `from` field MUST represent the bridging user’s address on the canonical chain.

#### - len: `u16`

The `len` field MUST represent the number of the deposit messages to discern between deposits that must be forwarded to an EOA vs deposits that must be forwarded to a contract.

#### - to: `Identity`

The `to` field MUST represent the bridging target destination `Address` or `ContractId` on the Fuel Chain.

#### - token_address: `b256`

The `token_address` field MUST represent the bridged token's address on the canonical chain.

#### - token_id: `b256`

The `token_id` field MUST represent the token's ID on the canonical chain. The `ZERO_B256` MUST be used if this is a fungible token and no token ID exists.

### Example

```sway
struct MessageData {
amount: b256,
from: b256,
len: u16,
to: Identity,
token_address: b256,
token_id: b256,
}
```

## Required Standards

Any contract that implements the SRC-10; Native Bridge Standard MUST implement the [SRC-8; Bridged Asset Standard](https://github.com/FuelLabs/sway-standards/tree/master/standards/src_8) for all bridged assets.

# Rationale

The SRC-10; Native Bridge Standard is designed to standardize the native bridge interface between all Fuel instances.

# Backwards Compatibility

This standard is compatible with the SRC-20 and SRC-8 standards.

# Example ABI

```sway
abi SRC10 {
fn register_token(token_address: b256, gateway_contract: b256);
fn process_message(message_index: u64);
fn withdraw(to_address: b256, sub_id: SubId, gateway_contract: b256);
fn claim_refund(to_address: b256, token_address: b256, token_id: b256, gateway_contract: b256);
}
```
114 changes: 114 additions & 0 deletions standards/src10-native-bridge/src/src10.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
library;

/// Enscapsultes metadata sent between the canonical chain and Fuel.
struct MessageData {
/// The number of tokens.
amount: b256,
/// The user's address on the canonical chain.
from: b256,
/// The number of deposit messages.
len: u16,
/// The bridging target destination on the Fuel chain.
to: Identity,
/// The bridged token's address on the canonical chain.
token_address: b256,
/// The token's ID on the canonical chain.
token_id: b256,
}

abi SRC10 {
/// Compiles a message to be sent back to the canonical chain.
///
/// # Additional Information
///
/// * The `gateway` contract on the canonical chain receives the `token_address` ID in the message such that when assets are deposited they are reported to prevent loss of funds.
///
/// # Arguments
///
/// * `token_address`: [b256] - The token's address on the canonical chain.
/// * `gateway_contract`: [b256] - The contract that accepts deposits on the canonical chain.
///
/// # Examples
///
/// ```sway
/// use src10::SRC10;
///
/// fn foo(gateway_contract: b256, token_address: b256, bridge: ContractId) {
/// let bridge_abi = abi(SRC10, bridge.value);
/// bridge_abi.register_token(token_address, gateway_contract);
/// }
/// ```
#[storage(read, write)]
fn register_token(token_address: b256, gateway_contract: b256);

/// Accepts incoming deposit messages from the canonical chain and issues the corresponding bridged asset.
///
/// # Arguments
///
/// * `message_index`: [u64] - The index of the message to parse.
///
/// # Examples
///
/// ```sway
/// use src10::SRC10;
///
/// fn foo(message_index: u64, bridge: ContractId) {
/// let bridge_abi = abi(SRC10, bridge.value);
/// bridge_abi.process_message(message_index);
/// }
/// ```
#[storage(read, write)]
fn process_message(message_index: u64);

/// Accepts and burns a bridged asset and sends a messages to the canonical chain to release the original deposited token.
///
/// # Arguments
///
/// * `to_address`: [b256] - The address on the canonical chain to send the released tokens to.
/// * `sub_id`: [SubId] - The SubId of the asset sent in the transaction.
/// * `gateway_contract`: [b256] - The contract that holds the deposited tokens on the canonical chain.
///
/// # Examples
///
/// ```sway
/// use src10::SRC10;
///
/// fn foo(to_address: b256, asset_sub_id: SubId, gateway_contract: b256, bridge: ContractId, bridged_asset: AssetId) {
/// let bridge_abi = abi(SRC10, bridge.value);
/// bridge_abi {
/// gas: 10000,
/// coins: 100,
/// asset_id: bridged_asset,
/// }.withdraw(to_address, asset_sub_id, gateway_contract);
/// }
/// ```
#[storage(read, write)]
fn withdraw(to_address: b256, sub_id: SubId, gateway_contract: b256);

/// Returns a refund on the canonical chain if an error occurs while bridging.
///
/// # Arguments
///
/// * `to_address`: [b256] - The address on the canonical chain to send the refunded tokens to.
/// * `token_address`: [b256] - The token on the canonical chain to be refunded.
/// * `token_id`: [b256] - The token id of the token on the canonical chain to be refunded.
/// * `gateway_contract`: [b256] - The contract that holds the deposited tokens on the canonical chain.
///
/// # Examples
///
/// ```sway
/// use src10::SRC10;
///
/// fn foo(to_address: b256, token_address: b256, token_id: b256, gateway_contract: b256, bridge: ContractId) {
/// let bridge_abi = abi(SRC10, bridge.value);
/// bridge_abi.claim_refund(to_address, token_address, token_id, gateway_contract);
/// }
/// ```
#[storage(read, write)]
fn claim_refund(
to_address: b256,
token_address: b256,
token_id: b256,
gateway_contract: b256,
);
}

0 comments on commit 68fd4f5

Please sign in to comment.