diff --git a/gitlab-pages/docs/intro/ligo-intro.md b/gitlab-pages/docs/intro/ligo-intro.md
index 5cdabec930..4f5fbfdcaa 100644
--- a/gitlab-pages/docs/intro/ligo-intro.md
+++ b/gitlab-pages/docs/intro/ligo-intro.md
@@ -98,7 +98,7 @@ For a quick overview, [get-started](../tutorials/getting-started) is a good choi
Your choice to learn LIGO is already available:
- Read [basics](../language-basics/types) to have a basic comprehension
-- Write your first [smart contract](../tutorials/taco-shop/tezos-taco-shop-smart-contract).
+- Write your first [smart contract](../tutorials/taco-shop/selling-tacos).
- Others resources are available on [marigold.dev](https://www.marigold.dev/learn)
### Do you want to build a production-ready project?
diff --git a/gitlab-pages/docs/tutorials/getting-started/getting-started.md b/gitlab-pages/docs/tutorials/getting-started/getting-started.md
index 04b97cf553..ea1c8c2903 100644
--- a/gitlab-pages/docs/tutorials/getting-started/getting-started.md
+++ b/gitlab-pages/docs/tutorials/getting-started/getting-started.md
@@ -579,4 +579,4 @@ octez-client get contract storage for counter
Now you have a simple LIGO smart contract and can test it, deploy it, and call it.
You can use it as a starting point to write your own contracts and experiment with LIGO.
-You can also continue with the [Taco shop tutorial](../taco-shop/tezos-taco-shop-smart-contract) to learn more about programming with LIGO.
+You can also continue with the [Taco shop tutorial](../taco-shop/selling-tacos) to learn more about programming with LIGO.
diff --git a/gitlab-pages/docs/tutorials/taco-shop/getting-payouts.md b/gitlab-pages/docs/tutorials/taco-shop/getting-payouts.md
new file mode 100644
index 0000000000..4f5fb490ad
--- /dev/null
+++ b/gitlab-pages/docs/tutorials/taco-shop/getting-payouts.md
@@ -0,0 +1,380 @@
+---
+title: "Part 3: Getting the payouts"
+pagination_next: null
+---
+
+Now that the customer-facing entrypoint of the contract is ready, you can set up the administrator-related entrypoint.
+In this case, Pedro needs a way to reset the stock of tacos and send the tez from the contract to his account.
+You could do this in two entrypoints, but for simplicity this tutorial shows how to do both of these things in one entrypoint named `payout`.
+
+## Adding administrator information
+
+Also for the sake of simplicity, the contract provides no way to change Pedro's account address after the contract is deployed.
+In production applications, the address of the administrator should be in the contract storage and an entrypoint should allow the current administrator to change the administrator address.
+As it is, this contract cannot change the administrator address after it is deployed, so use caution.
+
+
+
+1. In the `payout` entrypoint, add this code to verify that the administrator is calling the entrypoint:
+
+ ```jsligo skip
+ // Ensure that only the admin can call this entrypoint
+ if (Tezos.get_sender() != storage.admin_address) {
+ failwith("Only the admin can call this entrypoint");
+ }
+ ```
+
+ The function `Tezos.get_sender` returns the address of the account that called the smart contract.
+
+1. Add this code to generate the operation that sends tez to the administrator account:
+
+ ```jsligo skip
+ // Create contract object that represents the target account
+ const receiver_contract = $match(Tezos.get_contract_opt(storage.admin_address), {
+ "Some": (contract) => contract,
+ "None": () => failwith("Couldn't find account"),
+ });
+
+ // Create operation to send tez
+ const payout_operation = Tezos.Operation.transaction(unit, Tezos.get_balance(), receiver_contract);
+ ```
+
+ Sending tez to a user account means treating the user account as though it is a smart contract account.
+ This way, sending tez to a user account works in the same way as sending tez to a smart contract.
+
+ The `Tezos.Operation.transaction` function creates a Tezos transaction.
+ There are many kinds of internal transactions in Tezos, but most smart contracts deal with these transactions:
+
+ - Transferring tez to another account
+ - Calling an entrypoint on a smart contract
+
+ Calling an entrypoint on a smart contract (either the current contract or another contract) is beyond the scope of this tutorial.
+ For information, see [Calling a contract](../../syntax/contracts/operation#calling-a-contract).
+
+ The `Tezos.Operation.transaction` function takes these parameters:
+
+ 1. The parameter to pass, in this case `unit`, which means no value
+ 1. The amount of tez to include with the transaction, in this case all of the tez the contract has, denoted by the `Tezos.get_balance` function
+ 1. The address of the target contract
+
+1. Add this code to calculate the new value of the storage, using the existing admin address and the default taco data:
+
+ ```jsligo skip
+ // Restore stock of tacos
+ const new_storage: storage = {
+ admin_address: storage.admin_address,
+ taco_data: default_taco_data,
+ };
+ ```
+
+1. Replace the `payout` entrypoint's `return` statement with this code:
+
+ ```jsligo skip
+ return [[payout_operation], new_storage];
+ ```
+
+ Creating the transaction is not enough to run it; you must return it in the list of operations at the end of the entrypoint.
+
+The complete entrypoint looks like this:
+
+```jsligo skip
+// @entry
+const payout = (_u: unit, storage: storage): [
+ list,
+ storage
+ ] => {
+
+ // Ensure that only the admin can call this entrypoint
+ if (Tezos.get_sender() != storage.admin_address) {
+ failwith("Only the admin can call this entrypoint");
+ }
+
+ // Create contract object that represents the target account
+ const receiver_contract = $match(Tezos.get_contract_opt(storage.admin_address), {
+ "Some": (contract) => contract,
+ "None": () => failwith("Couldn't find account"),
+ });
+
+ // Create operation to send tez
+ const payout_operation = Tezos.Operation.transaction(unit, Tezos.get_balance(), receiver_contract);
+
+ // Restore stock of tacos
+ const new_storage: storage = {
+ admin_address: storage.admin_address,
+ taco_data: default_taco_data,
+ };
+
+ return [[payout_operation], new_storage];
+}
+```
+
+
+
+
+
+1. In the `payout` entrypoint, add this code to verify that the administrator is calling the entrypoint:
+
+ ```cameligo skip
+ (* Ensure that only the admin can call this entrypoint *)
+ let _ = if (Tezos.get_sender () <> storage.admin_address) then
+ failwith "Only the admin can call this entrypoint" in
+ ```
+
+ The function `Tezos.get_sender` returns the address of the account that called the smart contract.
+
+1. Add this code to generate the operation that sends tez to the administrator account:
+
+ ```cameligo skip
+ (* Create contract object that represents the target account *)
+ let receiver_contract = match Tezos.get_contract_opt storage.admin_address with
+ | Some contract -> contract
+ | None -> failwith "Couldn't find account" in
+
+ (* Create operation to send tez *)
+ let payout_operation = Tezos.Operation.transaction unit (Tezos.get_balance ()) receiver_contract in
+ ```
+
+ Sending tez to a user account means treating the user account as though it is a smart contract account.
+ This way, sending tez to a user account works in the same way as sending tez to a smart contract.
+
+ The `Tezos.Operation.transaction` function creates a Tezos transaction.
+ There are many kinds of internal transactions in Tezos, but most smart contracts deal with these transactions:
+
+ - Transferring tez to another account
+ - Calling an entrypoint on a smart contract
+
+ Calling an entrypoint on a smart contract (either the current contract or another contract) is beyond the scope of this tutorial.
+ For information, see [Calling a contract](../../syntax/contracts/operation#calling-a-contract).
+
+ The `Tezos.Operation.transaction` function takes these parameters:
+
+ 1. The parameter to pass, in this case `unit`, which means no value
+ 1. The amount of tez to include with the transaction, in this case all of the tez the contract has, denoted by the `Tezos.get_balance` function
+ 1. The address of the target contract
+
+1. Add this code to calculate the new value of the storage, using the existing admin address and the default taco data:
+
+ ```cameligo skip
+ (* Restore stock of tacos *)
+ let new_storage : storage = {
+ admin_address = storage.admin_address;
+ taco_data = default_taco_data
+ } in
+ ```
+
+1. Replace the last line of the `payout` entrypoint with this code:
+
+ ```cameligo skip
+ [payout_operation], new_storage
+ ```
+
+ Creating the transaction is not enough to run it; you must return it in the list of operations at the end of the entrypoint.
+
+The complete entrypoint looks like this:
+
+```cameligo skip
+[@entry]
+let payout (_u : unit) (storage : storage) : operation list * storage =
+
+ (* Ensure that only the admin can call this entrypoint *)
+ let _ = if (Tezos.get_sender () <> storage.admin_address) then
+ failwith "Only the admin can call this entrypoint" in
+
+ (* Create contract object that represents the target account *)
+ let receiver_contract = match Tezos.get_contract_opt storage.admin_address with
+ | Some contract -> contract
+ | None -> failwith "Couldn't find account" in
+
+ (* Create operation to send tez *)
+ let payout_operation = Tezos.Operation.transaction unit (Tezos.get_balance ()) receiver_contract in
+
+ (* Restore stock of tacos *)
+ let new_storage : storage = {
+ admin_address = storage.admin_address;
+ taco_data = default_taco_data
+ } in
+
+ [payout_operation], new_storage
+```
+
+
+
+That's all you need to do to reset the storage and send the contract's tez to the administrator.
+If you want to extend this logic, try separating the `payout` entrypoint into separate entrypoints for paying out the tez and resetting the stock of tacos.
+
+## Testing the new entrypoint
+
+Of course, after you implement the `payout` entrypoint, you should add tests for it.
+
+
+
+1. At the end of the test function, add this code to get the current balance of Pedro's account before calling the entrypoint:
+
+ ```jsligo skip
+ // Test the payout entrypoint as the administrator
+ const admin_balance_before = Test.Address.get_balance(admin_address);
+ ```
+
+1. Add this code to set the account that smart contract calls come from in the test scenario:
+
+ ```jsligo skip
+ Test.State.set_source(admin_address);
+ ```
+
+ Now when you call the `Test.Contract.transfer` function, the transaction comes from Pedro's account.
+
+1. Add this code to call the `payout` entrypoint and verify that the storage was updated, as in previous tests:
+
+ ```jsligo skip
+ const payout_result =
+ Test.Contract.transfer(
+ Test.Typed_address.get_entrypoint("payout", contract.taddr),
+ unit,
+ 0 as tez
+ );
+ $match(payout_result, {
+ "Success": (_s) => (() => {
+ const storage = Test.Typed_address.get_storage(contract.taddr);
+ // Check that the stock has been reset
+ Assert.assert(
+ eq_in_map(
+ Map.find(1 as nat, TacoShop.default_taco_data),
+ storage.taco_data,
+ 1 as nat
+ ));
+ Assert.assert(
+ eq_in_map(
+ Map.find(2 as nat, TacoShop.default_taco_data),
+ storage.taco_data,
+ 2 as nat
+ ));
+ Test.IO.log("Successfully reset taco storage");
+ })(),
+ "Fail": (_err) => failwith("Failed to reset taco storage"),
+ });
+ ```
+
+1. Add this code to verify that Pedro's account received the tez from the contract:
+
+ ```jsligo skip
+ // Check that the admin account got a payout
+ const admin_balance_after = Test.Address.get_balance(admin_address);
+ Assert.assert(Test.Compare.lt(admin_balance_before, admin_balance_after));
+ ```
+
+ The exact amounts differ because calling the `payout` entrypoint costs a small fee, but this code verifies that Pedro's account has more tez in it after calling the `payout` entrypoint.
+
+1. Add this code to generate a test account and verify that it can't call the `payout` entrypoint because it is not the administrator:
+
+ ```jsligo skip
+ // Verify that the entrypoint fails if called by someone else
+ const other_user_account = Test.Account.address(1 as nat);
+ Test.State.set_source(other_user_account);
+ const failed_payout_result =
+ Test.Contract.transfer(
+ Test.Typed_address.get_entrypoint("payout", contract.taddr),
+ unit,
+ 0 as tez
+ );
+ $match(failed_payout_result, {
+ "Success": (_s) => failwith("A non-admin user was able to call the payout entrypoint"),
+ "Fail": (_err) => Test.IO.log("Successfully prevented a non-admin user from calling the payout entrypoint"),
+ });
+ ```
+
+1. Run the test with `ligo run test taco_shop.jsligo` and verify that the test runs successfully.
+
+
+
+
+
+1. At the end of the test function, replace the last block with this code so the function can continue:
+
+ ```cameligo skip
+ let () = match fail_result with
+ | Success _s -> failwith "Test was able to buy a taco for the wrong price"
+ | Fail _err -> Test.IO.log "Contract successfully blocked purchase with incorrect price" in
+ ```
+
+1. Add this code to get the current balance of Pedro's account before calling the entrypoint:
+
+ ```cameligo skip
+ (* Test the payout entrypoint as the administrator *)
+ let admin_balance_before = Test.Address.get_balance admin_address in
+ ```
+
+1. Add this code to set the account that smart contract calls come from in the test scenario:
+
+ ```cameligo skip
+ let () = Test.State.set_source admin_address in
+ ```
+
+ Now when you call the `Test.Contract.transfer` function, the transaction comes from Pedro's account.
+
+1. Add this code to call the `payout` entrypoint and verify that the storage was updated, as in previous tests:
+
+ ```cameligo skip
+ let payout_result = Test.Contract.transfer
+ (Test.Typed_address.get_entrypoint "payout" contract.taddr)
+ unit
+ 0tez
+ in
+ let () = match payout_result with
+ | Success _s -> let storage = Test.Typed_address.get_storage contract.taddr in
+ let () = Assert.assert
+ (eq_in_map (Map.find 1n TacoShop.default_taco_data)
+ storage.taco_data
+ 1n) in
+ let () = Assert.assert
+ (eq_in_map (Map.find 2n TacoShop.default_taco_data)
+ storage.taco_data
+ 2n) in
+ Test.IO.log "Successfully reset taco storage"
+ | Fail _err -> failwith "Failed to reset taco storage" in
+ ```
+
+1. Add this code to verify that Pedro's account received the tez from the contract:
+
+ ```cameligo skip
+ (* Check that the admin account got a payout *)
+ let admin_balance_after = Test.Address.get_balance admin_address in
+ let () = Assert.assert (Test.Compare.lt admin_balance_before admin_balance_after) in
+ ```
+
+ The exact amounts differ because calling the `payout` entrypoint costs a small fee, but this code verifies that Pedro's account has more tez in it after calling the `payout` entrypoint.
+
+1. Add this code to generate a test account and verify that it can't call the `payout` entrypoint because it is not the administrator:
+
+ ```cameligo skip
+ (* Verify that the entrypoint fails if called by someone else *)
+ let other_user_account = Test.Account.address 1n in
+ let _ = Test.State.set_source other_user_account in
+ let failed_payout_result = Test.Contract.transfer
+ (Test.Typed_address.get_entrypoint "payout" contract.taddr)
+ unit
+ 0tez
+ in
+ match failed_payout_result with
+ | Success _s -> failwith "A non-admin user was able to call the payout entrypoint"
+ | Fail _err -> Test.IO.log "Successfully prevented a non-admin user from calling the payout entrypoint"
+ ```
+
+1. Run the test with `ligo run test taco_shop.mligo` and verify that the test runs successfully.
+
+
+
+Now you can allow different users to do different things in the contract.
+
+## Conclusion
+
+Now you have a contract that Pedro can use to sell tacos and manage the profits and the taco stock.
+From here you can expand the contract in many ways, such as:
+
+- Adding more types of tacos
+- Changing how the price of tacos is calculated
+- Expanding the administrator functionality
+- Accepting more than the price of the taco as a tip
+- Adding more tests
+
+You can also try deploying the contract to a test network and trying it in a real Tezos environment.
+For a tutorial that covers deploying a contract, see [Deploy a smart contract](https://docs.tezos.com/tutorials/smart-contract) on docs.tezos.com.
diff --git a/gitlab-pages/docs/tutorials/taco-shop/selling-tacos.md b/gitlab-pages/docs/tutorials/taco-shop/selling-tacos.md
new file mode 100644
index 0000000000..50e5ef1008
--- /dev/null
+++ b/gitlab-pages/docs/tutorials/taco-shop/selling-tacos.md
@@ -0,0 +1,771 @@
+---
+title: "Part 1: Creating a contract"
+pagination_prev: null
+---
+
+import Syntax from '@theme/Syntax';
+
+
+
+Meet Pedro, our artisan taco chef, who has decided to open a Taco shop on the Tezos blockchain, using a smart contract.
+
+In this tutorial, to help Pedro open his dream taco shop, you will implement a smart contract that manages supply, pricing, and sales of his tacos to the consumers.
+This scenario is ideal for a smart contract because smart contracts behave much like vending machines: users send requests to them along with information and money.
+If the request is correct, the smart contract does something in response, in this case giving the customer an imaginary taco.
+
+
+
+
+
+## Learning objectives
+
+In this tutorial, you will learn how to:
+
+- Set up a smart contract in JsLIGO or CameLIGO
+- Define the storage for the contract
+- Define what requests the contract can accept and how it behaves
+- Implement the code that handles these requests
+- Write tests that ensure that the contract behaves correctly
+
+## Prerequisites
+
+Before you begin, install LIGO as described in [Installation](../../intro/installation).
+
+Optionally, you can also set up your editor to work with LIGO as described in [Editor Support](../../intro/editor-support).
+
+## Syntaxes
+
+LIGO has two syntaxes:
+
+- JsLIGO is inspired by TypeScript/JavaScript, intended for web developers
+
+- CameLIGO is inspired by OCaml, intended for functional programmers
+
+The syntaxes do the same thing and have nearly all the same features, so which one you choose depends on your preference or programming background.
+You can use either syntax for this tutorial, but you must use the same syntax for the entire contract.
+Use the **Syntax Preference** slider at the top left of this page to select the syntax to use.
+
+## Pricing
+
+Pedro sells two kinds of tacos: **el Clásico** and the **Especial del Chef**.
+His tacos are a rare delicacy and he has a finite amount of each kind, so the price goes up as the stock for the day depletes.
+Taco prices are in tez, the currency of the Tezos blockchain.
+
+The cost for one taco is the maximum price for the taco divided by the total number of tacos, as in this formula:
+
+```
+current_purchase_price = max_price / available_stock
+```
+
+For example, the maximum price for an el Clásico taco is 50 tez.
+This table shows the price when there are certain amounts of tacos left:
+
+| Number of tacos available | Maximum price | Purchase price |
+|---|---|---|
+| 50 | 50 tez | 1 tez |
+| 20 | 50 tez | 2.5 tez |
+| 5 | 50 tez | 10 tez |
+| 1 | 50 tez | 50 tez |
+
+The maximum price for an Especial del Chef taco is 75 tez, so the prices are different, as in this table:
+
+| Number of tacos available | Maximum price | Purchase price |
+|---|---|---|
+| 20 | 75 tez | 3.75 tez |
+| 10 | 75 tez | 7.5 tez|
+| 5 | 75 tez | 15 tez |
+| 1 | 75 tez | 75 tez |
+
+## Setting up the data storage
+
+Smart contracts can store persistent data.
+Only the contract itself can write to its data, but the data is visible to outside users.
+This data can be in many data types, including simple data types like numbers, Boolean values, and strings, and complex data types like arrays and maps.
+
+Because the cost of a taco is determined by a formula, the contract needs to store only two pieces of data for each type of taco: the maximum price and the number of tacos currently in stock.
+LIGO contracts store this type of data in a data type called a *map*, which is a key-value store where each key is the same data type and each value is the same data type.
+Maps are flexible, so you can add and remove elements.
+
+The key for this map is a natural number (also known as a *nat*, an integer zero or greater) and the value is a [Record](../../data-types/records) data type that has two fields: a natural number for the current stock of tacos and a tez amount for the maximum price.
+In table format, the map data looks ike this:
+
+Key | Value
+--- | ---
+1 | `{ current_stock: 50, maximum_price: 50tez }`
+2 | `{ current_stock: 20, maximum_price: 75tez }`
+
+Follow these steps to set up the data storage for your contract:
+
+
+
+1. Anywhere on your computer, create a folder to store your work for this tutorial with a name such as `TacoShopTutorial`.
+
+1. In the folder, create a file named `taco_shop.jsligo` to store the code of the smart contract.
+You can create and edit this file in any text editor.
+
+1. In the file, create a type named `taco_supply` that represents the value of the map, consisting of a nat for the number of tacos and a tez value for the maximum price:
+
+ ```jsligo skip
+ export type taco_supply = { current_stock: nat, max_price: tez };
+ ```
+
+1. Create a map type named `taco_data`, with the key a nat and the value the `taco_supply` type:
+
+ ```jsligo skip
+ export type taco_data = map;
+ ```
+
+ This map can contain the supply and max price for any number of tacos, indexed by a natural number key.
+
+1. Create an address type to store Pedro's account address, which allows him to lock some features of the contract behind an administrator account:
+
+ ```jsligo skip
+ export type admin_address = address;
+ ```
+
+1. Create a type to represent the storage for the contract.
+In this case, the contract needs to store the taco data map and the administrator address, so the overall contract storage contains those two values:
+
+ ```jsligo skip
+ export type storage = {
+ admin_address: admin_address,
+ taco_data: taco_data,
+ };
+ ```
+
+1. Create a constant to represent the starting values for the taco data map:
+
+ ```jsligo skip
+ export const default_taco_data: taco_data = Map.literal([
+ [1 as nat, { current_stock: 50 as nat, max_price: 50 as tez }],
+ [2 as nat, { current_stock: 20 as nat, max_price: 75 as tez }]
+ ]);
+ ```
+
+ Note that the natural numbers are indicated with an `as nat` after the number; otherwise, LIGO assumes that numbers are integers.
+ Similarly, the maximum prices of the tacos have `as tez` to indicate that they are amounts of tez.
+
+1. To keep the code for the contract organized, put the types and values in a namespace named `TacoShop`.
+The contract looks like this so far:
+
+ ```jsligo skip
+ namespace TacoShop {
+ export type taco_supply = { current_stock: nat, max_price: tez };
+ export type taco_data = map;
+ export type admin_address = address;
+ export type storage = {
+ admin_address: admin_address,
+ taco_data: taco_data,
+ };
+
+ export const default_taco_data: taco_data = Map.literal([
+ [1 as nat, { current_stock: 50 as nat, max_price: 50 as tez }],
+ [2 as nat, { current_stock: 20 as nat, max_price: 75 as tez }]
+ ]);
+
+ };
+ ```
+
+
+
+
+
+1. Anywhere on your computer, create a folder to store your work for this tutorial with a name such as `TacoShopTutorial`.
+
+1. In the folder, create a file named `taco_shop.mligo` to store the code of the smart contract.
+You can create and edit this file in any text editor.
+
+1. In the file, create a type named `taco_supply` that represents the value of the map, consisting of a nat for the number of tacos and a tez value for the maximum price:
+
+ ```cameligo skip
+ type taco_supply = { current_stock: nat; max_price: tez }
+ ```
+
+1. Create a map type named `taco_data`, with the key a nat and the value the `taco_supply` type:
+
+ ```cameligo skip
+ type taco_data = (nat, taco_supply) map
+ ```
+
+ This map can contain the supply and max price for any number of tacos, indexed by a natural number key.
+
+1. Create an address type to store Pedro's account address, which allows him to lock some features of the contract behind an administrator account:
+
+ ```cameligo skip
+ type admin_address = address
+ ```
+
+1. Create a type to represent the storage for the contract.
+In this case, the contract needs to store the taco data map and the administrator address, so the overall contract storage contains those two values:
+
+ ```cameligo skip
+ type storage = {
+ admin_address: admin_address;
+ taco_data: taco_data;
+ }
+ ```
+
+1. Create a variable to represent the starting values for the taco data map:
+
+ ```cameligo skip
+ let default_taco_data: taco_data = Map.literal [
+ (1n, { current_stock = 50n; max_price = 50tez });
+ (2n, { current_stock = 20n; max_price = 75tez });
+ ]
+ ```
+
+ Note that the natural numbers are indicated with an `n` after the number; otherwise, LIGO assumes that numbers are integers.
+ Similarly, the maximum prices of the tacos are suffixed with `tez` to indicate that they are amounts of tez.
+
+1. To keep the code for the contract organized, put the types and values in a module named `TacoShop`.
+The contract looks like this so far:
+
+ ```cameligo skip
+ module TacoShop = struct
+
+ type taco_supply = { current_stock: nat; max_price: tez }
+ type taco_data = (nat, taco_supply) map
+ type admin_address = address
+ type storage = {
+ admin_address: admin_address;
+ taco_data: taco_data;
+ }
+
+ let default_taco_data: taco_data = Map.literal [
+ (1n, { current_stock = 50n; max_price = 50tez });
+ (2n, { current_stock = 20n; max_price = 75tez });
+ ]
+
+ end
+ ```
+
+
+
+## Getting the price of tacos
+
+Because the price of tacos changes, it'll be helpful to have a function to get the current price of a certain kind of taco.
+
+
+
+Add this function inside the namespace, immediately after the `default_taco_data` constant:
+
+```jsligo skip
+// Internal function to get the price of a taco
+const get_taco_price_internal = (taco_kind_index: nat, taco_data: taco_data): tez => {
+ const taco_kind: taco_supply =
+ $match (Map.find_opt(taco_kind_index, taco_data), {
+ "Some": (kind) => kind,
+ "None": () => failwith("Unknown kind of taco"),
+ });
+ return taco_kind.max_price / taco_kind.current_stock;
+}
+```
+
+
+
+
+
+Add this function inside the module, immediately after the `default_taco_data` variable:
+
+```cameligo skip
+(* Internal function to get the price of a taco *)
+let get_taco_price_internal (taco_kind_index : nat) (taco_data : taco_data) : tez =
+ let taco_kind : taco_supply =
+ match Map.find_opt taco_kind_index taco_data with
+ | Some kind -> kind
+ | None -> failwith "Unknown kind of taco"
+ in
+ taco_kind.max_price / taco_kind.current_stock
+```
+
+
+
+This code uses the `Map.find_opt` function to get an entry from a map based on a key.
+It returns an [option](../../data-types/variants#options) value, which is a data type that LIGO uses to handle cases where a value may not exist.
+In this case, the option has the value for that key if the key exists or a `None` value if the key does not exist.
+If the `taco_kind_index` parameter is not a valid taco ID, the transaction fails.
+
+This is an internal function, so external callers can't call it directly.
+Later, you will add a way for external callers to get the current price of a taco.
+
+## Selling tacos
+
+Contracts have one or more _entrypoints_, which are a kind of function that clients can call, like endpoints in an API or functions or methods in many other programming languages.
+A contract can have any number of internal functions, but only the functions designated as entrypoints can be called by outside consumers and other contracts.
+
+The contract you create in this tutorial has two entrypoints:
+
+- An entrypoint named `buy_taco` which accepts the type of taco to buy and the price of the taco and deducts that type of taco from the current stock in storage
+- An entrypoint named `payout` that sends the tez in the contract to Pedro and restocks the supply of tacos
+
+As described in [Entrypoints](../../syntax/contracts/entrypoints), entrypoints must follow a specific signature to be compiled as entrypoints:
+
+
+
+- Entrypoints are functions marked with the `@entry` decorator, which (when used in a namespace) must be in a comment immediately before the function
+- Entrypoints receive a parameter from the caller and the current state of the contract storage
+- Entrypoints return a tuple consisting of a list of operations to run (such as calls to other smart contracts or transfers of tez) and the new state of the contract storage
+
+1. In the smart contract file, within the `TacoShop` namespace, add this stub of an entrypoint:
+
+ ```jsligo skip
+ // Buy a taco
+ // @entry
+ const buy_taco = (taco_kind_index: nat, storage: storage): [
+ list,
+ storage
+ ] => {
+
+ // Entrypoint logic goes here
+
+ return [[], updated_storage];
+ }
+ ```
+
+ Your IDE may show an error that the `updated_storage` value is not defined, but you can ignore this error for now because you will define it in the next few steps.
+
+ To call this entrypoint, the caller passes a nat to indicate the type of taco.
+ The function automatically receives the current state of the storage as the last parameter.
+ The line `return [[], updated_storage];` returns an empty list of operations to run and the new state of the storage.
+ In the next few steps, you add logic to verify that the caller sent the correct price and to deduct the taco from the current stock.
+
+1. Within the entrypoint, add code to get the admin address and the taco data by destructuring the storage parameter:
+
+ ```jsligo skip
+ const { admin_address, taco_data } = storage;
+ ```
+
+1. After this code, add code to get the type of taco that the caller requested based on the `taco_kind_index` parameter:
+
+ ```jsligo skip
+ // Retrieve the kind of taco from the contracts storage or fail
+ const taco_kind: taco_supply =
+ $match (Map.find_opt(taco_kind_index, taco_data), {
+ "Some": (kind) => kind,
+ "None": () => failwith("Unknown kind of taco"),
+ });
+ ```
+
+1. After the code you just added, add this code to get the current price of a taco:
+
+ ```jsligo skip
+ // Get the current price of this type of taco
+ const current_purchase_price = get_taco_price_internal(taco_kind_index, taco_data);
+ ```
+
+1. Add this code to verify that the caller sent the correct amount of tez with the transaction.
+It uses the `Tezos.get_amount()` function, which returns the amount of tez that the caller sent:
+
+ ```jsligo skip
+ // Verify that the caller sent the correct amount of tez
+ if ((Tezos.get_amount()) != current_purchase_price) {
+ return failwith("Sorry, the taco you are trying to purchase has a different price");
+ }
+ ```
+
+1. Add this code to verify that there is at least one taco in stock:
+
+ ```jsligo skip
+ // Verify that there is at least one of this type of taco
+ if (taco_kind.current_stock == 0 as nat) {
+ return failwith("Sorry, we are out of this type of taco");
+ }
+ ```
+
+1. Add this code to calculate the updated taco data map and put it in the `updated_taco_data` constant:
+
+ ```jsligo skip
+ // Update the storage with the new quantity of tacos
+ const updated_taco_data: taco_data = Map.update(
+ taco_kind_index,
+ ["Some" as "Some", {...taco_kind, current_stock: abs(taco_kind.current_stock - 1) }],
+ taco_data);
+ ```
+
+ This code uses the `Map.update` function to create a new version of the map with an updated record.
+ In this case, the new map updates the stock of the specified type of taco to be one less.
+ It uses the `abs` function to ensure that the new stock of tacos is a nat, because subtraction yields an integer.
+
+1. Create the new value of the contract storage, including the admin address and the updated taco data:
+
+ ```jsligo skip
+ const updated_storage: storage = {
+ admin_address: admin_address,
+ taco_data: updated_taco_data,
+ };
+ ```
+
+ The next line is the line `return [[], updated_taco_data];`, which you added when you stubbed in the entrypoint code earlier.
+
+ Now the `buy_taco` entrypoint updates the stock in storage to indicate that it has one less of that type of taco.
+ The contract automatically accepts the tez that is included with the transaction.
+
+1. After the code for the `buy_taco` entrypoint, stub in the code for the entrypoint that allows Pedro to retrieve the tez in the contract, which you will add in a later section:
+
+ ```jsligo skip
+ // @entry
+ const payout = (_u: unit, storage: storage): [
+ list,
+ storage
+ ] => {
+
+ // Entrypoint logic goes here
+
+ return [[], storage];
+ }
+ ```
+
+ Currently this entrypoint does nothing, but you will add code for it later.
+
+
+
+
+
+- Entrypoints are functions marked with the `@entry` attribute
+- Entrypoints receive a parameter from the caller and the current state of the contract storage
+- Entrypoints return a tuple consisting of a list of operations to run (such as calls to other smart contracts or transfers of tez) and the new state of the contract storage
+
+1. In the smart contract file, within the `TacoShop` module, add this stub of an entrypoint:
+
+ ```cameligo skip
+ (* Buy a taco *)
+ [@entry]
+ let buy_taco (taco_kind_index : nat) (storage : storage) : operation list * storage =
+
+ (* Entrypoint logic goes here *)
+
+ [], updated_storage
+ ```
+
+ Your IDE may show an error that the `updated_storage` value is not defined, but you can ignore this error for now because you will define it in the next few steps.
+
+ To call this entrypoint, the caller passes a nat to indicate the type of taco.
+ The function automatically receives the current state of the storage as the last parameter.
+ The line `[], updated_storage` returns an empty list of operations to run and the new state of the storage.
+ In the next few steps, you add logic to verify that the caller sent the correct price and to deduct the taco from the current stock.
+
+1. Within the entrypoint, add code to get the admin address and the taco data by destructuring the storage parameter:
+
+ ```cameligo skip
+ let { admin_address; taco_data } = storage in
+ ```
+
+1. After this code, add code to get the type of taco that the caller requested based on the `taco_kind_index` parameter:
+
+ ```cameligo skip
+ (* Retrieve the kind of taco from the contracts storage or fail *)
+ let taco_kind : taco_supply =
+ match Map.find_opt taco_kind_index taco_data with
+ | Some kind -> kind
+ | None -> failwith "Unknown kind of taco" in
+ ```
+
+1. After the code you just added, add this code to get the current price of a taco:
+
+ ```cameligo skip
+ (* Get the current price of this type of taco *)
+ let current_purchase_price = get_taco_price_internal taco_kind_index taco_data in
+ ```
+
+1. Add this code to verify that the caller sent the correct amount of tez with the transaction.
+It uses the `Tezos.get_amount()` function, which returns the amount of tez that the caller sent:
+
+ ```cameligo skip
+ (* Verify that the caller sent the correct amount of tez *)
+ let _ = if (Tezos.get_amount () <> current_purchase_price) then
+ failwith "Sorry, the taco you are trying to purchase has a different price" in
+ ```
+
+1. Add this code to verify that there is at least one taco in stock:
+
+ ```cameligo skip
+ (* Verify that there is at least one of this type of taco *)
+ let _ = if (taco_kind.current_stock = 0n) then
+ failwith "Sorry, we are out of this type of taco" in
+ ```
+
+1. Add this code to calculate the updated taco data map and put it in the `updated_taco_data` variable:
+
+ ```cameligo skip
+ (* Update the storage with the new quantity of tacos *)
+ let updated_taco_data : taco_data = Map.update
+ taco_kind_index
+ (Some { taco_kind with current_stock = abs (taco_kind.current_stock - 1n) })
+ taco_data in
+ ```
+
+ This code uses the `Map.update` function to create a new version of the map with an updated record.
+ In this case, the new map updates the stock of the specified type of taco to be one less.
+ It uses the `abs` function to ensure that the new stock of tacos is a nat, because subtraction yields an integer.
+
+1. Create the new value of the contract storage, including the admin address and the updated taco data:
+
+ ```cameligo skip
+ let updated_storage : storage = {
+ admin_address = admin_address;
+ taco_data = updated_taco_data;
+ } in
+ ```
+
+ The next line is the line `[], updated_taco_data`, which you added when you stubbed in the entrypoint code earlier.
+
+ Now the `buy_taco` entrypoint updates the stock in storage to indicate that it has one less of that type of taco.
+ The contract automatically accepts the tez that is included with the transaction.
+
+1. After the code for the `buy_taco` entrypoint, stub in the code for the entrypoint that allows Pedro to retrieve the tez in the contract, which you will add in a later section:
+
+ ```cameligo skip
+ [@entry]
+ let payout (_u : unit) (storage : storage) : operation list * storage =
+
+ (* Entrypoint logic goes here *)
+
+ [], storage
+ ```
+
+ Currently this entrypoint does nothing, but you will add code for it later.
+
+
+
+## Providing information to clients
+
+Earlier, you added an internal function that calculated the price of a taco.
+External clients can't call this function because it is private to the contract.
+
+The contract should give Pedro's customers a way to get the current price of a taco.
+However, because entrypoints don't return a value directly to the caller, an entrypoint isn't the best way to provide information to clients.
+
+If you need to provide information to clients, one way is to use a _view_, which is a static function that returns a value to clients but does not change the storage or generate any operations.
+Like entrypoints, views are functions that receive one or more parameters from the caller and the current value of the storage.
+Unlike entrypoints, they return a single value to the caller instead of a list of operations and the new value of the storage.
+
+
+
+Add this view to the contract, after the `get_taco_price_internal` function and somewhere within the namespace:
+
+```jsligo skip
+// @view
+const get_taco_price = (taco_kind_index: nat, storage: storage): tez =>
+ get_taco_price_internal(taco_kind_index, storage.taco_data);
+```
+
+This view is merely a wrapper around the `get_taco_price_internal` function, but the `@view` decorator makes external clients able to call it.
+
+For more information about views, see [Views](../../syntax/contracts/views).
+
+The complete contract file looks like this:
+
+```jsligo skip
+namespace TacoShop {
+ export type taco_supply = { current_stock: nat, max_price: tez };
+ export type taco_data = map;
+ export type admin_address = address;
+ export type storage = {
+ admin_address: admin_address,
+ taco_data: taco_data,
+ };
+
+ export const default_taco_data: taco_data = Map.literal([
+ [1 as nat, { current_stock: 50 as nat, max_price: 50 as tez }],
+ [2 as nat, { current_stock: 20 as nat, max_price: 75 as tez }]
+ ]);
+
+ // Internal function to get the price of a taco
+ const get_taco_price_internal = (taco_kind_index: nat, taco_data: taco_data): tez => {
+ const taco_kind: taco_supply =
+ $match (Map.find_opt(taco_kind_index, taco_data), {
+ "Some": (kind) => kind,
+ "None": () => failwith("Unknown kind of taco"),
+ });
+ return taco_kind.max_price / taco_kind.current_stock;
+ }
+
+ // @view
+ const get_taco_price = (taco_kind_index: nat, storage: storage): tez =>
+ get_taco_price_internal(taco_kind_index, storage.taco_data);
+
+ // Buy a taco
+ // @entry
+ const buy_taco = (taco_kind_index: nat, storage: storage): [
+ list,
+ storage
+ ] => {
+
+ const { admin_address, taco_data } = storage;
+
+ // Retrieve the kind of taco from the contracts storage or fail
+ const taco_kind: taco_supply =
+ $match (Map.find_opt(taco_kind_index, taco_data), {
+ "Some": (kind) => kind,
+ "None": () => failwith("Unknown kind of taco"),
+ });
+
+ // Get the current price of this type of taco
+ const current_purchase_price = get_taco_price_internal(taco_kind_index, taco_data);
+
+ // Verify that the caller sent the correct amount of tez
+ if ((Tezos.get_amount()) != current_purchase_price) {
+ return failwith("Sorry, the taco you are trying to purchase has a different price");
+ }
+
+ // Verify that there is at least one of this type of taco
+ if (taco_kind.current_stock == (0 as nat)) {
+ return failwith("Sorry, we are out of this type of taco");
+ }
+
+ // Update the storage with the new quantity of tacos
+ const updated_taco_data: taco_data = Map.update(
+ taco_kind_index,
+ ["Some" as "Some", {...taco_kind, current_stock: abs(taco_kind.current_stock - 1) }],
+ taco_data);
+
+ const updated_storage: storage = {
+ admin_address: admin_address,
+ taco_data: updated_taco_data,
+ };
+
+ return [[], updated_storage];
+ }
+
+ // @entry
+ const payout = (_u: unit, storage: storage): [
+ list,
+ storage
+ ] => {
+
+ // Entrypoint logic goes here
+
+ return [[], storage];
+ }
+
+};
+```
+
+
+
+
+
+Add this view to the contract, after the `get_taco_price_internal` function and somewhere within the module:
+
+```cameligo skip
+[@view]
+let get_taco_price (taco_kind_index : nat) (storage : storage) : tez =
+ get_taco_price_internal taco_kind_index storage.taco_data
+```
+
+This view is merely a wrapper around the `get_taco_price_internal` function, but the `@view` attribute makes external clients able to call it.
+
+For more information about views, see [Views](../../syntax/contracts/views).
+
+The complete contract file looks like this:
+
+```cameligo skip
+module TacoShop = struct
+
+ type taco_supply = { current_stock: nat; max_price: tez }
+ type taco_data = (nat, taco_supply) map
+ type admin_address = address
+ type storage = {
+ admin_address: admin_address;
+ taco_data: taco_data;
+ }
+
+ let default_taco_data: taco_data = Map.literal [
+ (1n, { current_stock = 50n; max_price = 50tez });
+ (2n, { current_stock = 20n; max_price = 75tez });
+ ]
+
+ (* Internal function to get the price of a taco *)
+ let get_taco_price_internal (taco_kind_index : nat) (taco_data : taco_data) : tez =
+ let taco_kind : taco_supply =
+ match Map.find_opt taco_kind_index taco_data with
+ | Some kind -> kind
+ | None -> failwith "Unknown kind of taco"
+ in
+ taco_kind.max_price / taco_kind.current_stock
+
+ [@view]
+ let get_taco_price (taco_kind_index : nat) (storage : storage) : tez =
+ get_taco_price_internal taco_kind_index storage.taco_data
+
+ (* Buy a taco *)
+ [@entry]
+ let buy_taco (taco_kind_index : nat) (storage : storage) : operation list * storage =
+
+ let { admin_address; taco_data } = storage in
+
+ (* Retrieve the kind of taco from the contracts storage or fail *)
+ let taco_kind : taco_supply =
+ match Map.find_opt taco_kind_index taco_data with
+ | Some kind -> kind
+ | None -> failwith "Unknown kind of taco" in
+
+ (* Get the current price of this type of taco *)
+ let current_purchase_price = get_taco_price_internal taco_kind_index taco_data in
+
+ (* Verify that the caller sent the correct amount of tez *)
+ let _ = if (Tezos.get_amount () <> current_purchase_price) then
+ failwith "Sorry, the taco you are trying to purchase has a different price" in
+
+ (* Verify that there is at least one of this type of taco *)
+ let _ = if (taco_kind.current_stock = 0n) then
+ failwith "Sorry, we are out of this type of taco" in
+
+
+ (* Update the storage with the new quantity of tacos *)
+ let updated_taco_data : taco_data = Map.update
+ taco_kind_index
+ (Some { taco_kind with current_stock = abs (taco_kind.current_stock - 1n) })
+ taco_data in
+
+
+ let updated_storage : storage = {
+ admin_address = admin_address;
+ taco_data = updated_taco_data;
+ } in
+
+ [], updated_storage
+
+ [@entry]
+ let payout (_u : unit) (storage : storage) : operation list * storage =
+
+ (* Entrypoint logic goes here *)
+
+ [], storage
+
+ end
+```
+
+
+
+## Compiling the contract
+
+Before you can deploy the contract to Tezos, you must compile it to Michelson,the low-level language of contracts on Tezos.
+
+Run this command to compile the contract:
+
+
+
+```bash
+ligo compile contract -m TacoShop -o taco_shop.tz taco_shop.jsligo
+```
+
+
+
+
+
+```bash
+ligo compile contract -m TacoShop -o taco_shop.tz taco_shop.mligo
+```
+
+
+
+If compilation is successful, LIGO prints nothing to the console and writes the compiled contract to the file `taco_shop.tz`.
+You don't need to interact with this file directly.
+
+If you see errors, make sure your code matches the code in the previous section.
+
+You now have a basic contract that can accept requests to sell tacos.
+However, before you deploy it, you should test the contract to make sure it works.
+Continue to [Part 2: Testing the contract](./testing-contract).
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/a.jsligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/a.jsligo
deleted file mode 100644
index f827e40d02..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/a.jsligo
+++ /dev/null
@@ -1,36 +0,0 @@
-namespace TacoShop {
- export type taco_supply = { current_stock: nat, max_price: tez };
- export type taco_shop_storage = map;
-
- // @entry
- function buy_taco(taco_kind_index: nat, taco_shop_storage: taco_shop_storage): [list, taco_shop_storage] {
- /* Retrieve the taco_kind from the contracts storage or fail */
- const taco_kind : taco_supply =
- $match(Map.find_opt (taco_kind_index, taco_shop_storage), {
- "Some": kind => kind,
- "None": () => failwith ("Unknown kind of taco")
- });
- const current_purchase_price : tez = taco_kind.max_price / taco_kind.current_stock ;
- /* We won't sell tacos if the amount is not correct */
- if ((Tezos.get_amount ()) != current_purchase_price)
- return failwith ("Sorry, the taco you are trying to purchase has a different price");
- else {
- /* Update the storage decreasing the stock by 1n */
- const taco_shop_storage = Map.update (
- taco_kind_index,
- ["Some" as "Some", {...taco_kind, current_stock : abs (taco_kind.current_stock - (1 as nat)) }],
- taco_shop_storage );
- return [[], taco_shop_storage]
- }
- }
-};
-
-const default_storage: TacoShop.taco_shop_storage =
- Map.literal(
- list(
- [
- [1 as nat, { current_stock: 50 as nat, max_price: 50000000 as mutez }],
- [2 as nat, { current_stock: 20 as nat, max_price: 75000000 as mutez }]
- ]
- )
- );
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/a.mligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/a.mligo
deleted file mode 100644
index 43bf74f414..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/a.mligo
+++ /dev/null
@@ -1,53 +0,0 @@
-module TacoShop = struct
- type taco_supply =
- {
- current_stock : nat;
- max_price : tez
- }
-
- type taco_shop_storage = (nat, taco_supply) map
-
- [@entry]
- let buy_taco (taco_kind_index : nat) (taco_shop_storage : taco_shop_storage)
- : operation list * taco_shop_storage =
- (* Retrieve the taco_kind from the contract's storage or fail *)
-
- let taco_kind =
- match Map.find_opt (taco_kind_index) taco_shop_storage with
- Some k -> k
- | None -> failwith "Unknown kind of taco" in
- let current_purchase_price : tez =
- taco_kind.max_price / taco_kind.current_stock in
- (* We won't sell tacos if the amount is not correct *)
-
- let () =
- if (Tezos.get_amount ()) <> current_purchase_price
- then
- failwith
- "Sorry, the taco you are trying to purchase has a different price" in
- (* Update the storage decreasing the stock by 1n *)
-
- let taco_shop_storage =
- Map.update
- taco_kind_index
- (Some
- {taco_kind with current_stock = abs (taco_kind.current_stock - 1n)})
- taco_shop_storage in
- [], taco_shop_storage
-
-end
-
-let default_storage : TacoShop.taco_shop_storage =
- Map.literal
- [
- (1n,
- {
- current_stock = 50n;
- max_price = 50000000mutez
- });
- (2n,
- {
- current_stock = 20n;
- max_price = 75000000mutez
- })
- ]
\ No newline at end of file
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/b.jsligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/b.jsligo
deleted file mode 100644
index 5dee19197c..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/b.jsligo
+++ /dev/null
@@ -1,75 +0,0 @@
-namespace TacoShop {
- export type taco_supply = { current_stock: nat, max_price: tez };
- export type taco_shop_storage = map;
-
- const ownerAddress : address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV";
-
- const donationAddress : address = "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx";
-
- // @entry
- function buy_taco(taco_kind_index: nat, taco_shop_storage: taco_shop_storage): [list, taco_shop_storage] {
- /* Retrieve the taco_kind from the contracts storage or fail */
- const taco_kind: taco_supply =
- $match(Map.find_opt(taco_kind_index, taco_shop_storage), {
- "Some": kind => kind,
- "None": () => failwith("Unknown kind of taco")
- });
- const current_purchase_price: tez =
- taco_kind.max_price / taco_kind.current_stock;
- /* We won't sell tacos if the amount is not correct */
-
- if ((Tezos.get_amount()) != current_purchase_price) {
- return failwith(
- "Sorry, the taco you are trying to purchase has a different price"
- )
- } else {
- /* Update the storage decreasing the stock by 1n */
-
- const taco_shop_storage =
- Map.update(
- taco_kind_index,
- [
- "Some" as "Some", {
- ...taco_kind, current_stock: abs(taco_kind.current_stock - (1 as nat))
- }
- ],
- taco_shop_storage
- );
-
- const receiver : contract =
- $match(Tezos.get_contract_opt (ownerAddress), {
- "Some": contract => contract,
- "None": () => failwith ("Not a contract")
- });
-
- const donationReceiver : contract =
- $match((Tezos.get_contract_opt (donationAddress)), {
- "Some": contract => contract,
- "None": () => failwith ("Not a contract")
- });
-
- const donationAmount = ((Tezos.get_amount ()) / (10 as nat)) as tez;
-
- // Pedro will get 90% of the amount
- const op1 =
- $match (Tezos.get_amount () - donationAmount, {
- "Some": x => Tezos.transaction (unit, x, receiver),
- "None": () => failwith ("Insufficient balance")
- });
- const op2 = Tezos.transaction (unit, donationAmount, donationReceiver);
- const operations : list = [ op1 , op2 ];
-
- return [operations, taco_shop_storage]
- }
- };
-}
-
-const default_storage: TacoShop.taco_shop_storage =
- Map.literal(
- list(
- [
- [1 as nat, { current_stock: 50 as nat, max_price: 50000000 as mutez }],
- [2 as nat, { current_stock: 20 as nat, max_price: 75000000 as mutez }]
- ]
- )
- );
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/b.mligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/b.mligo
deleted file mode 100644
index e88bf99e20..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/b.mligo
+++ /dev/null
@@ -1,63 +0,0 @@
-module TacoShop = struct
- type taco_supply =
- {
- current_stock : nat;
- max_price : tez
- }
-
- type taco_shop_storage = (nat, taco_supply) map
-
- let ownerAddress : address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address)
-
- [@entry]
- let buy_taco (taco_kind_index : nat) (taco_shop_storage : taco_shop_storage)
- : operation list * taco_shop_storage =
- (* Retrieve the taco_kind from the contract's storage or fail *)
-
- let taco_kind =
- match Map.find_opt (taco_kind_index) taco_shop_storage with
- Some k -> k
- | None -> failwith "Unknown kind of taco" in
- let current_purchase_price : tez =
- taco_kind.max_price / taco_kind.current_stock in
- (* We won't sell tacos if the amount is not correct *)
-
- let () =
- if (Tezos.get_amount ()) <> current_purchase_price
- then
- failwith
- "Sorry, the taco you are trying to purchase has a different price" in
- (* Update the storage decreasing the stock by 1n *)
-
- let taco_shop_storage =
- Map.update
- taco_kind_index
- (Some
- {taco_kind with current_stock = abs (taco_kind.current_stock - 1n)})
- taco_shop_storage in
-
- let receiver : unit contract =
- match (Tezos.get_contract_opt ownerAddress : unit contract option) with
- Some (contract) -> contract
- | None -> (failwith "Not a contract" : unit contract) in
-
- let payoutOperation : operation = Tezos.transaction () (Tezos.get_amount ()) receiver in
- let operations : operation list = [payoutOperation] in
-
- operations, taco_shop_storage
-end
-
-let default_storage : TacoShop.taco_shop_storage =
- Map.literal
- [
- (1n,
- {
- current_stock = 50n;
- max_price = 50000000mutez
- });
- (2n,
- {
- current_stock = 20n;
- max_price = 75000000mutez
- })
- ]
\ No newline at end of file
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/bonus.jsligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/bonus.jsligo
deleted file mode 100644
index 3a1556c30e..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/bonus.jsligo
+++ /dev/null
@@ -1,25 +0,0 @@
-const ownerAddress : address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV";
-const donationAddress : address = "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx";
-
-const receiver : contract =
- $match((Tezos.get_contract_opt (ownerAddress)) as option>, {
- "Some": contract => contract,
- "None": () => (failwith ("Not a contract")) as contract
- });
-
-const donationReceiver : contract =
- $match((Tezos.get_contract_opt (donationAddress)) as option>, {
- "Some": contract => contract,
- "None": () => (failwith ("Not a contract")) as contract
- });
-
-const donationAmount = ((Tezos.get_amount ()) / (10 as nat)) as tez;
-
-// Pedro will get 90% of the amount
-const op1 =
- $match((Tezos.get_amount ()) - donationAmount, {
- "Some": x => Tezos.transaction (unit, x, receiver),
- "None": () => failwith ("Insufficient balance")
- });
-const op2 = Tezos.transaction (unit, donationAmount, donationReceiver);
-const operations : list = [ op1 , op2 ];
\ No newline at end of file
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/bonus.mligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/bonus.mligo
deleted file mode 100644
index 5352171b6a..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/bonus.mligo
+++ /dev/null
@@ -1,22 +0,0 @@
-let ownerAddress : address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address)
-let donationAddress : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address)
-
-let receiver : unit contract =
- match ((Tezos.get_contract_opt ownerAddress) : unit contract option) with
- Some contract -> contract
- | None -> ((failwith "Not a contract") : unit contract)
-
-let donationReceiver : unit contract =
- match ((Tezos.get_contract_opt donationAddress) : unit contract option) with
- Some contract -> contract
- | None -> ((failwith "Not a contract") : unit contract)
-
-let donationAmount : tez = (Tezos.get_amount ()) / 10n
-
-let operations : operation list =
- // Pedro will get 90% of the amount
- let op = match ((Tezos.get_amount ()) - donationAmount) with
- | Some x -> Tezos.transaction () x receiver
- | None -> (failwith "Insufficient balance")
- in
- [ op ; Tezos.transaction () donationAmount donationReceiver ]
\ No newline at end of file
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/ex1.jsligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/ex1.jsligo
deleted file mode 100644
index 9300223070..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/ex1.jsligo
+++ /dev/null
@@ -1,9 +0,0 @@
-const ownerAddress : address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV"
-
-const receiver : contract =
- $match(Tezos.get_contract_opt(ownerAddress) as option>, {
- "Some": contract => contract,
- "None": () => failwith ("Not a contract") as contract
- })
-const payoutOperation : operation = Tezos.transaction (unit, Tezos.get_amount (), receiver) ;
-const operations : list = [payoutOperation];
\ No newline at end of file
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/ex1.mligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/ex1.mligo
deleted file mode 100644
index 265475f849..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-payout/ex1.mligo
+++ /dev/null
@@ -1,7 +0,0 @@
-let ownerAddress : address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV"
-let receiver : unit contract =
- match (Tezos.get_contract_opt ownerAddress : unit contract option) with
- Some (contract) -> contract
- | None -> (failwith "Not a contract" : unit contract)
-let payoutOperation : operation = Tezos.transaction () (Tezos.get_amount ()) receiver
-let operations : operation list = [payoutOperation]
\ No newline at end of file
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/TacoShop.jsligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/TacoShop.jsligo
deleted file mode 100644
index 0834787329..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/TacoShop.jsligo
+++ /dev/null
@@ -1,28 +0,0 @@
-export type taco_supply = { current_stock : nat , max_price : tez };
-
-export type taco_shop_storage = map ;
-const default_storage: taco_shop_storage = Map.literal ([
- [1 as nat, { current_stock : 50 as nat, max_price : 50 as tez }],
- [2 as nat, { current_stock : 20 as nat, max_price : 75 as tez }]
-]);
-// @entry
-function buy_taco (taco_kind_index: nat, taco_shop_storage: taco_shop_storage) : [list, taco_shop_storage] {
- /* Retrieve the taco_kind from the contracts storage or fail */
- const taco_kind : taco_supply =
- $match (Map.find_opt (taco_kind_index, taco_shop_storage), {
- "Some": kind => kind,
- "None": () => failwith ("Unknown kind of taco")
- });
- const current_purchase_price : tez = taco_kind.max_price / taco_kind.current_stock ;
- /* We won't sell tacos if the amount is not correct */
- if ((Tezos.get_amount ()) != current_purchase_price)
- return failwith ("Sorry, the taco you are trying to purchase has a different price");
- else {
- /* Update the storage decreasing the stock by 1 nat */
- const taco_shop_storage = Map.update (
- taco_kind_index,
- ["Some" as "Some", {...taco_kind, current_stock : abs (taco_kind.current_stock - (1 as nat)) }],
- taco_shop_storage );
- return [[], taco_shop_storage]
- }
-};
\ No newline at end of file
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/TacoShop.mligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/TacoShop.mligo
deleted file mode 100644
index 410e62876b..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/TacoShop.mligo
+++ /dev/null
@@ -1,34 +0,0 @@
-type taco_supply = { current_stock : nat ; max_price : tez }
-
-type taco_shop_storage = (nat, taco_supply) map
-let default_storage: taco_shop_storage = Map.literal [
- (1n, { current_stock = 50n ; max_price = 50tez }) ;
- (2n, { current_stock = 20n ; max_price = 75tez }) ;
-]
-[@entry]
-let buy_taco (taco_kind_index : nat) (taco_shop_storage : taco_shop_storage)
- : operation list * taco_shop_storage =
- (* Retrieve the taco_kind from the contract's storage or fail *)
-
- let taco_kind =
- match Map.find_opt (taco_kind_index) taco_shop_storage with
- Some k -> k
- | None -> failwith "Unknown kind of taco" in
- let current_purchase_price : tez =
- taco_kind.max_price / taco_kind.current_stock in
- (* We won't sell tacos if the amount is not correct *)
-
- let () =
- if (Tezos.get_amount ()) <> current_purchase_price
- then
- failwith
- "Sorry, the taco you are trying to purchase has a different price" in
- (* Update the storage decreasing the stock by 1n *)
-
- let taco_shop_storage =
- Map.update
- taco_kind_index
- (Some
- {taco_kind with current_stock = abs (taco_kind.current_stock - 1n)})
- taco_shop_storage in
- [], taco_shop_storage
\ No newline at end of file
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/b12.jsligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/b12.jsligo
deleted file mode 100644
index 2fbec1a519..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/b12.jsligo
+++ /dev/null
@@ -1,9 +0,0 @@
-
-namespace TacoShop {
- type taco_supply = { current_stock: nat, max_price: tez };
- export type taco_shop_storage = map;
-
- // @entry
- const buy_taco = (taco_kind_index: nat, taco_shop_storage: taco_shop_storage): [list, taco_shop_storage] =>
- [[], taco_shop_storage]
-};
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/b12.mligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/b12.mligo
deleted file mode 100644
index 21ce5f0074..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/b12.mligo
+++ /dev/null
@@ -1,14 +0,0 @@
-module TacoShop = struct
- type taco_supply =
- {
- current_stock : nat;
- max_price : tez
- }
-
- type taco_shop_storage = (nat, taco_supply) map
-
- [@entry]
- let buy_taco (taco_kind_index : nat) (taco_shop_storage : taco_shop_storage) : operation list * taco_shop_storage =
- [], taco_shop_storage
-
-end
\ No newline at end of file
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/test.jsligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/test.jsligo
deleted file mode 100644
index cc72119d77..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/test.jsligo
+++ /dev/null
@@ -1,107 +0,0 @@
-import * as TacoShop from "gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/TacoShop.jsligo";
-
-function assert_string_failure (res: test_exec_result, expected: string) {
- const expected_bis = Test.eval(expected);
- $match(res, {
- "Fail": x =>
- $match(x, {
- "Rejected": y =>
- Assert.assert(Test.michelson_equal(y[0], expected_bis)),
- "Balance_too_low": _ =>
- failwith("contract failed for an unknown reason"),
- "Other": _o =>
- failwith("contract failed for an unknown reason")
- }),
- "Success": _s => failwith("bad price check")
- });
-}
-
-const test = (
- (_u: unit): unit => {
- /* Originate the contract with a initial storage */
- let init_storage =
- Map.literal(
- list(
- [
- [1 as nat, { current_stock: 50 as nat, max_price: 50000000 as mutez }],
- [2 as nat, { current_stock: 20 as nat, max_price: 75000000 as mutez }]
- ]
- )
- );
- const { addr , code , size } =
- Test.originate(contract_of(TacoShop), init_storage, 0 as mutez);
-
- /* Test inputs */
-
- const clasico_kind : parameter_of =
- ["Buy_taco" as "Buy_taco", 1 as nat];
-
- const unknown_kind : parameter_of =
- ["Buy_taco" as "Buy_taco", 3 as nat];
-
- /* Auxiliary function for testing equality in maps */
-
- const eq_in_map = (r: TacoShop.taco_supply, m: TacoShop.taco_shop_storage, k: nat) =>
- $match(Map.find_opt(k, m), {
- "None": () => false,
- "Some": v =>
- v.current_stock == r.current_stock && v.max_price == r.max_price
- });
-
- /* Purchasing a Taco with 1tez and checking that the stock has been updated */
-
- const ok_case: test_exec_result =
- Test.transfer(
- addr,
- clasico_kind,
- 1000000 as mutez
- );
-
- $match(ok_case, {
- "Success": _s =>
- (() => {
- let storage = Test.get_storage(addr);
- Assert.assert(
- eq_in_map(
- { current_stock: 49 as nat, max_price: 50000000 as mutez },
- storage,
- 1 as nat
- )
- &&
- eq_in_map(
- { current_stock: 20 as nat, max_price: 75000000
- as mutez },
- storage,
- 2 as nat
- )
- );
- })(),
- "Fail": _e => failwith("ok test case failed")
- });
-
- /* Purchasing an unregistred Taco */
-
- const nok_unknown_kind =
- Test.transfer(
- addr,
- unknown_kind,
- 1000000 as mutez
- );
- assert_string_failure(nok_unknown_kind, "Unknown kind of taco");
-
- /* Attempting to Purchase a Taco with 2tez */
-
- const nok_wrong_price =
- Test.transfer(
- addr,
- clasico_kind,
- 2000000 as mutez
- );
-
- assert_string_failure(
- nok_wrong_price,
- "Sorry, the taco you are trying to purchase has a different price"
- );
- return unit
- }
- )();
\ No newline at end of file
diff --git a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/test.mligo b/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/test.mligo
deleted file mode 100644
index 10a865867f..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/test.mligo
+++ /dev/null
@@ -1,45 +0,0 @@
-module TacoShop = Gitlab_pages.Docs.Tutorials.Taco_shop.Src.Tezos_taco_shop_smart_contract.TacoShop
-
-let assert_string_failure (res : test_exec_result) (expected : string) =
- let expected = Test.eval expected in
- match res with
- | Fail (Rejected (actual,_)) -> assert (Test.michelson_equal actual expected)
- | Fail _ -> failwith "contract failed for an unknown reason"
- | Success _ -> failwith "bad price check"
-
-let test =
- (* originate the contract with a initial storage *)
- let init_storage = Map.literal [
- (1n, { current_stock = 50n ; max_price = 50tez }) ;
- (2n, { current_stock = 20n ; max_price = 75tez }) ; ]
- in
- let { addr ; code = _; size = _ } = Test.originate (contract_of TacoShop) init_storage 0tez in
-
- (* Test inputs *)
- let clasico_kind : TacoShop parameter_of = Buy_taco 1n in
- let unknown_kind : TacoShop parameter_of = Buy_taco 3n in
-
- (* Auxiliary function for testing equality in maps *)
- let eq_in_map (r : TacoShop.taco_supply) (m : TacoShop.taco_shop_storage) (k : nat) =
- match Map.find_opt k m with
- | None -> false
- | Some v -> v.current_stock = r.current_stock && v.max_price = r.max_price in
-
- (* Purchasing a Taco with 1tez and checking that the stock has been updated *)
- let ok_case : test_exec_result = Test.transfer addr clasico_kind 1tez in
- let () = match ok_case with
- | Success _ ->
- let storage = Test.get_storage addr in
- assert ((eq_in_map { current_stock = 49n ; max_price = 50tez } storage 1n) &&
- (eq_in_map { current_stock = 20n ; max_price = 75tez } storage 2n))
- | Fail _ -> failwith ("ok test case failed")
- in
-
- (* Purchasing an unregistred Taco *)
- let nok_unknown_kind = Test.transfer addr unknown_kind 1tez in
- let () = assert_string_failure nok_unknown_kind "Unknown kind of taco" in
-
- (* Attempting to Purchase a Taco with 2tez *)
- let nok_wrong_price = Test.transfer addr clasico_kind 2tez in
- let () = assert_string_failure nok_wrong_price "Sorry, the taco you are trying to purchase has a different price" in
- ()
\ No newline at end of file
diff --git a/gitlab-pages/docs/tutorials/taco-shop/testing-contract.md b/gitlab-pages/docs/tutorials/taco-shop/testing-contract.md
new file mode 100644
index 0000000000..0924ec43d0
--- /dev/null
+++ b/gitlab-pages/docs/tutorials/taco-shop/testing-contract.md
@@ -0,0 +1,513 @@
+---
+title: "Part 2: Testing the contract"
+---
+
+It's critical to test contracts before you deploy them because they cannot be changed after you deploy them.
+LIGO includes automated testing tools that let you test contracts and verify that they work the way you intend before you deploy them.
+In this section, you add tests for the `buy_taco` entrypoint.
+
+## Creating tests
+
+You can put tests in the same file as the contract or in a different file.
+For convenience, in this tutorial, you put the tests in the same file.
+
+
+
+1. At the top of the contract file, outside of the namespace, add this code to import the new version of LIGO testing tools:
+
+ ```jsligo skip
+ import Test = Test.Next;
+ import Tezos = Tezos.Next;
+ ```
+
+1. At the end of the contract file, outside of the namespace, add this convenience function to call the view and get the current price of a taco:
+
+ ```jsligo skip
+ // Convenience function to get current taco price
+ const get_taco_price = (untyped_address: address, taco_kind_index: nat): tez => {
+ const view_result_option: option = Tezos.View.call("get_taco_price", taco_kind_index, untyped_address);
+ return $match(view_result_option, {
+ "Some": (cost_mutez) => cost_mutez,
+ "None": () => Test.failwith("Couldn't get the price of the taco."),
+ });
+ }
+ ```
+
+1. Add this convenience function to verify the current stock and maximum price of a taco:
+
+ ```jsligo skip
+ // Convenience function for testing equality in maps
+ const eq_in_map = (r: TacoShop.taco_supply, m: TacoShop.taco_data, k: nat) =>
+ $match(Map.find_opt(k, m), {
+ "None": () => false,
+ "Some": (v) => v.current_stock == r.current_stock && v.max_price == r.max_price
+ });
+ ```
+
+ This function accepts information about a taco type and verifies that the values in the stored map match.
+
+1. At the end of the contract file, outside of the namespace, add this stub of a function to hold the test logic:
+
+ ```jsligo skip
+ const test = (() => {
+
+ // Test logic goes here
+
+ }) ();
+ ```
+
+1. Inside the test function, add code to deploy the contract in the test scenario:
+
+ ```jsligo skip
+ // Set the initial storage and deploy the contract
+ const admin_address: address = Test.Account.address(0 as nat);
+ const initial_storage: TacoShop.storage = {
+ admin_address: admin_address,
+ taco_data: TacoShop.default_taco_data,
+ }
+ const contract = Test.Originate.contract(contract_of(TacoShop), initial_storage, 0 as tez);
+ ```
+
+ This code creates the `contract` object to represent the deployed (originated) contract.
+ This object has a few fields, but the main one the test uses is the `taddr` field, which is the address of the deployed contract.
+ Now you can call the deployed contract in the test scenario.
+
+1. Get the current price of one kind of taco by calling the `get_taco_price` function:
+
+ ```jsligo skip
+ // Get the current price of a taco
+ const untyped_address = Test.Typed_address.to_address(contract.taddr);
+ const current_price = get_taco_price(untyped_address, 1 as nat);
+ ```
+
+1. Call the `buy_taco` entrypoint with this code:
+
+ ```jsligo skip
+ // Purchase a taco
+ const success_result =
+ Test.Contract.transfer(
+ Test.Typed_address.get_entrypoint("buy_taco", contract.taddr),
+ 1 as nat,
+ current_price
+ );
+ ```
+
+ The `Test.Contract.transfer` function calls an entrypoint in a test scenario.
+ It takes these parameters:
+
+ 1. The contract to call, here represented by the `buy_taco` entrypoint of the contract.
+ 1. The parameter to pass to the entrypoint, in this case `1 as nat` to represent the first type of taco.
+ 1. The amount of tez to send with the transaction, in this case the current price of that type of taco from the previous lines of code.
+
+1. Verify that the transaction completed successfully and that the number of tacos of that type decreased by 1:
+
+ ```jsligo skip
+ // Verify that the stock was updated
+ $match(success_result, {
+ "Success": (_s) => (() => {
+ const storage = Test.Typed_address.get_storage(contract.taddr);
+ // Check that the stock has been updated correctly
+ Assert.assert(
+ eq_in_map(
+ { current_stock: 49 as nat, max_price: 50000000 as mutez },
+ storage.taco_data,
+ 1 as nat
+ ));
+ // Check that the amount of the other taco type has not changed
+ Assert.assert(eq_in_map(
+ { current_stock: 20 as nat, max_price: 75000000 as mutez },
+ storage.taco_data,
+ 2 as nat
+ )
+ );
+ Test.IO.log("Successfully bought a taco");
+ })(),
+ "Fail": (err) => failwith(err),
+ });
+ ```
+
+1. Verify that the entrypoint fails when a client passes the wrong price:
+
+ ```jsligo skip
+ // Fail to purchase a taco without sending enough tez
+ const fail_result =
+ Test.Contract.transfer(
+ Test.Typed_address.get_entrypoint("buy_taco", contract.taddr),
+ 1 as nat,
+ 1 as mutez
+ );
+ $match(fail_result, {
+ "Success": (_s) => failwith("Test was able to buy a taco for the wrong price"),
+ "Fail": (_err) => Test.IO.log("Contract successfully blocked purchase with incorrect price"),
+ });
+ ```
+
+ It's important to test failure cases as well as success cases to make sure the contract works properly in all cases.
+
+The completed convenience functions and test functions look like this:
+
+```jsligo skip
+import Test = Test.Next;
+import Tezos = Tezos.Next;
+
+// TacoShop namespace goes here
+
+// Convenience function to get current taco price
+const get_taco_price = (untyped_address: address, taco_kind_index: nat): tez => {
+ const view_result_option: option = Tezos.View.call("get_taco_price", taco_kind_index, untyped_address);
+ return $match(view_result_option, {
+ "Some": (cost_mutez) => cost_mutez,
+ "None": () => Test.failwith("Couldn't get the price of the taco."),
+ });
+}
+
+// Convenience function for testing equality in maps
+const eq_in_map = (r: TacoShop.taco_supply, m: TacoShop.taco_data, k: nat) =>
+ $match(Map.find_opt(k, m), {
+ "None": () => false,
+ "Some": (v) => v.current_stock == r.current_stock && v.max_price == r.max_price
+ });
+
+const test = (() => {
+
+ // Set the initial storage and deploy the contract
+ const admin_address: address = Test.Account.address(0 as nat);
+ const initial_storage: TacoShop.storage = {
+ admin_address: admin_address,
+ taco_data: TacoShop.default_taco_data,
+ }
+ const contract = Test.Originate.contract(contract_of(TacoShop), initial_storage, 0 as tez);
+
+ // Get the current price of a taco
+ const untyped_address = Test.Typed_address.to_address(contract.taddr);
+ const current_price = get_taco_price(untyped_address, 1 as nat);
+
+ // Purchase a taco
+ const success_result =
+ Test.Contract.transfer(
+ Test.Typed_address.get_entrypoint("buy_taco", contract.taddr),
+ 1 as nat,
+ current_price
+ );
+
+ // Verify that the stock was updated
+ $match(success_result, {
+ "Success": (_s) => (() => {
+ const storage = Test.Typed_address.get_storage(contract.taddr);
+ // Check that the stock has been updated correctly
+ Assert.assert(
+ eq_in_map(
+ { current_stock: 49 as nat, max_price: 50000000 as mutez },
+ storage.taco_data,
+ 1 as nat
+ ));
+ // Check that the amount of the other taco type has not changed
+ Assert.assert(eq_in_map(
+ { current_stock: 20 as nat, max_price: 75000000 as mutez },
+ storage.taco_data,
+ 2 as nat
+ )
+ );
+ Test.IO.log("Successfully bought a taco");
+ })(),
+ "Fail": (err) => failwith(err),
+ });
+
+ // Fail to purchase a taco without sending enough tez
+ const fail_result =
+ Test.Contract.transfer(
+ Test.Typed_address.get_entrypoint("buy_taco", contract.taddr),
+ 1 as nat,
+ 1 as mutez
+ );
+ $match(fail_result, {
+ "Success": (_s) => failwith("Test was able to buy a taco for the wrong price"),
+ "Fail": (_err) => Test.IO.log("Contract successfully blocked purchase with incorrect price"),
+ });
+}) ();
+```
+
+
+
+
+
+1. At the top of the contract file, outside of the module, add this code to import the new version of LIGO testing tools:
+
+ ```cameligo skip
+ module Test = Test.Next
+ module Tezos = Tezos.Next
+ ```
+
+1. At the end of the contract file, outside of the module, add this convenience function to call the view and get the current price of a taco:
+
+ ```cameligo skip
+ (* Convenience function to get current taco price *)
+ let get_taco_price (untyped_address : address) (taco_kind_index : nat) : tez =
+ let view_result_option : tez option = Tezos.View.call
+ "get_taco_price"
+ taco_kind_index
+ untyped_address in
+ match view_result_option with
+ | Some cost_mutez -> cost_mutez
+ | None -> Test.failwith "Couldn't get the price of a taco"
+ ```
+
+1. Add this convenience function to verify the current stock and maximum price of a taco:
+
+ ```cameligo skip
+ (* Convenience function for testing equality in maps *)
+ let eq_in_map (r : TacoShop.taco_supply) (m : TacoShop.taco_data) (k : nat) =
+ match Map.find_opt k m with
+ | None -> false
+ | Some v -> v.current_stock = r.current_stock && v.max_price = r.max_price
+ ```
+
+ This function accepts information about a taco type and verifies that the values in the stored map match.
+
+1. At the end of the contract file, outside of the namespace, create a function to hold the test logic:
+
+ ```cameligo skip
+ let test =
+ ```
+
+1. Inside the test function, add code to deploy the contract in the test scenario:
+
+ ```cameligo skip
+ (* Set the initial storage and deploy the contract *)
+ let admin_address : address = Test.Account.address 0n in
+ let initial_storage : TacoShop.storage = {
+ admin_address = admin_address;
+ taco_data = TacoShop.default_taco_data
+ } in
+ let contract = Test.Originate.contract (contract_of TacoShop) initial_storage 0tez in
+ ```
+
+ This code creates the `contract` object to represent the deployed (originated) contract.
+ This object has a few fields, but the main one the test uses is the `taddr` field, which is the address of the deployed contract.
+ Now you can call the deployed contract in the test scenario.
+
+1. Get the current price of one kind of taco by calling the `get_taco_price` function:
+
+ ```cameligo skip
+ (* Get the current price of a taco *)
+ let untyped_address = Test.Typed_address.to_address contract.taddr in
+ let current_price = get_taco_price untyped_address 1n in
+ ```
+
+1. Call the `buy_taco` entrypoint with this code:
+
+ ```cameligo skip
+ (* Purchase a taco *)
+ let success_result =
+ Test.Contract.transfer
+ (Test.Typed_address.get_entrypoint "buy_taco" contract.taddr)
+ 1n
+ current_price
+ in
+ ```
+
+ The `Test.Contract.transfer` function calls an entrypoint in a test scenario.
+ It takes these parameters:
+
+ 1. The contract to call, here represented by the `buy_taco` entrypoint of the contract.
+ 1. The parameter to pass to the entrypoint, in this case `1n` to represent the first type of taco.
+ 1. The amount of tez to send with the transaction, in this case the current price of that type of taco from the previous lines of code.
+
+1. Verify that the transaction completed successfully and that the number of tacos of that type decreased by 1:
+
+ ```cameligo skip
+ (* Verify that the stock was updated *)
+ let () = match success_result with
+ | Success _s ->
+ let storage = Test.Typed_address.get_storage contract.taddr in
+ let () = Assert.assert (eq_in_map
+ { current_stock = 49n; max_price = 50000000mutez }
+ storage.taco_data
+ 1n
+ ) in
+ let () = Assert.assert (eq_in_map
+ { current_stock = 20n; max_price = 75000000mutez }
+ storage.taco_data
+ 2n
+ ) in
+ Test.IO.log "Successfully bought a taco"
+ | Fail err -> failwith err
+ in
+ ```
+
+1. Verify that the entrypoint fails when a client passes the wrong price:
+
+ ```cameligo skip
+ (* Fail to purchase a taco without sending enough tez *)
+ let fail_result = Test.Contract.transfer
+ (Test.Typed_address.get_entrypoint "buy_taco" contract.taddr)
+ 1n
+ 1mutez in
+ match fail_result with
+ | Success _s -> failwith "Test was able to buy a taco for the wrong price"
+ | Fail _err -> Test.IO.log "Contract successfully blocked purchase with incorrect price"
+ ```
+
+ It's important to test failure cases as well as success cases to make sure the contract works properly in all cases.
+
+The completed convenience functions and test functions look like this:
+
+```cameligo skip
+module Test = Test.Next
+module Tezos = Tezos.Next
+
+(* TacoShop module goes here *)
+
+(* Convenience function to get current taco price *)
+let get_taco_price (untyped_address : address) (taco_kind_index : nat) : tez =
+ let view_result_option : tez option = Tezos.View.call
+ "get_taco_price"
+ taco_kind_index
+ untyped_address in
+ match view_result_option with
+ | Some cost_mutez -> cost_mutez
+ | None -> Test.failwith "Couldn't get the price of a taco"
+
+(* Convenience function for testing equality in maps *)
+let eq_in_map (r : TacoShop.taco_supply) (m : TacoShop.taco_data) (k : nat) =
+ match Map.find_opt k m with
+ | None -> false
+ | Some v -> v.current_stock = r.current_stock && v.max_price = r.max_price
+
+let test =
+
+ (* Set the initial storage and deploy the contract *)
+ let admin_address : address = Test.Account.address 0n in
+ let initial_storage : TacoShop.storage = {
+ admin_address = admin_address;
+ taco_data = TacoShop.default_taco_data
+ } in
+ let contract = Test.Originate.contract (contract_of TacoShop) initial_storage 0tez in
+
+ (* Get the current price of a taco *)
+ let untyped_address = Test.Typed_address.to_address contract.taddr in
+ let current_price = get_taco_price untyped_address 1n in
+
+ (* Purchase a taco *)
+ let success_result =
+ Test.Contract.transfer
+ (Test.Typed_address.get_entrypoint "buy_taco" contract.taddr)
+ 1n
+ current_price
+ in
+
+ (* Verify that the stock was updated *)
+ let () = match success_result with
+ | Success _s ->
+ let storage = Test.Typed_address.get_storage contract.taddr in
+ let () = Assert.assert (eq_in_map
+ { current_stock = 49n; max_price = 50000000mutez }
+ storage.taco_data
+ 1n
+ ) in
+ let () = Assert.assert (eq_in_map
+ { current_stock = 20n; max_price = 75000000mutez }
+ storage.taco_data
+ 2n
+ ) in
+ Test.IO.log "Successfully bought a taco"
+ | Fail err -> failwith err
+ in
+
+ (* Fail to purchase a taco without sending enough tez *)
+ let fail_result = Test.Contract.transfer
+ (Test.Typed_address.get_entrypoint "buy_taco" contract.taddr)
+ 1n
+ 1mutez in
+ match fail_result with
+ | Success _s -> failwith "Test was able to buy a taco for the wrong price"
+ | Fail _err -> Test.IO.log "Contract successfully blocked purchase with incorrect price"
+```
+
+
+
+## Running tests
+
+LIGO tests do not run automatically when you run the `ligo compile contract` command; you must run them with the `ligo run test` command.
+
+Run the tests in the contract file by running this command:
+
+
+
+```bash
+ligo run test taco_shop.jsligo
+```
+
+
+
+
+
+```bash
+ligo run test taco_shop.mligo
+```
+
+
+
+The console response prints the messages from the calls to `Test.IO.log` and a message that the test function completed:
+
+```
+"Successfully bought a taco"
+"Contract successfully blocked purchase with incorrect price"
+Everything at the top-level was executed.
+- test exited with value ().
+```
+
+If you want to expand the tests for your contract, you can add more test functions or more test code to the existing function.
+For example, you can try buying the other kind of taco or buying more of the first kind of taco and verifying that the stock and price changes as expected.
+
+## Testing with dry-run
+
+Another way to test contracts is with the `ligo run dry-run` command.
+This command runs the contract in a simulated environment with parameters that you provide on the command line.
+You pass these arguments to the command:
+
+- The contract file to run
+- The amount of tez to pass with the transaction
+- The parameter to pass to the contract, as a LIGO expression
+- The value of the contract storage, as a LIGO expression
+
+For example, you can test the `buy_taco` entrypoint with this command:
+
+
+
+```bash
+ligo run dry-run taco_shop.jsligo -m TacoShop --amount 1 '["Buy_taco" as "Buy_taco", 1 as nat]' \
+ '{admin_address: "tz1QCVQinE8iVj1H2fckqx6oiM85CNJSK9Sx" as address, taco_data: TacoShop.default_taco_data}'
+```
+
+The entrypoint and parameter in this command are formatted as a variant type.
+When the contract is compiled to Michelson, its parameter is a variant that has cases for each entrypoint, so you must pass the variant that corresponds to the entrypoint.
+For the purposes of the `ligo run dry-run` command, the variant type is the name of the entrypoint with the first letter in upper case.
+Note also that you can use variables from the contract (as in `TacoShop.default_taco_data`) in the command because the contract parameter and storage value are LIGO expressions.
+
+
+
+
+
+```bash
+ligo run dry-run taco_shop.mligo -m TacoShop --amount 1 "Buy_taco 1n" \
+ '{admin_address = "tz1QCVQinE8iVj1H2fckqx6oiM85CNJSK9Sx" ; taco_data = TacoShop.default_taco_data}'
+```
+
+Note that the entrypoint name starts with a capital letter when you use it in a dry run.
+Note also that you can use variables from the contract (as in `TacoShop.default_taco_data`) in the command because the contract parameter and storage value are LIGO expressions.
+
+
+
+The address in the dry run command isn't stored beyond this run of the command; you just need to provide any address for the amin address in storage.
+However, you must use the `as address` declaration to specify that the string is a LIGO `address` type; without the type declaration, LIGO would assume that it was a string.
+
+The output of the command is the return value of the entrypoint that you called.
+In this case, it is an empty list of operations (`LIST_EMPTY()`) and the code for the new state of the storage.
+
+In this way, you can test different storage states and entrypoints from the command line.
+Sometimes testing with a dry run can be more convenient than writing tests; it's up to you how to test the contract.
+
+Now you know that the customer interface of the contract works.
+In the next section, you implement the `payout` entrypoint to retrieve the profits.
+Continue to [Part 3: Getting the payouts](./getting-payouts).
diff --git a/gitlab-pages/docs/tutorials/taco-shop/tezos-taco-shop-payout.md b/gitlab-pages/docs/tutorials/taco-shop/tezos-taco-shop-payout.md
deleted file mode 100644
index f8e8e9bb06..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/tezos-taco-shop-payout.md
+++ /dev/null
@@ -1,505 +0,0 @@
----
-id: tezos-taco-shop-payout
-title: Paying out profits from the Taco Shop
----
-
-import Syntax from '@theme/Syntax';
-
-In the
-[previous tutorial](tezos-taco-shop-smart-contract.md)
-we have learnt how to setup & interact with the LIGO CLI. Followed an
-implementation of a simple Taco Shop smart contract for our
-entrepreneur Pedro.
-
-In this tutorial we will make sure Pedro has access to tokens that
-people have spent at his shop when buying tacos.
-
-
-
-
-
-
-
-## Analysing the Current Contract
-
-
-
-### **`taco-shop.mligo`**
-
-```cameligo group=a
-module TacoShop = struct
- type taco_supply =
- {
- current_stock : nat;
- max_price : tez
- }
-
- type taco_shop_storage = (nat, taco_supply) map
-
- [@entry]
- let buy_taco (taco_kind_index : nat) (taco_shop_storage : taco_shop_storage)
- : operation list * taco_shop_storage =
- (* Retrieve the taco_kind from the contract's storage or fail *)
-
- let taco_kind =
- match Map.find_opt (taco_kind_index) taco_shop_storage with
- Some k -> k
- | None -> failwith "Unknown kind of taco" in
- let current_purchase_price : tez =
- taco_kind.max_price / taco_kind.current_stock in
- (* We won't sell tacos if the amount is not correct *)
-
- let () =
- if (Tezos.get_amount ()) <> current_purchase_price
- then
- failwith
- "Sorry, the taco you are trying to purchase has a different price" in
- (* Update the storage decreasing the stock by 1n *)
-
- let taco_shop_storage =
- Map.update
- taco_kind_index
- (Some
- {taco_kind with current_stock = abs (taco_kind.current_stock - 1n)})
- taco_shop_storage in
- [], taco_shop_storage
-
-end
-
-let default_storage : TacoShop.taco_shop_storage =
- Map.literal
- [
- (1n,
- {
- current_stock = 50n;
- max_price = 50000000mutez
- });
- (2n,
- {
- current_stock = 20n;
- max_price = 75000000mutez
- })
- ]
-```
-
-
-
-
-
-### **`taco-shop.jsligo`**
-
-```jsligo group=a
-namespace TacoShop {
- export type taco_supply = { current_stock: nat, max_price: tez };
- export type taco_shop_storage = map;
-
- // @entry
- function buy_taco(taco_kind_index: nat, taco_shop_storage: taco_shop_storage): [list, taco_shop_storage] {
- /* Retrieve the taco_kind from the contracts storage or fail */
- const taco_kind : taco_supply =
- $match(Map.find_opt (taco_kind_index, taco_shop_storage), {
- "Some": kind => kind,
- "None": () => failwith ("Unknown kind of taco")
- });
- const current_purchase_price : tez = taco_kind.max_price / taco_kind.current_stock ;
- /* We won't sell tacos if the amount is not correct */
- if ((Tezos.get_amount ()) != current_purchase_price)
- return failwith ("Sorry, the taco you are trying to purchase has a different price");
- else {
- /* Update the storage decreasing the stock by 1n */
- const taco_shop_storage = Map.update (
- taco_kind_index,
- ["Some" as "Some", {...taco_kind, current_stock : abs (taco_kind.current_stock - (1 as nat)) }],
- taco_shop_storage );
- return [[], taco_shop_storage]
- }
- }
-};
-
-const default_storage: TacoShop.taco_shop_storage =
- Map.literal(
- list(
- [
- [1 as nat, { current_stock: 50 as nat, max_price: 50000000 as mutez }],
- [2 as nat, { current_stock: 20 as nat, max_price: 75000000 as mutez }]
- ]
- )
- );
-
-```
-
-
-
-### Purchase Price Formula
-
-Pedro's Taco Shop contract currently enables customers to buy tacos,
-at a price based on a simple formula.
-
-
-
-```cameligo skip
-let current_purchase_price : tez =
- taco_kind.max_price / taco_kind.current_stock
-```
-
-
-
-
-
-```jsligo skip
-const current_purchase_price : tez =
- taco_kind.max_price / taco_kind.current_stock
-```
-
-
-
----
-
-## Designing a Payout Scheme
-
-Pedro is a standalone business owner, and in our case, he does not
-have to split profits and earnings of the taco shop with anyone. So
-for the sake of simplicity, we will payout all the earned XTZ directly
-to Pedro right after a successful purchase.
-
-This means that after all the *purchase conditions* of our contract
-are met, e.g., the correct amount is sent to the contract, we will not
-only decrease the supply of the individual purchased *taco kind*, but
-we will also transfer this amount in a *subsequent transaction* to
-Pedro's personal address.
-
-## Forging a Payout Transaction
-
-### Defining the Recipient
-
-In order to send tokens, we will need a receiver address, which, in
-our case, will be Pedro's personal account. Additionally we will wrap
-the given address as a *`contract (unit)`*, which represents either a
-contract with no parameters, or an implicit account.
-
-
-
-```cameligo group=ex1
-let ownerAddress : address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV"
-let receiver : unit contract =
- match (Tezos.get_contract_opt ownerAddress : unit contract option) with
- Some (contract) -> contract
- | None -> (failwith "Not a contract" : unit contract)
-```
-
-
-
-
-
-```jsligo group=ex1
-const ownerAddress : address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV"
-
-const receiver : contract =
- $match(Tezos.get_contract_opt(ownerAddress) as option>, {
- "Some": contract => contract,
- "None": () => failwith ("Not a contract") as contract
- })
-```
-
-
-
-> Would you like to learn more about addresses, contracts and
-> operations in LIGO? Check out the
-> [LIGO cheat sheet](../../api/cheat-sheet.md)
-
-### Adding the Transaction to the List of Output Operations
-
-Now we can transfer the amount received by `buy_taco` to Pedro's
-`ownerAddress`. We will do so by forging a `transaction (unit, amount,
-receiver)` within a list of operations returned at the end of our
-contract.
-
-
-
-```cameligo group=ex1
-let payoutOperation : operation = Tezos.transaction () (Tezos.get_amount ()) receiver
-let operations : operation list = [payoutOperation]
-```
-
-
-
-
-
-```jsligo group=ex1
-const payoutOperation : operation = Tezos.transaction (unit, Tezos.get_amount (), receiver) ;
-const operations : list = [payoutOperation];
-```
-
-
-
----
-
-## Finalising the Contract
-
-
-
-### **`taco-shop.mligo`**
-
-```cameligo group=b
-module TacoShop = struct
- type taco_supply =
- {
- current_stock : nat;
- max_price : tez
- }
-
- type taco_shop_storage = (nat, taco_supply) map
-
- let ownerAddress : address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address)
-
- [@entry]
- let buy_taco (taco_kind_index : nat) (taco_shop_storage : taco_shop_storage)
- : operation list * taco_shop_storage =
- (* Retrieve the taco_kind from the contract's storage or fail *)
-
- let taco_kind =
- match Map.find_opt (taco_kind_index) taco_shop_storage with
- Some k -> k
- | None -> failwith "Unknown kind of taco" in
- let current_purchase_price : tez =
- taco_kind.max_price / taco_kind.current_stock in
- (* We won't sell tacos if the amount is not correct *)
-
- let () =
- if (Tezos.get_amount ()) <> current_purchase_price
- then
- failwith
- "Sorry, the taco you are trying to purchase has a different price" in
- (* Update the storage decreasing the stock by 1n *)
-
- let taco_shop_storage =
- Map.update
- taco_kind_index
- (Some
- {taco_kind with current_stock = abs (taco_kind.current_stock - 1n)})
- taco_shop_storage in
-
- let receiver : unit contract =
- match (Tezos.get_contract_opt ownerAddress : unit contract option) with
- Some (contract) -> contract
- | None -> (failwith "Not a contract" : unit contract) in
-
- let payoutOperation : operation = Tezos.transaction () (Tezos.get_amount ()) receiver in
- let operations : operation list = [payoutOperation] in
-
- operations, taco_shop_storage
-end
-
-let default_storage : TacoShop.taco_shop_storage =
- Map.literal
- [
- (1n,
- {
- current_stock = 50n;
- max_price = 50000000mutez
- });
- (2n,
- {
- current_stock = 20n;
- max_price = 75000000mutez
- })
- ]
-```
-
-
-
-
-
-### **`taco-shop.jsligo`**
-
-```jsligo group=b
-namespace TacoShop {
- export type taco_supply = { current_stock: nat, max_price: tez };
- export type taco_shop_storage = map;
-
- const ownerAddress : address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV";
-
- const donationAddress : address = "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx";
-
- // @entry
- function buy_taco(taco_kind_index: nat, taco_shop_storage: taco_shop_storage): [list, taco_shop_storage] {
- /* Retrieve the taco_kind from the contracts storage or fail */
- const taco_kind: taco_supply =
- $match(Map.find_opt(taco_kind_index, taco_shop_storage), {
- "Some": kind => kind,
- "None": () => failwith("Unknown kind of taco")
- });
- const current_purchase_price: tez =
- taco_kind.max_price / taco_kind.current_stock;
- /* We won't sell tacos if the amount is not correct */
-
- if ((Tezos.get_amount()) != current_purchase_price) {
- return failwith(
- "Sorry, the taco you are trying to purchase has a different price"
- )
- } else {
- /* Update the storage decreasing the stock by 1n */
-
- const taco_shop_storage =
- Map.update(
- taco_kind_index,
- [
- "Some" as "Some", {
- ...taco_kind, current_stock: abs(taco_kind.current_stock - (1 as nat))
- }
- ],
- taco_shop_storage
- );
-
- const receiver : contract =
- $match(Tezos.get_contract_opt (ownerAddress), {
- "Some": contract => contract,
- "None": () => failwith ("Not a contract")
- });
-
- const donationReceiver : contract =
- $match((Tezos.get_contract_opt (donationAddress)), {
- "Some": contract => contract,
- "None": () => failwith ("Not a contract")
- });
-
- const donationAmount = ((Tezos.get_amount ()) / (10 as nat)) as tez;
-
- // Pedro will get 90% of the amount
- const op1 =
- $match (Tezos.get_amount () - donationAmount, {
- "Some": x => Tezos.transaction (unit, x, receiver),
- "None": () => failwith ("Insufficient balance")
- });
- const op2 = Tezos.transaction (unit, donationAmount, donationReceiver);
- const operations : list = [ op1 , op2 ];
-
- return [operations, taco_shop_storage]
- }
- };
-}
-
-const default_storage: TacoShop.taco_shop_storage =
- Map.literal(
- list(
- [
- [1 as nat, { current_stock: 50 as nat, max_price: 50000000 as mutez }],
- [2 as nat, { current_stock: 20 as nat, max_price: 75000000 as mutez }]
- ]
- )
- );
-
-```
-
-
-
-### Dry-run the Contract
-
-To confirm that our contract is valid, we can dry-run it. As a result,
-we see a *new operation* in the list of returned operations to be
-executed subsequently.
-
-
-
-```cameligo skip
-ligo run dry-run taco-shop.mligo --syntax cameligo --amount 1 --entry-point buy_taco 1n "Map.literal [
- (1n, { current_stock = 50n; max_price = 50tez }) ;
- (2n, { current_stock = 20n; max_price = 75tez }) ;
-]"
-```
-
-
-
-
-
-```jsligo skip
-ligo run dry-run taco-shop.jsligo --syntax jsligo -m TacoShop --amount 1 --entry-point buy_taco '1 as nat' "default_storage"
-```
-
-
-
-
-
-Operation(...bytes) included in the output
-
-
-
-
-**Done! Our tokens are no longer locked in the contract, and instead
- they are sent to Pedro's personal account/wallet.**
-
----
-
-## 👼 Bonus: Donating Part of the Profits
-
-Because Pedro is a member of the Speciality Taco Association (STA), he
-has decided to donate **10%** of the earnings to the STA. We will just
-add a `donationAddress` to the contract, and compute a 10% donation
-sum from each taco purchase.
-
-
-
-```cameligo group=bonus
-let ownerAddress : address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address)
-let donationAddress : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address)
-
-let receiver : unit contract =
- match ((Tezos.get_contract_opt ownerAddress) : unit contract option) with
- Some contract -> contract
- | None -> ((failwith "Not a contract") : unit contract)
-
-let donationReceiver : unit contract =
- match ((Tezos.get_contract_opt donationAddress) : unit contract option) with
- Some contract -> contract
- | None -> ((failwith "Not a contract") : unit contract)
-
-let donationAmount : tez = (Tezos.get_amount ()) / 10n
-
-let operations : operation list =
- // Pedro will get 90% of the amount
- let op = match ((Tezos.get_amount ()) - donationAmount) with
- | Some x -> Tezos.transaction () x receiver
- | None -> (failwith "Insufficient balance")
- in
- [ op ; Tezos.transaction () donationAmount donationReceiver ]
-```
-
-
-
-
-
-```jsligo group=bonus
-const ownerAddress : address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV";
-const donationAddress : address = "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx";
-
-const receiver : contract =
- $match((Tezos.get_contract_opt (ownerAddress)) as option>, {
- "Some": contract => contract,
- "None": () => (failwith ("Not a contract")) as contract
- });
-
-const donationReceiver : contract =
- $match((Tezos.get_contract_opt (donationAddress)) as option>, {
- "Some": contract => contract,
- "None": () => (failwith ("Not a contract")) as contract
- });
-
-const donationAmount = ((Tezos.get_amount ()) / (10 as nat)) as tez;
-
-// Pedro will get 90% of the amount
-const op1 =
- $match((Tezos.get_amount ()) - donationAmount, {
- "Some": x => Tezos.transaction (unit, x, receiver),
- "None": () => failwith ("Insufficient balance")
- });
-const op2 = Tezos.transaction (unit, donationAmount, donationReceiver);
-const operations : list = [ op1 , op2 ];
-```
-
-
-
-This will result into two operations being subsequently executed on the blockchain:
-- Donation transfer (10%)
-- Pedro's profits (90%)
diff --git a/gitlab-pages/docs/tutorials/taco-shop/tezos-taco-shop-smart-contract.md b/gitlab-pages/docs/tutorials/taco-shop/tezos-taco-shop-smart-contract.md
deleted file mode 100644
index a3ad20ab5a..0000000000
--- a/gitlab-pages/docs/tutorials/taco-shop/tezos-taco-shop-smart-contract.md
+++ /dev/null
@@ -1,649 +0,0 @@
----
-id: tezos-taco-shop-smart-contract
-title: The Taco Shop Smart Contract
----
-
-import Syntax from '@theme/Syntax';
-import Link from '@docusaurus/Link';
-
-
-
-Meet **Pedro**, our *artisan taco chef*, who has decided to open a
-Taco shop on the Tezos blockchain, using a smart contract. He sells
-two different kinds of tacos: **el Clásico** and the **Especial
-del Chef**.
-
-To help Pedro open his dream taco shop, we will implement a smart
-contract that will manage supply, pricing & sales of his tacos to the
-consumers.
-
-
-
-
-
----
-
-## Pricing
-
-Pedro's tacos are a rare delicacy, so their **price goes up** as the
-**stock for the day begins to deplete**.
-
-Each taco kind, has its own `max_price` that it sells for, and a
-finite supply for the current sales life-cycle.
-
-> For the sake of simplicity, we will not implement the replenishing
-> of the supply after it has run out.
-
-### Daily Offer
-
-|**kind** |id |**available_stock**| **max_price**|
-|---|---|---|---|
-|Clásico | `1n` | `50n` | `50tez` |
-|Especial del Chef | `2n` | `20n` | `75tez` |
-
-### Calculating the Current Purchase Price
-
-The current purchase price is calculated with the following formula:
-
-```cameligo skip
-current_purchase_price = max_price / available_stock
-```
-
-#### El Clásico
-|**available_stock**|**max_price**|**current_purchase_price**|
-|---|---|---|
-| `50n` | `50tez` | `1tez`|
-| `20n` | `50tez` | `2.5tez` |
-| `5n` | `50tez` | `10tez` |
-
-#### Especial del chef
-|**available_stock**|**max_price**|**current_purchase_price**|
-|---|---|---|
-| `20n` | `75tez` | `3.75tez` |
-| `10n` | `75tez` | `7.5tez`|
-| `5n` | `75tez` | `15tez` |
-
----
-## Draft a first contract
-### Designing the Taco Shop's Contract Storage
-
-First think to do when you create a smart contract is
-think about what gonna be stored onto it.
-We know that Pedro's Taco Shop serves two kinds of tacos, so we will
-need to manage stock individually, per kind. Let us define a type,
-that will keep the `stock` & `max_price` per kind in a record with two
-fields. Additionally, we will want to combine our `taco_supply` type
-into a map, consisting of the entire offer of Pedro's shop.
-
-**Taco shop's storage**
-
-
-
-```cameligo group=TacoShop
-type taco_supply = { current_stock : nat ; max_price : tez }
-
-type taco_shop_storage = (nat, taco_supply) map
-```
-
-
-
-
-
-```jsligo group=TacoShop
-export type taco_supply = { current_stock : nat , max_price : tez };
-
-export type taco_shop_storage = map ;
-```
-
-
-
-Now that the storage is defined, let's interact with it.
-
-### Selling the Tacos for Free
-
-Create your first entrypoint `buy_taco` which is doing nothing for now :
-
-
-
-```cameligo skip
-[@entry]
-let buy_taco (taco_kind_index : nat) (taco_shop_storage : taco_shop_storage) : operation list * taco_shop_storage = [], taco_shop_storage
-
-```
-
-
-
-
-
-```jsligo skip
-// @entry
-const buy_taco = (taco_kind_index: nat, taco_shop_storage: taco_shop_storage): [list, taco_shop_storage] => [[], taco_shop_storage]
-```
-
-
-
-It's already possible to compile your contract by running :
-
-
-
-```
-ligo compile contract taco_shop.jsligo
-```
-
-
-
-
-
-```
-ligo compile contract taco_shop.mligo
-```
-
-
-
-> To avoid warning at compilation, change `taco_kind_index` into `_taco_kind_index`, it'll tell to the compiler that this variable is authorized to not be used.
-
-
-A good practice is to scope your contract into a [module](../../language-basics/modules).
-
-
-
-```cameligo group=b12
-module TacoShop = struct
- type taco_supply =
- {
- current_stock : nat;
- max_price : tez
- }
-
- type taco_shop_storage = (nat, taco_supply) map
-
- [@entry]
- let buy_taco (taco_kind_index : nat) (taco_shop_storage : taco_shop_storage) : operation list * taco_shop_storage =
- [], taco_shop_storage
-
-end
-```
-
-
-
-
-
-```jsligo group=b12
-
-namespace TacoShop {
- type taco_supply = { current_stock: nat, max_price: tez };
- export type taco_shop_storage = map;
-
- // @entry
- const buy_taco = (taco_kind_index: nat, taco_shop_storage: taco_shop_storage): [list, taco_shop_storage] =>
- [[], taco_shop_storage]
-};
-
-```
-
-> We export `taco_shop_storage` to be accessible outside the module/namespace on the next section.
-
-
-
-There is an impact onto the compilation, now you have to tell to the compiler which [module](../../language-basics/modules) it need to compile :
-
-```
-ligo compile contract taco_shop.mligo -m TacoShop
-```
-
-### Populating our Storage
-
-When deploying contract, it is crucial to provide a correct
-initial storage value. In our case the storage is type-checked as
-`taco_shop_storage`, because the default storage is not directly used in the code,
-we encourage to declare the type, if your storage mutate, your default_storage will be in error.
-Reflecting [Pedro's daily offer](tezos-taco-shop-smart-contract.md#daily-offer),
-our storage's value will be defined as follows:
-
-
-
-```cameligo group=TacoShop
-let default_storage: taco_shop_storage = Map.literal [
- (1n, { current_stock = 50n ; max_price = 50tez }) ;
- (2n, { current_stock = 20n ; max_price = 75tez }) ;
-]
-```
-
-
-
-
-
-```jsligo group=TacoShop
-const default_storage: taco_shop_storage = Map.literal ([
- [1 as nat, { current_stock : 50 as nat, max_price : 50 as tez }],
- [2 as nat, { current_stock : 20 as nat, max_price : 75 as tez }]
-]);
-```
-
-
-
-> The storage value is a map with two bindings (entries) distinguished
-> by their keys `1n` and `2n`.
-
-Out of curiosity, let's try to use LIGO `compile storage` command compile this value down to Michelson.
-
-
-
-```zsh
-ligo compile storage TacoShop.jsligo default_storage -m TacoShop
-# Output:
-#
-# { Elt 1 (Pair 50 50000000) ; Elt 2 (Pair 20 75000000) }
-```
-
-
-
-
-
-```zsh
-ligo compile storage TacoShop.jsligo default_storage -m TacoShop
-# Output:
-#
-# { Elt 1 (Pair 50 50000000) ; Elt 2 (Pair 20 75000000) }
-```
-
-
-
-Our initial storage record is compiled to a Michelson map `{ Elt 1 (Pair 50 50000000) ; Elt 2 (Pair 20 75000000) }`
-holding the `current_stock` and `max_prize` in as a pair.
-
----
-## Implement some logic
-
-### Decreasing `current_stock` when a Taco is Sold
-
-In order to decrease the stock in our contract's storage for a
-specific taco kind, a few things needs to happen:
-
-- retrieve the `taco_kind` from our storage, based on the
- `taco_kind_index` provided;
-- subtract the `taco_kind.current_stock` by `1n`;
-- we can find the absolute value of the subtraction above by
- calling `abs` (otherwise we would be left with an `int`);
-- update the storage, and return it.
-
-
-
-```cameligo skip
-[@entry]
-let buy_taco (taco_kind_index : nat) (taco_shop_storage : taco_shop_storage) : operation list * taco_shop_storage =
- (* Retrieve the taco_kind from the contract's storage or fail *)
- let taco_kind =
- match Map.find_opt (taco_kind_index) taco_shop_storage with
- | Some k -> k
- | None -> failwith "Unknown kind of taco"
- in
- (* Update the storage decreasing the stock by 1n *)
- let taco_shop_storage = Map.update
- taco_kind_index
- (Some { taco_kind with current_stock = abs (taco_kind.current_stock - 1n) })
- taco_shop_storage
- in
- [], taco_shop_storage
-```
-
-
-
-
-
-```jsligo skip
-// @entry
-function buy_taco(taco_kind_index: nat, taco_shop_storage: taco_shop_storage): [list, taco_shop_storage] {
- /* Retrieve the taco_kind from the contracts storage or fail */
- const taco_kind: taco_supply =
- $match (Map.find_opt (taco_kind_index, taco_shop_storage), {
- "Some": kind => kind,
- "None": ()=> failwith ("Unknown kind of taco")
- });
-
- // Update the storage decreasing the stock by 1n
- const taco_shop_storage_updated = Map.update (
- taco_kind_index,
- ["Some" as "Some", {...taco_kind,
- current_stock : abs(taco_kind.current_stock - (1 as nat)) }],
- taco_shop_storage );
- return [[], taco_shop_storage_updated]
-};
-```
-
-
-
-### Making Sure We Get Paid for Our Tacos
-
-In order to make Pedro's taco shop profitable, he needs to stop giving
-away tacos for free. When a contract is invoked via a transaction, an
-amount of tezzies to be sent can be specified as well. This amount is
-accessible within LIGO as `Tezos.get_amount`.
-
-To make sure we get paid, we will:
-
-- calculate a `current_purchase_price` based on the
- [equation specified earlier](tezos-taco-shop-smart-contract.md#calculating-the-current-purchase-price)
-- check if the sent amount matches the `current_purchase_price`:
- - if not, then our contract will fail (`failwith`)
- - otherwise, stock for the given `taco_kind` will be decreased and
- the payment accepted
-
-
-
-```cameligo group=TacoShop
-[@entry]
-let buy_taco (taco_kind_index : nat) (taco_shop_storage : taco_shop_storage)
- : operation list * taco_shop_storage =
- (* Retrieve the taco_kind from the contract's storage or fail *)
-
- let taco_kind =
- match Map.find_opt (taco_kind_index) taco_shop_storage with
- Some k -> k
- | None -> failwith "Unknown kind of taco" in
- let current_purchase_price : tez =
- taco_kind.max_price / taco_kind.current_stock in
- (* We won't sell tacos if the amount is not correct *)
-
- let () =
- if (Tezos.get_amount ()) <> current_purchase_price
- then
- failwith
- "Sorry, the taco you are trying to purchase has a different price" in
- (* Update the storage decreasing the stock by 1n *)
-
- let taco_shop_storage =
- Map.update
- taco_kind_index
- (Some
- {taco_kind with current_stock = abs (taco_kind.current_stock - 1n)})
- taco_shop_storage in
- [], taco_shop_storage
-```
-
-
-
-
-
-```jsligo group=TacoShop
-// @entry
-function buy_taco (taco_kind_index: nat, taco_shop_storage: taco_shop_storage) : [list, taco_shop_storage] {
- /* Retrieve the taco_kind from the contracts storage or fail */
- const taco_kind : taco_supply =
- $match (Map.find_opt (taco_kind_index, taco_shop_storage), {
- "Some": kind => kind,
- "None": () => failwith ("Unknown kind of taco")
- });
- const current_purchase_price : tez = taco_kind.max_price / taco_kind.current_stock ;
- /* We won't sell tacos if the amount is not correct */
- if ((Tezos.get_amount ()) != current_purchase_price)
- return failwith ("Sorry, the taco you are trying to purchase has a different price");
- else {
- /* Update the storage decreasing the stock by 1 nat */
- const taco_shop_storage = Map.update (
- taco_kind_index,
- ["Some" as "Some", {...taco_kind, current_stock : abs (taco_kind.current_stock - (1 as nat)) }],
- taco_shop_storage );
- return [[], taco_shop_storage]
- }
-};
-```
-
-
-
-Now let's test our function against a few inputs using the LIGO test framework.
-For that, we will have another file in which will describe our test:
-
-
-
-```cameligo test-ligo group=test
-module TacoShop = Gitlab_pages.Docs.Tutorials.Taco_shop.Src.Tezos_taco_shop_smart_contract.TacoShop
-
-let assert_string_failure (res : test_exec_result) (expected : string) =
- let expected = Test.eval expected in
- match res with
- | Fail (Rejected (actual,_)) -> assert (Test.michelson_equal actual expected)
- | Fail _ -> failwith "contract failed for an unknown reason"
- | Success _ -> failwith "bad price check"
-
-let test =
- (* originate the contract with a initial storage *)
- let init_storage = Map.literal [
- (1n, { current_stock = 50n ; max_price = 50tez }) ;
- (2n, { current_stock = 20n ; max_price = 75tez }) ; ]
- in
- let { addr ; code = _; size = _ } = Test.originate (contract_of TacoShop) init_storage 0tez in
-
- (* Test inputs *)
- let clasico_kind : TacoShop parameter_of = Buy_taco 1n in
- let unknown_kind : TacoShop parameter_of = Buy_taco 3n in
-
- (* Auxiliary function for testing equality in maps *)
- let eq_in_map (r : TacoShop.taco_supply) (m : TacoShop.taco_shop_storage) (k : nat) =
- match Map.find_opt k m with
- | None -> false
- | Some v -> v.current_stock = r.current_stock && v.max_price = r.max_price in
-
- (* Purchasing a Taco with 1tez and checking that the stock has been updated *)
- let ok_case : test_exec_result = Test.transfer addr clasico_kind 1tez in
- let () = match ok_case with
- | Success _ ->
- let storage = Test.get_storage addr in
- assert ((eq_in_map { current_stock = 49n ; max_price = 50tez } storage 1n) &&
- (eq_in_map { current_stock = 20n ; max_price = 75tez } storage 2n))
- | Fail _ -> failwith ("ok test case failed")
- in
-
- (* Purchasing an unregistred Taco *)
- let nok_unknown_kind = Test.transfer addr unknown_kind 1tez in
- let () = assert_string_failure nok_unknown_kind "Unknown kind of taco" in
-
- (* Attempting to Purchase a Taco with 2tez *)
- let nok_wrong_price = Test.transfer addr clasico_kind 2tez in
- let () = assert_string_failure nok_wrong_price "Sorry, the taco you are trying to purchase has a different price" in
- ()
-```
-
-
-
-
-
-```jsligo test-ligo group=test
-import * as TacoShop from "gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/TacoShop.jsligo";
-
-function assert_string_failure (res: test_exec_result, expected: string) {
- const expected_bis = Test.eval(expected);
- $match(res, {
- "Fail": x =>
- $match(x, {
- "Rejected": y =>
- Assert.assert(Test.michelson_equal(y[0], expected_bis)),
- "Balance_too_low": _ =>
- failwith("contract failed for an unknown reason"),
- "Other": _o =>
- failwith("contract failed for an unknown reason")
- }),
- "Success": _s => failwith("bad price check")
- });
-}
-
-const test = (
- (_u: unit): unit => {
- /* Originate the contract with a initial storage */
- let init_storage =
- Map.literal(
- list(
- [
- [1 as nat, { current_stock: 50 as nat, max_price: 50000000 as mutez }],
- [2 as nat, { current_stock: 20 as nat, max_price: 75000000 as mutez }]
- ]
- )
- );
- const { addr , code , size } =
- Test.originate(contract_of(TacoShop), init_storage, 0 as mutez);
-
- /* Test inputs */
-
- const clasico_kind : parameter_of =
- ["Buy_taco" as "Buy_taco", 1 as nat];
-
- const unknown_kind : parameter_of =
- ["Buy_taco" as "Buy_taco", 3 as nat];
-
- /* Auxiliary function for testing equality in maps */
-
- const eq_in_map = (r: TacoShop.taco_supply, m: TacoShop.taco_shop_storage, k: nat) =>
- $match(Map.find_opt(k, m), {
- "None": () => false,
- "Some": v =>
- v.current_stock == r.current_stock && v.max_price == r.max_price
- });
-
- /* Purchasing a Taco with 1tez and checking that the stock has been updated */
-
- const ok_case: test_exec_result =
- Test.transfer(
- addr,
- clasico_kind,
- 1000000 as mutez
- );
-
- $match(ok_case, {
- "Success": _s =>
- (() => {
- let storage = Test.get_storage(addr);
- Assert.assert(
- eq_in_map(
- { current_stock: 49 as nat, max_price: 50000000 as mutez },
- storage,
- 1 as nat
- )
- &&
- eq_in_map(
- { current_stock: 20 as nat, max_price: 75000000
- as mutez },
- storage,
- 2 as nat
- )
- );
- })(),
- "Fail": _e => failwith("ok test case failed")
- });
-
- /* Purchasing an unregistred Taco */
-
- const nok_unknown_kind =
- Test.transfer(
- addr,
- unknown_kind,
- 1000000 as mutez
- );
- assert_string_failure(nok_unknown_kind, "Unknown kind of taco");
-
- /* Attempting to Purchase a Taco with 2tez */
-
- const nok_wrong_price =
- Test.transfer(
- addr,
- clasico_kind,
- 2000000 as mutez
- );
-
- assert_string_failure(
- nok_wrong_price,
- "Sorry, the taco you are trying to purchase has a different price"
- );
- return unit
- }
- )();
-```
-
-
-
-Let's break it down a little bit:
-- we include the file corresponding to the smart contract we want to
- test;
-- we define `assert_string_failure`, a function reading a transfer
- result and testing against a failure. It also compares the failing
- data - here, a string - to what we expect it to be;
-- `test` is actually performing the tests: Originates the taco-shop
- contract; purchasing a Taco with 1tez and checking that the stock
- has been updated ; attempting to purchase a Taco with 2tez and
- trying to purchase an unregistered Taco. An auxiliary function to
- check equality of values on maps is defined.
-
-> checkout the [reference page](../../reference/test.md) for a more detailed description of the Test API
-
-Now it is time to use the LIGO command `test`. It will evaluate our
-smart contract and print the result value of those entries that start
-with `"test"`:
-
-
-
-```zsh
-ligo run test gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/test.mligo
-# Output:
-#
-# Everything at the top-level was executed.
-# - test exited with value ().
-```
-
-
-
-
-
-```zsh
-ligo run test gitlab-pages/docs/tutorials/taco-shop/src/tezos-taco-shop-smart-contract/test.jsligo
-# Output:
-#
-# Everything at the top-level was executed.
-# - test exited with value ().
-```
-
-
-
-
-**The test passed ! That's it - Pedro can now sell tacos on-chain, thanks to Tezos & LIGO.**
-
----
-
-## 💰 Bonus: *Accepting Tips above the Taco Purchase Price*
-
-If you would like to accept tips in your contract, simply change the
-following line, depending on your preference.
-
-**Without tips**
-
-
-
-```cameligo skip
-if (Tezos.get_amount ()) <> current_purchase_price then
-```
-
-
-
-
-```jsligo skip
-if ((Tezos.get_amount ()) != current_purchase_price)
-```
-
-
-
-**With tips**
-
-
-
-```cameligo skip
-if (Tezos.get_amount ()) >= current_purchase_price then
-```
-
-
-
-
-
-```jsligo skip
-if ((Tezos.get_amount ()) >= current_purchase_price)
-```
-
-
diff --git a/gitlab-pages/website/sidebars.js b/gitlab-pages/website/sidebars.js
index c4bef81065..b5c376064d 100644
--- a/gitlab-pages/website/sidebars.js
+++ b/gitlab-pages/website/sidebars.js
@@ -12,15 +12,10 @@ const sidebars = {
"intro/template",
"intro/upgrade-v1",
],
- "Writing a Contract": [
- {
- "type": "category",
- "label": "First contract",
- "items": [
- "tutorials/taco-shop/tezos-taco-shop-smart-contract",
- "tutorials/taco-shop/tezos-taco-shop-payout"
- ]
- },
+ "Tutorial": [
+ "tutorials/taco-shop/selling-tacos",
+ "tutorials/taco-shop/testing-contract",
+ "tutorials/taco-shop/getting-payouts",
],
"Syntax": [
"syntax/comments",
diff --git a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-payout/dry-run-1.png b/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-payout/dry-run-1.png
deleted file mode 100644
index a8930f63ff..0000000000
Binary files a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-payout/dry-run-1.png and /dev/null differ
diff --git a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-payout/get-money.svg b/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-payout/get-money.svg
deleted file mode 100644
index 117937d258..0000000000
--- a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-payout/get-money.svg
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
diff --git a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-1.png b/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-1.png
deleted file mode 100644
index e685074fce..0000000000
Binary files a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-1.png and /dev/null differ
diff --git a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-2.png b/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-2.png
deleted file mode 100644
index 6f5c902e0b..0000000000
Binary files a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-2.png and /dev/null differ
diff --git a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-3.png b/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-3.png
deleted file mode 100644
index 5eb7178854..0000000000
Binary files a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-3.png and /dev/null differ
diff --git a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-4.png b/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-4.png
deleted file mode 100644
index 6ee09b1181..0000000000
Binary files a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-4.png and /dev/null differ
diff --git a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-5.png b/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-5.png
deleted file mode 100644
index ac390ce9cd..0000000000
Binary files a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-5.png and /dev/null differ
diff --git a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/install-ligo.png b/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/install-ligo.png
deleted file mode 100644
index ca33648207..0000000000
Binary files a/gitlab-pages/website/static/img/tutorials/get-started/tezos-taco-shop-smart-contract/install-ligo.png and /dev/null differ