получить array.length без геттера из другого контракта?

Есть ли способ получить длину массива в другом контракте без геттера?

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)

Нет. Вам нужно представить функцию, которая вернет длину массива в виде uint.

Что-то вроде

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

Это довольно распространенное требование. Эти шаблоны хранения могут сэкономить вам время, пытаясь понять, как действовать в рамках ограничений, с которыми мы имеем дело: Существуют ли хорошо решенные и простые шаблоны хранения для Solidity?

Надеюсь, это поможет.

Недавно у меня возникла эта проблема, и мне действительно нужно было получить длину массива в уже развернутом контракте. И, конечно же, я не развернул какую-то приятную getCount()функцию.

Вот мое действительно ужасное , но рабочее решение:

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

Чтобы это работало для вашего контракта, вам нужно будет изменить имя массива arrayToCountи возвращаемый тип массива на то, что у вас есть в интерфейсе и в tryстроке.

Вам нужно будет передать ему начальный индекс. Что касается меня, я знал, что мой массив имеет длину чуть более 14 КБ, поэтому я просто прошел 14 КБ. Вы должны быть в состоянии получить достаточно близкое число, разделив его пополам.

Вы можете использовать что-то вроде бинарного поиска, чтобы немного улучшить это.