diff --git a/gitlab-pages/docs/language-basics/cheat-sheet.md b/gitlab-pages/docs/language-basics/cheat-sheet.md index 1e0e7aaef..6f46a6b3f 100644 --- a/gitlab-pages/docs/language-basics/cheat-sheet.md +++ b/gitlab-pages/docs/language-basics/cheat-sheet.md @@ -2,6 +2,8 @@ id: cheat-sheet title: Cheat Sheet --- +
+ @@ -32,6 +34,9 @@ title: Cheat Sheet |Variant *(pattern)* matching|
const a: action = Increment(5);
case a of
| Increment n -> n + 1
| Decrement n -> n - 1
end
| |Records|
type person is record
  age: int ;
  name: string ;
end

const john : person = record
  age = 18;
  name = "John Doe";
end

const name: string = john.name;
| |Maps|
type prices is map(nat, tez);

const prices : prices = map
  10n -> 60mtz;
  50n -> 30mtz;
  100n -> 10mtz;
end

const price: option(tez) = prices[50n];
| +|Contracts & Accounts|
const destinationAddress : address = "tz1...";
const contract : contract(unit) = get_contract(destinationAddress);
| +|Transactions|
const payment : operation = transaction(unit, amount, receiver);
| + - \ No newline at end of file +
\ No newline at end of file diff --git a/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-payout.ligo b/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-payout.ligo new file mode 100644 index 000000000..5623eaf3f --- /dev/null +++ b/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-payout.ligo @@ -0,0 +1,37 @@ +type taco_supply is record + current_stock : nat; + max_price : tez; +end +type taco_shop_storage is map(nat, taco_supply); + +const ownerAddress: address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV"; +const donationAddress: address = "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; + +function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_shop_storage) : (list(operation) * taco_shop_storage) is + begin + // Retrieve the taco_kind from the contract's storage + const taco_kind : taco_supply = get_force(taco_kind_index, taco_shop_storage); + + const current_purchase_price : tez = taco_kind.max_price / taco_kind.current_stock; + + if amount =/= current_purchase_price then + // we won't sell tacos if the amount isn't correct + fail("Sorry, the taco you're trying to purchase has a different price"); + else + // Decrease the stock by 1n, because we've just sold one + taco_kind.current_stock := abs(taco_kind.current_stock - 1n); + + // Update the storage with the refreshed taco_kind + taco_shop_storage[taco_kind_index] := taco_kind; + + const receiver: contract(unit) = get_contract(ownerAddress); + const donationReceiver: contract(unit) = get_contract(donationAddress); + + const donationAmount: tez = amount / 10n; + + const operations : list(operation) = list + transaction(unit, amount - donationAmount, receiver); + transaction(unit, donationAmount, donationReceiver); + end; + + end with (operations, taco_shop_storage) \ No newline at end of file diff --git a/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-payout.md b/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-payout.md new file mode 100644 index 000000000..f22f59452 --- /dev/null +++ b/gitlab-pages/docs/tutorials/get-started/tezos-taco-shop-payout.md @@ -0,0 +1,180 @@ +--- +id: tezos-taco-shop-payout +title: Paying out profits from the Taco Shop +--- + +In the [previous tutorial](tutorials/get-started/tezos-taco-shop-smart-contract.md) we've learned how to setup & interact with the LIGO CLI. Followed by implementation of a simple Taco Shop smart contract for our entepreneur Pedro. In this tutorial we'll make sure Pedro has access to tokens that people have spent at his shop when buying tacos. + + +
+ + +
+
Icons made by Smashicons from www.flaticon.com is licensed by CC 3.0 BY
+
+ + +## Analyzing the current contract + +### **`taco-shop.ligo`** +``` +type taco_supply is record + current_stock : nat; + max_price : tez; +end +type taco_shop_storage is map(nat, taco_supply); + +function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_shop_storage) : (list(operation) * taco_shop_storage) is + begin + // Retrieve the taco_kind from the contract's storage + const taco_kind : taco_supply = get_force(taco_kind_index, taco_shop_storage); + + const current_purchase_price : tez = taco_kind.max_price / taco_kind.current_stock; + + if amount =/= current_purchase_price then + // we won't sell tacos if the amount isn't correct + fail("Sorry, the taco you're trying to purchase has a different price"); + else + // Decrease the stock by 1n, because we've just sold one + taco_kind.current_stock := abs(taco_kind.current_stock - 1n); + + // Update the storage with the refreshed taco_kind + taco_shop_storage[taco_kind_index] := taco_kind; + end with ((nil : list(operation)), taco_shop_storage) +``` + +### Purchase price formula +Pedro's Taco Shop contract currently enables customers to buy tacos, at a computed price based on a simple formula. + +``` +const current_purchase_price : tez = taco_kind.max_price / taco_kind.current_stock; +``` + +### Replacing *spendable* smart contracts +However, due to the [recent protocol upgrade](http://tezos.gitlab.io/mainnet/protocols/004_Pt24m4xi.html) of the Tezos mainnet, Pedro can't access the tokens stored in his Shop's contract directly. This was previously possible via `spendable` smart contracts, which are no longer available in the new protocol. We will have to implement a solution to access tokens from the contract programatically. + +--- + +## Designing a payout scheme + +Pedro is a standalone bussines owner, and in our case, he doesn't have to split profits / earnings of the taco shop with anyone. So for the sake of simplicity, we'll payout all the earned XTZ directly to Pedro right after a succesful taco purchase. + +This means that after all the *purchase conditions* of our contract are met - e.g. correct amount is sent to the contract - we'll not only decrease the supply of the individual purchased *taco kind*, but we'll 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'll wrap the given address as a *`contract(unit)`* - which represents either a contract with no parameters, or an implicit account. + +``` +const ownerAddress : address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV"; +const receiver : contract(unit) = get_contract(ownerAddress); +``` + +> Would you like to learn more about addresses, contracts and operations in LIGO? Check out the [LIGO cheat sheet](language-basics/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. + + +``` +const payoutOperation : operation = transaction(unit, amount, receiver) ; +const operations : list(operation) = list + payoutOperation +end; +``` + +--- + +## Finalizing the contract + +### **`taco-shop.ligo`** +``` +type taco_supply is record + current_stock : nat; + max_price : tez; +end +type taco_shop_storage is map(nat, taco_supply); + +const ownerAddress: address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV"; + +function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_shop_storage) : (list(operation) * taco_shop_storage) is + begin + // Retrieve the taco_kind from the contract's storage + const taco_kind : taco_supply = get_force(taco_kind_index, taco_shop_storage); + + const current_purchase_price : tez = taco_kind.max_price / taco_kind.current_stock; + + if amount =/= current_purchase_price then + // we won't sell tacos if the amount isn't correct + fail("Sorry, the taco you're trying to purchase has a different price"); + else + // Decrease the stock by 1n, because we've just sold one + taco_kind.current_stock := abs(taco_kind.current_stock - 1n); + + // Update the storage with the refreshed taco_kind + taco_shop_storage[taco_kind_index] := taco_kind; + + const receiver : contract(unit) = get_contract(ownerAddress); + const payoutOperation : operation = transaction(unit, amount, receiver); + const operations : list(operation) = list + payoutOperation + end; + + end with (operations, taco_shop_storage) +``` + + +### 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. + +``` +ligo dry-run taco-shop.ligo --syntax pascaligo --amount 1 buy_taco 1n "map + 1n -> record + current_stock = 50n; + max_price = 50000000mtz; + end; + 2n -> record + current_stock = 20n; + max_price = 75000000mtz; + end; +end" +``` + + +
+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 (STA) Specialty Taco Association, he has decided to donate **10%** of the earnings to the STA. We'll just add a `donationAddress` to the contract, and compute a 10% donation sum from each taco purchase. + +``` +const ownerAddress: address = "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV"; +const donationAddress: address = "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; +``` + +``` +const receiver : contract(unit) = get_contract(ownerAddress); +const donationReceiver : contract(unit) = get_contract(donationAddress); + +const donationAmount: tez = amount / 10n; + +const operations : list(operation) = list + // Pedro will get 90% of the amount + transaction(unit, amount - donationAmount, receiver); + transaction(unit, donationAmount, donationReceiver); +end; +``` + +This will result into two operations being subsequently executed on the blockchain: +- Donation transfer (10%) +- Pedro's profits (90%) \ No newline at end of file diff --git a/gitlab-pages/website/sidebars.json b/gitlab-pages/website/sidebars.json index 708dc299a..3f80e2e51 100644 --- a/gitlab-pages/website/sidebars.json +++ b/gitlab-pages/website/sidebars.json @@ -16,6 +16,6 @@ "Road Map": ["contributors/road-map/short-term", "contributors/road-map/long-term"] }, "tutorials": { - "Get Started": ["tutorials/get-started/tezos-taco-shop-smart-contract"] + "Get Started": ["tutorials/get-started/tezos-taco-shop-smart-contract", "tutorials/get-started/tezos-taco-shop-payout"] } } diff --git a/gitlab-pages/website/static/css/custom.css b/gitlab-pages/website/static/css/custom.css index 890a8c081..7f643b6e2 100644 --- a/gitlab-pages/website/static/css/custom.css +++ b/gitlab-pages/website/static/css/custom.css @@ -228,6 +228,10 @@ body > div.fixedHeaderContainer > div > header > div > nav > ul > li:nth-child(5 background: transparent; } +.cheatsheet tr > td:first-of-type { + min-width: 240px; +} + @media only screen and (min-device-width: 360px) and (max-device-width: 736px) { }