fuellabs / sway-standards Goto Github PK
View Code? Open in Web Editor NEWSRC Standards set for the Sway language
License: Apache License 2.0
SRC Standards set for the Sway language
License: Apache License 2.0
The following standard allows for the implementation of a standard API for Native Assets using the Sway Language. This standard provides basic functionality as well as on-chain metadata for other applications to use.
A standard interface for Native Assets on Fuel allows external applications to interact with the token, whether that be decentralized exchanges, wallets, or Fuel's Scripts and Predicates.
The SRC-20 Fungible Token Standard naming pays homage to the ERC-20 Token Standard seen on Ethereum. While there is functionality we may use as reference, it is noted that Fuel's Native Assets are fundamentally different than Ethereum's tokens.
There has been a discussion of the Fungile Token Standard on the Fuel Forum. This discussion can be found here.
There has also been a Fungile Token Standard implementation added to the Sway-Libs repository before the creation of the Sway-Standards repository. The introduction of this standard in the Sway-Standards repository will deprecate the Sway-Libs Fungible Token Standard.
The following functions MUST be implemented to follow the SRC-20 standard:
fn name() -> String
Returns the name of the token, such as “Ether”.
fn total_supply() -> u64
Returns the total supply of tokens that have been minted.
fn decimals() -> u8
Returns the number of decimals the token uses - e.g. 8, means to divide the token amount by 100000000 to get its user representation.
fn symbol() -> String
Returns the symbol of the token, such as “ETH”.
As the SRC-20 Fungible Token Standard leverages Native Assets on Fuel, we do not require the implementation of certain functions such as transfer. This is done directly within the FuelVM and there is no smart contract that requires updating of balances. As Fuel is UTXO based, any transfer events may be indexed on transaction receipts.
Following this, we have omitted the inclusion of any transfer functions or events. The provided specification outlines only the required functions and events to implement fully functional tokens on the Fuel Network. Additional functionality and properties may be added as needed.
This standard is compatible with Fuel's Native Assets. There are no other standards that require compatibility.
This standard does not introduce any security concerns, as it does not call external contracts, nor does it define any mutations of the contract state.
abi MyToken {
#[storage(read)]
fn total_supply() -> u64;
#[storage(read)]
fn decimals() -> u8;
#[storage(read)]
fn name() -> String;
#[storage(read)]
fn symbol() -> String;
}
This draft standard is to be released as v0.1
.
The following standard allows for the implementation of a standard API for Non-Fungible Tokens (NFT) using the Sway Language. This standard provides basic functionality as well as on-chain metadata for other applications to use.
A Non-Fungible Token is a unique token that has an identifier that distinguishes itself from other tokens within the same token contract. Unlike Fuel's Native Assets, these tokens are not fungible with one another and may contain metadata or other traits giving them distinctive characteristics.
Some common applications of an NFT include artwork/collectibles, DeFi short positions, deeds, and more.
A standard interface for Non-Fungible Tokens on Fuel allows external applications to interact with each token individually, whether that be decentralized exchanges, wallets, or Fuel's Scripts and Predicates.
It is important to note that the Non-Fungible Token standard does not use Fuel's Native Assets. Instead, a smart contract that implements the SRC-721 standard tracks and transfers the ownership of these tokens.
The SRC-721 Non-Fungible Token Standard naming pays homage to the ERC-721 Non-Fungible Token Standard seen on Ethereum.
There has been a discussion of the Non-Fungile Token Standard on the Fuel Forum. This discussion can be found here.
There has also been a Non-Fungile Token Standard implementation added to the Sway-Libs repository before the creation of the Sway-Standards repository. The introduction of this standard in the Sway-Standards repository will deprecate the Sway-Libs Non-Fungible Token Standard.
The following functions MUST be implemented to follow the SRC-721 standard:
fn transfer(to: Identity, token_id: u64)
Transfer ownership of an NFT from one Identity
to another.
At the time of a transfer, the approved Identity
for that NFT (if any) MUST be reset to Option::None
.
The caller is responsible for confirming that to
is capable of receiving NFTs or else they may be permanently lost.
to
- The Identity
which the ownership of this token SHALL be set to.token_id
- The token identifier of which ownership SHALL change.token_id
is valid NFT.msg_sender()
is not the owner of this token.msg_sender()
is not approved to transfer this token on the owner's behalf.msg_sender()
is not approved to transfer all tokens on the owner's behalf.Transfer
event MUST be emitted when the function is not reverted.fn approve(approved: Option<Identity>, token_id: u64)
Set or reaffirm a single approved Identity
for an NFT. Option::None
denotes no approved entity.
The approved Identity
for the specified NFT MAY transfer the token to a new owner.
approved
- The Identity
that SHALL be approved as an NFT controller, or Option::None
.token_id
- The token identifier of which the NFT approval SHALL change.token_id
is valid NFT.msg_sender()
is the owner of (or an approved Operator for) this NFT.Approval
event MUST be emitted when the function is not reverted.fn set_approval_for_all(approve: bool, operator: Identity)
Enables or disables approval for a third party "Operator" to manage all of msg_sender()
's NFTs.
An operator for an Identity
MAY transfer and MAY set approved Identity
s for all tokens owned by the msg_sender()
.
The contract MUST allow multiple operators per owner.
approve
- MUST be True
if the operator is approved and MUST be False
to revoke approval.operator
- The Identity
that SHALL be added to the set of authorized operators.Operator
event MUST be emitted.fn approved(token_id: u64) -> Option<Identity>
Returns the approved Identity
for a single NFT.
Option::None
indicates there is no approved Identity
.
token_id
- The NFT identifier to find the approved Identity
for.token_id
is valid NFT.fn balance_of(owner: Identity) -> u64
Returns the number of NFTs owned by an Identity
.
owner
- The Identity
of which to query the balance.fn is_approved_for_all(operator: Identity, owner: Identity) -> bool
Query if an Identity
is an authorized operator for another Identity
.
operator
- The Identity
that acts on behalf of the owner.owner
- The Identity
that owns the NFT/NFTs.fn owner_of(token_id: u64) -> Option<Identity>
Returns the owner of an NFT.
Option::None
indicates there is no owner Identity
.
token_id
- The NFT identifier to find the owner for.token_id
is valid NFT.fn name() -> String
Returns the name of the token.
fn symbol() -> String
Return the symbol of the token.
The following functions are not required to create a Non-Fungible Token that is SRC-721 compliant on Fuel, but provide additional functions if they are required. Any contract that implements any SRC-721 Extensions SHALL also implement SRC-721.
fn mint(recipient: Identity, token_id: u64)
Mints a token with token_id
id and transfers it to the recipient
. This function may contain arbitrary conditions for minting, and revert if those conditions are not met.
recipient
- The Identity
which SHALL own the newly created NFT token.token_id
- The unique identifier linked to the newly created NFT token.token_id
does not correspond to an already existing token in the contract.Mint
event MUST be emitted.fn burn(token_id: u64)
Burns the token with token_id
identifier.
When an NFT is burned, the owner SHALL be set to Option::None
.
This function MUST emit the Burn
event.
msg_sender()
is the owner of (or an approved Operator for) this NFT.Burn
event MUST be emitted.fn uri(token_id: u64) -> String
Returns a distinct Uniform Resource Identifier (URI) for a given asset. Often used for off-chain metadata.
URIs are defined in RFC-3986.
token_id
- The NFT identifier for which the URI is returned for.token_id
is valid NFT.fn token_metadata<T>(token_id: u64) -> Option<T>
Returns arbitrary on-chain metadata. Option::None
designates no metadata exists for the corresponding token.
The T
data structure MUST be made public.
The caller is responsible for confirming that they have the appropriate logic for handling T
.
token_id
- The NFT identifier for which the metadata is returned for.token_id
is valid NFT.The following events MUST be emitted to follow the SRC-20 standard:
Approval
This event MUST be logged when the approved Identity
for an NFT is changed or modified.
Option::None
indicates there is no approved Identity
.
approved
- The Identity
that SHALL be approved as an NFT controller, or Option::None
.owner
- The Identity
that owns the token_id
NFT token.token_id
- The token identifier for which approval has changed.struct Approval {
approved: Option<Identity>,
owner: Identity,
token_id: u64,
}
Operator
This event MUST be logged when an operator is enabled or disabled for an owner.
The operator can manage all NFTs of the owner.
approved
- The state of which the operator
has operator status.operator
- The Identity
which has been given or revoked operator status.owner
- The Identity
which has changed the status of the operator.struct Operator {
approved: bool,
operator: Identity,
owner: Identity,
}
Transfer
This event MUST be logged when ownership of any NFT changes between two Identity
s.
Exception: In cases where there is no new or previous owner, formally known as minting and burning, the event SHALL NOT be logged.
from
- The previous owner of the NFT.sender
- The Identity
which has initiated the tranfer.to
- The new owner of the NFT.token_id
- The unique identifer of the token of which ownership has changed.struct Transfer {
from: Identity,
sender: Identity,
to: Identity,
token_id: u64,
}
Mint
This event MUST be emitted when a Non-Fungible Token with a new unique id is created.
recipient
- The owner of the newly minted NFT.token_id
- The unique identifier of the newly minted NFT.struct Mint {
recipient: Identity,
token_id: u64,
}
Burn
This event MUST be emitted when a Non-Fungible Token with a unique id is burned.
sender
- The previous owner of the NFT.token_id
- The unique identifier of the NFT which has been burned.struct Burn {
sender: Identity,
token_id: u64,
}
The presented standard shall enable cross-compatibility between different applications. Any contract that implements the SRC-721 standard shall be able to track, manage, and transfer Non-Fungible Tokens on the Fuel Network.
There are no other standards that require compatibility.
Across the blockchain ecosystem today we see countless exploits using operator approvals. These present a very dangerous opportunity to siphon all NFTs out of a user's wallet. The set_approval_for_all()
functionality should be used with care.
abi MyNonFungibleToken {
#[storage(read, write)]
fn transfer(to: Identity, token_id: u64);
#[storage(read, write)]
fn approve(approved: Option<Identity>, token_id: u64);
#[storage(read, write)]
fn set_approval_for_all(approve: bool, operator: Identity);
#[storage(read)]
fn approved(token_id: u64) -> Option<Identity>;
#[storage(read)]
fn balance_of(owner: Identity) -> u64;
#[storage(read)]
fn is_approved_for_all(operator: Identity, owner: Identity) -> bool;
#[storage(read)]
fn owner_of(token_id: u64) -> Option<Identity>;
#[storage(read)]
fn name() -> String;
#[storage(read)]
fn symbol() -> String;
}
abi MyNonFungibleTokenExtensions {
#[storage(read, write)]
fn mint(recipient: Identity, token_id: u64);
#[storage(read, write)]
fn burn(token_id: u64);
#[storage(read)]
fn uri(token_id: u64) -> String;
#[storage(read)]
fn token_metadata(token_id: u64) -> Option<MyMetadataStruct>`
}
This draft standard is to be released as v0.1
.
The following standard intends to define the structure and organization of inline documentation for functions within the Sway Language. This will be a living standard.
The standard seeks to provide a better developer experience using Fuel's tooling.
A number of pre-existing functions in the sway standard library, sway-applications, and sway-libs repositories have inline documentation. The inline documentation for these is already compatible with Fuel's VS Code extension. These however do not all follow the same structure and outline.
The following describes the structure and order of inline documentation for functions. Some sections may not apply to each function. When a section is not relevant shall be omitted.
This section has no header.
A simple explanation of the function's intent or functionality.
Example:
/// This function computes the hash of two numbers.
This section has a h3
header.
This section is directly below the description and can provide additional information beyond the function's intent or functionality.
Example:
/// ### Additional Information
///
/// This function also has some complex behaviors.
This section has a h3
header.
Lists the arguments of the function's definition with the *
symbol and describes each one. The list shall provide the name, type, and description.
Example:
/// ### Arguments
///
/// * `argument_1`: `Identity` - This argument is a user to be hashed.
This section has a h3
header.
Lists the cases in which the function will revert starting with the *
symbol.
Example:
/// # Reverts
///
/// * When `argument_1` or `argument_2` are a zero `b256`.
This section has a h3
header.
Provides information on how many storage reads, writes, and clears occur within the function.
Example:
/// ### Number of Storage Accesses
///
/// * Reads: `1`
/// * Clears: `2`
This section has a h3
header.
This section provides an example of the use of the function. This section is not required to follow the SRC-2 standard however encouraged for auxiliary and library functions.
Example:
/// ### Examples
///
/// ```sway
/// fn foo(argument_1: b256, argument_2: b256) {
/// let result = my_function(argument_1, argument_2);
/// }
The following describes the structure and order of inline documentation for enums. Some sections may not apply to each enum. When a section is not relevant shall be omitted.
This section has no header.
A simple explanation of the enum's purpose or functionality.
Example:
/// This struct contains information on an NFT.
This section has a h3
header.
This section is directly below the description and can provide additional information beyond the struct's purpose or functionality.
Example:
/// ### Additional Information
///
/// This struct also has some complex behaviors.
This section has a h3
header.
Lists the fields of the struct with the *
symbol and describes each one. The list shall provide the name, type, and description.
Example:
/// ### Fields
///
/// * `field_1`: `Identity` - This field represents an owner.
The following describes the structure and order of inline documentation for enums. Some sections may not apply to each enum. When a section is not relevant shall be omitted.
This section has no header.
A simple explanation of the enum's purpose or functionality.
Example:
/// This enum holds the state of a contract.
This section has a h3
header.
This section is directly below the description and can provide additional information beyond the enum's purpose or functionality.
Example:
/// ### Additional Information
///
/// This enum also has some complex behaviors.
This section has a h3
header.
Lists the variants of the enum with the *
symbol and describes each one. The list shall provide the name, type, and description.
Example:
/// ### Variants
///
/// * `variant_1`: () - This variant represents the uninitialized state of a contract.
/// * `variant_2`: Identity - This variant represents the initialized state of a contract.
The SRC-2 standard should help provide developers with an easy way to both quickly write inline documentation and get up to speed on other developers' code. This standard in combination with Fuel's VS Code extension provides for readily accessible information on functions, structs, and enums
There are no standards that the SRC-2 standard requires to be backward compatible with.
This standard will improve security by providing developers with relevant information such as revert cases.
/// Ensures that the sender is the owner.
///
/// ### Reverts
///
/// * When the sender is not the owner.
///
/// ### Number of Storage Accesses
///
/// * Reads: `1`
///
/// ### Examples
///
/// ```sway
/// use ownable::Ownership;
///
/// storage {
/// owner: Ownership = Ownership::initalized(Identity::Address(Address::from(ZERO_B256))),
/// }
///
/// fn foo() {
/// storage.owner.only_owner();
/// // Do stuff here
/// }
#[storage(read)]
pub fn only_owner(self) {
require(self.owner() == State::Initialized(msg_sender().unwrap()), AccessError::NotOwner);
}
/// Metadata that is tied to a token.
///
/// ### Fields
///
/// * `value`: `u64` - Represents the token ID of this NFT.
pub struct NFTMetadata {
value: u64,
}
/// Determines the state of ownership.
///
/// ### Variants
///
/// * `Uninitialized`: () - The ownership has not been set.
/// * `Initialized`: `Identity` - The user which has been given ownership.
/// * `Revoked`: () - The ownership has been given up and can never be set again.
pub enum State {
Uninitialized: (),
Initialized: Identity,
Revoked: (),
}
The following are required:
This is a brand new repository.
The following standard enables the minting and burning of tokens for any fungible assets within the Sway Language. It seeks to define mint and burn functions defined separately from the SRC-20 standard. Any contract that implements the SRC-3 standard MUST implement the SRC-20 standard.
The intent of this standard is to separate the extensions of minting and burning from the SRC-20 standard.
Minting and burning were initially added to the SRC-20 standard.
The following functions MUST be implemented to follow the SRC-3 standard:
fn mint(recipient: Identity, amount: u64)
This function MUST mint amount
tokens and transfer them to the recipient
. This function MAY contain arbitrary conditions for minting, and revert if those conditions are not met.
recipient
- The Identity
to which the newly minted tokens are transferred to.amount
- The quantity of tokens to mint.This function MUST emit the Mint
event.
fn burn()
This function MUST burn all tokens sent to the contract in this function invocation.
This function MUST emit the Burn
event.
The following events MUST be emitted to follow the SRC-3 standard:
Mint
This event MUST be emitted when the std::token::mint
function is called either directly or indirectly.
recipient
- The Identity
to which the newly minted tokens are transferred to.amount
- The quantity of tokens minted.struct Mint {
recipient: Identity,
amount: u64,
}
Burn
This event MUST be emitted then the std::token::burn
function is called either directly or indirectly.
sender
- The Identity
which sent the tokens to the contract to burn.amount
- The quantity of tokens burned.struct Burn {
sender: Identity,
amount: u64,
}
This standard has been added to enable compatibility between applications and allow minting and burning tokens per use case. This standard has been separated from the SRC-20 standard to allow for the minting and burning for all fungible tokens, irrelevant of whether they are Native Assets or not.
This standard is compatible with Fuel's Native Assets as well as the SRC-20 standard.
This standard may introduce security considerations if the mint function does not include any checks to ensure the calling of the mint()
function is deemed valid or permitted. Checks are highly encouraged.
The burn function may also introduce a security consideration if the total supply within the SRC-20 standard is not modified.
abi MyTokenSRC3 {
fn mint(recipient: Identity, amount: u64);
fn burn();
}
This draft standard is to be released as v0.1
.
The following standard intends to enable the use of administrators or owners in Sway contracts.
The standard seeks to provide a method for restricting access to particular users within a Sway contract.
The sway-libs repository contains a pre-existing Ownership library.
Ownership libraries exist for other ecosystems such as OpenZeppelin's Ownership library.
There shall be 3 states for any library implementing an ownership module, these are:
Uninitialized
The Uninitialized
state SHALL be set as the initial state if no owner or admin is set. The Uninitialized
state may be used when an owner or admin MAY be set in the future.
Initialized
The Initialized
state SHALL be set as the state if an owner or admin is set.
Revoked
The Revoked
state SHALL be set when there is no owner or admin and there SHALL not be one set in the future.
The following functions MUST be implemented to follow the SRC-5 standard:
fn only_owner()
This function SHALL be used as a check to ensure the current function caller is an owner or admin.
This function MUST revert if the caller is not defined as an owner or admin.
fn owner() -> State
This function SHALL return the current state of ownership for the contract where State
is either Uninitialized
, Initialized
, or Revkoed
.
In order to provide a universal method of administrative capabilities, SRC-5 will further enable interoperability between applications and provide safeguards for smart contract security.
The SRC-5 standard is compatible with the sway-libs](https://github.com/FuelLabs/sway-libs) repository pre-existing Ownership library. Considerations should be made to best handle multiple owners or admins.
There are no standards that SRC-5 requires to be compatible with.
The SRC-5 standard should help improve the security of Sway contracts and their interoperability.
pub enum State {
Uninitialized: (),
Initialized: Identity,
Revoked: (),
}
pub struct Ownership {
owner: State,
}
impl StorageKey<Ownership> {
#[storage(read)]
pub fn owner(self) -> State {
self.read().owner
}
}
impl StorageKey<Ownership> {
pub fn only_owner(self) {
require(self.owner() == State::Initialized(msg_sender().unwrap()), AccessError::NotOwner);
}
}
The following standard allows for the implementation of a standard API for flash mints for native-assets using the Sway language. This standard is an optional add-on to the SRC-20 standard.
Flash mints allow anyone to temporarily mint out a large number of tokens and use them for any purpose with the requirement that they be returned within the same transaction. This pattern is highly useful and would greatly benefit from standardisation
Flash mints have been thoroughly explored on Ethereum and with EIP 3156 they have their own standard for it. However as Fuel's native assets are fundamentally different to Ethereum's ERC-20 tokens, the implementation will differ, but the interface may be used as reference.
The following functions MUST be implemented (on top of the SRC-20 functions) to follow the SRC-4 standard
fn flash_mint(amount: u64, target: ContractId, function_selector: Vec<u8>, calldata: Vec<u8>, single_value_type_arg: bool, gas_required: u64)
Calls the target
ContractId with the specified function_selector
, call_data
, and single_value_type_arg
, with CallParams
of amount
coins and gas_required
gas forwarded.
fn flash_fee(amount: u64)
Read only function that returns the fee that would be charged for a flashloan of the given amount
The parameters of the function may change depending on the implementation of native multi tokens on Fuel.
The following logs MUST be emitted at the specified occasions
enum FlashLoanError {
// The loan was not repaid. The missing amount is logged
LoanNotRepaid: u64,
}
The LoanNotRepaid
variant of this enum must be logged in the event that the entire expected amount is not repaid to the contract. The amount remaining to be paid must be the value associated.
The ABI discussed is simple and covers the known use cases of flash mints while allowing safe implementations
This standard is fully compatible with the SRC-20 standard
Incorrect implementation of flashmints could allow attackers to gain very large number of tokens. It is recommended to properly audit any code using this standard to ensure exploits are not possible.
Full reference implementation can be seen here
This is a draft standard
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.