0

When I run the code in remix, The state variable requesting is overwritten after a call to addSimpleStruct(), which makes it impossible to add another struct because of the require statement. Why would this be and how can I make it so the address in requesting persists throughout the contracts entire lifetime.

pragma solidity ^0.4.21;


contract test {
  address public requesting;

  struct simpleStruct {
    bytes32 desc;
    uint256 startTime;
  }

  struct itmap
  {
    mapping(bytes32 => IndexValue) data;
    KeyFlag[] keys;
    uint size;
  } 

  struct IndexValue { uint keyIndex; simpleStruct value; }
  struct KeyFlag { bytes32 key; bool deleted; }

  itmap data;

  function test() public {
      requesting = msg.sender;
  }

  function addSimpleStruct(bytes32 key, bytes32 _desc) public { 

    require(msg.sender == requesting); 

    simpleStruct storage newStruct;
    newStruct.desc = _desc; 
    newStruct.startTime = now; 
    insert(data, key, newStruct); 
  }

  function insert(itmap storage self, bytes32 key, simpleStruct storage value) internal returns (bool replaced)
  {
    uint keyIndex = self.data[key].keyIndex;
    self.data[key].value = value;
    if (keyIndex > 0)
      return true;
    else
    {
      keyIndex = self.keys.length++;
      self.data[key].keyIndex = keyIndex + 1;
      self.keys[keyIndex].key = key;
      self.size++;
      return false;
    }
  }
}
1

I found the bug.

  function addSimpleStruct(bytes32 key, bytes32 _desc) public { 

    require(msg.sender == requesting); 

    simpleStruct storage newStruct; <-----
    newStruct.desc = _desc; 
    newStruct.startTime = now; 
    insert(data, key, newStruct); 
  }

If you remove it, and declare in the contract simpleStruct newStruct, it will work.

Now, why it doesn't work? Right now, I am trying to understand exactly why, but my first guess, I could be wrong on this one, probably am, but I think since it's written to storage, it's written at slot 0, and "crushes" the value of requesting? But I doubt...

1
  • Since newStruct is not initialized it will reference the first slot of storage, which is requesting. So modifying it will override requesting. – Ismael Apr 14 '18 at 19:29
0

Eli and Ismael are exactly right.

This syntax...

simpleStruct storage newStruct;

causes an "uninitialized storage pointer" error in 0.5.x compilers. You need to initialize with = to set it to something, otherwise it will default to slot 0 in memory, which is a horrible thing because it mean overwriting whatever else is there.

This is a confusing and scary topic. Have a look over here: https://blog.b9lab.com/storage-pointers-in-solidity-7dcfaa536089

Hope it helps.

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.