2

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?

3

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.

  • 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 '17 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. – Matthew Schmidt Jul 29 '17 at 20:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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