Chapter 3: Advanced

Lesson 10: Procedure

Procedures are another way to define now the state of the contract may change, but in contrast to transitions, procedures are not part of the public interface of the contract, and may not be invoked by sending a message to the contract.

The only way to invoke a procedure is to call it from a transition or from another procedure. Procedures can be used to abstract some logic from our transitions to make our code cleaner and easier to follow.

For example, we can use a procedure to clean up the way we emit events from our transitions. Here we accept two arguments, failure and error_code.

We then check the failure argument and accordingly emit the required events.

Note that the special parameters _sender , _origin and _amount are available to a procedure even though the procedure is invoked by a transition rather than by an incoming message. It is not necessary to pass these special parameters as arguments to the procedure.

We have a task for you!

Declare a send_message procedure that accepts a code argument of type Uint32.

Replace the use of the one_msg function and send msgs with the send_message procedure, with the appropriate code as argument.

Your Workspace

Show Solution

Solution

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

scilla_version 0
import BoolUtils
library SocialMediaPayment
let one_msg =
fun (msg: Message) =>
let nil_msg = Nil {Message} in
Cons {Message} msg nil_msg
let zero = Uint128 0
let not_owner_code = Uint32 1
let accepted_code = Uint32 0
let user_exists_code = Uint32 2
let true = True
contract SocialMediaPayment (owner: ByStr20)
field users: Map ByStr20 String
= Emp ByStr20 String
field used_usernames: Map String Bool
= Emp String Bool
(* Start typing from the line below. Declare the send_message procedure. *)
procedure send_message (code: Uint32)
msg = {
_tag: "";
_recipient: _sender;
_amount: zero;
code: code
};
msgs = one_msg msg;
send msgs
end
transition deposit()
sender_is_owner = builtin eq _sender owner;
match sender_is_owner with
| False =>
(* Start typing from the line below. Replace with the send_message procedure below. *)
send_message not_owner_code
| True =>
accept;
(* Start typing from the line below. Replace with the send_message procedure below. *)
send_message accepted_code
end
end
transition register_user (user_address: ByStr20, twitter_username: String)
user_exists <- exists users[user_address];
username_exists <- exists used_usernames[twitter_username];
already_exists = orb user_exists username_exists;
match already_exists with
| True =>
(* Start typing from the line below. Replace with the send_message procedure below. *)
send_message user_exists_code
| False =>
users[user_address] := twitter_username;
used_usernames[twitter_username] := true;
e = {_eventname: "register_user";
user: user_address;
username: twitter_username };
event e
end
end
scilla_version 0
import BoolUtils

library SocialMediaPayment

let one_msg = 
  fun (msg: Message) => 
  let nil_msg = Nil {Message} in
  Cons {Message} msg nil_msg

let zero = Uint128 0
let not_owner_code = Uint32 1
let accepted_code = Uint32 0
let user_exists_code = Uint32 2
let true = True

contract SocialMediaPayment (owner: ByStr20)


field users: Map ByStr20 String
  = Emp ByStr20 String

field used_usernames: Map String Bool
  = Emp String Bool

(* Start typing from the line below. Declare the send_message procedure. *)


transition deposit()
  sender_is_owner = builtin eq _sender owner;
  match sender_is_owner with
  | False =>

    (* Start typing from the line below. Replace with the send_message procedure below. *)
    msg = { _tag: "";
            _recipient: _sender;
            _amount: zero;
            code: not_owner_code};
    msgs = one_msg msg;
    send msgs

  | True =>
    accept;
    (* Start typing from the line below. Replace with the send_message procedure below. *)
    msg = { _tag: "";
            _recipient: _sender;
            _amount: zero;
            code: accepted_code};
    msgs = one_msg msg;
    send msgs

  end
end

transition register_user (user_address: ByStr20, twitter_username: String)

  user_exists <- exists users[user_address];
  username_exists <- exists used_usernames[twitter_username];
  already_exists = orb user_exists username_exists;

  match already_exists with
  | True =>
    (* Start typing from the line below. Replace with the send_message procedure below. *)
    msg = {_tag: ""; _recipient: _sender; _amount: zero; code: user_exists_code};
    msgs = one_msg msg;
    send msgs

  | False =>

    users[user_address] := twitter_username;
    used_usernames[twitter_username] := true;

    e = {_eventname: "register_user";
         user: user_address;
         username: twitter_username };
    event e

  end
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79