We currently charge quite a lot of gas for new storage; new_storage_per_byte: 63, meaning over 2000 gas for a new 32 byte slot. With the old fixed-width storage system this was feasible, but dynamic storage makes this less nice.
We charge for new storage to limit state growth. Gas is not the ideal way to do this, as gas is meant to constrain execution time. Ideally we would charge for storage directly.
Secondly, it would be nice if the contract itself, not the script calling it, would buy the extra storage capacity. This would make it cleaner to amortize costs across calls, and to pay for storage capacity up-front. And perhaps it could be sold back for a refund, too.
Considerations for dynamic storage
One problem with dynamic storage is that writes would be way faster than reads, but they require reading the value anyway to check how much the size increased, just to charge for the new bytes (this isn't implemented yet). Since in many cases the value is read first, before writing to it, caching these reads would be a nice way to reduce the cost. This is also something that hot/cold storage caching likely requires (#983).
Even with the legacy storage instructions, clearing a slot (using SCWQ) would not refund the cost. With dynamic storage there's very little need to ever actually clear a slot. Moreover, since there's currently no way to refund freed-up storage, there's an incentive for the contracts to never let go of any storage space claimed.
Moreover, it's currently pretty complex to properly amortize the storage costs across multiple contract calls. Some apparently random call might need to pay for quite a bit of extra just because they happen to call at the moment when new storage allocation is needed.
Possible solutions
- Design an alternative way to charge for storage, instead of gas. Maybe a policy to pay in assets, directly?
- We could fall back to charging gas for backwards compatibility reasons
- Keep a global storage quota counter per contract, so that freed-up storage would be retained there * Would this hurt parallelism?
- Perhaps allows some nice database optimizations?
- Keep the current system as-is, and let contract developers deal with these complications
- Never truncate storage slots, and instead just keep them zero-extended at maximum length ever reached
- Refund gas on instructions that free storage
- Dangerous implications on execution time constraints if an instruction can be gas-positive
- Doesn't much help with abovementioned problems
We currently charge quite a lot of gas for new storage;
new_storage_per_byte: 63, meaning over 2000 gas for a new 32 byte slot. With the old fixed-width storage system this was feasible, but dynamic storage makes this less nice.We charge for new storage to limit state growth. Gas is not the ideal way to do this, as gas is meant to constrain execution time. Ideally we would charge for storage directly.
Secondly, it would be nice if the contract itself, not the script calling it, would buy the extra storage capacity. This would make it cleaner to amortize costs across calls, and to pay for storage capacity up-front. And perhaps it could be sold back for a refund, too.
Considerations for dynamic storage
One problem with dynamic storage is that writes would be way faster than reads, but they require reading the value anyway to check how much the size increased, just to charge for the new bytes (this isn't implemented yet). Since in many cases the value is read first, before writing to it, caching these reads would be a nice way to reduce the cost. This is also something that hot/cold storage caching likely requires (#983).
Even with the legacy storage instructions, clearing a slot (using
SCWQ) would not refund the cost. With dynamic storage there's very little need to ever actually clear a slot. Moreover, since there's currently no way to refund freed-up storage, there's an incentive for the contracts to never let go of any storage space claimed.Moreover, it's currently pretty complex to properly amortize the storage costs across multiple contract calls. Some apparently random call might need to pay for quite a bit of extra just because they happen to call at the moment when new storage allocation is needed.
Possible solutions