diff --git a/src/proto_alpha/lib_protocol/test/delegation.ml b/src/proto_alpha/lib_protocol/test/delegation.ml new file mode 100644 index 000000000..44a1e4eee --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/delegation.ml @@ -0,0 +1,996 @@ +(**************************************************************************) +(* *) +(* Copyright (c) 2014 - 2018. *) +(* Dynamic Ledger Solutions, Inc. *) +(* *) +(* All rights reserved. No warranty, explicit or implicit, provided. *) +(* *) +(**************************************************************************) + +open Proto_alpha +open Alpha_context +open Test_tez + +(**************************************************************************) +(* bootstrap contracts *) +(**************************************************************************) +(* Bootstrap contracts are heavily used in other tests. It is helpful + to test some properties of these contracts, so we can correctly + interpret the other tests that use them. *) + +let expect_error err = function + | err0 :: _ when err = err0 -> return () + | _ -> failwith "Unexpected successful result" + +let expect_alpha_error err = + expect_error (Alpha_environment.Ecoproto_error err) + +let expect_non_delegatable_contract = function + | Alpha_environment.Ecoproto_error (Delegate_storage.Non_delegatable_contract _) :: _ -> + return () + | _ -> + failwith "Contract is not delegatable and operation should fail." + +let expect_no_deletion_pkh pkh = function + | Alpha_environment.Ecoproto_error (Delegate_storage.No_deletion pkh0) :: _ when pkh0 = pkh -> + return () + | _ -> + failwith "Delegate can not be deleted and operation should fail." + +(** bootstrap contracts delegate to themselves *) +let bootstrap_manager_is_bootstrap_delegate () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + let bootstrap0 = List.hd bootstrap_contracts in + Context.Contract.delegate (B b) bootstrap0 >>=? fun delegate0 -> + Context.Contract.manager (B b) bootstrap0 >>=? fun manager0 -> + Assert.equal_pkh ~loc:__LOC__ delegate0 manager0.pkh + +(** bootstrap contracts cannot change their delegate *) +let bootstrap_delegate_cannot_change ~fee () = + Context.init 2 >>=? fun (b, bootstrap_contracts) -> + let bootstrap0 = List.nth bootstrap_contracts 0 in + let bootstrap1 = List.nth bootstrap_contracts 1 in + Incremental.begin_construction b >>=? fun i -> + Context.Contract.manager (I i) bootstrap1 >>=? fun manager1 -> + Context.Contract.balance (I i) bootstrap0 >>=? fun balance0 -> + Context.Contract.delegate (I i) bootstrap0 >>=? fun delegate0 -> + Op.delegation ~fee (I i) bootstrap0 (Some manager1.pkh) >>=? fun set_delegate -> + if fee > balance0 then + Incremental.add_operation i set_delegate >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + else + Incremental.add_operation + ~expect_failure:expect_non_delegatable_contract i set_delegate >>=? fun i -> + Incremental.finalize_block i >>=? fun b -> + (* bootstrap0 still has same delegate *) + Context.Contract.delegate (B b) bootstrap0 >>=? fun delegate0_after -> + Assert.equal_pkh ~loc:__LOC__ delegate0 delegate0_after >>=? fun () -> + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (B b) bootstrap0 balance0 fee + + +(** bootstrap contracts cannot delete their delegation *) +let bootstrap_delegate_cannot_be_removed ~fee () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + let bootstrap = List.hd bootstrap_contracts in + Incremental.begin_construction b >>=? fun i -> + Context.Contract.balance (I i) bootstrap >>=? fun balance -> + Context.Contract.delegate (I i) bootstrap >>=? fun delegate -> + Context.Contract.manager (I i) bootstrap >>=? fun manager -> + Op.delegation ~fee (I i) bootstrap None >>=? fun set_delegate -> + if fee > balance then + Incremental.add_operation i set_delegate >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + else + Incremental.add_operation + ~expect_failure:(expect_no_deletion_pkh manager.pkh) i set_delegate >>=? fun i -> + (* delegate has not changed *) + Context.Contract.delegate (I i) bootstrap >>=? fun delegate_after -> + Assert.equal_pkh ~loc:__LOC__ delegate delegate_after >>=? fun () -> + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee + +(** bootstrap keys are already registered as delegate keys *) +let bootstrap_manager_already_registered_delegate ~fee () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + Context.Contract.manager (I i) bootstrap >>=? fun manager -> + let pkh = manager.pkh in + let impl_contract = Contract.implicit_contract pkh in + Context.Contract.balance (I i) impl_contract >>=? fun balance -> + Op.delegation ~fee (I i) impl_contract (Some pkh) >>=? fun sec_reg -> + if fee > balance then + begin + Incremental.add_operation i sec_reg >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + end + else + begin + Incremental.add_operation ~expect_failure:(function + | Alpha_environment.Ecoproto_error Delegate_storage.Active_delegate :: _ -> + return () + | _ -> + failwith "Delegate is already active and operation should fail.") + i sec_reg >>=? fun i -> + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract balance fee + end + +(** bootstrap manager can be set as delegate of an originated contract + (through origination operation) *) +let delegate_to_bootstrap_by_origination ~fee () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + Context.Contract.manager (I i) bootstrap >>=? fun manager -> + Context.Contract.balance (I i) bootstrap >>=? fun balance -> + (* originate a contract with bootstrap's manager as delegate *) + Op.origination ~fee ~credit:Tez.zero ~delegate:manager.pkh (I i) bootstrap >>=? fun (op, orig_contract) -> + Context.get_constants (I i) >>=? fun { parametric = { origination_burn ; _ }} -> (* 0.257tz *) + Lwt.return (Tez.(+?) fee origination_burn) >>=? fun total_fee -> + if fee > balance then + begin + Incremental.add_operation i op >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + end + else if total_fee > balance && balance >= fee then + (* origination did not proceed; fee has been debited *) + begin + Incremental.add_operation i ~expect_failure:(function + | Alpha_environment.Ecoproto_error Contract.Balance_too_low _ :: _ -> + return () + | _ -> + failwith "Not enough balance for origination burn: operation should fail.") + op >>=? fun i -> + (* fee was taken *) + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee >>=? fun () -> + (* originated contract has not been created *) + Context.Contract.balance (I i) orig_contract >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> true + | _ -> false) + end + else + (* bootstrap is delegate, fee + origination burn have been debited *) + begin + Incremental.add_operation i op >>=? fun i -> + Context.Contract.delegate (I i) orig_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate manager.pkh >>=? fun () -> + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance total_fee + end + +(** bootstrap manager can be set as delegate of an originated contract + without initial delegate (through delegation operation) *) +let delegate_to_bootstrap_by_delegation ~fee () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + Context.Contract.manager (I i) bootstrap >>=? fun manager -> + (* originate a contract with no delegate *) + Op.origination ~fee:Tez.zero (I i) bootstrap >>=? fun (op, orig_contract) -> + Incremental.add_operation i op >>=? fun i -> + Context.Contract.balance (I i) orig_contract >>=? fun orig_balance -> + (* Format.printf "\nBalance of originated contract: %a\n%!" Tez.pp orig_balance; *) + (* delegate to bootstrap *) + Op.delegation ~fee (I i) orig_contract (Some manager.pkh) >>=? fun deleg_op -> + if fee > orig_balance then + begin + Incremental.add_operation i deleg_op >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + end + else + (* manager is delegate, fee is debited *) + begin + Incremental.add_operation i deleg_op >>=? fun i -> + Context.Contract.delegate (I i) orig_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate manager.pkh >>=? fun () -> + Assert.balance_was_debited ~loc:__LOC__ (I i) orig_contract orig_balance fee + end + +(** bootstrap manager can be set as delegate of an originated contract + with initial delegate (through delegation operation) *) +let delegate_to_bootstrap_by_delegation_switch ~fee () = + Context.init 2 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap0 = List.hd bootstrap_contracts in + Context.Contract.manager (I i) bootstrap0 >>=? fun manager0 -> + let bootstrap1 = List.nth bootstrap_contracts 1 in + Context.Contract.manager (I i) bootstrap1 >>=? fun manager1 -> + (* originate a contract with bootstrap1's manager as delegate *) + Op.origination ~fee:Tez.zero ~credit:Tez.one ~delegate:manager1.pkh (I i) bootstrap0 >>=? fun (op, orig_contract) -> + Incremental.add_operation i op >>=? fun i -> + Context.Contract.balance (I i) orig_contract >>=? fun orig_balance -> + Context.Contract.delegate (I i) orig_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate manager1.pkh >>=? fun _ -> + (* switch delegate to bootstrap0 *) + Op.delegation ~fee (I i) orig_contract (Some manager0.pkh) >>=? fun switch_deleg -> + if fee > orig_balance then + begin + Incremental.add_operation i switch_deleg >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + end + else + (* manager0 is delegate, fee is debited *) + begin + Incremental.add_operation i switch_deleg >>=? fun i -> + Context.Contract.delegate (I i) orig_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate manager0.pkh >>=? fun () -> + Assert.balance_was_debited ~loc:__LOC__ (I i) orig_contract orig_balance fee + end + +let tests_bootstrap_contracts = [ + Test.tztest "bootstrap contracts delegate to themselves" `Quick bootstrap_manager_is_bootstrap_delegate ; + Test.tztest "bootstrap contracts cannot change their delegate (small fee)" `Quick (bootstrap_delegate_cannot_change ~fee:Tez.one_mutez) ; + Test.tztest "bootstrap contracts cannot change their delegate (max fee)" `Quick (bootstrap_delegate_cannot_change ~fee:Tez.max_tez) ; + Test.tztest "bootstrap contracts cannot delete their delegation (small fee)" `Quick (bootstrap_delegate_cannot_be_removed ~fee:Tez.one_mutez) ; + Test.tztest "bootstrap contracts cannot delete their delegation (max fee)" `Quick (bootstrap_delegate_cannot_be_removed ~fee:Tez.max_tez) ; + Test.tztest "bootstrap keys are already registered as delegate keys (small fee)" `Quick (bootstrap_manager_already_registered_delegate ~fee:Tez.one_mutez) ; + Test.tztest "bootstrap keys are already registered as delegate keys (max fee)" `Quick (bootstrap_manager_already_registered_delegate ~fee:Tez.max_tez) ; + Test.tztest "bootstrap manager can be delegate (init origination, small fee)" `Quick (delegate_to_bootstrap_by_origination ~fee:Tez.one_mutez) ; + (* balance enough for fee but not for fee + origination burn *) + Test.tztest "bootstrap manager can be delegate (init origination, edge case)" `Quick (delegate_to_bootstrap_by_origination ~fee:(Tez.of_mutez_exn 3_999_999_750_000L)) ; + (* fee bigger than bootstrap's initial balance*) + Test.tztest "bootstrap manager can be delegate (init origination, large fee)" `Quick (delegate_to_bootstrap_by_origination ~fee:(Tez.of_int 10_000_000)) ; + Test.tztest "bootstrap manager can be delegate (init delegation, small fee)" `Quick (delegate_to_bootstrap_by_delegation ~fee:Tez.one_mutez) ; + Test.tztest "bootstrap manager can be delegate (init delegation, max fee)" `Quick (delegate_to_bootstrap_by_delegation ~fee:Tez.max_tez) ; + Test.tztest "bootstrap manager can be delegate (switch delegation, small fee)" `Quick (delegate_to_bootstrap_by_delegation_switch ~fee:Tez.one_mutez) ; + Test.tztest "bootstrap manager can be delegate (switch delegation, max fee)" `Quick (delegate_to_bootstrap_by_delegation_switch ~fee:Tez.max_tez) ; +] + +(**************************************************************************) +(* delegate registration *) +(**************************************************************************) +(* A delegate is a pkh. Delegates must be registered. Registration is + done via the self-delegation of the implicit contract corresponding + to the pkh. The implicit contract must be credited when the + self-delegation is done. Furthermore, trying to register an already + registered key raises an error. + + In this series of tests, we verify that + 1- unregistered delegate keys cannot be delegated to, + 2- registered keys can be delegated to, + 3- registering an already registered key raises an error. + + + We consider three scenarios for setting a delegate: + - through origination, + - through delegation when the originated contract has no delegate yet, + - through delegation when the originated contract already has a delegate. + + We also test that emptying the implicit contract linked to a + registered delegate key does not unregister the delegate key. +*) + +(* + Valid registration + + Unregistered key: + - contract not credited and no self-delegation + - contract credited but no self-delegation + - contract not credited and self-delegation + +Not credited: +- no credit operation +- credit operation of 1μꜩ and then debit operation of 1μꜩ + +*) + +(** A- unregistered delegate keys cannot be used for delegation *) + +(* Two main series of tests: without self-delegation, and with a failed attempt at self-delegation + 1- no self-delegation + a- no credit + - no token transfer + - credit of 1μꜩ and then debit of 1μꜩ + b- with credit of 1μꜩ. + For every scenario, we try three different ways of delegating: + - through origination (init origination) + - through delegation when no delegate was assigned at origination (init delegation) + - through delegation when a delegate was assigned at origination (switch delegation). + + 2- Self-delegation fails if the contract has no credit. We try the + two possibilities of 1a for non-credited contracts. +*) + +let expect_unregistered_key pkh = function + | Alpha_environment.Ecoproto_error Roll_storage.Unregistered_delegate pkh0 :: _ + when pkh = pkh0 -> return () + | _ -> failwith "Delegate key is not registered: operation should fail." + +(* A1: no self-delegation *) +(* no token transfer, no self-delegation *) +let unregistered_delegate_key_init_origination ~fee () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + (* origination with delegate argument *) + Op.origination ~fee ~delegate:unregistered_pkh (I i) bootstrap >>=? fun (op, orig_contract) -> + Context.get_constants (I i) >>=? fun { parametric = { origination_burn ; _ }} -> + Lwt.return (Tez.(+?) fee origination_burn) >>=? fun _total_fee -> (* FIXME unused variable *) + Context.Contract.balance (I i) bootstrap >>=? fun balance -> + if fee > balance then + begin + Incremental.add_operation i op >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + end + else + (* origination did not proceed; fee has been debited *) + begin + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_pkh) + i op >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee >>=? fun () -> + (* originated contract has not been created *) + Context.Contract.balance (I i) orig_contract >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> true + | _ -> false) + end + +let unregistered_delegate_key_init_delegation ~fee () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + Context.Contract.balance (I i) bootstrap >>=? fun _balance -> (* FIXME unused variable *) + (* origination without delegate argument *) + let credit = Tez.of_int 10 in + Op.origination (I i) bootstrap ~credit >>=? fun (op, orig_contract) -> + Incremental.add_operation i op >>=? fun i -> + Op.delegation ~fee (I i) orig_contract (Some unregistered_pkh) >>=? fun delegate_op -> + if fee > credit then + begin + Incremental.add_operation i delegate_op >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + end + else + (* fee has been debited; no delegate *) + begin + Incremental.add_operation i + ~expect_failure:(expect_unregistered_key unregistered_pkh) + delegate_op >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) orig_contract credit fee >>=? fun () -> + (* originated contract has no delegate *) + Context.Contract.delegate (I i) orig_contract >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> true + | _ -> false) + end + +let unregistered_delegate_key_switch_delegation ~fee () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + (* origination with delegate setting *) + Context.Contract.manager (I i) bootstrap >>=? fun manager -> + let credit = Tez.of_int 10 in + Op.origination (I i) ~delegate:manager.pkh bootstrap ~credit >>=? fun (op, orig_contract) -> + Incremental.add_operation i op >>=? fun i -> + Context.Contract.delegate (I i) orig_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate manager.pkh >>=? fun _ -> + (* switch delegate through delegation *) + Op.delegation ~fee (I i) orig_contract (Some unregistered_pkh) >>=? fun delegate_op -> + if fee > credit then + begin + Incremental.add_operation i delegate_op >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + end + else + (* fee has been debited; no delegate *) + begin + Incremental.add_operation i + ~expect_failure:(expect_unregistered_key unregistered_pkh) + delegate_op >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) orig_contract credit fee >>=? fun () -> + (* originated contract's delegate has not changed *) + Context.Contract.delegate (I i) orig_contract >>=? fun delegate -> + Assert.not_equal_pkh ~loc:__LOC__ delegate unregistered_pkh >>=? fun () -> + Assert.equal_pkh ~loc:__LOC__ delegate manager.pkh + end + +(* credit of some amount, no self-delegation *) +let unregistered_delegate_key_init_origination_credit ~fee ~amount () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* credit + check balance *) + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* origination with delegate argument *) + Context.Contract.balance (I i) bootstrap >>=? fun balance -> + Op.origination ~fee ~delegate:unregistered_pkh (I i) bootstrap >>=? fun (op, orig_contract) -> + if fee > balance then + begin + Incremental.add_operation i op >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + end + else (* origination not done, fee taken *) + begin + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_pkh) + i op >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee >>=? fun () -> + Context.Contract.balance (I i) orig_contract >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> true + | _ -> false) + end + +let unregistered_delegate_key_init_delegation_credit ~fee ~amount () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* credit + check balance *) + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* origination without delegate argument *) + let credit = Tez.of_int 10 in + Op.origination ~fee:Tez.zero ~credit (I i) bootstrap >>=? fun (op, contract) -> + Incremental.add_operation i op >>=? fun i -> + Op.delegation ~fee (I i) contract (Some unregistered_pkh) >>=? fun delegate_op -> + if fee > credit then + Incremental.add_operation i delegate_op >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + else + begin + (* fee has been taken, no delegate for contract *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_pkh) + i delegate_op >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) contract credit fee >>=? fun () -> + Context.Contract.delegate (I i) contract >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> true + | _ -> false) + end + +let unregistered_delegate_key_switch_delegation_credit ~fee ~amount () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* credit + check balance *) + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* origination without delegate setting *) + Context.Contract.manager (I i) bootstrap >>=? fun manager -> + let credit = Tez.of_int 10 in + Op.origination (I i) ~fee:Tez.zero ~credit ~delegate:manager.pkh bootstrap >>=? fun (op, contract) -> + Incremental.add_operation i op >>=? fun i -> + Context.Contract.delegate (I i) contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate manager.pkh >>=? fun _ -> + (* switch delegate through delegation *) + Op.delegation ~fee (I i) contract (Some unregistered_pkh) >>=? fun delegate_op -> + if fee > credit then + Incremental.add_operation i delegate_op >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + else + begin + (* fee has been taken, delegate for contract has not changed *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_pkh) + i delegate_op >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) contract credit fee >>=? fun () -> + Context.Contract.delegate (I i) contract >>=? fun delegate -> + Assert.not_equal_pkh ~loc:__LOC__ delegate unregistered_pkh >>=? fun () -> + Assert.equal_pkh ~loc:__LOC__ delegate manager.pkh + end + +(* a credit of some amount followed by a debit of the same amount, no self-delegation *) +let unregistered_delegate_key_init_origination_credit_debit ~fee ~amount () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* credit + check balance *) + Op.transaction (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* debit + check balance *) + Op.transaction (I i) impl_contract bootstrap amount >>=? fun debit_contract -> + Incremental.add_operation i debit_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero >>=? fun _ -> + (* origination with delegate argument *) + Context.Contract.balance (I i) bootstrap >>=? fun balance -> + Op.origination ~fee ~delegate:unregistered_pkh (I i) bootstrap >>=? fun (op, orig_contract) -> + if fee > balance then + begin + Incremental.add_operation i op >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + end + else (* fee taken, origination not processed *) + begin + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_pkh) + i op >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee >>=? fun () -> + Context.Contract.balance (I i) orig_contract >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> true + | _ -> false) + end + +let unregistered_delegate_key_init_delegation_credit_debit ~amount ~fee () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* credit + check balance *) + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* debit + check balance *) + Op.transaction ~fee:Tez.zero (I i) impl_contract bootstrap amount >>=? fun debit_contract -> + Incremental.add_operation i debit_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero >>=? fun _ -> + (* origination without delegate argument *) + let credit = Tez.of_int 10 in + Op.origination ~fee:Tez.zero (I i) ~credit bootstrap >>=? fun (op, contract) -> + Incremental.add_operation i op >>=? fun i -> + (* set a delegate with delegation operation *) + Op.delegation ~fee (I i) contract (Some unregistered_pkh) >>=? fun delegate_op -> + if fee > credit then + begin + Incremental.add_operation i delegate_op >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + end + else + begin + (* fee has been taken, no delegate for contract *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_pkh) + i delegate_op >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) contract credit fee >>=? fun () -> + Context.Contract.delegate (I i) contract >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> true + | _ -> false) + end + +let unregistered_delegate_key_switch_delegation_credit_debit ~fee ~amount () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* credit + check balance *) + Op.transaction ~fee:Tez.zero (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* debit + check balance *) + Op.transaction (I i) impl_contract bootstrap amount >>=? fun debit_contract -> + Incremental.add_operation i debit_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero >>=? fun _ -> + (* origination with delegate setting *) + Context.Contract.manager (I i) bootstrap >>=? fun manager -> + let credit = Tez.of_int 10 in + Op.origination (I i) ~fee:Tez.zero ~credit ~delegate:manager.pkh bootstrap >>=? fun (op, contract) -> + Incremental.add_operation i op >>=? fun i -> + Context.Contract.delegate (I i) contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate manager.pkh >>=? fun _ -> + (* switch delegate through delegation *) + Op.delegation (I i) ~fee contract (Some unregistered_pkh) >>=? fun delegate_op -> + if fee > credit then + Incremental.add_operation i delegate_op >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Balance_too_low _ -> true + | _ -> false) + else + begin + (* fee has been taken, delegate for contract has not changed *) + Incremental.add_operation + ~expect_failure:(expect_unregistered_key unregistered_pkh) + i delegate_op >>=? fun i -> + Assert.balance_was_debited ~loc:__LOC__ (I i) contract credit fee >>=? fun () -> + Context.Contract.delegate (I i) contract >>=? fun delegate -> + Assert.not_equal_pkh ~loc:__LOC__ delegate unregistered_pkh >>=? fun () -> + Assert.equal_pkh ~loc:__LOC__ delegate manager.pkh + end + +(* A2- self-delegation to an empty contract fails *) +let failed_self_delegation_no_transaction () = + Context.init 1 >>=? fun (b, _) -> + Incremental.begin_construction b >>=? fun i -> + let account = Account.new_account () in + let unregistered_pkh = Account.(account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* check balance *) + Context.Contract.balance (I i) impl_contract >>=? fun balance -> + Assert.equal_tez ~loc:__LOC__ Tez.zero balance >>=? fun _ -> + (* self delegation fails *) + Op.delegation (I i) impl_contract (Some unregistered_pkh) >>=? fun self_delegation -> + Incremental.add_operation i self_delegation >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Empty_implicit_contract pkh -> + if pkh = unregistered_pkh then true else false + | _ -> false) + +let failed_self_delegation_emptied_implicit_contract amount () = + (* create an implicit contract *) + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let account = Account.new_account () in + let unregistered_pkh = Account.(account.pkh) in + let impl_contract = Contract.implicit_contract unregistered_pkh in + (* credit implicit contract and check balance *) + Op.transaction (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* empty implicit contract and check balance *) + Op.transaction (I i) impl_contract bootstrap amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero >>=? fun _ -> + (* self delegation fails *) + Op.delegation (I i) impl_contract (Some unregistered_pkh) >>=? fun self_delegation -> + Incremental.add_operation i self_delegation >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Contract_storage.Empty_implicit_contract pkh -> + if pkh = unregistered_pkh then true else false + | _ -> false) + +(** B- valid registration: + - credit implicit contract with some ꜩ + verification of balance + - self delegation + verification + - empty contract + verification of balance + verification of not being erased / self-delegation + - originate contract w implicit contract as delegate + verification of delegation *) +let valid_delegate_registration_init_origination_credit amount () = + (* create an implicit contract *) + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.implicit_contract delegate_pkh in + (* credit > 0ꜩ + check balance *) + Op.transaction (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* self delegation + verification *) + Op.delegation (I i) impl_contract (Some delegate_pkh) >>=? fun self_delegation -> + Incremental.add_operation i self_delegation >>=? fun i -> + Context.Contract.delegate (I i) impl_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate delegate_pkh >>=? fun _ -> + (* originating a contract with the newly registered delegate account as delegate *) + Op.origination ~delegate:delegate_account.pkh (I i) bootstrap >>=? fun (op, orig_contract) -> + Incremental.add_operation i op >>=? fun i -> + Context.Contract.delegate (I i) orig_contract >>=? fun orig_delegate -> + Assert.equal_pkh ~loc:__LOC__ orig_delegate delegate_pkh + +let valid_delegate_registration_init_delegation_credit amount () = + (* create an implicit contract *) + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.implicit_contract delegate_pkh in + (* credit > 0ꜩ + check balance *) + Op.transaction (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* self delegation + verification *) + Op.delegation (I i) impl_contract (Some delegate_pkh) >>=? fun self_delegation -> + Incremental.add_operation i self_delegation >>=? fun i -> + Context.Contract.delegate (I i) impl_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate delegate_pkh >>=? fun _ -> + (* originating a contract with no delegate *) + Op.origination (I i) bootstrap >>=? fun (op, orig_contract) -> + Incremental.add_operation i op >>=? fun i -> + (* check no delegate for orig contract *) + Context.Contract.delegate (I i) orig_contract >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> true + | _ -> false) >>=? fun _ -> + (* delegation to the newly registered key *) + Op.delegation (I i) orig_contract (Some delegate_account.pkh) >>=? fun delegation -> + Incremental.add_operation i delegation >>=? fun i -> + (* check delegation *) + Context.Contract.delegate (I i) orig_contract >>=? fun orig_delegate -> + Assert.equal_pkh ~loc:__LOC__ orig_delegate delegate_pkh + +let valid_delegate_registration_switch_delegation_credit amount () = + (* create an implicit contract *) + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.implicit_contract delegate_pkh in + (* credit > 0ꜩ + check balance *) + Op.transaction (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* self delegation + verification *) + Op.delegation (I i) impl_contract (Some delegate_pkh) >>=? fun self_delegation -> + Incremental.add_operation i self_delegation >>=? fun i -> + Context.Contract.delegate (I i) impl_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate delegate_pkh >>=? fun _ -> + (* originating a contract with bootstrap's account as delegate *) + Context.Contract.manager (I i) bootstrap >>=? fun bootstrap_manager -> + Op.origination (I i) ~delegate:bootstrap_manager.pkh bootstrap >>=? fun (op, orig_contract) -> + Incremental.add_operation i op >>=? fun i -> + (* test delegate of new contract is bootstrap *) + Context.Contract.delegate (I i) orig_contract >>=? fun orig_delegate -> + Assert.equal_pkh ~loc:__LOC__ orig_delegate bootstrap_manager.pkh >>=? fun _ -> + (* delegation with newly registered key *) + Op.delegation (I i) orig_contract (Some delegate_account.pkh) >>=? fun delegation -> + Incremental.add_operation i delegation >>=? fun i -> + Context.Contract.delegate (I i) orig_contract >>=? fun orig_delegate -> + Assert.equal_pkh ~loc:__LOC__ orig_delegate delegate_pkh + +let valid_delegate_registration_init_origination_credit_debit amount () = + (* create an implicit contract *) + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.implicit_contract delegate_pkh in + (* credit > 0ꜩ+ check balance *) + Op.transaction (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* self delegation + verification *) + Op.delegation (I i) impl_contract (Some delegate_pkh) >>=? fun self_delegation -> + Incremental.add_operation i self_delegation >>=? fun i -> + Context.Contract.delegate (I i) impl_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate >>=? fun _ -> + (* empty implicit contracts are usually deleted but they are kept if + they were registered as delegates. we empty the contract in + order to verify this. *) + Op.transaction (I i) impl_contract bootstrap amount >>=? fun empty_contract -> + Incremental.add_operation i empty_contract >>=? fun i -> + (* impl_contract is empty *) + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero >>=? fun _ -> + (* verify self-delegation after contract is emptied *) + Context.Contract.delegate (I i) impl_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate >>=? fun _ -> + (* originating a contract with the newly registered delegate account as delegate *) + Op.origination ~delegate:delegate_account.pkh (I i) bootstrap >>=? fun (op, orig_contract) -> + Incremental.add_operation i op >>=? fun i -> + Context.Contract.delegate (I i) orig_contract >>=? fun orig_delegate -> + Assert.equal_pkh ~loc:__LOC__ orig_delegate delegate_pkh + +let valid_delegate_registration_init_delegation_credit_debit amount () = + (* create an implicit contract *) + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.implicit_contract delegate_pkh in + (* credit > 0ꜩ+ check balance *) + Op.transaction (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* self delegation + verification *) + Op.delegation (I i) impl_contract (Some delegate_pkh) >>=? fun self_delegation -> + Incremental.add_operation i self_delegation >>=? fun i -> + Context.Contract.delegate (I i) impl_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate >>=? fun _ -> + (* empty implicit contracts are usually deleted but they are kept if + they were registered as delegates. we empty the contract in + order to verify this. *) + Op.transaction (I i) impl_contract bootstrap amount >>=? fun empty_contract -> + Incremental.add_operation i empty_contract >>=? fun i -> + (* impl_contract is empty *) + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero >>=? fun _ -> + (* verify self-delegation after contract is emptied *) + Context.Contract.delegate (I i) impl_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate >>=? fun _ -> + (* originating a contract with no delegate *) + Op.origination (I i) bootstrap >>=? fun (op, orig_contract) -> + Incremental.add_operation i op >>=? fun i -> + (* check no delegate for orig contract *) + Context.Contract.delegate (I i) orig_contract >>= fun err -> + Assert.error ~loc:__LOC__ err (function + | RPC_context.Not_found _ -> true + | _ -> false) >>=? fun _ -> + (* delegation to the newly registered key *) + Op.delegation (I i) orig_contract (Some delegate_account.pkh) >>=? fun delegation -> + Incremental.add_operation i delegation >>=? fun i -> + (* check delegation *) + Context.Contract.delegate (I i) orig_contract >>=? fun orig_delegate -> + Assert.equal_pkh ~loc:__LOC__ orig_delegate delegate_pkh + +let valid_delegate_registration_switch_delegation_credit_debit amount () = + (* create an implicit contract *) + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.implicit_contract delegate_pkh in + (* credit > 0ꜩ + check balance *) + Op.transaction (I i) bootstrap impl_contract amount >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + Assert.balance_is ~loc:__LOC__ (I i) impl_contract amount >>=? fun _ -> + (* self delegation + verification *) + Op.delegation (I i) impl_contract (Some delegate_pkh) >>=? fun self_delegation -> + Incremental.add_operation i self_delegation >>=? fun i -> + Context.Contract.delegate (I i) impl_contract >>=? fun delegate -> + Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate >>=? fun _ -> + (* empty implicit contracts are usually deleted but they are kept if + they were registered as delegates. we empty the contract in + order to verify this. *) + Op.transaction (I i) impl_contract bootstrap amount >>=? fun empty_contract -> + Incremental.add_operation i empty_contract >>=? fun i -> + (* impl_contract is empty *) + Assert.balance_is ~loc:__LOC__ (I i) impl_contract Tez.zero >>=? fun _ -> + (* originating a contract with bootstrap's account as delegate *) + Context.Contract.manager (I i) bootstrap >>=? fun bootstrap_manager -> + Op.origination (I i) ~delegate:bootstrap_manager.pkh bootstrap >>=? fun (op, orig_contract) -> + Incremental.add_operation i op >>=? fun i -> + (* test delegate of new contract is bootstrap *) + Context.Contract.delegate (I i) orig_contract >>=? fun orig_delegate -> + Assert.equal_pkh ~loc:__LOC__ orig_delegate bootstrap_manager.pkh >>=? fun _ -> + (* delegation with newly registered key *) + Op.delegation (I i) orig_contract (Some delegate_account.pkh) >>=? fun delegation -> + Incremental.add_operation i delegation >>=? fun i -> + Context.Contract.delegate (I i) orig_contract >>=? fun orig_delegate -> + Assert.equal_pkh ~loc:__LOC__ orig_delegate delegate_pkh + +(** C- a second self-delegation should raise an `Active_delegate` error *) +(* with implicit contract with some credits *) +let double_registration () = + Context.init 1 >>=? fun (b, bootstrap_contracts) -> + Incremental.begin_construction b >>=? fun i -> + let bootstrap = List.hd bootstrap_contracts in + let account = Account.new_account () in + let pkh = Account.(account.pkh) in + let impl_contract = Contract.implicit_contract pkh in + (* credit 1μꜩ+ check balance *) + Op.transaction (I i) bootstrap impl_contract (Tez.one_mutez) >>=? fun create_contract -> + Incremental.add_operation i create_contract >>=? fun i -> + (* return () *) + (* self-delegation *) + Op.delegation (I i) impl_contract (Some pkh) >>=? fun self_delegation -> + Incremental.add_operation i self_delegation >>=? fun i -> + (* second self-delegation *) + Op.delegation (I i) impl_contract (Some pkh) >>=? fun second_registration -> + Incremental.add_operation i second_registration >>= fun err -> + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_storage.Active_delegate -> true + | _ -> false) + +let tests_delegate_registration = + [ + (*** unregistered delegate key: no self-delegation ***) + (* no token transfer, no self-delegation *) + Test.tztest "unregistered delegate key (origination, small fee)" + `Quick (unregistered_delegate_key_init_origination ~fee:Tez.one_mutez); + Test.tztest "unregistered delegate key (origination, edge case fee)" + `Quick (unregistered_delegate_key_init_origination ~fee:(Tez.of_int 3_999_488)); + Test.tztest "unregistered delegate key (origination, large fee)" + `Quick (unregistered_delegate_key_init_origination ~fee:(Tez.of_int 10_000_000)); + + Test.tztest "unregistered delegate key (init with delegation, small fee)" + `Quick (unregistered_delegate_key_init_delegation ~fee:Tez.one_mutez); + Test.tztest "unregistered delegate key (init with delegation, max fee)" + `Quick (unregistered_delegate_key_init_delegation ~fee:Tez.max_tez); + + Test.tztest "unregistered delegate key (switch with delegation, small fee)" + `Quick (unregistered_delegate_key_switch_delegation ~fee:Tez.one_mutez) ; + Test.tztest "unregistered delegate key (switch with delegation, max fee)" + `Quick (unregistered_delegate_key_switch_delegation ~fee:Tez.max_tez) ; + + (* credit/debit 1μꜩ, no self-delegation *) + Test.tztest "unregistered delegate key - credit/debit 1μꜩ (origination, small fee)" + `Quick (unregistered_delegate_key_init_origination_credit_debit ~fee:Tez.one_mutez ~amount:Tez.one_mutez) ; + Test.tztest "unregistered delegate key - credit/debit 1μꜩ (origination, large fee)" + `Quick (unregistered_delegate_key_init_origination_credit_debit ~fee:Tez.max_tez ~amount:Tez.one_mutez) ; + + Test.tztest "unregistered delegate key - credit/debit 1μꜩ (init with delegation, small fee)" + `Quick (unregistered_delegate_key_init_delegation_credit_debit ~amount:Tez.one_mutez ~fee:Tez.one_mutez) ; + Test.tztest "unregistered delegate key - credit/debit 1μꜩ (init with delegation, large fee)" + `Quick (unregistered_delegate_key_init_delegation_credit_debit ~amount:Tez.one_mutez ~fee:Tez.max_tez) ; + + Test.tztest "unregistered delegate key - credit/debit 1μꜩ (switch with delegation, small fee)" + `Quick (unregistered_delegate_key_switch_delegation_credit_debit ~amount:Tez.one_mutez ~fee:Tez.one_mutez) ; + Test.tztest "unregistered delegate key - credit/debit 1μꜩ (switch with delegation, large fee)" + `Quick (unregistered_delegate_key_switch_delegation_credit_debit ~amount:Tez.one_mutez ~fee:Tez.max_tez) ; + + (* credit 1μꜩ, no self-delegation *) + Test.tztest "unregistered delegate key - credit 1μꜩ (origination, small fee)" + `Quick (unregistered_delegate_key_init_origination_credit ~fee:Tez.one_mutez ~amount:Tez.one_mutez) ; + Test.tztest "unregistered delegate key - credit 1μꜩ (origination, edge case fee)" + `Quick (unregistered_delegate_key_init_origination_credit ~fee:(Tez.of_int 3_999_488) ~amount:Tez.one_mutez) ; + Test.tztest "unregistered delegate key - credit 1μꜩ (origination, large fee)" + `Quick (unregistered_delegate_key_init_origination_credit ~fee:(Tez.of_int 10_000_000) ~amount:Tez.one_mutez) ; + + Test.tztest "unregistered delegate key - credit 1μꜩ (init with delegation, small fee)" + `Quick (unregistered_delegate_key_init_delegation_credit ~amount:Tez.one_mutez ~fee:Tez.one_mutez) ; + Test.tztest "unregistered delegate key - credit 1μꜩ (init with delegation, large fee)" + `Quick (unregistered_delegate_key_init_delegation_credit ~amount:Tez.one_mutez ~fee:Tez.max_tez) ; + + Test.tztest "unregistered delegate key - credit 1μꜩ (switch with delegation, small fee)" + `Quick (unregistered_delegate_key_switch_delegation_credit ~amount:Tez.one_mutez ~fee:Tez.one_mutez) ; + Test.tztest "unregistered delegate key - credit 1μꜩ (switch with delegation, large fee)" + `Quick (unregistered_delegate_key_switch_delegation_credit ~amount:Tez.one_mutez ~fee:Tez.max_tez) ; + + (*** unregistered delegate key: failed self-delegation ***) + (* no token transfer, self-delegation *) + Test.tztest "failed self-delegation: no transaction" `Quick failed_self_delegation_no_transaction ; + (* credit 1μtz, debit 1μtz, self-delegation *) + Test.tztest "failed self-delegation: credit & debit 1μꜩ" `Quick (failed_self_delegation_emptied_implicit_contract Tez.one_mutez) ; + + (*** valid registration ***) + (* valid registration: credit 1 μꜩ, self delegation *) + Test.tztest "valid delegate registration: credit 1μꜩ, self delegation (origination)" + `Quick (valid_delegate_registration_init_origination_credit Tez.one_mutez) ; + Test.tztest "valid delegate registration: credit 1μꜩ, self delegation (init with delegation)" + `Quick (valid_delegate_registration_init_delegation_credit Tez.one_mutez) ; + Test.tztest "valid delegate registration: credit 1μꜩ, self delegation (switch with delegation)" + `Quick (valid_delegate_registration_switch_delegation_credit Tez.one_mutez) ; + (* valid registration: credit 1 μꜩ, self delegation, debit 1μꜩ *) + Test.tztest "valid delegate registration: credit 1μꜩ, self delegation, debit 1μꜩ (origination)" + `Quick (valid_delegate_registration_init_origination_credit_debit Tez.one_mutez) ; + Test.tztest "valid delegate registration: credit 1μꜩ, self delegation, debit 1μꜩ (init with delegation)" + `Quick (valid_delegate_registration_init_delegation_credit_debit Tez.one_mutez) ; + Test.tztest "valid delegate registration: credit 1μꜩ, self delegation, debit 1μꜩ (switch with delegation)" + `Quick (valid_delegate_registration_switch_delegation_credit_debit Tez.one_mutez) ; + + (*** double registration ***) + Test.tztest "double registration" `Quick double_registration ; + ] + + + +(******************************************************************************) +(* Main *) +(******************************************************************************) + +let tests = + tests_bootstrap_contracts @ + tests_delegate_registration diff --git a/src/proto_alpha/lib_protocol/test/main.ml b/src/proto_alpha/lib_protocol/test/main.ml index 117353bac..3a7d04872 100644 --- a/src/proto_alpha/lib_protocol/test/main.ml +++ b/src/proto_alpha/lib_protocol/test/main.ml @@ -17,5 +17,6 @@ let () = "double baking", Double_baking.tests ; "seed", Seed.tests ; "baking", Baking.tests ; + "delegation", Delegation.tests ; "rolls", Rolls.tests ; ]