Tokens

Introduction

CasperLabs is a decentralized computation platform based on a proof-of-stake consensus algorithm. Having a unit of value is required to make this system work because users must pay for computation and validators must have stake to bond. It is traditional in the blockchain space to name this unit of value “token” and we continue that tradition here.

This chapter describes how we define tokens and how they are used in our platform.

Token Generation and Distribution

A blockchain system will need to have a supply of tokens available for the purposes of paying for computation and rewarding validators for the processing of transactions on the network. The tokens will be allocated in the following fashion (subject to applicable laws and regulations):

  • 70% of total token supply will be sold
    • 10% in the private validator sale for purposes of securing the genesis block
    • 10% in the initial public sale (around the time of main net launch)
    • The remainder in public sales over an extended period of time
  • 12% reserved for developer & entrepreneur incentives, advisors and community managers
  • 10% reserved for CasperLabs shareholders
  • 8% reserved for personnel in a manner consistent with customary employee incentive programs.

In addition to the initial supply, the system will have a low rate of inflation, the results of which will be paid out to validators in the form of seigniorage, as described previously in this document.

The number of tokens used as a basis for calculating seigniorage and the above stated allocations is 10 billion.

Divisibility of tokens

Typically, a “token” is divisible into some number of parts. For example, Ether is divisible into \(10^{18}\) parts (called Wei). To avoid rounding error, it is important to always represent token balances internally in terms of the number of indivisible parts. For the purposes of this document we will always work in terms of these indivisible units so as to not need to pick a particular level of divisibility for our “token” (as this detail is not important for the present description). We call the indivisible units which make up our token motes.

Mints and pursers

A mint is a contract which has the ability to produce new motes of a particular type. We allow for multiple mote types (each of which would have their own mint) because we anticipate the existence of a large ecosystem of different tokens, similar to ERC20 tokens on Ethereum. CasperLabs will deploy a specific mint contract and it will manage the CasperLabs utility token (used for paying for computation and bonding onto the network). The mint also maintains all the balances for its type of mote. Each balance is associated with a PurseId, which acts as a sort of key to instruct the mint to perform actions on that balance (e.g., transfer motes). Informally, we will refer to these balances as purses and conceptually they represent a container for motes. The PurseId is how a purse is referenced from outside the mint.

PurseIds have the same permissions model as URefs (indeed our implementation models PurseIds as simply a new-type wrapper over a URef). Each PurseId has AccessRights which determine what actions are allowed to be performed using that ID. The basic global state options map onto more standard monetary operations according to the table below:

Global State Action Monetary Action
Add Deposit (i.e. transfer to)
Write Withdraw (i.e. transfer from)
Read Balance check

PurseIds are unforgable (just like URefs), so the only way to interact with a purse is for the ID to be given to the current context in a valid way (see URef permissions for details).

We will use these definitions throughout this chapter as we describe the implementation and usage of tokens on the CasperLabs system.

The mint contract interface

A valid mint contract exposes the following methods (recall that many mint implementations may exist, each corresponding to a different “currency”).

  • transfer(source: PurseId, target: PurseId, amount: Motes) -> TransferResult
    • source must have at least Write access rights, target must have at least Add access rights
    • TransferResult may be a success acknowledgement or an error in the case of invalid source or target or insufficient balance in the source purse
  • mint(amount: Motes) -> MintResult
    • MintResult either gives the created PurseId (with full access rights), which now has balance equal to the given amount; or an error due to the minting of new motes not being allowed
    • In the CasperLabs mint only the system account can call mint, and it has no private key to produce valid cryptographic signatures, which means only the software itself can execute contracts in the context of the system account
  • create() -> PurseId
    • a convenience function for mint(0) which cannot fail because it is always allowed to create an empty purse
  • balance(purse: PurseId) -> Option<Motes>
    • purse must have at least Read access rights
    • BalanceResult either returns the number of motes held by the purse, or nothing if the PurseId is not valid

Using PurseIds

It is dangerous to pass a PurseId with Write permissions to any contract. A malicious contract may use that access to take more tokens than was intended or share that PurseId with another contract which was not meant to have that access. Therefore, if a contract requires a purse with Write permissions, it is recommended to always use a “payment purse”, which is a purse used for that single transaction and nothing else. This ensures even if that PurseId becomes compromised it does not contain any more funds than the user intended on giving.

let main_purse = contract_api::main_purse();
let payment_purse = contract_api::create_purse();

match contract_api::transfer_purse_to_purse(main_purse, payment_purse, payment_amount) {
    TransferResult::Success => contract_api::call_contract(contract_to_pay, payment_purse),
    _ => contract_api::revert(1),
}

To avoid this inconvenience, it is better practice for application developers intending to accept payment on-chain to make a version of their own PurseId with Read access rights publicly available. This allows clients to pay via a transfer using their own purse, without either party exposing Write access to any purse.

Purses and accounts

Every Accounts on the CasperLabs system has a purse associated with the CasperLabs system mint, which we call the account’s “main purse”. However, for security reasons, the PurseId of the main purse is only available to code running in the context of that account (i.e. only in payment or session code). Therefore, the mint’s transfer method which accepts PurseIds is not the most convenient to use when transferring between account main purses. For this reason, CasperLabs supplies a transfer_to_account function which takes the public key used to derive the identity key of the account. This function uses the mint transfer function with the current account’s main purse as the source``and the main purse of the account at the provided key as the ``target. The transfer_from_purse_to_account` function is similar, but uses a given purse as the source instead of the present account’s main purse.