Skip to main content
Version: Next

Compiling contracts

You must compile LIGO contracts to Michelson before deploying them. LIGO can also help you compile the initial storage value for a contract and parameters for calls to contracts.

Compiling contracts

To compile a LIGO contract, make sure that LIGO is installed as described in Installation. Then, pass the source file to the ligo compile contract command.

For example, this command compiles a contract that is at the root level of a source file named my_contract.jsligo and writes it to the file my_contract.tz:

ligo compile contract my_contract.jsligo -o my_contract.tz

If the contract is in a module, pass the name of the module to the -m argument, as in this example:

ligo compile contract my_contract.jsligo -m MyModule -o my_contract.tz

Now you can deploy (originate) the contract; see Deploying contracts.

For more information about the ligo compile contract command, see compile contract.

info

The ligo compile contract command does not automatically run tests in the source file. To run tests, use the ligo run test command as described in Testing.

Compiling storage

When you originate a contract, you set the initial value of the contract storage as a Michelson value. The ligo compile storage command compiles LIGO expressions to Michelson expressions that you can use for the initial value of the storage.

For example, this contract has a complex storage type that includes two records and an address:

namespace ComplexStorage {
type my_record = {
x: int,
y: int,
z: int,
};
type my_labels = {
a: string,
b: string,
c: string,
};
type storage = [my_record, my_labels, address];
type return_type = [list<operation>, storage];
// @entry
const noop = (_u: unit, storage: storage): return_type => [[], storage];
}

To compile an initial storage value for this contract, create a JsLIGO expression of the storage type and pass it to the ligo compile storage command, as in this example:

ligo compile storage -m ComplexStorage complexStorage.jsligo \
'[{x: 1, y: 2, z: 3}, {a: "A", b: "B", c: "C"}, "tz1QCVQinE8iVj1H2fckqx6oiM85CNJSK9Sx" as address]'

The result is a Michelson expression that you can use as the initial storage value:

(Pair (Pair 1 2 3) (Pair "A" "B" "C") "tz1QCVQinE8iVj1H2fckqx6oiM85CNJSK9Sx")

If you deploy a contract with the octez-client originate contract command, you can pass this expression as the value of the --init argument, as in this example:

octez-client originate contract ComplexStorage \
transferring 0 from my_wallet running ComplexStorage.tz \
--init '(Pair (Pair 1 2 3) (Pair "A" "B" "C") "tz1QCVQinE8iVj1H2fckqx6oiM85CNJSK9Sx")' --burn-cap 2

For more information about the ligo compile storage command, see compile storage.

Compiling parameters

If you have the source code of a LIGO contract, you can use the ligo compile parameter command to compile the parameter that another contract or client can use to call it.

For example, this contract has an entrypoint that accepts a complex parameter:

namespace ComplexParam {
type storage = int;
type returnType = [list<operation>, storage];
type paramType = [list<int>, list<int>, [string, string]];
const sum_fold = ([result, i]: [int, int]): int => result + i;
const mult_fold = ([result, i]: [int, int]): int => result * i;
// @entry
function complexmath (param: paramType, _s: storage): returnType {
const [list1, list2, str_tuple] = param;
const sum: int = List.fold(sum_fold, list1, 0);
const product: int = List.fold(mult_fold, list2, 1);
const [str1, str2] = str_tuple;
const string_diff: int = String.length(str2) - String.length(str1);
const newVal = (sum + product) * string_diff;
return [[], newVal];
}
}

To compile a parameter to call this contract, create a JsLIGO expression for the parameter and pass it and the entrypoint name to the ligo compile parameter command, as in this example:

ligo compile parameter ComplexParam.jsligo -m ComplexParam
'["Complexmath" as "Complexmath", ([[1, 2, 3], [2, 2, 1], ["three", "fifteen"]])]'

The result is a Michelson expression that represents passing the value to the entrypoint:

(Pair { 1 ; 2 ; 3 } { 2 ; 2 ; 1 } "three" "fifteen")

You can use this expression as the parameter to call the contract, as in this example:

If you deploy a contract with the octez-client originate contract command, you can pass this expression as the value of the --init argument, as in this example:

octez-client transfer 0 from my_wallet to ComplexParam \
--arg '(Pair { 1 ; 2 ; 3 } { 2 ; 2 ; 1 } "three" "fifteen")' \
--burn-cap 1

For more information about the ligo compile parameter command, see compile parameter.

Compiling expressions

The ligo compile expression command is more general than the ligo compile parameter command because it does not take any source file into account. Instead, it compiles a single LIGO expression to Michelson using only the information you provide to the command, which means that you must provide information like type annotations and the syntax to use.

One use of this command is to compile the parameter for a view, which you can not do with the ligo compile parameter command. For example, this contract has a view that accepts a complex parameter with multiple numbers and does some math on them:

type storage_type = int;
type return_type = [list<operation>, storage_type];
type view_param = [
list<int>,
[int, int, int],
option<int>,
];
class Counter {
@entry
add = (value: int, storage: storage_type): return_type =>
[[], storage + value];
@entry
sub = (value: int, storage: storage_type): return_type =>
[[], storage - value];
@view
math = (param: view_param, storage: storage_type): int => {
const [intList, intSet, intOption] = param;
// Get the sum of the ints in the list
let listSum = 0;
for (const i of intList) listSum = listSum + i;
// Multiply by the sum of the ints in the set
const [a, b, c] = intSet;
const setSum = a + b + c;
let returnValue = listSum * setSum;
// If the option int was provided, subtract it
return $match(intOption, {
"None": () => storage + returnValue,
"Some": (value) => storage + returnValue - value,
});
}
}

To compile the parameter to pass to the view, create an expression that matches the parameter for the view, including type annotations to ensure that the command compiles it to the correct types, as in this example:

ligo compile expression jsligo "[([1, 2, 3, 4]: list<int>), Set.literal([1, 2, 3]), [\"Some\" as \"Some\", 2]]"

The result is a Michelson expression that is the parameter for the view:

(Pair { 1 ; 2 ; 3 ; 4 } { 1 ; 2 ; 3 } (Some 2))

You can use this value as the parameter to call the view, as in this example:

octez-client run view math on contract counter with input "(Pair { 1 ; 2 ; 3 ; 4 } { 1 ; 2 ; 3 } (Some 2))"