From 89c6be3afb25168d31f4f1b513307b0c0232a7d7 Mon Sep 17 00:00:00 2001 From: Erik Stenman Date: Wed, 18 Sep 2019 16:37:36 +0200 Subject: [PATCH 01/14] Some serializations. --- serializations.md | 10 +++++++ tokens/tokens.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 tokens/tokens.md diff --git a/serializations.md b/serializations.md index dec37773..284051ed 100644 --- a/serializations.md +++ b/serializations.md @@ -141,6 +141,7 @@ ambiguity. | 4 | oracle | | 5 | contract | | 6 | channel | +| 7 | token | In Erlang notation, the `id()` type pattern is: ``` @@ -252,6 +253,7 @@ subsequent sections divided by object. | Sophia byte code | 70 | | Generalized accounts attach transaction | 80 | | Generalized accounts meta transaction | 81 | +| Tokens | 90 | | Key block | 100 | | Micro block | 101 | | Light micro block | 102 | @@ -282,6 +284,14 @@ subsequent sections divided by object. ] ``` +#### Accounts (version 4, Normal accounts with flags and tokens, from XXX release) +``` +[ :: int() +, :: int() +, :: int() +, :: [{id(),int()}] +``` + ### Signed transaction ``` [ :: [binary()] diff --git a/tokens/tokens.md b/tokens/tokens.md new file mode 100644 index 00000000..8e6f4d5b --- /dev/null +++ b/tokens/tokens.md @@ -0,0 +1,67 @@ +# Native Tokens + +A native tokens is made up of two parts: a Native token type and a native token balance. + +Native tokens types are a first class object on the chain that defines the +behaviour of a type of tokens. Native tokens live in their own account balances +of accounts. + +Native tokens (from now on just tokens) are: +- Transferable (`spend`, `trade`) +- Countable +- Mintable (`mint`) +- Destroyable (`burn`) + +Token types are: +- Creatable + + +## Token transactions + +There is one transaction on token types: +- create + +There are five token transactions: +- mint +- spend +- trade +- burn +- finalize + +Other transactions that takes a balance can also take a native token balance. + +### token create transaction + +The token create transaction takes the following argument +- Meta data : string +and the followin optional arguments +- Contract +- Amount +- Recipient +- Parent +- Final + +The `meta data` is an uniterpreted string but token minters are encouraged to +use the following json object: +{ + "type" : "object", + "properties": { + "name": {"type" : "string"}, + } +} + +The `contract` has to provide the following ACI: + spend(recipient : address, payload : Type) : booleano + trade([(from : address, to: address, Optional(token : address))], payload : Type) + mint(amount: integer) + burn(amount : integer) : boolean + +The `amount` is the number of tokens to create. + +The `recipient` an account to dump the tokens created, if not given the tokens are +spent to the creators account. + +The `parent` is a pointer to a parent token for hierarchical tokens. + +The `final` argument sets the final flag which would block future minting. + From f0e5be63216e6a6d83201a8137012c78a8133d7f Mon Sep 17 00:00:00 2001 From: Erik Stenman Date: Wed, 18 Sep 2019 16:46:01 +0200 Subject: [PATCH 02/14] Describe use of token contract. --- serializations.md | 22 ++++++++++++++++++++++ tokens/tokens.md | 7 ++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/serializations.md b/serializations.md index 284051ed..15a09e31 100644 --- a/serializations.md +++ b/serializations.md @@ -319,6 +319,28 @@ The recipient must be one of the following: * A contract identifier. * A name identifier, whose related name entry has an identifier as value of pointer with key `account_pubkey`. If multiple pointer entries are present for such key, then the first of such entries is used. +` + +### Spend token transaction +``` +[ :: id() +, :: id() +, :: id() +, :: int() +, :: int() +, :: int() +, :: int() +, :: binary() +] +``` + +The recipient must be one of the following: +* An account identifier. +* An oracle identifier. +* A contract identifier. +* A name identifier, whose related name entry has an identifier as value of pointer with key `account_pubkey`. + If multiple pointer entries are present for such key, then the first of such entries is used. +` #### Oracles ``` diff --git a/tokens/tokens.md b/tokens/tokens.md index 8e6f4d5b..81d08431 100644 --- a/tokens/tokens.md +++ b/tokens/tokens.md @@ -51,7 +51,7 @@ use the following json object: } The `contract` has to provide the following ACI: - spend(recipient : address, payload : Type) : booleano + spend(recipient : address, payload : Type) : boolean trade([(from : address, to: address, Optional(token : address))], payload : Type) mint(amount: integer) burn(amount : integer) : boolean @@ -65,3 +65,8 @@ The `parent` is a pointer to a parent token for hierarchical tokens. The `final` argument sets the final flag which would block future minting. +If a contract is provided then any transaction (spend, trade, mint, burn) would +call this contract and the transaction only goes through if the result of the +corresponfing contract call returns true. Any other transaction using +the token (such as contract call) would only be ececuted if a call to spend +returns true. From 69fdff075a1fbefa4c30703cda6546f117482b35 Mon Sep 17 00:00:00 2001 From: Erik Stenman Date: Wed, 18 Sep 2019 17:02:37 +0200 Subject: [PATCH 03/14] Apply suggestions from code review Co-Authored-By: Hans Svensson --- tokens/tokens.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tokens/tokens.md b/tokens/tokens.md index 81d08431..d059bba1 100644 --- a/tokens/tokens.md +++ b/tokens/tokens.md @@ -34,14 +34,14 @@ Other transactions that takes a balance can also take a native token balance. The token create transaction takes the following argument - Meta data : string -and the followin optional arguments +and the following optional arguments - Contract - Amount - Recipient - Parent - Final -The `meta data` is an uniterpreted string but token minters are encouraged to +The `meta data` is an uninterpreted string but token minters are encouraged to use the following json object: { "type" : "object", From 6d2b9e62dc9d46e1822c5e7c3ab95322aa73d137 Mon Sep 17 00:00:00 2001 From: Erik Stenman Date: Wed, 18 Sep 2019 17:12:45 +0200 Subject: [PATCH 04/14] Token create transaction --- serializations.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/serializations.md b/serializations.md index 15a09e31..64131c3c 100644 --- a/serializations.md +++ b/serializations.md @@ -253,7 +253,7 @@ subsequent sections divided by object. | Sophia byte code | 70 | | Generalized accounts attach transaction | 80 | | Generalized accounts meta transaction | 81 | -| Tokens | 90 | +| Token | 90 | | Key block | 100 | | Micro block | 101 | | Light micro block | 102 | @@ -1045,3 +1045,21 @@ NOTE: , :: binary() ] ``` + + +#### Token create transaction +``` +[ :: id() +, :: binary() +, :: id() +, :: int() +, :: id() +, :: id() +, :: bool() +, :: int() +, :: int() +, :: [id()] +, :: binary() +, :: int() +] +``` From 8d53bb4ad4b04b1e6b3b5517429e7ebbc4785e3e Mon Sep 17 00:00:00 2001 From: Erik Stenman Date: Wed, 18 Sep 2019 17:25:01 +0200 Subject: [PATCH 05/14] Transaction serializations. --- serializations.md | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/serializations.md b/serializations.md index 64131c3c..12049456 100644 --- a/serializations.md +++ b/serializations.md @@ -254,6 +254,11 @@ subsequent sections divided by object. | Generalized accounts attach transaction | 80 | | Generalized accounts meta transaction | 81 | | Token | 90 | +| Token create transaction | 91 | +| Token mint transaction | 92 | +| Token trade transaction | 93 | +| Token burn transaction | 94 | +| Token finalize transaction | 95 | | Key block | 100 | | Micro block | 101 | | Light micro block | 102 | @@ -321,7 +326,7 @@ The recipient must be one of the following: If multiple pointer entries are present for such key, then the first of such entries is used. ` -### Spend token transaction +### Spend token transaction From the XXX release ``` [ :: id() , :: id() @@ -1058,8 +1063,43 @@ NOTE: , :: bool() , :: int() , :: int() -, :: [id()] -, :: binary() +, :: int() +] +``` + +#### Token mint transaction +``` +[ :: int() +, :: id() +, :: bool() +, :: int() +, :: int() +, :: int() +] +``` + +#### Token trade transaction +``` +[ :: [{id(), id(), int(), id()}] +, :: int() +, :: int() +, :: int() +] +``` + +#### Token burn transaction +``` +[ :: int() +, :: int() +, :: int() +, :: int() +] +``` + +#### Token finalize transaction +``` +[ :: int() +, :: int() , :: int() ] ``` From f802cf83bacc73430531bce79cd043dbcec86c4f Mon Sep 17 00:00:00 2001 From: Erik Stenman Date: Wed, 18 Sep 2019 17:45:36 +0200 Subject: [PATCH 06/14] Tokens state tree. --- tokens/tokens.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tokens/tokens.md b/tokens/tokens.md index d059bba1..fe609c61 100644 --- a/tokens/tokens.md +++ b/tokens/tokens.md @@ -70,3 +70,30 @@ call this contract and the transaction only goes through if the result of the corresponfing contract call returns true. Any other transaction using the token (such as contract call) would only be ececuted if a call to spend returns true. + +## Tokens state tree + +The tokens state tree contain token type objects. +Tokens are stored in the account state tree as a list of tuples of +token id:s and balances. + +### Token state tree objects + +- The token state tree contains + - Token type objects + +#### The token type object + +- Created by an token create transaction. + +``` +{ creator :: id() +, :: binary() +, :: id() +, :: int() +, :: id() +, :: bool() + +} +``` + From 29964c54813bb991186417ac374eefd9c0f02a73 Mon Sep 17 00:00:00 2001 From: Tobias Lindahl Date: Thu, 26 Sep 2019 14:46:32 +0200 Subject: [PATCH 07/14] Hook in native tokens on top level --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ef7980e2..18d8f552 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ implemented or considered for implementation. ## [Serialization formats](./serializations.md) +## [Native tokens](./tokens/tokens.md) + ## Aeternity node The Aeternity node is the reference implementation of the Aeternity protocol. Since we don't From 04d7d6ca39106184fa046a5da4b0e9726e4f5773 Mon Sep 17 00:00:00 2001 From: Tobias Lindahl Date: Thu, 26 Sep 2019 14:46:57 +0200 Subject: [PATCH 08/14] Rewrite overview --- tokens/tokens.md | 109 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 32 deletions(-) diff --git a/tokens/tokens.md b/tokens/tokens.md index fe609c61..b9c403ba 100644 --- a/tokens/tokens.md +++ b/tokens/tokens.md @@ -1,60 +1,105 @@ -# Native Tokens +# Aeternity Native Tokens -A native tokens is made up of two parts: a Native token type and a native token balance. +## Overview -Native tokens types are a first class object on the chain that defines the -behaviour of a type of tokens. Native tokens live in their own account balances -of accounts. +We need to distinguish between a specification of a token, and a +countable amount of the token. In this document we use **ANT** +(Aeternity Native Token) to represent the specification, and **native +token** or simply **token** to represent the countable asset. -Native tokens (from now on just tokens) are: -- Transferable (`spend`, `trade`) -- Countable -- Mintable (`mint`) -- Destroyable (`burn`) +Informally, when you need a new type of token for whatever purpose, +you create an ANT describing the token, and then you can mint new +tokens and start sending them to accounts. -Token types are: -- Creatable +Owners of the tokens can spend them to other accounts, or trade them +(atomically) for other assets with other accounts. If tokens are no +longer wanted you can burn them. +Only the owner of the ANT can mint new tokens, and is the owner +decides that enough is enough, the ANT can be finalized, preventing +more minting. An ANT can also be created with a final supply already +minted and given to the owner of the ANT. + +An ANT can only be destroyed (TODO: design decision) if the total +token supply of the ANT is zero (i.e., all tokens are burnt). + +Fees cannot be payed by native tokens, but only by aeons, but other +services can be payed for with them. (TODO: Oracle query fees, etc?) + +If you need to govern the behavior of the tokens, a contract can be +connected to the ANT. The contract has functions that will be called +for example when tokens of the type is traded. The result of the call +decides if the trade can happen or not. -## Token transactions -There is one transaction on token types: -- create +## Definitions -There are five token transactions: -- mint -- spend -- trade -- burn -- finalize +Note that when *account* is used below, the account can belong to a +contract, the account may be an oracle, etc. -Other transactions that takes a balance can also take a native token balance. +An Aeternity Native Token (ANT): +- is a *specification* of tokens +- is a *first class object* on the chain with its own state tree +- is *created* by an account which becomes its owner +- *governs the behavior* when interacting with tokens (trading, sending, minting, etc). +- can have a *connected contract* to govern the handling of its tokens + +A native token: +- has an ANT describing its behavior. +- is *countable* +- is recorded as a *balance in the account* that owns it (in the accounts state tree). +- is *mintable* (`mint`) +- is *transferable* (`spend`, `trade`) +- is *destroyable* (`burn`) + +## ANT transactions +An ANT can be: +- *created* through the `ant_create_tx` +- *finalized* through the `ant_finalize_tx`, preventing more minting. + +## Token transactions -### token create transaction +Tokens can be: +- *minted* through the `ant_mint_tx`. +- *destroyed* through the `ant_burn_tx`. +- *traded* atomically through the `ant_trade_tx`. -The token create transaction takes the following argument +Tokens can also be transfered from one account to another through any +other transaction that can pass an amount. You can: +- spend tokens through the `spend_tx` +- pass tokens as value in a `contract_call_tx` or `contract_create_tx` +- pass tokens as value in contract calls in a smart contract. +- spend tokens as query fees in `oracle_query_tx` (TODO: Might be a future extension). + +### ANT create transaction (`ant_create_tx`) + +The ANT create transaction takes the mandatory argument: - Meta data : string -and the following optional arguments + +The ANT create transaction takes the optional arguments: - Contract - Amount - Recipient -- Parent +- Parent (TODO: Decide what impact this have. Possibly delay having hierarchical tokens) - Final The `meta data` is an uninterpreted string but token minters are encouraged to use the following json object: +``` { "type" : "object", - "properties": { - "name": {"type" : "string"}, - } + "properties": { "name": {"type" : "string"}, + } } +``` The `contract` has to provide the following ACI: +``` spend(recipient : address, payload : Type) : boolean - trade([(from : address, to: address, Optional(token : address))], payload : Type) - mint(amount: integer) + trade([(from : address, to: address, Optional(token : address))], payload : Type) : boolean + mint(amount: integer) : boolean burn(amount : integer) : boolean +``` The `amount` is the number of tokens to create. @@ -68,7 +113,7 @@ The `final` argument sets the final flag which would block future minting. If a contract is provided then any transaction (spend, trade, mint, burn) would call this contract and the transaction only goes through if the result of the corresponfing contract call returns true. Any other transaction using -the token (such as contract call) would only be ececuted if a call to spend +the token (such as contract call) would only be executed if a call to spend returns true. ## Tokens state tree From 5981435ed935537750687b91bdfe9384d535da5d Mon Sep 17 00:00:00 2001 From: Tobias Lindahl Date: Mon, 30 Sep 2019 14:05:38 +0200 Subject: [PATCH 09/14] More rewriting --- node/api/api_encoding.md | 1 + serializations.md | 50 +++++++++++++++------- tokens/tokens.md | 91 ++++++++++++++++++++++++---------------- 3 files changed, 90 insertions(+), 52 deletions(-) diff --git a/node/api/api_encoding.md b/node/api/api_encoding.md index 54aef7e2..f37f29b6 100644 --- a/node/api/api_encoding.md +++ b/node/api/api_encoding.md @@ -43,6 +43,7 @@ tag. | kh | base58 | Key block hash | | mh | base58 | Micro block hash | | nm | base58 | Name | +| nt | base58 | Aeternity Native Token (ANT) | | ok | base58 | Oracle pubkey | | oq | base58 | Oracle query id | | or | base64 | Oracle response | diff --git a/serializations.md b/serializations.md index 12049456..7ee38525 100644 --- a/serializations.md +++ b/serializations.md @@ -253,12 +253,12 @@ subsequent sections divided by object. | Sophia byte code | 70 | | Generalized accounts attach transaction | 80 | | Generalized accounts meta transaction | 81 | -| Token | 90 | -| Token create transaction | 91 | -| Token mint transaction | 92 | -| Token trade transaction | 93 | -| Token burn transaction | 94 | -| Token finalize transaction | 95 | +| Aeternity Native Token (ANT) | 90 | +| ANT create transaction | 91 | +| ANT mint transaction | 92 | +| ANT finalize transaction | 93 | +| Token trade transaction | 94 | +| Token burn transaction | 95 | | Key block | 100 | | Micro block | 101 | | Light micro block | 102 | @@ -1051,15 +1051,26 @@ NOTE: ] ``` +#### Aeternity Native Token (ANT) +``` +{ creator :: id() +, meta_data :: binary() +, contract :: id() +, total_amount :: int() +, parent :: id() TODO: Decide if we should have hierarchical tokens +, final :: bool() +} +``` + -#### Token create transaction +#### ANT create transaction ``` [ :: id() , :: binary() , :: id() , :: int() , :: id() -, :: id() +, :: id() TODO: Decide on hierarchical tokens , :: bool() , :: int() , :: int() @@ -1067,9 +1078,11 @@ NOTE: ] ``` -#### Token mint transaction +#### ANT mint transaction ``` -[ :: int() +[ :: id() +, :: id() +, :: int() , :: id() , :: bool() , :: int() @@ -1078,27 +1091,32 @@ NOTE: ] ``` -#### Token trade transaction +#### ANT finalize transaction ``` -[ :: [{id(), id(), int(), id()}] +[ :: id() +, :: id() , :: int() , :: int() , :: int() ] ``` -#### Token burn transaction +#### Token trade transaction + ``` -[ :: int() +[ :: [{ :: id(), :: id(), :: int(), :: id()}] , :: int() , :: int() , :: int() ] ``` -#### Token finalize transaction +#### Token burn transaction ``` -[ :: int() +[ :: id() +, :: int() +, :: int() +, :: int() , :: int() , :: int() ] diff --git a/tokens/tokens.md b/tokens/tokens.md index b9c403ba..4147114e 100644 --- a/tokens/tokens.md +++ b/tokens/tokens.md @@ -15,22 +15,25 @@ Owners of the tokens can spend them to other accounts, or trade them (atomically) for other assets with other accounts. If tokens are no longer wanted you can burn them. -Only the owner of the ANT can mint new tokens, and is the owner -decides that enough is enough, the ANT can be finalized, preventing -more minting. An ANT can also be created with a final supply already -minted and given to the owner of the ANT. +Only the owner of the ANT can mint new tokens. Only the owner can +finalize the ANT, preventing more minting. An ANT can also be +created with a final supply already minted. An ANT can only be destroyed (TODO: design decision) if the total token supply of the ANT is zero (i.e., all tokens are burnt). -Fees cannot be payed by native tokens, but only by aeons, but other -services can be payed for with them. (TODO: Oracle query fees, etc?) - -If you need to govern the behavior of the tokens, a contract can be -connected to the ANT. The contract has functions that will be called -for example when tokens of the type is traded. The result of the call -decides if the trade can happen or not. +Aeons are not part of the ANT system. There are no consensus +controlled exchange rate between tokens and aeons. Fees cannot be +payed by native tokens, but only by aeons. Other services could be +payed for with tokens (e.g., contracts accepting tokens as +payment). (TODO: Design decision: Should oracles be allowed to set +fees in tokens?) +The owner of a token can decide to govern the behavior of the tokens +by connecting a contract when an ANT is created. The contract must +provide entrypoints according to a specified ACI where one or many of +the primitive operation (spend, trade, mint, etc) is called to decide +if the operation is allowed or not. ## Definitions @@ -52,6 +55,45 @@ A native token: - is *transferable* (`spend`, `trade`) - is *destroyable* (`burn`) +## Tokens state tree + +The tokens state tree contains ANT objects. Tokens are stored in the +accounts state tree in the owner's account. + +### ANT object + +The token id is determined by the creator's account and nonce. +``` + id := Blake2b() +``` +where `Blake2b` is the 256 bit hash. The [API +serialization](../node/api/api_encoding.md) of an ANT id is tagged by +`nt_` + +The ANT contains the fields: +- `creator` - The account id of the creator +- `meta_data` - A byte array field uninterpreted under consensus +- `contract` - A contract id if there is a governing contract, or the empty binary otherwise +- `total_amount` - A counter of the currently available amount of the token +- `parent` - The id of the parent ANT (TODO: Hierarchical tokens?) +- `final` - Boolean that indicated whether new tokens can be minted. Can flip to false, but never back to true again. + +The `meta data` is an uninterpreted string but token minters are +encouraged to use the following json object: (TODO: Extend). The +intention of the meta data is to have a consensus controlled way of +providing information usable by tools (e.g., displaying an intended +denominator, a display name, etc). +``` +{ + "type" : "object", + "properties": { "name": {"type" : "string"}, + } +} +``` + +# REWORKED UP TO HERE. + + ## ANT transactions An ANT can be: - *created* through the `ant_create_tx` @@ -83,15 +125,6 @@ The ANT create transaction takes the optional arguments: - Parent (TODO: Decide what impact this have. Possibly delay having hierarchical tokens) - Final -The `meta data` is an uninterpreted string but token minters are encouraged to -use the following json object: -``` -{ - "type" : "object", - "properties": { "name": {"type" : "string"}, - } -} -``` The `contract` has to provide the following ACI: ``` @@ -112,24 +145,11 @@ The `final` argument sets the final flag which would block future minting. If a contract is provided then any transaction (spend, trade, mint, burn) would call this contract and the transaction only goes through if the result of the -corresponfing contract call returns true. Any other transaction using +corresponding contract call returns true. Any other transaction using the token (such as contract call) would only be executed if a call to spend returns true. -## Tokens state tree - -The tokens state tree contain token type objects. -Tokens are stored in the account state tree as a list of tuples of -token id:s and balances. - -### Token state tree objects - -- The token state tree contains - - Token type objects - -#### The token type object - -- Created by an token create transaction. +## Create transaction ``` { creator :: id() @@ -141,4 +161,3 @@ token id:s and balances. } ``` - From 73c403120ce85cd042829a44c9bf7169847bd290 Mon Sep 17 00:00:00 2001 From: Tobias Lindahl Date: Mon, 30 Sep 2019 15:13:59 +0200 Subject: [PATCH 10/14] Even more rewriting --- serializations.md | 2 +- tokens/tokens.md | 140 +++++++++++++++++++++++++++++----------------- 2 files changed, 91 insertions(+), 51 deletions(-) diff --git a/serializations.md b/serializations.md index 7ee38525..95f88d83 100644 --- a/serializations.md +++ b/serializations.md @@ -1056,7 +1056,7 @@ NOTE: { creator :: id() , meta_data :: binary() , contract :: id() -, total_amount :: int() +, total_supply :: int() , parent :: id() TODO: Decide if we should have hierarchical tokens , final :: bool() } diff --git a/tokens/tokens.md b/tokens/tokens.md index 4147114e..6a45eafc 100644 --- a/tokens/tokens.md +++ b/tokens/tokens.md @@ -74,7 +74,7 @@ The ANT contains the fields: - `creator` - The account id of the creator - `meta_data` - A byte array field uninterpreted under consensus - `contract` - A contract id if there is a governing contract, or the empty binary otherwise -- `total_amount` - A counter of the currently available amount of the token +- `total_supply` - A counter of the currently available amount of the token - `parent` - The id of the parent ANT (TODO: Hierarchical tokens?) - `final` - Boolean that indicated whether new tokens can be minted. Can flip to false, but never back to true again. @@ -91,73 +91,113 @@ denominator, a display name, etc). } ``` -# REWORKED UP TO HERE. +A contract governing the usage of tokens must have a non-empty subset +of the following ACI: +``` + spend(recipient : address, payload : Type) : boolean + trade([(from : address, to: address, Option(token : address))], payload : Type) : boolean + mint(amount: integer) : boolean + burn(amount : integer) : boolean +``` -## ANT transactions -An ANT can be: -- *created* through the `ant_create_tx` -- *finalized* through the `ant_finalize_tx`, preventing more minting. - -## Token transactions +The contract may contain other endpoints as well, but at least one of +the entrypoints above must be implemented. The contract can only be +attached at create time. -Tokens can be: -- *minted* through the `ant_mint_tx`. -- *destroyed* through the `ant_burn_tx`. -- *traded* atomically through the `ant_trade_tx`. +If a contract is provided, any transaction (spend, trade, mint, burn) +would call this contract and the transaction only goes through if the +result of the corresponding contract call returns true. Any other +transaction using the token (such as contract call) would only be +executed if a call to spend returns true. (TODO: Decide how this plays +with contract calls that tries to pass tokens as value, etc). -Tokens can also be transfered from one account to another through any -other transaction that can pass an amount. You can: -- spend tokens through the `spend_tx` -- pass tokens as value in a `contract_call_tx` or `contract_create_tx` -- pass tokens as value in contract calls in a smart contract. -- spend tokens as query fees in `oracle_query_tx` (TODO: Might be a future extension). +## ANT transactions ### ANT create transaction (`ant_create_tx`) -The ANT create transaction takes the mandatory argument: +The ANT create transaction takes the argument: - Meta data : string - -The ANT create transaction takes the optional arguments: -- Contract - Amount - Recipient -- Parent (TODO: Decide what impact this have. Possibly delay having hierarchical tokens) - Final +- Contract +- Parent (TODO: Hierarchical tokens?) +The `amount` is the number of tokens to mint at create time. Set to +`0` if none should be minted. This can for example be combined with +setting the `final` argument to false, thereby immediately minting all +tokens that will ever exist. -The `contract` has to provide the following ACI: -``` - spend(recipient : address, payload : Type) : boolean - trade([(from : address, to: address, Optional(token : address))], payload : Type) : boolean - mint(amount: integer) : boolean - burn(amount : integer) : boolean -``` +The `recipient` is the recipient of the minted tokens in `amount`. If +not provided, the tokens are given to the creator's account. -The `amount` is the number of tokens to create. +The `parent` is a pointer to a parent token for hierarchical +tokens. (TODO: hierarchical tokens?) -The `recipient` an account to dump the tokens created, if not given the tokens are -spent to the creators account. +### ANT finalize transaction (`ant_finalize_tx`) -The `parent` is a pointer to a parent token for hierarchical tokens. +The ANT finalize transaction takes the arguments: +- owner +- ANT -The `final` argument sets the final flag which would block future minting. +The finalize transaction can only be submitted by the actual owner, +and only if the ANT is not already finalized. -If a contract is provided then any transaction (spend, trade, mint, burn) would -call this contract and the transaction only goes through if the result of the -corresponding contract call returns true. Any other transaction using -the token (such as contract call) would only be executed if a call to spend -returns true. +### ANT mint transaction (`ant_mint_tx`) +The ANT mint transaction takes the argument: +- owner +- ANT +- amount +- recipient +- final -## Create transaction +Only the `owner` can mint new tokens, but it can pass the minted +tokens to a recipient. If `final` is set to true, the ANT will be +finalized after the new tokens are minted. -``` -{ creator :: id() -, :: binary() -, :: id() -, :: int() -, :: id() -, :: bool() +### ANT destroy transaction +TODO: Should we be able to destroy an ANT that has a `total_supply` of 0? -} -``` + +## Token transactions + +### Token trade transaction +The token trade transaction takes the argument: +- trades + +The `trades` field contans a non-empty list of token transfers. A +single token transfer consists of the fields: + +- Sender +- Receiver +- Amount +- An ANT id + +This construct makes it possible to atomically perform complicated +trade operations involving more than one ANT and also aeons (TODO: How +to signal that a trade concerns aeons) between multiple parties. + +The transaction must be signed by all senders. (TODO: Should we use +some alternative multisig format here?). + + +### Token burn transaction + +The token burn transaction contains the fields +- Account (owner of the tokens, not necessarily of the ANT) +- Amount +- ANT + +Destroy an `Amount` of `ANT` tokens currently owned by the +`account`. The burned amount is also counted from the `total_supply` +in the ANT object. + +### Other transactions on tokens + +Tokens can also be transfered from one account to another through any +other transaction that can pass an amount. You can: +- spend tokens through the `spend_tx` +- pass tokens as value in a `contract_call_tx` or `contract_create_tx` +- pass tokens as value in contract calls in a smart contract. +- spend tokens as query fees in `oracle_query_tx` (TODO: Might be a future extension). From 8be5d64debd8e2b63f571ca2634088ad4b7ec763 Mon Sep 17 00:00:00 2001 From: Tobias Lindahl Date: Mon, 30 Sep 2019 15:53:15 +0200 Subject: [PATCH 11/14] Fix confusion of final ANTs --- tokens/tokens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tokens/tokens.md b/tokens/tokens.md index 6a45eafc..c344403a 100644 --- a/tokens/tokens.md +++ b/tokens/tokens.md @@ -76,7 +76,7 @@ The ANT contains the fields: - `contract` - A contract id if there is a governing contract, or the empty binary otherwise - `total_supply` - A counter of the currently available amount of the token - `parent` - The id of the parent ANT (TODO: Hierarchical tokens?) -- `final` - Boolean that indicated whether new tokens can be minted. Can flip to false, but never back to true again. +- `final` - Boolean that indicated whether new tokens can be minted. Can flip to true, but never back to false again. The `meta data` is an uninterpreted string but token minters are encouraged to use the following json object: (TODO: Extend). The From a1c8cba9e3fe7d73a25370dba373eee19f47d9fa Mon Sep 17 00:00:00 2001 From: Tobias Lindahl Date: Mon, 30 Sep 2019 15:55:01 +0200 Subject: [PATCH 12/14] Better fix --- tokens/tokens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tokens/tokens.md b/tokens/tokens.md index c344403a..2baf2066 100644 --- a/tokens/tokens.md +++ b/tokens/tokens.md @@ -76,7 +76,7 @@ The ANT contains the fields: - `contract` - A contract id if there is a governing contract, or the empty binary otherwise - `total_supply` - A counter of the currently available amount of the token - `parent` - The id of the parent ANT (TODO: Hierarchical tokens?) -- `final` - Boolean that indicated whether new tokens can be minted. Can flip to true, but never back to false again. +- `final` - If the ANT is final, new tokens cannot be minted. Can flip to true, but never back to false again. The `meta data` is an uninterpreted string but token minters are encouraged to use the following json object: (TODO: Extend). The From 3cef20da379a6c7c048cc8ebd65d2097327f17e0 Mon Sep 17 00:00:00 2001 From: Tobias Lindahl Date: Tue, 1 Oct 2019 09:07:52 +0200 Subject: [PATCH 13/14] Address review comments --- serializations.md | 10 ++++++++++ tokens/tokens.md | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/serializations.md b/serializations.md index 95f88d83..76a04c8a 100644 --- a/serializations.md +++ b/serializations.md @@ -297,6 +297,16 @@ subsequent sections divided by object. , :: [{id(),int()}] ``` +#### Accounts (version 5, Generalized accounts with tokens, from XXX release) +``` +[ :: int() +, :: int() +, :: int() +, :: id() +, :: binary() +, :: [{id(),int()}] +``` + ### Signed transaction ``` [ :: [binary()] diff --git a/tokens/tokens.md b/tokens/tokens.md index 2baf2066..bfb20234 100644 --- a/tokens/tokens.md +++ b/tokens/tokens.md @@ -72,7 +72,7 @@ serialization](../node/api/api_encoding.md) of an ANT id is tagged by The ANT contains the fields: - `creator` - The account id of the creator -- `meta_data` - A byte array field uninterpreted under consensus +- `meta_data` - A byte array field, uninterpreted, but under consensus - `contract` - A contract id if there is a governing contract, or the empty binary otherwise - `total_supply` - A counter of the currently available amount of the token - `parent` - The id of the parent ANT (TODO: Hierarchical tokens?) @@ -126,7 +126,7 @@ The ANT create transaction takes the argument: The `amount` is the number of tokens to mint at create time. Set to `0` if none should be minted. This can for example be combined with -setting the `final` argument to false, thereby immediately minting all +setting the `final` argument to true, thereby immediately minting all tokens that will ever exist. The `recipient` is the recipient of the minted tokens in `amount`. If From e7138dcb7f1e1895823cc804746d7761c8477b9a Mon Sep 17 00:00:00 2001 From: Tobias Lindahl Date: Tue, 1 Oct 2019 09:13:43 +0200 Subject: [PATCH 14/14] Clarify ANT/contract precedence --- tokens/tokens.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tokens/tokens.md b/tokens/tokens.md index bfb20234..ef6a5a7c 100644 --- a/tokens/tokens.md +++ b/tokens/tokens.md @@ -112,6 +112,10 @@ transaction using the token (such as contract call) would only be executed if a call to spend returns true. (TODO: Decide how this plays with contract calls that tries to pass tokens as value, etc). +Note that the `final` field in the ANT takes precedence over the +governing contract. If the ANT is final, no minting can occur. (TODO: +Perhaps the contract should have a `finalize` endpoint as well?) + ## ANT transactions ### ANT create transaction (`ant_create_tx`)