[Ethereum] Accessing a public mapping within a contract from a different contract

contract-developmentsolidity

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!

Best Answer

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.

Related Topic