Skip to content

Commit

Permalink
refactor chapter 10 to 16
Browse files Browse the repository at this point in the history
  • Loading branch information
AymericBethencourt committed Apr 22, 2020
1 parent 39896e7 commit 12ceeb5
Show file tree
Hide file tree
Showing 43 changed files with 355 additions and 605 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INLINE_RUNTIME_CHUNK=false
Binary file added public/fonts/vulcan.ttf
Binary file not shown.
40 changes: 21 additions & 19 deletions src/Chapter/Chapter.controller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,22 @@ import { PENDING, RIGHT, WRONG } from "../Chapters/ChapterAbout/ChapterAbout.con
import { dataAddresses } from "../Chapters/ChapterAddresses";
import { dataBuiltIns } from "../Chapters/ChapterBuiltIns";
import { dataConditionals } from "../Chapters/ChapterConditionals";
import { dataMainFunction } from "../Chapters/ChapterMainFunction";
import { dataFunctions } from "../Chapters/ChapterFunctions";
import { dataLists } from "../Chapters/ChapterLists";
import { dataLoops } from "../Chapters/ChapterLoops";
import { dataMainFunction } from "../Chapters/ChapterMainFunction";
import { dataMaps } from "../Chapters/ChapterMaps";
import { dataMath } from "../Chapters/ChapterMath";
import { dataPatternMatching } from "../Chapters/ChapterPatternMatching";
import { dataRecords } from "../Chapters/ChapterRecords";
import { dataStrings } from "../Chapters/ChapterStrings";
import { dataTimestamps } from "../Chapters/ChapterTimestamps";
import { dataTransactions } from "../Chapters/ChapterTransactions";
import { dataTuples } from "../Chapters/ChapterTuples";
import { dataTypes } from "../Chapters/ChapterTypes";
import { dataVariables } from "../Chapters/ChapterVariables";
import { ChapterView } from "./Chapter.view";
import { dataTuples } from "../Chapters/ChapterTuples";
import { dataFailWith } from "../Chapters/ChapterFailwith";
import { dataVariant } from "../Chapters/ChapterVariant";
import { dataPatternMatching } from "../Chapters/ChapterPatternMatching";
import { dataCast } from "../Chapters/ChapterCast";
import { dataTransactions } from "../Chapters/ChapterTransactions";
import { dataLists } from "../Chapters/ChapterLists";
import { ChapterView } from "./Chapter.view";

export const Chapter = () => {
const [validatorState, setValidatorState] = useState(PENDING);
Expand Down Expand Up @@ -63,26 +61,30 @@ export const Chapter = () => {
setData({ course: dataLists.course, exercise: dataLists.exercise, solution: dataLists.solution });
if (pathname === "/12")
setData({
course: dataMainFunction.course,
exercise: dataMainFunction.exercise,
solution: dataMainFunction.solution,
course: dataVariant.course,
exercise: dataVariant.exercise,
solution: dataVariant.solution,
});
if (pathname === "/13")
setData({
course: dataTimestamps.course,
exercise: dataTimestamps.exercise,
solution: dataTimestamps.solution,
course: dataMainFunction.course,
exercise: dataMainFunction.exercise,
solution: dataMainFunction.solution,
});
if (pathname === "/14")
setData({ course: dataBuiltIns.course, exercise: dataBuiltIns.exercise, solution: dataBuiltIns.solution });
setData({ course: dataLoops.course, exercise: dataLoops.exercise, solution: dataLoops.solution });
if (pathname === "/15")
setData({ course: dataCast.course, exercise: dataCast.exercise, solution: dataCast.solution });
setData({ course: dataAddresses.course, exercise: dataAddresses.exercise, solution: dataAddresses.solution });
if (pathname === "/16")
setData({ course: dataTuples.course, exercise: dataTuples.exercise, solution: dataTuples.solution });
setData({ course: dataBuiltIns.course, exercise: dataBuiltIns.exercise, solution: dataBuiltIns.solution });
if (pathname === "/17")
setData({ course: dataFailWith.course, exercise: dataFailWith.exercise, solution: dataFailWith.solution });
setData({
course: dataTransactions.course,
exercise: dataTransactions.exercise,
solution: dataTransactions.solution,
});
if (pathname === "/18")
setData({ course: dataVariant.course, exercise: dataVariant.exercise, solution: dataVariant.solution });
setData({ course: dataTimestamps.course, exercise: dataTimestamps.exercise, solution: dataTimestamps.solution });
if (pathname === "/19")
setData({
course: dataPatternMatching.course,
Expand Down
34 changes: 14 additions & 20 deletions src/Chapters/ChapterAddresses/course.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,30 @@
# Chapter 12 : Addresses
# Chapter 15 : Addresses

## Addresses
<dialog character="mechanics">The scan showed some unusual activity on the planet Osiris, it's likely we will find Xenomorph activity there. We should gear up first. I suggest we stop by a weapon merchant. Here is the address.</dialog>

You can define Tezos addresses by casting a string to an address type :
## Casting

You can cast a type into another type if you are sure they are compatible :

```
const my_account : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address)
const a : int = int (1n)
const b : nat = abs (-3)
```

⚠️ You will not see a transpilation error if the address you enter is wrong but the execution will fail.
⚠️ You will not see a transpilation error if the types are not compatible but the execution will fail.

## Signatures
## Addresses

You can also cast strings as Tezos signatures (edsig, spsig) :
You can define Tezos addresses by casting a string to an address type :

```
const my_sig : signature = ("edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" : signature)
const my_account : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address)
```

## Keys

Same principle for Tezos public keys :

```
const my_key : key = ("edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" : key)
```
⚠️ You will not see a transpilation error if the address you enter is wrong but the execution will fail.

## Your mission

<!-- prettier-ignore -->
1- Modify the mapping *owner\_of* so that the owner is no longer a string but an address.

2- Make the Galactica belong to address "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"
<!-- prettier-ignore -->1- Define *ship\_address* as _tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV_

3- Make the Enterprise belong to address "tz1YfuHeaaPyKFGAjrCskb8kzEEkmaMhiDhd"
<!-- prettier-ignore -->2- Define *vendor\_address* as _tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx_
31 changes: 3 additions & 28 deletions src/Chapters/ChapterAddresses/exercise.ligo
Original file line number Diff line number Diff line change
@@ -1,29 +1,4 @@
type ship is
record [
name : string;
code : string;
price : tez;
created_at : timestamp
]

// Type your solution below
type owner is map (string, string)

function main (const p : unit; const store : owner) : (list(operation) * owner) is
block {
const my_ship : ship =
record [
name = "Galactica";
code = "222031";
price = 1tez;
created_at = Tezos.now
];

function purchase (const purchase_price : tez) : bool is
// Type your solution below
const owner_of : owner =
map [
"Galactica" -> "Adama";
"Enterprise" -> "Kirk";
];
store := owner_of;
} with ((nil: list(operation)), store)

return True
33 changes: 5 additions & 28 deletions src/Chapters/ChapterAddresses/solution.ligo
Original file line number Diff line number Diff line change
@@ -1,29 +1,6 @@
type ship is
record [
name : string;
code : string;
price : tez;
created_at : timestamp
]

// Type your solution below
type owner is map (string, address)

function main (const p : unit; const store : owner) : (list(operation) * owner) is
block {
const my_ship : ship =
record [
name = "Galactica";
code = "222031";
price = 1tez;
created_at = Tezos.now
];

function purchase (const purchase_price : tez) : bool is
// Type your solution below
const owner_of : owner =
map [
"Galactica" -> ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address);
"Enterprise" -> ("tz1YfuHeaaPyKFGAjrCskb8kzEEkmaMhiDhd" : address);
];
store := owner_of;
} with ((nil: list(operation)), store)
const ship_address : address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address);
const vendor_address : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address);

return True
91 changes: 26 additions & 65 deletions src/Chapters/ChapterBuiltIns/course.md
Original file line number Diff line number Diff line change
@@ -1,88 +1,49 @@
# Chapter 14 : Built-ins
# Chapter 16 : Built-ins

A LIGO smart contract can query part of the state of the Tezos blockchain by means of built-in values. In this section you will find how those built-ins can be utilized.

## Accepting or Declining Tokens in a Smart Contract

This example shows how Tezos.amount and failwith can be used to decline any transaction that sends more tez than 0tez, that is, no incoming tokens are accepted.

```
type parameter is unit
type storage is unit
type return is list (operation) \* storage
function deny (const action : parameter; const store : storage) : return is
if Tezos.amount > 0tez then
(failwith ("This contract does not accept tokens.") : return)
else ((nil : list (operation)), store)
```
<dialog character="scientist">We need a Flux Capacitor, don't ask me why, you wouldn't get it. Just buy it!</dialog>

Note that amount is deprecated. Please use Tezos.amount.

## Access Control

This example shows how Tezos.source can be used to deny access to an entrypoint.
A LIGO smart contract can query part of the state of the Tezos blockchain by means of built-in values. In this section you will find how those built-ins can be utilized.

```
const owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
## A few built-ins

function main (const action : parameter; const store : storage) : return is
if Tezos.source =/= owner then (failwith ("Access denied.") : return)
else ((nil : list (operation)), store)
```
_Tezos.balance_ : Get the balance for the contract.

Note that source is deprecated. Please use Tezos.source.
_Tezos.amount_ : Get the amount of tez provided by the sender to complete this transaction.

## Inter-Contract Invocations
_Tezos.sender_ : Get the address that initiated the current transaction.

It would be somewhat misleading to speak of "contract calls", as this wording may wrongly suggest an analogy between contract "calls" and function "calls". Indeed, the control flow returns to the site of a function call, and composed function calls therefore are stacked, that is, they follow a last in, first out ordering. This is not what happens when a contract invokes another: the invocation is queued, that is, follows a first in, first our ordering, and the dequeuing only starts at the normal end of a contract (no failure). That is why we speak of "contract invocations" instead of "calls".
<!-- prettier-ignore -->*Tezos.self\_address* : Get the address of the currently running contract.

The following example shows how a contract can invoke another by emiting a transaction operation at the end of an entrypoint.
_Tezos.source_ : Get the originator (address) of the current transaction. That is, if a chain of transactions led to the current execution get the address that began the chain. Not to be confused with Tezos.sender, which gives the address of the contract or user which directly caused the current transaction.

The same technique can be used to transfer tokens to an implicit account (tz1, ...): all you have to do is use a unit value as the parameter of the smart contract.
<!-- prettier-ignore -->*Tezos.chain\_id* : Get the identifier of the chain to distinguish between main and test chains.

In our case, we have a counter.ligo contract that accepts an action of type parameter, and we have a proxy.ligo contract that accepts the same parameter type, and forwards the call to the deployed counter contract.
ℹ️ A more complete list is available on <a href="https://ligolang.org/docs/reference/current-reference" target="_blank">ligolang.org</a>

```
// counter.ligo
type parameter is
Increment of nat
| Decrement of nat
| Reset
## Failwith

type storage is unit
The keyword _failwith_ throws an exception and stop the execution of the smart contract

type return is list (operation) \* storage
```

failwith(<string_message>)
```
// proxy.ligo
type parameter is
Increment of nat
| Decrement of nat
| Reset

type storage is unit
type return is list (operation) \* storage
## Access Control

const dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address)
This example shows how Tezos.source can be used to deny access to an entrypoint.

function proxy (const action : parameter; const store : storage): return is
block {
const counter : contract (parameter) =
case (Tezos.get*contract_opt (dest) : option (contract (parameter))) of
Some (contract) -> contract
| None -> (failwith ("Contract not found.") : contract (parameter))
end;
```
const owner : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address);
const mock_param : parameter = Increment (5n);
const op : operation = Tezos.transaction (action, 0tez, counter);
const ops : list (operation) = list [op]
} with (ops, store)
function main (const action : parameter; const store : storage) : return is
if Tezos.source =/= owner then (failwith ("Access denied.") : return)
else ((nil : list (operation)), store)
```

_<string_message>_ must be a string value

## Your mission

Coming soon ...
<!-- prettier-ignore -->1- Check that the originitor address is indeed our *ship\_address*, or fail with _"Access denied"_

<!-- prettier-ignore -->2- Check that the sent amount corresponds to the *purchase\_price*, or fail with _"Incorrect amount"_
7 changes: 6 additions & 1 deletion src/Chapters/ChapterBuiltIns/exercise.ligo
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
// Type your solution below
function purchase (const purchase_price : tez) : bool is
const ship_address : address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address);
const vendor_address : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address);

// Type your solution below

return True
9 changes: 8 additions & 1 deletion src/Chapters/ChapterBuiltIns/solution.ligo
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
// Type your solution below
function purchase (const purchase_price : tez) : bool is
const ship_address : address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address);
const vendor_address : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address);

// Type your solution below
if Tezos.source =/= ship_address then failwith ("Access denied")
if Tezos.amount =/= purchase_price then failwith ("Incorrect amount")

return True
Loading

0 comments on commit 12ceeb5

Please sign in to comment.