Как иметь адрес внутри Solidity Struct?

Моя проблема

Предположим, у меня есть эта структура:

struct TextThatWorks {
        bytes32 text;
        uint reads;
}

Как я могу добавить addressк нему переменную?

Что я пробовал

Я попытался просто добавить address someadress;внутри объявления структуры, например:

struct TextThatDoesNotWork {
        bytes32 text;
        uint reads;
        address addr;
}

Я видел много примеров, делающих то же самое. Пример: документы Solidity

Но когда я это делаю, мои функции ломаются.

Что происходит, когда я пытаюсь сделать выше

Что работает

Итак, в моем контракте у меня есть массив Text:

TextThatWorks[] public textArray;

И у меня есть функция для вызова текстов внутри этого массива, которая возвращает массивы:

function listTexts () public view returns (bytes32[], uint[]) {

        bytes32[] memory texts = new bytes32[](textArray.length);
        uint[] memory readsArray = new uint[](textArray.length);

        for (uint i = 0; i < textArray.length; i++){
            texts[i] = textArray[i].text;
            readsArray[i] = textArray[i].reads;
        }

        return (texts, readsArray);

}

Это возвращает хороший массив в формате[["some hexadecimal example"],[12]]

Что не работает

Вторая структура TextThatDoesNotWorkотличается только TextThatWorksтем, что имеет addressполе.

Когда я его использую, моя listTexts()функция перестает работать. Он всегда возвращает пустые массивы, например[[],[],[]]

Чтобы разместить дополнительное поле, моя listTexts()функция становится следующей:

function listTexts () public view returns (bytes32[], uint[], address[]) {

        bytes32[] memory texts = new bytes32[](textArray.length);
        uint[] memory readsArray = new uint[](textArray.length);
        address[] memory addresses = new address[](textArray.length);

        for (uint i = 0; i < textArray.length; i++){
            texts[i] = textArray[i].text;
            readsArray[i] = textArray[i].reads;
            addresses[i] = textArray[i].addr;
        }

        return (texts, readsArray, addresses);

}

Как я заполняю массив

function put(bytes32 _text, uint _reads) public returns (uint){
    return textArray.push(TextThatDoesNotWork({
        text: _text,
        reads: _reads,
        addr: msg.sender
    }))-1;
}

Ответы (1)

Убедитесь, что вы правильно заполнили массив

TextThatDoesNotWork[] textArray;

function put(bytes32 s, uint r, address a) public {
    textArray.push(TextThatDoesNotWork({
        text: s, 
        reads: r,
        addr: a
    }));
}

введите описание изображения здесь

Проверьте мое редактирование. Я добавил ваш код. Я попробовал это, но я все еще не могу заставить его работать. Хотя есть что-то цепляющее. Всякий раз, когда я запускаю contract.put("text", 200), я получаю хэш транзакции в консоли вместо индекса, возвращаемого функцией. Может ли проблема быть в том, как я вызываю функцию put()?
Давайте решать вопросы по порядку, потому что возвращаемое значение из putфункции — это другой вопрос. Что у вас есть после действий: контракт развертывания -> вызов put(0x1221, 10)-> вызов listTexts()?
Кстати, contract.put("text", 200)не будет работать, потому что первый параметр имеет тип bytes32, вам нужно преобразовать строку в bytes32, вы можете использовать web3.utils.fromAscii("text")функцию
это работает, как описано в тексте вопроса. Я предполагаю, что контракт делает это преобразование для меня. Проблема возникает, когда я добавляю addressатрибут в структуру. Он просто перестает работать, но до добавления этого атрибута он работает!
Я использую консоль geth для проверки этого контракта. Без addressатрибута в структуре я могу развернуть контракт, вызвать contract.put("some text", 200)и просмотреть новые данные с помощью contract.listTexts().
Я думал, что мы обсуждаем только полную версию (с адресом). Вот полная версия кода gist.github.com/aquiladev/75ac4f981075caa059ccfdd71125899b Убедитесь, что вы запускаете его с правильной версией Solidity. Если это не сработает, скорее всего, проблема в связи с договором.
так что, кажется, вы и я оба правы. Я не использовал Remix IDE для проверки своего контракта, я компилировал самостоятельно в терминале bash и использовал консоль geth. Итак, вы были правы, потому что в Remix я не могу просто передать строку. Мне действительно нужно передать текст в шестнадцатеричном формате. Но когда я взаимодействую со своим контрактом через консоль geth, в этом нет необходимости. Если говорить о моей проблеме, я до сих пор не могу использовать поле адреса в структуре при тестировании через консоль geth. Однако он работает через Remix IDE. Я предполагаю, что я должен делать что-то неправильно при компиляции? Или это может быть ошибка в компиляторе?
Хорошо бы проверить версию компилятора, но я не уверен, что это так, только если у вас действительно старая версия. Я бы попробовал скомпилировать через solcили truffleс тестами.
Я вижу, что он пытается вернуть значение из функции put(), но я думал, что вы не можете возвращать значения из функций изменения состояния, только функции просмотра.