Вызов функции из контракта, переданного в качестве аргумента

Я пытаюсь создать DAPP с двумя контрактами, генерирующими активы. Один действует как «фабрика» для других контрактов. Из последнего я пытаюсь вызвать функцию на фабрике, еще не зная ее адреса, поэтому я хочу передать ее в качестве аргумента. Это вызывает ошибку в Remix, потому что этого контракта, очевидно, еще не существует.

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

    contract AssetFactory{

    address[] deployedAssets;

      function createAsset(string name) public {
        address newAsset = new Asset(name);
        deployedAssets.push(newAsset);
        return newAsset;
      }

    }

    contract Asset{

     string name;

     function Asset(string name) public{
       name = name;
     }

     function ModifyAssetAndCreateNew(string name, address factory){
       factory.createAsset(name);
       name = name;
     }

   }

Любые идеи или другие подходы? Я понимаю, что идея приведенного выше контракта не имеет особого смысла в этом примере, но я постарался сделать его как можно короче.

Спасибо!

Ответы (2)

В вашем примере кода было несколько ошибок компиляции, но как только я их исправил и изменил address factoryна AssetFactory factory, все выглядит хорошо.

(Я просто предположил, что nameвы имели в виду в строке factory.createAsset(name). Создавая простой пример, убедитесь, что вы действительно тестировали его.)

pragma solidity ^0.4.23;

contract AssetFactory {
    Asset[] deployedAssets;

    function createAsset(string name) public returns (Asset) {
        Asset newAsset = new Asset(name);
        deployedAssets.push(newAsset);
        return newAsset;
    }

}

contract Asset {
    string name;

    constructor(string _name) public {
        name = _name;
    }

    function modifyAssetAndCreateNew(string _name, AssetFactory factory) public {
        factory.createAsset(_name);
        name = _name;
    }
}
Это решило проблему, с которой я столкнулся. Извините за глупый пример. Вы правы, я не проверял это, а просто быстро собрал что-то вместе, чтобы доказать свою точку зрения. Спасибо!

Кроме того, я заметил некоторые странные вещи и подумал, что стоит упомянуть некоторые альтернативы.

  1. Активы могут получить заводской адрес автоматически.
  2. Вы можете запретить кому-либо развертывать Актив без использования Фабрики, и это может быть полезно для обеспечения целостности и защиты предположений о том, что происходит.
  3. Мне показалось странным помещать функцию «создать актив» в сам актив. Это кажется мне немного похожим на то, чтобы попросить машину принять заказы на другие машины. Немыслимо, но почему? В большинстве случаев было бы более последовательно, если бы фабрика была фабрикой, а актив — продуктом фабрики.
  4. Я изменил конструктор Asset обратно на старый стиль, проигнорировав предупреждение, потому что многие вещи не компилируются таким же образом, включая это, с использованием нового синтаксиса.

прочность прагмы 0,4,23;

  contract AssetFactory {
    Asset[] public deployedAssets;

  function createAsset(string name) public returns (Asset) {
    Asset newAsset = new Asset(name);
    deployedAssets.push(newAsset);
    return newAsset;
  }

  function isFactory() public pure returns(bool isIndeed) {
    return true;
  }
}

contract Asset {
  string public name;
  AssetFactory factory;

  event LogAsset(address sender, bool isFactory);

  function Asset(string _name) public {
    name = _name;
    factory = AssetFactory(msg.sender);
  }

  // this seems like a strange thing to want. Consider removing it.

  function modifyAssetAndCreateNew(string _name) public {
    factory.createAsset(_name);
    name = _name;
  }   
}
Спасибо за ваш комментарий! Я пытался разработать сценарий цепочки создания стоимости, в котором активы (такие вещи, как корова или кусок дерева) могут быть зарегистрированы и позже обработаны. Я еще не потратил на это много времени, но единственный способ, которым я видел, как это работает, прежде чем я получил ответ smarx, заключался в изменении «родительского актива» и сразу же создании нового «дочернего актива» в той же функции.
С решением, которое @smarx и вы дали мне, я, вероятно, мог бы также передать актив в новую функцию ProcessAsset() контракта AssetFactory. Таким образом, AssetFactory по-прежнему будет контролировать
У вас, вероятно, будут контракты для каждого класса активов и некоторая двунаправленная привязка. Корова записывала владельца. Владельцам также может быть полезно вести книгу учета всех принадлежащих им активов (другое направление).
Не могли бы вы уточнить, что вы имеете в виду под двунаправленной привязкой? Насколько мне известно, сопоставления были бы единственным возможным решением для этого, но вы не можете перебирать сопоставления, что делает вашу идею вести книгу всех активов, находящихся в собственности, очень сложной.
Начните здесь: medium.com/@robhitchens/solidity-crud-part-1-824ffa69509a Это решает основные проблемы итерации и управления, обобщенные здесь. Подытожено здесь. эфириум.stackexchange.com/questions/13167/ … . Для двусторонней привязки, medium.com/@robhitchens/…