aex-9
AEX 9
Simple Summary
This document aims to outline a standard and define how fungible tokens should be created and used on aeternity blockchain.
Abstract
The following standard allows for the implementation of a standard API for tokens within smart contracts. This standard provides basic functionality to transfer tokens, as well as allow tokens to be approved so they can be spent by another on-chain third party.
Motivation
This standard will allow decentralized applications and wallets to handle fungible tokens in a standardized way. A standard interface allows any tokens to be re-used by other applications, e.g. from wallets to decentralized exchanges.
The provided specification is following the ERC20 standard introduced in Ethereum for fungible tokens. This standard is proven to be working, it will help with interoperability and easier developer onboarding as the main differences will be Sophia syntax related. Another goal with following the ERC20 standard, is to learn from its mistakes and not repeat them.
The newly proposed standard should be easy to use but extendable with more functionality, both first and third party as shown by splitting allowance, minting, burning and swapping into optional extensions.
Specification
Basic Token
Interface
Methods
aex9_extensions()
This function returns a hardcoded list of all implemented extensions on the deployed contract.
meta_info()
This function returns meta information associated with the token contract.
meta_info
meta_info
total_supply()
This function returns the total token supply.
total_supply
int
balances()
This function returns the full balance state for static calls, e.g. by a blockchain explorer.
balances
map(address, int)
balance()
This function returns the account balance of another account with address owner
, if the account exists. If the owner address is unknown to the contract None
will be returned. Using option
type as a return value allows us to determine if the account has balance of 0, more than 0, or the account has never had balance and is still unknown to the contract.
owner
address
balance
option(int)
transfer()
This function allows transfer of value
amount of tokens to to_account
address and MUST fire the Transfer
event. The function SHOULD abort if the Call.caller's account balance does not have enough tokens to spend.
Note: Transfers of 0 values MUST be treated as normal transfers and fire the Transfer
event.
to_account
address
value
int
Events
Transfer
This event MUST be triggered and emitted when tokens are transferred, including zero value transfers.
The transfer event arguments should be as follows: (from_account, to_account, value)
from_account
address
to_account
address
value
int
Mint (optional if token creation happens) - MUST trigger when tokens are minted and thus are newly available in the given token contract, this also applies to tokens created using the init
method on contract creation.
The mint event arguments should be as follows: (account, value)
account
address
value
int
Extensions
This section covers the extendability of the basic token - e.g. mintable, burnable and allowances.
When a token contract implements an extension its name should be included in the aex9_extensions
array, in order for third party software or contracts to know the interface. Any extensions should be implementable without permission. Developers of extensions MUST choose a name for aex9_extensions
that is not yet used. Developers CAN make a pull request to the reference implementation for general purpose extensions and maintainers choose to eventually include them.
Extension Mintable ("mintable")
mint()
This function mints value
new tokens to account
. The function SHOULD abort if Call.caller
is not the owner of the contract state.owner
.
account
address
value
int
Events
Mint - MUST trigger when tokens are minted and thus are newly available in the given token contract, this also applies to tokens created using the init
method on contract creation.
The mint event arguments should be as follows: (account, value)
account
address
value
int
Extension Burnable ("burnable")
burn()
This function burns value
of tokens from Call.caller
.
value
int
Events
Burn - MUST trigger when tokens are burned and thus are no longer available in the given token contact.
The burn event arguments should be as follows: (account, value)
account
address
value
int
Extension Allowance ("allowances")
create_allowance()
Allows for_account
to withdraw from your account multiple times, up to the value
amount. If this function is called again it overwrites the current allowance with value
.
Note: To prevent attack vectors (like the ones possible in ERC20) clients SHOULD make sure to create user interfaces in such a way that they set the allowance first to 0 before setting it to another value for the same spender. THOUGH the contract itself shouldn't enforce it, to allow backwards compatibility with contracts deployed before.
for_account
address
value
int
transfer_allowance()
Transfers value
amount of tokens from address from_account
to address to_account
, and MUST fire the Transfer
event.
The transfer_allowance
method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf. This can be used for example to allow a contract to transfer tokens on your behalf and/or to charge fees in sub-currencies. The function SHOULD abort unless the from_account
account has deliberately authorized the sender of the message via some mechanism.
Note: Transfers of 0 values MUST be treated as normal transfers and fire the Transfer
event.
from_account
address
to_account
address
value
int
allowance()
This function returns the amount which for_account
is still allowed to withdraw from from_account
, where record allowance_accounts = { from_account: address, for_account: address }
. If no allowance for this combination of accounts exists, None
is returned.
allowance_accounts
allowance_accounts
allowances()
This function returns all allowances stored in state.allowances
record.
allowances
map(allowance_accounts, int)
allowance_for_caller()
This function will look up the allowances and return the allowed spendable amount from from_account
for the transaction sender Call.caller
. If there is no such allowance present result is None
, otherwise Some(int)
is returned with the allowance amount.
from_account
address
option(int)
change_allowance()
This function allows the Call.caller
to change the allowed spendable value for for_account
with value_change
. This adds the value_change
to the current allowance value. If used for increasing allowance amount a positive value should be passed, if the desired outcome is to lower the value of the allowed spendable value a negative value_change
should be passed.
for_account
address
value_change
int
unit
reset_allowance()
Resets the allowance given for_account
to zero.
for_account
address
unit
Events
Allowance - MUST trigger on any successful allowance creation or change.
The approval event arguments should be as follows: (from_account, for_account, value)
from_account
address
for_account
address
value
int
Extension Swappable ("swappable")
swap()
This function burns the whole balance of the Call.caller
and stores the same amount in the swapped
map.
value
int
()
unit
check_swap()
This function returns the amount of tokens that were burned trough swap
for the provided account.
account
address
int
int
swapped()
This function returns all swapped tokens that are stored in contract state.
swapped
map(address, int)
Events
Swap - MUST trigger when tokens are swapped and thus are no longer available in the given token contact.
The swap event arguments should be as follows: (account, value)
account
address
value
int
Implementation
There are several implementations available at the moment, but they lack a thing or two (that is why this standard is being proposed).
Example implementations:
References
Last updated