Smart contract
A smart contract is some code written in Michelson language (a low-level stack-based turing-complete language).
It defines all entry points (invocable functions) of the smart contract. It defines the prototype of each entry point (e.g. specifies the parameters types of the entry point). It defines the storage of the smart contract.
Storage
The storage is an allocated memory space associated to a smart contract. The storage is a persistent data store for the smart contract.
The description of the storage is done by strongly-typing the data structure.
Entry points
Entry points of a smart contract describe how to mutate a storage.
Executing an entry point takes some parameters and a state of a storage and returns a new state of storage and some operations

The execution of an entry point produces a new state of the storage of the smart contract. If the entry point execution did not throw an exception and did not fail then the new state of storage is applied.
Operations are transactions (smart contract invocation) that will be sent to some other contracts. They will trigger an entry point of the targeted contract or a tez transfer (no invocation of entry point). If the execution of an entry point produces operations (an ordered list of transactions) then they are sent and executed following the order of the list of operations.
Deploy
A smart contract must be deployed on the blockchain in order to be invoked. When deploying a smart contract on the blockchain, one must specify the initial state of the storage.
Deployment of a smart contract in Tezos is called “origination”.
Here is the syntax of the tezos command line to deploy a smart contract :
tezos-client originate contract <contract_name> for <user> transferring <amount_tez> from <from_user> \ running <tz_file> \ --init '<initial_storage>' --burn-cap <gaz_fee>
<contract_name> name given to the contract <tz_file> path of the Michelson smart contract code (TZ file). <amount_tez> is the quantity of tez being transferred to the newly deployed contract. If a contract balance reaches 0 then it is deactivated. <from_user> account from which the tez are taken from (and transferred to the new contract). <initial_storage> is a Michelson expression. The –init parameter is used to specify initial state of the storage. <gaz_fee> it specifies the the maximal fee the user is willing to pay for this operation (using the –burn-cap parameter).
Invoke
Once the smart contract has been deployed on the blockchain (contract-origination operation baked into a block), it is possible to invoke an entry point of the smart contract using the command line.
Here is the syntax of the tezos command line to invoke a smart contract :
tezos-client transfer <amount_tez> from <user> to <contract_name> --arg '<entrypoint_invocation>' --dry-run
<amount_tez> is the quantity of tez being transferred to the contract. <contract_name> name given to the contract <entrypoint_invocation> is a Michelson expression specifying the entry point and its corresponding parameters. For example, in Ligo the invocation call ‘Increment(5)’ would be translated into following Michelson expression ‘Left (Right 5)’.
⚠️ Notice that the –arg parameter specifies an entry point call.
⚠️ Notice that the –dry-run parameter simulate the invocation of the entrypoint.
Ligo compiler
In order to produce a smart contract, a tool called transpiler (aka LIGO compiler) is used to transform LIGO code into Michelson code. Michelson smart contract are stored in a file with .tz extension.
This LIGO compiler is also used to transform “LIGO expression” into “Michelson expression” as needed to deploy or invoke a smart contract.
Compile
Here is how to transform LIGO code into Michelson code using the LIGO compiler in command line.
ligo compile-contract code.religo mainFunc > code.tz
argument is the name of the “main function” in the .ligo file. (see Chapter “Main Function”).
⚠️ Notice that the output of the command is the Michelson code. We just redirect the command output into a .tz file.
Initial storage
Here is how to transform LIGO expression into Michelson expression using the LIGO compiler in command line.
ligo compile-storage [options] code.religo mainFunc '<ligo-expression>'
<ligo-expression> is a LIGO expression
Invocation parameter
Here is how to transform LIGO expression into Michelson expression using the LIGO compiler in command line.
ligo compile-parameter [options] code.religo mainFunc '<ligo-expression>'
<ligo-expression> is a LIGO expression
Simulating
Here is how to simulate the execution of an entry point using the LIGO compiler in command line.
ligo dry-run [options] code.religo mainFunc '<entrypoint(p)>' '<storage_state>'
<storage*state> state of the storage when simulating the execution of the entry point <entrypoint(p)> entry point of the smart contract that is invoked (parameter _p* of this entry point is specified between parantheses).
Ligo Expression in command line
Let’s see some example how to transpile a storage LIGO expression into a Michelson one.
Let’s consider this smart contract which associates coordinates to a planet name.
// starmap.religo type coordinates = (int, int, int) type storage = map (string, coordinates) type return = (list (operation), storage); type parameter = | AddPlanet ((string, coordinates)) | DoNothing let addPlanet = ((input,store) : ((string,coordinates),storage)) : return => { let modified : storage = switch (Map.find_opt (input[0], store)) { | Some (v) => (failwith("planet already exist") : storage) | None => Map.add (input[0],input[1], store) }; (([] : list (operation)), modified); } let main = ((action,store) : (parameter,storage)): return => switch (action) { | AddPlanet (input) => addPlanet ((input,store)) | DoNothing => (([] : list (operation)),store) };
Maps
The Map.literal predefined function can be used to initialize a map
Here is an example of a command line ligo compile-storage for transpiling a map containing a tuple.
ligo compile-storage starmap.religo main 'Map.literal ([("earth", (1,1,1))])'
Tuples
Initialization of elements of a tuple is specified between ( and ) separated by comma ,.
Here is an example of a command line ligo compile-storage for transpiling a map containing a tuple.
ligo compile-storage starmap.religo main 'Map.literal ([("earth", (1,1,1))])'
This command returns :
{ Elt "earth" (Pair (Pair 1 1) 1) }
Record
Initialization of elements of a record is specified between { and } separated by comma ,. Each element is a key/value pair separated by : and follow the syntax :
{ <key1> : <value1>, <key2> : <value2> }
Let’s modify our type coordinates to be a record instead of a tuple.
// starmap2.religo type coordinates = { x : int, y : int, z : int } ... let main = ((action,store) : (parameter,storage)): return => switch (action) { | AddPlanet (input) => addPlanet ((input,store)) | DoNothing => (([] : list (operation)),store) };
Here is an example of a command line ligo compile-storage for transpiling a map containing a record tuple.
ligo compile-storage starmap2.religo main 'Map.literal ([("earth", {x:1,y:1,z:1})])'
This command returns :
{ Elt "earth" (Pair (Pair 1 1) 1) }
⚠️ Notice that the record is transformed into pairs (same for tuples).
Your mission
We want to prepare the initial state of our star system database before deploying the following smart contract. It would be nice to simulate our entry point AddPlanet.
//starmap3.religo type coordinates = { x : int, y : int, z : int} type planets = map (string, coordinates) type system = { name : string, systemplanets : planets } type storage = system type return = (list (operation), storage); type parameter = | AddPlanet ((string, coordinates)) | DoNothing let addPlanet = ((input,store) : ((string,coordinates),storage)) : return => { let modified : planets = switch (Map.find_opt (input[0], store.systemplanets)) { | Some (v) => (failwith("planet already exist") : planets) | None => Map.add (input[0],input[1], store.systemplanets) }; (([] : list (operation)), {name : store.name, systemplanets : modified}); } let main = ((action,store) : (parameter,storage)): return => switch (action) { | AddPlanet (input) => addPlanet ((input,store)) | DoNothing => (([] : list (operation)),store) };
1- Write the compile-storage command and the LIGO expression for initializing the Sol system containing planet “earth” with coordinates (2,7,1).
2- Write the dry-run command and the LIGO expression for adding a planet “mars” with coordinates (4,15,2) in our Sol system. ⚠️ Remind that the dry-run command expects a parameter “<entrypoint(p)>” and a parameter “<storage_state>” as shown in Simulating section. For this dry-run command you must write the “<entrypoint(p)>” parameter and reuse the Sol system of step 1 as “<storage_state>” parameter.