21

Is there a way to get length of an array in an other contract without a getter?

pragma solidity ^0.4.11;

contract MyContractA {
    uint[] public myArray;

    function MyContractA() {
        myArray.length = 1;
    }

}

contract MyContractB {

    function test() returns (uint ret) {
        address instanceAddress = new MyContractA();
        MyContractA instance = MyContractA(instanceAddress);
        // works:
        return instance.myArray(0); 
        //
        // doesn't work: 
        //
        //  TypeError: Member "length" not found or not visible after argument-dependent lookup in function (uint256) constant external returns (uint256)
        // return instance.myArray.length;

        // TypeError: Member "length" not found or not visible after argument-dependent lookup in function (uint256) constant external returns (uint256)
        // return instance.myArray.length();

        //   TypeError: Wrong argument count for function call: 0 arguments given but expected 1.
        //return instance.myArray().length;
    }
}
Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
szerte
  • 1,231
  • 1
  • 14
  • 32

2 Answers2

24

No. You need to present a function that will return the array length as a uint.

Something like

function getCount() public view returns(uint count) {
    return array.length;
}

It's a pretty common requirement. These storage patterns might save you some time working out how to do things within the constraints we're dealing with: Are there well-solved and simple storage patterns for Solidity?

Hope it helps.

OWADVL
  • 290
  • 1
  • 11
Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
0

I recently had this issue and really needed to get the array length on an already deployed contract. And of course I didn't deploy some nice getCount() function.

Here's my really terrible, but working solution:

interface IExternalContract {
    function arrayToCount(uint idx) external view returns (address);
}

contract ArrayCounter { function getOfferCount(IExternalContract factory, uint start) public view returns (uint) { for (uint256 i = start; i < 10000; i++) { try factory.arrayToCount(i) returns (uint v) { start = i; // keep going } catch Error(string memory /reason/) { return i; } catch (bytes memory /lowLevelData/) { return i; } } return start; } }

To make this work for your contract you will need to change the array name arrayToCount and the return type of the array to whatever your is in the interface and in the try line.

You will need to pass it a starting index. For me, I knew my array was a little over 14k in length so I just passed in 14k. You should be able to get a close enough number by bisecting it down.

Zach
  • 1
  • 1