Proporcionar argumentos de constructor de contratos base

Estoy un poco desconcertado acerca de la herencia múltiple y el suministro de argumentos para diferentes constructores. La documentación de Solidity tiene largas explicaciones sobre esto ( http://solidity.readthedocs.io/en/develop/contracts.html#arguments-for-base-constructors ) pero (en mi opinión) no hay suficiente información sobre los argumentos de los contratos base. Afirma:

Si los constructores base tienen argumentos, los contratos derivados deben especificarlos todos.

¿Cómo funciona esto exactamente cuando hay un cuadro de herencia complicado? Un ejemplo:

pragma solidity ^0.4.0;

contract A {
    constructor(uint paramA) public {

    }
}

contract B is A {
    constructor(address paramB) public {

    }
}

contract C is A {
    constructor(string paramC) public {

    }
}

contract D is B, C {
    constructor(uint paramForA, address paramForB, string paramForC) public // stuff here to call A, B and C constructors with non-static parameters
    {

    }
}

¿Cómo debe el contrato Despecificar los argumentos de su constructor para los contratos A By Cproporcionar todos los parámetros requeridos y en qué orden? ¿Hay un solo orden correcto?

Respuestas (1)

En Solidity, especifica los argumentos del constructor base de dos maneras (según https://docs.soliditylang.org/en/latest/contracts.html#arguments-for-base-constructors ):

La primera forma de hacerlo es más conveniente si el argumento del constructor es una constante y define el comportamiento del contrato o lo describe. La segunda forma debe usarse si los argumentos constructores de la base dependen de los del contrato derivado. Los argumentos deben proporcionarse en la lista de herencia o en estilo modificador en el constructor derivado. Especificar argumentos en ambos lugares es un error.

Su estructura de herencia es la siguiente: D->C->B->A.

Si cambiamos un poco el orden (solo para asegurarnos de que las ejecuciones del constructor sean diferentes a la secuencia del código) y agregamos algo de registro, obtenemos:

contract A {
    constructor(uint paramA) public {
        log0(bytes32(0x00000000));  
    }
}


contract C is A(0) {
    constructor(string paramC) public {
        log0(bytes32(0x00000002));  
    }
}

contract B is A{
    constructor(address paramB) public {
      log0(bytes32(0x00000001));  
    }
}

contract D is B, C {
    constructor(uint paramForA, address paramForB, string paramForC) public  C(paramForC) B(paramForB)// stuff here to call A, B and C constructors with non-static parameters
    {
        log0(bytes32(0x00000003));  
    }
}

Obtiene la siguiente ejecución de constructores: A->B->C->D

Tenga en cuenta que si cambia el orden de herencia y reescribe D de la siguiente manera:

contract D is C, B {
    constructor(uint paramForA, address paramForB, string paramForC) public  C(paramForC) B(paramForB)// stuff here to call A, B and C constructors with non-static parameters
    {
        log0(bytes32(0x00000003));  
    }
}

Obtendrá un orden de ejecución diferente A->C->B->D

Así que el orden sí importa.

EDIT1: Como lo anterior no fue exactamente al grano, a continuación trato de abordar la pregunta: "¿Cómo debe el contrato D especificar sus argumentos de constructor para los contratos AB y C para proporcionar todos los parámetros requeridos y en qué orden? ¿Hay solo un orden correcto? ?" directamente.

Puede asignar parámetros a los constructores de contratos principales de dos formas:

1. Directamente en la declaración de herencia:

contract D is B('0x0b'), C('0x0c') {
    constructor(uint paramForA, address paramForB, string paramForC) public 
    {
    }
}

donde 0x0b y 0x0c son literales de dirección.

2. Asignándolos usando una sintaxis similar a los modificadores de Solidez si desea usar argumentos del constructor D:

contract D is B, C {
    constructor(uint paramForA, address paramForB, string paramForC) public  C(paramForC) B(paramForB) {}
}

No hay otra forma de inicializar los constructores de contratos principales que yo sepa. Si desea inicializar las variables de estado de un contrato principal, puede hacerlo dentro del constructor D. Esas variables de estado deben ser públicas o internas en el contrato principal. Espero que esto ayude.

¡Gracias por el aporte! Lo siento, pero no entiendo muy bien cómo responde esto a mi pregunta "¿Cómo debe Despecificar el contrato sus argumentos de constructor". Según tengo entendido, su respuesta dice "bueno, si cambia esto y esto, suceden otras cosas".
Creo que esa respuesta se incluyó, pero estaba borrosa por ejemplos que no eran tan relevantes para la pregunta, lo siento. Creo que "Edit1" debería responder a su pregunta.
¿Sobre qué paramForA? No lo has incluido en tu ejemplo. (Solo estoy interesado en una forma no estática de proporcionar los parámetros). ¿Y solo hay un orden válido para las llamadas al constructor? (actualmente tiene orden C..B, ¿de dónde viene A?)