diff --git a/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.ml b/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.ml index 9931865f1ea27d5eccd7125b83849d76b8ff4d91..819c1d4c28a953af037ed227748ba3eeaf7b7f82 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.ml @@ -367,7 +367,14 @@ let apply_game_result ctxt rollup (stakers : Sc_rollup_game_repr.Index.t) in let balances_updates = balance_updates_loser @ balance_updates_winner in return (ctxt, balances_updates) - | Draw -> return (ctxt, []) + | Draw -> + let* ctxt, balances_updates_alice = + Stake_storage.remove_staker ctxt rollup stakers.alice + in + let* ctxt, balances_updates_bob = + Stake_storage.remove_staker ctxt rollup stakers.bob + in + return (ctxt, balances_updates_alice @ balances_updates_bob) in let* ctxt, _, _ = Store.Game_timeout.remove (ctxt, rollup) stakers in let* ctxt, _, _ = Store.Opponent.remove (ctxt, rollup) stakers.alice in diff --git a/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.mli b/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.mli index e01bf187b773bf6cec88d9d3888f2a152592d352..6b4a68028cd6d0dc1336ba42552da1f0de022bc8 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.mli +++ b/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.mli @@ -155,7 +155,8 @@ val get_timeout : (** [apply_game_result ctxt rollup game_result] takes a [game_result] produced by [timeout] or [game_move] and performs the necessary end-of-game cleanup: remove the game itself from the store and punish the losing - player by removing their stake. + player by removing their stake. In the case where the game ended in + a draw, both players are slashed. This is mostly just calling [remove_staker], so it can fail with the same errors as that. However, if it is called on an [game_result] diff --git a/src/proto_alpha/lib_protocol/test/helpers/assert.ml b/src/proto_alpha/lib_protocol/test/helpers/assert.ml index 49b4e62d799850fc8e2e7b735a249a989eca9e5e..b0609e6506fe1f76a74f02cffaa49263fe7a68b7 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/assert.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/assert.ml @@ -214,27 +214,60 @@ open Context (* Some asserts for account operations *) -(** [balance_is b c amount] checks that the current balance of contract [c] is - [amount]. - Default balance type is [Main], pass [~kind] with [Deposit], [Fees] or - [Rewards] for the others. *) -let balance_is ~loc b contract expected = - Contract.balance b contract >>=? fun balance -> - equal_tez ~loc balance expected - -(** [balance_was_operated ~operand b c old_balance amount] checks that the - current balance of contract [c] is [operand old_balance amount] and - returns the current balance. - Default balance type is [Main], pass [~kind] with [Deposit], [Fees] or - [Rewards] for the others. *) -let balance_was_operated ~operand ~loc b contract old_balance amount = +let contract_property_is property ~loc b contract expected = + property b contract >>=? fun balance -> equal_tez ~loc balance expected + +(** [balance_is b c amount] checks that the current balance [b] of contract [c] + is [amount]. +*) +let balance_is = contract_property_is Contract.balance + +(** [frozen_bonds_is b c amount] checks that the current frozen bonds of + contract [c] is [amount]. +*) +let frozen_bonds_is = contract_property_is Contract.frozen_bonds + +let balance_or_frozen_bonds_was_operated ~is_balance ~operand ~loc b contract + old_balance amount = operand old_balance amount |> Environment.wrap_tzresult >>?= fun expected -> - balance_is ~loc b contract expected + let f = if is_balance then balance_is else frozen_bonds_is in + f ~loc b contract expected +(** [balance_was_credited ~loc ctxt contract old_balance amount] checks + that [contract]'s balance was credited [amount] tez in comparison to + [old_balance]. +*) let balance_was_credited = - balance_was_operated ~operand:Alpha_context.Tez.( +? ) - -let balance_was_debited = balance_was_operated ~operand:Alpha_context.Tez.( -? ) + balance_or_frozen_bonds_was_operated + ~is_balance:true + ~operand:Alpha_context.Tez.( +? ) + +(** [balance_was_credited ~loc ctxt contract old_balance amount] checks + that [contract]'s balance was debited [amount] tez in comparison to + [old_balance]. +*) +let balance_was_debited = + balance_or_frozen_bonds_was_operated + ~is_balance:true + ~operand:Alpha_context.Tez.( -? ) + +(** [frozen_bonds_was_credited ~loc ctxt contract old_balance amount] checks + that [contract]'s frozen bonds was credited [amount] tez in comparison to + [old_balance]. +*) +let frozen_bonds_was_credited = + balance_or_frozen_bonds_was_operated + ~is_balance:false + ~operand:Alpha_context.Tez.( +? ) + +(** [frozen_bonds_was_credited ~loc ctxt contract old_balance amount] checks + that [contract]'s frozen bonds was credited [amount] tez in comparison to + [old_balance]. +*) +let frozen_bonds_was_debited = + balance_or_frozen_bonds_was_operated + ~is_balance:false + ~operand:Alpha_context.Tez.( -? ) let pp_print_list pp out xs = let list_pp fmt = diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/test_sc_rollup.ml b/src/proto_alpha/lib_protocol/test/integration/operations/test_sc_rollup.ml index 0a977a29a2a54b2a7ca25fe594c7b4850ce33eb7..50f1c057c4c0008616724ce0c22e43061164e87a 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/test_sc_rollup.ml +++ b/src/proto_alpha/lib_protocol/test/integration/operations/test_sc_rollup.ml @@ -1740,13 +1740,16 @@ let test_draw_with_two_invalid_moves () = let choice = Sc_rollup.Tick.initial in dumb_proof ~choice in - let* p1_final_move_op = Op.sc_rollup_refute (B block) p1 rollup p2_pkh (Some p1_refutation) in add_op block p1_final_move_op in + (* Get the frozen bonds for the two players before the draw. *) + let* frozen_bonds_p1 = Context.Contract.frozen_bonds (B block) p1 in + let* frozen_bonds_p2 = Context.Contract.frozen_bonds (B block) p2 in + (* Player2 will also send an invalid final move. *) let* incr = let* p2_refutation = @@ -1762,7 +1765,28 @@ let test_draw_with_two_invalid_moves () = (* As both players played invalid moves, the game ends in a draw. *) let expected_game_status : Sc_rollup.Game.status = Ended Draw in - assert_refute_result ~game_status:expected_game_status incr + let* () = assert_refute_result ~game_status:expected_game_status incr in + + (* The two players should have been slashed. *) + let* constants = Context.get_constants (I incr) in + let stake_amount = constants.parametric.sc_rollup.stake_amount in + let* () = + Assert.frozen_bonds_was_debited + ~loc:__LOC__ + (I incr) + p1 + frozen_bonds_p1 + stake_amount + in + let* () = + Assert.frozen_bonds_was_debited + ~loc:__LOC__ + (I incr) + p2 + frozen_bonds_p2 + stake_amount + in + return_unit (** Test that timeout a player during the final move ends the game if the other player played. *)