Skip to content
On this page

Tokens โ€‹

The GamePlatform's Ledger contains:

  • 3 bigmaps related to tokens: ledger, token_metadata and token_permissions.
    The two first are those describe in FA2 standard.
    The token_permissions describes specific permissions associated with the token.
  • FA2 entrypoints + transfer_and_call + update_token_permissions, push_bonds, mint, burn, withdraw.

Platform tokens should not be confused with bonds. Tokens are stored outside of channels.

Token 0 often corresponds to wrapped XTZ (basically they can be minted by sending xtz and burned so you receive xtz). Other tokens can correspond to FA1.2/FA2 external tokens or internal tokens.

The admin can authorize a model or a specific game to distribute platform tokens (like reputation tokens).

Push bonds โ€‹

See push_bonds.

Mint tokens โ€‹

Native tokens (tokens managed by the ledger) can be minted according to the permissions.

python
@sp.entrypoint
def mint(self, address, token_id, amount):
    sp.set_type(address, sp.TAddress)  # Address of the receiver
    sp.set_type(token_id, sp.TNat)  # Id of the token
    sp.set_type(amount)  # Amount minted
python
ledger.mint(
    address = player1.address,
    token_id = 0,
    amount = 100 * 10**6
).run(sender = player1, amount = sp.tez(100))

Burn tokens โ€‹

python
@sp.entrypoint
def burn(self, address, token_id, amount):
    sp.set_type(address, sp.TAddress)  # Address of the receiver
    sp.set_type(token_id, sp.TNat)  # Id of the token
    sp.set_type(amount)  # Amount minted
python
ledger.burn(
    address = player1.address,
    token_id = 0,
    amount = 100 * 10**6
).run(sender = player1, amount = sp.tez(100))

Unwrap native tokens โ€‹

Certain native tokens can be unwrapped. In this case they are burned and retransformed.

For example you can unwrap your wXTZ to receive XTZ.

python
@sp.entrypoint
def withdraw_ledger(self, receiver, tokens):
    sp.set_type(receiver, sp.TAddress)  # Address of the receiver
    # Map of `token_id => amount` you want to withdraw
    sp.set_type(tokens, sp.TMap(sp.TNat, sp.TNat))
python
platform.withdraw_ledger(
    receiver = player1.address,
    tokens = sp.map({0: 10_000_000})
).run(sender = player1)

Tokens metadata and authorization โ€‹

Token Metadata โ€‹

Set the token metadata.

Token metadata corresponds to those described in TZIP-12 and TZIP-16.

python
@sp.entrypoint
def set_token_metadata(self, token_id, metadata):
    # The id of the token as represented in the platform
    sp.set_type(token_id, sp.TNat)
    # Metadata of the tokens
    sp.set_type(metadata, sp.TMap(sp.TString, sp.TBytes))
python
c1.set_token_metadata(
    token_id = 1,
    metadata = {
        "name"        : sp.utils.bytes_of_string("Wrapped Dummy FA2"),
        "decimals"    : sp.utils.bytes_of_string("%d" % 0),
        "symbol"      : sp.utils.bytes_of_string("WDFA2"),
        "type"        : sp.pack("FA2"),
        "max_supply"  : sp.pack(100_000_000_000),
        "fa2_address" : sp.pack(dummyToken.address),
        "fa2_token_id": sp.pack(0),
    }
).run(sender = admin)

Set Token Permissions (admin only) โ€‹

Set the token permissions.

The token permissions are pack of the value.

KeyValue TypeDescription
burn_permissionssp.TVariant("onlyOwner": Unit, "allow_only: Set(Address))Type of permission applied to burn (if not present no burn allowed) "allow_only": only addresses in this set are allowed to burn
fa_tokenPair(Address, Nat)Contract address and token_id of the corresponding fa token
fa2_token_idNatid of the corresponding fa2 token
mint_costMuteznumber of mutez need to mint 1 token
mint_permissionssp.TVariant("allow_everyone": Unit, "allow_only: Set(Address))Type of permission applied to mint (if not present no mint allowed) "allow_only": only addresses in this set are allowed to mint
transfer_only_toSet(Address)The token can only be transferred to one of those addresses
transfer_only_fromSet(Address)The token can only be transferred from one of those addresses
type*String {"FA2", "Native"}Type of token represented.

* required

python
@sp.entrypoint
def update_token_permissions(self, token_id, metadata):
    # The id of the token as represented in the platform
    sp.set_type(token_id, sp.TNat)
    # Permissions of the tokens. If None, the key is deleted.
    sp.set_type(metadata, sp.TMap(sp.TString, TOption(bytes)))
python
lgr = sp.io.import_template("state_channel_games/ledger.py")
c1.update_token_permissions(
    token_id = 1,
    metadata = lgr.build_token_permissions({
    "type"            : "NATIVE",
    "mint_cost"       : sp.mutez(1),
    "mint_permissions": sp.variant("allow_everyone", sp.unit)
})
).run(sender = admin)

Game permissions โ€‹

Each running game can have the permission to mint tokens.

The metadata of the game must contain the following key: allowed_mint.

Its value is a map of bonds and amount.

The game can at most ask the platform to mint this number of tokens when being settled.

Change the game metadata โ€‹

Only admins can change the game metadata.

python
gameplatform.admin_game_metadata(game_id, "allowed_mint", sp.pack({42: 1000}))

Model permissions โ€‹

The models can have the permission to mint tokens.

The metadata of the model must contain the following key: allowed_mint.

Its value is a map of bonds and amount.

The model can at most ask the platform to mint this number of tokens.

The value is decreased or left unchanged after each settle of a game held by the model.

Change the model metadata โ€‹

Only admins can change the model metadata.

python
gameplatform.update_model_metadata(model_id, "allowed_mint", {42: 100_000_000})