5

im wondering if it still makes sense to remove entries from mappings in ethereum contract. It seems like initially there was a relatively big benefit of cleaning up the storage but from what i read its no longer like that.

For example Eip-3529 reduced refund.

Im desigining some cross-blockchain protocol. The assumption is that some requests are created on ethereum then they are brought to some other blockchain and eventually their statuses/results are brought back to L1. At this point the requests could be removed from L1 but i went thought multiple discussions that suggests that these days it doesnt really pays off. On the other hand im facing an issue where L1 is able to process only limited amount of request statuses in single cal because processing them is quite pricey...

So should i look into that kind of optimization or its rather dead end these days.

1
  • 1
    As you said, probably not worth it nowadays. But this should be easy enough to test - just write a simple contract and deploy on Remix or so. Commented May 6 at 5:44

4 Answers 4

4
+50

For you, as a protocol, it's not worth it. The EVM ecosystem, at some point, will need to address the state bloat of ETH, but as of today, it's a tomorrow problem.

Since getting access to data in a mapping requires constant gas, it doesn't matter how many elements are stored in your mapping. 1, 5, 200, it doesn't matter, gas to access/store from/to the mapping with be constant.

If costs are the biggest concern, then removing elements from a mapping costs extra gas, with no added benefit.

This might change in the future if incentives are created to clean up state bloat, but as of now, no such incentives exist.

Now... If you're doing something crazy like looping through your mapping as a list, it might make sense to remove elements. But I hope you're not doing that.

1
  • 1
    Maybe expand a bit on why it's not worth it for the protocol? The question was about possible refunds. I wouldn't just shove the problem for the future when data gets possible pruned. Commented May 7 at 5:14
4

Yes.

EIP-3529 reduced refund amounts because those amounts were exploited to create a parallel mechanism of managing GAS out of the initial EF's intents (i.e., the GasToken project, which allowed storing GAS when prices were low and using it when prices were high).

The reduction introduced by the EIP killed that technique, and now, the only reason for refunds is to incentivize people to clean the state. How? By reducing the costs of normal function calls if they do it. And that cost reduction is something you always want to apply.

So, if, for example, while executing your function, you are sure a value will never be used again (e.g., it's a nonce, OTP, or something similar), you can set it to 0 to reduce the overall cost of that function.

Without that set to 0 operation, the overall cost of your function would have been higher.

Because saving GAS while preserving the same behavior is always a good thing, removing unused entries can still be a viable technique for achieving that goal.

To be clearer, below is a code example.

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;

contract leveraging_EIP_3529 {

    mapping(uint256 => address) public list;
    uint256 public counter = 0;
    address public FAKE_ADDRESS = 0x1212121212121212121212121212121212121212;

    event addressReadEvent(address indexed myAddress);

    constructor() {
        list[0] = FAKE_ADDRESS;
    }

    /**
     * This function costs 52,572 GAS.
     * If you remove the set to 0 line, the cost of this function INCREASES to 54,170 GAS.
     */
    function saveNewValueAndCleanThePreviousState() public payable {
        // Important: read/use the value you want to clean, or there's not gain in cleaning the state
        emit addressReadEvent(list[counter]);

        //Clean the state
        list[counter] = 0x0000000000000000000000000000000000000000;

        counter++;
        list[counter] = FAKE_ADDRESS;
    }

}

There is a single function that costs 52,572 GAS. If you remove line 25 (set to 0x0), you are no longer cleaning the state, and the cost of the function increases to 54,170 GAS.

It's important to note that while the function's execution cost increases the more operations you do - it's 36,308 GAS with line 25 vs. 33,106 GAS if you remove it - cleaning the state grants you a refund at the end of the execution - 4800 GAS in this case. This refund reduces the overall transaction cost.

Here is the cost breakdown.

> Without cleaning the state:

   base:          21000
   calldata:    +    64
   execution:   + 33160 <-- cheaper execution
   refund:      -     0 <-- no refund
   total:       = 54170 

> Cleaning the state:

   base:          21000
   calldata:    +    64
   execution:   + 36308 <-- more costly execution
   refund:      -  4800 <-- refund
   total:       = 52572 <-- overall cheaper tx
3
  • How does this make sense for a mapping though? Commented May 8 at 16:03
  • 1
    if you are not going to use that mapped value anymore, setting it to 0 reduces the cost of the current operation (you need to do inside another operation, not in a dedicated one) Commented May 8 at 16:46
  • edited the answer with a code example Commented May 8 at 17:24
3

The decision to remove entries from mappings in Ethereum contracts depends on various factors, including the specific requirements of your protocol, the anticipated volume of requests, gas costs, and the overall design considerations. While there may have been benefits to cleaning up storage in the past, recent changes like EIP-3529 reducing refunds have indeed altered the cost dynamics.

In your cross-blockchain protocol, where requests are created on Ethereum and processed on other blockchains before returning to L1, optimizing gas costs and contract storage usage is crucial. While removing entries from mappings can help manage storage costs, it's essential to weigh this against the gas costs associated with removing and reorganizing data in the contract.

If your L1 is struggling to process a large volume of request statuses due to gas costs, optimizing storage usage could still be beneficial, especially if it helps reduce the gas costs associated with processing requests. However, it's essential to consider whether the potential savings in gas costs outweigh the costs of managing and updating mappings.

Additionally, consider alternative optimization strategies, such as batch processing, where multiple request statuses are processed in a single transaction, or implementing gas-efficient data structures like arrays or linked lists instead of mappings.

Ultimately, the decision should be based on a comprehensive analysis of your protocol's requirements, gas costs, and the trade-offs between storage optimization and gas efficiency. It may be beneficial to conduct gas cost simulations and perform thorough testing to evaluate the impact of different optimization strategies on your protocol's performance and cost-effectiveness.

1
2

Yes, It makes even more sense to use merkle trees instead of mappings. Please reduce the state bloat and do the good for the ecosystem, in general.

Here is a thread on Hash lists vs merkle trees: https://stackoverflow.com/questions/53804660/merkle-tree-vs-hash-list.

In summary, merkle trees are much lighter in data size.

Here is a great introduction article to merkle trees or hash trees: https://moosecode.nl/blog/introducing_merkle_map.

So, what is a Merkle Tree, otherwise known as a Hash Tree? It is a binary tree, where the leaves are representing some data, maybe a file, or in our case, a map. The nodes of the tree also have hashes, which we calculate by combining the hashes of the child nodes, and hashing that. This continues up the tree until the root node only has one hash, representing the entire tree.

Much more interesting: we can tell, by starting at the top and working our way down, where the differences are in two trees by comparing the hashes. In fact, we can find a single difference in constant time! Now we’re talking!

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.