Code Monkey home page Code Monkey logo

sway-standards's People

Contributors

bitzoic avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sway-standards's Issues

SRC-20; Fungible Token Standard

Abstract

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.

Motivation

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.

Prior Art

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.

Specification

Required Public Functions

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”.

Rationale

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.

Backwards Compatibility

This standard is compatible with Fuel's Native Assets. There are no other standards that require compatibility.

Security Considerations

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.

Example ABI

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.

SRC-721; Non-Fungible Token Standard

Abstract

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.

Motivation

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.

Prior Art

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.

Specification

Required Public Functions

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.

Arguments
  • to - The Identity which the ownership of this token SHALL be set to.
  • token_id - The token identifier of which ownership SHALL change.
Reverts
  • It is REQUIRED that token_id is valid NFT.
  • It is REQUIRED that msg_sender() is not the owner of this token.
  • It is REQUIRED that msg_sender() is not approved to transfer this token on the owner's behalf.
  • It is REQUIRED that msg_sender() is not approved to transfer all tokens on the owner's behalf.
Events
  • The 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.

Arguments
  • 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.
Reverts
  • It is REQUIRED that token_id is valid NFT.
  • It is REQUIRED that msg_sender() is the owner of (or an approved Operator for) this NFT.
Events
  • The 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 Identitys for all tokens owned by the msg_sender().
The contract MUST allow multiple operators per owner.

Arguments
  • 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.
Events
  • The 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.

Arguments
  • token_id - The NFT identifier to find the approved Identity for.
Reverts
  • It is REQUIRED that token_id is valid NFT.

fn balance_of(owner: Identity) -> u64

Returns the number of NFTs owned by an Identity.

Arguments
  • 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.

Arguments
  • 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.

Arguments
  • token_id - The NFT identifier to find the owner for.
Reverts
  • It is REQUIRED that token_id is valid NFT.

fn name() -> String

Returns the name of the token.

fn symbol() -> String

Return the symbol of the token.

Extensions

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.

Arguments
  • recipient - The Identity which SHALL own the newly created NFT token.
  • token_id - The unique identifier linked to the newly created NFT token.
Reverts
  • It is REQUIRED that token_id does not correspond to an already existing token in the contract.
Events
  • The 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.

Reverts
  • It is REQUIRED that msg_sender() is the owner of (or an approved Operator for) this NFT.
Events
  • The 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.

Arguments
  • token_id - The NFT identifier for which the URI is returned for.
Reverts
  • It is REQUIRED that 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.

Arguments
  • token_id - The NFT identifier for which the metadata is returned for.
Reverts
  • It is REQUIRED that token_id is valid NFT.

Events

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.

Arguments
  • 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.

Arguments
  • 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 Identitys.
Exception: In cases where there is no new or previous owner, formally known as minting and burning, the event SHALL NOT be logged.

Arguments
  • 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.

Arguments
  • 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.

Argument
  • 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,
}

Rationale

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.

Backwards Compatibility

There are no other standards that require compatibility.

Security Considerations

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.

Example ABI

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.

SRC-2; Inline Documentation Standard

Motivation

Abstract

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.

Motivation

The standard seeks to provide a better developer experience using Fuel's tooling.

Prior Art

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.

Specification

Functions

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.

- Description

This section has no header.
A simple explanation of the function's intent or functionality.
Example:

/// This function computes the hash of two numbers.

- Additional Information

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.

- Arguments

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.

- Reverts

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`.

- Number of Storage Accesses

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`

- Examples

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);
/// }

Structs

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.

- Description

This section has no header.
A simple explanation of the enum's purpose or functionality.
Example:

/// This struct contains information on an NFT.

- Additional Information

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.

- Fields

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.

Enums

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.

- Description

This section has no header.
A simple explanation of the enum's purpose or functionality.
Example:

/// This enum holds the state of a contract.

- Additional Information

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.

- Variant

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.

Rationale

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

Screenshot 2023-05-10 125656

Backwards Compatability

There are no standards that the SRC-2 standard requires to be backward compatible with.

Secutiry Considerations

This standard will improve security by providing developers with relevant information such as revert cases.

Examples

/// 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: (),
}

Basic Repository Structure

Description

The following are required:

  • README
  • CODEOWNERS
  • gitignore
  • standards folder
  • issues template
  • etc

Motivation

This is a brand new repository.

SRC-3; Mint and Burn Standard

Motivation

Abstract

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.

Motivation

The intent of this standard is to separate the extensions of minting and burning from the SRC-20 standard.

Prior Art

Minting and burning were initially added to the SRC-20 standard.

Specification

Required Public Functions

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.

Arguments
  • recipient - The Identity to which the newly minted tokens are transferred to.
  • amount - The quantity of tokens to mint.
Events

This function MUST emit the Mint event.

fn burn()

This function MUST burn all tokens sent to the contract in this function invocation.

Events

This function MUST emit the Burn event.

Events

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.

Arguments
  • 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.

Argument
  • sender - The Identity which sent the tokens to the contract to burn.
  • amount - The quantity of tokens burned.
struct Burn {
     sender: Identity,
     amount: u64,
}

Rationale

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.

Backwards Compatibility

This standard is compatible with Fuel's Native Assets as well as the SRC-20 standard.

Security Considerations

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.

Example ABI

abi MyTokenSRC3 {
    fn mint(recipient: Identity, amount: u64);
    fn burn();
}

This draft standard is to be released as v0.1.

SRC-5; Ownership Standard

Motivation

Abstract

The following standard intends to enable the use of administrators or owners in Sway contracts.

Motivation

The standard seeks to provide a method for restricting access to particular users within a Sway contract.

Prior Art

The sway-libs repository contains a pre-existing Ownership library.

Ownership libraries exist for other ecosystems such as OpenZeppelin's Ownership library.

Specification

State

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.

Functions

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.

Rationale

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.

Backwards Compatability

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.

Security Considerations

The SRC-5 standard should help improve the security of Sway contracts and their interoperability.

Examples

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);
    }
}

SRC-4; Flash Mint Standard

Motivation

Abstract

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.

Motivation

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

Prior Art

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.

Specification

Required public functions

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.

Required logs

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.

Rationale

The ABI discussed is simple and covers the known use cases of flash mints while allowing safe implementations

Backwards compatibility

This standard is fully compatible with the SRC-20 standard

Security Considerations

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.

Reference implementation

Full reference implementation can be seen here

This is a draft standard

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.