From 3260e87d67b51eaa15d5c9c2271694413c4111fe Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 27 Feb 2020 12:49:38 +0100 Subject: [PATCH 1/8] new constant : C_CREATE_CONTRACT --- src/stages/common/PP.ml | 1 + src/stages/common/types.ml | 1 + src/stages/mini_c/PP.ml | 1 + 3 files changed, 3 insertions(+) diff --git a/src/stages/common/PP.ml b/src/stages/common/PP.ml index a04d303a7..14cde83d5 100644 --- a/src/stages/common/PP.ml +++ b/src/stages/common/PP.ml @@ -146,6 +146,7 @@ let constant ppf : constant' -> unit = function | C_SELF_ADDRESS -> fprintf ppf "SELF_ADDRESS" | C_IMPLICIT_ACCOUNT -> fprintf ppf "IMPLICIT_ACCOUNT" | C_SET_DELEGATE -> fprintf ppf "SET_DELEGATE" + | C_CREATE_CONTRACT -> fprintf ppf "CREATE_CONTRACT" let literal ppf (l : literal) = match l with diff --git a/src/stages/common/types.ml b/src/stages/common/types.ml index e923bc924..d6b0839fd 100644 --- a/src/stages/common/types.ml +++ b/src/stages/common/types.ml @@ -288,3 +288,4 @@ and constant' = | C_SELF_ADDRESS | C_IMPLICIT_ACCOUNT | C_SET_DELEGATE + | C_CREATE_CONTRACT diff --git a/src/stages/mini_c/PP.ml b/src/stages/mini_c/PP.ml index 0fde6061c..46899c212 100644 --- a/src/stages/mini_c/PP.ml +++ b/src/stages/mini_c/PP.ml @@ -242,6 +242,7 @@ and constant ppf : constant' -> unit = function | C_SELF_ADDRESS -> fprintf ppf "SELF_ADDRESS" | C_IMPLICIT_ACCOUNT -> fprintf ppf "IMPLICIT_ACCOUNT" | C_SET_DELEGATE -> fprintf ppf "SET_DELEGATE" + | C_CREATE_CONTRACT -> fprintf ppf "CREATE_CONTRACT" let%expect_test _ = Format.printf "%a" value (D_bytes (Bytes.of_string "foo")) ; From 4e48026daa0747b09df8e5b4c4bca9247c82c0fb Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 27 Feb 2020 12:49:50 +0100 Subject: [PATCH 2/8] typer: typing C_CREATE_CONTRACT --- src/passes/operators/operators.ml | 26 ++++++++++++++------------ src/passes/operators/operators.mli | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/passes/operators/operators.ml b/src/passes/operators/operators.ml index 7cc7f556d..3537e1d89 100644 --- a/src/passes/operators/operators.ml +++ b/src/passes/operators/operators.ml @@ -88,6 +88,7 @@ module Simplify = struct | "source" -> ok C_SOURCE (* Deprecated *) | "Tezos.failwith" -> ok C_FAILWITH | "failwith" -> ok C_FAILWITH + | "Tezos.create_contract" -> ok C_CREATE_CONTRACT | "Tezos.transaction" -> ok C_CALL | "transaction" -> ok C_CALL (* Deprecated *) @@ -287,6 +288,7 @@ module Simplify = struct | "Operation.get_entrypoint" -> ok C_CONTRACT_ENTRYPOINT (* Deprecated *) | "Tezos.get_entrypoint_opt" -> ok C_CONTRACT_ENTRYPOINT_OPT | "Operation.get_entrypoint_opt" -> ok C_CONTRACT_ENTRYPOINT_OPT (* Deprecated *) + | "Tezos.create_contract" -> ok C_CREATE_CONTRACT | "Michelson.is_nat" -> ok C_IS_NAT (* Deprecated *) | "is_nat" -> ok C_IS_NAT @@ -800,18 +802,17 @@ module Typer = struct let%bind () = assert_type_expression_eq (param , contract_param) in ok @@ t_operation () - let originate = typer_6 "ORIGINATE" @@ fun manager delegate_opt spendable delegatable init_balance code -> - let%bind () = assert_eq_1 manager (t_key_hash ()) in - let%bind () = assert_eq_1 delegate_opt (t_option (t_key_hash ()) ()) in - let%bind () = assert_eq_1 spendable (t_bool ()) in - let%bind () = assert_eq_1 delegatable (t_bool ()) in - let%bind () = assert_t_mutez init_balance in - let%bind (arg , res) = get_t_function code in - let%bind (_param , storage) = get_t_pair arg in - let%bind (storage' , op_lst) = get_t_pair res in - let%bind () = assert_eq_1 storage storage' in - let%bind () = assert_eq_1 op_lst (t_list (t_operation ()) ()) in - ok @@ (t_pair (t_operation ()) (t_address ()) ()) + let create_contract = typer_4 "CREATE_CONTRACT" @@ fun f kh_opt amount init_storage -> + let%bind (args , ret) = get_t_function f in + let%bind (_,s) = get_t_pair args in + let%bind (oplist,s') = get_t_pair ret in + let%bind () = assert_t_mutez amount in + let%bind (delegate) = get_t_option kh_opt in + let%bind () = assert_type_expression_eq (s,s') in + let%bind () = assert_type_expression_eq (s,init_storage) in + let%bind () = assert_t_list_operation oplist in + let%bind () = assert_t_key_hash delegate in + ok @@ t_pair (t_operation ()) (t_address ()) () let get_contract = typer_1_opt "CONTRACT" @@ fun addr_tv tv_opt -> if not (type_expression_eq (addr_tv, t_address ())) @@ -1229,6 +1230,7 @@ module Typer = struct | C_SELF_ADDRESS -> ok @@ self_address; | C_IMPLICIT_ACCOUNT -> ok @@ implicit_account; | C_SET_DELEGATE -> ok @@ set_delegate ; + | C_CREATE_CONTRACT -> ok @@ create_contract ; | _ -> simple_fail @@ Format.asprintf "Typer not implemented for consant %a" PP.constant c diff --git a/src/passes/operators/operators.mli b/src/passes/operators/operators.mli index 2adb00b5b..77ce53196 100644 --- a/src/passes/operators/operators.mli +++ b/src/passes/operators/operators.mli @@ -140,7 +140,7 @@ module Typer : sig val now : typer val transaction : typer *) - val originate : typer + val create_contract : typer (* val get_contract : typer *) From ad7024c62b442f19a88ce6461f971aa7fb4502fe Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Fri, 28 Feb 2020 18:11:02 +0100 Subject: [PATCH 3/8] compiler: compile CREATE_CONTRACT --- src/passes/8-compiler/compiler_program.ml | 21 +++++++++++++++++++-- src/stages/mini_c/combinators.ml | 2 +- src/stages/mini_c/combinators.mli | 2 +- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/passes/8-compiler/compiler_program.ml b/src/passes/8-compiler/compiler_program.ml index a93b58299..a4ffbd0e0 100644 --- a/src/passes/8-compiler/compiler_program.ml +++ b/src/passes/8-compiler/compiler_program.ml @@ -27,7 +27,7 @@ end open Errors (* This does not makes sense to me *) -let get_operator : constant' -> type_value -> expression list -> predicate result = fun s ty lst -> +let rec get_operator : constant' -> type_value -> expression list -> predicate result = fun s ty lst -> match Operators.Compiler.get_operators s with | Ok (x,_) -> ok x | Error _ -> ( @@ -114,10 +114,23 @@ let get_operator : constant' -> type_value -> expression list -> predicate resul i_drop ; (* drop the entrypoint... *) prim ~annot:[entry] ~children:[r_ty] I_CONTRACT ; ] + | C_CREATE_CONTRACT -> + let%bind ch = match lst with + | { content= E_closure {body;binder} ; type_value = T_function (T_pair ((_,p),(_,s)) as tin,_)} :: _ -> + let%bind closure = translate_function_body {body;binder} [] tin in + let%bind (p',s') = bind_map_pair Compiler_type.type_ (p,s) in + ok @@ contract p' s' closure + | _ -> fail @@ corner_case ~loc:__LOC__ "mini_c . CREATE_CONTRACT" + in + ok @@ simple_tetrary @@ seq [ + i_drop ; + prim ~children:[ch] I_CREATE_CONTRACT ; + i_pair ; + ] | x -> simple_fail (Format.asprintf "predicate \"%a\" doesn't exist" PP.constant x) ) -let rec translate_value (v:value) ty : michelson result = match v with +and translate_value (v:value) ty : michelson result = match v with | D_bool b -> ok @@ prim (if b then D_True else D_False) | D_int n -> ok @@ int (Z.of_int n) | D_nat n -> ok @@ int (Z.of_int n) @@ -249,6 +262,10 @@ and translate_expression (expr:expression) (env:environment) : michelson result pre_code ; f ; ] + | Tetrary f, 4 -> ok @@ seq [ + pre_code ; + f ; + ] | _ -> simple_fail (Format.asprintf "bad arity for %a" PP.constant str) in let error = diff --git a/src/stages/mini_c/combinators.ml b/src/stages/mini_c/combinators.ml index 2912aec93..019a111be 100644 --- a/src/stages/mini_c/combinators.ml +++ b/src/stages/mini_c/combinators.ml @@ -152,7 +152,7 @@ let get_t_contract t = match t with | _ -> fail @@ wrong_type "contract" t let get_t_operation t = match t with - | T_base TC_operation -> ok () + | T_base TC_operation -> ok t | _ -> fail @@ wrong_type "operation" t let get_operation (v:value) = match v with diff --git a/src/stages/mini_c/combinators.mli b/src/stages/mini_c/combinators.mli index 3f9b1552e..d61620589 100644 --- a/src/stages/mini_c/combinators.mli +++ b/src/stages/mini_c/combinators.mli @@ -49,7 +49,7 @@ val wrong_type : string -> type_value -> unit -> error val get_t_left : type_value -> type_value result val get_t_right : type_value -> type_value result val get_t_contract : type_value -> type_value result -val get_t_operation : type_value -> unit result +val get_t_operation : type_value -> type_value result val get_operation : value -> Memory_proto_alpha.Protocol.Alpha_context.packed_internal_operation result val t_int : type_value From ffd792e2f8248841f7a3bd6bdad10e89ab6cdbfe Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Fri, 28 Feb 2020 19:30:09 +0100 Subject: [PATCH 4/8] CREATE_CONTRACT: add a check in the typer to allow only closures --- src/passes/4-typer-old/typer.ml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/passes/4-typer-old/typer.ml b/src/passes/4-typer-old/typer.ml index 2d5d70a12..e966b5a52 100644 --- a/src/passes/4-typer-old/typer.ml +++ b/src/passes/4-typer-old/typer.ml @@ -154,6 +154,15 @@ module Errors = struct ] in error ~data title message () + let fvs_in_create_contract_lambda (e : I.expression) (case : Ast_typed.expression_variable) () = + let title = (thunk "No free variable allowed in this lambda") in + let message () = Format.asprintf "%a " Var.pp case in + let data = [ + ("expression" , fun () -> Format.asprintf "%a" I.PP.expression e) ; + ("location" , fun () -> Format.asprintf "%a" Location.pp e.location) + ] in + error ~data title message () + let type_error_approximate ?(msg="") ~(expected: string) ~(actual: O.type_expression) ~(expression : I.expression) (loc:Location.t) () = let title = (thunk "type error") in let message () = msg in @@ -696,6 +705,20 @@ and type_expression' : environment -> ?tv_opt:O.type_expression -> I.expression let%bind (opname',tv) = type_constant opname tv_lst tv_opt in Format.printf "Typed constant : %a \n%!" O.PP.type_expression tv; return (E_constant {cons_name=opname';arguments=lst'}) tv + | E_constant {cons_name=C_CREATE_CONTRACT as cons_name;arguments} -> + let%bind lst' = bind_list @@ List.map (type_expression' e) arguments in + let%bind () = match lst' with + | { expression_content = O.E_lambda l ; _ } :: _ -> + let open Ast_typed.Misc in + let fvs = Free_variables.lambda [] l in + if List.length fvs = 0 then ok () + else fail @@ fvs_in_create_contract_lambda ae (List.hd fvs) + | _ -> ok () + in + let tv_lst = List.map get_type_expression lst' in + let%bind (name', tv) = + type_constant cons_name tv_lst tv_opt in + return (E_constant {cons_name=name';arguments=lst'}) tv | E_constant {cons_name;arguments} -> let%bind lst' = bind_list @@ List.map (type_expression' e) arguments in let tv_lst = List.map get_type_expression lst' in From 9a30eb67c1016ac6a11846e95e64b52c7ae50366 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Fri, 28 Feb 2020 19:49:51 +0100 Subject: [PATCH 5/8] create_contract: add some tests --- src/bin/expect_tests/contract_tests.ml | 49 ++++++++++++++++++- src/test/contracts/create_contract.mligo | 10 ++++ .../negative/create_contract_toplevel.mligo | 10 ++++ .../negative/create_contract_var.mligo | 12 +++++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 src/test/contracts/create_contract.mligo create mode 100644 src/test/contracts/negative/create_contract_toplevel.mligo create mode 100644 src/test/contracts/negative/create_contract_var.mligo diff --git a/src/bin/expect_tests/contract_tests.ml b/src/bin/expect_tests/contract_tests.ml index facee666d..795e554ea 100644 --- a/src/bin/expect_tests/contract_tests.ml +++ b/src/bin/expect_tests/contract_tests.ml @@ -1144,4 +1144,51 @@ let%expect_test _ = * Visit our documentation: https://ligolang.org/docs/intro/what-and-why/ * Ask a question on our Discord: https://discord.gg/9rhYaEt * Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new - * Check the changelog by running 'ligo changelog' |}] \ No newline at end of file + * Check the changelog by running 'ligo changelog' |}] + +let%expect_test _ = + run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_toplevel.mligo" ; "main" ] ; + [%expect {| + ligo: in file "create_contract_toplevel.mligo", line 4, character 35 to line 8, character 8. No free variable allowed in this lambda: store {"expression":"CREATE_CONTRACT(lambda (#P : ( nat * string ):Some(( nat * string ))) : None return let rhs#752 = #P in let p = rhs#752.0 in let s = rhs#752.1 in ( list[] : (TO_list(operation)) , store ) , NONE() : (TO_option(key_hash)) , 300000000mutez , \"un\")","location":"in file \"create_contract_toplevel.mligo\", line 4, character 35 to line 8, character 8"} + + + If you're not sure how to fix this error, you can + do one of the following: + + * Visit our documentation: https://ligolang.org/docs/intro/what-and-why/ + * Ask a question on our Discord: https://discord.gg/9rhYaEt + * Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new + * Check the changelog by running 'ligo changelog' |}] ; + + run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_var.mligo" ; "main" ] ; + [%expect {| + ligo: in file "create_contract_var.mligo", line 6, character 35 to line 10, character 5. No free variable allowed in this lambda: a {"expression":"CREATE_CONTRACT(lambda (#P : ( nat * int ):Some(( nat * int ))) : None return let rhs#755 = #P in let p = rhs#755.0 in let s = rhs#755.1 in ( list[] : (TO_list(operation)) , a ) , NONE() : (TO_option(key_hash)) , 300000000mutez , 1)","location":"in file \"create_contract_var.mligo\", line 6, character 35 to line 10, character 5"} + + + If you're not sure how to fix this error, you can + do one of the following: + + * Visit our documentation: https://ligolang.org/docs/intro/what-and-why/ + * Ask a question on our Discord: https://discord.gg/9rhYaEt + * Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new + * Check the changelog by running 'ligo changelog' |}] ; + run_ligo_good [ "compile-contract" ; contract "create_contract.mligo" ; "main" ] ; + [%expect {| + { parameter string ; + storage string ; + code { PUSH string "un" ; + PUSH mutez 300000000 ; + NONE key_hash ; + CREATE_CONTRACT + { parameter nat ; + storage string ; + code { PUSH string "one" ; NIL operation ; PAIR ; DIP { DROP } } } ; + PAIR ; + DUP ; + CAR ; + NIL operation ; + SWAP ; + CONS ; + DIP { DIP { DUP } ; SWAP ; CDR } ; + PAIR ; + DIP { DROP 2 } } } |}] diff --git a/src/test/contracts/create_contract.mligo b/src/test/contracts/create_contract.mligo new file mode 100644 index 000000000..8c405102c --- /dev/null +++ b/src/test/contracts/create_contract.mligo @@ -0,0 +1,10 @@ +type return = operation list * string + +let main (action, store : string * string) : return = + let toto : operation * address = Tezos.create_contract + (fun (p, s : nat * string) -> (([] : operation list), "one")) + (None: key_hash option) + 300tz + "un" + in + ([toto.0], store) \ No newline at end of file diff --git a/src/test/contracts/negative/create_contract_toplevel.mligo b/src/test/contracts/negative/create_contract_toplevel.mligo new file mode 100644 index 000000000..051464c11 --- /dev/null +++ b/src/test/contracts/negative/create_contract_toplevel.mligo @@ -0,0 +1,10 @@ +type return = operation list * string + +let main (action, store : string * string) : return = + let toto : operation * address = Tezos.create_contract + (fun (p, s : nat * string) -> (([] : operation list), store)) + (None: key_hash option) + 300tz + "un" + in + ([toto.0], store) \ No newline at end of file diff --git a/src/test/contracts/negative/create_contract_var.mligo b/src/test/contracts/negative/create_contract_var.mligo new file mode 100644 index 000000000..9bd0a3ffb --- /dev/null +++ b/src/test/contracts/negative/create_contract_var.mligo @@ -0,0 +1,12 @@ +type return = operation list * string + +let a : int = 2 + +let main (action, store : string * string) : return = + let toto : operation * address = Tezos.create_contract + (fun (p, s : nat * int) -> (([] : operation list), a)) + (None: key_hash option) + 300tz + 1 + in + ([toto.0], store) \ No newline at end of file From 1e5abda3eed2c66f005457293c9924a4600ddd32 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Mon, 2 Mar 2020 12:53:03 +0100 Subject: [PATCH 6/8] create contract : conservative restrictions & errors in typer, before inlining/beta optimizations --- src/passes/4-typer-old/typer.ml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/passes/4-typer-old/typer.ml b/src/passes/4-typer-old/typer.ml index e966b5a52..1b220754f 100644 --- a/src/passes/4-typer-old/typer.ml +++ b/src/passes/4-typer-old/typer.ml @@ -154,9 +154,18 @@ module Errors = struct ] in error ~data title message () - let fvs_in_create_contract_lambda (e : I.expression) (case : Ast_typed.expression_variable) () = + let fvs_in_create_contract_lambda (e : I.expression) (fvar : Ast_typed.expression_variable) () = let title = (thunk "No free variable allowed in this lambda") in - let message () = Format.asprintf "%a " Var.pp case in + let message () = Format.asprintf "variable '%a'" Var.pp fvar in + let data = [ + ("expression" , fun () -> Format.asprintf "%a" I.PP.expression e) ; + ("location" , fun () -> Format.asprintf "%a" Location.pp e.location) + ] in + error ~data title message () + + let create_contract_lambda (cst : I.constant') (e : I.expression) () = + let title () = Format.asprintf "%a first argument must be inlined" I.PP.constant cst in + let message () = Format.asprintf "contract code can be inlined using a lambda" in let data = [ ("expression" , fun () -> Format.asprintf "%a" I.PP.expression e) ; ("location" , fun () -> Format.asprintf "%a" Location.pp e.location) @@ -713,7 +722,7 @@ and type_expression' : environment -> ?tv_opt:O.type_expression -> I.expression let fvs = Free_variables.lambda [] l in if List.length fvs = 0 then ok () else fail @@ fvs_in_create_contract_lambda ae (List.hd fvs) - | _ -> ok () + | _ -> fail @@ create_contract_lambda C_CREATE_CONTRACT ae in let tv_lst = List.map get_type_expression lst' in let%bind (name', tv) = From cf383fe3274cc93b9bd44afb1e74f6449ccd92fa Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Mon, 2 Mar 2020 12:53:10 +0100 Subject: [PATCH 7/8] more tests --- src/bin/expect_tests/contract_tests.ml | 18 ++++++++++++++++-- .../negative/create_contract_no_inline.mligo | 11 +++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 src/test/contracts/negative/create_contract_no_inline.mligo diff --git a/src/bin/expect_tests/contract_tests.ml b/src/bin/expect_tests/contract_tests.ml index 795e554ea..0706ceda8 100644 --- a/src/bin/expect_tests/contract_tests.ml +++ b/src/bin/expect_tests/contract_tests.ml @@ -1149,7 +1149,7 @@ let%expect_test _ = let%expect_test _ = run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_toplevel.mligo" ; "main" ] ; [%expect {| - ligo: in file "create_contract_toplevel.mligo", line 4, character 35 to line 8, character 8. No free variable allowed in this lambda: store {"expression":"CREATE_CONTRACT(lambda (#P : ( nat * string ):Some(( nat * string ))) : None return let rhs#752 = #P in let p = rhs#752.0 in let s = rhs#752.1 in ( list[] : (TO_list(operation)) , store ) , NONE() : (TO_option(key_hash)) , 300000000mutez , \"un\")","location":"in file \"create_contract_toplevel.mligo\", line 4, character 35 to line 8, character 8"} + ligo: in file "create_contract_toplevel.mligo", line 4, character 35 to line 8, character 8. No free variable allowed in this lambda: variable 'store' {"expression":"CREATE_CONTRACT(lambda (#P : ( nat * string ):Some(( nat * string ))) : None return let rhs#752 = #P in let p = rhs#752.0 in let s = rhs#752.1 in ( list[] : (TO_list(operation)) , store ) , NONE() : (TO_option(key_hash)) , 300000000mutez , \"un\")","location":"in file \"create_contract_toplevel.mligo\", line 4, character 35 to line 8, character 8"} If you're not sure how to fix this error, you can @@ -1162,7 +1162,7 @@ let%expect_test _ = run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_var.mligo" ; "main" ] ; [%expect {| - ligo: in file "create_contract_var.mligo", line 6, character 35 to line 10, character 5. No free variable allowed in this lambda: a {"expression":"CREATE_CONTRACT(lambda (#P : ( nat * int ):Some(( nat * int ))) : None return let rhs#755 = #P in let p = rhs#755.0 in let s = rhs#755.1 in ( list[] : (TO_list(operation)) , a ) , NONE() : (TO_option(key_hash)) , 300000000mutez , 1)","location":"in file \"create_contract_var.mligo\", line 6, character 35 to line 10, character 5"} + ligo: in file "create_contract_var.mligo", line 6, character 35 to line 10, character 5. No free variable allowed in this lambda: variable 'a' {"expression":"CREATE_CONTRACT(lambda (#P : ( nat * int ):Some(( nat * int ))) : None return let rhs#755 = #P in let p = rhs#755.0 in let s = rhs#755.1 in ( list[] : (TO_list(operation)) , a ) , NONE() : (TO_option(key_hash)) , 300000000mutez , 1)","location":"in file \"create_contract_var.mligo\", line 6, character 35 to line 10, character 5"} If you're not sure how to fix this error, you can @@ -1172,6 +1172,20 @@ let%expect_test _ = * Ask a question on our Discord: https://discord.gg/9rhYaEt * Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new * Check the changelog by running 'ligo changelog' |}] ; + + run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_no_inline.mligo" ; "main" ] ; + [%expect {| + ligo: in file "create_contract_no_inline.mligo", line 9, characters 19-89. CREATE_CONTRACT first argument must be inlined: contract code can be inlined using a lambda {"expression":"CREATE_CONTRACT(dummy_contract , NONE() : (TO_option(key_hash)) , 300000000mutez , 1)","location":"in file \"create_contract_no_inline.mligo\", line 9, characters 19-89"} + + + If you're not sure how to fix this error, you can + do one of the following: + + * Visit our documentation: https://ligolang.org/docs/intro/what-and-why/ + * Ask a question on our Discord: https://discord.gg/9rhYaEt + * Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new + * Check the changelog by running 'ligo changelog' |}] ; + run_ligo_good [ "compile-contract" ; contract "create_contract.mligo" ; "main" ] ; [%expect {| { parameter string ; diff --git a/src/test/contracts/negative/create_contract_no_inline.mligo b/src/test/contracts/negative/create_contract_no_inline.mligo new file mode 100644 index 000000000..ba5a30cd0 --- /dev/null +++ b/src/test/contracts/negative/create_contract_no_inline.mligo @@ -0,0 +1,11 @@ +let foo : int = 42 + +let dummy_contract (p, s : nat * int) : return = + (([] : operation list), foo) + +type return = operation list * string + +let main (action, store : int * int) : return = + let (op, addr) = Tezos.create_contract dummy_contract ((None: key_hash option)) 300tz 1 in + let toto : operation list = [ op ] in + (toto, foo) From a4fece03d66e9b957c1049416763e023ad668e7b Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Mon, 2 Mar 2020 13:35:26 +0100 Subject: [PATCH 8/8] doc & changelog --- CHANGELOG.md | 4 ++ .../docs/language-basics/tezos-specific.md | 39 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b40924f28..fe908e334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +## [Add crypto reference page to docs](https://gitlab.com/ligolang/ligo/-/merge_requests/459) +### Added +- support for `Tezos.create_contract` origination + ## [9164206ef1fcf3e577820442b5afbad92d03ffa4] - 2020-02-09 ### Changed - Mutation of variables inside lambdas passed to list_iter do not have effect anymore. Side-effects used to survive iterations of list_iter via a quirk in the Michelson list_iter. Now, either use a list_fold and explicitly pass through the updated variables (e.g. storage) to the next iteration, or use a `for` loop which automatically detects mutations within the loop body and lifts the affected variables to a record that is passed from iteration to iteration. diff --git a/gitlab-pages/docs/language-basics/tezos-specific.md b/gitlab-pages/docs/language-basics/tezos-specific.md index 9fed6760a..99b980f44 100644 --- a/gitlab-pages/docs/language-basics/tezos-specific.md +++ b/gitlab-pages/docs/language-basics/tezos-specific.md @@ -154,3 +154,42 @@ let current_addr : address = Tezos.self_address; ``` + +## Origination of a contract + +`Tezos.create_contract` allows you to originate a contract given its code, delegate (if any), initial balance and initial storage. +The return value is a pair of type `(operation * address)`. + +> ⚠️ Due to limitations in Michelson, `Tezos.create_contract` first argument +> must be inlined and must not contain references to free variables + + + + +```pascaligo group=e +const origination : operation * address = Tezos.create_contract ( + function (const p : nat; const s : string): list(operation) * string is ((nil : list(operation)), s), + (None : option(key_hash)), + 3tz, + "initial_storage") +``` + + +```cameligo group=e +let origination : operation * address = Tezos.create_contract + (fun (p, s : nat * string) -> (([] : operation list), s)) + (None: key_hash option) + 3tz + "initial_storage" +``` + + +```reasonligo group=e +let origination : (operation, address) = Tezos.create_contract ( + ((p, s) : (nat,string)) : (list(operation),string) => (([] : list(operation)), s), + None: option(key_hash), + 3tz, + "initial_storage") +``` + +