Through a parent contract, I want to be able to originate multiple child contracts. How can I do this in LIGO?
2 Answers
Unfortunately, Tezos.create_contract
does not work well in practice. It only works if the child contract is extremely simple. The child code must either be written entirely inside the Tezos.create_contract
call, or all of the definitions it uses must be [@inline]
'd. If not all definitions are inlined, you will get the somewhat cryptic error "Not all free variables could be inlined in Tezos.create_contract usage."
A better alternative should be provided in some future Ligo version. Hopefully soon-ish.
In the meantime there is a workaround: compile your child contract separately, and use inline %Michelson
with CREATE_CONTRACT
, possibly using #include
to include the compiled .tz file. Here is an example in Cameligo:
type child_storage = unit
type create_contract_args =
[@layout:comb]
(* order matters because we will cross the Michelson boundary *)
{ delegate : key_hash option;
balance : tez;
storage : child_storage }
type create_contract_result =
[@layout:comb]
{ operation : operation;
address : address }
[@inline] let create_contract =
[%Michelson ({|{ UNPAIR 3;
CREATE_CONTRACT
#include "./child.tz"
;
PAIR
}|} : create_contract_args -> create_contract_result)]
let main (_ : unit * unit) : operation list * unit =
let {operation; address = _} =
create_contract { delegate = (None : key_hash option);
balance = Tezos.get_amount ();
storage = () } in
([operation], ())
Check the contract factory example: https://ligolang.org/docs/tutorials/inter-contract-calls/inter-contract-calls/#contract-factories
The code they are using is available here: https://gitlab.com/ligolang/ligo/-/blob/dev/gitlab-pages/docs/tutorials/inter-contract-calls/examples/contracts/ligo/CreateAndCall.ligo