Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Solving state staking issue #124

Open
evgenykuzyakov opened this issue Oct 9, 2020 · 5 comments
Open

Proposal: Solving state staking issue #124

evgenykuzyakov opened this issue Oct 9, 2020 · 5 comments

Comments

@evgenykuzyakov
Copy link
Contributor

Solving state staking issue

Background

With the current state staking pricing, the cost of storing 100 bytes of data is 0.01 NEAR.

Storage stake

A fungible token contract will stop functioning once the total state stake exceeds account balance.
This may break the logic of some contracts that rely on the fact that the transfer method doesn't fail.
So fungible token standard charges small amount of
extra NEAR deposit for every function call in order to cover increased storage cost.

If we attach extra NEAR for every function in fungible token, it breaks the DevX.
Because now exchange contracts that wants to transfer with fungible token, has to attach extra NEAR.
The exchange doesn't want to pay from their balance, so it will ask the user to pay for this, but the
refund will go to exchange, so the exchange needs to return to a user. It creates a deep chain of
extra deposits for every function calls with complicated refunds.

Ethereum EVM doesn't have this issue, because the storage increase comes from gas.
But because our compute is cheaper than ethereum, it possible to increase the state size faster
than the persistent state of the network. It'll be possible to exceed the storage in the long term.

Research

At the research meeting, we had a few options on how to address the issue:

  1. Introduce an extra field on a function call action to pay for the increased storage in bytes. Requires large Runtime changes and complicates DevX.
  2. Shared token standard. It requires a code to be deployed on user's accounts and they can transact. Requires large Runtime changes.
  3. Register account within a fungible token contract. One time payment, but doesn't address global DevX.
  4. Generic storage contract standard that a user controls. Can be used to share state and storage across multiple contracts, but paid by user. Complicates the DevX by increasing number of cross-contract calls and async storage.
  5. Cancel state staking and price the cost of writing new bytes in gas. Similar to Eth model (maybe with refunds). It has a lot of changes and may have negative side-effects. May be also abused at NEAR scale.
  6. Reduce the price of state staking by 100X. Be able to use gas to convert into new storage. Requires Runtime changes for gas -> state stake conversion.
  7. Reduce the price of state staking by 100X but only for the contract state with gas -> state stake. Keep account/access_keys/contract pricing of storage. Requires Runtime changes as well, but has some benefits comparing to the previous item.
  8. Allow to write into storage with expiration. This operation may be cheaper than persistent storage write. Requires Runtime changes and trie changes.
  9. Lending of storage, makes storage writing cheaper without bloating the cost. But may have negative side-effects and unclear how to implement.

After the discussion we've decided to explore (7).

Research meeting video recording: https://drive.google.com/file/d/1CIbj89DXWXUWNTVJI42OqWEmFvU0tYma/view?usp=sharing

Proposal

  • Split contract storage usage and non-contract storage usage.
  • Reduce the price of contract storage usage by 100X.
  • Introduce a new runtime host method to convert gas into tokens to cover storage stake increase.

The goal is to be able to write storage and cover the persistent storage stake only from gas.
Currently, you need 1T gas to pay for 1 byte of state stake at minimum gas price.
If we decrease the cost by 100X, then 1T gas will be able to pay for the 100 bytes.

Considering the contract has a reward of 30% from the burnt gas, this operation is very similar.
Let's say a contract burns 1T gas as the minimum gas price, it will result in being able to store
extra 30 bytes.

We can make a decision whether to allow burn gas for storage increase to receive a reward at a higher percentage or just keep it as is to not adjust economics.

For example if we consider this change and the new fungible contract implementation. In order to do a transfer to a new account, a
contract has to get a storage for extra 69 bytes. So it needs to regularly burn 2.3T gas.

Drawbacks

Biggest drawback is the potential state size increase due to cheaper state stake.

With the current pricing the maximum state is 10T bytes if all tokens are used for state stake.
With the proposed change, the maximum state can potentially grow to 1000T bytes.

Another drawback is the changes required to split the contract storage usage vs non-contract storage usage.

Alternative

Just drop the price of storage stake by 100X. No changes needed for the runtime, considering they burn gas enough gas during regular operations.

We can get this done fast with a simple protocol upgrade and it will address most of the problems.
It's unclear whether this alternative is worse than the proposed solution.

@MaksymZavershynskyi
Copy link
Contributor

Expanding on (7) I suggest the following:
We add two changes:

  • Have two storage prices: fixed price per account, and price per byte of the contract state;
  • Limit the size of the contract state.

If we limit the size of the contract state to be 10MiB and make creation of a single contract require staking 200 NEAR then it will limit the total state to 50Tb, independently on what is the price per byte of a contract state.

@MaksymZavershynskyi
Copy link
Contributor

Re @mfornet

Regarding the approach from Max to put a hard limit on the contract size, Evgeny pointed out that someone can spent enough NEAR to fill the full state and make it unusable.

This problem already exists today in a different form. If contract is not implemented carefully its users can increase state without staking tokens, and at some point contract will not have enough staked tokens to function.

Additionally, limiting contract state has the following benefits:

  • It incentivizes user to shard their contracts;
  • It is easy to have this limit early and then drop it in a year or so if we have a better solution. It will be very difficult to introduce this limit later if we discover that we need it anyway for some other reason;
  • It leaves opportunity to do efficient dynamic resharding later.

@evgenykuzyakov
Copy link
Contributor Author

evgenykuzyakov commented Oct 12, 2020

Having a limit on the contract state effectively blocks the contract from processing further transactions, so it's not much different from being blocked someone who fills the storage with random data.

If a developer needs to think about the maximum state right now, then we are making it even more complicated than just to think about the capital. I'm pretty sure that once we hit one account congestion, it will be a better motivation than introducing a state limit. But it will also allow contracts to react by sharding them once the time arrives.

@bowenwang1996
Copy link
Collaborator

Cancel state staking and price the cost of writing new bytes in gas. Similar to Eth model (maybe with refunds). It has a lot of changes and may have negative side-effects. May be also abused at NEAR scale.

@evgenykuzyakov could you remind me what the abuse is here (assuming we only do this for contract storage)?

@norwnd
Copy link

norwnd commented Aug 16, 2023

Cancel state staking and price the cost of writing new bytes in gas. Similar to Eth model (maybe with refunds). It has a lot of changes and may have negative side-effects. May be also abused at NEAR scale.

@evgenykuzyakov could you remind me what the abuse is here (assuming we only do this for contract storage)?

Would be also curious to know what the actual concerns for getting rid of staking in favor of charging written bytes at sufficient/appropriate rate (besides implementation complexity) are, the devX/UX is definitely simpler without storage staking. I guess the downside is - storage becomes more expensive overall (because 1-time fee you'd charge must be high enough to account for the fact that it's permanent - and you'd wanna err on the safe side).

For completeness, looks like the continuation of this discussion resides at gov.near.org and there is a relevant video-call discussion and an older design session too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants