1

I want to implement my contract in much better way and want to use the inheritence. I wrote the code and i face one problem that i want to access the mapping variable of Contract A in the Contract B. My Code is as below

pragma solidity ^0.5;
import "./ConvertLib.sol";

contract A {
    mapping(address => address[]) public inves;

    function totalInves() public view returns(uint) {
        return(inves[msg.sender].length);
    }

}

The another contract is

pragma solidity ^0.5;
import "./ConvertLib.sol";
import "./A.sol";

contract B is A {
    function total() public view returns(uint) {
        return(inves[msg.sender].length);
    }
}

Contract A has more functions too and it stores the data in the mapping function. I am using Truffle framework so what i tried to do is to call the both function. When i call the function totalInves in the Contract A using truffle it gives me this ( Truffle console) where as i am running testrpc

 truffle(development)> var acont = await A.deployed()
 truffle(development)> var data = acont.totalInves.call({from:acc[0]})
 undefined
 truffle(development)> data
 <BN: 1>

Where as when i execute the contract B function it gives me this

 truffle(development)> var bcont = await B.deployed()
 truffle(development)> var data = bcont.total.call({from:acc[0]})
 undefined
 truffle(development)> data
 <BN: 0>

I am confuse why the same variable is having different result where as it should give the same resultset if i call the total function in contract B.

1

I think possibly you misunderstand inheritance.

When B is A, then A source code is rolled up into B. Here it is as one file:

pragma solidity ^0.5;

contract A  {

      mapping(address =>address[]) public inves;

      function totalInvesCount(address index) public view returns(uint){
        return(inves[index].length);
      }

}

// import "./A.sol"; // You use this if A.sol is a separate file

contract B is A {

}

Not much happening in B. Here's B in Remix to show what's going on.

enter image description here

Notice that B has functions for inves and totalInvesCount (I renamed). Those correspond to the public mapping and function in A that was inherited by B.

Also, note that B was deployed at address 0xbbf.... A was not deployed at all. So B has the functions and the mapping and you can treat them as local "normal" variables/functions in B.

You can deploy A and talk to one directly, but it will have a different address and therefore it's own storage space. You will not get the same values because those contracts would be separate in every way except they are based on the same code.

If you go ahead to do that, then A lands on a different address. I got 0x0dc....

enter image description here

I can talk to it if I want, but it won't have any impact on the B and the B won't have any impact the A.

It's possible you want separate A to be accessible from separate B, so each contract would have its own address and they would communicate. If that is the case, then you don't want inheritance at all. You want composition.

Inheritance and composition look eerily similar. This is what it would look like. Notice the additional concern of informing B about where to locate A. Also notice that we remove the inheritance part. B is not A because we're not using inheritance.

pragma solidity ^0.5;

contract A  {

      mapping(address =>address[]) public inves;

      function totalInvesCount(address index) public view returns(uint){
        return(inves[index].length);
      }

}

// import "./A.sol"; // You use this if A.sol is a separate file

contract B {

    A a;

    constructor(address _a) public {
        a = A(_a); 
    }

    function totalInvesCount() public view returns(uint) {
        return a.totalInvesCount(msg.sender);
    }

}

The following might help you work out if you really want inheritance or composition.

Ask yourself if it's more like "Driver drives Car" or "Hatchback is Car". The former is composition, the latter is inheritance. The former is more compact as it's not necessary to roll up all the code for the car into driver - only knowledge of the controls. The latter is always cumulative, so the contracts will get larger and larger as more code is inherited.

Hope it helps.

  • Thanks for your detail reply, it cleared my concept of inheritance in Solidity. As my contracts are made for one system so I think the best approach would be is to use inheritance and then use the instance which inherits other contracts to call functions of another contracts. – Uahmed Dec 28 '18 at 21:49
2

acont and bcont are 2 separate contracts. They have nothing shared between them.

In the Inheritance section in the docs it says that:

Solidity supports multiple inheritance by copying code including polymorphism.

And a paragraph later that:

When a contract inherits from multiple contracts, only a single contract is created on the blockchain, and the code from all the base contracts is copied into the created contract.

In order to access the same inves data in your code, you should call bcont.total... and bcont.totalInves..., otherwise you read from 2 different data sources.

  • Thanks for your reply. Yes, that's how it will work smoothly and now I have common data. – Uahmed Dec 28 '18 at 21:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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