How to specify unknown return type when calling function of another contract?

I’ve a Contract A as follows

contract A {

  struct Product {
    uint256 id;
    string name;
    uint256 quantity;
  }

  function someFunction(address user) external view returns(Product[] memory _product) {
    // do some processing
    return  _product;
  }

}

Another contract B is calling someFunction and needs to return Product struct received (from Contract A). But contract B doesn’t know the Product struct (as it’s defined in Contract A).

contract B {
  
  ContractAInterface internal contractA;  

  function bFunction() public view returns(/* what return type to specify here? */) {
    return contractA.someFunction(msg.sender);
  }

}

Would I need to duplicate Product struct definition in Contract B and then use:

function bFunction() public view returns(Product[] memory _Product)

Is that the only way around?

1 Like

Hi @megatower66,

You can just import the contract with the struct and then use [Contract Name].[Struct Name].

Have a look at Counters.sol

I had a quick try in Remix. Please note the following hasn’t been tested or audited.

A.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma abicoder v2;

contract A {

  struct Product {
    uint256 id;
    string name;
    uint256 quantity;
  }

  function someFunction(address user) external view returns(Product[] memory _product) {
    // do some processing
    return  _product;
  }

}

B.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma abicoder v2;

import "./A.sol";

contract B {
  
  A private _a;
  
  A.Product private _p;
  
  constructor (A a) {
      _a = a;
  }

  function bFunction() public view returns(A.Product[] memory _product) {
    return _a.someFunction(msg.sender);
  }
}

Thanks @abcoathup! But I was wondering if there's a way to do it without importing Contract A. Actually, Contract A is an on-chain Oracle and Contract B is a contract that user interacts with through the client side Dapp.

All user interactions are with Contract B and this contract just calls Contract A (on-chain Oracle) functions as defined by the OracleInterface (ContractAInterface).

Is there a way to import Struct as well in an interface? Also, technically Contract A resides in different repo and Contract B (and ContractAInterface) resides together in same repo.

1 Like

Hi @megatower66,

You could try putting the struct definition in the interface. Otherwise I assume you have to declare it again.

Thanks @abcoathup, putting the struct definition in the interface worked! Here's the updated one in case someone else is looking or will look:

contract B {
  
  ContractAInterface internal contractA;
  ContractAInterface.Product private _p;

  function bFunction() public view returns(ContractAInterface.Product[] memory _product) {
    return _a.someFunction(msg.sender);
  }

Also, am assuming the second line below:

pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

is to return struct from external call to contract function.

On another note, in truffle:

truffle(ganache)> (await contractB.bFunction({from: accounts[1]}))

outputs (duplicate values with key and without key:

[
  [
    1,
    'product1',
    '100', 
    id: '1',
    name: 'product1',
    quantity: '100'
  ],
  [
    2,
    'product2',
    '150', 
    id: '2',
    name: 'product2',
    quantity: '150'
  ]
]

but am using named return values in

Any idea what might be wrong?

Hi @megatower66,

I assume this is just how truffle does this output.

1 Like