3

I have a construct like this:

var s = SomeStruct(a, b);
map1[addr1] = s;
map2[addr2] = s;

... and want both maps to point to the same data.
Now if I afterwards do

map1[addr1].field1 = x;

... then map2[addr2].field1 still returns the initial value instead of x - which suggests that 2 copies of the data were created when initially assigning to the maps.

Question: How can I avoid this duplication?

1 Answer 1

4

There's not a simple way to do this directly. From the solidity docs:

The mapping or the dynamic array itself occupies an (unfilled) slot in storage at some position p according to the above rule (or by recursively applying this rule for mappings to mappings or arrays of arrays). For a dynamic array, this slot stores the number of elements in the array (byte arrays and strings are an exception here, see below). For a mapping, the slot is unused (but it is needed so that two equal mappings after each other will use a different hash distribution). Array data is located at keccak256(p) and the value corresponding to a mapping key k is located at keccak256(k . p) where . is concatenation. If the value is again a non-elementary type, the positions are found by adding an offset of keccak256(k . p).

That is, mappings do not contain pointers to values. Mappings are ways to turn arbitrary key into pointers to values. For two different mapping keys to point to the same location in memory, and therefore share an value, would be astronomically unlikely.

But there is a workaround.

Let map1 and map2 be mappings of addresses to uints. Then, use either a dynamic array of someStructs or a mapping of uints to someStructs. Store the actual structs in this latter array or mapping. Use the uints of map1 and map2 as a kind of homemade pointer to said structs. This should not use all that much more gas in the end.

3
  • Sounds like a good idea, I'll immediately try that. Do you have an opinion about array or mapping being the better solution for the actual structs? Does it make a difference that most items will be deleted after a while?
    – didi_X8
    Jul 29, 2017 at 16:55
  • 1
    If you're going to be doing deletion, I suggest mappings. It is possible, but complicated, to delete from the middle of an array, while deleting from mappings is trivial. The only real downside is that you cannot iterate through a mapping. Jul 29, 2017 at 20:44
  • @Matthew Schmidt, , just so I'm clear, if I have a fat struct with a lot of data, to store the same struct in two different mapping wont consume a 2x memory, just the overhead of two rather one pointers to the struct memory?
    – GGizmos
    Jul 25, 2022 at 5:45

This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .