Stakable frozen bonds
Context
This MR proposes a mechanism for frozen deposits (called bonds) that can be delegated (issue #2366 (closed)). A frozen bond is associated to a contract and a bond identifier. Currently a bond identifier can be a tx_rollup, but it should be straightforward to extend the type bond_id_repr.t of bond identifiers.
Summary of changes
-
A new kind of account has been added to the token module, namely the kind of frozen bonds accounts. Each account of that kind is identified by contract and a bond identifier, such as in
Frozen_bonds (contract, bond_id). Hence to freeze a deposit, unfreeze a deposit, or punish a user, the following instruction can be used respectively:Token.transfer (`Contract c) (`Frozen_bonds (c,bid)) amount_of_depositToken.transfer (`Frozen_bonds (c,bid)) (`Contract c) amount_of_deposit-
Token.transfer (`Frozen_bonds (c,bid)) `Burned amount_of_deposit.
-
To help detect errors, a deposit must be transferred at once, i.e. when the source of a transfer is a frozen bonds account, the amount transferred must be equal to the balance of the said account.
-
Funds in all accounts
`Frozen_bonds (c,_)are part of the stake of the contractc. This is true regardless of whethercis a delegate or not. Hence the staking balance of a delegatedis(balance d) + (delegated_balances d) + (frozen_deposits d) + (frozen_bonds d). -
Implicit contracts that do not delegate to other contracts are not de-allocated if their balance is zero and they still have frozen bonds. In that situation those accounts are considered to be still active. They are de-allocated only when their balance and frozen bonds are both zero (i.e. when they become stake-less). This is to prevent charging origination fees, when funds are transferred to an account that has been emptied (and unallocated) subsequently to freezing deposit. The de-allocation is now handled in the Token module, and is triggered just after a transfer renders an account stake-less either by clearing its balance or by removing all its frozen bonds.
This choice is to avoid having to manage the de-allocation in two locations, i.e. when funds are withdrawn from a.(`Contract c)(in moduleContract_storage) and when funds are withdrawn from a(`Frozen_bonds (c,_))(in moduleFrozen_bonds)
Manually testing the MR
CI, in particular :
-
dune exec src/proto_alpha/lib_protocol/test/integration/main.exe -- test "^token", and -
dune exec src/proto_alpha/lib_protocol/test/integration/main.exe -- test "^frozen bonds".