Baking Accounts proposal contains unexpected breaking changes

Summary

Ongoing testing and review of baking accounts has uncovered some important and previously undocumented breaking changes (see the section on breaking changes in the TZIP for Baking Accounts) in the baking account proposal.

These issues are significant, and affect the functionality of both existing and future smart contracts; they are detailed below. Bakers should please these carefully when casting their vote.

We believe Baking Accounts should be postponed until a thorough audit of functionality is complete, or an alternative implementation produced. The version of Florence without baking accounts is a safer choice.

SOURCE and SENDER changes

Consensus keys can not be SENDER (or SOURCE)

After the migration to Florence, a baker’s consensus key can never be SENDER (or SOURCE). This means they cannot authenticate themselves in the usual way to smart contracts (through SENDER, though some contracts incorrectly use SOURCE).

This includes all current delegate keys, including those of inactive delegates. These keys will become consensus keys upon the migration.

In particular, if any tokens (FA1.2, FA2, or similar) are sent to consensus keys, or already owned by delegates upon the protocol migration, these tokens will be locked, unless an allowance or an operator was set up before the migration.

Any manager.tz contracts (like those created automatically from originated “accounts” during the Babylon migration) which are managed by delegates

  • will become inoperable, and
  • their tez will be locked,

unless emptied before the migration. Roughly 85,000 ꜩ are currently in this state.

The “bakers registry” contract would need to be updated and redeployed to account for this, since it expects a baker to use their key hash as SENDER at least once (to set a “reporter” address). A new version of this contract should use the baker hash instead.

There could be other examples. For instance: any contract with an “owner” or “admin” address set to a delegate key would become impossible to administrate upon the protocol migration.

Rotating the consensus key out by setting a different one does not solve this problem. Any consensus key is permanently unable to be SENDER or SOURCE, until a future protocol fixes the problem.

SOURCE might not be an implicit account

The SOURCE instruction normally returns the address of the account responsible for invoking the call in the first place. Since the Babylon upgrade, the invariant that SOURCE is always an implicit account has held.

If a baker consensus key is used to initiate a transaction, the SOURCE instruction in Michelson will return the baking account address, and not the address of an implicit account.

Code that relies on SOURCE necessarily being an implicit account would be broken. We are not currently aware of any contract that relies on this behavior.

SOURCE = SENDER does not imply a top-level call

The interaction with SENDER is potentially more problematic. In the case of the consensus key being used as part of a multisig call to trigger the baking contract to send out transaction, the instruction SENDER would also return the baking account address.

A common pattern is to use SOURCE = SENDER to ensure that a transaction is happening at the top-level and cannot be interleaved with other calls. With baking accounts, it would no longer be true that SOURCE = SENDER implies a top-level call. Indeed, using the consensus key to trigger a baking account to release a series of transactions creates a non-top-level call where SOURCE = SENDER nonetheless.

However, given the change to the DFS calling convention in Florence, it’s no longer possible to use a top-level call to interleave transactions, which seemingly mitigates the issue.

A design where SOURCE represents the implicit account associated with the consensus key and SENDER the baking account would be more consistent. It could be folded in later on, so long as no application comes to depends on the semantics detailed above.

Calls to implicit accounts can fail

Calls to implicit accounts never fail when the burn limit is sufficiently high, the gas limit is sufficiently high, and the amount is positive.

In baking accounts, when a baker rotates to a new key, there is a period of time where the key is pending. During that period, transfers to that implicit account fail.

This can break contracts. For instance, the auction contract from tzcolors breaks as follows: A user could maliciously create an implicit account, bid on an item, delete the implicit account, and then register the account as a consensus key. If someone tries to outbid them, the transaction would involve a transfer back to the current winning bid, which would fail as it is the pending consensus key of a baking account. This would make it impossible to outbid the malicious bid.

While it might be possible for tzcolors to migrate their auction contract in the interim, the functionality could not be replicated with the baking account proposal. Instead, participants who are outbid would need to manually claim their bids back. Other versions of this contract deployed on the chain could face similar issues.

CREATE_CONTRACT fails with some legacy code

The baking account proposal changes the Michelson instruction SET_DELEGATE to take a option baking_hash instead of a option key_hash. Contracts which rely on a key_hash are marked as legacy, and can continue to use the old instruction, but new contracts can only use the new version of the SET_DELEGATE instruction.

This breaks contracts that work as contract factories, if they try to automatically deploy new contracts with the legacy SET_DELEGATE instruction. This includes Kolibri and wXTZ. Both contracts are upgradeable and could adapt to the change, but the activation of the baking account proposal could distrupt their operation.

Conclusion

Due to these breaking changes, we believe that

A future version of Baking Accounts which does not break current contracts and preserves important invariants is possible, and should be developed to take its place.

Baking accounts is a feature whose design and implementation have proven a significant challenge, because:

  • it requires extensive code updates; and
  • it changes the delegation system and thus how Tezos as a blockchain operates.

This underscores that Tezos development needs to provide more room for specifying precisely and systematically how new features integrate with the existing codebase. The Tezos Improvement Proposals (TZIPs) process is a much-needed step in this direction, and we are acting to integrate this even more tightly into our development process.

By conditioning the implementation and integration of new features on the formulation of comprehensive, community-reviewed specifications, we increase our chances of catching issues like those presented in this article. From this perspective, the Baking accounts TZIP was a missed opportunity, and we believe it is in our interest as a community to allocate more time and attention to this process.

14 Likes

This includes Kolibri and wXTZ. Both contracts are upgradeable and could adapt to the change, but the activation of the baking account proposal could distrupt their operation.

In order for us to deploy any replacements to our OvenFactory, we’d need to undergo a security review (especially given the $7M+ worth of XTZ in ovens) of the changes to our replacement contract, which given global security review backlog doesn’t seem easily achievable before F goes live (not to mention quite expensive and time consuming), so I suspect we’re going to put some resources behind reaching out to bakers to try to sway the vote for no baking accounts. I’m definitely not a happy camper that there’s even a slight possibility (recommended or not, this helps the very people voting) that we may suddenly have to pour a lot of our resources into working around this issue.

This breaks contracts that work as contract factories, if they try to automatically deploy new contracts with the legacy SET_DELEGATE instruction.

Also, where is this documented to be “legacy”?

There are no instructions listed on the michelson reference docs’ “Deprecated Instructions” - Michelson Reference, and the instruction itself mentions nothing about this - Michelson Reference.

3 Likes

The simplest and safest solution is probably not to allow one contract to call another and just raise the current gas limit even further.