From 37a3fde6fd41447730003f46b031b0b2d01ad584 Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Sat, 29 Feb 2020 00:12:24 -0800 Subject: [PATCH] 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 ;