Tests: add tests for transfer and origination operations
This commit is contained in:
parent
e8e66a83c7
commit
d9a11caeb8
@ -11,10 +11,4 @@ let () =
|
||||
Alcotest.run "protocol_alpha" [
|
||||
"transfer", Transfer.tests ;
|
||||
"origination", Origination.tests ;
|
||||
"baking", Baking.tests ;
|
||||
"activation", Activation.tests ;
|
||||
"seed", Seed.tests ;
|
||||
"endorsement", Endorsement.tests ;
|
||||
"double endorsement", Double_endorsement.tests ;
|
||||
"double baking", Double_baking.tests ;
|
||||
]
|
||||
|
327
src/proto_alpha/lib_protocol/test/origination.ml
Normal file
327
src/proto_alpha/lib_protocol/test/origination.ml
Normal file
@ -0,0 +1,327 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2018. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
open Proto_alpha
|
||||
open Test_tez
|
||||
|
||||
let ten_tez = Tez.of_int 10
|
||||
|
||||
(* create a source contract, use it to create an originate contract
|
||||
with fee and credit as parameters (default to zero tez), this originate
|
||||
contract can also be spendable and/or delegatable. *)
|
||||
let register_origination ?(fee=Tez.zero) ?(credit=Tez.zero) ?spendable ?delegatable () =
|
||||
Context.init 1 >>=? fun (b, contracts) ->
|
||||
let contract = List.hd contracts in
|
||||
Op.origination (B b) contract ~fee ~credit ?spendable ?delegatable
|
||||
>>=? fun (operation, originated) ->
|
||||
Block.bake ~operation b >>=? fun b ->
|
||||
return (b, contract, originated)
|
||||
|
||||
|
||||
(* like register_origination but additionally tests that
|
||||
- the source contract has payed all the fees
|
||||
- the originated has been credited correctly *)
|
||||
let test_origination_balances ~loc ?(fee=Tez.zero) ?(credit=Tez.zero)
|
||||
?spendable ?delegatable () =
|
||||
Context.init 1 >>=? fun (b, contracts) ->
|
||||
let contract = List.hd contracts in
|
||||
|
||||
Context.Contract.balance (B b) contract >>=? fun balance ->
|
||||
Op.origination (B b) contract ~fee ~credit ?spendable ?delegatable >>=? fun (operation, new_contract) ->
|
||||
|
||||
(* The possible fees are: a given credit, an origination burn fee of 1 tez,
|
||||
a fee that is paid when creating an originate contract *)
|
||||
Context.get_constants (B b) >>=? fun {parametric = {origination_burn ;
|
||||
block_security_deposit}} ->
|
||||
Lwt.return (
|
||||
Tez.(+?) credit block_security_deposit >>?
|
||||
Tez.(+?) fee >>?
|
||||
Tez.(+?) origination_burn ) >>=? fun total_fee ->
|
||||
|
||||
Block.bake ~operation b >>=? fun b ->
|
||||
|
||||
(* check that after the block has been baked the source contract
|
||||
was debited all the fees *)
|
||||
Assert.balance_was_debited ~loc (B b) contract balance total_fee
|
||||
>>=? fun _ ->
|
||||
|
||||
(* check the balance of the originate contract is equal to credit *)
|
||||
Assert.balance_is ~loc (B b) new_contract credit
|
||||
|
||||
|
||||
(* transfer an amount of tez (with no fee) and check the source and
|
||||
destination balances. *)
|
||||
let transfer_and_check_balances b source dest amount =
|
||||
Context.Contract.balance (B b) source >>=? fun balance ->
|
||||
Op.transaction (B b) source dest amount >>=? fun operation ->
|
||||
Block.bake ~operation b >>=? fun b ->
|
||||
Assert.balance_was_debited ~loc:__LOC__ (B b) source balance amount >>=? fun _ ->
|
||||
return b
|
||||
|
||||
(******************************************************)
|
||||
(* Tests *)
|
||||
|
||||
let balances_simple () = test_origination_balances ~loc:__LOC__ ()
|
||||
|
||||
let balances_credit () =
|
||||
test_origination_balances ~loc:__LOC__ ~credit:ten_tez ()
|
||||
|
||||
let balances_credit_fee () =
|
||||
test_origination_balances ~loc:__LOC__ ~credit:(Tez.of_int 2) ~fee:ten_tez ()
|
||||
|
||||
let balances_credit_unspendable () =
|
||||
test_origination_balances ~loc:__LOC__ ~credit:Tez.one ~spendable:false ()
|
||||
|
||||
let balances_undelegatable () =
|
||||
test_origination_balances ~loc:__LOC__ ~delegatable:false ()
|
||||
|
||||
|
||||
(* create an originate contract with a credit, then use this contract to
|
||||
transfer some tez back into the source contract, change the delegate
|
||||
contract to the endorser account *)
|
||||
|
||||
let regular () =
|
||||
register_origination ~credit:ten_tez () >>=? fun (b, contract, new_contract) ->
|
||||
transfer_and_check_balances b new_contract contract Tez.one_cent >>=? fun _ ->
|
||||
|
||||
(* Delegatable *)
|
||||
Context.get_endorser (B b) 0 >>=? fun account ->
|
||||
Op.delegation (B b) new_contract (Some account) >>=? fun operation ->
|
||||
Block.bake ~operation b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(* ask source contract to pay a fee when originating a contract *)
|
||||
|
||||
let pay_fee () =
|
||||
register_origination ~credit:(Tez.of_int 2) ~fee:ten_tez () >>=? fun (b, contract, new_contract) ->
|
||||
transfer_and_check_balances b new_contract contract (Tez.of_int 2) >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(******************************************************)
|
||||
(* Errors *)
|
||||
|
||||
(* the originate contract is marked as unspendable. Then ask this
|
||||
contract to transfer, it will raise an error *)
|
||||
|
||||
let unspendable () =
|
||||
register_origination ~credit:Tez.one ~spendable:false () >>=? fun (b, contract, new_contract) ->
|
||||
Op.transaction (B b) new_contract contract Tez.one_cent >>=? fun operation ->
|
||||
Block.bake ~operation b >>= fun e ->
|
||||
let unspendable = function
|
||||
| Proto_alpha.Contract_storage.Unspendable_contract _ -> true
|
||||
| _ -> false in
|
||||
Assert.proto_error ~loc:__LOC__ e unspendable
|
||||
|
||||
(* the originate contract is marked as undelegatable. Then do the delegation
|
||||
for this contract, it will raise an error *)
|
||||
|
||||
let undelegatable fee () =
|
||||
register_origination ~delegatable:false () >>=? fun (b, _, new_contract) ->
|
||||
Context.get_endorser (B b) 0 >>=? fun account ->
|
||||
Incremental.begin_construction b >>=? fun i ->
|
||||
Context.Contract.balance (I i) new_contract >>=? fun balance ->
|
||||
(* FIXME need Context.Contract.delegate: cf. delegation tests
|
||||
Context.Contract.delegate (I i) new_contract >>=? fun delegate -> *)
|
||||
Op.delegation ~fee (I i) new_contract (Some account) >>=? fun operation ->
|
||||
if fee > balance then
|
||||
(* fees cannot be paid *)
|
||||
begin
|
||||
Incremental.add_operation i operation >>= fun res ->
|
||||
let not_enough_money = function
|
||||
| Proto_alpha.Contract_storage.Balance_too_low _ -> true
|
||||
| _ -> false
|
||||
in
|
||||
Assert.proto_error ~loc:__LOC__ res not_enough_money
|
||||
end
|
||||
else
|
||||
(* delegation is processed ; but delegate does not change *)
|
||||
begin
|
||||
Incremental.add_operation i operation >>=? fun i ->
|
||||
(* new contracts loses the fee *)
|
||||
Assert.balance_was_debited ~loc:__LOC__ (I i) new_contract balance fee
|
||||
(* TODO delegate has not changed : wait for delegation tests and Context.Contract.delegate
|
||||
>>=? fun () ->
|
||||
Context.Contract.delegate (I i) new_contract >>=? fun new_delegate ->
|
||||
Assert.equal_account ~loc:__LOC__ delegate new_delegate
|
||||
*)
|
||||
end
|
||||
|
||||
let credit fee () =
|
||||
register_origination ~credit:Tez.zero () >>=? fun (b, contract, new_contract) ->
|
||||
Incremental.begin_construction b >>=? fun i ->
|
||||
Context.Contract.balance (I i) contract >>=? fun balance ->
|
||||
Context.Contract.balance (I i) new_contract >>=? fun new_balance ->
|
||||
(* the source contract does not have enough tez to transfer *)
|
||||
Op.transaction ~fee (I i) new_contract contract Tez.one_cent >>=? fun operation ->
|
||||
if fee > new_balance then
|
||||
begin
|
||||
Incremental.add_operation i operation >>= fun res ->
|
||||
let not_enough_money = function
|
||||
| Proto_alpha.Contract_storage.Balance_too_low _ -> true
|
||||
| _ -> false
|
||||
in
|
||||
Assert.proto_error ~loc:__LOC__ res not_enough_money
|
||||
end
|
||||
else
|
||||
begin
|
||||
Incremental.add_operation i operation >>=? fun i ->
|
||||
(* new contracts loses the fee *)
|
||||
Assert.balance_was_debited ~loc:__LOC__ (I i) new_contract new_balance fee >>=? fun () ->
|
||||
(* contract is not credited *)
|
||||
Assert.balance_was_credited ~loc:__LOC__ (I i) contract balance Tez.zero
|
||||
end
|
||||
|
||||
(* same as register_origination but for an incremental *)
|
||||
let register_origination_inc ~credit () =
|
||||
Context.init 1 >>=? fun (b, contracts) ->
|
||||
let contract = List.hd contracts in
|
||||
Incremental.begin_construction b >>=? fun inc ->
|
||||
Op.origination (I inc) ~credit contract >>=? fun (operation, new_contract) ->
|
||||
Incremental.add_operation inc operation >>=? fun inc ->
|
||||
return (inc, new_contract)
|
||||
|
||||
(* Using the originate contract to create another
|
||||
originate contract *)
|
||||
|
||||
let origination_contract_from_origination_contract_not_enough_fund fee () =
|
||||
let amount = Tez.one in
|
||||
register_origination_inc ~credit:amount () >>=? fun (inc, contract) ->
|
||||
(* contract's balance is not enough to afford origination burn *)
|
||||
Op.origination ~fee (I inc) ~credit:amount contract >>=? fun (operation, orig_contract) ->
|
||||
Incremental.add_operation inc operation >>=? fun inc ->
|
||||
Context.Contract.balance (I inc) contract >>=? fun balance_aft ->
|
||||
(* contract was debited of [fee] but not of origination burn *)
|
||||
Assert.balance_was_debited ~loc:__LOC__ (I inc) contract balance_aft fee >>=? fun () ->
|
||||
(* orig_contract does not exist *)
|
||||
Context.Contract.balance (I inc) orig_contract >>= fun res ->
|
||||
Assert.error ~loc:__LOC__ res begin function
|
||||
| RPC_context.Not_found _ -> true
|
||||
| _ -> false
|
||||
end
|
||||
|
||||
(* create an originate contract where the contract
|
||||
does not have enough tez to pay for the fee *)
|
||||
let not_tez_in_contract_to_pay_fee () =
|
||||
Context.init 2 >>=? fun (b, contracts) ->
|
||||
let contract_1 = List.nth contracts 0 in
|
||||
let contract_2 = List.nth contracts 1 in
|
||||
Incremental.begin_construction b >>=? fun inc ->
|
||||
(* transfer everything but one tez from 1 to 2 and check balance of 1 *)
|
||||
Context.Contract.balance (I inc) contract_1 >>=? fun balance ->
|
||||
Lwt.return @@ Tez.(-?) balance Tez.one >>=? fun amount ->
|
||||
Op.transaction (I inc) contract_1 contract_2 amount >>=? fun operation ->
|
||||
Incremental.add_operation inc operation >>=? fun inc ->
|
||||
Assert.balance_was_debited ~loc:__LOC__ (I inc) contract_1 balance amount
|
||||
>>=? fun _ ->
|
||||
|
||||
(* use this source contract to create an originate contract where it requires
|
||||
to pay a fee and add an amount of credit into this new contract *)
|
||||
Op.origination (I inc) ~fee:ten_tez ~credit:Tez.one contract_1 >>=? fun (op, _) ->
|
||||
Incremental.add_operation inc op >>= fun inc ->
|
||||
Assert.proto_error ~loc:__LOC__ inc begin function
|
||||
| Contract_storage.Balance_too_low _ -> true
|
||||
| _ -> false
|
||||
end
|
||||
|
||||
(******************************************************)
|
||||
(* change the manager/delegate of this account to the account
|
||||
of endorser *)
|
||||
|
||||
let register_contract_get_ownership slot () =
|
||||
Context.init 1 >>=? fun (b, contracts) ->
|
||||
let contract = List.hd contracts in
|
||||
Incremental.begin_construction b >>=? fun inc ->
|
||||
Context.get_endorser (I inc) slot >>=? fun account_endorser ->
|
||||
return (inc, contract, account_endorser)
|
||||
|
||||
let change_manager () =
|
||||
register_contract_get_ownership 0 () >>=? fun (inc, contract, account_endorser) ->
|
||||
Op.origination ~manager:account_endorser (I inc) ~credit:Tez.one contract >>=? fun (op, _) ->
|
||||
Incremental.add_operation inc op >>=? fun inc ->
|
||||
Incremental.finalize_block inc >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
let change_delegate () =
|
||||
register_contract_get_ownership 0 () >>=? fun (inc, contract, account_endorser) ->
|
||||
Op.origination ~delegate:account_endorser (I inc) ~credit:Tez.one contract >>=? fun (op, _) ->
|
||||
Incremental.add_operation inc op >>=? fun inc ->
|
||||
Incremental.finalize_block inc >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(******************************************************)
|
||||
(* create a multiple originate contracts and
|
||||
ask contract to pay the fee
|
||||
*)
|
||||
|
||||
let n_originations n ?credit ?fee ?spendable ?delegatable () =
|
||||
fold_left_s (fun new_contracts _ ->
|
||||
register_origination ?fee ?credit ?spendable ?delegatable () >>=? fun (_, _, new_contract) ->
|
||||
let contracts = new_contract :: new_contracts in
|
||||
return contracts
|
||||
) [] (1 -- n)
|
||||
|
||||
let multiple_originations () =
|
||||
n_originations 100 ~credit:(Tez.of_int 2) ~fee:ten_tez () >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(******************************************************)
|
||||
(* cannot originate two contracts with the same context's counter *)
|
||||
|
||||
let counter () =
|
||||
Context.init 1 >>=? fun (b, contracts) ->
|
||||
let contract = List.hd contracts in
|
||||
Incremental.begin_construction b >>=? fun inc ->
|
||||
Op.origination (I inc) ~credit:Tez.one contract >>=? fun (op1, _) ->
|
||||
Op.origination (I inc) ~credit:Tez.one contract >>=? fun (op2, _) ->
|
||||
Incremental.add_operation inc op1 >>=? fun inc ->
|
||||
Incremental.add_operation inc op2 >>= fun res ->
|
||||
Assert.proto_error ~loc:__LOC__ res begin function
|
||||
| Contract_storage.Counter_in_the_past _ -> true
|
||||
| _ -> false
|
||||
end
|
||||
|
||||
(******************************************************)
|
||||
(* create an originate contract from an originate contract *)
|
||||
|
||||
let origination_contract_from_origination_contract () =
|
||||
register_origination_inc ~credit:ten_tez () >>=? fun (inc, new_contract) ->
|
||||
Op.origination (I inc) ~credit:Tez.one new_contract >>=? fun (op2, _) ->
|
||||
Incremental.add_operation inc op2 >>=? fun inc ->
|
||||
Incremental.finalize_block inc >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(******************************************************)
|
||||
|
||||
let tests = [
|
||||
Test.tztest "balances_simple" `Quick balances_simple ;
|
||||
Test.tztest "balances_credit" `Quick balances_credit ;
|
||||
Test.tztest "balances_credit_fee" `Quick balances_credit_fee ;
|
||||
Test.tztest "balances_credit_unspendable" `Quick balances_credit_unspendable ;
|
||||
Test.tztest "balances_undelegatable" `Quick balances_undelegatable ;
|
||||
|
||||
Test.tztest "regular" `Quick regular ;
|
||||
Test.tztest "pay_fee" `Quick pay_fee;
|
||||
|
||||
Test.tztest "unspendable" `Quick unspendable ;
|
||||
Test.tztest "undelegatable (no fee)" `Quick (undelegatable Tez.zero);
|
||||
Test.tztest "undelegatable (with fee)" `Quick (undelegatable Tez.one);
|
||||
Test.tztest "credit" `Quick (credit Tez.one) ;
|
||||
Test.tztest "create origination from origination not enough fund" `Quick (origination_contract_from_origination_contract_not_enough_fund Tez.zero);
|
||||
Test.tztest "not enough tez in contract to pay fee" `Quick not_tez_in_contract_to_pay_fee;
|
||||
|
||||
Test.tztest "change manager" `Quick change_manager;
|
||||
Test.tztest "change delegate" `Quick change_delegate;
|
||||
|
||||
Test.tztest "multiple originations" `Quick multiple_originations;
|
||||
|
||||
Test.tztest "counter" `Quick counter;
|
||||
|
||||
Test.tztest "create origination from origination" `Quick
|
||||
origination_contract_from_origination_contract;
|
||||
]
|
479
src/proto_alpha/lib_protocol/test/transfer.ml
Normal file
479
src/proto_alpha/lib_protocol/test/transfer.ml
Normal file
@ -0,0 +1,479 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2018. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
open Proto_alpha
|
||||
open Alpha_context
|
||||
open Test_utils
|
||||
open Test_tez
|
||||
|
||||
(*********************************************************************)
|
||||
(* Utility functions *)
|
||||
(*********************************************************************)
|
||||
|
||||
(** 1- Transfer the amount of tez from a source contract to a
|
||||
destination contract with or without the fee of transfer.
|
||||
2- Check the equivalent of the balance of the source/destination
|
||||
contract before and after the transfer *)
|
||||
let transfer_and_check_balances ~loc b ?(fee=Tez.zero) src dst amount =
|
||||
Tez.(+?) fee amount >>?= fun amount_fee ->
|
||||
Context.Contract.balance (I b) src >>=? fun bal_src ->
|
||||
Context.Contract.balance (I b) dst >>=? fun bal_dst ->
|
||||
Op.transaction (I b) ~fee src dst amount >>=? fun op ->
|
||||
Incremental.add_operation b op >>=? fun b ->
|
||||
Assert.balance_was_debited ~loc (I b) src bal_src amount_fee >>=? fun () ->
|
||||
Assert.balance_was_credited ~loc (I b) dst bal_dst amount >>=? fun () ->
|
||||
return (b, op)
|
||||
|
||||
(** 1- Transfer the amount of tez from/to a contract itself, with or
|
||||
without fee of transfer.
|
||||
2- Check the equivalent of the balance of the contract before
|
||||
and after transfer *)
|
||||
let transfer_to_itself_and_check_balances ~loc b ?(fee=Tez.zero) contract amount =
|
||||
Context.Contract.balance (I b) contract >>=? fun bal ->
|
||||
Op.transaction (I b) ~fee contract contract amount >>=? fun op ->
|
||||
Incremental.add_operation b op >>=? fun b ->
|
||||
Assert.balance_was_debited ~loc (I b) contract bal fee >>=? fun () ->
|
||||
return (b, op)
|
||||
|
||||
(** Apply a transfer n times *)
|
||||
let n_transactions n b ?fee source dest amount =
|
||||
fold_left_s (fun b _ ->
|
||||
transfer_and_check_balances ~loc:__LOC__ b ?fee source dest amount >>=? fun (b,_) ->
|
||||
return b)
|
||||
b (1 -- n)
|
||||
|
||||
let ten_tez = Tez.of_int 10
|
||||
|
||||
let max_tez =
|
||||
match Tez.of_mutez Int64.max_int with
|
||||
| None -> assert false
|
||||
| Some p -> p
|
||||
|
||||
(*********************************************************************)
|
||||
(* Tests *)
|
||||
(*********************************************************************)
|
||||
|
||||
let register_two_contracts () =
|
||||
Context.init 2 >>=? fun (b, contracts) ->
|
||||
let contract_1 = List.nth contracts 0 in
|
||||
let contract_2 = List.nth contracts 1 in
|
||||
return (b, contract_1, contract_2)
|
||||
|
||||
(** 1- Create a block and two contracts/accounts;
|
||||
2- Add a single transfer into this block;
|
||||
3- Bake this block. *)
|
||||
let single_transfer ?fee amount =
|
||||
register_two_contracts () >>=? fun (b, contract_1, contract_2) ->
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
transfer_and_check_balances ~loc:__LOC__ ?fee b contract_1 contract_2 amount >>=? fun (b,_) ->
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(** single transfer without fee *)
|
||||
let block_with_a_single_transfer () =
|
||||
single_transfer Tez.one
|
||||
|
||||
(** single transfer without fee *)
|
||||
let transfer_zero_tez () =
|
||||
single_transfer Tez.zero
|
||||
|
||||
(** single transfer with fee *)
|
||||
let block_with_a_single_transfer_with_fee () =
|
||||
single_transfer ~fee:Tez.one Tez.one
|
||||
|
||||
(** 1- Create a block, and a single contract/account;
|
||||
2- Add the originate operation into this block;
|
||||
3- Add a transfer from a contract to a contract created by
|
||||
originate operation, that requires to pay a fee of transfer;
|
||||
4- Bake this block. *)
|
||||
let block_originate_and_transfer_with_fee () =
|
||||
Context.init 1 >>=? fun (b, contracts) ->
|
||||
let contract = List.nth contracts 0 in
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
Op.origination (I b) ~fee:ten_tez contract >>=? fun (operation, new_contract) ->
|
||||
Incremental.add_operation b operation >>=? fun b ->
|
||||
transfer_and_check_balances ~loc:__LOC__ b ~fee:ten_tez contract new_contract ten_tez >>=? fun (b, _) ->
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(** 1- Create a block, and two contracts/accounts;
|
||||
2- Add a transfer from a current balance of a source contract
|
||||
into this block;
|
||||
3- Bake this block. *)
|
||||
let block_transfer_from_contract_balance () =
|
||||
register_two_contracts () >>=? fun (b, contract_1, contract_2) ->
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
Context.Contract.balance (I b) contract_1 >>=? fun balance ->
|
||||
transfer_and_check_balances ~loc:__LOC__ b contract_1 contract_2 balance >>=? fun (b,_) ->
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(** 1- Create a block and a single contract/account;
|
||||
2- Add a transfer to a contract itself without fee into this block;
|
||||
3- Add a transfer to a contract itself with fee into this block;
|
||||
4- Bake this block. *)
|
||||
let block_transfers_without_with_fee_to_self () =
|
||||
Context.init 1 >>=? fun (b, contracts) ->
|
||||
let contract = List.nth contracts 0 in
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
transfer_to_itself_and_check_balances ~loc:__LOC__ b contract ten_tez
|
||||
>>=? fun (b, _) ->
|
||||
transfer_to_itself_and_check_balances ~loc:__LOC__ b ~fee:ten_tez contract ten_tez
|
||||
>>=? fun (b, _) ->
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(** 1- Create a block, two contracts/accounts;
|
||||
2- Add three transfers into the block;
|
||||
3- Do a transfer without adding it to the block;
|
||||
4- Bake the block with three transfers. *)
|
||||
let four_transfers_bake_three_transfers () =
|
||||
register_two_contracts () >>=? fun (b, contract_1, contract_2) ->
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
n_transactions 3 b contract_1 contract_2 ten_tez >>=? fun b ->
|
||||
Op.transaction (I b) contract_1 contract_2 ten_tez >>=? fun _ ->
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(** 1- Create a contract from a bootstrap account;
|
||||
2- Create two implicit contracts;
|
||||
3- Build a block from genesis;
|
||||
4- Add a transfer with fee for transfer from a bootstrap countract into an
|
||||
implicit contract into this block;
|
||||
5- Add a transfer with fee for transfer, between two implicit contracts
|
||||
into this block;
|
||||
6- Bake this block. *)
|
||||
let transfer_from_implicit_to_implicit_contract () =
|
||||
Context.init 1 >>=? fun (b, contracts) ->
|
||||
let bootstrap_contract = List.nth contracts 0 in
|
||||
let account_a = Account.new_account () in
|
||||
let account_b = Account.new_account () in
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
let src = Contract.implicit_contract account_a.Account.pkh in
|
||||
transfer_and_check_balances ~loc:__LOC__ ~fee:ten_tez b
|
||||
bootstrap_contract src (Tez.of_int 20) >>=? fun (b, _) ->
|
||||
let dest = Contract.implicit_contract account_b.pkh in
|
||||
transfer_and_check_balances ~loc:__LOC__ ~fee:(Tez.of_int 3) b
|
||||
src dest ten_tez >>=? fun (b, _) ->
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(** 1- Create a block, contract from bootstrap accounts, contract from originate;
|
||||
2- Add a transfer from the bootstract contract into the implicit contract;
|
||||
3- Add a transfer from the impicit contract to the originate contract;
|
||||
4- Bake this block. *)
|
||||
let transfer_from_implicit_to_originated_contract () =
|
||||
Context.init 1 >>=? fun (b, contracts) ->
|
||||
let bootstrap_contract = List.nth contracts 0 in
|
||||
let contract = List.nth contracts 0 in
|
||||
let account = Account.new_account () in
|
||||
let src = Contract.implicit_contract account.Account.pkh in
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
transfer_and_check_balances ~loc:__LOC__ b bootstrap_contract src ten_tez
|
||||
>>=? fun (b, _) ->
|
||||
Op.origination (I b) contract >>=? fun (operation, new_contract) ->
|
||||
Incremental.add_operation b operation >>=? fun b ->
|
||||
transfer_and_check_balances ~loc:__LOC__ b src new_contract Alpha_context.Tez.one
|
||||
>>=? fun (b, _) ->
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(** 1- Create a block with 2 contracts;
|
||||
2- Originate 2 contracts from the previous ones;
|
||||
2- Add a transfer between the two originated contracts;
|
||||
3- Bake this block. *)
|
||||
let transfer_from_originated_to_originated () =
|
||||
register_two_contracts () >>=? fun (b, contract_1, contract_2) ->
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
Op.origination (I b) contract_1 >>=? fun (operation, orig_contract_1) ->
|
||||
Incremental.add_operation b operation >>=? fun b ->
|
||||
Op.origination (I b) contract_2 >>=? fun (operation, orig_contract_2) ->
|
||||
Incremental.add_operation b operation >>=? fun b ->
|
||||
transfer_and_check_balances ~loc:__LOC__ b
|
||||
orig_contract_1 orig_contract_2 Alpha_context.Tez.one >>=? fun (b,_) ->
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(** 1- Create a block, an originate contract, an impicit contract, a contract
|
||||
from bootstrap;
|
||||
2- Add a transfer from the originate contract to impicit contract;
|
||||
3- Bake this block. *)
|
||||
let transfer_from_originated_to_implicit () =
|
||||
Context.init 1 >>=? fun (b, contracts) ->
|
||||
let contract_1 = List.nth contracts 0 in
|
||||
let account = Account.new_account () in
|
||||
let src = Contract.implicit_contract account.pkh in
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
Op.origination (I b) contract_1 >>=? fun (operation, new_contract) ->
|
||||
Incremental.add_operation b operation >>=? fun b ->
|
||||
transfer_and_check_balances ~loc:__LOC__ b new_contract src Alpha_context.Tez.one
|
||||
>>=? fun (b, _) ->
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(* Slow tests case *)
|
||||
|
||||
let multiple_transfer n ?fee amount =
|
||||
register_two_contracts () >>=? fun (b, contract_1, contract_2) ->
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
n_transactions n b ?fee contract_1 contract_2 amount >>=? fun b ->
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(** 1- Create a block with two contracts;
|
||||
2- Apply 100 transfers. *)
|
||||
let block_with_multiple_transfers () =
|
||||
multiple_transfer 99 (Tez.of_int 1000)
|
||||
|
||||
(** 1- Create a block with two contracts;
|
||||
2- Apply 100 transfers with 10tz fee. *)
|
||||
let block_with_multiple_transfers_pay_fee () =
|
||||
multiple_transfer 10 ~fee:ten_tez (Tez.of_int 1000)
|
||||
|
||||
(** 1- Create a block with 8 contracts;
|
||||
2- Apply multiple transfers without fees;
|
||||
3- Apply multiple transfers with fees. *)
|
||||
(* TODO : increase the number of operations and add a `Slow tag to it in `tests` *)
|
||||
let block_with_multiple_transfers_with_without_fee () =
|
||||
Context.init 8 >>=? fun (b, contracts) ->
|
||||
let contracts = Array.of_list contracts in
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
let hundred = Tez.of_int 100 in
|
||||
let ten = Tez.of_int 10 in
|
||||
let twenty = Tez.of_int 20 in
|
||||
n_transactions 10 b contracts.(0) contracts.(1) Tez.one >>=? fun b ->
|
||||
n_transactions 30 b contracts.(1) contracts.(2) hundred >>=? fun b ->
|
||||
n_transactions 30 b contracts.(1) contracts.(3) hundred >>=? fun b ->
|
||||
n_transactions 30 b contracts.(4) contracts.(3) hundred >>=? fun b ->
|
||||
n_transactions 20 b contracts.(0) contracts.(1) hundred >>=? fun b ->
|
||||
n_transactions 10 b contracts.(1) contracts.(3) hundred >>=? fun b ->
|
||||
n_transactions 10 b contracts.(1) contracts.(3) hundred >>=? fun b ->
|
||||
|
||||
n_transactions 20 ~fee:ten b contracts.(3) contracts.(4) ten >>=? fun b ->
|
||||
n_transactions 10 ~fee:twenty b contracts.(4) contracts.(5) ten >>=? fun b ->
|
||||
n_transactions 70 ~fee:twenty b contracts.(6) contracts.(0) twenty >>=? fun b ->
|
||||
n_transactions 550 ~fee:twenty b contracts.(6) contracts.(4) twenty >>=? fun b ->
|
||||
n_transactions 50 ~fee:ten b contracts.(7) contracts.(5) twenty >>=? fun b ->
|
||||
n_transactions 30 ~fee:ten b contracts.(0) contracts.(7) hundred >>=? fun b ->
|
||||
n_transactions 20 ~fee:ten b contracts.(1) contracts.(0) twenty >>=? fun b ->
|
||||
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(** 1- Create a block with 8 contracts;
|
||||
2- Bake 10 blocks with a transfer each time. *)
|
||||
let build_a_chain () =
|
||||
register_two_contracts () >>=? fun (b, contract_1, contract_2) ->
|
||||
let ten = Tez.of_int 10 in
|
||||
fold_left_s (fun b _ ->
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
transfer_and_check_balances ~loc:__LOC__ b contract_1 contract_2 ten
|
||||
>>=? fun (b, _) ->
|
||||
Incremental.finalize_block b
|
||||
) b (1 -- 10) >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(*********************************************************************)
|
||||
(* Expected error test cases *)
|
||||
(*********************************************************************)
|
||||
|
||||
(** 1- Create a block;
|
||||
2- transfer an amount of tez that is bigger than the balance of the source
|
||||
contract;
|
||||
3a- If fee is smaller than the balance:
|
||||
Transfer is accepted but not processed. Fees are taken.
|
||||
3b- If fee higher than the balance: raises an `Balance_too_low` error.
|
||||
*)
|
||||
let balance_too_low fee () =
|
||||
register_two_contracts () >>=? fun (b, contract_1, contract_2) ->
|
||||
Incremental.begin_construction b >>=? fun i ->
|
||||
Context.Contract.balance (I i) contract_1 >>=? fun balance1 ->
|
||||
Context.Contract.balance (I i) contract_2 >>=? fun balance2 ->
|
||||
Op.transaction ~fee (I i) contract_1 contract_2 max_tez >>=? fun op ->
|
||||
if fee > balance1 then begin
|
||||
Incremental.add_operation i op >>= fun res ->
|
||||
Assert.proto_error ~loc:__LOC__ res begin function
|
||||
| Contract_storage.Balance_too_low _ -> true
|
||||
| _ -> false
|
||||
end
|
||||
end
|
||||
else begin
|
||||
Incremental.add_operation i op >>=? fun i ->
|
||||
(* contract_1 loses the fees *)
|
||||
Assert.balance_was_debited ~loc:__LOC__ (I i) contract_1 balance1 fee >>=? fun () ->
|
||||
(* contract_2 is not credited *)
|
||||
Assert.balance_was_credited ~loc:__LOC__ (I i) contract_2 balance2 Tez.zero
|
||||
end
|
||||
|
||||
(** 1- Create a block, and three contracts/accounts;
|
||||
2- Add a transfer that at the end the balance of a contract is
|
||||
zero into this block;
|
||||
3- Add another transfer that send tez from a zero balance contract;
|
||||
4- Catch the expected error: Balance_too_low. *)
|
||||
let balance_too_low_two_transfers fee () =
|
||||
Context.init 3 >>=? fun (b, contracts) ->
|
||||
let contract_1 = List.nth contracts 0 in
|
||||
let contract_2 = List.nth contracts 1 in
|
||||
let contract_3 = List.nth contracts 2 in
|
||||
Incremental.begin_construction b >>=? fun i ->
|
||||
Context.Contract.balance (I i) contract_1 >>=? fun balance ->
|
||||
Tez.(/?) balance 3L >>?= fun res ->
|
||||
Tez.( *?) res 2L >>?= fun two_third_of_balance ->
|
||||
transfer_and_check_balances ~loc:__LOC__ i
|
||||
contract_1 contract_2 two_third_of_balance >>=? fun (i, _) ->
|
||||
Context.Contract.balance (I i) contract_1 >>=? fun balance1 ->
|
||||
Context.Contract.balance (I i) contract_3 >>=? fun balance3 ->
|
||||
Op.transaction ~fee (I i) contract_1 contract_3
|
||||
two_third_of_balance >>=? fun operation ->
|
||||
Incremental.add_operation i operation >>=? fun i ->
|
||||
(* contract_1 loses the fees *)
|
||||
Assert.balance_was_debited ~loc:__LOC__ (I i) contract_1 balance1 fee >>=? fun () ->
|
||||
(* contract_3 is not credited *)
|
||||
Assert.balance_was_credited ~loc:__LOC__ (I i) contract_3 balance3 Tez.zero
|
||||
|
||||
(** 1- Create a block;
|
||||
2- Do two transfers one after another;
|
||||
3- Add two transfers into the block sequently;
|
||||
4- Catch the expected error: Counter_in_the_past. *)
|
||||
let invalid_counter () =
|
||||
register_two_contracts () >>=? fun (b, contract_1, contract_2) ->
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
Op.transaction (I b) contract_1 contract_2
|
||||
Tez.one >>=? fun op1 ->
|
||||
Op.transaction (I b) contract_1 contract_2
|
||||
Tez.one >>=? fun op2 ->
|
||||
Incremental.add_operation b op1 >>=? fun b ->
|
||||
Incremental.add_operation b op2 >>= fun b ->
|
||||
Assert.proto_error ~loc:__LOC__ b begin function
|
||||
| Contract_storage.Counter_in_the_past _ -> true
|
||||
| _ -> false
|
||||
end
|
||||
|
||||
(** 1- Create a block;
|
||||
2- Add a transfer into this block;
|
||||
3- Make another transfer, but did not add this transfer into the block,
|
||||
instead add the previous transfer again into this block;
|
||||
4- Catch the expected error: Counter_in_the_past. *)
|
||||
let add_the_same_operation_twice () =
|
||||
register_two_contracts () >>=? fun (b, contract_1, contract_2) ->
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
transfer_and_check_balances ~loc:__LOC__ b contract_1 contract_2 ten_tez
|
||||
>>=? fun (b, op_transfer) ->
|
||||
Op.transaction (I b) contract_1 contract_2 ten_tez >>=? fun _ ->
|
||||
Incremental.add_operation b op_transfer >>= fun b ->
|
||||
Assert.proto_error ~loc:__LOC__ b begin function
|
||||
| Contract_storage.Counter_in_the_past _ -> true
|
||||
| _ -> false
|
||||
end
|
||||
|
||||
(** 1- Create a block;
|
||||
2- Originate an unspendable new contract;
|
||||
3- Make a transfer from this contract;
|
||||
4- Catch the expected error: Unspendable_contract. *)
|
||||
let unspendable_contract () =
|
||||
register_two_contracts () >>=? fun (b, contract_1, contract_2) ->
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
Op.origination ~spendable:false (I b) contract_1 >>=? fun (operation, unspendable_contract) ->
|
||||
Incremental.add_operation b operation >>=? fun b ->
|
||||
Op.transaction (I b) unspendable_contract contract_2 Alpha_context.Tez.one_cent >>=? fun operation ->
|
||||
Incremental.add_operation b operation >>= fun res ->
|
||||
Assert.proto_error ~loc:__LOC__ res begin function
|
||||
| Contract_storage.Unspendable_contract _ -> true
|
||||
| _ -> false
|
||||
end
|
||||
|
||||
(** Checking that the sender of a transaction is the actual
|
||||
manager of the contract.
|
||||
Ownership of sender manager key (in case of a contract) *)
|
||||
let ownership_sender () =
|
||||
register_two_contracts () >>=? fun (b, contract_1, contract_2) ->
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
(* get the manager of the contract_1 as a sender *)
|
||||
Context.Contract.manager (I b) contract_1 >>=? fun manager ->
|
||||
(* create an implicit_contract *)
|
||||
let imcontract_1 = Alpha_context.Contract.implicit_contract manager.pkh in
|
||||
transfer_and_check_balances ~loc:__LOC__ b imcontract_1 contract_2 Tez.one
|
||||
>>=? fun (b,_) ->
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(*********************************************************************)
|
||||
(** Random transfer *)
|
||||
|
||||
(** Return a pair of minimum and maximum random number *)
|
||||
let random_range (min, max) =
|
||||
let interv = max - min + 1 in
|
||||
let init =
|
||||
Random.self_init ();
|
||||
(Random.int interv) + min
|
||||
in init
|
||||
|
||||
(** Return a random contract *)
|
||||
let random_contract contract_array =
|
||||
let i = Random.int (Array.length contract_array) in
|
||||
contract_array.(i)
|
||||
|
||||
(** Transfer by randomly choose amount 10 contracts, and randomly
|
||||
choose the amount in the source contract *)
|
||||
let random_transfer () =
|
||||
Context.init 10 >>=? fun (b, contracts) ->
|
||||
let contracts = Array.of_list contracts in
|
||||
Incremental.begin_construction b >>=? fun b ->
|
||||
let source = random_contract contracts in
|
||||
let dest = random_contract contracts in
|
||||
Context.Contract.balance (I b) source >>=? fun amount ->
|
||||
begin
|
||||
if source = dest
|
||||
then
|
||||
transfer_to_itself_and_check_balances ~loc:__LOC__ b source amount
|
||||
else
|
||||
transfer_and_check_balances ~loc:__LOC__ b source dest amount
|
||||
end >>=? fun (b,_) ->
|
||||
Incremental.finalize_block b >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
(** Transfer random transactions *)
|
||||
let random_multi_transactions () =
|
||||
let n = random_range (1, 100) in
|
||||
multiple_transfer n (Tez.of_int 100)
|
||||
|
||||
(*********************************************************************)
|
||||
|
||||
let tests = [
|
||||
Test.tztest "block with a single transfer" `Quick block_with_a_single_transfer ;
|
||||
Test.tztest "transfer zero tez" `Quick transfer_zero_tez ;
|
||||
Test.tztest "block with a single transfer with fee" `Quick block_with_a_single_transfer_with_fee ;
|
||||
Test.tztest "block originate and transfer with fee" `Quick block_originate_and_transfer_with_fee ;
|
||||
Test.tztest "block transfer from contract balance" `Quick block_transfer_from_contract_balance ;
|
||||
Test.tztest "block transfers without and with fee to itself" `Quick block_transfers_without_with_fee_to_self ;
|
||||
Test.tztest "four transfers but bake three transfers" `Quick four_transfers_bake_three_transfers ;
|
||||
Test.tztest "transfer from an implicit to implicit contract " `Quick transfer_from_implicit_to_implicit_contract ;
|
||||
Test.tztest "transfer from an impicit to an originated contract" `Quick transfer_from_implicit_to_originated_contract ;
|
||||
Test.tztest "transfer from an originated to an originated contract" `Quick transfer_from_originated_to_originated ;
|
||||
Test.tztest "transfer from an originated to an implicit contract" `Quick transfer_from_originated_to_implicit ;
|
||||
Test.tztest "ownership sender" `Quick ownership_sender ;
|
||||
|
||||
(* Slow tests *)
|
||||
Test.tztest "block with multiple transfers" `Quick block_with_multiple_transfers ;
|
||||
Test.tztest "block with multiple transfer paying fee" `Quick block_with_multiple_transfers_pay_fee ;
|
||||
Test.tztest "block with multiple transfer without paying fee" `Quick block_with_multiple_transfers_with_without_fee ;
|
||||
Test.tztest "build a chain" `Quick build_a_chain ;
|
||||
|
||||
(* Erroneous *)
|
||||
Test.tztest "balance too low" `Quick (balance_too_low Tez.zero);
|
||||
Test.tztest "balance too low" `Quick (balance_too_low Tez.one);
|
||||
Test.tztest "balance too low with two transfers" `Quick (balance_too_low_two_transfers Tez.zero);
|
||||
Test.tztest "balance too low with two transfers" `Quick (balance_too_low_two_transfers Tez.one);
|
||||
Test.tztest "invalid_counter" `Quick invalid_counter ;
|
||||
Test.tztest "add the same operation twice" `Quick add_the_same_operation_twice ;
|
||||
Test.tztest "unspendable contract" `Quick unspendable_contract ;
|
||||
|
||||
(* Random tests *)
|
||||
Test.tztest "random transfer" `Quick random_transfer ;
|
||||
Test.tztest "random multi transfer" `Quick random_multi_transactions ;
|
||||
]
|
Loading…
Reference in New Issue
Block a user