Skip to content

Commit 372d3f9

Browse files
Draft of update to taco shop tutorial
1 parent c61d549 commit 372d3f9

File tree

32 files changed

+1259
-1770
lines changed

32 files changed

+1259
-1770
lines changed

gitlab-pages/docs/tutorials/getting-started/getting-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,4 +575,4 @@ octez-client get contract storage for counter
575575
Now you have a simple LIGO smart contract and can test it, deploy it, and call it.
576576
You can use it as a starting point to write your own contracts and experiment with LIGO.
577577

578-
You can also continue with the [Taco shop tutorial](../taco-shop/tezos-taco-shop-smart-contract) to learn more about programming with LIGO.
578+
You can also continue with the [Taco shop tutorial](../taco-shop/selling-tacos) to learn more about programming with LIGO.
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
---
2+
title: "Part 3: Getting the payouts"
3+
---
4+
5+
Now that the customer-facing entrypoint of the contract is ready, you can set up the administrator-related entrypoint.
6+
In this case, Pedro needs a way to reset the stock of tacos and send the tez from the contract to his account.
7+
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`.
8+
9+
## Adding administrator information
10+
11+
Also for the sake of simplicity, the contract will hard-code Pedro's account address.
12+
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.
13+
As it is, this contract cannot change the administrator address after it is deployed, so use caution.
14+
15+
1. In the contract, after the storage information, add a constant with the address of the owner:
16+
17+
```jsligo skip
18+
export const owner_address: address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV";
19+
```
20+
21+
This is a made-up address for the purposes of the tutorial.
22+
In a production application, you would set the administrator address in storage when you deploy the contract.
23+
Note that the code defines the address as a LIGO `address` type; without the `: address` type declaration, LIGO would assume that it was a string.
24+
25+
1. Add a function to get the administrator's account:
26+
27+
```jsligo skip
28+
const get_receiver_contract = () => match(Tezos.get_contract_opt(owner_address)) {
29+
when(Some(contract)): contract;
30+
when(None): failwith("Couldn't find account");
31+
};
32+
```
33+
34+
Sending tez to a user account means treating the user account as though it was a smart contract account.
35+
This way, sending tez to a user account works in the same way as sending tez to a smart contract.
36+
37+
1. In the `payout` entrypoint, add this code to verify that the administrator is calling the entrypoint:
38+
39+
```jsligo skip
40+
// Ensure that only the admin can call this entrypoint
41+
if (Tezos.get_sender() != owner_address) {
42+
failwith("Only the admin can call this entrypoint");
43+
}
44+
```
45+
46+
1. Add this code to generate the operation that sends tez to the administrator account:
47+
48+
```jsligo skip
49+
const payout_operation = Tezos.Operation.transaction(unit, Tezos.get_balance(), get_receiver_contract());
50+
```
51+
52+
The `Tezos.Operation.transaction` function creates a Tezos transaction.
53+
There are many kinds of internal transactions in Tezos, but most smart contracts deal with these transactions:
54+
55+
- Transferring tez to another account
56+
- Calling an entrypoint on a smart contract
57+
58+
Calling an entrypoint on a smart contract (either the current contract or another contract) is beyond the scope of this tutorial.
59+
For information, see [Calling a contract](../../syntax/contracts/operation#calling-a-contract).
60+
61+
The `Tezos.Operation.transaction` function takes these parameters:
62+
63+
1. The parameter to pass, in this case `unit`, which means no value
64+
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
65+
1. The address of the target contract
66+
67+
1. Replace the `payout` entrypoint's `return` statement with this code:
68+
69+
```jsligo skip
70+
return [[payout_operation], default_storage];
71+
```
72+
73+
Creating the transaction is not enough to run it; you must return it in the list of operations at the end of the entrypoint.
74+
75+
The complete entrypoint looks like this:
76+
77+
```jsligo skip
78+
@entry
79+
const payout = (_u: unit, _taco_data: taco_data): [
80+
list<operation>,
81+
taco_data
82+
] => {
83+
84+
// Ensure that only the admin can call this entrypoint
85+
if (Tezos.get_sender() != owner_address) {
86+
failwith("Only the admin can call this entrypoint");
87+
}
88+
89+
const payout_operation = Tezos.Operation.transaction(unit, Tezos.get_balance(), get_receiver_contract());
90+
91+
return [[payout_operation], default_storage];
92+
}
93+
```
94+
95+
That's all you need to do to reset the storage and send the contract's tez to the administrator.
96+
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.
97+
98+
## Testing the new entrypoint
99+
100+
Of course, after you implement the `payout` entrypoint, you should add tests for it.
101+
102+
1. At the end of the test function, add this code to get the current balance of Pedro's account and the contract:
103+
104+
```jsligo skip
105+
// Test the payout entrypoint as the administrator
106+
const owner_balance_before = Test.Address.get_balance(TacoShop.owner_address);
107+
const contract_balance_before = Test.Typed_address.get_balance(contract.taddr);
108+
```
109+
110+
1. Add this code to call the `payout` entrypoint and verify that the storage was updated, as in previous tests:
111+
112+
```jsligo skip
113+
const payoutResult =
114+
Test.Contract.transfer(
115+
Test.Typed_address.get_entrypoint("payout", contract.taddr),
116+
unit,
117+
0tez
118+
);
119+
match(payoutResult) {
120+
when(Success(_s)):
121+
do {
122+
const storage = Test.Typed_address.get_storage(contract.taddr);
123+
// Check that the stock has been reset
124+
Assert.assert(
125+
eq_in_map(
126+
Map.find(1n, initial_storage),
127+
storage,
128+
1n
129+
));
130+
Assert.assert(
131+
eq_in_map(
132+
Map.find(2n, initial_storage),
133+
storage,
134+
2n
135+
));
136+
Test.IO.log("Successfully reset taco storage");
137+
}
138+
when(Fail(_err)): failwith("Failed to collect the payout");
139+
};
140+
```
141+
142+
1. Add this code to verify that Pedro's account received the tez from the contract:
143+
144+
```jsligo skip
145+
// Check that the balance of the contract was sent to the administrator
146+
const owner_balance_after = Test.Address.get_balance(TacoShop.owner_address);
147+
Assert.assert(owner_balance_before + contract_balance_before == owner_balance_after);
148+
```
149+
150+
1. Add this code to generate a test account and verify that it can not call the `payout` entrypoint because it is not the administrator:
151+
152+
```jsligo skip
153+
// Verify that the entrypoint fails if called by someone else
154+
const other_user_account = Test.Account.address(1n);
155+
Test.State.set_source(other_user_account);
156+
const failedPayoutResult =
157+
Test.Contract.transfer(
158+
Test.Typed_address.get_entrypoint("payout", contract.taddr),
159+
unit,
160+
0tez
161+
);
162+
match(failedPayoutResult) {
163+
when(Success(_s)): failwith("A non-admin user was able to call the payout entrypoint");
164+
when(Fail(_err)): Test.IO.log("Successfully prevented a non-admin user from calling the payout entrypoint");
165+
};
166+
```
167+
168+
1. Run the test with `ligo run test taco_shop.jsligo` and verify that the test runs successfully.
169+
170+
Now you can allow different users to do different things in the contract.
171+
172+
## Conclusion
173+
174+
Now you have a contract that Pedro can use to sell tacos and manage the profits and the taco stock.
175+
From here you can expand the contract in many ways, such as:
176+
177+
- Adding more types of tacos
178+
- Changing how the price of tacos is calculated
179+
- Expanding the administrator functionality
180+
- Accepting more than the price of the taco as a tip
181+
- Adding more tests
182+
183+
You can also try deploying the contract to a test network and trying it in a real Tezos environment.

0 commit comments

Comments
 (0)