Отправка адреса в массив другого контракта возвращает TypeError: элемент «push» не найден или не отображается после поиска в функции, зависящего от аргумента.

Контракт User.sol имеет функцию, requestValidationкоторая взаимодействует с другим контрактом. Его цель — поместить адрес владельца контракта User.sol в массив pendingRequests, хранящийся в другом контракте (TrustEntity.sol).

Контракт User.sol

pragma solidity ^0.4.11;
import "browser/TrustEntity.sol";

contract User {
    // State variables
    // The contract address for the TrustEntity
    TrustEntity trustEntity;
    address owner = msg.sender;
    bool verified = false;
    uint creationTime = now;
    uint level = 0;

    // Set trustEntity's deployed contract address
    function User(address _trustEntity) {
        trustEntity = TrustEntity(_trustEntity);
    }

    function requestValidation() {
        trustEntity.pendingRequests.push(owner);
    }
}

Контракт TrustEntity.sol

pragma solidity ^0.4.11;
import "browser/User.sol";

contract TrustEntity {
    address owner;
    address registry;
    address[] public pendingRequests;

    function verifyUsers() {
        /*
        Whenever a user requests verification, his
        address should be pushed to the pendingRequests
        array, so it can then be fetched to verify or
        reject
        */
    }   
}

Remix дает мне следующее сообщение об ошибке:

browser/User.sol:19:6: TypeError: Member "push" not found or not visible after argument-dependent lookup in function (uint256) constant external returns (address)
        trustEntity.pendingRequests.push(owner);
        ^------------------------------^

Я попытался вставить массив, хранящийся в контракте, который работает. Вот так

pragma solidity ^0.4.11;
import "browser/TrustEntity.sol";

contract User {
    // State variables
    // The contract address for the TrustEntity
    TrustEntity trustEntity;
    address owner = msg.sender;
    bool verified = false;
    uint creationTime = now;
    uint level = 0;
    address[] public pendingRequests;

    // Set trustEntity's deployed contract address
    function User(address _trustEntity) {
        trustEntity = TrustEntity(_trustEntity);
    }

    function requestValidation() {
        pendingRequests.push(owner);
    }
}

поэтому я не понимаю, почему это не сработает для другого контракта. Связано ли это с использованием ETH для оплаты транзакции, поскольку это функция изменения состояния?

Я не могу вставить массив, хранящийся в контракте в 0.6.0, как вы могли сделать в ^ 0.4.11

Ответы (1)

Контракты не получают доступа для записи в состояние друг друга. Модификатор publicозначает только то, что значение доступно для чтения. Предполагая, что вы являетесь разработчиком TrustEntity, могу предложить пару вариантов:

  1. Полностью удалите контракт пользователя, сохранив всю информацию о пользователях в контракте TrustEntity.
  2. Напишите «сеттер» в TrustEntity, например TrustEntity.pushPending(address)(с соответствующими элементами управления учетной записью, чтобы предотвратить глобальный доступ для записи)

На мой взгляд, первое — более стандартное использование, основанное на вашей очевидной цели. Например, контракты токенов обычно хранят всю информацию о владельцах токена централизованно, а не добавляют отдельные контракты для каждого пользователя.

Второй вариант увеличивает стоимость газа и раздувание блокчейна, а также увеличивает площадь поверхности для ошибок безопасности.

Это сработало, ура! Я выбрал вариант 2, так как мне нужно много других функций в пользовательском контракте, и я бы хотел, чтобы эти 2 функции были разделены. Кроме того, это игрушечное приложение, так что пока оно будет работать.