10

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!

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
skarred14
  • 945
  • 1
  • 9
  • 18
  • 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 '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 Oct 18 '18 at 16:57

2 Answers2

18

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.

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
1

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;
    }
Badr Bellaj
  • 18,780
  • 4
  • 58
  • 75