1

I have a contract that creates sub-contracts, I store these child contracts in an array that's mapped to the senders address

contact MyContract {
  mapping(address => MyChildContract[]) private children;

  function createChild(string memory name) public {
    MyChildContract child = new MyChildContract(name);
    children[msg.sender].push(child);
  }

  function getMyChildren() public view returns (MyChildContract[] memory myChildren) {
    return children[msg.sender];
  }
}

Everything is working great and the contract address shows up in the array, but not the contracts attributes! (such as name in this case)

The child contract is defined as

contact MyChildContract {
  string public name;
  constructor(string memory _name) {
    name = _name;
  }
}

When I try to call the getMyChildren from ethers I just get an array of addresses for MyChildContracts, how can I get an array of objects that include the children's attributes (like name here)?

1 Answer 1

1

When you have a MyChildContract variable in Solidity, it is not "the full contract object", but just the contract address, cast to the MyChildContract type. The casting allows you to execute MyChildContract functions on this variable. But all that is actually saved there is the contract address.

So you'll have to design your own solution to return the names (if it is really needed).

For example you can save in MyContract, (instead of an array of MyChildContract) an array of struct made of MyChildContract + the contract name. But that saves to storage and is an expensive operation.

So another option would be to create a view function in MyContract which gets the list of child addresses, queries each one for it's name, builds the array using structs and returns the array. This is also not a cheap operation but if it is only used in a view function then the user won't pay for it.

So the solution depends on what you really need.

Usually there is no need to return a "full contract object".

2
  • ah okay thanks - in my case the user may create dozens of children and in my UI I'm displaying a list of children with some basic info. I do need the name (and some other attributes) for a kind of list display. Since the getters are pure/view only I guess I can get the list of addresses and then call the view function for each and every address? Seems a better solution than duplicating the data on chain? Thanks, Feb 20, 2022 at 3:10
  • Yes, it's better to not duplicate the data. But if you query every contract you'll make a lot of queries to the ethereum node. This can create overhead and issues. To mitigate that you can either use Multicall (look it up) or make 1 general function in MyContract which will query all the child contracts. That way you'll only send one query to the ethereum node. Feb 20, 2022 at 5:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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