TypeError: la definición de base debe preceder a la definición de contrato derivado

En mi DAPP tengo 3 contratos donde quiero hacer algo como esto.

pragma solidity ^0.4.13;

import "./z2.sol";

contract z1 {

    uint example;

    function z1 (){ example = 33;}


    function createZ2() returns(z2){
        z2 newZ2 = new z2();
        return newZ2;
    }

    function getZ1example() returns(uint){
        return example;
    }

}

En z1, quiero devolver un contrato z2.

pragma solidity ^0.4.13;

import "./z3.sol";

contract z2 is z3{

    function z2 (){}

    function createZ3() returns(z3){
        z3 newZ3 = new z3();
        return newZ3;
    }



}

En z2, quiero devolver un contrato z3.

pragma solidity ^0.4.13;

import "./z1.sol";

contract z3 is z1  {


    function z3 (){}

    function getZ3example() returns(uint){
        return (z1.getZ1example());
    }


}

En z3, quiero llamar a una función del contrato z1.

Estoy probando esto en Remix y obtengo "Error de tipo: la definición de base debe preceder a la definición de contrato derivado".

¿Alguna idea de cómo puedo solucionar esto? ¡Gracias!

Respuestas (2)

Está demasiado enredado para resolverlo en unos pocos movimientos. Lo principal parece ser la forma en que mezclas las interfaces y la herencia. No desea utilizar la herencia para simplemente hablar con otro contrato o incluso para hacer otro contrato a partir de una plantilla.

Tomé sus tres conceptos y los renombré como "Almacenamiento", "Cliente" y "ClientFactory". La siguiente es una forma "sin lujos" de abordar las tres preocupaciones por separado.

pragma solidity 0.4.13;

contract Storage {

    mapping(uint => bytes32) public byteMap;

    function setStorage(uint key, bytes32 value) public returns(bool success) {
        byteMap[key] = value;
        return true;
    }

    function getStorage(uint key) public constant returns(bytes32 value) {
        return byteMap[key];
    }
}

contract Client {

    Storage datastore;

    function Client(address storageAddress) public {
        datastore = Storage(storageAddress);
    }

    function setValue(uint key, bytes32 value) public returns(bool success) {
        datastore.setStorage(key, value);
        return true;
    }

    function getValue(uint key) public constant returns(bytes32 value) {
        return datastore.getStorage(key);
    }
}

contract ClientFactory {

    event LogNewClientCreated(address sender, address newClient);

    function createClient(address storageContract) public returns(address newClient) {
        Client c = new Client(storageContract);
        LogNewClientCreated(msg.sender, c);
        return c;
    }
}

Usé Remix, que es excelente para pruebas y experimentación superficiales.

  1. Implemente un "Almacenamiento" y copie la dirección. Los clientes necesitarán saber esa dirección para localizarla y comunicarse con ella. Eso no es herencia . Lo que sucede es que el Cliente se compila en un código de bytes y, al hacerlo, el compilador puede "ver" el código fuente de almacenamiento al que se hace referencia y descubrir las firmas de funciones que el Cliente usará para comunicarse con él. Dado que los clientes también necesitan conocer la dirección implementada real (instancia implementada), le pasaremos esa información al constructor del cliente. Copie la dirección del contrato de almacenamiento en el portapapeles para el paso 3.

  2. Implemente una "ClientFactory".

  3. Usando la función ClientFactory createClient(), haga que implemente un nuevo Cliente. El constructor del cliente espera una dirección para una instancia de Storage (del paso 1). Pásalo a la función (entre comillas). La fábrica simplemente confía en que es verdad y lo transmite ciegamente. La nueva dirección de contrato del Cliente se registra para que pueda verla de inmediato.

  4. Desplácese hacia arriba hasta el contrato del cliente. En lo que respecta a Remix, nunca se ha implementado ningún "Cliente". Use el botón AT para pegar la dirección del contrato implementado que obtuvo en el paso 3 (sin comillas). Básicamente estás diciendo: "Sabes cómo debería verse la interfaz. Encontrarás una instancia en esta dirección".

  5. Juega con las funciones set/get en el Cliente. Dependen del contrato de almacenamiento para la persistencia.

Espero eso ayude.

Elimine todos los archivos en la carpeta build\contracts. Eso solucionó el error para mí.