2

I am trying to reduce code complexity by using inheritance. I was wondering if it is possible to share data store members like arrays or mapping between deployed base and derived contracts.

In other words, I was wondering if it is possible to modify the derived lookup contract using add, but get the same result with the base lookup contract getLookupById. Do I need to store the mapping in a separate contract?

pragma solidity ^0.4.11;

contract BaseLookup {

    address owner;
    function BaseLookup() { owner = msg.sender; }

    struct Lookup {
        uint id;
        string name;
    }

    mapping(uint => Lookup) lookupById;

    function getLookupById(uint _id) public constant returns (uint, string) {
        return (lookupById[_id].id, lookupById[_id].name);
    }
}

contract DerivedLookup is BaseLookup {

    function add(uint _id, string _name) public {
        Lookup memory newLookup;
        newLookup.id = _id;
        newLookup.name = _name;

        lookupById[newLookup.id] = newLookup;
    }
}

Remix screenshot

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
Titu
  • 379
  • 3
  • 13

1 Answers1

2

Its possible inheritance isn't the solution, but it depends on the end goal.

In a case where B is A, A would not generally be deployed, but as you've seen, B would acquire all of its state variables and functions. This is a way to modularize and compartmentalize code and you can use well-solved base contracts without cluttering up your app's main contract. Consider:

contract MainMapp is Owned, Pausible, Managed, Factory {}

Those four base contracts would be useless on their own, but the MainApp can acquire a lot of functionality without getting unwieldy.

There is a different pattern you might find more appropriate for your use-case: Separate but related contracts that form a larger system. For example, you might have a Storage contract and then have separate "client" contracts that rely on it for object persistence. This wouldn't be inheritance.

There's a lot wrong with this example, but I kept it as close as I could to yours while still showing the other approach.

pragma solidity ^0.4.11;

contract BaseLookup {

  struct Lookup {
    uint id;
    bytes32 name;
  }

  mapping(uint => Lookup) lookupById;

  function setLookupById(uint id, bytes32 name) public returns(bool success) {
    Lookup memory lookup;
    lookup.id = id;
    lookup.name = name;
    lookupById[id] = lookup;
    return true;
  }

  function getLookupById(uint _id) public constant returns (uint, bytes32) {
    return (lookupById[_id].id, lookupById[_id].name);
  }
}

contract ClientLookup {

  BaseLookup b;

  function DerivedLookup(address baseLookupAddress) public {
    b = BaseLookup(baseLookupAddress);
  }

  struct Lookup {
    uint id;
    string name;
  }

  function set(uint id, bytes32 name) public returns(bool success) {
    return b.setLookupById(id, name);
  }

  function get(uint id) public view returns(uint  theId, bytes32 name) {
    (theId, name) = b.getLookupById(id);
    return (theId, name);
  }
}

To use it, first deploy a BaseLookup contract and copy the address, then deploy a ClientLookup and pass Base's address into the constructor.

Here it is in Remix to show it working:

enter image description here

You can avoid storing duplicate information by removing the id from the struct. Have a look over here for examples of how to organize state storage: Are there well-solved and simple storage patterns for Solidity?

Hope it helps.

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
  • Thank you very much @Rob Hitchens for such detailed response and sharing the screenshots with the solution. I had started with your UserCrud example. Thank you for helping us learn. – Titu Dec 10 '17 at 20:13