Examples
Example 1: Modulo with LOOP
and IF
Let's illustrate the following Michelson instructions: LOOP
, DIP
, DUP
, SWAP
, PUSH
, CMPLE
, IF
, SUB
. The example below computes the modulo between two numbers (e.g. 7 % 5 = 2).
The idea is to repetitively subtract the divisor from the dividend. Once the dividend is smaller than the divisor, we have successfully computed the remainder.
The following smart contract takes a pair of integers and computes the modulo of these two integers (using a LOOP
instruction).
parameter (pair int int) ;
storage int ;
code { CAR ;
DUP ;
UNPAIR ;
COMPARE ;
GT ;
DIP { UNPAIR } ;
LOOP { DIP { DUP } ;
DUP ;
DIP { SWAP } ;
CMPLE ;
IF
{ PUSH bool False }
{ DIP { DUP } ; SUB ; PUSH bool True } ; } ;
DIP { DROP } ;
NIL operation ;
PAIR }
Now, let's simulate the execution of this snippet of code. For this example, the initial stack is initialized with 7 and 5 (in order to compute 7 % 5).
Notice that the LOOP
instruction stops when it is given a False
condition (it appears in red in the diagram below). In our example, the condition is initialized to True
because 7 is greater than 5 (and the modulo needs to be computed).
The execution of the "loop_example.tz" smart contract can be simulated with the following command:
octez-client run script loop_example.tz on storage '0' and input '(Pair 7 5)'
Example 2: Maximum of a list with ITER
and CMPLE
Let's illustrate the following Michelson instructions: CAR
, CDR
, ITER
, DIP
, DUP
, DROP
, SWAP
, CMPLE
, IF
, NONE
, SOME
, IF_NONE
, option
, list
. The following snippet of code computes the maximum of a list of integers.
The idea is to repetitively take an element from the list and compare it with the maximum computed so far. Once the list is processed, the stack contains the biggest integer of the list.
parameter (list int) ;
storage (option int) ;
code { CAR ;
DIP { NONE int } ;
ITER { SWAP ;
IF_NONE
{ SOME }
{ DIP { DUP } ;
DUP ;
DIP { SWAP } ;
CMPLE;
IF { DROP } { DIP { DROP } };
SOME
}
} ;
NIL operation ;
PAIR }
Notice that the storage stores an option int
. Indeed, if the given list is empty, then there is no maximum.
Notice, in red in the diagram above, that the ITER
instruction is called recursively on each element of the given list of integers.
If you have set up a Tezos node, you can use the octez-client program to simulate your smart contract (max_list.tz) with the following command.
octez-client run script max_list.tz on storage 'None' and input '{1;2;5;3;7;2;15;4}'
Example 3: Executing a lambda with EXEC
and LAMBDA
Let's illustrate the following Michelson instructions: EXEC
, LAMBDA
, SWAP
, PUSH
. The following snippet of code takes an integer and increments it using a lambda.
The idea is to define a lambda function (which increments an integer) and execute the function. Once the function has been applied, the result is returned as a new storage state.
parameter int ;
storage int ;
code { CAR ;
LAMBDA int int { PUSH int 1 ; ADD } ;
SWAP ;
EXEC ;
NIL operation ;
PAIR }
Example 4: Computing a sum with LOOP_LEFT
The following smart contract illustrates the LOOP_LEFT
instruction usage. It takes an integer as the parameter and computes the sum from zero to the given integer.
parameter int ;
storage int ;
code { CAR ; PUSH int 0 ; SWAP ; PAIR ;
LEFT int ;
LOOP_LEFT { DUP ;
CAR ;
DUP ;
PUSH int 1 ;
SWAP ;
SUB ;
DIP { SWAP ; CDR ; ADD };
DUP ;
GT ;
IF
{ PAIR ; LEFT int }
{ DROP ; RIGHT (pair int int) } } ;
NIL operation ;
PAIR }
Let's break down the execution of this smart contract. In our example, storage is only used to store the result of the execution. The diagram below shows how the sum of integers from 0 to 5 is computed.
FIGURE 4: Illustration of the `LOOP_LEFT` instructionExample 5 : Computing a factorial with LOOP_LEFT
Let's illustrate the following Michelson instructions: LOOP_LEFT
. The following snippet of code takes an integer and computes a factorial of the given integer; the result is saved in storage.
parameter int ;
storage int ;
code { PUSH int 1 ;
SWAP ;
CAR ;
PAIR ;
LEFT int ;
LOOP_LEFT
{ DUP ;
CAR ;
SWAP ;
CDR ;
PUSH int 0 ;
DIG 2 ;
DUP ;
DUG 3 ;
COMPARE ;
GT ;
IF { SWAP ;
DUP ;
DUG 2 ;
SWAP ;
MUL ;
PUSH int 1 ;
DIG 2 ;
SUB ;
PAIR ;
LEFT int }
{ SWAP ; DROP ; RIGHT (pair int int) } } ;
NIL operation ;
PAIR }