diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4d66ffe..082a847 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -59,23 +59,14 @@ jobs: asset_path: ./_build/app/metadata.json asset_name: metadata.json asset_content_type: application/json - - name: Upload unit contract + - name: Upload contract uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ github.token }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./_build/app/tzsafe_unit.tez - asset_name: tzsafe_unit.tez - asset_content_type: application/text - - name: Upload bytes contract - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ github.token }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./_build/app/tzsafe_bytes.tez - asset_name: tzsafe_bytes.tez + asset_path: ./_build/app/tzsafe.tez + asset_name: tzsafe.tez asset_content_type: application/text - name: Upload artifact uses: actions/upload-artifact@v3 diff --git a/Makefile b/Makefile index 93bf4d4..4b6e80f 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ BUILT_APP_DIRECTORY:=$(BUILD_DIRECTORY)/$(APP_DIRECTORY) # Ligo compiler LIGO_COMPILER_ARGS:=--protocol nairobi -LIGO_VERSION:=0.70.1 +LIGO_VERSION:=0.73.0 LIGO?=ligo LIGO_BUILD=$(LIGO) compile contract $(LIGO_COMPILER_ARGS) LIGO_TEST=$(LIGO) run test @@ -25,7 +25,7 @@ LIGO_CURRENT_VERSION:=$(shell $(LIGO) --version) LIGO_INSTALL=$(LIGO) install # Tezos binaries -TEZOS_BINARIES_VERSION:=v17.1-1 +TEZOS_BINARIES_VERSION:=v15.1-1 TEZOS_BINARIES_REPO:=https://github.com/serokell/tezos-packaging/releases/download/ TEZOS_BINARIES_URL:=$(TEZOS_BINARIES_REPO)$(TEZOS_BINARIES_VERSION) @@ -42,8 +42,7 @@ build-metadata: build-contract: check-ligo-version mkdir -p $(BUILT_APP_DIRECTORY) - $(LIGO_BUILD) $(APP_DIRECTORY)/main_unit.mligo > $(BUILT_APP_DIRECTORY)/$(PROJECT_NAME)_unit.tez - $(LIGO_BUILD) $(APP_DIRECTORY)/main_bytes.mligo > $(BUILT_APP_DIRECTORY)/$(PROJECT_NAME)_bytes.tez + $(LIGO_BUILD) $(APP_DIRECTORY)/main.mligo > $(BUILT_APP_DIRECTORY)/$(PROJECT_NAME).tez test: $(LIGO_TEST) $(TEST_DIRECTORY)/test.mligo @@ -72,8 +71,7 @@ gen-wallet: deploy: $(eval SIGNER := $(shell TEZOS_CLIENT_UNSAFE_DISABLE_DISCLAIMER=yes ./_build/octez-client --endpoint https://ghostnet.tezos.marigold.dev show address wallet_address | grep Hash | awk '{print $$2}')) - $(BUILD_DIRECTORY)/octez-client --endpoint https://ghostnet.tezos.marigold.dev originate contract $(PROJECT_NAME)_unit transferring 2 from wallet_address running $(BUILT_APP_DIRECTORY)/$(PROJECT_NAME)_unit.tez --init '(Pair 0 {} {"$(SIGNER)";} 1 604800 {})' --burn-cap 2 -f - $(BUILD_DIRECTORY)/octez-client --endpoint https://ghostnet.tezos.marigold.dev originate contract $(PROJECT_NAME)_bytes transferring 2 from wallet_address running $(BUILT_APP_DIRECTORY)/$(PROJECT_NAME)_bytes.tez --init '(Pair 0 {} {"$(SIGNER)";} 1 604800 {})' --burn-cap 2 -f + $(BUILD_DIRECTORY)/octez-client --endpoint https://ghostnet.tezos.marigold.dev originate contract $(PROJECT_NAME) transferring 2 from wallet_address running $(BUILT_APP_DIRECTORY)/$(PROJECT_NAME).tez --init '(Pair 0 {} {} {"$(SIGNER)"; "tz1inzFwAjE4oWXMabJFZdPHoDQN5S4XB3wH"} 1 604800 {})' --burn-cap 3 -f get-tezos-binary: wget -O $(BUILD_DIRECTORY)/octez-client $(TEZOS_BINARIES_URL)/octez-client diff --git a/app/main.mligo b/app/main.mligo new file mode 100644 index 0000000..4361929 --- /dev/null +++ b/app/main.mligo @@ -0,0 +1,25 @@ +(* MIT License + Copyright (c) 2022 Marigold + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. *) + +#import "../src/lib.mligo" "Lib" + +type result = Lib.result +type request = Lib.request + +let main (request : request) : result = + Lib.contract request diff --git a/package.json b/package.json index 0a0477e..861eda9 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "TzSafe", - "version": "0.3.0", + "version": "0.3.1", "author": "Marigold ", - "description": "TzSafe is a multisig wallet aiming at providing better assurance of security and management of ownership than a traditional single-signed wallet. The implementation adheres to the guidelines specified in TZIP-26.", + "description": "TzSafe is a multisig wallet aiming at providing better assurance of security and management of ownership than a traditional single-signed wallet. The implementation adheres to the guidelines specified in TZIP-27.", "scripts": { "test": "ligo run test test/test.mligo --project-root ." }, diff --git a/src/common/errors.mligo b/src/common/errors.mligo index a87a02e..5fb83a2 100644 --- a/src/common/errors.mligo +++ b/src/common/errors.mligo @@ -24,7 +24,7 @@ let unknown_contract = "Unknown contract" let invalidated_threshold = "Threshold must be greater than 1" let no_owner = "Require at least one owner in the contract" let no_enough_owner = "Number of owner should be greater than threshold" -let unresolved = "This proposal has been resolved" +let already_resolved = "This proposal has been resolved" let no_enough_signature_to_resolve = "No enough signature to resolve the proposal" let no_proposal = "There is no content in proposal" let no_owners = "No owner to be added or removed" diff --git a/src/internal/conditions.mligo b/src/internal/conditions.mligo index b5860ba..55978ed 100644 --- a/src/internal/conditions.mligo +++ b/src/internal/conditions.mligo @@ -29,34 +29,23 @@ type storage_types_proposal_state = Storage.Types.proposal_state type effective_period = Storage.Types.effective_period type proposal_content = Proposal_content.Types.t -[@inline] -let only_owner (type a) (storage : a storage_types) : unit = +let only_owner (storage : storage_types) : unit = assert_with_error (Set.mem (Tezos.get_sender ()) storage.owners) Errors.only_owner -[@inline] -let amount_must_be_zero_tez (an_amout : tez) : unit = - assert_with_error (an_amout = 0tez) Errors.amount_must_be_zero_tez +let amount_must_be_zero_tez (amount : tez) : unit = + assert_with_error (amount = 0tez) Errors.amount_must_be_zero_tez -[@inline] -let unsigned (type a) (proposal : a storage_types_proposal) : unit = +let unsigned (proposal : storage_types_proposal) : unit = assert_with_error (not Map.mem (Tezos.get_sender ()) proposal.signatures) Errors.has_already_signed -[@inline] let ready_to_execute (state : storage_types_proposal_state) : unit = assert_with_error (not (state = (Proposing : storage_types_proposal_state))) Errors.no_enough_signature_to_resolve -[@inline] -let unresolved (state : storage_types_proposal_state) : unit = - assert_with_error (state = (Proposing : storage_types_proposal_state)) Errors.unresolved - -[@inline] -let check_proposal (type a) (content: a proposal_content) : unit = +let check_proposal (content: proposal_content) : unit = match content with | Transfer t -> assert_with_error (not (t.amount = 0tez)) Errors.amount_is_zero - | Execute _ -> () - | Execute_lambda e -> - assert_with_error (Util.is_some e.lambda) Errors.no_proposal + | Execute_lambda _ -> () | Adjust_threshold t -> assert_with_error (t > 0n) Errors.invalidated_threshold | Add_owners s -> @@ -66,24 +55,20 @@ let check_proposal (type a) (content: a proposal_content) : unit = | Adjust_effective_period p -> assert_with_error (p > 0) Errors.invalid_effective_period -[@inline] -let not_empty_content (type a) (proposals_content: (a proposal_content) list) : unit = +let not_empty_content (proposals_content: proposal_content list) : unit = let () = assert_with_error ((List.length proposals_content) > 0n) Errors.no_proposal in List.iter check_proposal proposals_content -[@inline] -let check_setting (type a) (storage : a storage_types) : unit = +let check_setting (storage : storage_types) : unit = let () = assert_with_error (Set.cardinal storage.owners > 0n) Errors.no_owner in let () = assert_with_error (Set.cardinal storage.owners >= storage.threshold) Errors.no_enough_owner in let () = assert_with_error (storage.threshold > 0n) Errors.invalidated_threshold in let () = assert_with_error (storage.effective_period > 0) Errors.invalid_effective_period in () -[@inline] -let check_proposals_content (type a) (pack_from_input : bytes) (from_storage: (a proposal_content) list) : unit = +let check_proposals_content (from_input: bytes) (from_storage: proposal_content list) : unit = let pack_from_storage = Bytes.pack from_storage in - assert_with_error (pack_from_input = pack_from_storage) Errors.not_the_same_content + assert_with_error (from_input = pack_from_storage) Errors.not_the_same_content -[@inline] let within_expiration_time (created_timestamp: timestamp) (effective_period: effective_period) : unit = assert_with_error (created_timestamp + effective_period > Tezos.get_now ()) Errors.pass_expiration_time diff --git a/src/internal/contract.mligo b/src/internal/contract.mligo index e7d8faf..b69b5ba 100644 --- a/src/internal/contract.mligo +++ b/src/internal/contract.mligo @@ -24,98 +24,106 @@ #import "storage.mligo" "Storage" #import "conditions.mligo" "Conditions" #import "execution.mligo" "Execution" +#import "event.mligo" "Event" type parameter_types = Parameter.Types.t +type payload = Parameter.Types.payload +type challenge_id = Parameter.Types.challenge_id type storage_types = Storage.Types.t type storage_types_proposal = Storage.Types.proposal type storage_types_proposal_state = Storage.Types.proposal_state type effective_period = Storage.Types.effective_period type proposal_content = Proposal_content.Types.t -type 'a request = 'a parameter_types * 'a storage_types -type 'a result = operation list * 'a storage_types +type request = parameter_types * storage_types +type result = operation list * storage_types (** * Default entrypoint *) -let default (type a) (_, s : unit * a storage_types) : a result = - let event = Tezos.emit "%receiving_tez" (Tezos.get_sender (), Tezos.get_amount ()) in +let default (_, s : unit * storage_types) : result = + let event = Tezos.emit "%receiving_tez" ({ from = Tezos.get_sender (); amount = Tezos.get_amount (); } : Event.Types.receiving_tez) in ([event], s) (** * Proposal creation *) -let create_proposal (type a) (proposal_content, storage : (a proposal_content) list * a storage_types) : a result = + +let create_proposal (proposal_contents, storage : proposal_content list * storage_types) : result = let () = Conditions.only_owner storage in let () = Conditions.amount_must_be_zero_tez (Tezos.get_amount ()) in - let () = Conditions.not_empty_content proposal_content in - let proposal = Storage.Op.create_proposal proposal_content in + let () = Conditions.not_empty_content proposal_contents in + let proposal = Storage.Op.create_proposal proposal_contents in let storage = Storage.Op.register_proposal(proposal, storage) in - let event = Tezos.emit "%create_proposal" (bytes storage.proposal_counter, proposal) in + let packed_proposal_contents = Bytes.pack proposal_contents in + let event = Tezos.emit "%create_proposal" ({ challenge_id = bytes storage.proposal_counter; payload = packed_proposal_contents } : Event.Types.create_proposal) in ([event], storage) (** - * Proposal signature only + * Proposal Signing *) -let sign_proposal (type a) - ( proposal_id, proposal_content, agreement, storage - : Parameter.Types.proposal_id - * (a proposal_content) list +let sign_proposal + ( challenge_id, proposal_content, agreement, storage + : challenge_id + * payload * Parameter.Types.agreement - * a storage_types) - : a result = + * storage_types) + : result = let () = Conditions.only_owner storage in let () = Conditions.amount_must_be_zero_tez (Tezos.get_amount ()) in - let proposal = Storage.Op.retrieve_proposal(proposal_id, storage) in - let () = Conditions.unresolved proposal.state in + let proposal = Storage.Op.retrieve_proposal (challenge_id, storage) in let () = Conditions.unsigned proposal in let () = Conditions.within_expiration_time proposal.proposer.timestamp storage.effective_period in - let packed_proposal_content = Bytes.pack proposal_content in - let () = Conditions.check_proposals_content packed_proposal_content proposal.contents in + let () = Conditions.check_proposals_content proposal_content proposal.contents in let owner = Tezos.get_sender () in let proposal = Storage.Op.update_signature (proposal, owner, agreement) in - let storage = Storage.Op.update_proposal(proposal_id, proposal, storage) in - let event = Tezos.emit "%sign_proposal" (proposal_id, owner, agreement) in + let storage = Storage.Op.update_proposal(challenge_id, proposal, storage) in + let event = Tezos.emit "%sign_proposal" ({challenge_id; signer = owner; agreement } : Event.Types.sign_proposal) in ([event], storage) (** * Proposal Execution *) -let resolve_proposal (type a) - ( proposal_id, packed_proposal_content, storage - : Parameter.Types.proposal_id - * bytes - * a storage_types) - : a result = +let resolve_proposal + ( challenge_id, proposal_content, storage + : challenge_id + * payload + * storage_types) + : result = let () = Conditions.only_owner storage in let () = Conditions.amount_must_be_zero_tez (Tezos.get_amount ()) in - let proposal = Storage.Op.retrieve_proposal(proposal_id, storage) in - let () = Conditions.unresolved proposal.state in - let () = Conditions.check_proposals_content packed_proposal_content proposal.contents in - let owner = Tezos.get_sender () in + let proposal = Storage.Op.retrieve_proposal(challenge_id, storage) in + let () = Conditions.check_proposals_content proposal_content proposal.contents in let expiration_time = proposal.proposer.timestamp + storage.effective_period in let proposal = Storage.Op.update_proposal_state (proposal, storage.owners, storage.threshold, expiration_time) in let () = Conditions.ready_to_execute proposal.state in - let storage = Storage.Op.update_proposal(proposal_id, proposal, storage) in - let ops, proposal, storage = Execution.perform_operations proposal storage in - let storage = Storage.Op.update_proposal(proposal_id, proposal, storage) in - let event = Tezos.emit "%resolve_proposal" (proposal_id, owner) in - let poe = Tezos.emit "%proof_of_event" (proposal_id, packed_proposal_content) in - (poe::event::ops, storage) + let storage = Storage.Op.update_proposal(challenge_id, proposal, storage) in + let ops, storage = Execution.perform_operations challenge_id proposal storage in + let event = Tezos.emit "%resolve_proposal" ({ challenge_id = challenge_id; proposal_state = proposal.state } : Event.Types.resolve_proposal) in + (event::ops, storage) + +(** + * Update Metadata + *) +let update_metadata (key, value, storage : string * bytes * storage_types) : result = + let s = Storage.Op.update_metadata (key, value, storage) in + ([], s) -let contract (type a) (action, storage : a request) : a result = +let contract (action, storage : request) : result = let ops, storage = match action with | Default u -> default (u, storage) - | Create_proposal (proposal_params) -> - create_proposal (proposal_params, storage) - | Sign_proposal (proposal_id, proposal_content, agreement) -> - sign_proposal (proposal_id, proposal_content, agreement, storage) - | Proof_of_event_challenge { challenge_id; payload; } -> + | Create_proposal { proposal_contents } -> + create_proposal (proposal_contents, storage) + | Sign_proposal { challenge_id; payload; agreement } -> + sign_proposal (challenge_id, payload, agreement, storage) + | Proof_of_event_challenge { challenge_id; payload } -> resolve_proposal (challenge_id, payload, storage) + | Update_metadata { key; value } -> + update_metadata(key, value, storage) in let _ = Conditions.check_setting storage in (ops, storage) diff --git a/src/internal/event.mligo b/src/internal/event.mligo new file mode 100644 index 0000000..da66782 --- /dev/null +++ b/src/internal/event.mligo @@ -0,0 +1,34 @@ +(* MIT License + Copyright (c) 2022 Marigold + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. *) + +#import "parameter.mligo" "Parameter" +#import "storage.mligo" "Storage" + +module Types = struct + + type challenge_id = Parameter.Types.challenge_id + type payload = Parameter.Types.payload + type agreement = Parameter.Types.agreement + type proposal_state = Storage.Types.proposal_state + + type create_proposal = { challenge_id: challenge_id; payload: payload} + type sign_proposal = { challenge_id: challenge_id; signer: address; agreement: agreement} + type resolve_proposal = { challenge_id: challenge_id; proposal_state: proposal_state} + type proof_of_event = { challenge_id: challenge_id; payload: payload} + type receiving_tez = { from :address ; amount : tez} +end diff --git a/src/internal/execution.mligo b/src/internal/execution.mligo index 7a841f9..e7d882f 100644 --- a/src/internal/execution.mligo +++ b/src/internal/execution.mligo @@ -22,59 +22,51 @@ #import "proposal_content.mligo" "Proposal_content" #import "./storage.mligo" "Storage" #import "conditions.mligo" "Conditions" +#import "event.mligo" "Event" type storage_types = Storage.Types.t +type storage_types_challenge_id = Storage.Types.challenge_id type storage_types_proposal = Storage.Types.proposal type storage_types_proposal_state = Storage.Types.proposal_state type proposal_content = Proposal_content.Types.t -let send_by (type a) (parameter: a) (target : address) (amount : tez) : operation = - [@no_mutation] - let contract_opt : a contract option = Tezos.get_contract_opt target in +let send_by (target : address) (amount : tez) : operation = + let contract_opt : unit contract option = Tezos.get_contract_opt target in let contract = Option.unopt_with_error contract_opt Errors.unknown_contract in - Tezos.transaction parameter amount contract + Tezos.transaction () amount contract -let send (type a) (content : a proposal_content) (storage : a storage_types) - : (operation option * a proposal_content * a storage_types) = +let send (content : proposal_content) (storage : storage_types) + : (operation list * storage_types) = match content with - | Transfer tx -> (Some (send_by tx.parameter tx.target tx.amount), content, storage) - | Execute tx -> (Some (send_by tx.parameter tx.target tx.amount), content, storage) - | Execute_lambda e -> - let new_content = Execute_lambda { e with lambda = None } in - (Option.map (fun (f : (unit -> operation)) : operation -> f ()) e.lambda, new_content, storage) - | Adjust_threshold t -> (None, content, Storage.Op.adjust_threshold t storage) - | Add_owners s -> (None, content, Storage.Op.add_owners s storage) - | Remove_owners s -> (None, content, Storage.Op.remove_owners s storage) - | Adjust_effective_period i -> (None, content, Storage.Op.adjust_effective_period i storage) + | Transfer tx -> ([send_by tx.target tx.amount], storage) + | Execute_lambda e -> (e.lambda (), storage) + | Adjust_threshold t -> ([], Storage.Op.adjust_threshold t storage) + | Add_owners s -> ([], Storage.Op.add_owners s storage) + | Remove_owners s -> ([], Storage.Op.remove_owners s storage) + | Adjust_effective_period i -> ([], Storage.Op.adjust_effective_period i storage) -let clear (type a) (content : a proposal_content) : (a proposal_content) = - match content with - | Transfer _ -> content - | Execute _ -> content - | Execute_lambda e -> Execute_lambda { e with lambda = None } - | Adjust_threshold _ -> content - | Add_owners _ -> content - | Remove_owners _ -> content - | Adjust_effective_period _ -> content - -let perform_operations (type a) (proposal: a storage_types_proposal) (storage : a storage_types) : operation list * a storage_types_proposal * a storage_types = - let batch (type a) ((ops, cs, s), c : (operation list * a proposal_content list * a storage_types) * a proposal_content) : (operation list * a proposal_content list * a storage_types) = - let (opt_op, new_c, new_s) = send c s in - match opt_op with - | Some op -> op::ops, new_c::cs, new_s - | None -> ops, new_c::cs, new_s +let perform_operations + (challenge_id: storage_types_challenge_id) + (proposal: storage_types_proposal) + (storage : storage_types) + : operation list * storage_types = + let batch ((ops, s), c : (operation list * storage_types) * proposal_content) : (operation list * storage_types) = + let (new_ops, new_s) = send c s in + let acc (x,ys : (operation * operation list)) : operation list = x :: ys in + List.fold_right acc ops new_ops, new_s in + let proof = Tezos.emit "%proof_of_event" ({challenge_id; payload = Bytes.pack proposal} : Event.Types.proof_of_event) in match proposal.state with | Executed -> - let (ops, cs, s) = List.fold_left batch (Constants.no_operation, [], storage) proposal.contents in - let ops = Util.reverse ops in - let cs = Util.reverse cs in - (ops, { proposal with contents = cs} , s) - | Proposing -> (Constants.no_operation, proposal, storage) + let (ops, s) = List.fold_left batch (Constants.no_operation, storage) proposal.contents in + let new_s = Storage.Op.archive_proposal (challenge_id, Executed, s) in + (proof::ops, new_s) + | Proposing -> + (Constants.no_operation, storage) | Rejected -> - let proposal = { proposal with contents = List.map clear proposal.contents } in - (Constants.no_operation, proposal, storage) + let new_s = Storage.Op.archive_proposal (challenge_id, Rejected, storage) in + ([proof], new_s) | Expired -> - let proposal = { proposal with contents = List.map clear proposal.contents } in - (Constants.no_operation, proposal, storage) + let new_s = Storage.Op.archive_proposal (challenge_id, Expired, storage) in + ([proof], new_s) diff --git a/src/internal/parameter.mligo b/src/internal/parameter.mligo index 7262be5..2f1455c 100644 --- a/src/internal/parameter.mligo +++ b/src/internal/parameter.mligo @@ -20,14 +20,15 @@ module Types = struct type proposal_content = Proposal_content.Types.t - type proposal_id = bytes + type challenge_id = bytes + type payload = bytes type agreement = bool type expiration_time = timestamp - type proof_of_event_challenge = { challenge_id : bytes; payload : bytes; } - type 'a t = + type t = | Default of unit - | Create_proposal of ('a proposal_content) list - | Sign_proposal of (proposal_id * ('a proposal_content) list * agreement) - | Proof_of_event_challenge of proof_of_event_challenge + | Create_proposal of { proposal_contents: proposal_content list } + | Sign_proposal of { challenge_id: challenge_id ; payload: payload; agreement: agreement } + | Proof_of_event_challenge of { challenge_id: challenge_id; payload: payload } + | Update_metadata of { key: string; value: bytes; } end diff --git a/src/internal/proposal_content.mligo b/src/internal/proposal_content.mligo index b99ecfe..dc9c828 100644 --- a/src/internal/proposal_content.mligo +++ b/src/internal/proposal_content.mligo @@ -17,18 +17,16 @@ SOFTWARE. *) module Types = struct - type 'a transaction = + type transaction = [@layout:comb] { target: address; - parameter: 'a; amount: tez; } - type 'a t = - | Transfer of unit transaction - | Execute of ('a transaction) - | Execute_lambda of { metadata: bytes option; lambda: (unit -> operation) option } + type t = + | Transfer of transaction + | Execute_lambda of { metadata: bytes option; lambda: (unit -> operation list)} | Adjust_threshold of nat | Add_owners of address set | Remove_owners of address set diff --git a/src/internal/storage.mligo b/src/internal/storage.mligo index 3707665..0c41e03 100644 --- a/src/internal/storage.mligo +++ b/src/internal/storage.mligo @@ -22,7 +22,7 @@ #import "proposal_content.mligo" "Proposal_content" module Types = struct - type proposal_id = Parameter.Types.proposal_id + type challenge_id = Parameter.Types.challenge_id type proposal_content = Proposal_content.Types.t type effective_period = int @@ -35,21 +35,22 @@ module Types = struct type proposal_state = Proposing | Executed | Rejected | Expired - type 'a proposal = + type proposal = [@layout:comb] { state: proposal_state; signatures: (address, bool) map; proposer : actor; resolver : actor option; - contents : ('a proposal_content) list + contents : proposal_content list } - type 'a t = + type t = [@layout:comb] { proposal_counter : nat; - proposals : (proposal_id, 'a proposal) big_map; + proposals : (challenge_id, proposal) big_map; + archives : (challenge_id, proposal_state) big_map; owners : address set; threshold : nat; effective_period : effective_period; @@ -59,7 +60,7 @@ end module Op = struct type proposal_content = Proposal_content.Types.t - type proposal_id = Parameter.Types.proposal_id + type challenge_id = Parameter.Types.challenge_id type agreement = Parameter.Types.agreement type proposal = Types.proposal type proposal_state = Types.proposal_state @@ -67,8 +68,7 @@ module Op = struct type proposal_state = Types.proposal_state type types = Types.t - [@inline] - let create_proposal (type a) (contents: (a proposal_content) list) : a proposal = + let create_proposal (contents: proposal_content list) : proposal = { state = Proposing; signatures = Map.empty; @@ -82,8 +82,7 @@ module Op = struct } - [@inline] - let register_proposal (type a) (proposal, storage: a proposal * a types) : a types = + let register_proposal (proposal, storage: proposal * types) : types = let proposal_counter = storage.proposal_counter + 1n in let proposals = Big_map.add (bytes proposal_counter) proposal storage.proposals in { @@ -92,22 +91,23 @@ module Op = struct proposal_counter = proposal_counter } - [@inline] - let retrieve_proposal (type a) (proposal_number, storage : proposal_id * a types) : a proposal = + let retrieve_proposal (proposal_number, storage : challenge_id * types) : proposal = match Big_map.find_opt proposal_number storage.proposals with - | None -> failwith Errors.no_proposal_exist - | Some proposal -> proposal - - - [@inline] - let update_signature (type a) (proposal, owner, agreement: a proposal * address * agreement) : a proposal = + | Some proposal -> proposal + | None -> + begin + match Big_map.find_opt proposal_number storage.archives with + | Some _ -> failwith Errors.already_resolved + | None -> failwith Errors.no_proposal_exist + end + + let update_signature (proposal, owner, agreement: proposal * address * agreement) : proposal = { proposal with signatures = Map.update owner (Some agreement) proposal.signatures; } - [@inline] - let ready_execution (type a) (proposal, approvals, threshold : a proposal * nat * nat) : a proposal = + let ready_execution (proposal, approvals, threshold : proposal * nat * nat) : proposal = let is_executed = approvals >= threshold && proposal.state = (Proposing : proposal_state) in if is_executed then @@ -122,8 +122,7 @@ module Op = struct } else proposal - [@inline] - let reject_proposal (type a) (proposal, disapprovals, threshold : a proposal * nat * nat) : a proposal = + let reject_proposal (proposal, disapprovals, threshold : proposal * nat * nat) : proposal = let is_closed = disapprovals > threshold && proposal.state = (Proposing : proposal_state) in if is_closed then @@ -138,8 +137,7 @@ module Op = struct } else proposal - [@inline] - let expire_proposal (type a) (proposal, expiration_time : a proposal * timestamp) : a proposal = + let expire_proposal (proposal, expiration_time : proposal * timestamp) : proposal = if expiration_time < Tezos.get_now () then { proposal with @@ -152,16 +150,14 @@ module Op = struct } else proposal - [@inline] - let remove_invalid_signature (type a) (owners : address set) (proposal : a proposal) : a proposal = + let remove_invalid_signature (owners : address set) (proposal : proposal) : proposal = let aux ((acc, k): ((address, bool) map * address)) = match Map.find_opt k proposal.signatures with | None -> acc | Some v -> Map.add k v acc in { proposal with signatures = Set.fold aux owners Map.empty } - [@inline] - let update_proposal_state (type a) (proposal, owners , threshold, expiration_time : a proposal * address set * nat * timestamp) : a proposal = + let update_proposal_state (proposal, owners , threshold, expiration_time : proposal * address set * nat * timestamp) : proposal = let proposal = expire_proposal (proposal, expiration_time) in if proposal.state = (Expired : proposal_state) then proposal else @@ -173,29 +169,40 @@ module Op = struct let number_of_owners = Set.cardinal owners in reject_proposal (proposal, disapprovals, abs(number_of_owners - threshold)) - [@inline] - let update_proposal (type a) (proposal_number, proposal, storage: proposal_id * a proposal * a types) : a types = - let proposals = Big_map.update proposal_number (Some proposal) storage.proposals in + let update_proposal (challenge_id, proposal, storage: challenge_id * proposal * types) : types = + let proposals = Big_map.update challenge_id (Some proposal) storage.proposals in { storage with proposals = proposals } - [@inline] - let adjust_threshold (type a) (threshold : nat) (storage : a types) : a types = + let archive_proposal (challenge_id, proposal_state, storage: challenge_id * proposal_state * types) : types = + let proposals = Big_map.remove challenge_id storage.proposals in + let archives = Big_map.add challenge_id proposal_state storage.archives in + { + storage with + proposals = proposals; + archives = archives + } + + let update_metadata (key, value, storage: string * bytes * types) : types = + let metadata = Big_map.update key (Some value) storage.metadata in + { + storage with + metadata = metadata + } + + let adjust_threshold (threshold : nat) (storage : types) : types = { storage with threshold = threshold } - [@inline] - let adjust_effective_period (type a) (effective_period: int) (storage : a types) : a types = + let adjust_effective_period (effective_period: int) (storage : types) : types = { storage with effective_period = effective_period } - [@inline] - let add_owners (type a) (owners: address set) (storage : a types) : a types = + let add_owners (owners: address set) (storage : types) : types = let add (set, s : address set * address) : address set = Set.add s set in { storage with owners = Set.fold add owners storage.owners } - [@inline] - let remove_owners (type a) (owners: address set) (storage : a types) : a types = + let remove_owners (owners: address set) (storage : types) : types = let remove (set, s : address set * address) : address set = Set.remove s set in { storage with owners = Set.fold remove owners storage.owners } end diff --git a/src/lib.mligo b/src/lib.mligo index ef0c366..8c50cc9 100644 --- a/src/lib.mligo +++ b/src/lib.mligo @@ -32,5 +32,5 @@ type request = Contract.request (* type ['a request] is an alias of [operation list * 'a storage_types] *) type result = Contract.result -let contract (type a) (request : a request) : a result = +let contract (request : request) : result = Contract.contract request diff --git a/test/common/assert.mligo b/test/common/assert.mligo index 9066626..27d0c9a 100644 --- a/test/common/assert.mligo +++ b/test/common/assert.mligo @@ -25,7 +25,7 @@ type storage_types_actor = Storage.Types.actor let mock_timestamp (timestamp : timestamp) (actor: storage_types_actor) : storage_types_actor = { actor with timestamp = timestamp } -let is_proposal_equal (type a) (msg:string) (actual : a storage_types_proposal) (expected : a storage_types_proposal) = +let is_proposal_equal (msg:string) (actual : storage_types_proposal) (expected : storage_types_proposal) = let mock_time = Tezos.get_now () in let actual = { actual with proposer = mock_timestamp mock_time actual.proposer ; diff --git a/test/common/helper.mligo b/test/common/helper.mligo index 153a7e9..b1dd312 100644 --- a/test/common/helper.mligo +++ b/test/common/helper.mligo @@ -17,20 +17,16 @@ SOFTWARE. *) #import "ligo-breathalyzer/lib/lib.mligo" "Breath" -#import "../../src/internal/contract.mligo" "Contract" +#include "../../src/internal/contract.mligo" #import "../../src/internal/proposal_content.mligo" "Proposal_content" #import "./util.mligo" "Util" type proposal_content = Proposal_content.Types.t -type storage_types = Contract.storage_types -type storage_types_proposal = Contract.storage_types_proposal -type parameter_types = Contract.parameter_types -type contract_request = Contract.request -type contract_result = Contract.result -let init_storage (type a) (owners, threshold: address set * nat) : a storage_types = +let init_storage (owners, threshold: address set * nat) : storage_types = { proposal_counter = 0n; - proposals = (Big_map.empty : (bytes, a storage_types_proposal) big_map); + proposals = (Big_map.empty : (bytes, storage_types_proposal) big_map); + archives = (Big_map.empty : (bytes, storage_types_proposal_state) big_map); owners = owners; threshold = threshold; effective_period = 172800; @@ -39,25 +35,32 @@ let init_storage (type a) (owners, threshold: address set * nat) : a storage_typ type originated = Breath.Contract.originated -let originate (type a) (level: Breath.Logger.level) (main : a contract_request -> a contract_result) (init_storage : a storage_types ) (amount : tez) = - Breath.Contract.originate level "multisig" main init_storage amount +let originate (level: Breath.Logger.level) (main : request -> result) (init_storage : storage_types ) (amount : tez) = + Breath.Contract.originate + level + "multisig" + main + init_storage + amount -let create_proposal_with_amount (type a) (amount : tez) (contract : (a parameter_types, a storage_types) originated) (proposal : (a proposal_content) list) () : Breath.Result.result = +let create_proposal_with_amount (amount : tez) (contract : (parameter_types, storage_types) originated) (proposal : (proposal_content) list) () = Breath.Contract.transfer_with_entrypoint_to contract "create_proposal" proposal amount -let sign_proposal_with_amount (type a) (amount : tez) (contract : (a parameter_types, a storage_types) originated) (proposal_id : nat) (agreement : bool) (proposal : (a proposal_content) list) () : Breath.Result.result = - let b_proposal_id = bytes proposal_id in - Breath.Contract.transfer_with_entrypoint_to contract "sign_proposal" (b_proposal_id, proposal, agreement) amount +let sign_proposal_with_amount (amount : tez) (contract : (parameter_types, storage_types) originated) (proposal_id : nat) (agreement : bool) (proposal_contents : (proposal_content) list) () = + let challenge_id = bytes proposal_id in + let payload = Bytes.pack proposal_contents in + Breath.Contract.transfer_with_entrypoint_to contract "sign_proposal" { challenge_id; payload; agreement } amount -let resolve_proposal_with_amount (type a) (amount : tez) (contract : (a parameter_types, a storage_types) originated) (proposal_id : nat) (proposal : (a proposal_content) list) () : Breath.Result.result = - let poe = { challenge_id = bytes proposal_id; payload = Bytes.pack proposal} in - Breath.Contract.transfer_with_entrypoint_to contract "proof_of_event_challenge" poe amount +let resolve_proposal_with_amount (amount : tez) (contract : (parameter_types, storage_types) originated) (proposal_id : nat) (proposal_contents: (proposal_content) list) () = + let challenge_id = bytes proposal_id in + let payload = Bytes.pack proposal_contents in + Breath.Contract.transfer_with_entrypoint_to contract "proof_of_event_challenge" {challenge_id; payload; } amount -let create_proposal (type a) (contract : (a parameter_types, a storage_types) originated) (proposal : (a proposal_content) list) () : Breath.Result.result = - create_proposal_with_amount 0tez contract proposal () +let create_proposal = + create_proposal_with_amount 0tez -let sign_proposal (type a) (contract : (a parameter_types, a storage_types) originated) (proposal_id : nat) (agreement : bool) (proposal : (a proposal_content) list) () : Breath.Result.result = - sign_proposal_with_amount 0tez contract proposal_id agreement proposal () +let sign_proposal = + sign_proposal_with_amount 0tez -let resolve_proposal (type a) (contract : (a parameter_types, a storage_types) originated) (proposal_id : nat) (proposal : (a proposal_content) list) () : Breath.Result.result = - resolve_proposal_with_amount 0tez contract proposal_id proposal () +let resolve_proposal = + resolve_proposal_with_amount 0tez diff --git a/test/common/mock_contract.mligo b/test/common/mock_contract.mligo index d7fd68d..8ec27ac 100644 --- a/test/common/mock_contract.mligo +++ b/test/common/mock_contract.mligo @@ -19,22 +19,8 @@ #import "ligo-breathalyzer/lib/lib.mligo" "Breath" #import "../../src/internal/contract.mligo" "Contract" -(* multisig wallet 1 *) -type result = Contract.result -type request = Contract.request - (* ------------------------ *) (* contract 1 *) -type add_action = nat -let add_main (n,storage : add_action * nat) : operation list * nat = - [], n + storage - - -let multisig_main (request : add_action request) : add_action result = - Contract.contract request - -(* ------------------------ *) -(* contract 2 *) let transfer_only_contract (addr, storage: address * unit) : operation list * unit = let contr = Tezos.get_contract_with_error addr "contract doesn't exist" in [Tezos.transaction () 10tez contr], storage diff --git a/test/test_adjust_threshold_proposal.mligo b/test/test_adjust_threshold_proposal.mligo index 5d65f15..5985efc 100644 --- a/test/test_adjust_threshold_proposal.mligo +++ b/test/test_adjust_threshold_proposal.mligo @@ -22,6 +22,7 @@ #import "./common/util.mligo" "Util" #import "./common/mock_contract.mligo" "Mock_contract" #import "../src/internal/proposal_content.mligo" "Proposal_content" +#import "../app/main.mligo" "App" type proposal_content = Proposal_content.Types.t @@ -33,9 +34,9 @@ let case_execute_adjust_threshold_proposal = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in + let param = ([] : proposal_content list) in (* create proposal *) let param = Adjust_threshold 2n :: param in @@ -60,9 +61,9 @@ let case_adjust_invalid_threshold_proposal = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in + let param = ([] : proposal_content list) in (* create proposal *) let param = Adjust_threshold 0n :: param in @@ -80,9 +81,9 @@ let case_fail_to_remove_all_owners_proposal = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in + let param = ([] : proposal_content list) in (* create proposal *) let param = Remove_owners owners :: param in @@ -104,20 +105,22 @@ let case_fail_to_reduce_number_of_owners_below_threshold_proposal = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in + let param = ([] : proposal_content list) in (* create proposal *) let param = Remove_owners (Set.literal [alice.address; ]) :: param in let create_action = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param) in - let sign_action = Breath.Context.act_as alice (Helper.sign_proposal multisig_contract 1n true param) in + let sign_action1 = Breath.Context.act_as alice (Helper.sign_proposal multisig_contract 1n true param) in + let sign_action2 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param) in let exe_action = Breath.Context.act_as alice (Helper.resolve_proposal multisig_contract 1n param) in Breath.Result.reduce [ create_action - ; sign_action - ; Breath.Expect.fail_with_message "No enough signature to resolve the proposal" exe_action + ; sign_action1 + ; sign_action2 + ; Breath.Expect.fail_with_message "Number of owner should be greater than threshold" exe_action ]) let case_fail_to_set_invalid_effective_proposal = @@ -128,9 +131,9 @@ let case_fail_to_set_invalid_effective_proposal = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in + let param = ([] : proposal_content list) in (* create proposal *) let param = Adjust_effective_period (-1) :: param in diff --git a/test/test_basic_proposal.mligo b/test/test_basic_proposal.mligo index 04c90f5..d71b359 100644 --- a/test/test_basic_proposal.mligo +++ b/test/test_basic_proposal.mligo @@ -22,6 +22,7 @@ #import "./common/mock_contract.mligo" "Mock_contract" #import "./common/util.mligo" "Util" #import "../src/internal/proposal_content.mligo" "Proposal_content" +#import "../app/main.mligo" "App" type proposal_content = Proposal_content.Types.t @@ -30,71 +31,77 @@ let case_create_proposal = "test create proposal" "successuful create proposal" (fun (level: Breath.Logger.level) -> - let (_, (alice, bob, _carol)) = Breath.Context.init_default () in + let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in (* create proposal 2 *) - let param2 = (Execute { target = add_contract.originated_address; parameter = 20n; amount = 10tez;} :: param) in - let action2 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param2) in + let param2 = Adjust_effective_period 100 :: param in + let action2 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param2) in (* create proposal 3 *) - let param3 = (Transfer { target = alice.address; parameter = (); amount = 10tez;} :: param) in + let param3 = Adjust_threshold 2n :: param in let action3 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param3) in (* create proposal 4 *) - let param4 = - [ Transfer { target = alice.address; parameter = (); amount = 10tez;} - ; Transfer { target = alice.address; parameter = (); amount = 10tez;} - ; Execute { target = add_contract.originated_address; parameter = 20n; amount = 10tez;} + let param4 = Add_owners (Set.literal [bob.address; carol.address]) :: param in + let action4 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param4) in + + (* create proposal 5 *) + let param5 = Remove_owners (Set.literal [bob.address; carol.address]) :: param in + let action5 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param5) in + + (* create proposal 7 *) + let param6 = + [ Transfer { target = alice.address; amount = 10tez;} + ; Transfer { target = bob.address;amount = 20tez;} + ; Adjust_threshold 2n + ; Add_owners (Set.literal [bob.address; carol.address]) + ; Remove_owners (Set.literal [bob.address; carol.address]) + ; Adjust_effective_period 100 ] in - let action4 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param4) in + let action6 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param6) in let balance = Breath.Contract.balance_of multisig_contract in let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in - let proposal2 = Util.unopt (Big_map.find_opt 0x02 storage.proposals) "proposal 2 doesn't exist" in - let proposal3 = Util.unopt (Big_map.find_opt 0x03 storage.proposals) "proposal 3 doesn't exist" in - let proposal4 = Util.unopt (Big_map.find_opt 0x04 storage.proposals) "proposal 4 doesn't exist" in + let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in + let proposal2 = Util.unopt (Big_map.find_opt 0x02 storage.proposals) "proposal 2 doesn't exist" in + let proposal3 = Util.unopt (Big_map.find_opt 0x03 storage.proposals) "proposal 3 doesn't exist" in + let proposal4 = Util.unopt (Big_map.find_opt 0x04 storage.proposals) "proposal 4 doesn't exist" in + let proposal5 = Util.unopt (Big_map.find_opt 0x05 storage.proposals) "proposal 5 doesn't exist" in + let proposal6 = Util.unopt (Big_map.find_opt 0x06 storage.proposals) "proposal 6 doesn't exist" in Breath.Result.reduce [ action1 ; action2 ; action3 ; action4 + ; action5 + ; action6 ; Breath.Assert.is_equal "balance" balance 0tez - ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 4n + ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 6n ; Assert.is_proposal_equal "#1 proposal" proposal1 ({ state = Proposing; signatures = Map.empty; proposer = { actor = alice.address; timestamp = Tezos.get_now () }; resolver = None; - contents = [ Execute { - parameter = 10n; - amount = 0tez; - target = add_contract.originated_address; - }] + contents = param1 }) ; Assert.is_proposal_equal "#2 proposal" proposal2 ({ state = Proposing; signatures = Map.empty; - proposer = { actor = bob.address; timestamp = Tezos.get_now () }; + proposer = { actor = alice.address; timestamp = Tezos.get_now () }; resolver = None; - contents = [ Execute { - target = add_contract.originated_address; - amount = 10tez; - parameter = 20n; - }] + contents = param2 }) ; Assert.is_proposal_equal "#3 proposal" proposal3 ({ @@ -102,23 +109,31 @@ let case_create_proposal = signatures = Map.empty; proposer = { actor = bob.address; timestamp = Tezos.get_now () }; resolver = None; - contents = [ Transfer { - parameter = (); - amount = 10tez; - target = alice.address; - }] + contents = param3 }) ; Assert.is_proposal_equal "#4 proposal" proposal4 + ({ + state = Proposing; + signatures = Map.empty; + proposer = { actor = alice.address; timestamp = Tezos.get_now () }; + resolver = None; + contents = param4 + }) + ; Assert.is_proposal_equal "#5 proposal" proposal5 + ({ + state = Proposing; + signatures = Map.empty; + proposer = { actor = bob.address; timestamp = Tezos.get_now () }; + resolver = None; + contents = param5 + }) + ; Assert.is_proposal_equal "#6 proposal" proposal6 ({ state = Proposing; signatures = Map.empty; proposer = { actor = bob.address; timestamp = Tezos.get_now () }; resolver = None; - contents = - [ Transfer {parameter = (); amount = 10tez; target = alice.address; } - ; Transfer {parameter = (); amount = 10tez; target = alice.address; } - ; Execute {parameter = 20n; amount = 10tez; target = add_contract.originated_address; } - ] + contents = param6 }) ]) @@ -130,10 +145,10 @@ let case_fail_to_create_empty_proposal = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in - let action : Breath.Result.result = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param) in + let action = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param) in Breath.Result.reduce [ Breath.Expect.fail_with_message "There is no content in proposal" action @@ -147,9 +162,9 @@ let case_fail_to_create_transfer_0_amount_proposal = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in - let param = (Transfer { target = alice.address; parameter = (); amount = 0tez;} :: param) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in + let param = (Transfer { target = alice.address; amount = 0tez;} :: param) in let action = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param) in @@ -165,8 +180,8 @@ let case_fail_to_create_proposal_with_empty_owner_adjustment = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in let param1 = Remove_owners (Set.literal []) :: param in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in @@ -187,23 +202,17 @@ let case_unauthorized_user_fail_to_create_proposal = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in (* create proposal 1 *) - let param1 = [Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;}] in + let param1 = [Transfer { target = alice.address; amount = 0tez;}] in let action1 = Breath.Context.act_as carol (Helper.create_proposal multisig_contract param1) in - (* create proposal 1 *) - let param2 = [Transfer { target = alice.address; parameter = (); amount = 0tez;}] in - let action2 = Breath.Context.act_as carol (Helper.create_proposal multisig_contract param2) in - let balance = Breath.Contract.balance_of multisig_contract in let storage = Breath.Contract.storage_of multisig_contract in Breath.Result.reduce [ Breath.Expect.fail_with_message "Only the contract owners can perform this operation" action1 - ; Breath.Expect.fail_with_message "Only the contract owners can perform this operation" action2 ; Breath.Assert.is_equal "balance" balance 0tez ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 0n ]) @@ -213,13 +222,13 @@ let case_fail_to_create_proposal_with_nonzero_amount = "create proposal with nonzero amount" "fail to create proposal" (fun (level: Breath.Logger.level) -> - let (_, (alice, bob, carol)) = Breath.Context.init_default () in + let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in (* create proposal 1 *) - let param1 = [Transfer { target = alice.address; parameter=(); amount = 0tez;}] in + let param1 = [Transfer { target = alice.address; amount = 0tez;}] in let action1 = Breath.Context.act_as alice (Helper.create_proposal_with_amount 1tez multisig_contract param1) in Breath.Result.reduce [ @@ -229,8 +238,8 @@ let case_fail_to_create_proposal_with_nonzero_amount = let test_suite = Breath.Model.suite "Suite for create proposal" [ case_create_proposal - ; case_unauthorized_user_fail_to_create_proposal ; case_fail_to_create_empty_proposal + ; case_unauthorized_user_fail_to_create_proposal ; case_fail_to_create_transfer_0_amount_proposal ; case_fail_to_create_proposal_with_empty_owner_adjustment ; case_fail_to_create_proposal_with_nonzero_amount diff --git a/test/test_change_owner_proposal.mligo b/test/test_change_owner_proposal.mligo index a798127..6a5a655 100644 --- a/test/test_change_owner_proposal.mligo +++ b/test/test_change_owner_proposal.mligo @@ -22,6 +22,7 @@ #import "./common/util.mligo" "Util" #import "./common/mock_contract.mligo" "Mock_contract" #import "../src/internal/proposal_content.mligo" "Proposal_content" +#import "../app/main.mligo" "App" type proposal_content = Proposal_content.Types.t @@ -33,9 +34,9 @@ let case_execute_add_owner_proposal = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in + let param = ([] : proposal_content list) in (* create proposal *) let param = Add_owners (Set.literal [bob.address; carol.address]) :: param in @@ -45,22 +46,12 @@ let case_execute_add_owner_proposal = let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in - Breath.Result.reduce [ action ; sign_action ; resolve_action ; Breath.Assert.is_equal "storage threshold" storage.owners (Set.literal [alice.address; bob.address; carol.address]) - ; Assert.is_proposal_equal "#1 proposal" proposal1 - ({ - state = Executed; - signatures = Map.literal [(alice.address, true)]; - proposer = { actor = alice.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = alice.address; timestamp = Tezos.get_now () }; - contents = [ Add_owners (Set.literal [bob.address; carol.address]) ] - }) ]) let case_execute_add_existed_owner_proposal = @@ -71,9 +62,9 @@ let case_execute_add_existed_owner_proposal = let (_, (alice, _bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in + let param = ([] : proposal_content list) in (* create proposal *) let param = Add_owners (Set.literal [alice.address;]) :: param in @@ -99,9 +90,9 @@ let case_execute_remove_owner_proposal = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in + let param = ([] : proposal_content list) in (* create proposal *) let param = Remove_owners (Set.literal [bob.address; carol.address]) :: param in @@ -127,9 +118,9 @@ let case_execute_remove_nonexisted_owner_proposal = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address;] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in + let param = ([] : proposal_content list) in (* create proposal *) let param = Remove_owners (Set.literal [bob.address; carol.address]) :: param in @@ -155,12 +146,12 @@ let case_resolve_transfer_proposal_after_owner_changed = let (_, (alice, bob, _)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in + let multisig_contract = Helper.originate level App.main init_storage 100tez in - let param = ([] : (nat proposal_content) list) in + let param = ([] : proposal_content list) in (* 1. create transfer proposal *) - let param1 = Transfer { target = alice.address; parameter = (); amount = 10tez;} :: param in + let param1 = Transfer { target = alice.address; amount = 10tez;} :: param in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as alice (Helper.sign_proposal multisig_contract 1n true param1) in @@ -178,10 +169,6 @@ let case_resolve_transfer_proposal_after_owner_changed = let sign_action4 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let resolve_action4 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in - let storage = Breath.Contract.storage_of multisig_contract in - - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in - Breath.Result.reduce [ action1 ; sign_action1 @@ -192,7 +179,6 @@ let case_resolve_transfer_proposal_after_owner_changed = ; Breath.Expect.fail_with_message "No enough signature to resolve the proposal" resolve_action3_2 ; sign_action4 ; resolve_action4 - ; Breath.Assert.is_equal "signature" proposal1.signatures (Map.literal [(bob.address, true)]) ]) let test_suite = diff --git a/test/test_disapproval.mligo b/test/test_disapproval.mligo index 0201dfc..b54e212 100644 --- a/test/test_disapproval.mligo +++ b/test/test_disapproval.mligo @@ -22,6 +22,7 @@ #import "./common/mock_contract.mligo" "Mock_contract" #import "./common/util.mligo" "Util" #import "../src/internal/proposal_content.mligo" "Proposal_content" +#import "../app/main.mligo" "App" type proposal_content = Proposal_content.Types.t @@ -33,11 +34,10 @@ let case_sign_for_disapproval = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n false param1) in @@ -57,10 +57,9 @@ let case_sign_for_disapproval = signatures = Map.literal [(bob.address, false)]; proposer = { actor = alice.address; timestamp = Tezos.get_now () }; resolver = None; - contents = [ Execute { - amount = 0tez; - target = add_contract.originated_address; - parameter = 10n; + contents = [ Transfer { + amount = 10tez; + target = alice.address; }] }) ]) @@ -73,11 +72,10 @@ let case_fail_double_sign = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let sign_action2 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n false param1) in @@ -96,11 +94,10 @@ let case_close_proposal_1_1 = let (_, (_alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [bob.address;] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 10tez;} :: param) in + let param1 = (Transfer { target = bob.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n false param1) in let resolve_action1 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in @@ -108,29 +105,15 @@ let case_close_proposal_1_1 = let balance = Breath.Contract.balance_of multisig_contract in let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in - - let add_contract_balance = Breath.Contract.balance_of add_contract in + let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.archives) "proposal 1 doesn't exist" in Breath.Result.reduce [ create_action1 ; sign_action1 ; resolve_action1 ; Breath.Assert.is_equal "balance" balance 100tez - ; Breath.Assert.is_equal "balance of add contract" add_contract_balance 0tez ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 1n - ; Assert.is_proposal_equal "#1 proposal" proposal1 - ({ - state = Rejected; - signatures = Map.literal [(bob.address, false)]; - proposer = { actor = bob.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = bob.address; timestamp = Tezos.get_now () }; - contents = [ Execute { - amount = 10tez; - target = add_contract.originated_address; - parameter = 10n; - }] - }) + ; Breath.Assert.is_equal "#1 proposal" proposal1 Rejected ]) let case_close_proposal_2_2 = @@ -141,11 +124,10 @@ let case_close_proposal_2_2 = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 10tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as alice (Helper.sign_proposal multisig_contract 1n false param1) in let resolve_action1 = Breath.Context.act_as alice (Helper.resolve_proposal multisig_contract 1n param1) in @@ -153,29 +135,15 @@ let case_close_proposal_2_2 = let balance = Breath.Contract.balance_of multisig_contract in let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in - - let add_contract_balance = Breath.Contract.balance_of add_contract in + let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.archives) "proposal 1 doesn't exist" in Breath.Result.reduce [ create_action1 ; sign_action1 ; resolve_action1 - ; Breath.Assert.is_equal "balance" balance 100tez - ; Breath.Assert.is_equal "balance of add contract" add_contract_balance 0tez + ; Breath.Assert.is_equal "balance of add contract" balance 100tez ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 1n - ; Assert.is_proposal_equal "#1 proposal" proposal1 - ({ - state = Rejected; - signatures = Map.literal [(alice.address, false)]; - proposer = { actor = bob.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = alice.address; timestamp = Tezos.get_now () }; - contents = [ Execute { - amount = 10tez; - target = add_contract.originated_address; - parameter = 10n; - }] - }) + ; Breath.Assert.is_equal "#1 proposal" proposal1 Rejected ]) let case_close_proposal_2_3 = @@ -186,11 +154,10 @@ let case_close_proposal_2_3 = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 10tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as alice (Helper.sign_proposal multisig_contract 1n false param1) in let sign_action2 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n false param1) in @@ -199,9 +166,7 @@ let case_close_proposal_2_3 = let balance = Breath.Contract.balance_of multisig_contract in let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in - - let add_contract_balance = Breath.Contract.balance_of add_contract in + let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.archives) "proposal 1 doesn't exist" in Breath.Result.reduce [ create_action1 @@ -209,20 +174,8 @@ let case_close_proposal_2_3 = ; sign_action2 ; resolve_action1 ; Breath.Assert.is_equal "balance" balance 100tez - ; Breath.Assert.is_equal "balance of add contract" add_contract_balance 0tez ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 1n - ; Assert.is_proposal_equal "#1 proposal" proposal1 - ({ - state = Rejected; - signatures = Map.literal [(bob.address, false); (alice.address, false)]; - proposer = { actor = bob.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = bob.address; timestamp = Tezos.get_now () }; - contents = [ Execute { - amount = 10tez; - target = add_contract.originated_address; - parameter = 10n; - }] - }) + ; Breath.Assert.is_equal "#1 proposal" proposal1 Rejected ]) let case_not_closed_1_2 = @@ -233,11 +186,10 @@ let case_not_closed_1_2 = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 10tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as alice (Helper.sign_proposal multisig_contract 1n false param1) in let resolve_action1 = Breath.Context.act_as alice (Helper.resolve_proposal multisig_contract 1n param1) in @@ -247,14 +199,11 @@ let case_not_closed_1_2 = let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in - let add_contract_balance = Breath.Contract.balance_of add_contract in - Breath.Result.reduce [ create_action1 ; sign_action1 ; Breath.Expect.fail_with_message "No enough signature to resolve the proposal" resolve_action1 ; Breath.Assert.is_equal "balance" balance 100tez - ; Breath.Assert.is_equal "balance of add contract" add_contract_balance 0tez ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 1n ; Assert.is_proposal_equal "#1 proposal" proposal1 ({ @@ -262,10 +211,9 @@ let case_not_closed_1_2 = signatures = Map.literal [(alice.address, false)]; proposer = { actor = bob.address; timestamp = Tezos.get_now () }; resolver = None; - contents = [ Execute { + contents = [ Transfer { amount = 10tez; - target = add_contract.originated_address; - parameter = 10n; + target = alice.address; }] }) ]) diff --git a/test/test_emit_events.mligo b/test/test_emit_events.mligo index 93fa9aa..230d155 100644 --- a/test/test_emit_events.mligo +++ b/test/test_emit_events.mligo @@ -17,16 +17,19 @@ SOFTWARE. *) #import "ligo-breathalyzer/lib/lib.mligo" "Breath" +#import "./common/mock_contract.mligo" "Mock_contract" #import "./common/helper.mligo" "Helper" #import "./common/assert.mligo" "Assert" -#import "./common/mock_contract.mligo" "Mock_contract" #import "./common/util.mligo" "Util" #import "../src/internal/proposal_content.mligo" "Proposal_content" #import "../src/internal/storage.mligo" "Storage" +#import "../src/internal/event.mligo" "Event" +#import "../app/main.mligo" "App" type proposal_content = Proposal_content.Types.t type storage_types_proposal = Storage.Types.proposal -type storage_types_proposal_id = Storage.Types.proposal_id +type storage_types_challenge_id = Storage.Types.challenge_id +type storage_types_proposal_state = Storage.Types.proposal_state let case_emitted_create_proposal = Breath.Model.case @@ -36,25 +39,21 @@ let case_emitted_create_proposal = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let multisig_address = multisig_contract.originated_address in - let events = (Util.get_last_events_from multisig_address "create_proposal" : (storage_types_proposal_id * nat storage_types_proposal) list) in + let events = (Util.get_last_events_from multisig_address "create_proposal" : Event.Types.create_proposal list) in - let (emitted_id, emitted_proposal) = Option.unopt (List.head_opt events) in - - let storage = Breath.Contract.storage_of multisig_contract in - let proposal = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in + let { challenge_id = emitted_id; payload = emitted_proposal_content} = Option.unopt (List.head_opt events) in Breath.Result.reduce [ action1 - ; Breath.Assert.is_equal "proposal id" emitted_id 0x01 - ; Breath.Assert.is_equal "proposal" emitted_proposal proposal + ; Breath.Assert.is_equal "challenge id" emitted_id 0x01 + ; Breath.Assert.is_equal "proposal payload" emitted_proposal_content (Bytes.pack param1) ]) let case_emitted_sign_proposal = @@ -65,23 +64,22 @@ let case_emitted_sign_proposal = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = bob.address; amount = 20tez;} :: param) in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let multisig_address = multisig_contract.originated_address in - let events = (Util.get_last_events_from multisig_address "sign_proposal" : (storage_types_proposal_id * address * bool) list) in + let events = (Util.get_last_events_from multisig_address "sign_proposal" : Event.Types.sign_proposal list) in - let (emitted_proposal_id, emitted_addr, emitted_agreement) = Option.unopt (List.head_opt events) in + let {challenge_id = emitted_challenge_id; signer = emitted_addr; agreement = emitted_agreement} = Option.unopt (List.head_opt events) in Breath.Result.reduce [ action1 ; sign_action1 - ; Breath.Assert.is_equal "proposal id" emitted_proposal_id 0x01 + ; Breath.Assert.is_equal "challenge_id id" emitted_challenge_id 0x01 ; Breath.Assert.is_equal "owner" emitted_addr bob.address ; Breath.Assert.is_equal "agreement" emitted_agreement true ]) @@ -94,30 +92,39 @@ let case_emitted_exe_proposal = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 10tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = bob.address; amount = 1tez;} :: param) in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in + let exe_action1 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in let multisig_address = multisig_contract.originated_address in - let events = (Util.get_last_events_from multisig_address "resolve_proposal" : (storage_types_proposal_id * address) list) in - let poe_events = (Util.get_last_events_from multisig_address "proof_of_event" : (bytes * bytes) list) in - let (emitted_proposal_id, emitted_addr) = Option.unopt (List.head_opt events) in - let (emitted_chellenge_id, emitted_payload) = Option.unopt (List.head_opt poe_events) in + let events = (Util.get_last_events_from multisig_address "resolve_proposal" : Event.Types.resolve_proposal list) in + let {challenge_id = emitted_challenge_id1; proposal_state = emitted_state} = Option.unopt (List.head_opt events) in + + let proof = (Util.get_last_events_from multisig_address "proof_of_event" : Event.Types.proof_of_event list) in + let {challenge_id = emitted_challenge_id2; payload = emitted_payload} = Option.unopt (List.head_opt proof) in + + let unpack_payload_opt = (Bytes.unpack emitted_payload : storage_types_proposal option ) in + let unpack_payload = Option.unopt unpack_payload_opt in Breath.Result.reduce [ action1 ; sign_action1 ; exe_action1 - ; Breath.Assert.is_equal "proposal id" emitted_proposal_id 0x01 - ; Breath.Assert.is_equal "owner" emitted_addr bob.address - ; Breath.Assert.is_equal "proposal id" emitted_chellenge_id 0x01 - ; Breath.Assert.is_equal "owner" emitted_payload (Bytes.pack param1) + ; Breath.Assert.is_equal "challenge id" emitted_challenge_id1 0x01 + ; Breath.Assert.is_equal "state" emitted_state Executed + ; Breath.Assert.is_equal "challenge id" emitted_challenge_id2 0x01 + ; Assert.is_proposal_equal "payload" unpack_payload + { contents = param1 + ; proposer = { actor = alice.address; timestamp = Tezos.get_now () } + ; resolver = (Some {actor = bob.address; timestamp = Tezos.get_now ()}) + ; signatures = Map.literal [ (bob.address, true) ] + ; state = Executed} ]) let case_emitted_receiving_amount = @@ -128,14 +135,14 @@ let case_emitted_receiving_amount = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in let contract = Mock_contract.originate_transfer_only_contract level in let action = Breath.Context.act_as carol (fun (_u:unit) -> (Breath.Contract.transfer_to contract multisig_contract.originated_address 0tez)) in - let events = (Util.get_last_events_from multisig_contract.originated_address "receiving_tez" : (address * tez) list) in + let events = (Util.get_last_events_from multisig_contract.originated_address "receiving_tez" : Event.Types.receiving_tez list) in - let (emitted_sender, emitted_amount) = Option.unopt (List.head_opt events) in + let {from = emitted_sender; amount = emitted_amount} = Option.unopt (List.head_opt events) in Breath.Result.reduce [ action diff --git a/test/test_expiration_time.mligo b/test/test_expiration_time.mligo index 515d077..44fafdc 100644 --- a/test/test_expiration_time.mligo +++ b/test/test_expiration_time.mligo @@ -22,6 +22,7 @@ #import "./common/mock_contract.mligo" "Mock_contract" #import "./common/util.mligo" "Util" #import "../src/internal/proposal_content.mligo" "Proposal_content" +#import "../app/main.mligo" "App" type proposal_content = Proposal_content.Types.t @@ -34,12 +35,11 @@ let case_sign_proposal_passing_expiration_time = let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in let init_storage = { init_storage with effective_period = 1_800 } in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let _ = Test.bake_until_n_cycle_end 100n in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in @@ -58,36 +58,24 @@ let case_resolve_proposal_passing_expiration_time = let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in let init_storage = { init_storage with effective_period = 1_800 } in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let _ = Test.bake_until_n_cycle_end 100n in let exe_action1 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in + let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.archives) "proposal 1 doesn't exist" in Breath.Result.reduce [ create_action1 ; sign_action1 ; exe_action1 - ; Assert.is_proposal_equal "#1 proposal" proposal1 - ({ - state = Expired; - signatures = Map.literal [(bob.address, true)]; - proposer = { actor = alice.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = bob.address; timestamp = Tezos.get_now () }; - contents = [ Execute { - amount = 0tez; - target = add_contract.originated_address; - parameter = 10n; - }] - }) + ; Breath.Assert.is_equal "#1 proposal" proposal1 Expired ]) let case_resolve_executed_proposal_passing_expiration_time = @@ -99,12 +87,11 @@ let case_resolve_executed_proposal_passing_expiration_time = let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in let init_storage = { init_storage with effective_period = 1_800 } in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let exe_action1 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in @@ -112,25 +99,14 @@ let case_resolve_executed_proposal_passing_expiration_time = let exe_action2 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in + let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.archives) "proposal 1 doesn't exist" in Breath.Result.reduce [ create_action1 ; sign_action1 ; exe_action1 ; Breath.Expect.fail_with_message "This proposal has been resolved" exe_action2 - ; Assert.is_proposal_equal "#1 proposal" proposal1 - ({ - state = Executed; - signatures = Map.literal [(bob.address, true)]; - proposer = { actor = alice.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = bob.address; timestamp = Tezos.get_now () }; - contents = [ Execute { - amount = 0tez; - target = add_contract.originated_address; - parameter = 10n; - }] - }) + ; Breath.Assert.is_equal "#1 proposal" proposal1 Executed ]) let case_resolve_rejected_proposal_passing_expiration_time= @@ -142,12 +118,11 @@ let case_resolve_rejected_proposal_passing_expiration_time= let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 3n) in let init_storage = { init_storage with effective_period = 1_800 } in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n false param1) in let exe_action1 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in @@ -155,25 +130,14 @@ let case_resolve_rejected_proposal_passing_expiration_time= let exe_action2 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in + let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.archives) "proposal 1 doesn't exist" in Breath.Result.reduce [ create_action1 ; sign_action1 ; exe_action1 ; Breath.Expect.fail_with_message "This proposal has been resolved" exe_action2 - ; Assert.is_proposal_equal "#1 proposal" proposal1 - ({ - state = Rejected; - signatures = Map.literal [(bob.address, false)]; - proposer = { actor = alice.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = bob.address; timestamp = Tezos.get_now () }; - contents = [ Execute { - amount = 0tez; - target = add_contract.originated_address; - parameter = 10n; - }] - }) + ; Breath.Assert.is_equal "#1 proposal" proposal1 Rejected ]) let case_adjust_effective_time = @@ -185,8 +149,8 @@ let case_adjust_effective_time = let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in let init_storage = { init_storage with effective_period = 1_800 } in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) let param1 = (Adjust_effective_period 200) :: param in @@ -212,8 +176,8 @@ let case_adjust_effective_time_with_invalid_value = let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in let init_storage = { init_storage with effective_period = 1_800 } in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) let param1 = (Adjust_effective_period 0) :: param in diff --git a/test/test_lambda_proposal.mligo b/test/test_lambda_proposal.mligo index aeb5d97..ed8fb85 100644 --- a/test/test_lambda_proposal.mligo +++ b/test/test_lambda_proposal.mligo @@ -19,13 +19,17 @@ #import "ligo-breathalyzer/lib/lib.mligo" "Breath" #import "./common/helper.mligo" "Helper" #import "./common/assert.mligo" "Assert" -#import "./common/mock_contract.mligo" "Mock_contract" #import "./common/util.mligo" "Util" #import "../src/internal/proposal_content.mligo" "Proposal_content" #import "../src/internal/storage.mligo" "Storage" +#import "../app/main.mligo" "App" type proposal_content = Proposal_content.Types.t +(* contract *) +let add_main (n,storage : nat * nat) : operation list * nat = + [], n + storage + let case_execute_lambda_proposal = Breath.Model.case "test create lambda proposal and execute" @@ -34,44 +38,31 @@ let case_execute_lambda_proposal = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let add_contract = Breath.Contract.originate level "add_contr" add_main 1n 0tez in let add_contract_address = add_contract.originated_address in - let param = ([] : (nat proposal_content) list) in + let param = ([] : proposal_content list) in (* lambda *) - let call_add_contract (_ : unit) : operation = + let call_add_contract (_ : unit) : operation list = let add_contr = Tezos.get_contract_with_error add_contract_address "add contract doesn't exist" in - Tezos.transaction 10n 0tez add_contr + [ Tezos.transaction 10n 0tez add_contr ] in (* create proposal *) - let param = Execute_lambda { metadata = None; lambda = Some call_add_contract } :: param in + let param = Execute_lambda { metadata = None; lambda = call_add_contract } :: param in let action = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param) in let sign_action = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param) in let resolve_action = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param) in let add_contract_storage = Breath.Contract.storage_of add_contract in - let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in Breath.Result.reduce [ action ; sign_action ; resolve_action ; Breath.Assert.is_equal "storage of add contract" add_contract_storage 11n - ; Assert.is_proposal_equal "#1 proposal" proposal1 - ({ - state = Executed; - signatures = Map.literal [(bob.address, true)]; - proposer = { actor = alice.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = bob.address; timestamp = Tezos.get_now () }; - contents = [ Execute_lambda { - metadata = None; - lambda = None; - }] - }) ]) let test_suite = diff --git a/test/test_receiving_tez.mligo b/test/test_receiving_tez.mligo index 4d641ec..360efa9 100644 --- a/test/test_receiving_tez.mligo +++ b/test/test_receiving_tez.mligo @@ -1,7 +1,7 @@ #import "ligo-breathalyzer/lib/lib.mligo" "Breath" #import "./common/helper.mligo" "Helper" #import "./common/mock_contract.mligo" "Mock" -#import "../app/main_unit.mligo" "App" +#import "../app/main.mligo" "App" let case_receive_tez = diff --git a/test/test_resolve_proposal_entrypoint.mligo b/test/test_resolve_proposal_entrypoint.mligo index d382a16..3f755eb 100644 --- a/test/test_resolve_proposal_entrypoint.mligo +++ b/test/test_resolve_proposal_entrypoint.mligo @@ -22,6 +22,7 @@ #import "./common/mock_contract.mligo" "Mock_contract" #import "./common/util.mligo" "Util" #import "../src/internal/proposal_content.mligo" "Proposal_content" +#import "../app/main.mligo" "App" type proposal_content = Proposal_content.Types.t @@ -33,61 +34,79 @@ let case_resolve_proposal = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = bob.address; amount = 20tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let exe_action1 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in - (* create proposal 2 *) - let param2 = (Transfer { target = bob.address; parameter = (); amount = 20tez;} :: param) in - let create_action2 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param2) in - let sign_action2 = Breath.Context.act_as carol (Helper.sign_proposal multisig_contract 2n true param2) in - let exe_action2 = Breath.Context.act_as alice (Helper.resolve_proposal multisig_contract 2n param2) in - let balance = Breath.Contract.balance_of multisig_contract in let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in - let proposal2 = Util.unopt (Big_map.find_opt 0x02 storage.proposals) "proposal 2 doesn't exist" in + let archive = Util.unopt (Big_map.find_opt 0x01 storage.archives) "proposal 1 doesn't exist" in + let removed_proposal = Big_map.find_opt 0x01 storage.proposals in Breath.Result.reduce [ create_action1 ; sign_action1 ; exe_action1 - ; create_action2 - ; sign_action2 - ; exe_action2 ; Breath.Assert.is_equal "balance" balance 80tez - ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 2n - ; Assert.is_proposal_equal "#1 proposal" proposal1 - ({ - state = Executed; - signatures = Map.literal [(bob.address, true)]; - proposer = { actor = alice.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = bob.address; timestamp = Tezos.get_now () }; - contents = [ Execute { - amount = 0tez; - target = add_contract.originated_address; - parameter = 10n; - }] - }) - ; Assert.is_proposal_equal "#2 proposal" proposal2 - ({ - state = Executed; - signatures = Map.literal [(carol.address, true)]; - proposer = { actor = bob.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = alice.address; timestamp = Tezos.get_now () }; - contents = [ Transfer { - parameter = (); - target = bob.address; - amount = 20tez; - }] - }) + ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 1n + ; Breath.Assert.is_equal "proposal should be removed" removed_proposal None + ; Breath.Assert.is_equal "#1 proposal" archive Executed; + ]) + +let case_order_of_transactions = + Breath.Model.case + "test order of transactions" + "execute in right order" + (fun (level: Breath.Logger.level) -> + let (_, (alice, bob, carol)) = Breath.Context.init_default () in + let owners : address set = Set.literal [alice.address; bob.address; carol.address] in + let init_storage = Helper.init_storage (owners, 1n) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + + let lambda1 ((): unit) : operation list = + [ Tezos.emit "%order" 1 + ; Tezos.emit "%order" 2 + ] + in + + let lambda2 ((): unit) : operation list = + [ Tezos.emit "%order" 3 + ; Tezos.emit "%order" 4 + ] + in + + (* create proposal 1 *) + let param1 = + [ Execute_lambda { metadata = None; lambda = lambda1 } + ; Execute_lambda { metadata = None; lambda = lambda2 } + ] in + let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in + let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in + let exe_action1 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in + + let events = (Util.get_last_events_from multisig_contract.originated_address "order" : int list) in + + let balance = Breath.Contract.balance_of multisig_contract in + let storage = Breath.Contract.storage_of multisig_contract in + + let archive = Util.unopt (Big_map.find_opt 0x01 storage.archives) "proposal 1 doesn't exist" in + let removed_proposal = Big_map.find_opt 0x01 storage.proposals in + + Breath.Result.reduce [ + create_action1 + ; sign_action1 + ; exe_action1 + ; Breath.Assert.is_equal "balance" balance 100tez + ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 1n + ; Breath.Assert.is_equal "proposal should be removed" removed_proposal None + ; Breath.Assert.is_equal "#1 proposal" archive Executed + ; Breath.Assert.is_equal "ordering" events [1; 2; 3; 4] ]) let case_fail_to_resolve_proposal_with_nonzero_amount = @@ -98,11 +117,11 @@ let case_fail_to_resolve_proposal_with_nonzero_amount = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Transfer { target = alice.address; parameter = (); amount = 10tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let exe_action1 = Breath.Context.act_as bob (Helper.resolve_proposal_with_amount 1tez multisig_contract 1n param1) in @@ -123,12 +142,11 @@ let case_fail_to_resolve_proposal_twice = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let exe_action1 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in @@ -149,11 +167,10 @@ let case_not_owner = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let exe_action1 = Breath.Context.act_as carol (Helper.resolve_proposal multisig_contract 1n param1) in @@ -172,11 +189,10 @@ let case_no_enough_signature = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let exe_action1 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in @@ -195,12 +211,11 @@ let case_wrong_content_bytes = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 100tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 100tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let exe_action1 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param) in @@ -219,18 +234,17 @@ let case_execute_transaction_1_of_1 = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 40tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 40tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let resolve_action1 = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param1) in (* create proposal 2 *) - let param2 = (Transfer { target = bob.address; parameter = (); amount = 20tez;} :: param) in + let param2 = (Transfer { target = bob.address; amount = 20tez;} :: param) in let create_action2 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param2) in let sign_action2 = Breath.Context.act_as carol (Helper.sign_proposal multisig_contract 2n true param2) in let resolve_action2 = Breath.Context.act_as carol (Helper.resolve_proposal multisig_contract 2n param2) in @@ -238,8 +252,8 @@ let case_execute_transaction_1_of_1 = let balance = Breath.Contract.balance_of multisig_contract in let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in - let proposal2 = Util.unopt (Big_map.find_opt 0x02 storage.proposals) "proposal 2 doesn't exist" in + let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.archives) "proposal 1 doesn't exist" in + let proposal2 = Util.unopt (Big_map.find_opt 0x02 storage.archives) "proposal 2 doesn't exist" in Breath.Result.reduce [ create_action1 @@ -248,32 +262,10 @@ let case_execute_transaction_1_of_1 = ; create_action2 ; sign_action2 ; resolve_action2 - ; Breath.Assert.is_equal "balance" balance 20tez + ; Breath.Assert.is_equal "balance" balance 10tez ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 2n - ; Assert.is_proposal_equal "#1 proposal" proposal1 - ({ - state = Executed; - signatures = Map.literal [(bob.address, true)]; - proposer = { actor = alice.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = bob.address; timestamp = Tezos.get_now () }; - contents = [ Execute { - target = add_contract.originated_address; - amount = 0tez; - parameter = 10n; - }] - }) - ; Assert.is_proposal_equal "#2 proposal" proposal2 - ({ - state = Executed; - signatures = Map.literal [(carol.address, true)]; - proposer = { actor = bob.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = carol.address; timestamp = Tezos.get_now () }; - contents = [ Transfer { - target = bob.address; - parameter = (); - amount = 20tez; - }] - }) + ; Breath.Assert.is_equal "#1 proposal" proposal1 Executed + ; Breath.Assert.is_equal "#2 proposal" proposal2 Executed ]) let case_execute_transaction_1_of_1_batch = @@ -284,13 +276,12 @@ let case_execute_transaction_1_of_1_batch = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 40tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in + let multisig_contract = Helper.originate level App.main init_storage 40tez in (* create proposal 1 *) let param1 = - [ Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} - ; Transfer { target = bob.address; parameter = (); amount = 20tez;} + [ Transfer { target = bob.address; amount = 20tez;} + ; Transfer { target = bob.address; amount = 20tez;} ] in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in @@ -299,31 +290,15 @@ let case_execute_transaction_1_of_1_batch = let balance = Breath.Contract.balance_of multisig_contract in let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in + let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.archives) "proposal 1 doesn't exist" in Breath.Result.reduce [ create_action1 ; sign_action1 ; resolve_action1 - ; Breath.Assert.is_equal "balance" balance 20tez + ; Breath.Assert.is_equal "balance" balance 0tez ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 1n - ; Assert.is_proposal_equal "#1 proposal" proposal1 - ({ - state = Executed; - signatures = Map.literal [(bob.address, true)]; - proposer = { actor = alice.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = bob.address; timestamp = Tezos.get_now () }; - contents = - [ Execute { - target = add_contract.originated_address; - amount = 0tez; - parameter = 10n; } - ; Transfer { - target = bob.address; - parameter = (); - amount = 20tez; } - ] - }) + ; Breath.Assert.is_equal "#1 proposal" proposal1 Executed; ]) let case_execute_transaction_3_of_3 = @@ -334,12 +309,11 @@ let case_execute_transaction_3_of_3 = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 3n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 40tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 40tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = bob.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1_1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let sign_action1_2 = Breath.Context.act_as carol (Helper.sign_proposal multisig_contract 1n true param1) in @@ -347,7 +321,7 @@ let case_execute_transaction_3_of_3 = let resolve_action1 = Breath.Context.act_as alice (Helper.resolve_proposal multisig_contract 1n param1) in (* create proposal 2 *) - let param2 = (Transfer { target = bob.address; parameter = (); amount = 20tez;} :: param) in + let param2 = (Transfer { target = bob.address; amount = 20tez;} :: param) in let create_action2 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param2) in let sign_action2_1 = Breath.Context.act_as carol (Helper.sign_proposal multisig_contract 2n true param2) in let sign_action2_2 = Breath.Context.act_as alice (Helper.sign_proposal multisig_contract 2n true param2) in @@ -357,8 +331,8 @@ let case_execute_transaction_3_of_3 = let balance = Breath.Contract.balance_of multisig_contract in let storage = Breath.Contract.storage_of multisig_contract in - let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.proposals) "proposal 1 doesn't exist" in - let proposal2 = Util.unopt (Big_map.find_opt 0x02 storage.proposals) "proposal 2 doesn't exist" in + let proposal1 = Util.unopt (Big_map.find_opt 0x01 storage.archives) "proposal 1 doesn't exist" in + let proposal2 = Util.unopt (Big_map.find_opt 0x02 storage.archives) "proposal 2 doesn't exist" in Breath.Result.reduce [ create_action1 @@ -371,32 +345,10 @@ let case_execute_transaction_3_of_3 = ; sign_action2_2 ; sign_action2_3 ; resolve_action2 - ; Breath.Assert.is_equal "balance" balance 20tez + ; Breath.Assert.is_equal "balance" balance 10tez ; Breath.Assert.is_equal "the counter of proposal" storage.proposal_counter 2n - ; Assert.is_proposal_equal "#1 proposal" proposal1 - ({ - state = Executed; - signatures = Map.literal [(alice.address, true); (bob.address, true); (carol.address, true)]; - proposer = { actor = alice.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = alice.address; timestamp = Tezos.get_now () }; - contents = [ Execute { - target = add_contract.originated_address; - parameter = 10n; - amount = 0tez; - }] - }) - ; Assert.is_proposal_equal "#2 proposal" proposal2 - ({ - state = Executed; - signatures = Map.literal [(alice.address, true); (bob.address, true); (carol.address, true)]; - proposer = { actor = bob.address; timestamp = Tezos.get_now () }; - resolver = Some { actor = bob.address; timestamp = Tezos.get_now () }; - contents = [ Transfer { - target = bob.address; - parameter = (); - amount = 20tez; - }] - }) + ; Breath.Assert.is_equal "#1 proposal" proposal1 Executed + ; Breath.Assert.is_equal "#2 proposal" proposal2 Executed ]) let test_suite = @@ -410,4 +362,5 @@ let test_suite = ; case_execute_transaction_1_of_1 ; case_execute_transaction_1_of_1_batch ; case_execute_transaction_3_of_3 + ; case_order_of_transactions ] diff --git a/test/test_setting.mligo b/test/test_setting.mligo index 9fa9da9..a305624 100644 --- a/test/test_setting.mligo +++ b/test/test_setting.mligo @@ -20,6 +20,7 @@ #import "./common/helper.mligo" "Helper" #import "./common/mock_contract.mligo" "Mock_contract" #import "../src/internal/proposal_content.mligo" "Proposal_content" +#import "../app/main.mligo" "App" type proposal_content = Proposal_content.Types.t @@ -31,11 +32,10 @@ let case_invalidated_threshold = let (_, (alice, _bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address] in let init_storage = Helper.init_storage (owners, 0n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in Breath.Result.reduce [ @@ -50,11 +50,10 @@ let case_number_of_owner_less_than_threshold = let (_, (alice, _bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in Breath.Result.reduce [ diff --git a/test/test_sign_only_entrypoint.mligo b/test/test_sign_only_entrypoint.mligo index e45e9ce..cdaf1ca 100644 --- a/test/test_sign_only_entrypoint.mligo +++ b/test/test_sign_only_entrypoint.mligo @@ -22,6 +22,7 @@ #import "./common/mock_contract.mligo" "Mock_contract" #import "./common/util.mligo" "Util" #import "../src/internal/proposal_content.mligo" "Proposal_content" +#import "../app/main.mligo" "App" type proposal_content = Proposal_content.Types.t @@ -33,18 +34,17 @@ let case_gathering_signatures = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 10tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 10tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1_1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let sign_action1_2 = Breath.Context.act_as carol (Helper.sign_proposal multisig_contract 1n true param1) in (* create proposal 2 *) - let param2 = (Transfer { target = bob.address; parameter = (); amount = 20tez;} :: param) in + let param2 = (Transfer { target = bob.address; amount = 20tez;} :: param) in let create_action2 = Breath.Context.act_as bob (Helper.create_proposal multisig_contract param2) in let sign_action2_1 = Breath.Context.act_as carol (Helper.sign_proposal multisig_contract 2n true param2) in let sign_action2_2 = Breath.Context.act_as alice (Helper.sign_proposal multisig_contract 2n true param2) in @@ -70,10 +70,9 @@ let case_gathering_signatures = signatures = Map.literal [(bob.address, true); (carol.address, true)]; proposer = { actor = alice.address; timestamp = Tezos.get_now () }; resolver = None; - contents = [ Execute { - amount = 0tez; - target = add_contract.originated_address; - parameter = 10n; + contents = [ Transfer { + amount = 10tez; + target = alice.address; }] }) ; Assert.is_proposal_equal "#2 proposal" proposal2 @@ -83,7 +82,6 @@ let case_gathering_signatures = proposer = { actor = bob.address; timestamp = Tezos.get_now () }; resolver = None; contents = [ Transfer { - parameter = (); target = bob.address; amount = 20tez; }] @@ -98,10 +96,10 @@ let case_fail_to_sign_proposal_with_nonzero_amount = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in - let param1 = (Transfer { target = alice.address; parameter=(); amount = 10tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal_with_amount 1tez multisig_contract 1n true param1) in @@ -118,11 +116,10 @@ let case_fail_double_sign = let (_, (alice, bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in let sign_action2 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param1) in @@ -141,11 +138,10 @@ let case_unauthorized_user_fail_to_sign = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as carol (Helper.sign_proposal multisig_contract 1n true param1) in @@ -162,11 +158,10 @@ let case_sign_nonexisted_proposal = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address;] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in let sign_action1 = Breath.Context.act_as carol (Helper.sign_proposal multisig_contract 2n true param1) in @@ -183,39 +178,38 @@ let case_no_owner = let (_, (alice, _bob, _carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [] in let init_storage = Helper.init_storage (owners, 2n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 0tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 0tez in + let param = ([] : proposal_content list) in - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in Breath.Result.reduce [ Breath.Expect.fail_with_message "Only the contract owners can perform this operation" action1 ]) -let case_fail_to_sign_after_executed_flag_set = +let case_fail_to_sign_after_proposal_is_resolved = Breath.Model.case - "test fail to sign after executed of proposal is set" + "test fail to sign after proposal is resolved" "fail to sign" (fun (level: Breath.Logger.level) -> let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 10tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 10tez in + let param = ([] : proposal_content list) in - let param = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param) in - let sign_exe_action = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param) in - let sign_exe_action = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param) in - let sign_action = Breath.Context.act_as carol (Helper.sign_proposal multisig_contract 1n true param) in + let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param) in + let exe_action = Breath.Context.act_as bob (Helper.resolve_proposal multisig_contract 1n param) in + let sign_action2 = Breath.Context.act_as carol (Helper.sign_proposal multisig_contract 1n true param) in Breath.Result.reduce [ create_action - ; sign_exe_action - ; Breath.Expect.fail_with_message "This proposal has been resolved" sign_action + ; sign_action1 + ; exe_action + ; Breath.Expect.fail_with_message "This proposal has been resolved" sign_action2 ]) let case_wrong_content_bytes = @@ -226,14 +220,15 @@ let case_wrong_content_bytes = let (_, (alice, bob, carol)) = Breath.Context.init_default () in let owners : address set = Set.literal [alice.address; bob.address; carol.address] in let init_storage = Helper.init_storage (owners, 1n) in - let multisig_contract = Helper.originate level Mock_contract.multisig_main init_storage 10tez in - let add_contract = Breath.Contract.originate level "add_contr" Mock_contract.add_main 1n 0tez in - let param = ([] : (nat proposal_content) list) in + let multisig_contract = Helper.originate level App.main init_storage 10tez in + let param = ([] : proposal_content list) in (* create proposal 1 *) - let param1 = (Execute { target = add_contract.originated_address; parameter = 10n; amount = 0tez;} :: param) in + let param1 = (Transfer { target = alice.address; amount = 10tez;} :: param) in let create_action1 = Breath.Context.act_as alice (Helper.create_proposal multisig_contract param1) in - let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param) in + + let param2 = (Transfer { target = bob.address; amount = 10tez;} :: param) in + let sign_action1 = Breath.Context.act_as bob (Helper.sign_proposal multisig_contract 1n true param2) in Breath.Result.reduce [ @@ -249,7 +244,7 @@ let test_suite = ; case_unauthorized_user_fail_to_sign ; case_sign_nonexisted_proposal ; case_no_owner - ; case_fail_to_sign_after_executed_flag_set + ; case_fail_to_sign_after_proposal_is_resolved ; case_wrong_content_bytes ]