Hello World In Scilla

Dean Schmid
7 min readJan 25, 2019

“Scilla imposes a structure on smart contracts that will make applications less vulnerable to attacks by eliminating certain known vulnerabilities directly at the language-level. Furthermore, the principled structure of Scilla will make applications inherently more secure and amenable to formal verification.”

Here is the Hello World contract. I encourage you to continually flip back and forth or split screen the contract, on the ide or github, as you work through this post.

(* HelloWorld contract *)

(***************************************************)
(* Scilla version *)
(***************************************************)

scilla_version 1

(***************************************************)
(* Associated library *)
(***************************************************)
library HelloWorld

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

let not_owner_code = Uint32 1
let set_hello_code = Uint32 2

(***************************************************)
(* The contract definition *)
(***************************************************)

contract HelloWorld
(owner: ByStr20)

field welcome_msg : String = ""

transition setHello (msg : String)
is_owner = builtin eq owner _sender;
match is_owner with
| False =>
msg = {_tag : "Main"; _recipient : _sender; _amount : 0; code : not_owner_code};
msgs = one_msg msg;
send msgs
| True =>
welcome_msg := msg;
msg = {_tag : "Main"; _recipient : _sender; _amount : 0; code : set_hello_code};
msgs = one_msg msg;
send msgs
end
end

transition getHello ()
r <- welcome_msg;
e = {_eventname: "getHello"; msg: r};
event e
end

It’s a lot to take in.

for now, I am going to ignore the library section at the top and jump ahead to this on line 8.

contract HelloWorld

This defines and names the contract.

(Im)mutable Variables

Scilla has two types of variable. Immutable and mutable variable.

First we worry about the immutable variables which will always immediately follow naming the contract.

In our Hello World contract we want to check that only the owner of the contract can use the contract. So we declare an immutable variable like this.

(owner : ByStr20)

Immutable variable are structured like this ([name] : [type]).

The IDE will require these initialisation parameters before deploying the contract.

Mutable Variables

When doing operations on data, we need to have variables whose value will be changed by the code in the contract.

These variables, which can be updated, are still stored on the blockchain and are known as the mutable variables.

To declare a mutable variable, we need to pay attention to three things:- Variable name: This is the identifier of the variable to be used by various operators later in the contract. Variable type: Choose the appropriate type of the variable. Such as Uint128 for amounts, String for names, ByStr20 for addresses etc. Variable value: We may choose to declare a variable with or without an initial value. https://github.com/noelyoo/learn-scilla

The mutable variable looks like this

field welcome_msg : String = ""//structurefield [Variable Name] : [Variable Type] = “[Variable Text]”
  • Field is the mutable variable keyword
  • welcome_msg is the name of our mutable variable
  • String is the type
  • At welcome_msg there is an empty string

The Contract So Far

contract HelloWorld
(owner: ByStr20)

field welcome_msg : String = ""

Transition

Now we need to set this mutable variable. This is done with a transition. Think of a transition like a function, and you will do just fine.

transition setHello (msg : String) //structure[keyword]  [Name] (parameter : type)

It’s very important to make sure only the owner of this contract (who we set as our immutable variable) is the only one able to call the setHello function (I mean transition)

Builtin?

Take a look at this next bit of code.

is_owner = builtin eq owner _sender;----------------Structure------------------[variable] = [keyword] [equivalence] [A] [B]// is_owner = A === B

builtin is a keyword that lets you use the builtin Scilla functionality. The functionality being used here is eq.

eq is a function that equates owner with _sender and returns either true or false. Similar to == or ===

_sender?

Every transition has access to _sender. It is the address of the account which called the transition.

is_owner = builtin eq owner _sender;

This sets is_owner to true or false depending on if the contract is owned by the account that’s calling the transition.

Match This Do That

now for a chunk

match is_owner with
| False =>
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : not_owner_code};
msgs = one_msg msg;
send msgs
| True =>
welcome_msg := msg;
msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : set_hello_code};
msgs = one_msg msg;
send msgs
end
end

Bit by bit

match is_owner with | False => 

A JavaScript Comparison

let is_owner = true || false;switch (is_owner) {
case true:
//Do something
break;
case false:
//Do something else;
break;
}

The match operator makes a comparison. If a condition is matched, it does whatever comes after this =>

What are we doing after this => ? It depends on if we take the false or the true path. If is_sender = false we do this.

False => msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : not_owner_code};

WTF?

You can’t understand what is happening up there, without first understanding what’s happening down here.

msgs = one_msg msg;
send msgs
  • one_msg is a utility function that allows you to create a list of messages and inserts msg into the list. (it’s defined above in the library)
  • This list of type messages are all stored in a variable named msgs
  • The messages are then sent

What Is A Message?

A message is a type. An outgoing message contains information

All messages need to have_tag, _recipient and _amount entries. If you leave them out, it will pass the type checker but when you try call the transition in you contract you will get this error.

msg = {_tag : "Main"; _recipient : _sender; _amount : Uint128 0; code : not_owner_code};

What does this all mean?

  • {_tag : “Main”; is old syntax and no longer necessary. Try using an empty string instead, and it will work fine.
  • _recipient : _sender; means that the sender is the recipient of this message.
  • _amount : Uint128 0; means that nothing is being sent.
  • code : not_owner_code} it’s defined up top in the library, but this either returns a 1 or 2.

The Library

library HelloWorldlet one_msg = 
fun (msg : Message) =>
let nil_msg = Nil {Message} in
Cons {Message} msg nil_msg
let not_owner_code = Int32 1
let set_hello_code = Int32 2

This is where the one_msg function is declared. It’s up in the library. So what is happening here?

fun is a keyword (arguments : type) => (*This is what happens*)

  • Nil creates an empty List. It takes the following form: Nil {A} , is an empty list of type {A}. Nil {Message}
  • What is in? in is not a separate keyword. Consider this,let v = expr1 in expr2. This is the way in OCaml to define a "local" variable. What it's saying is that you're going to use v as a named value in expr2, and its value when it appears in expr2 is the value of expr1.
  • in can also mean the same thing as a semicolon does in JavaScript or Python. It’s common syntax in functional programming.
let x = int32 1 in // is pretty much the same as saying 
let x = 1;
  • Cons adds an element to an existing list. It takes the following form: Cons {'A} h l, where 'A is a type variable that can be instantiated with any type and h is an element of type 'A that is inserted at the head of list l (of type List 'A).

I think that should clear up the one_msg function. It creates a list and then adds the transition argument to the list before sending it.

msgs = one_msg msg;
send msgs

The Final Transition

transition getHello ()
r <- welcome_msg;
e = {_eventname: "GetHello"; msg: r};
event e
end

Notice we are using an event here rather than send.

It’s also possible to write this transition like this with send

transition getHello ()
r <- welcome_msg;
msg = {_tag : “Main”; _recipient : _sender; _amount : Uint128 0; msg : r};
msgs = one_msg msg;
send msgs
end

In Scilla, there are two ways that transitions can transmit data. One way is through send messages and another way is through events.

send is used to send message to another smart contract and is not emitted back to your client application. Meanwhile, events are dispatched signals that smart contracts can use to transmit data to client applications.

r <- welcome_msg;

This takes the value in welcome_msg and copies it into r.

e = {_eventname : "Gethello"; msg : r};

The first part {_eventname : “Gethello”;} names the event. The eventname is compulsory. You can call the event whatever you want. “Gethello” can be “Leavegoodbye” it doesn’t make a difference. Next there is a ; followed by another name : value pair. msg is the name and r is the value. r of course, contains the value of welcome_msg.

finally

event e

emits the event called e.

References

https://github.com/noelyoo/learn-scilla

--

--

Dean Schmid

Full-Stack Developer, Web Designer. I’m a Lover of the Internet and all the Opportunity it Brings.