Marigold, Nomadic Labs and TriliTech are pleased to introduce the possibility to transfer tickets from user account to Smart Contracts and the new Michelson Ticket constructor!
This new transfer feature and this new Michelson Ticket constructor will be available in protocol Q.
A bit of history
A few months ago, we have posted a proposal to improve the Ticket transfer UX.
We propose to use the transaction
operation instead of the transfer_ticket
one and also to introduce a new Michelson Ticket
constructor.
-
Switching from
transfer_ticket
totransaction
allowing users to transfer tickets along with any required data from the implicit account to the smart contract directly. -
Introducing new Michelson
Ticket
constructor solves the inability to differentiate tickets from nested pairs just by looking at the transaction payload
Previously, tickets were represented as a nested Pair
, like:
Pair %ticketer (Pair %contents %amount)
In our proposal, Tickets
will now be represented as:
Ticket %ticketer %contents_type %contents %amount
This is way more explicit for users that they are dealing with Tickets! Moreover, we have added a new field contents_type
, to ensure that the provided contents
match the ticket type.
A detailed example
What is better than a detailed example to explain the newly introduced Michelson Ticket constructor?
Using the octez-client
Thanks to the normalize data
command of the octez-client
we can see how the introduction of the new Ticket
constructor works:
First, let’s use the --unparsing-mode Optimized_legacy
which uses the “legacy” nested Pair
representation for Tickets:
$ octez-client normalize data 'Ticket "KT1FHqsvc7vRS3u54L66DdMX4gb6QKqxJ1JW" string "Marigold" 1' of type 'ticket string' --unparsing-mode Optimized_legacy
Warning:
This is NOT the Tezos Mainnet.
Do NOT use your fundraiser keys on this network.
Pair 0x01499568d6d97798fac71c8e5b810e1cc3062a5d9300 (Pair "Marigold" 1)
As we can see, the ticket is normalized as Pair %ticketer (Pair %contents %amount)
Let’s run the exact same command but with the --unparsing-mode Optimized
which uses the new Michelson Ticket
constructor!
$ octez-client normalize data 'Ticket "KT1FHqsvc7vRS3u54L66DdMX4gb6QKqxJ1JW" string "Marigold" 1' of type 'ticket string' --unparsing-mode Optimized
Warning:
This is NOT the Tezos Mainnet.
Do NOT use your fundraiser keys on this network.
Ticket 0x01499568d6d97798fac71c8e5b810e1cc3062a5d9300 string "Marigold" 1
Thank you contents_type
!
In the initial part we introcuded the contents_type
field. Let’s see how it prevents any error whilst using the Ticket
constructor:
$ octez-client normalize data 'Ticket "KT1FHqsvc7vRS3u54L66DdMX4gb6QKqxJ1JW" string "Marigold" 1' of type 'ticket unit' --unparsing-mode Optimized
Warning:
This is NOT the Tezos Mainnet.
Do NOT use your fundraiser keys on this network.
At (unshown) location 0, Type unit is not compatible with type string.
At (unshown) location 0, Type unit is not compatible with type string.
Fatal error:
ill-typed data expression
In the previous command, we try to normalize a Ticket "KT1FHqsvc7vRS3u54L66DdMX4gb6QKqxJ1JW" string "Marigold" 1
which is obviously a ticket string
, but we say the node that its type is ticket unit
. We are blocked.
Let’s see if we try to normalize Ticket "KT1FHqsvc7vRS3u54L66DdMX4gb6QKqxJ1JW" unit "Marigold" 1
saying it is a ticket unit
:
$ octez-client normalize data 'Ticket "KT1FHqsvc7vRS3u54L66DdMX4gb6QKqxJ1JW" unit "Marigold" 1' of type 'ticket unit' --unparsing-mode Optimized
Warning:
This is NOT the Tezos Mainnet.
Do NOT use your fundraiser keys on this network.
At (unshown) location 3, value "Marigold" is invalid for type unit.
At (unshown) location 3, unexpected string, only a primitive
can be used here.
Fatal error:
ill-typed data expression
End to end test scenario
To illustrate the new UX, let’s explain an end-to-end test scenario we have in the Tezos codebase:
Tests that an implicit account can send a single ticket to originated using the [Transfer] manager operation.
In details, the test scenario does:
-
Setup: The test initializes by setting up the Tezos node and client, enabling direct ticket spending to facilitate ticket transfers.
-
Ticket Deposit: Tickets are deposited into an implicit account. This involves originating a contract referred to as ticketer, which serves as the destination for ticket deposits.
-
Ticket Transfer: The test ensures that the implicit account holds the deposited ticket. This step validates the successful transfer of tickets to the implicit account.
-
Originating Contract: A new contract, known as bag, is originated on the Tezos blockchain. This contract is designed to store tickets that are sent to its designated entry point called
save
. -
Ticket Transfer to Originated Contract: The test executes a transfer operation to move tickets from the implicit account to the newly originated contract (bag). This operation is facilitated by the Tezos transaction manager.
-
Assertion: Assertions are performed to validate the ticket balances after the transfer. The test ensures that the ticket balance in the implicit account is reduced to zero while confirming that the bag contract now holds the transferred ticket.
Detailed commands run for this test scenario
Here, we will only focus on the commands useful to transfer the ticket and verify the balance.
As explained in the previous section, before the tranfer, we have to
- setup the node,
- originate the contract,
- deposit the initial ticket.
The initial deposit:
$ octez-client --endpoint http://127.0.0.1:62659 \
--base-dir /tmp/tezt-36584/1/client1 \
get ticket balance for bootstrap1 \
with ticketer KT1XU7JNShJpKXuutHacmsQXdd1EmfXozEb3 \
and type string and content '"Ticket"'
1
Now, we can tranfer the ticket from bootstrap1
(implicit account) to KT198aGhEPaTusD75SSD8qVpQGzkp3tYqacq
(smart contract)!
Transfer the ticket!
$ octez-client --endpoint http://127.0.0.1:62659 \
--base-dir /tmp/tezt-36584/1/client1 --wait none \
transfer 0 from bootstrap1 to KT198aGhEPaTusD75SSD8qVpQGzkp3tYqacq \
--burn-cap 1 --entrypoint save \
--arg 'Ticket "KT1XU7JNShJpKXuutHacmsQXdd1EmfXozEb3" string "Ticket" 1'
Check the balance!
We have two balances to check to ensure the transfer had been successfully and well done:
bootstrap1
must have exactly 0 ticket with content"Ticket"
,KT198aGhEPaTusD75SSD8qVpQGzkp3tYqacq
must have exactly one ticket with content"Ticket"
$ octez-client --endpoint http://127.0.0.1:62659 \
--base-dir /tmp/tezt-36584/1/client1 \
get ticket balance for bootstrap1 \
with ticketer KT1XU7JNShJpKXuutHacmsQXdd1EmfXozEb3 \
and type string and content '"Ticket"'
0
First balance is perfect, let’s see the second one…
$ octez-client --endpoint http://127.0.0.1:62659 \
--base-dir /tmp/tezt-36584/1/client1 \
get ticket balance for KT198aGhEPaTusD75SSD8qVpQGzkp3tYqacq \
with ticketer KT1XU7JNShJpKXuutHacmsQXdd1EmfXozEb3 \
and type string and content '"Ticket"'
1
Yes!!!
Conclusion
In this blog post, we have introduced two new features for tickets:
- Transfer tickets from user account to smart contract
- New Michelson
Ticket
constructor
Thanks to these two new features, a whole new era is ready for tickets!