2

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
    }
}

1 Answer 1

4

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

1
  • 1
    You rock Rob! This is just what I needed and thanks for the pointers too.
    – thefett
    Commented May 7, 2017 at 21:09

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.