14

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;
    }
}

2 Answers 2

20

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.

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.

1
  • You could use something like a binary search to improve this a little.
    – Ismael
    May 5 at 2:13

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.