Adaptive Inflation

Deprecated - see version 1.1

by Sophia Gold and Nicolas Ochem - Oxhead Alpha

This is a functional specification of Adaptive Inflation, based on Arthur Breitman's original post on Agora. It attempts to formally introduce the notion of cobaking based on the follow-up discussion on the Blockchain Evolved show. It introduces an accounting model that allows cobakers to have arbitrarily small balances in a scalable way. It also introduces a mechanism for in-protocol collection of cobaking fees.

The specification is accompanied by design notes in this format.

Cobaking

There are two types of delegators under Adaptive Inflation:

  • Regular delegators, as they currently exist in Tezos
  • Cobakers, who contribute to the security deposit.

Delegation with slashable security deposit exists in other protocols, e.g. Cosmos and Polkadot. Since adaptive inflation targets a higher percentage of supply held in security deposit, the ability of delegators to contribute to their bakers' deposit is useful for smaller bakers to remain competitive and therefore to preserve the decentralization of the network.

Cobakers trust bakers to not equivocate, otherwise they may lose their deposit.

A new operation cobake is introduced. Any manager account can call this operation. It takes a strictly positive amount value in mutez as a parameter.

Contracts can cobake using a new COBAKE Michelson instruction, taking a strictly positive amount value in mutez as a parameter.

Whenever the cobake operation is called on a manager account, or the COBAKE instruction is called within a contract, the following happens:

  • if amount is larger than the account's free balance, the operation is rejected,
  • if the account is not delegating, the operation is rejected,
  • otherwise, amount goes into a cobaking staging area and is no longer part of the account's free balance: it is frozen,
  • if as a result the free balance becomes zero, the account is not reaped and it is not necessary to pay a storage burn to transfer new tez to it.

Note that the above also applies when the manager account is the baker itself, e.g. the baker can contribute to their own security deposit with the cobake operation.

The only way to contribute to the security deposit is by cobaking. The protocol no longer takes it automatically from the free balance.

The purpose of amount parameter is to prevent the entire balance from being frozen. This would remove the ability to pay fees, preventing for example a subsequent uncobake operation.
It is still possible for an account to freeze its entire balance by setting amount to exactly the free balance minus fee. Then an inbound transfer of tez is required prior to any further operation.

Baking rights for every cycle C are based on a stake snapshot taken during at cycle C - PRESERVED_CYCLES - 1. If this snapshot contains delegators with a non-zero balance in their cobaking staging area, this amount is considered as part of the deposit of the delegator's baker for the purposes of rights calculation. Then, when cycle C starts, this amount is converted into an actual security deposit for the delegator's baker and starts earning rewards and being susceptible to slashing.

Whoever succesfully runs this operation is then known as a cobaker for the baker they are delegating to (unless they are the baker themselves).

Wallets and Octez CLI can further simplify cobaking by batching the delegation operation with the cobake operation, and set good defaults for the user (for example, cobake the entire balance minus one tez).

The purpose of the staging area is to prevent opportunistic cobaking to a baker that has been lucky with block and endorsement rights in the next 5 cycles. As a consequence, cobaking, just like baking and delegation, becomes effective 6 cycles after the operation is submitted.

Existing contracts on Tezos today can not cobake. New contracts will be written that will have cobaking ability using the COBAKE instruction.
For example, it will be possible to write a multisig cobaking contract.

Baking Rights

Octez documentation refers to a baker as a "delegate". In this document we used "baker".

Baking and endorsing rights for any active baker

b are distributed using a discrete probablilty distribution weighed on the value of
bakingRights(b)
given by the formula below.

We define:

  • deposit(b,c)
    as the security deposit of any cobaker
    c
    of baker
    b
    • this includes the baker's own security deposit
      deposit(b,b)
  • deposit(b)
    as
    b
    's total security deposit:
    deposit(b)=cdeposit(b,c)
  • delegation(b)
    as the balance of
    b
    and all delegators of
    b
    , free and frozen.

A baker can potentially bake without contributing to the security deposit themselves, instead relying only on cobakers to get rights. This is fine: cobaking is a trust relationship. What matters is that someone's funds are at stake.

We then define:

X(b)={deposit(b)if deposit(b)>minimalStake0otherwise.

totalDeposit=bX(b)

minimalStake is 6,000 on mainnet. This means, a baker must have over 6k of security deposit to bake, either provided by the baker, a cobaker, or a combination of both. Otherwise, they don't get any rights at all.

Y(b)=min(10X(b),delegation(b))

totalDelegation=bY(b)

As is the case today, the "free space" of a baker for delegation is at most 10 times the amount of security deposit. These is to prevent the baker from accumulating too many rights while having little at stake.

bakingRights(b)=23X(b)totalDeposit+13Y(b)totalDelegation

This has the property that the total deposit grants twice as many rights as the total delegation.

It holds that:

bbakingRights(b)=1

The mechanism that maps the distribution of baking rights into discrete rights per block is unchanged.

For a given cycle

n, the calculations above are considering the balances as of a randomly chosen stake snapshot during the cycle n-PRESERVED_CYCLES - 1. This is also unchanged.

The governance voting power is proportional to the baking rights at the beginning of the governance period.

Protocol Rewards

totalSupply is the total amount of tez in circulation.

The value of

totalSupply can be accessed from within the protocol since Ithaca.

Under adaptive inflation, the global inflation rate is set at

2(1/(100x))2 where
x
is
totalDeposittotalSupply
.

Every new cycle, the global inflation rate is computed based on the value of

x as of the chosen stake snapshot. We then use the constants blocks_per_cycle and minimal_block_delay to convert the desired yearly inflation into an amount of inflation by cycle.

This amount is then further split between baking and endorsing rewards following the rules that already exist.

As a result, every block baked during a cycle receives a similar block reward (and bonus, assuming all endorsers are active). Endorsement reward is distributed based on the baking rights distribution. This does not change.

What changes is the total amount of rewards given for baking and endorsing. Currently it is 80 tez per minute. Under Mumbai with 15 second blocks, each block grants up to 10 tez baking rewards and up to 10 tez endorsing rewards. Under adaptive inflation, this amount is reevaluated at every cycle based on the percentage of tez in security deposits globally.

Today, the frozen supply is at 7.7% and the total supply is 950M tez. Assuming this is the case when Adaptive Inflation kicks in, the global inflation rate will be

2(1/7.7)2=0.034, or about 61 tez per minute.
People are incentivized to switch their delegation to cobaking to earn more rewards. As they do, the total amount of security deposits increase and the inflation rate goes down further.

Adaptive inflation only affects block and endorsement rewards. Other type of rewards (revelation, block fees, denunciations, VDF revelation) remain unchanged.

Internal Security Deposit Accounting

Within this section, "account" refers to an container account within the account generalization introduced in Ithaca.

For every cobaker

c, we store a pseudo-token balance
tokBal(b,c)
. The baker itself also has a pseudo-balance
tokBal(b,b)
.

A baker is associated with 2 convenience accounts (as is the case today) and one pseudo-token balance:

  • ('Contract b) stores the free balance
  • ('Frozen_deposits b) stores the security deposit
    deposit(b)
    associated with the baker
  • tokBal(b,b)
    stores the portion of the deposit contributed by the baker

This is an internal representation not exposed to the user.

A delegator account (manager or contract) is also associated with 2 convenience accounts and one pseudo-token balance:

  • ('Contract c) stores the delegator free balance (subject to free delegation)
  • ('Pending_cobaking c) stores the amount in the cobaking staging area
  • tokBal(b,c)
    stores the cobaker's portion of
    deposit(b)

The purpose of this design is to lazily limit the number of storage updates. A reward does not require any update of any of the cobaker's three values described above. Only upon uncobaking are these values updated.

We define

tokBal(b) as the sum of pseudo-tokens belonging to the baker and any associated cobaker:

tokBal(b)=ctokBal(b,c)

The cobake operation or COBAKE Michelson instruction causes an Token.transfer from ('Contract c) to ('Pending_cobaking c).

When the stake snapshot being considered for rights calculation contains delegators with a balance in ('Pending_cobaking c), the protocol performs a Token.transfer to move these amount to ('Frozen_deposits b) for their respective baker.

The first contribution to ('Frozen_deposits b) grants the contributor

c an amount
tokBal(b,c)
of pseudo-tokens equal to the amount contributed in mutez.

Then, when a baker or cobaker

c makes a contribution of
k
mutez to the security deposit, they receive
K
pseudo-tokens according the formula:

K=ktokBal(b)deposit(b)

At any time, the frozen deposit in tez of a baker or cobaker

c can be calculated by:

deposit(b,c)=tokBal(b,c)deposit(b)tokBal(b)

The pseudo-token balances are units of internal accounting that are never exposed to the user by CLI, and should not be exposed by wallets or block explorers. They can not be transfered between accounts.

Instead, wallets and CLI should expose the current frozen balance in tez by computing it on-the fly with the formula above (plus any amounts in the staging area).

Reward Distribution

When rewards are earned during a given cycle, the protocol splits them according to the baking rights formula in the section above:

  • the portion
    13Y(b)totalDelegationbakingRights(b)
    corresponding to delegation is credited to the baker's free balance ('Contract b)
  • the remaining amount
    23X(b)totalDepositbakingRights(b)
    goes to ('Frozen_deposits b).

The portion of the rewards that come from cobaking is split between all cobakers in proportion of their contribution.

This happens in-protocol: no payout is required. Until they withdraw, they can monitor their gains by querying their RPC balance, which computes it based on the pseudo-token balance of the cobaker and the deposit amount in tez. And when they withdraw, both rewards and principal are credited to their free balance after unfreezing.

On the other hand, rewards from delegation are credited to the baker as free balance, and the baker is expected to pay them out with a payout engine (TRD, breadcrumbs, TAPS, tezpay), as was the case before.

Every reward (baking, endorsing, fees, revelation, denunciation) is split in the same way.

Over time, we expect cobaking to become dominant compared to existing delegation, and therefore most rewards will be accrued in-protocol without explicit payout transactions.

This is desirable since it removes the regulatory ambiguity regarding payouts.

Rewards from cobaking are automatically added as part of the security deposit. If the cobaker wants to cash them out, they have to uncobake them and wait for them to unfreeze.

Cobaking Fee

A new operation set_cobaking_fee is introduced, taking a numerical value

f as parameter. Any baker active or inactive can submit this operation. The default value is 0 and the acceptable values are numbers between 0 and 1, with a maximum precision of 4 digits.

The user-facing representation of the fee should be displayed as a percentage. For example

f=0.1000 is a 10% fee.

The fee is stored in the context, in the table that was introduced to store the consensus key. Bakers can update this value at will. The fee effective at the end of the cycle when the stake snapshot was taken is taken into account for any reward accrued during the cycle.

This means any change of fee takes 21 days to be effective on mainnet.

When the baker earns a reward of

r tez, the baker's fee is credited in the form of additional pseudo-tokens
Kfee
based on the formula:

Kfee=tokBal(b)(deposit(b)+rdeposit(b)+r(1f)1)

This design scales well. Indeed, only the pseudo-token balance of the baker is updated. The pseudo-token balance of all cobakers does not change. This is equivalent to the cobakers being slightly "diluted" at each reward.

By default, when the fee is zero,

Kfee is equal to zero and no token is credited to the baker when a reward is accrued.

See the appendix below for a detailed explanation of this formula.

Slashing

Slashing denunciation events lower the tez balance of

deposit(b).

  • if
    deposit(b)
    is positive after slashing, there is no effect on the pseudo-token balance
  • if
    deposit(b)
    is zero after slashing, all token balances of all cobakers are zeroed out and erased.

Slashing does not alter the ownership of the deposit. Everyone is slashed in proportion of their contribution.

The Tenderbake slashing rules remain unchanged under Adaptive Inflation: double baking slashes 640 tez from the security deposit, double endorsing slashes 50% of the initial security deposit for the cycle. Two double endorsing events result in the security deposit being entirely slashed. When the security deposit is zero, blocks and endorsements for this baker become invalid for the remainder of the cycle.

If a cobaker contributes to the security deposit after the offence but before the denunciation, then they get slashed like everyone else: the timing of the denunciation, not the offence, is relevant.

Uncobaking

Another new operation uncobake is introduced. It takes a strictly positive amount value in mutez as a parameter.

For contracts, a new Michelson instruction UNCOBAKE is introduced, which takes a strictly positive amount value in mutez as a parameter.

When uncobake is called, the following happens:

  • if amount is greater than the security deposit of the cobaker that is not currently unfreezing, the operation fails,
  • if the baker is inactive (a.k.a. passive delegate), amount is immediately transfered to the free balance of the cobaker,
  • otherwise, these pseudo-tokens go into an unfreezing period for MAX_SLASHING_PERIOD + PRESERVED_CYCLES cycles. During this time, they are still subject to slashing and still earning rewards.

These unfreezing pseudo-tokens are tracked by tagging them, along with the cycle number when the unfreezing will be complete. When amount is strictly lower than

deposit(b,c), the tokens are split in two entries, between the unfreezing tokens (tagged as such) and the remainder.

There may be several concurrent unfreezings completing in several future cycles.

At the beginning of every cycle, the protocol traverses the pseudo-tokens of every cobaker, and credits the newly unfrozen deposits to the cobakers' free balance.

Whenever any amount is credited to the cobaker's free balance, it decreases

deposit(b) accordingly and zeroes out the corresponding pseudo-token entry.

If the baker is active, the amount you get is higher than the amount you request. In includes the rewards accrued during the unfreezing period.

When a cobaker withdraws their delegation or switches their delegation to another baker, their entire security deposit is uncobaked.

A cobaker can delegate or cobake free tez with another baker as soon as they withdraw. But they can not cobake unfreezing funds. They have to wait for unfreezing to be complete before cobaking them again.

Consequently, it is possible for a cobaker to have frozen balance with several bakers. In this case, several pseudo-token balances

tokbal(b,c) and
tokbal(b,c)
are tracked in the cobaker's account.

Set Deposits Limit Deprecation and Orderly Shutdown

The set_deposits_limit operation is deprecated.

set_deposits_limit is made redundant by the cobake operation: the baker and their cobakers are now fully in control of their security deposit, and therefore the notion of deposits limit no longer applies.

The baker can perform an orderly shutdown of their operations by withdrawing their self-delegation. When this happens, the baker's and every cobaker's security deposit is uncobaked and unfreezes according to the schedule. The withdrawn baker is no longer considered for baking and endorsing right distribution.

This is to replace another common usage of set_deposits_limit which is to perform an orderly shutdown of baking operations by setting the limit to zero.

Drain Delegate Deprecation

The drain_delegate operation is deprecated.

drain_delegate transfers the free balance of the baker to its consensus key. The purpose is to act as a deterrent against careless handling of the consensus key. With adaptive inflation, bakers no longer have an incentive to maintain a free balance to attract delegations. Instead, they are expected to actively freeze all of their balance in order to maximize their income (except perhaps a few tez to pay fees). Therefore drain_delegate no longer is an effective deterrent and can be removed.

Switchover to Adaptive Inflation

Adaptive inflation is activated by a toggle signal in block headers, similar to the liquidity baking toggle. The signal may be "on", "off" and "pass" where "on" means "I want Adaptive Inflation to be on". The context maintains an exponential moving average of that toggle. The EMA is initiated at 100% "off".

Adaptive inflation permanently kicks in at the end of the first cycle

C when an EMA of 50% of blocks has signaled "on" or "off", and 80% of those have signaled "on" for 5 cycles.

Then, baker's accounts are immediately considered as security deposits according to the following rule:

  • for any baker without deposit limit set, their entire balance becomes
    deposit(b)
    ,
  • for bakers with deposit limit set, the minimum between 10% of their deposit limit or their entire balance becomes
    deposit(b)
    ,

The rights for the cycle C + 1 + PRESERVED_CYCLES + 1 are then calculated based on the Adaptive Inflation calculation of Baking Rights above, and so on for all future cycles.

Bakers will see all of their balance frozen unless they take action before activation to set their deposit limit.

The rights distribution in the first cycle of Adaptive Inflation Baking Rights will look very different than the cycles before. The dominant factor in rights distribution will be the baker's own balance.

RPC & CLI & Encodings & Gas

To be completed.

Appendix: explanation of the Fee Formula

Let's suppose the baker

b has a cobaker
c
.

The cobaker owns

tokBal(b,c) in pseudo-tokens. Shall they withdraw, they would be entitled to
tezBal(b,c)
.

The following holds:

tezBal(b,c)=tokBal(b,c)deposit(b)tokBal(b)

A reward

r is accrued. Now the cobaker owns
tokBal(b,c)
in pseudo-tokens. Shall they withdraw, they would be entitled to
deposit(b,c)
.

The following holds:

deposit(b,c)=tokBal(b,c)deposit(b)tokBal(b)

where:

deposit(b)=deposit(b)+r

We do not want to update the cobaker's pseudo-token balance each time there is a reward. Therefore:

tokBal(b,c)=tokBal(b,c)

Only the baker's pseudo-token balance changes and is increased by

Kfee, therefore:

tokBal(b)=tokBal(b)+Kfee

Consequently we have the result A:

deposit(b,c)=tokBal(b,c)deposit(b)+rtokBal(b)+Kfee

The balance of cobaker

c in tez has increased by the proportion of the reward
r
based on their current share of
deposit(b)
, minus the fee:

deposit(b,c)=deposit(b,c)+rdeposit(b,c)deposit(b)(1f)

or more simply we have the result B:

deposit(b,c)=deposit(b,c)(1+r(1f)deposit(b))

Taking A and B together:

deposit(b,c)(1+r(1f)deposit(b))=tokBal(b,c)deposit(b)+rtokBal(b)+Kfee

Hence:

tokBal(b)+Kfee=tokBal(b,c)deposit(b,c)deposit(b)+r1+r(1f)deposit(b)

Which simplifies to:

tokBal(b)+Kfee=tokBal(b)deposit(b)deposit(b)+r1+r(1f)deposit(b)

tokBal(b)+Kfee=tokBal(b)(deposit(b)+r)deposit(b)+r(1f)

Finally:

Kfee=tokBal(b)(deposit(b)+rdeposit(b)+r(1f)1)

Let's verify with 2 common scenarios:

  1. if
    f=0
    then
    Kfee=0
    . Indeed, the baker does not take a cobaking fee and the rewards are distributed equally between baker and cobakers. The baker's balance in pseudo-tokens needs not change.
  2. if
    f=1
    (100% fee) then
    Kfee=rtokBal(b)deposit(b)
    , indeed, the baker receives newly minted pseudo-tokens whose value in tez is equal to r: the baker pockets the entire reward r regardless how much they actually contribute to the deposit.

Why bother with minting new pseudo-tokens when the fee is 100%? The baker may have cobakers anyway, and these cobakers are entitled to withdraw their contribution to the deposit, though it will be equal to what they did put in.
Also, perhaps the fee has not always been 100%, and the cobaker earned a reward before that.