Consider the case where I want to get the elements of a struct via a public mapping from product contract to price contract:

contract Product{  
    struct prod{  
        string name;  
        uint id;  
        bool status;  
    }  
    mapping(uint => prod) public products;

    function updateStudent (string n, uint ID) {
      products[ID].n = "Temp";
      products[ID].status = true;
    }
}

At this point, I would like to access the elements of the mapping from a different contract:

contract ProductList {
    address productAddr;
    string p_name;
    uint p_id;
    Product p;
    function ProductList(address addr) {
        productAddr = addr;
        p = Product(addr);
    }

    function readProduct (uint u) returns (bool c) {
      p_id = p.products[u].id;
      p_name = p.products[u].name;
      c = true;
    }
}

In the above scenario, I am always getting the error: Indexed expression has to a type, mapping or array (is function...). Any suggestions would be greatly helpful!

  • What if I have another mapping inside a mapping? Say,mapping(uint => mapping(uint => ProductStruct) public productStructs; How can I access the element of the ProductStruct from the outer contract? Thing like p.getproduct(u1)(u2) doesn't work. – Roman Lashta Oct 18 at 13:53
  • That's a good question. We should observe the board rules so we don't anger the mods. Why not post it as a new question with a concise example of a contract would like to access from another contract? – Rob Hitchens B9lab Oct 18 at 16:57
up vote 11 down vote accepted

Main issue is you're calling a function in the foreign contract, so you use () instead of [].

Changed string to bytes32 so contracts can communicate. Also various touchups while I debugged it. bytes32 is more "native" and efficient, so it's generally best to do type conversion in the front-end.

I noticed the original concept was "ListProducts". Seems to be leading toward an indexed list of the mapped structs, so this might help: Are there well-solved and simple storage patterns for Solidity?

pragma solidity ^0.4.6;

contract Product{ 

  struct ProductStruct {  
    bytes32 name;  
    bool status;  
  }  

  mapping(uint => ProductStruct) public productStructs;

  function updateProduct(bytes32 name, uint ID) returns(bool success) {

  // following seems more like the intent. p[ID].n isn't valid

    productStructs[ID].name = name;
    productStructs[ID].status = true;
    return true;
  }
}

contract External {

  Product p;

  function External(address addr) {
    p = Product(addr);
  }

  function readProduct(uint u) constant returns(bytes32 name, bool status) {
    return(p.productStructs(u));
  }
}

Hope it helps.

  • What do you mean by "Changed string to bytes32 so contracts can communicate"? – JohnAllen Aug 20 '17 at 17:26
  • 1
    string is a variable length field that can't be passed between contracts. – Rob Hitchens B9lab Aug 20 '17 at 17:31

you can alternatively activate ABIEncoderV2 and use

a getter which will return the struct for you as follow

pragma experimental ABIEncoderV2;


function getproduct(address _adress)returns (player){
    return players[_adress];
}


  function readProduct (uint u) returns (bool c) {
      p_id = p.getproduct(u).id;
      p_name = p.getproduct(u).name;
      c = true;
    }

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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