From 8d781eebca3bd17727c01a00e65f2da9ba901302 Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Tue, 25 Feb 2020 00:04:52 -0800 Subject: [PATCH 01/14] Refactor id layer contract to use records instead of tuples --- src/test/contracts/id.mligo | 189 ++++++++++++++++++----------- src/test/id_tests.ml | 234 +++++++++++++++++++++--------------- 2 files changed, 256 insertions(+), 167 deletions(-) diff --git a/src/test/contracts/id.mligo b/src/test/contracts/id.mligo index e23f8d841..67233ce56 100644 --- a/src/test/contracts/id.mligo +++ b/src/test/contracts/id.mligo @@ -6,9 +6,21 @@ type id_details = { profile: bytes } -type buy = bytes * address option -type update_owner = id * address -type update_details = id * bytes option * address option +type buy = { + profile: bytes; + initial_controller: address option; +} + +type update_owner = { + id: id; + new_owner: address; +} + +type update_details = { + id: id; + new_profile: bytes option; + new_controller: address option; +} type action = | Buy of buy @@ -19,7 +31,14 @@ type action = (* The prices kept in storage can be changed by bakers, though they should only be adjusted down over time, not up. *) -type storage = (id, id_details) big_map * int * (tez * tez) +(* The prices kept in storage can be changed by bakers, though they should only be + adjusted down over time, not up. *) +type storage = { + identities: (id, id_details) big_map; + next_id: int; + name_price: tez; + skip_price: tez; +} type return = operation list * storage @@ -38,13 +57,17 @@ a lot that could be eaten up. Should probably do some napkin calculations for how expensive skipping needs to be to deter people from doing it just to chew up address space. *) -let buy (parameter, storage: (bytes * address option) * storage) = - let void : unit = - if Tezos.amount <> storage.2.0 - then (failwith "Incorrect amount paid.": unit) in - let profile, initial_controller = parameter in - let identities, new_id, prices = storage in - let controller : address = +let buy (parameter, storage: buy * storage) = + let void: unit = + if amount = storage.name_price + then () + else (failwith "Incorrect amount paid.": unit) + in + let profile = parameter.profile in + let initial_controller = parameter.initial_controller in + let identities = storage.identities in + let new_id = storage.next_id in + let controller: address = match initial_controller with | Some addr -> addr | None -> sender in @@ -54,74 +77,98 @@ let buy (parameter, storage: (bytes * address option) * storage) = profile = profile} in let updated_identities : (id, id_details) big_map = Big_map.update new_id (Some new_id_details) identities - in ([]: operation list), (updated_identities, new_id + 1, prices) + in + ([]: operation list), {identities = updated_identities; + next_id = new_id + 1; + name_price = storage.name_price; + skip_price = storage.skip_price; + } -let update_owner (parameter, storage : (id * address) * storage) = - if amount <> 0tez - then (failwith "Updating owner doesn't cost anything.": return) +let update_owner (parameter, storage: update_owner * storage) = + if (amount <> 0mutez) + then (failwith "Updating owner doesn't cost anything.": (operation list) * storage) else - let id, new_owner = parameter in - let identities, last_id, prices = storage in - let current_id_details : id_details = - match Big_map.find_opt id identities with - | Some id_details -> id_details - | None -> (failwith "This ID does not exist." : id_details) in - let is_allowed : bool = - if Tezos.sender = current_id_details.owner - then true - else (failwith "You are not the owner of this ID." : bool) in - let updated_id_details : id_details = { + let id = parameter.id in + let new_owner = parameter.new_owner in + let identities = storage.identities in + let current_id_details: id_details = + match Big_map.find_opt id identities with + | Some id_details -> id_details + | None -> (failwith "This ID does not exist.": id_details) + in + let is_allowed: bool = + if sender = current_id_details.owner + then true + else (failwith "You are not the owner of this ID.": bool) + in + let updated_id_details: id_details = { owner = new_owner; controller = current_id_details.controller; - profile = current_id_details.profile} in - let updated_identities = - Big_map.update id (Some updated_id_details) identities - in ([]: operation list), (updated_identities, last_id, prices) + profile = current_id_details.profile; + } + in + let updated_identities = Big_map.update id (Some updated_id_details) identities in + ([]: operation list), {identities = updated_identities; + next_id = storage.next_id; + name_price = storage.name_price; + skip_price = storage.skip_price; + } -let update_details (parameter, storage: (id * bytes option * address option) * storage) = - if Tezos.amount <> 0tez - then - (failwith "Updating details doesn't cost anything." : return) +let update_details (parameter, storage: update_details * storage) = + if (amount <> 0mutez) + then (failwith "Updating details doesn't cost anything.": (operation list) * storage) else - let id, new_profile, new_controller = parameter in - let identities, last_id, prices = storage in - let current_id_details: id_details = - match Big_map.find_opt id identities with - | Some id_details -> id_details - | None -> (failwith "This ID does not exist.": id_details) in - let is_allowed : bool = - if Tezos.sender = current_id_details.controller - || Tezos.sender = current_id_details.owner - then true - else - (failwith ("You are not the owner or controller of this ID.") - : bool) in - let owner : address = current_id_details.owner in - let profile : bytes = - match new_profile with - | None -> (* Default *) current_id_details.profile - | Some new_profile -> new_profile in - let controller : address = - match new_controller with - | None -> (* Default *) current_id_details.controller - | Some new_controller -> new_controller in - let updated_id_details: id_details = { - owner = owner; - controller = controller; - profile = profile} in + let id = parameter.id in + let new_profile = parameter.new_profile in + let new_controller = parameter.new_controller in + let identities = storage.identities in + let current_id_details: id_details = + match Big_map.find_opt id identities with + | Some id_details -> id_details + | None -> (failwith "This ID does not exist.": id_details) + in + let is_allowed: bool = + if (sender = current_id_details.controller) || (sender = current_id_details.owner) + then true + else (failwith ("You are not the owner or controller of this ID."): bool) + in + let owner: address = current_id_details.owner in + let profile: bytes = + match new_profile with + | None -> (* Default *) current_id_details.profile + | Some new_profile -> new_profile + in + let controller: address = + match new_controller with + | None -> (* Default *) current_id_details.controller + | Some new_controller -> new_controller + in + let updated_id_details: id_details = { + owner = owner; + controller = controller; + profile = profile; + } + in let updated_identities: (id, id_details) big_map = - Big_map.update id (Some updated_id_details) identities - in ([]: operation list), (updated_identities, last_id, prices) + Big_map.update id (Some updated_id_details) identities in + ([]: operation list), {identities = updated_identities; + next_id = storage.next_id; + name_price = storage.name_price; + skip_price = storage.skip_price; + } -(* Let someone skip the next identity so nobody has to take one that's -undesirable *) - -let skip (p, storage: unit * storage) = - let void : unit = - if Tezos.amount <> storage.2.1 - then (failwith "Incorrect amount paid." : unit) in - let identities, last_id, prices = storage in - ([]: operation list), (identities, last_id + 1, prices) +(* Let someone skip the next identity so nobody has to take one that's undesirable *) +let skip (p,storage: unit * storage) = + let void: unit = + if amount = storage.skip_price + then () + else (failwith "Incorrect amount paid.": unit) + in + ([]: operation list), {identities = storage.identities; + next_id = storage.next_id + 1; + name_price = storage.name_price; + skip_price = storage.skip_price; + } let main (action, storage : action * storage) : return = match action with diff --git a/src/test/id_tests.ml b/src/test/id_tests.ml index a1fca2a62..d65f9675d 100644 --- a/src/test/id_tests.ml +++ b/src/test/id_tests.ml @@ -40,9 +40,10 @@ let buy_id () = ("controller", e_address owner_addr) ; ("profile", owner_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1)]) ; - e_int 1; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1)])) ; + ("next_id", e_int 1) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let new_addr = first_owner in let options = Proto_alpha_utils.Memory_proto_alpha.make_options @@ -54,11 +55,15 @@ let buy_id () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let param = e_pair owner_website (e_some (e_address new_addr)) in - let new_storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let param = e_record_ez [("profile", owner_website) ; + ("initial_controller", (e_some (e_address new_addr))) ; + ] in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let%bind () = expect_eq ~options (program, state) "buy" (e_pair param storage) @@ -73,9 +78,10 @@ let buy_id_sender_addr () = ("controller", e_address owner_addr) ; ("profile", owner_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1)]) ; - e_int 1; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1)])) ; + ("next_id", e_int 1) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let new_addr = first_owner in let options = Proto_alpha_utils.Memory_proto_alpha.make_options @@ -87,11 +93,14 @@ let buy_id_sender_addr () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let param = e_pair owner_website (e_typed_none (t_address ())) in - let new_storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let param = e_record_ez [("profile", owner_website) ; + ("initial_controller", (e_typed_none (t_address ())))] in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let%bind () = expect_eq ~options (program, state) "buy" (e_pair param storage) @@ -107,18 +116,20 @@ let buy_id_wrong_amount () = ("controller", e_address owner_addr) ; ("profile", owner_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1)]) ; - e_int 1; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1)])) ; + ("next_id", e_int 1) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let new_addr = first_owner in let options = Proto_alpha_utils.Memory_proto_alpha.make_options ~sender:first_contract ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.fifty_cents) () in - let param = e_pair owner_website (e_some (e_address new_addr)) in + let param = e_record_ez [("profile", owner_website) ; + ("initial_controller", (e_some (e_address new_addr)))] in let%bind () = expect_string_failwith ~options (program, state) "buy" - (e_pair param storage) + (e_pair param storage) "Incorrect amount paid." in ok () @@ -133,7 +144,7 @@ let update_details_owner () = let new_addr = first_owner in let options = Proto_alpha_utils.Memory_proto_alpha.make_options ~sender:first_contract - ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) () in let new_website = e_bytes_string "ligolang.org" in @@ -144,20 +155,24 @@ let update_details_owner () = let id_details_2_diff = e_record_ez [("owner", e_address new_addr) ; ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let new_storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2_diff)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2_diff)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let details = e_bytes_string "ligolang.org" in - let param = e_tuple [e_int 1 ; - e_some details ; - e_some (e_address new_addr)] in + let param = e_record_ez [("id", e_int 1) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address new_addr))] in let%bind () = expect_eq ~options (program, state) "update_details" (e_pair param storage) (e_pair (e_list []) new_storage) @@ -185,20 +200,24 @@ let update_details_controller () = let id_details_2_diff = e_record_ez [("owner", e_address owner_addr) ; ("controller", e_address owner_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let new_storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2_diff)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2_diff)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let details = e_bytes_string "ligolang.org" in - let param = e_tuple [e_int 1 ; - e_some details ; - e_some (e_address owner_addr)] in + let param = e_record_ez [("id", e_int 1) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address owner_addr))] in let%bind () = expect_eq ~options (program, state) "update_details" (e_pair param storage) (e_pair (e_list []) new_storage) @@ -224,15 +243,17 @@ let update_details_nonexistent () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let details = e_bytes_string "ligolang.org" in - let param = e_tuple [e_int 2 ; - e_some details ; - e_some (e_address owner_addr)] in + let param = e_record_ez [("id", e_int 2) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address owner_addr))] in let%bind () = expect_string_failwith ~options (program, state) "update_details" (e_pair param storage) "This ID does not exist." @@ -257,15 +278,17 @@ let update_details_wrong_addr () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let details = e_bytes_string "ligolang.org" in - let param = e_tuple [e_int 0 ; - e_some details ; - e_some (e_address owner_addr)] in + let param = e_record_ez [("id", e_int 0) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address owner_addr))] in let%bind () = expect_string_failwith ~options (program, state) "update_details" (e_pair param storage) "You are not the owner or controller of this ID." @@ -291,14 +314,16 @@ let update_details_unchanged () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let param = e_tuple [e_int 1 ; - e_typed_none (t_bytes ()) ; - e_typed_none (t_address ())] in + let param = e_record_ez [("id", e_int 1) ; + ("new_profile", e_typed_none (t_bytes ())) ; + ("new_controller", e_typed_none (t_address ()))] in let%bind () = expect_eq ~options (program, state) "update_details" (e_pair param storage) (e_pair (e_list []) storage) @@ -326,17 +351,22 @@ let update_owner () = let id_details_2_diff = e_record_ez [("owner", e_address owner_addr) ; ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let new_storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2_diff)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2_diff)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let param = e_pair (e_int 1) (e_address owner_addr) in + let param = e_record_ez [("id", e_int 1) ; + ("new_owner", e_address owner_addr)] in let%bind () = expect_eq ~options (program, state) "update_owner" (e_pair param storage) (e_pair (e_list []) new_storage) @@ -362,12 +392,15 @@ let update_owner_nonexistent () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let param = e_pair (e_int 2) (e_address new_addr) in + let param = e_record_ez [("id", e_int 2); + ("new_owner", e_address new_addr)] in let%bind () = expect_string_failwith ~options (program, state) "update_owner" (e_pair param storage) "This ID does not exist." @@ -393,12 +426,15 @@ let update_owner_wrong_addr () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let param = e_pair (e_int 0) (e_address new_addr) in + let param = e_record_ez [("id", e_int 0); + ("new_owner", e_address new_addr)] in let%bind () = expect_string_failwith ~options (program, state) "update_owner" (e_pair param storage) "You are not the owner of this ID." @@ -422,15 +458,19 @@ let skip () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in - let new_storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 3; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 3) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let%bind () = expect_eq ~options (program, state) "skip" (e_pair (e_unit ()) storage) @@ -456,10 +496,12 @@ let skip_wrong_amount () = ("controller", e_address new_addr) ; ("profile", new_website)] in - let storage = e_tuple [(e_big_map [(e_int 0, id_details_1) ; - (e_int 1, id_details_2)]) ; - e_int 2; - e_tuple [e_mutez 1000000 ; e_mutez 1000000]] + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] in let%bind () = expect_string_failwith ~options (program, state) "skip" (e_pair (e_unit ()) storage) From 4e984850c1f0176c2efb17c519ec30daef3f728d Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Thu, 27 Feb 2020 07:42:58 -0800 Subject: [PATCH 02/14] Add syntactically passing PascaLIGO ID contract that does not typecheck --- src/test/contracts/id.ligo | 178 +++++++++++++ src/test/id_tests_p.ml | 527 +++++++++++++++++++++++++++++++++++++ src/test/test.ml | 1 + 3 files changed, 706 insertions(+) create mode 100644 src/test/contracts/id.ligo create mode 100644 src/test/id_tests_p.ml diff --git a/src/test/contracts/id.ligo b/src/test/contracts/id.ligo new file mode 100644 index 000000000..ec4d3c1ca --- /dev/null +++ b/src/test/contracts/id.ligo @@ -0,0 +1,178 @@ +type id is int + +type id_details is + record [ + owner: address; + controller: address; + profile: bytes; + ] + +type buy is + record [ + profile: bytes; + initial_controller: option(address); + ] + +type update_owner is + record [ + id: id; + new_owner: address; + ] + +type update_details is + record [ + id: id; + new_profile: option(bytes); + new_controller: option(address); + ] + +type action is + | Buy of buy + | Update_owner of update_owner + | Update_details of update_details + | Skip of unit + +(* The prices kept in storage can be changed by bakers, though they should only be + adjusted down over time, not up. *) +type storage is + record [ + identities: big_map (id, id_details); + next_id: int; + name_price: tez; + skip_price: tez; + ] + +(** Preliminary thoughts on ids: + +I very much like the simplicity of http://gurno.com/adam/mne/. +5 three letter words means you have a 15 character identity, not actually more +annoying than an IP address and a lot more memorable than the raw digits. This +can be stored as a single integer which is then translated into the corresponding +series of 5 words. + +I in general like the idea of having a 'skip' mechanism, but it does need to cost +something so people don't eat up the address space. 256 ^ 5 means you have a lot +of address space, but if people troll by skipping a lot that could be eaten up. +Should probably do some napkin calculations for how expensive skipping needs to +be to deter people from doing it just to chew up address space. +*) + +function buy (const parameter : buy; const storage : storage) : list(operation) * storage is + begin + if amount = storage.name_price + then skip + else failwith("Incorrect amount paid."); + const profile : bytes = parameter.profile; + const initial_controller : option(address) = parameter.initial_controller; + var identities : big_map (id, id_details) := storage.identities; + const new_id : int = storage.next_id; + const controller : address = + case initial_controller of + Some(addr) -> addr + | None -> sender + end; + const new_id_details: id_details = + record [ + owner = sender ; + controller = controller ; + profile = profile ; + ]; + identities[new_id] := Some(new_id_details); + end with ((nil : list(operation)), record [ + identities = updated_identities; + next_id = new_id + 1; + name_price = storage.name_price; + skip_price = storage.skip_price; + ]) + +function update_owner (const parameter : update_owner; const storage : storage) : + list(operation) * storage is + begin + if (amount =/= 0mutez) + then + begin + failwith("Updating owner doesn't cost anything."); + end + else skip; + const id : int = parameter[id]; + const new_owner : address = parameter[new_owner]; + var identities : big_map (id, id_details) := storage[identities]; + const id_details : id_details = + case identities[id] of + Some(id_details) -> id_details + | None -> (failwith("This ID does not exist."): id_details) + end; + var is_allowed : bool := false; + if sender = id_details[owner] + then is_allowed := true + else failwith("You are not the owner of this ID."); + id_details[owner] := new_owner; + identities[id] := Some(id_details); + end with ((nil: list(operation)), record [ + identities = updated_identities; + next_id = storage.next_id; + name_price = storage.name_price; + skip_price = storage.skip_price; + ]) + +function update_details (const parameter : update_details; const storage : storage ) : + list(operation) * storage is + begin + if (amount =/= 0mutez) + then failwith("Updating details doesn't cost anything.") + else skip; + const id : int = parameter[id]; + const new_profile : option(bytes) = parameter[new_profile]; + const new_controller : option(address) = parameter[new_controller]; + const identities : big_map (id, id_details) = storage[identities]; + const id_details: id_details = + case identities[id] of + Some(id_details) -> id_details + | None -> (failwith("This ID does not exist."): id_details) + end; + var is_allowed : bool := false; + if (sender = current_id_details[controller]) or (sender = current_id_details[owner]) + then is_allowed := true + else failwith("You are not the owner or controller of this ID."); + const owner: address = id_details[owner]; + const profile: bytes = + case new_profile of + None -> (* Default *) id_details[profile] + | Some(new_profile) -> new_profile + end; + const controller: address = + case new_controller of + None -> (* Default *) current_id_details[controller] + | Some(new_controller) -> new_controller + end; + id_details[owner] := owner; + id_details[controller] := controller; + id_details[profile] := profile; + identities[id] := Some(id_details); + end with ((nil: list(operation)), record [ + identities = identities; + next_id = storage[next_id]; + name_price = storage[name_price]; + skip_price = storage[skip_price]; + ]) + +(* Let someone skip the next identity so nobody has to take one that's undesirable *) +function skip_ (const p: unit; const storage: storage) : list(operation) * storage is + begin + if amount = storage[skip_price] + then skip + else failwith("Incorrect amount paid."); + end with ((nil: list(operation)), record [ + identities = storage[identities]; + next_id = storage[next_id] + 1; + name_price = storage[name_price]; + skip_price = storage[skip_price]; + ]) + +function main (const action : action; const storage : storage) : list(operation) * storage is + case action of + | Buy(b) -> buy (b, storage) + | Update_owner(uo) -> update_owner (uo, storage) + | Update_details(ud) -> update_details (ud, storage) + | Skip(s) -> skip_ (unit, storage) + end; diff --git a/src/test/id_tests_p.ml b/src/test/id_tests_p.ml new file mode 100644 index 000000000..ab98a8c95 --- /dev/null +++ b/src/test/id_tests_p.ml @@ -0,0 +1,527 @@ +open Trace +open Test_helpers +open Ast_simplified + + +let mtype_file f = + let%bind simplified = Ligo.Compile.Of_source.compile f (Syntax_name "pascaligo") in + let%bind typed,state = Ligo.Compile.Of_simplified.compile simplified in + ok (typed,state) + +let get_program = + let s = ref None in + fun () -> match !s with + | Some s -> ok s + | None -> ( + let%bind program = mtype_file "./contracts/id.ligo" in + s := Some program ; + ok program + ) + +let compile_main () = + let%bind simplified = Ligo.Compile.Of_source.compile "./contracts/id.ligo" (Syntax_name "pascaligo") in + let%bind typed_prg,_ = Ligo.Compile.Of_simplified.compile simplified in + let%bind mini_c_prg = Ligo.Compile.Of_typed.compile typed_prg in + let%bind michelson_prg = Ligo.Compile.Of_mini_c.aggregate_and_compile_contract mini_c_prg "main" in + let%bind (_contract: Tezos_utils.Michelson.michelson) = + (* fails if the given entry point is not a valid contract *) + Ligo.Compile.Of_michelson.build_contract michelson_prg in + ok () + +let (first_owner , first_contract) = + let open Proto_alpha_utils.Memory_proto_alpha in + let id = List.nth dummy_environment.identities 0 in + let kt = id.implicit_contract in + Protocol.Alpha_context.Contract.to_b58check kt , kt + +let buy_id () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1)])) ; + ("next_id", e_int 1) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.one) () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let param = e_record_ez [("profile", owner_website) ; + ("initial_controller", (e_some (e_address new_addr))) ; + ] in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let%bind () = expect_eq ~options program "buy" + (e_pair param storage) + (e_pair (e_list []) new_storage) + in ok () + +let buy_id_sender_addr () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1)])) ; + ("next_id", e_int 1) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.one) () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let param = e_record_ez [("profile", owner_website) ; + ("initial_controller", (e_typed_none t_address))] in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let%bind () = expect_eq ~options program "buy" + (e_pair param storage) + (e_pair (e_list []) new_storage) + in ok () + +(* Test that contract fails if we attempt to buy an ID for the wrong amount *) +let buy_id_wrong_amount () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1)])) ; + ("next_id", e_int 1) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.fifty_cents) () + in + let param = e_record_ez [("profile", owner_website) ; + ("initial_controller", (e_some (e_address new_addr)))] in + let%bind () = expect_string_failwith ~options program "buy" + (e_pair param storage) + "Incorrect amount paid." + in ok () + +let update_details_owner () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address owner_addr) ; + ("profile", new_website)] + in + let id_details_2_diff = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2_diff)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let details = e_bytes_string "ligolang.org" in + let param = e_record_ez [("id", e_int 1) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address new_addr))] in + let%bind () = expect_eq ~options program "update_details" + (e_pair param storage) + (e_pair (e_list []) new_storage) + in ok () + +let update_details_controller () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let id_details_2_diff = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", new_website)] in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2_diff)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let details = e_bytes_string "ligolang.org" in + let param = e_record_ez [("id", e_int 1) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address owner_addr))] in + let%bind () = expect_eq ~options program "update_details" + (e_pair param storage) + (e_pair (e_list []) new_storage) + in ok () + +(* Test that contract fails when we attempt to update details of nonexistent ID *) +let update_details_nonexistent () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let details = e_bytes_string "ligolang.org" in + let param = e_record_ez [("id", e_int 2) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address owner_addr))] in + let%bind () = expect_string_failwith ~options program "update_details" + (e_pair param storage) + "This ID does not exist." + in ok () + +(* Test that contract fails when we attempt to update details from wrong addr *) +let update_details_wrong_addr () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let details = e_bytes_string "ligolang.org" in + let param = e_record_ez [("id", e_int 0) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address owner_addr))] in + let%bind () = expect_string_failwith ~options program "update_details" + (e_pair param storage) + "You are not the owner or controller of this ID." + in ok () + +(* Test that giving none on both profile and controller address is a no-op *) +let update_details_unchanged () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let param = e_record_ez [("id", e_int 1) ; + ("new_profile", e_typed_none t_bytes) ; + ("new_controller", e_typed_none t_address)] in + let%bind () = expect_eq ~options program "update_details" + (e_pair param storage) + (e_pair (e_list []) storage) + in ok () + +let update_owner () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let id_details_2_diff = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2_diff)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let param = e_record_ez [("id", e_int 1) ; + ("new_owner", e_address owner_addr)] in + let%bind () = expect_eq ~options program "update_owner" + (e_pair param storage) + (e_pair (e_list []) new_storage) + in ok () + +(* Test that contract fails when we attempt to update owner of nonexistent ID *) +let update_owner_nonexistent () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let param = e_record_ez [("id", e_int 2); + ("new_owner", e_address new_addr)] in + let%bind () = expect_string_failwith ~options program "update_owner" + (e_pair param storage) + "This ID does not exist." + in ok () + +(* Test that contract fails when we attempt to update owner from non-owner addr *) +let update_owner_wrong_addr () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let param = e_record_ez [("id", e_int 0); + ("new_owner", e_address new_addr)] in + let%bind () = expect_string_failwith ~options program "update_owner" + (e_pair param storage) + "You are not the owner of this ID." + in ok () + +let skip () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.one) () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 3) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let%bind () = expect_eq ~options program "skip" + (e_pair (e_unit ()) storage) + (e_pair (e_list []) new_storage) + in ok () + +(* Test that contract fails if we try to skip without paying the right amount *) +let skip_wrong_amount () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.fifty_cents) () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let%bind () = expect_string_failwith ~options program "skip" + (e_pair (e_unit ()) storage) + "Incorrect amount paid." + in ok () + +let main = test_suite "ID Layer" [ + test "buy" buy_id ; + test "buy (sender addr)" buy_id_sender_addr ; + test "buy (wrong amount)" buy_id_wrong_amount ; + test "update_details (owner)" update_details_owner ; + test "update_details (controller)" update_details_controller ; + test "update_details_nonexistent" update_details_nonexistent ; + test "update_details_wrong_addr" update_details_wrong_addr ; + test "update_details_unchanged" update_details_unchanged ; + test "update_owner" update_owner ; + test "update_owner_nonexistent" update_owner_nonexistent ; + test "update_owner_wrong_addr" update_owner_wrong_addr ; + test "skip" skip ; + test "skip (wrong amount)" skip_wrong_amount ; +] diff --git a/src/test/test.ml b/src/test/test.ml index 01d8a78f6..04eb54428 100644 --- a/src/test/test.ml +++ b/src/test/test.ml @@ -11,6 +11,7 @@ let () = Coase_tests.main ; Vote_tests.main ; Id_tests.main ; + Id_tests_p.main ; Multisig_tests.main ; Multisig_v2_tests.main ; Replaceable_id_tests.main ; From 4d16b006c6c99f1fa499f62dd46164aba03e894a Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Thu, 27 Feb 2020 23:22:55 -0800 Subject: [PATCH 03/14] Fix PascaLIGO ID contract to pass tests --- src/test/contracts/id.ligo | 66 +++++++++++++++++++------------------- src/test/id_tests_p.ml | 6 ++-- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/test/contracts/id.ligo b/src/test/contracts/id.ligo index ec4d3c1ca..7f6418127 100644 --- a/src/test/contracts/id.ligo +++ b/src/test/contracts/id.ligo @@ -77,9 +77,9 @@ function buy (const parameter : buy; const storage : storage) : list(operation) controller = controller ; profile = profile ; ]; - identities[new_id] := Some(new_id_details); + identities[new_id] := new_id_details; end with ((nil : list(operation)), record [ - identities = updated_identities; + identities = identities; next_id = new_id + 1; name_price = storage.name_price; skip_price = storage.skip_price; @@ -94,22 +94,22 @@ function update_owner (const parameter : update_owner; const storage : storage) failwith("Updating owner doesn't cost anything."); end else skip; - const id : int = parameter[id]; - const new_owner : address = parameter[new_owner]; - var identities : big_map (id, id_details) := storage[identities]; + const id : int = parameter.id; + const new_owner : address = parameter.new_owner; + var identities : big_map (id, id_details) := storage.identities; const id_details : id_details = case identities[id] of Some(id_details) -> id_details | None -> (failwith("This ID does not exist."): id_details) end; - var is_allowed : bool := false; - if sender = id_details[owner] - then is_allowed := true + var is_allowed : bool := False; + if sender = id_details.owner + then is_allowed := True else failwith("You are not the owner of this ID."); - id_details[owner] := new_owner; - identities[id] := Some(id_details); + id_details.owner := new_owner; + identities[id] := id_details; end with ((nil: list(operation)), record [ - identities = updated_identities; + identities = identities; next_id = storage.next_id; name_price = storage.name_price; skip_price = storage.skip_price; @@ -121,52 +121,52 @@ function update_details (const parameter : update_details; const storage : stora if (amount =/= 0mutez) then failwith("Updating details doesn't cost anything.") else skip; - const id : int = parameter[id]; - const new_profile : option(bytes) = parameter[new_profile]; - const new_controller : option(address) = parameter[new_controller]; - const identities : big_map (id, id_details) = storage[identities]; + const id : int = parameter.id; + const new_profile : option(bytes) = parameter.new_profile; + const new_controller : option(address) = parameter.new_controller; + const identities : big_map (id, id_details) = storage.identities; const id_details: id_details = case identities[id] of Some(id_details) -> id_details | None -> (failwith("This ID does not exist."): id_details) end; - var is_allowed : bool := false; - if (sender = current_id_details[controller]) or (sender = current_id_details[owner]) - then is_allowed := true + var is_allowed : bool := False; + if (sender = id_details.controller) or (sender = id_details.owner) + then is_allowed := True else failwith("You are not the owner or controller of this ID."); - const owner: address = id_details[owner]; + const owner: address = id_details.owner; const profile: bytes = case new_profile of - None -> (* Default *) id_details[profile] + None -> (* Default *) id_details.profile | Some(new_profile) -> new_profile end; const controller: address = case new_controller of - None -> (* Default *) current_id_details[controller] + None -> (* Default *) id_details.controller | Some(new_controller) -> new_controller end; - id_details[owner] := owner; - id_details[controller] := controller; - id_details[profile] := profile; - identities[id] := Some(id_details); + id_details.owner := owner; + id_details.controller := controller; + id_details.profile := profile; + identities[id] := id_details; end with ((nil: list(operation)), record [ identities = identities; - next_id = storage[next_id]; - name_price = storage[name_price]; - skip_price = storage[skip_price]; + next_id = storage.next_id; + name_price = storage.name_price; + skip_price = storage.skip_price; ]) (* Let someone skip the next identity so nobody has to take one that's undesirable *) function skip_ (const p: unit; const storage: storage) : list(operation) * storage is begin - if amount = storage[skip_price] + if amount = storage.skip_price then skip else failwith("Incorrect amount paid."); end with ((nil: list(operation)), record [ - identities = storage[identities]; - next_id = storage[next_id] + 1; - name_price = storage[name_price]; - skip_price = storage[skip_price]; + identities = storage.identities; + next_id = storage.next_id + 1; + name_price = storage.name_price; + skip_price = storage.skip_price; ]) function main (const action : action; const storage : storage) : list(operation) * storage is diff --git a/src/test/id_tests_p.ml b/src/test/id_tests_p.ml index ab98a8c95..81f08c556 100644 --- a/src/test/id_tests_p.ml +++ b/src/test/id_tests_p.ml @@ -474,7 +474,7 @@ let skip () = ("name_price", e_mutez 1000000) ; ("skip_price", e_mutez 1000000) ; ] in - let%bind () = expect_eq ~options program "skip" + let%bind () = expect_eq ~options program "skip_" (e_pair (e_unit ()) storage) (e_pair (e_list []) new_storage) in ok () @@ -505,12 +505,12 @@ let skip_wrong_amount () = ("name_price", e_mutez 1000000) ; ("skip_price", e_mutez 1000000) ; ] in - let%bind () = expect_string_failwith ~options program "skip" + let%bind () = expect_string_failwith ~options program "skip_" (e_pair (e_unit ()) storage) "Incorrect amount paid." in ok () -let main = test_suite "ID Layer" [ +let main = test_suite "ID Layer (PascaLIGO)" [ test "buy" buy_id ; test "buy (sender addr)" buy_id_sender_addr ; test "buy (wrong amount)" buy_id_wrong_amount ; From 37a3fde6fd41447730003f46b031b0b2d01ad584 Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Sat, 29 Feb 2020 00:12:24 -0800 Subject: [PATCH 04/14] Add ReasonLIGO version of ID layer contract Change CameLIGO version tests to say they're for CameLIGO in test suite --- src/test/contracts/id.religo | 184 ++++++++++++ src/test/id_tests.ml | 2 +- src/test/id_tests_r.ml | 527 +++++++++++++++++++++++++++++++++++ src/test/test.ml | 1 + 4 files changed, 713 insertions(+), 1 deletion(-) create mode 100644 src/test/contracts/id.religo create mode 100644 src/test/id_tests_r.ml diff --git a/src/test/contracts/id.religo b/src/test/contracts/id.religo new file mode 100644 index 000000000..6fe854e6c --- /dev/null +++ b/src/test/contracts/id.religo @@ -0,0 +1,184 @@ +type id = int + +type id_details = { + owner: address, + controller: address, + profile: bytes, +} + +type buy = { + profile: bytes, + initial_controller: option(address), +} + +type update_owner = { + id: id, + new_owner: address, +} + +type update_details = { + id: id, + new_profile: option(bytes), + new_controller: option(address), +} + +type action = +| Buy(buy) +| Update_owner(update_owner) +| Update_details(update_details) +| Skip(unit) + +(* The prices kept in storage can be changed by bakers, though they should only be + adjusted down over time, not up. *) +type storage = { + identities: big_map (id, id_details), + next_id: int, + name_price: tez, + skip_price: tez, +} + +(** Preliminary thoughts on ids: + +I very much like the simplicity of http://gurno.com/adam/mne/. +5 three letter words means you have a 15 character identity, not actually more +annoying than an IP address and a lot more memorable than the raw digits. This +can be stored as a single integer which is then translated into the corresponding +series of 5 words. + +I in general like the idea of having a 'skip' mechanism, but it does need to cost +something so people don't eat up the address space. 256 ^ 5 means you have a lot +of address space, but if people troll by skipping a lot that could be eaten up. +Should probably do some napkin calculations for how expensive skipping needs to +be to deter people from doing it just to chew up address space. +*) + +let buy = ((parameter, storage): (buy, storage)) : (list(operation), storage) => { + let void: unit = + if (amount == storage.name_price) { (); } + else { failwith("Incorrect amount paid."); }; + let profile = parameter.profile; + let initial_controller = parameter.initial_controller; + let identities = storage.identities; + let new_id = storage.next_id; + let controller: address = + switch (initial_controller) { + | Some(addr) => addr + | None => sender + }; + let new_id_details: id_details = { + owner : sender, + controller : controller, + profile : profile, + }; + let updated_identities: big_map (id, id_details) = + Big_map.update(new_id, Some(new_id_details), identities); + (([]: list(operation)), { + identities : updated_identities, + next_id : new_id + 1, + name_price : storage.name_price, + skip_price : storage.skip_price, + }); + }; + +let update_owner = ((parameter, storage): (update_owner, storage)) : (list(operation), storage) => { + let void: unit = + if (amount != 0mutez) { + failwith("Updating owner doesn't cost anything."); + } + else { (); }; + let id : int = parameter.id; + let new_owner = parameter.new_owner; + let identities = storage.identities; + let current_id_details: id_details = + switch (Big_map.find_opt(id, identities)) { + | Some(id_details) => id_details + | None => (failwith("This ID does not exist."): id_details) + }; + let is_allowed: bool = + if (sender == current_id_details.owner) { true; } + else { (failwith("You are not the owner of this ID."): bool); }; + let updated_id_details: id_details = { + owner : new_owner, + controller : current_id_details.controller, + profile : current_id_details.profile, + }; + let updated_identities = Big_map.update(id, (Some updated_id_details), identities); + (([]: list(operation)), { + identities : updated_identities, + next_id : storage.next_id, + name_price : storage.name_price, + skip_price : storage.skip_price, + }); + }; + +let update_details = ((parameter, storage): (update_details, storage)) : + (list(operation), storage) => { + let void : unit = + if (amount != 0mutez) { + failwith("Updating details doesn't cost anything."); + } + else { (); }; + let id = parameter.id; + let new_profile = parameter.new_profile; + let new_controller = parameter.new_controller; + let identities = storage.identities; + let current_id_details: id_details = + switch (Big_map.find_opt(id, identities)) { + | Some(id_details) => id_details + | None => (failwith("This ID does not exist."): id_details) + }; + let is_allowed: bool = + if ((sender != current_id_details.controller) && + (sender != current_id_details.owner)) { + (failwith ("You are not the owner or controller of this ID."): bool) + } + else { true; }; + let owner: address = current_id_details.owner; + let profile: bytes = + switch (new_profile) { + | None => (* Default *) current_id_details.profile + | Some(new_profile) => new_profile + }; + let controller: address = + switch (new_controller) { + | None => (* Default *) current_id_details.controller + | Some new_controller => new_controller + }; + let updated_id_details: id_details = { + owner : owner, + controller : controller, + profile : profile, + }; + let updated_identities: big_map (id, id_details) = + Big_map.update(id, (Some updated_id_details), identities); + (([]: list(operation)), { + identities : updated_identities, + next_id : storage.next_id, + name_price : storage.name_price, + skip_price : storage.skip_price, + }); + }; + +(* Let someone skip the next identity so nobody has to take one that's undesirable *) +let skip = ((p,storage): (unit, storage)) => { + let void : unit = + if (amount != storage.skip_price) { + failwith("Incorrect amount paid."); + } + else { (); }; + (([]: list(operation)), { + identities : storage.identities, + next_id : storage.next_id + 1, + name_price : storage.name_price, + skip_price : storage.skip_price, + }); + }; + +let main = ((action, storage): (action, storage)) : (list(operation), storage) => { + switch (action) { + | Buy(b) => buy((b, storage)) + | Update_owner(uo) => update_owner((uo, storage)) + | Update_details ud => update_details((ud, storage)) + | Skip s => skip(((), storage)) + }; +}; diff --git a/src/test/id_tests.ml b/src/test/id_tests.ml index d65f9675d..9c86aecc5 100644 --- a/src/test/id_tests.ml +++ b/src/test/id_tests.ml @@ -508,7 +508,7 @@ let skip_wrong_amount () = "Incorrect amount paid." in ok () -let main = test_suite "ID Layer" [ +let main = test_suite "ID Layer (CameLIGO)" [ test "buy" buy_id ; test "buy (sender addr)" buy_id_sender_addr ; test "buy (wrong amount)" buy_id_wrong_amount ; diff --git a/src/test/id_tests_r.ml b/src/test/id_tests_r.ml new file mode 100644 index 000000000..d795134e1 --- /dev/null +++ b/src/test/id_tests_r.ml @@ -0,0 +1,527 @@ +open Trace +open Test_helpers +open Ast_simplified + + +let mtype_file f = + let%bind simplified = Ligo.Compile.Of_source.compile f (Syntax_name "reasonligo") in + let%bind typed,state = Ligo.Compile.Of_simplified.compile simplified in + ok (typed,state) + +let get_program = + let s = ref None in + fun () -> match !s with + | Some s -> ok s + | None -> ( + let%bind program = mtype_file "./contracts/id.religo" in + s := Some program ; + ok program + ) + +let compile_main () = + let%bind simplified = Ligo.Compile.Of_source.compile "./contracts/id.religo" (Syntax_name "reasonligo") in + let%bind typed_prg,_ = Ligo.Compile.Of_simplified.compile simplified in + let%bind mini_c_prg = Ligo.Compile.Of_typed.compile typed_prg in + let%bind michelson_prg = Ligo.Compile.Of_mini_c.aggregate_and_compile_contract mini_c_prg "main" in + let%bind (_contract: Tezos_utils.Michelson.michelson) = + (* fails if the given entry point is not a valid contract *) + Ligo.Compile.Of_michelson.build_contract michelson_prg in + ok () + +let (first_owner , first_contract) = + let open Proto_alpha_utils.Memory_proto_alpha in + let id = List.nth dummy_environment.identities 0 in + let kt = id.implicit_contract in + Protocol.Alpha_context.Contract.to_b58check kt , kt + +let buy_id () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1)])) ; + ("next_id", e_int 1) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.one) () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let param = e_record_ez [("profile", owner_website) ; + ("initial_controller", (e_some (e_address new_addr))) ; + ] in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let%bind () = expect_eq ~options program "buy" + (e_pair param storage) + (e_pair (e_list []) new_storage) + in ok () + +let buy_id_sender_addr () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1)])) ; + ("next_id", e_int 1) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.one) () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let param = e_record_ez [("profile", owner_website) ; + ("initial_controller", (e_typed_none t_address))] in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let%bind () = expect_eq ~options program "buy" + (e_pair param storage) + (e_pair (e_list []) new_storage) + in ok () + +(* Test that contract fails if we attempt to buy an ID for the wrong amount *) +let buy_id_wrong_amount () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1)])) ; + ("next_id", e_int 1) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.fifty_cents) () + in + let param = e_record_ez [("profile", owner_website) ; + ("initial_controller", (e_some (e_address new_addr)))] in + let%bind () = expect_string_failwith ~options program "buy" + (e_pair param storage) + "Incorrect amount paid." + in ok () + +let update_details_owner () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address owner_addr) ; + ("profile", new_website)] + in + let id_details_2_diff = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2_diff)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let details = e_bytes_string "ligolang.org" in + let param = e_record_ez [("id", e_int 1) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address new_addr))] in + let%bind () = expect_eq ~options program "update_details" + (e_pair param storage) + (e_pair (e_list []) new_storage) + in ok () + +let update_details_controller () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let id_details_2_diff = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", new_website)] in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2_diff)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let details = e_bytes_string "ligolang.org" in + let param = e_record_ez [("id", e_int 1) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address owner_addr))] in + let%bind () = expect_eq ~options program "update_details" + (e_pair param storage) + (e_pair (e_list []) new_storage) + in ok () + +(* Test that contract fails when we attempt to update details of nonexistent ID *) +let update_details_nonexistent () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let details = e_bytes_string "ligolang.org" in + let param = e_record_ez [("id", e_int 2) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address owner_addr))] in + let%bind () = expect_string_failwith ~options program "update_details" + (e_pair param storage) + "This ID does not exist." + in ok () + +(* Test that contract fails when we attempt to update details from wrong addr *) +let update_details_wrong_addr () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let details = e_bytes_string "ligolang.org" in + let param = e_record_ez [("id", e_int 0) ; + ("new_profile", e_some details) ; + ("new_controller", e_some (e_address owner_addr))] in + let%bind () = expect_string_failwith ~options program "update_details" + (e_pair param storage) + "You are not the owner or controller of this ID." + in ok () + +(* Test that giving none on both profile and controller address is a no-op *) +let update_details_unchanged () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let param = e_record_ez [("id", e_int 1) ; + ("new_profile", e_typed_none t_bytes) ; + ("new_controller", e_typed_none t_address)] in + let%bind () = expect_eq ~options program "update_details" + (e_pair param storage) + (e_pair (e_list []) storage) + in ok () + +let update_owner () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let id_details_2_diff = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2_diff)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let param = e_record_ez [("id", e_int 1) ; + ("new_owner", e_address owner_addr)] in + let%bind () = expect_eq ~options program "update_owner" + (e_pair param storage) + (e_pair (e_list []) new_storage) + in ok () + +(* Test that contract fails when we attempt to update owner of nonexistent ID *) +let update_owner_nonexistent () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let param = e_record_ez [("id", e_int 2); + ("new_owner", e_address new_addr)] in + let%bind () = expect_string_failwith ~options program "update_owner" + (e_pair param storage) + "This ID does not exist." + in ok () + +(* Test that contract fails when we attempt to update owner from non-owner addr *) +let update_owner_wrong_addr () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) + () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let param = e_record_ez [("id", e_int 0); + ("new_owner", e_address new_addr)] in + let%bind () = expect_string_failwith ~options program "update_owner" + (e_pair param storage) + "You are not the owner of this ID." + in ok () + +let skip () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.one) () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let new_storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 3) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let%bind () = expect_eq ~options program "skip" + (e_pair (e_unit ()) storage) + (e_pair (e_list []) new_storage) + in ok () + +(* Test that contract fails if we try to skip without paying the right amount *) +let skip_wrong_amount () = + let%bind program, _ = get_program () in + let owner_addr = addr 5 in + let owner_website = e_bytes_string "ligolang.org" in + let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; + ("controller", e_address owner_addr) ; + ("profile", owner_website)] + in + let new_addr = first_owner in + let options = Proto_alpha_utils.Memory_proto_alpha.make_options + ~sender:first_contract + ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.fifty_cents) () + in + let new_website = e_bytes_string "ligolang.org" in + let id_details_2 = e_record_ez [("owner", e_address new_addr) ; + ("controller", e_address new_addr) ; + ("profile", new_website)] + in + let storage = e_record_ez [("identities", (e_big_map + [(e_int 0, id_details_1) ; + (e_int 1, id_details_2)])) ; + ("next_id", e_int 2) ; + ("name_price", e_mutez 1000000) ; + ("skip_price", e_mutez 1000000) ; ] + in + let%bind () = expect_string_failwith ~options program "skip" + (e_pair (e_unit ()) storage) + "Incorrect amount paid." + in ok () + +let main = test_suite "ID Layer (ReasonLIGO)" [ + test "buy" buy_id ; + test "buy (sender addr)" buy_id_sender_addr ; + test "buy (wrong amount)" buy_id_wrong_amount ; + test "update_details (owner)" update_details_owner ; + test "update_details (controller)" update_details_controller ; + test "update_details_nonexistent" update_details_nonexistent ; + test "update_details_wrong_addr" update_details_wrong_addr ; + test "update_details_unchanged" update_details_unchanged ; + test "update_owner" update_owner ; + test "update_owner_nonexistent" update_owner_nonexistent ; + test "update_owner_wrong_addr" update_owner_wrong_addr ; + test "skip" skip ; + test "skip (wrong amount)" skip_wrong_amount ; +] diff --git a/src/test/test.ml b/src/test/test.ml index 04eb54428..b6a9a9c41 100644 --- a/src/test/test.ml +++ b/src/test/test.ml @@ -12,6 +12,7 @@ let () = Vote_tests.main ; Id_tests.main ; Id_tests_p.main ; + Id_tests_r.main ; Multisig_tests.main ; Multisig_v2_tests.main ; Replaceable_id_tests.main ; From e42e79eff3acedcf8ad80ac4fe4425598fb0eb10 Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Wed, 4 Mar 2020 03:32:58 -0800 Subject: [PATCH 05/14] Add ID contract examples to web ide without command defaults --- src/test/contracts/id.religo | 14 +- src/test/examples/cameligo/id.mligo | 195 +++++++++++++++++ src/test/examples/pascaligo/id.ligo | 197 +++++++++++++++++ src/test/examples/reasonligo/id.religo | 203 ++++++++++++++++++ src/test/id_tests_p.ml | 18 +- src/test/id_tests_r.ml | 18 +- .../packages/client/package-examples.js | 9 + 7 files changed, 627 insertions(+), 27 deletions(-) create mode 100644 src/test/examples/cameligo/id.mligo create mode 100644 src/test/examples/pascaligo/id.ligo create mode 100644 src/test/examples/reasonligo/id.religo diff --git a/src/test/contracts/id.religo b/src/test/contracts/id.religo index 6fe854e6c..d5814e211 100644 --- a/src/test/contracts/id.religo +++ b/src/test/contracts/id.religo @@ -28,8 +28,8 @@ type action = | Update_details(update_details) | Skip(unit) -(* The prices kept in storage can be changed by bakers, though they should only be - adjusted down over time, not up. *) +/* The prices kept in storage can be changed by bakers, though they should only be + adjusted down over time, not up. */ type storage = { identities: big_map (id, id_details), next_id: int, @@ -37,7 +37,7 @@ type storage = { skip_price: tez, } -(** Preliminary thoughts on ids: +/** Preliminary thoughts on ids: I very much like the simplicity of http://gurno.com/adam/mne/. 5 three letter words means you have a 15 character identity, not actually more @@ -50,7 +50,7 @@ something so people don't eat up the address space. 256 ^ 5 means you have a lot of address space, but if people troll by skipping a lot that could be eaten up. Should probably do some napkin calculations for how expensive skipping needs to be to deter people from doing it just to chew up address space. -*) +*/ let buy = ((parameter, storage): (buy, storage)) : (list(operation), storage) => { let void: unit = @@ -136,12 +136,12 @@ let update_details = ((parameter, storage): (update_details, storage)) : let owner: address = current_id_details.owner; let profile: bytes = switch (new_profile) { - | None => (* Default *) current_id_details.profile + | None => /* Default */ current_id_details.profile | Some(new_profile) => new_profile }; let controller: address = switch (new_controller) { - | None => (* Default *) current_id_details.controller + | None => /* Default */ current_id_details.controller | Some new_controller => new_controller }; let updated_id_details: id_details = { @@ -159,7 +159,7 @@ let update_details = ((parameter, storage): (update_details, storage)) : }); }; -(* Let someone skip the next identity so nobody has to take one that's undesirable *) +/* Let someone skip the next identity so nobody has to take one that's undesirable */ let skip = ((p,storage): (unit, storage)) => { let void : unit = if (amount != storage.skip_price) { diff --git a/src/test/examples/cameligo/id.mligo b/src/test/examples/cameligo/id.mligo new file mode 100644 index 000000000..2019eb815 --- /dev/null +++ b/src/test/examples/cameligo/id.mligo @@ -0,0 +1,195 @@ +(*_* + name: ID Contract (CameLIGO) + language: cameligo + compile: + entrypoint: main + dryRun: + entrypoint: main + parameters: Increment 1 + storage: 0 + deploy: + entrypoint: main + storage: 0 + evaluateValue: + entrypoint: "" + evaluateFunction: + entrypoint: add + parameters: 5, 6 +*_*) + +type id = int + +type id_details = { + owner: address; + controller: address; + profile: bytes; +} + +type buy = { + profile: bytes; + initial_controller: address option; +} + +type update_owner = { + id: id; + new_owner: address; +} + +type update_details = { + id: id; + new_profile: bytes option; + new_controller: address option; +} + +type action = +| Buy of buy +| Update_owner of update_owner +| Update_details of update_details +| Skip of unit + +(* The prices kept in storage can be changed by bakers, though they should only be + adjusted down over time, not up. *) +type storage = { + identities: (id, id_details) big_map; + next_id: int; + name_price: tez; + skip_price: tez; +} + +(** Preliminary thoughts on ids: + +I very much like the simplicity of http://gurno.com/adam/mne/. +5 three letter words means you have a 15 character identity, not actually more +annoying than an IP address and a lot more memorable than the raw digits. This +can be stored as a single integer which is then translated into the corresponding +series of 5 words. + +I in general like the idea of having a 'skip' mechanism, but it does need to cost +something so people don't eat up the address space. 256 ^ 5 means you have a lot +of address space, but if people troll by skipping a lot that could be eaten up. +Should probably do some napkin calculations for how expensive skipping needs to +be to deter people from doing it just to chew up address space. +*) + +let buy (parameter, storage: buy * storage) = + let void: unit = + if amount = storage.name_price + then () + else (failwith "Incorrect amount paid.": unit) + in + let profile = parameter.profile in + let initial_controller = parameter.initial_controller in + let identities = storage.identities in + let new_id = storage.next_id in + let controller: address = + match initial_controller with + | Some addr -> addr + | None -> sender + in + let new_id_details: id_details = { + owner = sender ; + controller = controller ; + profile = profile ; + } + in + let updated_identities: (id, id_details) big_map = + Big_map.update new_id (Some new_id_details) identities + in + ([]: operation list), {identities = updated_identities; + next_id = new_id + 1; + name_price = storage.name_price; + skip_price = storage.skip_price; + } + +let update_owner (parameter, storage: update_owner * storage) = + if (amount <> 0mutez) + then (failwith "Updating owner doesn't cost anything.": (operation list) * storage) + else + let id = parameter.id in + let new_owner = parameter.new_owner in + let identities = storage.identities in + let current_id_details: id_details = + match Big_map.find_opt id identities with + | Some id_details -> id_details + | None -> (failwith "This ID does not exist.": id_details) + in + let is_allowed: bool = + if sender = current_id_details.owner + then true + else (failwith "You are not the owner of this ID.": bool) + in + let updated_id_details: id_details = { + owner = new_owner; + controller = current_id_details.controller; + profile = current_id_details.profile; + } + in + let updated_identities = Big_map.update id (Some updated_id_details) identities in + ([]: operation list), {identities = updated_identities; + next_id = storage.next_id; + name_price = storage.name_price; + skip_price = storage.skip_price; + } + +let update_details (parameter, storage: update_details * storage) = + if (amount <> 0mutez) + then (failwith "Updating details doesn't cost anything.": (operation list) * storage) + else + let id = parameter.id in + let new_profile = parameter.new_profile in + let new_controller = parameter.new_controller in + let identities = storage.identities in + let current_id_details: id_details = + match Big_map.find_opt id identities with + | Some id_details -> id_details + | None -> (failwith "This ID does not exist.": id_details) + in + let is_allowed: bool = + if (sender = current_id_details.controller) || (sender = current_id_details.owner) + then true + else (failwith ("You are not the owner or controller of this ID."): bool) + in + let owner: address = current_id_details.owner in + let profile: bytes = + match new_profile with + | None -> (* Default *) current_id_details.profile + | Some new_profile -> new_profile + in + let controller: address = + match new_controller with + | None -> (* Default *) current_id_details.controller + | Some new_controller -> new_controller + in + let updated_id_details: id_details = { + owner = owner; + controller = controller; + profile = profile; + } + in + let updated_identities: (id, id_details) big_map = + Big_map.update id (Some updated_id_details) identities in + ([]: operation list), {identities = updated_identities; + next_id = storage.next_id; + name_price = storage.name_price; + skip_price = storage.skip_price; + } + +(* Let someone skip the next identity so nobody has to take one that's undesirable *) +let skip (p,storage: unit * storage) = + let void: unit = + if amount = storage.skip_price + then () + else (failwith "Incorrect amount paid.": unit) + in + ([]: operation list), {identities = storage.identities; + next_id = storage.next_id + 1; + name_price = storage.name_price; + skip_price = storage.skip_price; + } + +let main (action, storage: action * storage) : operation list * storage = + match action with + | Buy b -> buy (b, storage) + | Update_owner uo -> update_owner (uo, storage) + | Update_details ud -> update_details (ud, storage) + | Skip s -> skip ((), storage) diff --git a/src/test/examples/pascaligo/id.ligo b/src/test/examples/pascaligo/id.ligo new file mode 100644 index 000000000..ece089aa9 --- /dev/null +++ b/src/test/examples/pascaligo/id.ligo @@ -0,0 +1,197 @@ +(*_* + name: ID Contract (PascaLIGO) + language: pascaligo + compile: + entrypoint: main + dryRun: + entrypoint: main + parameters: Increment 1 + storage: 0 + deploy: + entrypoint: main + storage: 0 + evaluateValue: + entrypoint: "" + evaluateFunction: + entrypoint: add + parameters: 5, 6 +*_*) + +type id is int + +type id_details is + record [ + owner: address; + controller: address; + profile: bytes; + ] + +type buy is + record [ + profile: bytes; + initial_controller: option(address); + ] + +type update_owner is + record [ + id: id; + new_owner: address; + ] + +type update_details is + record [ + id: id; + new_profile: option(bytes); + new_controller: option(address); + ] + +type action is + | Buy of buy + | Update_owner of update_owner + | Update_details of update_details + | Skip of unit + +(* The prices kept in storage can be changed by bakers, though they should only be + adjusted down over time, not up. *) +type storage is + record [ + identities: big_map (id, id_details); + next_id: int; + name_price: tez; + skip_price: tez; + ] + +(** Preliminary thoughts on ids: + +I very much like the simplicity of http://gurno.com/adam/mne/. +5 three letter words means you have a 15 character identity, not actually more +annoying than an IP address and a lot more memorable than the raw digits. This +can be stored as a single integer which is then translated into the corresponding +series of 5 words. + +I in general like the idea of having a 'skip' mechanism, but it does need to cost +something so people don't eat up the address space. 256 ^ 5 means you have a lot +of address space, but if people troll by skipping a lot that could be eaten up. +Should probably do some napkin calculations for how expensive skipping needs to +be to deter people from doing it just to chew up address space. +*) + +function buy (const parameter : buy; const storage : storage) : list(operation) * storage is + begin + if amount = storage.name_price + then skip + else failwith("Incorrect amount paid."); + const profile : bytes = parameter.profile; + const initial_controller : option(address) = parameter.initial_controller; + var identities : big_map (id, id_details) := storage.identities; + const new_id : int = storage.next_id; + const controller : address = + case initial_controller of + Some(addr) -> addr + | None -> sender + end; + const new_id_details: id_details = + record [ + owner = sender ; + controller = controller ; + profile = profile ; + ]; + identities[new_id] := new_id_details; + end with ((nil : list(operation)), record [ + identities = identities; + next_id = new_id + 1; + name_price = storage.name_price; + skip_price = storage.skip_price; + ]) + +function update_owner (const parameter : update_owner; const storage : storage) : + list(operation) * storage is + begin + if (amount =/= 0mutez) + then + begin + failwith("Updating owner doesn't cost anything."); + end + else skip; + const id : int = parameter.id; + const new_owner : address = parameter.new_owner; + var identities : big_map (id, id_details) := storage.identities; + const id_details : id_details = + case identities[id] of + Some(id_details) -> id_details + | None -> (failwith("This ID does not exist."): id_details) + end; + var is_allowed : bool := False; + if sender = id_details.owner + then is_allowed := True + else failwith("You are not the owner of this ID."); + id_details.owner := new_owner; + identities[id] := id_details; + end with ((nil: list(operation)), record [ + identities = identities; + next_id = storage.next_id; + name_price = storage.name_price; + skip_price = storage.skip_price; + ]) + +function update_details (const parameter : update_details; const storage : storage ) : + list(operation) * storage is + begin + if (amount =/= 0mutez) + then failwith("Updating details doesn't cost anything.") + else skip; + const id : int = parameter.id; + const new_profile : option(bytes) = parameter.new_profile; + const new_controller : option(address) = parameter.new_controller; + const identities : big_map (id, id_details) = storage.identities; + const id_details: id_details = + case identities[id] of + Some(id_details) -> id_details + | None -> (failwith("This ID does not exist."): id_details) + end; + var is_allowed : bool := False; + if (sender = id_details.controller) or (sender = id_details.owner) + then is_allowed := True + else failwith("You are not the owner or controller of this ID."); + const owner: address = id_details.owner; + const profile: bytes = + case new_profile of + None -> (* Default *) id_details.profile + | Some(new_profile) -> new_profile + end; + const controller: address = + case new_controller of + None -> (* Default *) id_details.controller + | Some(new_controller) -> new_controller + end; + id_details.owner := owner; + id_details.controller := controller; + id_details.profile := profile; + identities[id] := id_details; + end with ((nil: list(operation)), record [ + identities = identities; + next_id = storage.next_id; + name_price = storage.name_price; + skip_price = storage.skip_price; + ]) + +(* Let someone skip the next identity so nobody has to take one that's undesirable *) +function skip_ (const p: unit; const storage: storage) : list(operation) * storage is + begin + if amount = storage.skip_price + then skip + else failwith("Incorrect amount paid."); + end with ((nil: list(operation)), record [ + identities = storage.identities; + next_id = storage.next_id + 1; + name_price = storage.name_price; + skip_price = storage.skip_price; + ]) + +function main (const action : action; const storage : storage) : list(operation) * storage is + case action of + | Buy(b) -> buy (b, storage) + | Update_owner(uo) -> update_owner (uo, storage) + | Update_details(ud) -> update_details (ud, storage) + | Skip(s) -> skip_ (unit, storage) + end; diff --git a/src/test/examples/reasonligo/id.religo b/src/test/examples/reasonligo/id.religo new file mode 100644 index 000000000..3177c8fa5 --- /dev/null +++ b/src/test/examples/reasonligo/id.religo @@ -0,0 +1,203 @@ +(*_* + name: ID Contract (ReasonLIGO) + language: reasonligo + compile: + entrypoint: main + dryRun: + entrypoint: main + parameters: Increment 1 + storage: 0 + deploy: + entrypoint: main + storage: 0 + evaluateValue: + entrypoint: "" + evaluateFunction: + entrypoint: add + parameters: 5, 6 +*_*) + +type id = int + +type id_details = { + owner: address, + controller: address, + profile: bytes, +} + +type buy = { + profile: bytes, + initial_controller: option(address), +} + +type update_owner = { + id: id, + new_owner: address, +} + +type update_details = { + id: id, + new_profile: option(bytes), + new_controller: option(address), +} + +type action = +| Buy(buy) +| Update_owner(update_owner) +| Update_details(update_details) +| Skip(unit) + +(* The prices kept in storage can be changed by bakers, though they should only be + adjusted down over time, not up. *) +type storage = { + identities: big_map (id, id_details), + next_id: int, + name_price: tez, + skip_price: tez, +} + +(** Preliminary thoughts on ids: + +I very much like the simplicity of http://gurno.com/adam/mne/. +5 three letter words means you have a 15 character identity, not actually more +annoying than an IP address and a lot more memorable than the raw digits. This +can be stored as a single integer which is then translated into the corresponding +series of 5 words. + +I in general like the idea of having a 'skip' mechanism, but it does need to cost +something so people don't eat up the address space. 256 ^ 5 means you have a lot +of address space, but if people troll by skipping a lot that could be eaten up. +Should probably do some napkin calculations for how expensive skipping needs to +be to deter people from doing it just to chew up address space. +*) + +let buy = ((parameter, storage): (buy, storage)) : (list(operation), storage) => { + let void: unit = + if (amount == storage.name_price) { (); } + else { failwith("Incorrect amount paid."); }; + let profile = parameter.profile; + let initial_controller = parameter.initial_controller; + let identities = storage.identities; + let new_id = storage.next_id; + let controller: address = + switch (initial_controller) { + | Some(addr) => addr + | None => sender + }; + let new_id_details: id_details = { + owner : sender, + controller : controller, + profile : profile, + }; + let updated_identities: big_map (id, id_details) = + Big_map.update(new_id, Some(new_id_details), identities); + (([]: list(operation)), { + identities : updated_identities, + next_id : new_id + 1, + name_price : storage.name_price, + skip_price : storage.skip_price, + }); + }; + +let update_owner = ((parameter, storage): (update_owner, storage)) : (list(operation), storage) => { + let void: unit = + if (amount != 0mutez) { + failwith("Updating owner doesn't cost anything."); + } + else { (); }; + let id : int = parameter.id; + let new_owner = parameter.new_owner; + let identities = storage.identities; + let current_id_details: id_details = + switch (Big_map.find_opt(id, identities)) { + | Some(id_details) => id_details + | None => (failwith("This ID does not exist."): id_details) + }; + let is_allowed: bool = + if (sender == current_id_details.owner) { true; } + else { (failwith("You are not the owner of this ID."): bool); }; + let updated_id_details: id_details = { + owner : new_owner, + controller : current_id_details.controller, + profile : current_id_details.profile, + }; + let updated_identities = Big_map.update(id, (Some updated_id_details), identities); + (([]: list(operation)), { + identities : updated_identities, + next_id : storage.next_id, + name_price : storage.name_price, + skip_price : storage.skip_price, + }); + }; + +let update_details = ((parameter, storage): (update_details, storage)) : + (list(operation), storage) => { + let void : unit = + if (amount != 0mutez) { + failwith("Updating details doesn't cost anything."); + } + else { (); }; + let id = parameter.id; + let new_profile = parameter.new_profile; + let new_controller = parameter.new_controller; + let identities = storage.identities; + let current_id_details: id_details = + switch (Big_map.find_opt(id, identities)) { + | Some(id_details) => id_details + | None => (failwith("This ID does not exist."): id_details) + }; + let is_allowed: bool = + if ((sender != current_id_details.controller) && + (sender != current_id_details.owner)) { + (failwith ("You are not the owner or controller of this ID."): bool) + } + else { true; }; + let owner: address = current_id_details.owner; + let profile: bytes = + switch (new_profile) { + | None => (* Default *) current_id_details.profile + | Some(new_profile) => new_profile + }; + let controller: address = + switch (new_controller) { + | None => (* Default *) current_id_details.controller + | Some new_controller => new_controller + }; + let updated_id_details: id_details = { + owner : owner, + controller : controller, + profile : profile, + }; + let updated_identities: big_map (id, id_details) = + Big_map.update(id, (Some updated_id_details), identities); + (([]: list(operation)), { + identities : updated_identities, + next_id : storage.next_id, + name_price : storage.name_price, + skip_price : storage.skip_price, + }); + }; + +(* Let someone skip the next identity so nobody has to take one that's undesirable *) +let skip = ((p,storage): (unit, storage)) => { + let void : unit = + if (amount != storage.skip_price) { + failwith("Incorrect amount paid."); + } + else { (); }; + (([]: list(operation)), { + identities : storage.identities, + next_id : storage.next_id + 1, + name_price : storage.name_price, + skip_price : storage.skip_price, + }); + }; + +let main = ((action, storage): (action, storage)) : (list(operation), storage) => { + switch (action) { + | Buy(b) => buy((b, storage)) + | Update_owner(uo) => update_owner((uo, storage)) + | Update_details ud => update_details((ud, storage)) + | Skip s => skip(((), storage)) + }; +}; diff --git a/src/test/id_tests_p.ml b/src/test/id_tests_p.ml index 81f08c556..6e45d4d1d 100644 --- a/src/test/id_tests_p.ml +++ b/src/test/id_tests_p.ml @@ -1,11 +1,10 @@ open Trace open Test_helpers -open Ast_simplified +open Ast_imperative -let mtype_file f = - let%bind simplified = Ligo.Compile.Of_source.compile f (Syntax_name "pascaligo") in - let%bind typed,state = Ligo.Compile.Of_simplified.compile simplified in +let type_file f = + let%bind typed,state = Ligo.Compile.Utils.type_file f "pascaligo" Env in ok (typed,state) let get_program = @@ -13,14 +12,13 @@ let get_program = fun () -> match !s with | Some s -> ok s | None -> ( - let%bind program = mtype_file "./contracts/id.ligo" in + let%bind program = type_file "./contracts/id.ligo" in s := Some program ; ok program ) let compile_main () = - let%bind simplified = Ligo.Compile.Of_source.compile "./contracts/id.ligo" (Syntax_name "pascaligo") in - let%bind typed_prg,_ = Ligo.Compile.Of_simplified.compile simplified in + let%bind typed_prg,_ = get_program () in let%bind mini_c_prg = Ligo.Compile.Of_typed.compile typed_prg in let%bind michelson_prg = Ligo.Compile.Of_mini_c.aggregate_and_compile_contract mini_c_prg "main" in let%bind (_contract: Tezos_utils.Michelson.michelson) = @@ -96,7 +94,7 @@ let buy_id_sender_addr () = ("profile", new_website)] in let param = e_record_ez [("profile", owner_website) ; - ("initial_controller", (e_typed_none t_address))] in + ("initial_controller", (e_typed_none (t_address ())))] in let new_storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1) ; (e_int 1, id_details_2)])) ; @@ -324,8 +322,8 @@ let update_details_unchanged () = ("skip_price", e_mutez 1000000) ; ] in let param = e_record_ez [("id", e_int 1) ; - ("new_profile", e_typed_none t_bytes) ; - ("new_controller", e_typed_none t_address)] in + ("new_profile", e_typed_none (t_bytes ())) ; + ("new_controller", e_typed_none (t_address ()))] in let%bind () = expect_eq ~options program "update_details" (e_pair param storage) (e_pair (e_list []) storage) diff --git a/src/test/id_tests_r.ml b/src/test/id_tests_r.ml index d795134e1..0e5e273a6 100644 --- a/src/test/id_tests_r.ml +++ b/src/test/id_tests_r.ml @@ -1,11 +1,10 @@ open Trace open Test_helpers -open Ast_simplified +open Ast_imperative -let mtype_file f = - let%bind simplified = Ligo.Compile.Of_source.compile f (Syntax_name "reasonligo") in - let%bind typed,state = Ligo.Compile.Of_simplified.compile simplified in +let retype_file f = + let%bind typed,state = Ligo.Compile.Utils.type_file f "reasonligo" Env in ok (typed,state) let get_program = @@ -13,14 +12,13 @@ let get_program = fun () -> match !s with | Some s -> ok s | None -> ( - let%bind program = mtype_file "./contracts/id.religo" in + let%bind program = retype_file "./contracts/id.religo" in s := Some program ; ok program ) let compile_main () = - let%bind simplified = Ligo.Compile.Of_source.compile "./contracts/id.religo" (Syntax_name "reasonligo") in - let%bind typed_prg,_ = Ligo.Compile.Of_simplified.compile simplified in + let%bind typed_prg,_ = get_program () in let%bind mini_c_prg = Ligo.Compile.Of_typed.compile typed_prg in let%bind michelson_prg = Ligo.Compile.Of_mini_c.aggregate_and_compile_contract mini_c_prg "main" in let%bind (_contract: Tezos_utils.Michelson.michelson) = @@ -96,7 +94,7 @@ let buy_id_sender_addr () = ("profile", new_website)] in let param = e_record_ez [("profile", owner_website) ; - ("initial_controller", (e_typed_none t_address))] in + ("initial_controller", (e_typed_none (t_address ())))] in let new_storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1) ; (e_int 1, id_details_2)])) ; @@ -324,8 +322,8 @@ let update_details_unchanged () = ("skip_price", e_mutez 1000000) ; ] in let param = e_record_ez [("id", e_int 1) ; - ("new_profile", e_typed_none t_bytes) ; - ("new_controller", e_typed_none t_address)] in + ("new_profile", e_typed_none (t_bytes ())) ; + ("new_controller", e_typed_none (t_address ()))] in let%bind () = expect_eq ~options program "update_details" (e_pair param storage) (e_pair (e_list []) storage) diff --git a/tools/webide/packages/client/package-examples.js b/tools/webide/packages/client/package-examples.js index b6e2be960..1e1d83aea 100644 --- a/tools/webide/packages/client/package-examples.js +++ b/tools/webide/packages/client/package-examples.js @@ -109,6 +109,15 @@ async function main() { // const EXAMPLES_GLOB = '**/*.ligo'; // const files = await findFiles(EXAMPLES_GLOB, EXAMPLES_DIR); + const CURATED_EXAMPLES = [ + 'pascaligo/arithmetic-contract.ligo', + 'cameligo/arithmetic-contract.ligo', + 'reasonligo/arithmetic-contract.ligo', + 'pascaligo/id.ligo', + 'cameligo/id.mligo', + 'reasonligo/id.religo', + ]; + const EXAMPLES_DEST_DIR = join(process.cwd(), 'build', 'static', 'examples'); fs.mkdirSync(EXAMPLES_DEST_DIR, { recursive: true }); From 74dab76fb413a28d0a106914dde0aab91cedfefe Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Wulfman Date: Wed, 29 Apr 2020 09:23:15 +0200 Subject: [PATCH 06/14] optimizing contract --- src/test/contracts/id.ligo | 31 ++++++------------------------ src/test/contracts/id.mligo | 36 +++++++++++------------------------ src/test/contracts/id.religo | 37 ++++++++++-------------------------- 3 files changed, 27 insertions(+), 77 deletions(-) diff --git a/src/test/contracts/id.ligo b/src/test/contracts/id.ligo index 7f6418127..f4302dbfc 100644 --- a/src/test/contracts/id.ligo +++ b/src/test/contracts/id.ligo @@ -78,11 +78,9 @@ function buy (const parameter : buy; const storage : storage) : list(operation) profile = profile ; ]; identities[new_id] := new_id_details; - end with ((nil : list(operation)), record [ + end with ((nil : list(operation)), storage with record [ identities = identities; next_id = new_id + 1; - name_price = storage.name_price; - skip_price = storage.skip_price; ]) function update_owner (const parameter : update_owner; const storage : storage) : @@ -102,18 +100,12 @@ function update_owner (const parameter : update_owner; const storage : storage) Some(id_details) -> id_details | None -> (failwith("This ID does not exist."): id_details) end; - var is_allowed : bool := False; if sender = id_details.owner - then is_allowed := True + then skip; else failwith("You are not the owner of this ID."); id_details.owner := new_owner; identities[id] := id_details; - end with ((nil: list(operation)), record [ - identities = identities; - next_id = storage.next_id; - name_price = storage.name_price; - skip_price = storage.skip_price; - ]) + end with ((nil: list(operation)), storage with record [ identities = identities; ]) function update_details (const parameter : update_details; const storage : storage ) : list(operation) * storage is @@ -130,9 +122,8 @@ function update_details (const parameter : update_details; const storage : stora Some(id_details) -> id_details | None -> (failwith("This ID does not exist."): id_details) end; - var is_allowed : bool := False; if (sender = id_details.controller) or (sender = id_details.owner) - then is_allowed := True + then skip; else failwith("You are not the owner or controller of this ID."); const owner: address = id_details.owner; const profile: bytes = @@ -149,12 +140,7 @@ function update_details (const parameter : update_details; const storage : stora id_details.controller := controller; id_details.profile := profile; identities[id] := id_details; - end with ((nil: list(operation)), record [ - identities = identities; - next_id = storage.next_id; - name_price = storage.name_price; - skip_price = storage.skip_price; - ]) + end with ((nil: list(operation)), storage with record [ identities = identities; ]) (* Let someone skip the next identity so nobody has to take one that's undesirable *) function skip_ (const p: unit; const storage: storage) : list(operation) * storage is @@ -162,12 +148,7 @@ function skip_ (const p: unit; const storage: storage) : list(operation) * stora if amount = storage.skip_price then skip else failwith("Incorrect amount paid."); - end with ((nil: list(operation)), record [ - identities = storage.identities; - next_id = storage.next_id + 1; - name_price = storage.name_price; - skip_price = storage.skip_price; - ]) + end with ((nil: list(operation)), storage with record [ next_id = storage.next_id + 1; ]) function main (const action : action; const storage : storage) : list(operation) * storage is case action of diff --git a/src/test/contracts/id.mligo b/src/test/contracts/id.mligo index 67233ce56..88cb8d3dc 100644 --- a/src/test/contracts/id.mligo +++ b/src/test/contracts/id.mligo @@ -78,10 +78,8 @@ let buy (parameter, storage: buy * storage) = let updated_identities : (id, id_details) big_map = Big_map.update new_id (Some new_id_details) identities in - ([]: operation list), {identities = updated_identities; + ([]: operation list), {storage with identities = updated_identities; next_id = new_id + 1; - name_price = storage.name_price; - skip_price = storage.skip_price; } let update_owner (parameter, storage: update_owner * storage) = @@ -96,10 +94,10 @@ let update_owner (parameter, storage: update_owner * storage) = | Some id_details -> id_details | None -> (failwith "This ID does not exist.": id_details) in - let is_allowed: bool = + let u : unit = if sender = current_id_details.owner - then true - else (failwith "You are not the owner of this ID.": bool) + then () + else failwith "You are not the owner of this ID." in let updated_id_details: id_details = { owner = new_owner; @@ -108,11 +106,7 @@ let update_owner (parameter, storage: update_owner * storage) = } in let updated_identities = Big_map.update id (Some updated_id_details) identities in - ([]: operation list), {identities = updated_identities; - next_id = storage.next_id; - name_price = storage.name_price; - skip_price = storage.skip_price; - } + ([]: operation list), {storage with identities = updated_identities} let update_details (parameter, storage: update_details * storage) = if (amount <> 0mutez) @@ -127,10 +121,10 @@ let update_details (parameter, storage: update_details * storage) = | Some id_details -> id_details | None -> (failwith "This ID does not exist.": id_details) in - let is_allowed: bool = + let u : unit = if (sender = current_id_details.controller) || (sender = current_id_details.owner) - then true - else (failwith ("You are not the owner or controller of this ID."): bool) + then () + else failwith ("You are not the owner or controller of this ID.") in let owner: address = current_id_details.owner in let profile: bytes = @@ -151,24 +145,16 @@ let update_details (parameter, storage: update_details * storage) = in let updated_identities: (id, id_details) big_map = Big_map.update id (Some updated_id_details) identities in - ([]: operation list), {identities = updated_identities; - next_id = storage.next_id; - name_price = storage.name_price; - skip_price = storage.skip_price; - } + ([]: operation list), {storage with identities = updated_identities} (* Let someone skip the next identity so nobody has to take one that's undesirable *) let skip (p,storage: unit * storage) = let void: unit = if amount = storage.skip_price then () - else (failwith "Incorrect amount paid.": unit) + else failwith "Incorrect amount paid." in - ([]: operation list), {identities = storage.identities; - next_id = storage.next_id + 1; - name_price = storage.name_price; - skip_price = storage.skip_price; - } + ([]: operation list), {storage with next_id = storage.next_id + 1} let main (action, storage : action * storage) : return = match action with diff --git a/src/test/contracts/id.religo b/src/test/contracts/id.religo index d5814e211..661d544a0 100644 --- a/src/test/contracts/id.religo +++ b/src/test/contracts/id.religo @@ -72,11 +72,9 @@ let buy = ((parameter, storage): (buy, storage)) : (list(operation), storage) => }; let updated_identities: big_map (id, id_details) = Big_map.update(new_id, Some(new_id_details), identities); - (([]: list(operation)), { + (([]: list(operation)), { ...storage, identities : updated_identities, next_id : new_id + 1, - name_price : storage.name_price, - skip_price : storage.skip_price, }); }; @@ -94,21 +92,16 @@ let update_owner = ((parameter, storage): (update_owner, storage)) : (list(opera | Some(id_details) => id_details | None => (failwith("This ID does not exist."): id_details) }; - let is_allowed: bool = - if (sender == current_id_details.owner) { true; } - else { (failwith("You are not the owner of this ID."): bool); }; + let u: unit = + if (sender == current_id_details.owner) { (); } + else { failwith("You are not the owner of this ID."); }; let updated_id_details: id_details = { owner : new_owner, controller : current_id_details.controller, profile : current_id_details.profile, }; let updated_identities = Big_map.update(id, (Some updated_id_details), identities); - (([]: list(operation)), { - identities : updated_identities, - next_id : storage.next_id, - name_price : storage.name_price, - skip_price : storage.skip_price, - }); + (([]: list(operation)), { ...storage, identities : updated_identities }); }; let update_details = ((parameter, storage): (update_details, storage)) : @@ -127,12 +120,12 @@ let update_details = ((parameter, storage): (update_details, storage)) : | Some(id_details) => id_details | None => (failwith("This ID does not exist."): id_details) }; - let is_allowed: bool = + let u: unit = if ((sender != current_id_details.controller) && (sender != current_id_details.owner)) { - (failwith ("You are not the owner or controller of this ID."): bool) + failwith ("You are not the owner or controller of this ID.") } - else { true; }; + else { (); }; let owner: address = current_id_details.owner; let profile: bytes = switch (new_profile) { @@ -151,12 +144,7 @@ let update_details = ((parameter, storage): (update_details, storage)) : }; let updated_identities: big_map (id, id_details) = Big_map.update(id, (Some updated_id_details), identities); - (([]: list(operation)), { - identities : updated_identities, - next_id : storage.next_id, - name_price : storage.name_price, - skip_price : storage.skip_price, - }); + (([]: list(operation)), { ...storage, identities : updated_identities }); }; /* Let someone skip the next identity so nobody has to take one that's undesirable */ @@ -166,12 +154,7 @@ let skip = ((p,storage): (unit, storage)) => { failwith("Incorrect amount paid."); } else { (); }; - (([]: list(operation)), { - identities : storage.identities, - next_id : storage.next_id + 1, - name_price : storage.name_price, - skip_price : storage.skip_price, - }); + (([]: list(operation)), { ...storage, next_id : storage.next_id + 1 }); }; let main = ((action, storage): (action, storage)) : (list(operation), storage) => { From 0c9aeeeb64be2ecaf25996c724f8940c1a59c3a1 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Wulfman Date: Wed, 29 Apr 2020 13:36:36 +0200 Subject: [PATCH 07/14] checking contracts --- src/test/id_tests_p.ml | 17 +++++++---------- src/test/id_tests_r.ml | 2 +- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/test/id_tests_p.ml b/src/test/id_tests_p.ml index 6e45d4d1d..106839c1b 100644 --- a/src/test/id_tests_p.ml +++ b/src/test/id_tests_p.ml @@ -4,7 +4,7 @@ open Ast_imperative let type_file f = - let%bind typed,state = Ligo.Compile.Utils.type_file f "pascaligo" Env in + let%bind typed,state = Ligo.Compile.Utils.type_file f "pascaligo" (Contract "main") in ok (typed,state) let get_program = @@ -50,10 +50,9 @@ let buy_id () = ~sender:first_contract ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.one) () in - let new_website = e_bytes_string "ligolang.org" in let id_details_2 = e_record_ez [("owner", e_address new_addr) ; ("controller", e_address new_addr) ; - ("profile", new_website)] + ("profile", owner_website)] in let param = e_record_ez [("profile", owner_website) ; ("initial_controller", (e_some (e_address new_addr))) ; @@ -88,10 +87,9 @@ let buy_id_sender_addr () = ~sender:first_contract ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.one) () in - let new_website = e_bytes_string "ligolang.org" in let id_details_2 = e_record_ez [("owner", e_address new_addr) ; ("controller", e_address new_addr) ; - ("profile", new_website)] + ("profile", owner_website)] in let param = e_record_ez [("profile", owner_website) ; ("initial_controller", (e_typed_none (t_address ())))] in @@ -147,14 +145,13 @@ let update_details_owner () = ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) () in - let new_website = e_bytes_string "ligolang.org" in let id_details_2 = e_record_ez [("owner", e_address new_addr) ; ("controller", e_address owner_addr) ; - ("profile", new_website)] + ("profile", owner_website)] in let id_details_2_diff = e_record_ez [("owner", e_address new_addr) ; ("controller", e_address new_addr) ; - ("profile", new_website)] in + ("profile", owner_website)] in let storage = e_record_ez [("identities", (e_big_map [(e_int 0, id_details_1) ; (e_int 1, id_details_2)])) ; @@ -169,7 +166,7 @@ let update_details_owner () = ("name_price", e_mutez 1000000) ; ("skip_price", e_mutez 1000000) ; ] in - let details = e_bytes_string "ligolang.org" in + let details = owner_website in let param = e_record_ez [("id", e_int 1) ; ("new_profile", e_some details) ; ("new_controller", e_some (e_address new_addr))] in @@ -192,7 +189,7 @@ let update_details_controller () = ~amount:(Memory_proto_alpha.Protocol.Alpha_context.Tez.zero) () in - let new_website = e_bytes_string "ligolang.org" in + let new_website = owner_website in let id_details_2 = e_record_ez [("owner", e_address owner_addr) ; ("controller", e_address new_addr) ; ("profile", new_website)] diff --git a/src/test/id_tests_r.ml b/src/test/id_tests_r.ml index 0e5e273a6..fe8ee6595 100644 --- a/src/test/id_tests_r.ml +++ b/src/test/id_tests_r.ml @@ -4,7 +4,7 @@ open Ast_imperative let retype_file f = - let%bind typed,state = Ligo.Compile.Utils.type_file f "reasonligo" Env in + let%bind typed,state = Ligo.Compile.Utils.type_file f "reasonligo" (Contract "main") in ok (typed,state) let get_program = From 4d51aa62cbbc804f9c4bf5b3201d1ce5b145068c Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Wulfman Date: Wed, 29 Apr 2020 13:43:02 +0200 Subject: [PATCH 08/14] removing wrong dryRun and evaluateFunction in ide examples --- src/test/examples/cameligo/id.mligo | 7 ------- src/test/examples/pascaligo/id.ligo | 5 ----- src/test/examples/reasonligo/id.religo | 5 ----- 3 files changed, 17 deletions(-) diff --git a/src/test/examples/cameligo/id.mligo b/src/test/examples/cameligo/id.mligo index 2019eb815..660c50616 100644 --- a/src/test/examples/cameligo/id.mligo +++ b/src/test/examples/cameligo/id.mligo @@ -4,17 +4,10 @@ compile: entrypoint: main dryRun: - entrypoint: main - parameters: Increment 1 - storage: 0 deploy: - entrypoint: main - storage: 0 evaluateValue: entrypoint: "" evaluateFunction: - entrypoint: add - parameters: 5, 6 *_*) type id = int diff --git a/src/test/examples/pascaligo/id.ligo b/src/test/examples/pascaligo/id.ligo index ece089aa9..468449535 100644 --- a/src/test/examples/pascaligo/id.ligo +++ b/src/test/examples/pascaligo/id.ligo @@ -4,17 +4,12 @@ compile: entrypoint: main dryRun: - entrypoint: main - parameters: Increment 1 - storage: 0 deploy: entrypoint: main storage: 0 evaluateValue: entrypoint: "" evaluateFunction: - entrypoint: add - parameters: 5, 6 *_*) type id is int diff --git a/src/test/examples/reasonligo/id.religo b/src/test/examples/reasonligo/id.religo index 3177c8fa5..715aec10d 100644 --- a/src/test/examples/reasonligo/id.religo +++ b/src/test/examples/reasonligo/id.religo @@ -4,17 +4,12 @@ compile: entrypoint: main dryRun: - entrypoint: main - parameters: Increment 1 - storage: 0 deploy: entrypoint: main storage: 0 evaluateValue: entrypoint: "" evaluateFunction: - entrypoint: add - parameters: 5, 6 *_*) type id = int From fa1185c20ed8653e9d2c0178590b42d0f9c081b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jev=20Bj=C3=B6rsell?= Date: Tue, 19 May 2020 13:15:23 -0700 Subject: [PATCH 09/14] Add new ID example contracts to dev initial state Remove duplicate def of CURATED_EXAMPLES --- tools/webide/packages/client/package-examples.js | 6 ------ tools/webide/packages/client/src/redux/examples.ts | 11 +++++++---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/tools/webide/packages/client/package-examples.js b/tools/webide/packages/client/package-examples.js index 1e1d83aea..2d7b7dbf4 100644 --- a/tools/webide/packages/client/package-examples.js +++ b/tools/webide/packages/client/package-examples.js @@ -4,12 +4,6 @@ const join = require('path').join; const fs = require('fs'); const YAML = require('yamljs'); -const CURATED_EXAMPLES = [ - 'cameligo/arithmetic-contract.ligo', - 'pascaligo/arithmetic-contract.ligo', - 'reasonligo/arithmetic-contract.ligo' -]; - function urlFriendlyHash(content) { const hash = createHash('md5'); hash.update(content); diff --git a/tools/webide/packages/client/src/redux/examples.ts b/tools/webide/packages/client/src/redux/examples.ts index 7e631cbc9..43ec23f1a 100644 --- a/tools/webide/packages/client/src/redux/examples.ts +++ b/tools/webide/packages/client/src/redux/examples.ts @@ -17,7 +17,7 @@ export interface ExamplesState { export class ChangeSelectedAction { public readonly type = ActionType.ChangeSelected; - constructor(public payload: ExamplesState['selected']) {} + constructor(public payload: ExamplesState['selected']) { } } export class ClearSelectedAction { @@ -33,9 +33,12 @@ export const DEFAULT_STATE: ExamplesState = { if (process.env.NODE_ENV === 'development') { DEFAULT_STATE.list = [ - { id: 'MzkMQ1oiVHJqbcfUuVFKTw', name: 'CameLIGO Contract' }, - { id: 'FEb62HL7onjg1424eUsGSg', name: 'PascaLIGO Contract' }, - { id: 'JPhSOehj_2MFwRIlml0ymQ', name: 'ReasonLIGO Contract' } + { id: 'MzkMQ1oiVHJqbcfUuVFKTw', name: 'Increment Example CameLIGO ' }, + { id: 'FEb62HL7onjg1424eUsGSg', name: 'Increment Example PascaLIGO' }, + { id: 'JPhSOehj_2MFwRIlml0ymQ', name: 'Increment Example ReasonLIGO' }, + { id: 'ehDv-Xaf70mQoiPhQDTAUQ', name: 'ID Example CameLIGO' }, + { id: 'CpnK7TFuUjJiQTT8KiiGyQ', name: 'ID Example ReasonLIGO' }, + { id: 'yP-THvmURsaqHxpwCravWg', name: 'ID Example PascaLIGO' }, ]; } From 5b398b47c293d17998c70c9a46d18e12ba771710 Mon Sep 17 00:00:00 2001 From: technomad21c Date: Thu, 21 May 2020 19:04:17 -0700 Subject: [PATCH 10/14] add an ID Contract example --- src/test/examples/pascaligo/id.ligo | 34 ++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/test/examples/pascaligo/id.ligo b/src/test/examples/pascaligo/id.ligo index 468449535..887d64d6d 100644 --- a/src/test/examples/pascaligo/id.ligo +++ b/src/test/examples/pascaligo/id.ligo @@ -4,12 +4,44 @@ compile: entrypoint: main dryRun: + entrypoint: main + parameters: | + Buy ( + record [ + profile=0x0501000000026869; + initial_controller=Some(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address)) + ] + ) + storage: | + record [ + identities=big_map[1->record [owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); + controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); profile=0x0501000000026869]]; + next_id=2; + name_price=0tez; + skip_price=50mutez; + ] deploy: entrypoint: main - storage: 0 + storage: evaluateValue: entrypoint: "" evaluateFunction: + entrypoint: buy + parameters: | + ( + record [ + profile=0x0501000000026869; + initial_controller=Some(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address)) + ], + + record [ identities=big_map[1->record [owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); + controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); + profile=0x0501000000026869]]; + next_id=2; + name_price=0tez; + skip_price=333mutez; + ] + ) *_*) type id is int From f29cf5a61281e7297cfe5e135943b8d7b1059c8a Mon Sep 17 00:00:00 2001 From: technomad21c Date: Fri, 22 May 2020 14:23:39 -0700 Subject: [PATCH 11/14] add the ID Contract example for cameligo and reasonligo --- src/test/examples/cameligo/id.mligo | 31 ++++++++++++++++ src/test/examples/reasonligo/id.religo | 49 +++++++++++++++++++++----- 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/src/test/examples/cameligo/id.mligo b/src/test/examples/cameligo/id.mligo index 660c50616..8ae86b16d 100644 --- a/src/test/examples/cameligo/id.mligo +++ b/src/test/examples/cameligo/id.mligo @@ -4,10 +4,41 @@ compile: entrypoint: main dryRun: + entrypoint: main + parameters: | + Buy ( + { + profile=0x0501000000026869; + initial_controller=Some(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address)) + } + ) + storage: | + { + identities=Big_map.literal[(1, {owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); profile=0x0501000000026869});]; + next_id=2; + name_price=0tez; + skip_price=333mutez + } + deploy: evaluateValue: entrypoint: "" evaluateFunction: + entrypoint: buy + parameters: | + { + profile=0x0501000000026869; + initial_controller=Some(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address)) + }, + + { + identities=Big_map.literal[(1, {owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); + controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); + profile=0x0501000000026869});]; + next_id=2; + name_price=0tez; + skip_price=333mutez + } *_*) type id = int diff --git a/src/test/examples/reasonligo/id.religo b/src/test/examples/reasonligo/id.religo index 715aec10d..456439a0c 100644 --- a/src/test/examples/reasonligo/id.religo +++ b/src/test/examples/reasonligo/id.religo @@ -1,16 +1,47 @@ -(*_* +/* (*_* name: ID Contract (ReasonLIGO) language: reasonligo compile: entrypoint: main dryRun: + entrypoint: main + parameters: | + Buy ( + { + profile: 0x0501000000026869, initial_controller: Some(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)) + } + ) + storage: | + { + identities:Big_map.literal([(1, {owner:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), + controller:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), profile:0x0501000000026869})]), + next_id:2, + name_price:0tez, + skip_price:333mutez + } deploy: entrypoint: main storage: 0 evaluateValue: entrypoint: "" evaluateFunction: -*_*) + entrypoint: buy + parameters: | + ( + { + profile: 0x0501000000026869, + initial_controller: Some(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)) + }, + { + identities:Big_map.literal([(1, {owner:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), + controller:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), + profile:0x0501000000026869})]), + next_id:2, + name_price:0tez, + skip_price:333mutez + } + ) +*_*) */ type id = int @@ -42,8 +73,8 @@ type action = | Update_details(update_details) | Skip(unit) -(* The prices kept in storage can be changed by bakers, though they should only be - adjusted down over time, not up. *) +/* The prices kept in storage can be changed by bakers, though they should only be + adjusted down over time, not up. */ type storage = { identities: big_map (id, id_details), next_id: int, @@ -51,7 +82,7 @@ type storage = { skip_price: tez, } -(** Preliminary thoughts on ids: +/** Preliminary thoughts on ids: I very much like the simplicity of http://gurno.com/adam/mne/. 5 three letter words means you have a 15 character identity, not actually more @@ -64,7 +95,7 @@ something so people don't eat up the address space. 256 ^ 5 means you have a lot of address space, but if people troll by skipping a lot that could be eaten up. Should probably do some napkin calculations for how expensive skipping needs to be to deter people from doing it just to chew up address space. -*) +*/ let buy = ((parameter, storage): (buy, storage)) : (list(operation), storage) => { let void: unit = @@ -150,12 +181,12 @@ let update_details = ((parameter, storage): (update_details, storage)) : let owner: address = current_id_details.owner; let profile: bytes = switch (new_profile) { - | None => (* Default *) current_id_details.profile + | None => /* Default */ current_id_details.profile | Some(new_profile) => new_profile }; let controller: address = switch (new_controller) { - | None => (* Default *) current_id_details.controller + | None => /* Default */ current_id_details.controller | Some new_controller => new_controller }; let updated_id_details: id_details = { @@ -173,7 +204,7 @@ let update_details = ((parameter, storage): (update_details, storage)) : }); }; -(* Let someone skip the next identity so nobody has to take one that's undesirable *) +/* Let someone skip the next identity so nobody has to take one that's undesirable */ let skip = ((p,storage): (unit, storage)) => { let void : unit = if (amount != storage.skip_price) { From a5419d01581081b347536f71537dfd3b78071fed Mon Sep 17 00:00:00 2001 From: technomad21c Date: Tue, 26 May 2020 10:01:40 -0700 Subject: [PATCH 12/14] add default parameters for deploy and modify the hashvalue for share-link test --- src/test/examples/cameligo/id.mligo | 8 +++++++- src/test/examples/pascaligo/id.ligo | 9 ++++++++- src/test/examples/reasonligo/id.religo | 7 ++++++- tools/webide/packages/e2e/test/share.spec.js | 2 +- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/test/examples/cameligo/id.mligo b/src/test/examples/cameligo/id.mligo index 8ae86b16d..cdce7161f 100644 --- a/src/test/examples/cameligo/id.mligo +++ b/src/test/examples/cameligo/id.mligo @@ -19,8 +19,14 @@ name_price=0tez; skip_price=333mutez } - deploy: + entrypoint: main + storage: | + { + identities=Big_map.literal[(1, {owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); profile=0x0501000000026869});]; + next_id=2; + name_price=10tez; + skip_price=333mutez} evaluateValue: entrypoint: "" evaluateFunction: diff --git a/src/test/examples/pascaligo/id.ligo b/src/test/examples/pascaligo/id.ligo index 887d64d6d..5178916bd 100644 --- a/src/test/examples/pascaligo/id.ligo +++ b/src/test/examples/pascaligo/id.ligo @@ -22,7 +22,14 @@ ] deploy: entrypoint: main - storage: + storage: | + record [ + identities=big_map[1->record [owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); + controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); profile=0x0501000000026869]]; + next_id=2; + name_price=0tez; + skip_price=50mutez; + ] evaluateValue: entrypoint: "" evaluateFunction: diff --git a/src/test/examples/reasonligo/id.religo b/src/test/examples/reasonligo/id.religo index 456439a0c..b399cba1b 100644 --- a/src/test/examples/reasonligo/id.religo +++ b/src/test/examples/reasonligo/id.religo @@ -21,7 +21,12 @@ } deploy: entrypoint: main - storage: 0 + storage: | + { + identities:Big_map.literal([(1, {owner:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), controller:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), profile:0x0501000000026869})]), + next_id:2, + name_price:10tez, + skip_price:333mutez} evaluateValue: entrypoint: "" evaluateFunction: diff --git a/tools/webide/packages/e2e/test/share.spec.js b/tools/webide/packages/e2e/test/share.spec.js index dd73d64db..2cece1c97 100644 --- a/tools/webide/packages/e2e/test/share.spec.js +++ b/tools/webide/packages/e2e/test/share.spec.js @@ -24,7 +24,7 @@ describe('Share', () => { await responseCallback; const actualShareLink = await page.evaluate(getInputValue, 'share-link'); - const expectedShareLink = `${API_HOST}/p/WxKPBq9-mkZ_kq4cMHXfCQ`; + const expectedShareLink = `${API_HOST}/p/2GnQR0cUYeO7feAw71SJYQ` expect(actualShareLink).toEqual(expectedShareLink); done(); From 9d0da34f965155e209a1d970d4ec77b0afba0d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jev=20Bj=C3=B6rsell?= Date: Thu, 28 May 2020 11:40:05 -0700 Subject: [PATCH 13/14] Improve formatting of default webide values --- src/test/examples/cameligo/id.mligo | 36 ++++++++++++++----- src/test/examples/pascaligo/id.ligo | 25 ++++++++++---- src/test/examples/reasonligo/id.religo | 48 +++++++++++++++++--------- 3 files changed, 76 insertions(+), 33 deletions(-) diff --git a/src/test/examples/cameligo/id.mligo b/src/test/examples/cameligo/id.mligo index cdce7161f..9f9fabac9 100644 --- a/src/test/examples/cameligo/id.mligo +++ b/src/test/examples/cameligo/id.mligo @@ -14,7 +14,13 @@ ) storage: | { - identities=Big_map.literal[(1, {owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); profile=0x0501000000026869});]; + identities=Big_map.literal[ + (1, + {owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); + controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); + profile=0x0501000000026869} + ); + ]; next_id=2; name_price=0tez; skip_price=333mutez @@ -23,10 +29,17 @@ entrypoint: main storage: | { - identities=Big_map.literal[(1, {owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); profile=0x0501000000026869});]; + identities=Big_map.literal[ + (1, + {owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); + controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); + profile=0x0501000000026869} + ); + ]; next_id=2; name_price=10tez; - skip_price=333mutez} + skip_price=333mutez + } evaluateValue: entrypoint: "" evaluateFunction: @@ -38,9 +51,13 @@ }, { - identities=Big_map.literal[(1, {owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); - controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); - profile=0x0501000000026869});]; + identities=Big_map.literal[ + (1, + {owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); + controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); + profile=0x0501000000026869} + ); + ]; next_id=2; name_price=0tez; skip_price=333mutez @@ -88,13 +105,14 @@ type storage = { (** Preliminary thoughts on ids: -I very much like the simplicity of http://gurno.com/adam/mne/. -5 three letter words means you have a 15 character identity, not actually more +I very much like the simplicity of http://gurno.com/adam/mne/ + +Five three letter words means you have a 15 character identity, not actually more annoying than an IP address and a lot more memorable than the raw digits. This can be stored as a single integer which is then translated into the corresponding series of 5 words. -I in general like the idea of having a 'skip' mechanism, but it does need to cost +I, in general like the idea of having a 'skip' mechanism, but it does need to cost something so people don't eat up the address space. 256 ^ 5 means you have a lot of address space, but if people troll by skipping a lot that could be eaten up. Should probably do some napkin calculations for how expensive skipping needs to diff --git a/src/test/examples/pascaligo/id.ligo b/src/test/examples/pascaligo/id.ligo index 5178916bd..a0023e201 100644 --- a/src/test/examples/pascaligo/id.ligo +++ b/src/test/examples/pascaligo/id.ligo @@ -14,8 +14,12 @@ ) storage: | record [ - identities=big_map[1->record [owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); - controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); profile=0x0501000000026869]]; + identities=big_map[ + 1->record + [owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); + controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); + profile=0x0501000000026869] + ]; next_id=2; name_price=0tez; skip_price=50mutez; @@ -24,8 +28,12 @@ entrypoint: main storage: | record [ - identities=big_map[1->record [owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); - controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); profile=0x0501000000026869]]; + identities=big_map[ + 1->record + [owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); + controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); + profile=0x0501000000026869] + ]; next_id=2; name_price=0tez; skip_price=50mutez; @@ -41,9 +49,12 @@ initial_controller=Some(("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address)) ], - record [ identities=big_map[1->record [owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); - controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); - profile=0x0501000000026869]]; + record [ identities=big_map[ + 1->record + [owner=("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address); + controller=("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address); + profile=0x0501000000026869] + ]; next_id=2; name_price=0tez; skip_price=333mutez; diff --git a/src/test/examples/reasonligo/id.religo b/src/test/examples/reasonligo/id.religo index b399cba1b..9131a9080 100644 --- a/src/test/examples/reasonligo/id.religo +++ b/src/test/examples/reasonligo/id.religo @@ -7,26 +7,36 @@ entrypoint: main parameters: | Buy ( - { - profile: 0x0501000000026869, initial_controller: Some(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)) + { + profile: 0x0501000000026869, + initial_controller: Some(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)) } ) storage: | { - identities:Big_map.literal([(1, {owner:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), - controller:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), profile:0x0501000000026869})]), - next_id:2, - name_price:0tez, + identities:Big_map.literal([ + (1, + {owner:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), + controller:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), profile:0x0501000000026869} + ) + ]), + next_id:2, + name_price:0tez, skip_price:333mutez } deploy: entrypoint: main storage: | { - identities:Big_map.literal([(1, {owner:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), controller:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), profile:0x0501000000026869})]), - next_id:2, - name_price:10tez, - skip_price:333mutez} + identities:Big_map.literal([ + (1, + {owner:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), controller:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), profile:0x0501000000026869} + ) + ]), + next_id:2, + name_price:10tez, + skip_price:333mutez + } evaluateValue: entrypoint: "" evaluateFunction: @@ -34,15 +44,19 @@ parameters: | ( { - profile: 0x0501000000026869, + profile: 0x0501000000026869, initial_controller: Some(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address)) }, { - identities:Big_map.literal([(1, {owner:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), - controller:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), - profile:0x0501000000026869})]), - next_id:2, - name_price:0tez, + identities:Big_map.literal([ + (1, + {owner:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address), + controller:("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), + profile:0x0501000000026869} + ) + ]), + next_id:2, + name_price:0tez, skip_price:333mutez } ) @@ -163,7 +177,7 @@ let update_owner = ((parameter, storage): (update_owner, storage)) : (list(opera let update_details = ((parameter, storage): (update_details, storage)) : (list(operation), storage) => { - let void : unit = + let void : unit = if (amount != 0mutez) { failwith("Updating details doesn't cost anything."); } From 267e2821746110538f9d2f190d91e22b63b0deb1 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Wulfman Date: Tue, 2 Jun 2020 17:02:16 +0200 Subject: [PATCH 14/14] rebase --- src/test/id_tests_p.ml | 28 ++++++++++++++-------------- src/test/id_tests_r.ml | 26 +++++++++++++------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/test/id_tests_p.ml b/src/test/id_tests_p.ml index 106839c1b..714af1c39 100644 --- a/src/test/id_tests_p.ml +++ b/src/test/id_tests_p.ml @@ -33,7 +33,7 @@ let (first_owner , first_contract) = Protocol.Alpha_context.Contract.to_b58check kt , kt let buy_id () = - let%bind program, _ = get_program () in + let%bind program, state = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -64,13 +64,13 @@ let buy_id () = ("name_price", e_mutez 1000000) ; ("skip_price", e_mutez 1000000) ; ] in - let%bind () = expect_eq ~options program "buy" + let%bind () = expect_eq ~options (program, state) "buy" (e_pair param storage) (e_pair (e_list []) new_storage) in ok () let buy_id_sender_addr () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -107,7 +107,7 @@ let buy_id_sender_addr () = (* Test that contract fails if we attempt to buy an ID for the wrong amount *) let buy_id_wrong_amount () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -132,7 +132,7 @@ let buy_id_wrong_amount () = in ok () let update_details_owner () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -176,7 +176,7 @@ let update_details_owner () = in ok () let update_details_controller () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -222,7 +222,7 @@ let update_details_controller () = (* Test that contract fails when we attempt to update details of nonexistent ID *) let update_details_nonexistent () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -258,7 +258,7 @@ let update_details_nonexistent () = (* Test that contract fails when we attempt to update details from wrong addr *) let update_details_wrong_addr () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -293,7 +293,7 @@ let update_details_wrong_addr () = (* Test that giving none on both profile and controller address is a no-op *) let update_details_unchanged () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -327,7 +327,7 @@ let update_details_unchanged () = in ok () let update_owner () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -371,7 +371,7 @@ let update_owner () = (* Test that contract fails when we attempt to update owner of nonexistent ID *) let update_owner_nonexistent () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -405,7 +405,7 @@ let update_owner_nonexistent () = (* Test that contract fails when we attempt to update owner from non-owner addr *) let update_owner_wrong_addr () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -438,7 +438,7 @@ let update_owner_wrong_addr () = in ok () let skip () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -476,7 +476,7 @@ let skip () = (* Test that contract fails if we try to skip without paying the right amount *) let skip_wrong_amount () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; diff --git a/src/test/id_tests_r.ml b/src/test/id_tests_r.ml index fe8ee6595..d36c84929 100644 --- a/src/test/id_tests_r.ml +++ b/src/test/id_tests_r.ml @@ -33,7 +33,7 @@ let (first_owner , first_contract) = Protocol.Alpha_context.Contract.to_b58check kt , kt let buy_id () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -71,7 +71,7 @@ let buy_id () = in ok () let buy_id_sender_addr () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -109,7 +109,7 @@ let buy_id_sender_addr () = (* Test that contract fails if we attempt to buy an ID for the wrong amount *) let buy_id_wrong_amount () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -134,7 +134,7 @@ let buy_id_wrong_amount () = in ok () let update_details_owner () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -179,7 +179,7 @@ let update_details_owner () = in ok () let update_details_controller () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -225,7 +225,7 @@ let update_details_controller () = (* Test that contract fails when we attempt to update details of nonexistent ID *) let update_details_nonexistent () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -261,7 +261,7 @@ let update_details_nonexistent () = (* Test that contract fails when we attempt to update details from wrong addr *) let update_details_wrong_addr () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -296,7 +296,7 @@ let update_details_wrong_addr () = (* Test that giving none on both profile and controller address is a no-op *) let update_details_unchanged () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -330,7 +330,7 @@ let update_details_unchanged () = in ok () let update_owner () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -374,7 +374,7 @@ let update_owner () = (* Test that contract fails when we attempt to update owner of nonexistent ID *) let update_owner_nonexistent () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -408,7 +408,7 @@ let update_owner_nonexistent () = (* Test that contract fails when we attempt to update owner from non-owner addr *) let update_owner_wrong_addr () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -441,7 +441,7 @@ let update_owner_wrong_addr () = in ok () let skip () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ; @@ -479,7 +479,7 @@ let skip () = (* Test that contract fails if we try to skip without paying the right amount *) let skip_wrong_amount () = - let%bind program, _ = get_program () in + let%bind program = get_program () in let owner_addr = addr 5 in let owner_website = e_bytes_string "ligolang.org" in let id_details_1 = e_record_ez [("owner", e_address owner_addr) ;