Native Tokens and Foundries
Stardust introduces the concept of native tokens, or also called user-defined custom tokens. These tokens are minted into existence by token foundries, represented as Foundry Outputs on protocol level. The foundry defines the supply control rules, that is, how many tokens can ever be created.
All outputs in the ledger support holding native tokens, therefore to transact with native tokens users don't need the approval of the foundry. Once native tokens are minted, they function as digital cash. The foundry acts as the central bank controlling supply via minting new tokens or buying back tokens from the market to be melted, hence decreasing the available supply. Users have the ability to burn native tokens in their possession, which is equivalent to sending the to-be burnt tokens to the zero address.
Foundries can only be created and controlled by alias accounts. Smart contract chains therefore can also act as token issuers on L1 and leverage the framework for L2 asset wrapping and inter-L2-chain transfers.
Creating a Foundry
As mentioned above, only an alias can create new foundries, therefore the process starts with an existing Alias Output. To create a new foundry, simply state transition the alias and create a new Foundry Output on the output side of the transaction.
Transaction A shows an example transaction that creates a foundry:
- The controlling alias is state transitioned, its State Index and Foundry Counter are incremented.
- To cover for the storage deposit of the created Foundry Output, the alias deposits 100i into the output.
- The Serial Number of the foundry must correspond to the updated Foundry Counter. Each foundry created by the alias is unique because of the unique Serial Number.
- The foundry uses the Simple Token Scheme as a supply control rule. It defines an upper cap (Maximum Supply) for tokens in circulation.
- Minted Tokens defines how many tokens have been minted by the foundry. Since we don't immediately mint tokens in this transaction, it is set to 0.
- Melted Tokens defines how many tokens have been melted by the foundry. At creation there are no tokens to be melted, therefore this must be 0.
- Foundries support only one unlock condition, namely the Immutable Alias Address Unlock Condition. It can never be changed during the lifetime of the foundry, therefore the issuer role can only be transferred via the controlling alias.
- Metadata about the token may be put in the Immutable Metadata Feature of the foundry. For example, it may hold an IRC30 compatible JSON file. By hosting token metadata on-chain in a foundry output, we make the data available on all network nodes 24/7. There is no need for additional, off-chain metadata servers.
Minting tokens
Now that we have the foundry, it's time to mint native tokens. We simply need to transition the foundry in a transaction, declare that we mint tokens and place them in an output of our choice.
Tokens controlled by a foundry have a globally unique identifier, called Token ID, that is derived from the properties of the foundry. To get the Token ID, one has to concatenate:
- the serialized Alias Address that controls the foundry (33 bytes),
- the Serial Number of the foundry,
- and the Token Scheme Type.
By knowing the Token ID, one can fetch current unspent foundry output from the Indexer API defined in TIP-26.
Transaction B mints all available tokens in the foundry.
- Minted Tokens in Foundry Output #2 is increased by the number of minted tokens, namely 1000.
- 500 tokens are minted into Basic Output #1 and locked to mintAddress.
- 500 tokens are minted into Basic Output #2 and locked to vestAddress. Additionally, a timelock is specified on the output so that these token can only be unlocked after May 24 2023 18:00:00.
Melting tokens
Melting tokens removes them from the circulating supply. Melting can only be carried out if the foundry is included in the transaction.
Transaction C assumes that the token issuer is in control of mintAddress where the to-be melted tokens are locked. 250 tokens are being melted in foundry.
- Melted Tokens of Foundry Output #3 is increased by the amount of melted tokens, 250.
- Basic Output #3 has only 250 tokens remaining. The input side of the transaction contains 500 tokens, but the output side only 250. By increasing Melted Tokens on Foundry Output #3 the transaction becomes balanced.
- Looking at Foundry Output #3 we can determine that the circulating supply of the token is Minted Tokens - Melted Tokens = 750.
- In a subsequent transaction we could mint 250 tokens to reach Maximum Supply again.
Burning tokens
Burning tokens by token holders without the involvement of the foundry is possible to prevent losing access to the storage deposit of the underlying tokens. What would happen if mintAddress in Basic Output #3 is not controlled by the issuer, but some other entity?
They obviously can't melt the tokens without controlling the foundry, therefore they can't free up the base tokens (IOTA/SMR) in Basic Output #3. Unless the issuer buys back the tokens or someone else relieves the user by taking the tokens and refunding the storage deposit, it is locked forever. Burning makes it possible to "forget" about these tokens and free up the storage deposit.
Burnt tokens are no longer tracked in the ledger, therefore burning is conceptually equivalent to sending to the zero address without a storage deposit.
Transaction D burns all tokens in Basic Output #3. Notice that mintAddress doesn't have to have the approval of the foundry and the controlling alias account.
Transferring native tokens with storage deposit
Transferring native tokens is similar to transferring base tokens. The output that you create on the receiver's address however needs to have base tokens to cover for the storage deposit. Therefore, there are two ways to transfer native tokens:
- Sending native tokens together with the required storage deposit. The sender loses access to the storage deposit.
- Sending native tokens with Storage Deposit Return Unlock Condition. The receiver has to claim the transfer by refunding the storage deposit of the sender. The sender doesn't lose the storage deposit.
The former method is depicted in Transaction E. Due to claiming in the latter method, it is called a conditional transfer, depicted in Transaction F.
Conditional transfer of native tokens
In order not to lose access to the storage deposit, two additional unlock conditions are defined on Basic Output #7 in Transaction F:
- A Storage Deposit Return Unlock Condition that forces the consumer of the output to refund Return Amount of base tokens to Return Address,
- and an Expiration Unlock Condition that defines a time window until the recipient has to claim the transfer. If they don't do so, ownership of Basic Output #7 bounces back to the sender and the Storage Deposit Return Unlock Condition is ignored.
- The expiration time is compared to the timestamp of the confirming milestone to decide whether the unlock is valid or not.
Transaction F shows the creation of a conditional transfer:
Once the "offer" is created, the recipient can claim the transfer until the expiration deadline. Transaction G shows a successful claiming.
- Note that the recipient needs to sweep the native tokens into an output they already own to cover for the storage deposit, hence Basic Output #8 is unlocked in the transaction.
- Basic Output #9 refunds the sender with the storage deposit used to create Basic Output #7.