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.
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.
Show Solution
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
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879