Transfer of Funds
A simple transaction moves funds from one user account to another. On a high level, transactions must define 3 things:
- Inputs: previously created unpsent transaction outputs holding funds that the transaction consumes,
- Unlock Blocks: they hold the signatures authorizing the consumption of inputs,
- Outputs: newly created outputs holding transferred funds.
In Stardust a simple transfer may be realized with an output type called Basic Output. Just like every other output type, Basic Outputs define the base token funds they hold in the Amount field. They have to have at least one Unlock Condition defined: the Address Unlock Condition.
It means that in order to unlock the output in a transaction, one has to present a valid signature for the given address. The signature signs the whole content of the transaction, thereby authorizing the consumption of inputs but also declaring the intention to create new outputs.
Transaction A simply:
- consumes as input a Basic Output with 100i locked under ownerAddress,
- provides an Unlock, namely a Signature Unlock that contains a valid signature of the transaction content corresponding to the private key behind ownerAddress,
- creates a new Basic Output with 100i locked under the recipients address, namely recipientAddress.
Transfer of Funds with Expiration
The first new Unlock Condition we are going to look at is the Expiration Unlock Condition. It lets the creator of the output define an Expiration Deadline. Before the deadline, the recipient can consume and unlock the output in a transaction, but once the deadline expired, only the Return Address defined in the Expiration Unlock Condition can unlock it.
Transaction B defines an output that can only be unlocked by the recipient in a transaction that is confirmed by a milestone where Milestone Unix Timestamp is less, than the Unix Time defined in the Expiration Unlock Condition.
Transaction C shows how the recipient can consume the output before the deadline and take the funds into full, unconditional custody.
Transaction D depicts how the original sender claims an expired output. Note, that it is not necessary for the sender to sweep the funds into their own wallet, they can just treat it as funds they have full custody of.
Timelocking Funds in Transfers
With Stardust, it is possible to lock funds away based on time. When an output has a Timelock Unlock Condition defined, not even its rightful owner can unlock it before the timelock expires. Just like in the case of the Transaction C and D, the notion of time in the ledger is determined by the timestamp of the milestone that confirms the transaction.
Transaction E creates an output owned by the recipient but timelocked until May 24 2022 18:00:00.
The recipient has no way to unlock the output before the deadline. Once the timelock expired, the funds can be moved, as depicted on Transaction F.
Storage Deposit Returns in Transfers
Stardust introduces a new system to protect the ledger size and hence node storage resources, called Byte-cost based Storage Deposit System. You can read more about it in TIP-19. In short, every output in the ledger need to carry enough base tokens to cover for its network storage use.
Implicitly this means that an output has to have a minimum amount of base tokens, otherwise it is considered invalid. The exact minimum depends on the size of the output and the protocol parameter Virtual Byte Cost. The implication of this is that is no longer possible to store microfunds in an output. So suppose you wanted to send 1i (0.000001 MIOTA): is it still possible?
The answer is yes. With the Storage Deposit Return Unlock Condition it is possible to define spending constraints on outputs that you create. Let's assume that the minimum amount of funds that need to be present in an output is 100i. If you wanted to send only 1i to the recipient, you would transfer 101i to the recipient's address with the extra condition that she can only use the funds if she refunds you in the very same transaction with 100i.
Transaction G show the creation of an output with Storage Deposit Return Unlock Condition. Notice, that Basic Output #11 holds 101i, and the unlock condition defines the Return Amount of 100i to ReturnAddress ownerAddress. All in all, the recipient can only freely use 1i when she consumes the output in Transaction H.
In order for the recipient to claim the 1i, she needs to sweep it into one of her own outputs. Therefore, she consumes Basic Output #12 in the transaction that holds her funds. On the output side, she has to have Basic Output #13 that refunds the original sender, plus she creates Basic Output #14 into which she sweeps the 1i.
What forces the recipient to post and execute Transaction H? Nothing. She can just keep the sender's 100i in limbo forever. That is why it is handy that you can combine unlock conditions. For example, the sender can add an expiration condition to Basic Output #11. Once the output is expired, the recipient won't be able to claim the 1i and the sender takes full custody of the 101i in the output.
Next to Unlock Conditions, Stardust allows to define optional Features on outputs of a transfer that do not impact the actual unlocking of the created output. The Sender feature is one of such features, which lets the creator of the output define an explicit Sender Address attribute for an output.
The Sender attribute is validated on protocol level. Validation ensures that the transaction that created the output unlocked the Sender address on the input side. Therefore, this feature is a protocol validated proof that the output was created by someone who controls the Sender address.
Transaction J shows how one can add a sender attribute to a created output. Note, that Transaction J would be invalid if:
- Basic Output #15 wouldn't be locked to senderAddress, or
- Basic Output #16 would define Sender as anything else than senderAddress from Basic Output #15.
On-ledger (originating from L1) requests of IOTA Smart Contracts use this feature heavily, but it is also possible to fetch outputs created by a specific party with the Sender Feature through the INX UTXO indexer application and REST API.
Another handy tool is the Metadata Feature of outputs. This feature makes it possible to store arbitrary data in outputs. Of course, storing data in outputs increases the minimum base token requirement, but in turn it provides a data storage option that is 24/7 available on any network node.
As soon as the output with metadata is consumed, it is pruned from nodes' databases and base tokens used as storage deposit are freed up.
The Tag Feature makes it possible to associate a maximum 64 bytes long indexation tag with an output. Similarly to the Metadata Feature, the actual Tag is treated as binary data by the protocol.
Note, that by default nodes do not store and expose the indexation by tag, however the Indexer API does. In an "IOTA as a payment method" use case the Tag field could be used as a payment reference field, much like the payment reference option of a regular wire transfer.