Llamar a una función desde un contrato pasado como argumento

Estoy tratando de crear un DAPP con dos contratos que generen activos. Uno está actuando como la "fábrica" ​​para los otros contratos. Desde este último trato de llamar a una función en la fábrica sin saber aún su dirección, por lo que quiero pasarla como argumento. Esto arroja un error en Remix porque ese contrato obviamente aún no existe.

Para simplificar la situación, piense en este escenario en Remix (ambos contratos están escritos en el mismo archivo):

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

   }

¿Alguna idea u otros enfoques? Me doy cuenta de que la idea detrás del contrato anterior no tiene mucho sentido en este ejemplo, pero traté de mantenerlo lo más breve posible.

¡Gracias!

Respuestas (2)

Hubo una serie de errores de compilación en su código de ejemplo, pero una vez que los arreglé y cambié address factorya AssetFactory factory, todo parece estar bien.

(Simplemente adiviné a qué namese refería en la línea factory.createAsset(name). Al producir un ejemplo simple, asegúrese de que realmente haya probado).

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;
    }
}
Esto resolvió el problema que estaba teniendo. Perdón por el ejemplo tonto. Tienes razón, no lo probé, pero rápidamente armé algo para demostrar mi punto. ¡Gracias!

Aparte, noté algunos sucesos extraños y pensé que vale la pena mencionar algunas alternativas.

  1. Los activos pueden derivar la dirección de fábrica automáticamente.
  2. Puede evitar que alguien implemente un Activo sin usar Factory, y eso puede ser útil para garantizar la integridad y salvaguardar las suposiciones sobre lo que está sucediendo.
  3. Me resultó extraño poner una función de "crear activo" en el propio activo. Esto me parece un poco como pedirle al auto que tome pedidos para más autos. No es impensable, pero ¿por qué? En la mayoría de los casos, sería más consistente dejar que la fábrica sea una fábrica y dejar que el activo sea un producto de la fábrica.
  4. Cambié el constructor de Asset al estilo antiguo, ignorando la advertencia, porque muchas cosas no se compilan de la misma manera, esto incluido, usando la nueva sintaxis.

solidez de pragma 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;
  }   
}
¡Gracias por tu comentario! Estaba tratando de desarrollar un tipo de escenario de cadena de valor, donde los activos (cosas como una vaca o un trozo de madera) pueden registrarse y luego procesarse. Todavía no he dedicado mucho tiempo a esto, pero la única forma en que vi que esto funcionaba antes de obtener una respuesta inteligente fue modificando el "activo principal" y creando de inmediato un nuevo "activo secundario" dentro de la misma función.
Con la solución que me dieron @smarx y usted, probablemente también podría pasar el activo a una nueva función ProcessAsset() del contrato de AssetFactory. De esa forma, AssetFactory seguiría teniendo el control
Probablemente tendría contratos para cada clase de activo y algún enlace bidireccional. La vaca registraría al dueño. También podría ser útil para los propietarios mantener un libro de todos los activos que poseen (otra dirección).
¿Podría especificar a qué se refiere con enlace bidireccional? Hasta donde yo sé, las asignaciones serían la única solución posible para esto, pero no puede iterar sobre las asignaciones, lo que hace que su idea de llevar un libro de todos los activos sea muy difícil.
Comience aquí: medium.com/@robhitchens/solidity-crud-part-1-824ffa69509a Eso resuelve los problemas básicos de iteración y gestión, resumidos aquí. Resumido por aquí. ethereum.stackexchange.com/questions/13167/… . Para el enlace bidireccional, medium.com/@robhitchens/…