Tezos Tickets: a Sports Car That Spends Years in the Garage
Tickets appeared in the Edo update back in February 2021 but Tezos projects have yet to say they use them. Maybe they forgot about tickets because of their linear logic, maybe because of the popularity and simplicity of FA1.2 and FA2: it’s hard to know for sure.
Last week, Marigold developer Pierre-Emmanuel Cornilleau explained how tickets work on Tezos. We decided to use Pierre-Emmanuel’s explanation and gather all available information about tickets in one place.
Why Do We Need Any Tickets When There Are Tokens
There are two types of tokens used in blockchains: native tokens, which have a protocol-based operation mechanism, and conventional tokens, whose operation mechanism is determined by a smart contract.
tez (XTZ) is a native Tezos token. The history of operations with it, the state of user balances, as well as methods like sending tez are stored in the protocol itself.
ctez, kUSD, QuipuSwap LP tokens are conventional tokens. Their operation procedures, description (metadata) and the ledger with user balances (vault) are stored in their smart contracts.
Technically, wallets don’t store any assets. They ask smart contracts whether the vault has a tz1… address record and then display the corresponding balance. When the user sends a token, they call the appropriate smart contract method to change the records in the vault.
For example, this is what the user’s balance looks like in the PLENTY token smart contract:
Tokens have two major disadvantages:
- A single point of failure, i.e. the smart contract. In theory, the contract of any token can be hacked to mint, erase, freeze the tokens at the hacker’s personal discretion;
- the Jakarta update should include an L2 solution for Optimistic Rollups. Tokens are poorly adapted to this: to transfer from L1 to L2, users will have to use bridges to wrap tokens.
Tickets solve these problems. Users store them in their own contract wallets and transfer them between L1 and L2 without wrapping.
How Tickets Work
Tickets are the same as tokens but they are literally transferred between contracts.
A ticket consists of three parts:
- ticketer, i.e. the address of the ticket-creating contract;
- payload or value, i.e. the identifier of the token. It must be of a comparable type: nat, int, string, etc;
- amount, volume or weight, i.e. the number of tickets in the record. It must be nat because an amount cannot be negative.
Ticketer and payload values are fixed at the moment of ticket creation and they identify it. They essentially work as the address and id of the token in the FA2 standard.
The value of amount can be changed using the join and split methods. They only apply to tickets with the same payload and ticketer values. For example, if you apply a join to tickets TICKET(T, P, A1) and TICKET(T, P, A2), you get one ticket TICKET(T, P, A3), where A3 = A1 + A2. Roughly speaking, if two identical contracts issue tickets with the same payload, Tezos will consider them as completely different tickets, because the ticketer values do not match.
A ticketer contract can store a register of users and their tickets in Storage, just like a normal token contract. But you can add a method to the ticketer to create and send tickets to special contract wallets. Thus, the tickets will only exist in the wallets, and further transactions with them will take place with no involvement from the ticketer. What this means in essence is that there is no single point of failure anymore.
A contract wallet is a contract that the user personally creates specifically for the purpose of working with tickets. Tickets cannot be stored on the regular address like “tz…” but only on the “Kt…” ones. Still, L2 addresses can store tickets without problems.
Ticket transfer basically looks as follows:
- The user creates a contract wallet and designates themselves as the administrator.
- The user calls the ticket request function from the ticketer contract and transmits the address of the contract wallet.
- The ticketer checks whether the user has the right to receive a ticket.
- The ticketer creates a ticket with the appropriate value.
- The ticketer calls the wallet’s receive function and passes the ticket as a parameter.
- The wallet adds the ticket to its repository.
It may look like the user can fake any ticket, but this is not true. The Tezos.create_ticket method automatically writes the address of the minting contract to the ticketer parameter. Contract A can’t create tickets that look like it was Contract B that created them, so passing tickets between contracts is actually safe.
How to Use Tickets
Elie Genesburger wrote and tested a specimen of an NFT auction with tickets instead of FA2, and a specimen of a contract wallet.
Meanwhile, Claude Bardot explained with an example how to work with linear types without losing tickets due to the inaccessibility of the DUP command.
Tickets can be used to represent any token in L2 without constant wrapping and unwrapping. For example, a user gives uUSD to a ticketer contract and receives the same number of the uUSD-type tickets. They deposit them in L2, buys other tokens with them, withdraws the tickets, and exchanges them back to uUSD.
Tickets, therefore, can replace multi-sig contracts. For example, a ticketer can allow access to a function only if the user has a certain ticket.
Why Tickets Are Still Not in Use
The first reason is that the community has not yet worked out a standard for a wallet contract and a ticketer contract. The standard should include a description of basic functions: accept a ticket, send it, see the balance, and others. Without it, app developers and regular wallet developers will not be able to implement ticket support well.
The second reason is the fact that FA1.2 and FA2 tokens do their job while developers have standard implementations and lots of examples of contracts to work with tokens. The cost of gas in Tezos is not so big that the community decides to switch to tokens for the sake of saving on transaction fees.
Subscribe and never miss updates from the world of Tezos: