solidity – How to Push and Pull Data from a Storage Contract?

contract-designsoliditystoragestruct

Is there any way I can have a smart contract that stores the a value and name and then is callable from another smart contract? Something like this..(but that works)

Contract D {
    struct Document{
      string name;
      uint value;
    }

    function StoreDocument(bytes32 key, string name, uint value) returns (bool success) {
     var doc = Document(name, value);
     documents[key].push(doc);
     return true;
    }
}

And then I would like another contract to take the key, contract address, and name and be able to return the value to use in a contract. Any help would be great.

Contract E {
    function RetrieveData(address ConDadd, bytes32 key, string name) {
    //some funciton to get the data from Contract D
    }
}

Best Answer

I started with your example and adapted it until it works. A few pointers I noticed while doing it.

struct defines a Type. You have to cast a Variable with that Type to storage values. mapping is the tool for organizing instances by unique key.

I changed the Type of name to bytes32 because it's not possible to pass strings between contracts at this time.

E will need knowledge of the ABI for D so it can make calls. D is in the same source file, so the compiler can "see" it when it encounters this line that casts a variable as type "D".

D d;

E will also need to know the address of "the" D instance it should be talking to. The constructor for E expects an address passed in when it gets deployed.

I made the mapping public so there's a "free" getter function called documentStructs() and it expects only the key passed in. It returns the two values stored.

pragma solidity ^0.4.6;

contract D {

  // This is a Type
  struct DocumentStruct{
    // Not possible to pass strings between contracts at this time
    bytes32 name;
    uint value;
  }

  // This is a namespace where we will store docs of Type DocumentStruct
  mapping(bytes32 => DocumentStruct) public documentStructs;

  // Set values in storage
  function StoreDocument(bytes32 key, bytes32 name, uint value) returns (bool success) {
   documentStructs[key].name  = name;
   documentStructs[key].value = value;
   return true;
  }

}

contract E {

  // "d" is of type "D" which is a contract ^
  D d;

  // Define the Type in this context
  struct DocumentStruct{
    bytes32 name;
    uint value;
  }    

  // For this to work, pass in D's address to E's constructor
  function E(address DContractAddress) {
    d = D(DContractAddress);
  }

  function RetrieveData(bytes32 key) 
    public
    constant
    returns(bytes32, uint) 
  {
    // Declare a temporary "doc" to hold a DocumentStruct
    DocumentStruct memory doc;
    // Get it from the "public" mapping's free getter.
    (doc.name, doc.value) = d.documentStructs(key);
    // return values with a fixed sized layout
    return(doc.name, doc.value);
  }
}

There are all sorts of non-obvious data organization considerations that can be a bit of a struggle in the early stages. It may be helpful to look at the strengths and weaknesses of different patterns unfolded over here: Are there well-solved and simple storage patterns for Solidity?

Here is the above in Remix to show it working.

Hope it helps.

enter image description here