From 3f3433a12d3f9a7bda5b71ec85f0046c6213726a Mon Sep 17 00:00:00 2001 From: bitzoic Date: Tue, 19 Dec 2023 10:13:27 -0500 Subject: [PATCH 01/13] Initial commit --- standards/src_10/README.md | 115 +++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 standards/src_10/README.md diff --git a/standards/src_10/README.md b/standards/src_10/README.md new file mode 100644 index 0000000..fd26933 --- /dev/null +++ b/standards/src_10/README.md @@ -0,0 +1,115 @@ +# 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_bridge(token: b256, gateway: b256)` + +The `register_bridge()` function compiles a message to be sent back to the canonical chain. The `gateway` contract on the canonical chain receives the `token` ID in the message such that when assets are deposited 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, registering the specified `token`. + +### - `fn process_message(msg_idx: 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 `msg_idx` 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: b256, sub_id: b256, gateway: b256)` + +The `withdraw()` function accepts and burns a bridged asset and sends a message to the `gateway` contract on the canonical chain to release the original deposited token to the `to` address. + +- This function SHALL send a message to the `gateway` contract to release the bridged tokens to the `to` address on the canonical chain. +- This function MUST ensure the `sha256(contract_id(), sub_id)` matches the asset's `AssetId` sent in the transaction. +- This function SHALL burn all tokens sent in the transaction. + +### - `fn claim_refund(to: b256, token: b256, token_id: b256, gateway: 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 on the canonical chain to release the `token` token with token id `token_id` to the `to` address. + +- This function SHALL send a message to the `gateway` contract to release the `token` token with id `token_id` to the `to` 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 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: `Option` + +The `token_id` field MUST represent the token's ID on the canonical chain. MUST be `None` 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: Option, +} +``` + +## 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_bridge(token: b256, gateway: b256); + fn process_message(msg_idx: u64); + fn withdraw(to: b256, sub_id: b256, gateway: b256); + fn claim_refund(to: b256, token_address: b256, token_id: b256, gateway: b256); +} +``` \ No newline at end of file From 24bf320866c7bf8553c3e82edcfde7c05c3aaa1a Mon Sep 17 00:00:00 2001 From: bitzoic Date: Wed, 20 Dec 2023 11:47:23 -0500 Subject: [PATCH 02/13] Add SRC10 library --- standards/src_10/Forc.toml | 5 ++ standards/src_10/src/src_10.sw | 109 +++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 standards/src_10/Forc.toml create mode 100644 standards/src_10/src/src_10.sw diff --git a/standards/src_10/Forc.toml b/standards/src_10/Forc.toml new file mode 100644 index 0000000..73ced7d --- /dev/null +++ b/standards/src_10/Forc.toml @@ -0,0 +1,5 @@ +[project] +authors = ["Fuel Labs "] +entry = "src_10.sw" +license = "Apache-2.0" +name = "src_10" diff --git a/standards/src_10/src/src_10.sw b/standards/src_10/src/src_10.sw new file mode 100644 index 0000000..2c2002c --- /dev/null +++ b/standards/src_10/src/src_10.sw @@ -0,0 +1,109 @@ +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 birdged token's addrss on the canonical chain. + token_address: b256, + /// The token's ID on the canonical chain. + token_id: Option, +} + +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` ID in the message such that when assets are deposited they are reported to prevent loss of funds. + /// + /// # Arguments + /// + /// * `token`: [b256] - The token's address on the canonical chain. + /// * `gateway`: [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_bridge(token_address, gateway_contract); + /// } + /// ``` + #[storage(read, write)] + fn register_bridge(token: b256, gateway: b256); + + /// Accepts incomming deposit messages from the canonical chain and issues the corresponding bridged asset. + /// + /// # Arguments + /// + /// * `msg_idx`: [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(msg_idx: u64); + + /// Accepts and burns a bridged asset and sends a messages to the canonical chain to release the original deposited token. + /// + /// # Arguments + /// + /// * `to`: [b256] - The address on the canoncial chain to send the released tokens to. + /// * `sub_id`: [SubId] - The SubId of the asset sent in the transaction. + /// * `gateway`: [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: b256, sub_id: SubId, gateway: b256); + + /// Returns a refund on the canonical chain if an error occurs swhile bridging. + /// + /// # Arguments + /// + /// * `to`: [b256] - The address on the canoncial chain to send the refunded tokens to. + /// * `token`: [b256] - The token on the canonical chain to be refunded. + /// * `token_id`: [Option] - The token id of the token on the canoncial chain to be refunded. + /// * `gateway`: [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: Option, 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: b256, token: b256, token_id: Option, gateway: b256); +} From 5477d847aa0e96e63ed48fc4b923f5f959f9f07a Mon Sep 17 00:00:00 2001 From: bitzoic Date: Wed, 20 Dec 2023 11:47:41 -0500 Subject: [PATCH 03/13] Add SRC10 header --- .../src_10/.docs/src-10-logo-dark-theme.png | Bin 0 -> 20897 bytes .../src_10/.docs/src-10-logo-light-theme.png | Bin 0 -> 23823 bytes standards/src_10/README.md | 17 ++++++++++++----- 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 standards/src_10/.docs/src-10-logo-dark-theme.png create mode 100644 standards/src_10/.docs/src-10-logo-light-theme.png diff --git a/standards/src_10/.docs/src-10-logo-dark-theme.png b/standards/src_10/.docs/src-10-logo-dark-theme.png new file mode 100644 index 0000000000000000000000000000000000000000..1eee3b5964869a0886308853a83ac5b2d1c6d4ce GIT binary patch literal 20897 zcmeFYXH=8X+9*hGqEzV}>4X+~Rhks(9hIH{(n1Xgq4%!RQ4thDQ9wZ{p#%`H1dt*~ z2?P*ON(dqZ3}s&QoO91vbMMT2Yt6mCK3IgjyF7b8z3lyFSejowPsc?^LPB!h*ht@+ zgoF$SeE&p41$@dcvq6D>{kLr$!>rxm0nC7L_ao7DRHRrd%RrF`VccP|Aw-;!|4mnjLX~RgGt!sTcEguZ3GX>BW5P_31;eW58p=bVTP`=9Ax$Z^tBgxrVW+R_BF9W!*Rw zr{C4a;7(>DuRaf%{guY7 zOw~zA)=J&li_YP4ZNJWyDPEG0$xZa@>B;MVo|M&8f1y56;DB^#ed)<}A(0bViRSbj zY%BjZP760rs@sWHtP`g4X%BeH94vqD=0&6nlPbrWVFA3WrsY>!AV z918BrRf4N*Go&tLCH+c z45kP1@in>~0-O{;tvS`fQAD5lmCzLVZPA+L9GAS+gZ;abpCxKz;geB{~x3OiTj_yz$h~_b^RdE z@UumY^|ge~_N(p{l-0l>RaM|oLCFj1p$Jx$_fi4> z8z|$z&@lHvPskZ40Jw}V00*L^qNE6xQvpFBUY;ODMNegrhn$BB$jigSL&Z}b3RZMi z`Zo|3A-;fAy8Hk8uFgPt0icxSGqJ2P(b3&fXd6sfEE8t_wrOX1VFk2lH(iT?hTQJ1$zJKIOB^tfDJ%d z_cK8SApdCxkWtqQfw+eSh1doK`D+QCZB5_|7d(_fXcfdv13`uphb z`$v}q1pa7+y1VCJ6hhr2AYOm=3BdZ><>})d=nVnP$3NutpY6W?6IoCJ%d5)E%PWJt z+~w6kiV6@Fkg9^G7YGb-_fU`nd#Jg~tNbVQ&>(0S+&u(x#T%d_Kr28#|IkW6{F-lI zc%;OCj)wa{&e#JG3?!!jQc$s#lT%laS65P$0=@tQll?z{q8wNOqNb(_QU)ujfD}EH zltJzuYJj*a05atcRg{zSaR1Lu|F2PW@D20|f`|S;APL~9YAdIvt^`(BQ2sxGp1XpI zlDzU6W?r81fHo^ZKprZw z%AVQ%e+sRp?Eg)y{|@*!M**<@ZyVr%0DmU?FNgLInK*MD{~Le)p-%rBR{%i&_agr# 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 + + + SRC-10 logo + +

+ # 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. @@ -33,7 +40,7 @@ The `process_message()` function accepts incoming deposit messages from the cano - 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: b256, sub_id: b256, gateway: b256)` +### - `fn withdraw(to: b256, sub_id: SubId, gateway: b256)` The `withdraw()` function accepts and burns a bridged asset and sends a message to the `gateway` contract on the canonical chain to release the original deposited token to the `to` address. @@ -41,7 +48,7 @@ The `withdraw()` function accepts and burns a bridged asset and sends a message - This function MUST ensure the `sha256(contract_id(), sub_id)` matches the asset's `AssetId` sent in the transaction. - This function SHALL burn all tokens sent in the transaction. -### - `fn claim_refund(to: b256, token: b256, token_id: b256, gateway: b256)` +### - `fn claim_refund(to: b256, token: b256, token_id: Option, gateway: 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 on the canonical chain to release the `token` token with token id `token_id` to the `to` address. @@ -76,7 +83,7 @@ The `token_address` field MUST represent the bridged token's address on the cano #### - token_id: `Option` -The `token_id` field MUST represent the token's ID on the canonical chain. MUST be `None` if this is a fungible token and no token ID exists +The `token_id` field MUST represent the token's ID on the canonical chain. MUST be `None` if this is a fungible token and no token ID exists. ### Example @@ -109,7 +116,7 @@ This standard is compatible with the SRC-20 and SRC-8 standards. abi SRC10 { fn register_bridge(token: b256, gateway: b256); fn process_message(msg_idx: u64); - fn withdraw(to: b256, sub_id: b256, gateway: b256); - fn claim_refund(to: b256, token_address: b256, token_id: b256, gateway: b256); + fn withdraw(to: b256, sub_id: SubId, gateway: b256); + fn claim_refund(to: b256, token_address: b256, token_id: Option, gateway: b256); } ``` \ No newline at end of file From eaa93f8c041d96d09e998fed220311fa5e2e396c Mon Sep 17 00:00:00 2001 From: bitzoic Date: Wed, 20 Dec 2023 11:49:39 -0500 Subject: [PATCH 04/13] Add SRC10 to source readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index de32097..d1990da 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ If you don't find what you're looking for, feel free to create an issue and prop - [SRC-5; Ownership Standard](./standards/src_5/) is used to restrict function calls to admin users in contracts. - [SRC-7; Arbitrary Asset Metadata Standard](./standards/src_7/) is used to store metadata for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets). - [SRC-9; Metadata Keys Standard](./standards/src_9/) is used to store standardized metadata keys for [Native Assets](https://fuellabs.github.io/sway/v0.44.0/book/blockchain-development/native_assets.html) in combination with the SRC-7 standard. +- [SRC-10; Native Bridge Standard](./standards/src_10/) defines the standard API for the Native Bridge between the Fuel Chain and the canonical base chain. ## Using a standard From 531d69f8dcd05cc83c3c6cf50c1b860717ee78d1 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Wed, 20 Dec 2023 11:49:47 -0500 Subject: [PATCH 05/13] Add SRC10 to workdspace --- standards/Forc.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standards/Forc.toml b/standards/Forc.toml index 67c80e8..349f2c1 100644 --- a/standards/Forc.toml +++ b/standards/Forc.toml @@ -1,2 +1,2 @@ [workspace] -members = ["src_3", "src_5", "src_6", "src_7", "src_20"] +members = ["src_3", "src_5", "src_6", "src_7", "src_10", "src_20"] From dacb3aaddb7c5821f53716061f6099e9a74b4d05 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Wed, 20 Dec 2023 11:50:44 -0500 Subject: [PATCH 06/13] Run formatter --- standards/src_10/src/src_10.sw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/standards/src_10/src/src_10.sw b/standards/src_10/src/src_10.sw index 2c2002c..b516929 100644 --- a/standards/src_10/src/src_10.sw +++ b/standards/src_10/src/src_10.sw @@ -21,7 +21,7 @@ abi SRC10 { /// /// # Additional Information /// - /// * The `gateway` contract on the canonical chain receives the `token` ID in the message such that when assets are deposited they are reported to prevent loss of funds. + /// * The `gateway` contract on the canonical chain receives the `token` ID in the message such that when assets are deposited they are reported to prevent loss of funds. /// /// # Arguments /// @@ -68,7 +68,7 @@ abi SRC10 { /// * `sub_id`: [SubId] - The SubId of the asset sent in the transaction. /// * `gateway`: [b256] - The contract that holds the deposited tokens on the canonical chain. /// - /// # Examples + /// # Examples /// /// ```sway /// use src10::SRC10; From ec69a6aa302a4af54ca1a627250a01c2595f1a4a Mon Sep 17 00:00:00 2001 From: bitzoic Date: Thu, 21 Dec 2023 10:19:41 -0500 Subject: [PATCH 07/13] Resolve PR comments --- standards/src_10/README.md | 35 +++++++++++++++++----------------- standards/src_10/src/src_10.sw | 32 +++++++++++++++---------------- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/standards/src_10/README.md b/standards/src_10/README.md index 45a16f8..141eb66 100644 --- a/standards/src_10/README.md +++ b/standards/src_10/README.md @@ -15,7 +15,7 @@ A standard interface for bridges intends to provide a safe and efficient bridge # 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 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. @@ -25,41 +25,42 @@ The following functions MUST be implemented to follow the SRC-10; Native Bridge ## Required Functions -### - `fn register_bridge(token: b256, gateway: b256)` +### - `fn register_bridge(token_address: b256, gateway_contract: b256)` + +The `register_bridge()` function compiles a message to be sent back to the canonical chain. The `gateway_contract` contract on the canonical chain receives the `token_address` token in the message such that when assets are deposited they are reported to prevent loss of funds. -The `register_bridge()` function compiles a message to be sent back to the canonical chain. The `gateway` contract on the canonical chain receives the `token` ID in the message such that when assets are deposited 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, registering the specified `token`. +- This function MUST send a message on the canonical chain to the `gateway_contract` contract, registering the specified `token_address`. -### - `fn process_message(msg_idx: u64)` +### - `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 `msg_idx` index. +- 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: b256, sub_id: SubId, gateway: b256)` +### - `fn withdraw(to_address: b256, sub_id: SubId, gateway_contract: b256)` -The `withdraw()` function accepts and burns a bridged asset and sends a message to the `gateway` contract on the canonical chain to release the original deposited token to the `to` address. +The `withdraw()` function accepts and burns a bridged asset and sends a message to the `gateway_contract` contract on the canonical chain to release the originally deposited token to the `to_address` address. -- This function SHALL send a message to the `gateway` contract to release the bridged tokens to the `to` address on the canonical chain. +- 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)` matches the asset's `AssetId` sent in the transaction. - This function SHALL burn all tokens sent in the transaction. -### - `fn claim_refund(to: b256, token: b256, token_id: Option, gateway: b256)` +### - `fn claim_refund(to_address: b256, token_address: b256, token_id: Option, 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 on the canonical chain to release the `token` token with token id `token_id` to the `to` address. +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 to release the `token` token with id `token_id` to the `to` address on the canonical chain. +- 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 single type. - There MUST be the following fields in the `MessageData` struct: +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` @@ -114,9 +115,9 @@ This standard is compatible with the SRC-20 and SRC-8 standards. ```sway abi SRC10 { - fn register_bridge(token: b256, gateway: b256); - fn process_message(msg_idx: u64); - fn withdraw(to: b256, sub_id: SubId, gateway: b256); - fn claim_refund(to: b256, token_address: b256, token_id: Option, gateway: b256); + fn register_bridge(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: Option, gateway_contract: b256); } ``` \ No newline at end of file diff --git a/standards/src_10/src/src_10.sw b/standards/src_10/src/src_10.sw index b516929..40ef06f 100644 --- a/standards/src_10/src/src_10.sw +++ b/standards/src_10/src/src_10.sw @@ -10,7 +10,7 @@ struct MessageData { len: u16, /// The bridging target destination on the Fuel chain. to: Identity, - /// The birdged token's addrss on the canonical chain. + /// The bridged token's address on the canonical chain. token_address: b256, /// The token's ID on the canonical chain. token_id: Option, @@ -25,8 +25,8 @@ abi SRC10 { /// /// # Arguments /// - /// * `token`: [b256] - The token's address on the canonical chain. - /// * `gateway`: [b256] - The contract that accepts deposits on the canonical chain. + /// * `token_address`: [b256] - The token's address on the canonical chain. + /// * `gateway_contract`: [b256] - The contract that accepts deposits on the canonical chain. /// /// # Examples /// @@ -39,13 +39,13 @@ abi SRC10 { /// } /// ``` #[storage(read, write)] - fn register_bridge(token: b256, gateway: b256); + fn register_bridge(token_address: b256, gateway_contract: b256); - /// Accepts incomming deposit messages from the canonical chain and issues the corresponding bridged asset. + /// Accepts incoming deposit messages from the canonical chain and issues the corresponding bridged asset. /// /// # Arguments /// - /// * `msg_idx`: [u64] - The index of the message to parse. + /// * `message_index`: [u64] - The index of the message to parse. /// /// # Examples /// @@ -58,15 +58,15 @@ abi SRC10 { /// } /// ``` #[storage(read, write)] - fn process_message(msg_idx: u64); + 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`: [b256] - The address on the canoncial chain to send the released tokens to. + /// * `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`: [b256] - The contract that holds the deposited tokens on the canonical chain. + /// * `gateway_contract`: [b256] - The contract that holds the deposited tokens on the canonical chain. /// /// # Examples /// @@ -83,16 +83,16 @@ abi SRC10 { /// } /// ``` #[storage(read, write)] - fn withdraw(to: b256, sub_id: SubId, gateway: b256); + fn withdraw(to_address: b256, sub_id: SubId, gateway_contract: b256); - /// Returns a refund on the canonical chain if an error occurs swhile bridging. + /// Returns a refund on the canonical chain if an error occurs while bridging. /// /// # Arguments /// - /// * `to`: [b256] - The address on the canoncial chain to send the refunded tokens to. - /// * `token`: [b256] - The token on the canonical chain to be refunded. - /// * `token_id`: [Option] - The token id of the token on the canoncial chain to be refunded. - /// * `gateway`: [b256] - The contract that holds the deposited tokens on the canonical chain. + /// * `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`: [Option] - 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 /// @@ -105,5 +105,5 @@ abi SRC10 { /// } /// ``` #[storage(read, write)] - fn claim_refund(to: b256, token: b256, token_id: Option, gateway: b256); + fn claim_refund(to_address: b256, token_address: b256, token_id: Option, gateway_contract: b256); } From 202a0115b77648ae4707d9f05791f1f81ef704d8 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Thu, 21 Dec 2023 10:25:27 -0500 Subject: [PATCH 08/13] Run formatter --- standards/src_10/src/src_10.sw | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/standards/src_10/src/src_10.sw b/standards/src_10/src/src_10.sw index 40ef06f..2534e6e 100644 --- a/standards/src_10/src/src_10.sw +++ b/standards/src_10/src/src_10.sw @@ -105,5 +105,10 @@ abi SRC10 { /// } /// ``` #[storage(read, write)] - fn claim_refund(to_address: b256, token_address: b256, token_id: Option, gateway_contract: b256); + fn claim_refund( + to_address: b256, + token_address: b256, + token_id: Option, + gateway_contract: b256, + ); } From 6866873a1ad3aa9dfa283e78a4712b0766e089f6 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Fri, 22 Dec 2023 12:24:49 -0500 Subject: [PATCH 09/13] Update SRC10 to new folder structure --- README.md | 4 ++-- standards/Forc.toml | 2 +- .../.docs/src-10-logo-dark-theme.png | Bin .../.docs/src-10-logo-light-theme.png | Bin standards/{src_10 => src10-native-bridge}/Forc.toml | 4 ++-- standards/{src_10 => src10-native-bridge}/README.md | 0 .../src_10.sw => src10-native-bridge/src/src10.sw} | 0 7 files changed, 5 insertions(+), 5 deletions(-) rename standards/{src_10 => src10-native-bridge}/.docs/src-10-logo-dark-theme.png (100%) rename standards/{src_10 => src10-native-bridge}/.docs/src-10-logo-light-theme.png (100%) rename standards/{src_10 => src10-native-bridge}/Forc.toml (67%) rename standards/{src_10 => src10-native-bridge}/README.md (100%) rename standards/{src_10/src/src_10.sw => src10-native-bridge/src/src10.sw} (100%) diff --git a/README.md b/README.md index ca1ce84..773cf9b 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,8 @@ If you don't find what you're looking for, feel free to create an issue and prop - [SRC-3; Mint and Burn](./standards/src_3/) is used to enable mint and burn functionality for Native Assets. - [SRC-5; Ownership Standard](./standards/src_5/) is used to restrict function calls to admin users in contracts. - [SRC-7; Arbitrary Asset Metadata Standard](./standards/src_7/) is used to store metadata for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets). -- [SRC-9; Metadata Keys Standard](./standards/src_9/) is used to store standardized metadata keys for [Native Assets](https://fuellabs.github.io/sway/v0.44.0/book/blockchain-development/native_assets.html) in combination with the SRC-7 standard. -- [SRC-10; Native Bridge Standard](./standards/src_10/) defines the standard API for the Native Bridge between the Fuel Chain and the canonical base chain. +- [SRC-9; Metadata Keys Standard](./standards/src_9/) is used to store standardized metadata keys for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets) in combination with the SRC-7 standard. +- [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. ## Using a standard diff --git a/standards/Forc.toml b/standards/Forc.toml index 70aabad..81cbc92 100644 --- a/standards/Forc.toml +++ b/standards/Forc.toml @@ -4,6 +4,6 @@ members = [ "src5-ownership", "src6-vault", "src7-metadata", - "src_10", + "src-10-native-bridge", "src20-token", ] diff --git a/standards/src_10/.docs/src-10-logo-dark-theme.png b/standards/src10-native-bridge/.docs/src-10-logo-dark-theme.png similarity index 100% rename from standards/src_10/.docs/src-10-logo-dark-theme.png rename to standards/src10-native-bridge/.docs/src-10-logo-dark-theme.png diff --git a/standards/src_10/.docs/src-10-logo-light-theme.png b/standards/src10-native-bridge/.docs/src-10-logo-light-theme.png similarity index 100% rename from standards/src_10/.docs/src-10-logo-light-theme.png rename to standards/src10-native-bridge/.docs/src-10-logo-light-theme.png diff --git a/standards/src_10/Forc.toml b/standards/src10-native-bridge/Forc.toml similarity index 67% rename from standards/src_10/Forc.toml rename to standards/src10-native-bridge/Forc.toml index 73ced7d..331e3ff 100644 --- a/standards/src_10/Forc.toml +++ b/standards/src10-native-bridge/Forc.toml @@ -1,5 +1,5 @@ [project] authors = ["Fuel Labs "] -entry = "src_10.sw" +entry = "src10.sw" license = "Apache-2.0" -name = "src_10" +name = "src10" diff --git a/standards/src_10/README.md b/standards/src10-native-bridge/README.md similarity index 100% rename from standards/src_10/README.md rename to standards/src10-native-bridge/README.md diff --git a/standards/src_10/src/src_10.sw b/standards/src10-native-bridge/src/src10.sw similarity index 100% rename from standards/src_10/src/src_10.sw rename to standards/src10-native-bridge/src/src10.sw From ad6e5de7355cb44a5cdcfe7be00439706d74e4b5 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Fri, 22 Dec 2023 12:28:34 -0500 Subject: [PATCH 10/13] Fix Forc.toml error --- README.md | 2 +- standards/Forc.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 773cf9b..8c3be87 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ If you don't find what you're looking for, feel free to create an issue and prop - [SRC-3; Mint and Burn](./standards/src_3/) is used to enable mint and burn functionality for Native Assets. - [SRC-5; Ownership Standard](./standards/src_5/) is used to restrict function calls to admin users in contracts. - [SRC-7; Arbitrary Asset Metadata Standard](./standards/src_7/) is used to store metadata for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets). -- [SRC-9; Metadata Keys Standard](./standards/src_9/) is used to store standardized metadata keys for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets) in combination with the SRC-7 standard. +- [SRC-9; Metadata Keys Standard](./standards/src_9/) is used to store standardized metadata keys for [Native Assets](https://fuellabs.github.io/sway/v0.44.0/book/blockchain-development/native_assets.html) in combination with the SRC-7 standard. - [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. ## Using a standard diff --git a/standards/Forc.toml b/standards/Forc.toml index 81cbc92..93ba3af 100644 --- a/standards/Forc.toml +++ b/standards/Forc.toml @@ -4,6 +4,6 @@ members = [ "src5-ownership", "src6-vault", "src7-metadata", - "src-10-native-bridge", + "src10-native-bridge", "src20-token", ] From cb9ade5bbce2b5dd66d793d05853c0578cb08fc6 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Tue, 9 Jan 2024 13:15:14 +0700 Subject: [PATCH 11/13] Update MessageData token_id from Option to b256 --- standards/src10-native-bridge/README.md | 12 ++++++------ standards/src10-native-bridge/src/src10.sw | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/standards/src10-native-bridge/README.md b/standards/src10-native-bridge/README.md index 141eb66..14c2ffb 100644 --- a/standards/src10-native-bridge/README.md +++ b/standards/src10-native-bridge/README.md @@ -46,10 +46,10 @@ The `process_message()` function accepts incoming deposit messages from the cano The `withdraw()` function accepts and burns a bridged asset and sends a message to the `gateway_contract` contract on the canonical chain to release the originally deposited token 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)` matches the asset's `AssetId` sent in the transaction. +- 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: Option, gateway_contract: b256)` +### - `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. @@ -82,9 +82,9 @@ The `to` field MUST represent the bridging target destination `Address` or `Cont The `token_address` field MUST represent the bridged token's address on the canonical chain. -#### - token_id: `Option` +#### - token_id: `b256` -The `token_id` field MUST represent the token's ID on the canonical chain. MUST be `None` if this is a fungible token and no token ID exists. +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 @@ -95,7 +95,7 @@ struct MessageData { len: u16, to: Identity, token_address: b256, - token_id: Option, + token_id: b256, } ``` @@ -118,6 +118,6 @@ abi SRC10 { fn register_bridge(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: Option, gateway_contract: b256); + fn claim_refund(to_address: b256, token_address: b256, token_id: b256, gateway_contract: b256); } ``` \ No newline at end of file diff --git a/standards/src10-native-bridge/src/src10.sw b/standards/src10-native-bridge/src/src10.sw index 2534e6e..71f3a76 100644 --- a/standards/src10-native-bridge/src/src10.sw +++ b/standards/src10-native-bridge/src/src10.sw @@ -13,7 +13,7 @@ struct MessageData { /// The bridged token's address on the canonical chain. token_address: b256, /// The token's ID on the canonical chain. - token_id: Option, + token_id: b256, } abi SRC10 { @@ -91,7 +91,7 @@ abi SRC10 { /// /// * `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`: [Option] - The token id of 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 @@ -99,7 +99,7 @@ abi SRC10 { /// ```sway /// use src10::SRC10; /// - /// fn foo(to_address: b256, token_address: b256, token_id: Option, gateway_contract: b256, bridge: ContractId) { + /// 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); /// } @@ -108,7 +108,7 @@ abi SRC10 { fn claim_refund( to_address: b256, token_address: b256, - token_id: Option, + token_id: b256, gateway_contract: b256, ); } From 497a18b4b9340e37cbad8da2953154420e558244 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Wed, 10 Jan 2024 09:12:06 +0700 Subject: [PATCH 12/13] Update register_bridge function name to register_token --- standards/src10-native-bridge/README.md | 8 ++++---- standards/src10-native-bridge/src/src10.sw | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/standards/src10-native-bridge/README.md b/standards/src10-native-bridge/README.md index 14c2ffb..cef781a 100644 --- a/standards/src10-native-bridge/README.md +++ b/standards/src10-native-bridge/README.md @@ -25,13 +25,13 @@ The following functions MUST be implemented to follow the SRC-10; Native Bridge ## Required Functions -### - `fn register_bridge(token_address: b256, gateway_contract: b256)` +### - `fn register_token(token_address: b256, gateway_contract: b256)` -The `register_bridge()` function compiles a message to be sent back to the canonical chain. The `gateway_contract` contract on the canonical chain receives the `token_address` token in the message such that when assets are deposited they are reported to prevent loss of funds. +The `register_token()` function compiles a message to be sent back to the canonical chain. The `gateway_contract` contract on the canonical chain receives the `token_address` token on the canonical chain in the message such that when assets are deposited 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`. +- This function MUST send a message on the canonical chain to the `gateway_contract` contract on the canonical chain, registering the specified `token_address` token that exists on the canonical chain. ### - `fn process_message(message_index: u64)` @@ -115,7 +115,7 @@ This standard is compatible with the SRC-20 and SRC-8 standards. ```sway abi SRC10 { - fn register_bridge(token_address: b256, gateway_contract: b256); + 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); diff --git a/standards/src10-native-bridge/src/src10.sw b/standards/src10-native-bridge/src/src10.sw index 71f3a76..ec85f0c 100644 --- a/standards/src10-native-bridge/src/src10.sw +++ b/standards/src10-native-bridge/src/src10.sw @@ -35,11 +35,11 @@ abi SRC10 { /// /// fn foo(gateway_contract: b256, token_address: b256, bridge: ContractId) { /// let bridge_abi = abi(SRC10, bridge.value); - /// bridge_abi.register_bridge(token_address, gateway_contract); + /// bridge_abi.register_token(token_address, gateway_contract); /// } /// ``` #[storage(read, write)] - fn register_bridge(token_address: b256, gateway_contract: b256); + fn register_token(token_address: b256, gateway_contract: b256); /// Accepts incoming deposit messages from the canonical chain and issues the corresponding bridged asset. /// From b16db318bd99d96a186f4a71050b7f12682265ce Mon Sep 17 00:00:00 2001 From: bitzoic Date: Wed, 10 Jan 2024 15:45:07 +0700 Subject: [PATCH 13/13] Wording adjustments --- standards/src10-native-bridge/README.md | 6 +++--- standards/src10-native-bridge/src/src10.sw | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/standards/src10-native-bridge/README.md b/standards/src10-native-bridge/README.md index cef781a..8930a38 100644 --- a/standards/src10-native-bridge/README.md +++ b/standards/src10-native-bridge/README.md @@ -27,11 +27,11 @@ The following functions MUST be implemented to follow the SRC-10; Native Bridge ### - `fn register_token(token_address: b256, gateway_contract: b256)` -The `register_token()` function compiles a message to be sent back to the canonical chain. The `gateway_contract` contract on the canonical chain receives the `token_address` token on the canonical chain in the message such that when assets are deposited they are reported to prevent loss of funds. +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 on the canonical chain, registering the specified `token_address` token that exists on the canonical chain. +- 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)` @@ -43,7 +43,7 @@ The `process_message()` function accepts incoming deposit messages from the cano ### - `fn withdraw(to_address: b256, sub_id: SubId, gateway_contract: b256)` -The `withdraw()` function accepts and burns a bridged asset and sends a message to the `gateway_contract` contract on the canonical chain to release the originally deposited token to the `to_address` address. +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. diff --git a/standards/src10-native-bridge/src/src10.sw b/standards/src10-native-bridge/src/src10.sw index ec85f0c..7eedfa1 100644 --- a/standards/src10-native-bridge/src/src10.sw +++ b/standards/src10-native-bridge/src/src10.sw @@ -21,7 +21,7 @@ abi SRC10 { /// /// # Additional Information /// - /// * The `gateway` contract on the canonical chain receives the `token` ID in the message such that when assets are deposited they are reported to prevent loss of funds. + /// * 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 ///