(*****************************************************************************) (* *) (* Open Source License *) (* Copyright (c) 2020-2021 Nomadic Labs *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) (* to deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) (* and/or sell copies of the Software, and to permit persons to whom the *) (* Software is furnished to do so, subject to the following conditions: *) (* *) (* The above copyright notice and this permission notice shall be included *) (* in all copies or substantial portions of the Software. *) (* *) (* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) (* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) (* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) (* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) (* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) (* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) (* DEALINGS IN THE SOFTWARE. *) (* *) (*****************************************************************************) (** The aim of this module is to manage operations involving tokens such as minting, transferring, and burning. Every constructor of the types [giver], [container], or [receiver] represents a kind of account that holds a given (or possibly infinite) amount of tokens. Tokens can be transferred from a [giver] to a [receiver]. To uniformly handle all cases, special constructors of givers and receivers may be used. For example, the giver [`Minted] is used to express a transfer of minted tokens to a receiver, and the receiver [`Burned] is used to express the action of burning a given amount of tokens taken from a giver. Thanks to uniformity, it is easier to track transfers of tokens throughout the protocol by running [grep -R "Token.transfer" src/proto_alpha]. For backward compatibility purpose, an ANTI-PATTERN is used to redistribute slashing to denunciator; this redistribution technic should not be mimicked if it can be avoided (see https://gitlab.com/tezos/tezos/-/issues/4787). The anti-pattern works as follows: The part of slashed amounts that goes to the author of the denunciation are not directly distributed to him. Tokens are transferred to a burning sink, then minted from an infinite source ( see `Double_signing_punishments, and `Sc_rollup_refutation_rewards ). Again, this is an ANTI-PATTERN that should not be mimicked. *) (** [container] is the type of token holders with finite capacity, and whose assets are contained in the context. An account may have several token holders, that can serve as sources and/or sinks. For example, an implicit account [d] serving as a delegate has a token holder for its own spendable balance, and another token holder for its frozen deposits. *) type container = [ `Contract of Contract_repr.t (** Implicit account's or Originated contract's spendable balance *) | `Collected_commitments of Blinded_public_key_hash.t (** Pre-funded account waiting for the commited pkh and activation code to be revealed to unlock the funds *) | `Frozen_deposits of Frozen_staker_repr.t (** Frozen tokens of a staker for consensus security deposits. *) | `Unstaked_frozen_deposits of Unstaked_frozen_staker_repr.t * Cycle_repr.t (** Frozen tokens of a contract that have been unstaked at the given cycle. *) | `Block_fees (** Current block's fees collection *) | `Frozen_bonds of Contract_repr.t * Bond_id_repr.t (** Frozen tokens of a contract for bond deposits (currently used by rollups) *) ] (** [infinite_source] defines types of tokens providers which are considered to be ** of infinite capacity. *) type infinite_source = [ `Invoice (** Tokens minted during a protocol upgrade, typically to fund the development of some part of the amendment. *) | `Bootstrap (** Bootstrap accounts funding *) | `Initial_commitments (** Funding of Genesis' prefunded accounts requiring an activation *) | `Revelation_rewards (** Seed nonce revelation rewards *) | `Attesting_rewards (** Consensus attesting rewards *) | `Baking_rewards (** Consensus baking fixed rewards *) | `Baking_bonuses (** Consensus baking variable bonus *) | `Minted (** Generic source for test purpose *) | `Liquidity_baking_subsidies (** Subsidy for liquidity-baking contract *) | `Sc_rollup_refutation_rewards (** Sc_rollup refutation rewards (slashing redistribution) *) ] (** [giver] is the type of token providers. Token providers that are not containers are considered to have infinite capacity. *) type giver = [infinite_source | container] type infinite_sink = [ `Storage_fees (** Fees burnt to compensate storage usage *) | `Double_signing_punishments (** Consensus slashing *) | `Lost_attesting_rewards of Signature.Public_key_hash.t * bool * bool (** Consensus rewards not distributed because the participation of the delegate was too low. *) | `Sc_rollup_refutation_punishments (** Smart rollups refutation slashing *) | `Burned (** Generic sink mainly for test purpose *) ] (** [receiver] is the type of token receivers. Token receivers that are not containers are considered to have infinite capacity. *) type receiver = [infinite_sink | container] (** [balance ctxt container] returns a new context because of an access to carbonated data, and the balance associated to the token holder. This function may fail if [allocated ctxt container] returns [false]. Returns an error with the message "get_balance" if [container] refers to an originated contract that is not allocated. This function is only defined on the few cases for which it is actually needed. *) val balance : Raw_context.t -> [< `Block_fees | `Collected_commitments of Blinded_public_key_hash.t] -> (Raw_context.t * Tez_repr.t) tzresult Lwt.t (** [transfer_n ?origin ctxt givers receiver] transfers [amount] Tez from [giver] to [receiver] for each [(giver, amount)] pair in [givers], and returns a new context, and the list of corresponding balance updates. The function behaves as though [transfer ?origin ctxt giver receiver amount] was invoked for each pair [(giver, amount)] in [givers], however a single balance update is generated for the total amount transferred to [receiver]. When [givers] is an empty list, the function does nothing to the context, and returns an empty list of balance updates. *) val transfer_n : ?origin:Receipt_repr.update_origin -> Raw_context.t -> ([< giver] * Tez_repr.t) list -> [< receiver] -> (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t (** [transfer ?origin ctxt giver receiver amount] transfers [amount] Tez from giver [giver] to receiver [receiver], and returns a new context, and the list of corresponding balance updates tagged with [origin]. By default, [~origin] is set to [Receipt_repr.Block_application]. Returns {!Storage_Error Missing_key} if [giver] refers to a contract that is not allocated. Returns a [Balance_too_low] error if [giver] refers to a contract whose balance is less than [amount]. Returns a [Subtraction_underflow] error if [giver] is not a contract and its balance is less than [amount]. Returns a [Empty_implicit_delegated_contract] error if [giver] is an implicit contract that delegates to a different contract, and whose balance is equal to [amount]. Returns a [Non_existing_contract] error if [receiver] refers to an originated contract that is not allocated. Returns a [Non_existing_contract] error if [amount <> Tez_repr.zero], and [receiver] refers to an originated contract that is not allocated. Returns a [Addition_overflow] error if [receiver] refers to a receiver whose balance is greater than [Int64.max - amount]. Returns a [Wrong_level] error if [src] or [receiver] refer to a level that is not the current level. *) val transfer : ?origin:Receipt_repr.update_origin -> Raw_context.t -> [< giver] -> [< receiver] -> Tez_repr.t -> (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t module Internal_for_tests : sig (** [allocated ctxt container] returns a new context because of possible access to carbonated data, and a boolean that is [true] when [balance ctxt container] is guaranteed not to fail, and [false] when [balance ctxt container] may fail. *) val allocated : Raw_context.t -> container -> (Raw_context.t * bool) tzresult Lwt.t type container_with_balance = [ `Contract of Contract_repr.t | `Collected_commitments of Blinded_public_key_hash.t | `Block_fees | `Frozen_bonds of Contract_repr.t * Bond_id_repr.t ] (** [balance ctxt container] returns a new context because of an access to carbonated data, and the balance associated to the token holder. This function may fail if [allocated ctxt container] returns [false]. Returns an error with the message "get_balance" if [container] refers to an originated contract that is not allocated. *) val balance : Raw_context.t -> [< container_with_balance] -> (Raw_context.t * Tez_repr.t) tzresult Lwt.t end