Try   HackMD

Adaptive Inflation v1.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.

Changelog
1.1 * Use a virtual contract instead of a special operation for cobaking
* Changed right calculation formula per Maxime Reynouard's feedback; also use "free delegation" iso "delegation"
* Added uncobaking staging areas per Alex Eichhorn's remarks
* Added section where 99% of slash amount is burned instead of 50% to prevent cobaking scams
* Acknowledge griefing attack issue in a remark, state it's still being discussed.

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 virtual contract is introduced: the cobaking contract. Any account (manager or smart contract) can call it. It has an entrypoint cobake that takes a strictly positive amount value in mutez as a parameter. It has more entrypoints (uncobake and set_cobaking_reward) described below.

Whenever an account calls the cobake entrypoint, the following happens:

  • if amount is larger than the account's free balance, the operation is backtracked,
  • if the account is not delegating, the operation is backtracked,
  • 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 by calling the cobake virtual contract.

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 calls this virtual contract 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 contract call, 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 by calling the cobake virtual contract.
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) = \sum_{c} deposit(b,c)\)
  • \(delegation(b)\) as the free balance of \(b\) and all delegators of \(b\). This excludes the security deposit.

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)=\begin{cases} deposit(b) & \text{if } deposit(b) > minimalStake \\ 0 & \text{otherwise.} \end{cases}\)

\(totalDeposit = \sum_{b} X(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(9*X(b), delegation(b))\)

\(totalDelegation = \sum_{b} Y(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) = \frac{2 * X(b) + Y(b)}{2 * totalDeposit + totalDelegation}\)

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

It holds that:

\(\sum_{b} bakingRights(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/(100 x))^2\) where \(x\) is \(\frac{totalDeposit}{totalSupply}\).

A different formula is possible, in particular, to discourage griefing attacks. This is still under discussion.

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) = \sum_{c} tokBal(b,c)\)

Calling the cobake entrypoint 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 = k * \frac{tokBal(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) * \frac{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 \(\frac{Y(b)}{2 * X(b) + Y(b)}\) corresponding to free delegation is credited to the baker's free balance ('Contract b)
  • the remaining amount \(\frac{2 * X(b)}{2 * X(b) + Y(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

An entrypoint set_cobaking_fee is introduced in the cobaking virtual contract, taking a numerical value \(f\) as parameter. Any baker active or inactive can call this entrypoint. Any other call is backtracked. 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 \(K_{fee}\) based on the formula:

\(K_{fee} = tokBal(b) * (\frac{deposit(b) + r}{deposit(b) + r * (1 - f)} - 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, \(K_{fee}\) 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.

Uncobaking

Another new entrypoint uncobake of the cobaking virutal contract is introduced. It 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.

In the latter case ,we maintain an uncobake staging area per baker per cycle. A convenience uncobaking staging account is created per baker per cycle, and a Token.transfer moves the unstaking balance from \(deposit(b)\) to the uncobaking staging account. The pseudo-token balance is accordingly substracted from \(tokBal(b,c)\). In case of full cobaking, \(tokBal(b,c)\) is zeroed and deleted from the state.

A new pseudo-token ledger per baker per cycle tracks the individual ownership balances of the unstaging account. Its mechanisms are identical to "Internal security deposit accounting" described above.

An unstaking cobaking area is necessary. Indeed, if bakers were still earning rewards for uncobaking stake, they would be earning without the associated risk of getting slashed for 5 cycles after earnings, violating proof-of-stake.

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

At the beginning of every cycle, the protocol traverses the uncobake staging area for this cycle, and credits the newly unfrozen deposits to the cobakers' free balance.

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.

Slashing

Slashing denunciation events lower the tez balance of \(deposit(b)\) and all cobaking staging areas, in proportion of their balance.

  • 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.

The same rule applies to all cobaking staging areas.

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.

The baker including the slashing denunciation receives 1% of the slashed amount, while 99% is burned.

This is contract to today's implementation where the baker receives 50%. The intent of this change is to discourage cobaking scams, where a baker attracts a large amount of cobaking then subsequently steals 50% of it by denouncing themselves using a different baking address.

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 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) * \frac{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) * \frac{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 \(K_{fee}\), therefore:

\(tokBal'(b) = tokBal(b) + K_{fee}\)

Consequently we have the result A:

\(deposit'(b,c) = tokBal(b,c) * \frac{deposit(b) + r}{tokBal(b) + K_{fee}}\)

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) + r * \frac{deposit(b,c)}{deposit(b)} * (1 - f)\)

or more simply we have the result B:

\(deposit'(b,c) = deposit(b,c) * ( 1 + \frac{r * (1 - f)}{deposit(b)})\)

Taking A and B together:

\(deposit(b,c) * ( 1 + \frac{r * (1 - f)}{deposit(b)}) = tokBal(b,c) * \frac{deposit(b) + r}{tokBal(b) + K_{fee}}\)

Hence:

\(tokBal(b) + K_{fee} = \frac{tokBal(b,c)}{deposit(b,c)} * \frac{deposit(b) + r}{1 + \frac{r * (1 - f)}{deposit(b)}}\)

Which simplifies to:

\(tokBal(b) + K_{fee} = \frac{tokBal(b)}{deposit(b)} * \frac{deposit(b) + r}{1 + \frac{r * (1 - f)}{deposit(b)}}\)

\(tokBal(b) + K_{fee} = \frac{tokBal(b)*(deposit(b) + r)}{deposit(b) + r * (1 - f)}\)

Finally:

\(K_{fee} = tokBal(b) * (\frac{deposit(b) + r}{deposit(b) + r * (1 - f)} - 1)\)

Let's verify with 2 common scenarios:

  1. if \(f = 0\) then \(K_{fee} = 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 \(K_{fee} = r * \frac{tokBal(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.