Skip to content

Latest commit

 

History

History
222 lines (176 loc) · 7.49 KB

sep-0041.md

File metadata and controls

222 lines (176 loc) · 7.49 KB

Preamble

SEP: 0041
Title: Soroban Token Interface
Authors: Jonathan Jove <@jonjove>, Siddharth Suresh <@sisuresh>
Track: Standard
Status: Draft
Created: 2023-09-22
Updated: 2023-10-18
Version 0.2.0
Discussion: https://discord.com/channels/897514728459468821/1159937045322547250

Simple Summary

This proposal defines a standard contract interface for tokens. The interface is a subset of the Stellar Asset contract, and compatible with its descriptive and token interfaces defined in CAP-46-6.

Motivation

A fungible asset is a fundamental concept on blockchains. Fungible assets can conceptually be divided into two pieces: standard functionality enabling push and pull transfers, and varying functionality around asset administration. Most blockchain ecosystems have very little innovation in the space of fungible assets, with developers often relying on open source implementations such as OpenZeppelin.

CAP-46-6 defines a Stellar Asset contract that implements a combination of that standard functionality, as well as functions to support behaviors that are specialized to Stellar assets.

Tokens could implement the interface that the Stellar Asset contract defines, but it contains functions that support behaviors that are specialized to Stellar assets.

An interface is needed that is less opinionated than the interface of the Stellar Asset contract. Tokens that implement this interface would support at least the standard functionality of tokens, without needing to support the specialized behaviors of Stellar Assets.

An interface is needed that is a subset of the Stellar Asset contract, such that the Stellar Asset contract would implement the interface. Tokens that implement the interface and the Stellar Asset contract would be usable with contracts that support the standard interface, and would be largely indistinguishable.

Specification

Interface

pub trait TokenInterface {
    /// Returns the allowance for `spender` to transfer from `from`.
    ///
    /// # Arguments
    ///
    /// - `from` - The address holding the balance of tokens to be drawn from.
    /// - `spender` - The address spending the tokens held by `from`.
    fn allowance(env: Env, from: Address, spender: Address) -> i128;

    /// Set the allowance by `amount` for `spender` to transfer/burn from
    /// `from`.
    ///
    /// # Arguments
    ///
    /// - `from` - The address holding the balance of tokens to be drawn from.
    /// - `spender` - The address being authorized to spend the tokens held by
    /// `from`.
    /// - `amount` - The tokens to be made available to `spender`.
    /// - `live_until_ledger` - The ledger number where this allowance expires.
    /// Cannot be less than the current ledger number unless the amount is being
    /// set to 0.  An expired entry (where live_until_ledger < the current
    /// ledger number) should be treated as a 0 amount allowance.
    ///
    /// # Events
    ///
    /// Emits an event with topics `["approve", from: Address,
    /// spender: Address], data = [amount: i128, live_until_ledger: u32]`
    ///
    /// Emits an event with:
    /// - topics - `["approve", from: Address, spender: Address]`
    /// - data - `[amount: i128, live_until_ledger: u32]`
    fn approve(env: Env, from: Address, spender: Address, amount: i128, live_until_ledger: u32);

    /// Returns the balance of `id`.
    ///
    /// # Arguments
    ///
    /// - `id` - The address for which a balance is being queried. If the
    /// address has no existing balance, returns 0.
    fn balance(env: Env, id: Address) -> i128;

    /// Transfer `amount` from `from` to `to`.
    ///
    /// # Arguments
    ///
    /// - `from` - The address holding the balance of tokens which will be
    /// withdrawn from.
    /// - `to` - The address which will receive the transferred tokens.
    /// - `amount` - The amount of tokens to be transferred.
    ///
    /// # Events
    ///
    /// Emits an event with:
    /// - topics - `["transfer", from: Address, to: Address]`
    /// - data - `[amount: i128]`
    fn transfer(env: Env, from: Address, to: Address, amount: i128);

    /// Transfer `amount` from `from` to `to`, consuming the allowance of
    /// `spender`. Authorized by spender (`spender.require_auth()`).
    ///
    /// # Arguments
    ///
    /// - `spender` - The address authorizing the transfer, and having its
    /// allowance consumed during the transfer.
    /// - `from` - The address holding the balance of tokens which will be
    /// withdrawn from.
    /// - `to` - The address which will receive the transferred tokens.
    /// - `amount` - The amount of tokens to be transferred.
    ///
    /// # Events
    ///
    /// Emits an event with:
    /// - topics - `["transfer", from: Address, to: Address]`
    /// - data - `[amount: i128]`
    fn transfer_from(env: Env, spender: Address, from: Address, to: Address, amount: i128);

    /// Burn `amount` from `from`.
    ///
    /// # Arguments
    ///
    /// - `from` - The address holding the balance of tokens which will be
    /// burned from.
    /// - `amount` - The amount of tokens to be burned.
    ///
    /// # Events
    ///
    /// Emits an event with:
    /// - topics - `["burn", from: Address]`
    /// - data - `[amount: i128]`
    fn burn(env: Env, from: Address, amount: i128);

    /// Burn `amount` from `from`, consuming the allowance of `spender`.
    ///
    /// # Arguments
    ///
    /// - `spender` - The address authorizing the burn, and having its allowance
    /// consumed during the burn.
    /// - `from` - The address holding the balance of tokens which will be
    /// burned from.
    /// - `amount` - The amount of tokens to be burned.
    ///
    /// # Events
    ///
    /// Emits an event with:
    /// - topics - `["burn", from: Address]`
    /// - data - `[amount: i128]`
    fn burn_from(env: Env, spender: Address, from: Address, amount: i128);

    /// Returns the number of decimals used to represent amounts of this token.
    fn decimals(env: Env) -> u32;

    /// Returns the name for this token.
    fn name(env: Env) -> String;

    /// Returns the symbol for this token.
    fn symbol(env: Env) -> String;
}

Events

Approve Event

The approve event is emitted when the allowance is set.

The event has topics:

  • Symbol with value "approve"
  • Address the address holding the balance of tokens to be drawn from.
  • Address the address spending the tokens held by from.

The event has data:

  • i128 the amount allowed to be spent.
  • u32 the expiration ledger.

Transfer Event

The transfer event is emitted when an amount is transferred from one address to another.

The event has topics:

  • Symbol with value "transfer"
  • Address the address holding the balance of tokens that was drawn from.
  • Address the address that received the tokens.

The event has data:

  • i128 the amount transferred.

Burn Event

The burn event is emitted when an amount is burned from one address.

The event has topics:

  • Symbol with value "burn"
  • Address the address holding the balance of tokens that was burned.

The event has data:

  • i128 the amount burned.

Changelog

  • v0.1.0 - Initial draft based on CAP-46-6.
  • v0.2.0 - Remove spendable_balance.

Implementations

  • The Rust soroban-sdk contains a copy of the interface verbatim, and a generated client for use in contracts.
  • The Soroban Env contains a native implementation of the interface that is a presentation layer on top of Stellar Assets.