July 30th 2018: Tezos betanet has now launched, and this article doesn’t reflect the current state of the project. You can still read through it, but the code examples won’t work as is, and will need various changes. Up to date documentation for the betanet is available here. You can change the address to access docs for other branches like zeronet.

A word about different testnets: there is usually a zeronet running, which follows new developments closely and an alphanet which is more stable. The real network is currently called betanet (transactions persist to the main network). The alphanet is currently obsolete.

Some of these concerns have been addressed by Tezos – a new cryptocurrency that’s been publicized recently on account of a very successful fundraiser this July. Tezos is written in the functional language OCaml, which has a robust type system, making it easier to debug and maintain. Their smart contract language (called Michelson), is statically typed and designed with security in mind, to help avoid common errors that could be used to attack a contract. The language should lend itself to formal verification, which can be used to prove e.g. that a contract only sends out at most the same amount of money it receives (which helps against hackers attempting to steal money contained in a contract) or other properties of interest.

In this article, we will cover setting up a Tezos alphanet node and writing basic contracts in Michelson, look at various resources to help us learn Michelson, typecheck the contracts we write and finally run them.

There are a few ways to get an alphanet node up and running, but the easiest one is to use the provided docker image. For this we will need to have a recent version of docker installed. If your repository has an outdated version, add the docker official repo and install it from there. Instructions are available here.

After you have docker installed, follow the instructions here to download the alphanet script and run it. It will run a node and synchronize with the rest of the network. It can take a while to crunch the numbers before it gets to the latest block, so it might make sense to let it run in the background while doing something else. A few common issues are also described there, so check that first if something doesn’t work. Check that an account has been created for you with:

./alphanet.sh client get balance for my_account

If this gives you an error, check the Known Issues section on how to create a new account and give it money manually.

The try-michelson REPL by Dan Robinson should help you understand more complicated constructs or instructions. You can get similar output using the command line client as well, with the typecheck command:

./alphanet.sh client typecheck program container:path/to/myContract.tz

You can also check data literals:

./alphanet.sh client typecheck data "hello" against type string

One of the best sources of information for learning Michelson is the michelson-lang website by Milo Davis. The “A contract a day” series is a good way to pick up the principles of writing Michelson contracts.

parameter unit; return string; storage unit;

The stack at the beginning of contract execution has a pair containing the parameter and the storage.

[ pair unit unit ]

At the end of contract execution, the compiler expects to find a similar pair, containing the return value and the storage and we will get an error if the types don’t match.

Besides the header, the contract also contains some code to be executed. The code can be zero or more instructions that manipulate the stack and ideally do something useful. At the beginning, we have a pair containing the input and storage. We can use CAR and CDR to access the first or second element of the pair. We’d like to output a string , so we’ll use the PUSH instruction to push a string onto the stack. We don’t care about the storage, but the compiler expects to see a pair of return value and storage, so we’ll use the PAIR instruction to form a pair.

code {CDR;PUSH string "Hello World!";PAIR}

The whole contract looks like this:

parameter unit; return string; storage unit; code {CDR;PUSH string "Hello World!";PAIR}

Try running it in the try-michelson REPL. You’ll need to specify the starting storage and the input – since we are using the unit type, you need to use the placeholder value Unit for them. In the “Typecheck” tab, you can see the types of elements on the stack after each instruction.

Try changing the contract so that it returns a stored string instead. You can change the storage in the “Run” tab.

parameter string; return string; storage string; code {DUP;DIP{CDR};CAR;CONCAT;DUP;PAIR}

What’s going on here? The CAR and CDR instructions actually modify the top pair (i.e. they are destructive), so we need to duplicate the top pair with DUP if we want to use both elements. The DIP lets us execute a block of code on a deeper element of the stack (we are dipping into the stack, so to say).

In the following section, the first line of code contains type information for elements on the stack and beneath them are my comments detailing the meaning of individual pieces of data.

So the first pair becomes two pairs:

[ pair string string : pair string string ] ^ ^ ^ ^ | | | | input storage input storage

Then we dip into the stack:

[ pair string string ] ^ ^ | | input storage

We pick the second element:

[ string ] ^ | storage

We come back from the dip:

[ pair string string : string ] ^ | this is the storage

And then we go back to the top and pick the first element:

[ string : string ] ^ ^ | | input storage

Then we concatenate the strings:

[ string ] ^ | result

Duplicate the result:

[ string : string ] ^ ^ | | result result

And finally, create a new pair:

[ pair string string ] ^ ^ | | return value new storage

Remember, the first part of the pair is the return value and the second part is the new storage. Try running it!

Something’s still off though – we said we’d like to append the parameter to the storage, not the other way around. The CONCAT simply concatenates the strings, but we need the input parameter to go after the storage. We can use the SWAP instruction to accomplish this – it simply swaps the top two elements of the stack. Find a suitable place to use the instruction and try running the contract again.

NB: You might need to run the commands with sudo .

Start the node with:

./alphanet.sh start

Create a test.tz file with an empty contract:

parameter unit; return unit; storage unit; code {}

Typecheck it to make sure the node works:

./alphanet.sh client typecheck program container:test.tz -details

The details flag will let us see the types of elements after each instruction like in the REPL.

Now that we’ve confirmed that the contract is well typed, we can try running it.

./alphanet.sh client run program container:test.tz on storage Unit and input Unit -trace-stack

The trace-stack flag will let us see the values on the stack during the execution.

Let’s try to run our previous contract that appends strings – create an append.tz file for it. When trying to run the contract from the command line, we need to escape the strings like so:

./alphanet.sh client run program container:append.tz on storage '"Hello"' and input '" world!"'

A neat list of various data types and how to escape them is available at the michelson-lang website.

If you forget the precise syntax of a command, you can use help or man to list available options and commands.

./alphanet.sh client --help ./alphanet.sh client man

That’s it for this article :)

If you liked it, share or discuss it with people who might find it interesting! If there are any mistakes, please let me know (my email address is in the top bar). In the next one, we’ll look at transactions and how to publish contracts to the blockchain.