Does key-value write cost less if it is later deleted from the state in a smart contract?

Viewed 36

If in a Near contract I write to a key in storage, then delete that same key all in one transaction, is the gas cost less than if I were to write to the key and delete it in separate transactions? The reasoning behind it possibly being cheaper is, on the level of the runtime, no change to storage needs to be made if the state is the same before and after the transaction (the intermediate state could be in memory internally)

1 Answers

Currently, the cost is the same. The general rule for smart contract fees is to deduct the gas immediately before the operation occurs, because otherwise if we have delayed cost of a certain operation than someone can create a contract that attempts 10,000 (or some other large number) of operations while it has attached gas for only one. Then once fees are attempted to be deducted the contract will fail, however it will incur 10,000 more CPU cost than what it actually paid for, which can be used to "grind" the blockchain by issuing cheap transactions that congest all the blocks. Even worse, it will break the invariant that the burnt gas reflects the execution time of the block. In this case our blocks will start taking far more than 1 sec to execute creating complex network effects in the consensus.

Storage operations are special compared to other contract operations, because the bulk of CPU computation (writing state into Rocksdb and recomputing merkle hashes) occurs not at the moment when contract call the host function, but when the chunk is finalized. This means that we can delay deduction of the storage costs until the very end of the contract execution, and then if the writing of the key-value was reverted by deletion we can avoid deducting a large fee. There are however caveats:

  • The operation of writing key-value still need to cost something, because just calling a host function and "scheduling" a write of a key-value still incurs some CPU costs, even if they are small. Therefore we need to split key-value fees into two categories: immediate and delayed. This will require a protocol upgrade and will make runtime more complex;
  • DevX can become more unpredictable because we are breaking the common-sense invariant. Currently, the contract can requests how much gas it has burnt with env::used_gas() and developers know that this number can be only increasing. If we make key-value costs lazy, this number will either be sometimes decreasing (when key-value is deleted) or it won't reflect the gas that is about to be burnt;

So protocol upgrade can be considered to make key-value write cost delayed (as long as it follows https://gov.near.org/t/quality-control-for-protocol-api-changes/1941) but there needs to be a proper justification (e.g. EVM will be much cheaper) since there is going to be a trade-off: we will be improving performance at the cost of making runtime more complex (and thus potentially impeding our velocity) and making DevX more confusing.

Related