You have approximately answered your own question. Let's walk through the details and sort out the concerns and syntax.
The requirements for reading a contract are
- Knowledge of the ABI. That can be derived by compiling source code or just given.
- Knowledge of the contract address.
Contract design can assist with the second requirement.
You wouldn't do:
contract A { import "./B.sol"; ...
But, you might do
import "./B.sol";
contract A { ...
And, you could have a function to deploy a new B
:
function createB() public returns(address contractB) {
B b = new B(); // cast b as B, defined by "contract B" in the imported file
return address(b);
}
Since that is a state-changing function, software clients will only get a transactionHash and not address(b)
- that response is only available to other contracts. It can be very useful and is generally recommended to also emit an event for an important state-change such as this. Events are observable by a Web3 watcher.
import "./B.sol";
contract A {
event LogNewB(address creator, address contractB);
function createB() public returns(address contractB) {
B b = new B();
emit LogNewB(msg.sender, b);
return address(b);
}
What if the observer isn't watching? It can be useful to make this discoverable by inspecting the contract. A can keep track of the B instances it deploys:
address[] public bList;
...
bList.push(b);
Altogether ...
import "./B.sol";
contract A {
address[] public bList;
event LogNewB(address creator, address contractB);
function createB() public returns(address contractB) {
B b = new B();
emit LogNewB(msg.sender, b);
bList.push(b);
return address(b);
}
Since bList
is public
, you get a "free" getter that will return the address at a row, roughly equivalent to:
function bList(uint row) public view returns(address) {
return bList[row];
}
Now there are three ways for a Web3 client to construct a list of all the B contracts that were deployed by A. They can listen to event logs, resolve mined transaction hashes and inspect the log arguments, or inspect the bList
. Together with knowledge of ABI for B, the client can:
var instanceB = web3.eth.contract(abi).at(address);
As Julien pointed out, Web3 is indifferent about the method that was used to deploy the contract.
Hope it helps.
p.s. It may be helpful to add a quick function to reveal the length of the bList
, otherwise software clients will not know where the end of the array is. Something like:
function getBCount() public view returns(uint) { return bList.length; }