Solidez - ¿No es posible llamar a los padres pagaderos?

Estoy tratando de heredar y anular la función de pago de un padre (y agregar algunos modificadores y lógica), pero hasta ahora parece que no puedo hacerlo.

Mi primer intento intuitivo fue algo como esto:

contract foo {
    function test() public payable returns (uint256) {
        return msg.value;
    }
}

contract bar is foo {
    function test() public payable returns (uint256) {
        return super.test.value(msg.value / 2)();
    }
}

y recibió un error de compilación:

TypeError: Member "value" not found or not visible after argument-dependent lookup in function () - did you forget the "payable" modifier?
    super.test.value(msg.value)();

Dar a la función un nombre diferente tampoco funciona, por lo que no es un problema primordial.

contract foo {
    function test() public payable returns (uint256) {
        return msg.value;
    }
}

contract bar is foo {
    function anotherTest() public payable returns (uint256) {
        return super.test.value(msg.value / 2)();
    }
}

Llegué un poco más lejos al engañar al compilador con una conversión, pero obviamente esto no es bueno, ya que causaría un bucle infinito en el tiempo de ejecución:

contract foo {
    function test() public payable returns (uint256) {
        return msg.value;
    }
}

contract bar is foo {
    function test() public payable returns (uint256) {
        return foo(address(this)).test.value(msg.value / 2)();
    }
}

Lo que funciona es combinar los dos, es decir, darle un nombre y un casting diferentes:

contract foo {
    function test() public payable returns (uint256) {
        return msg.value;
    }
}

contract bar is foo {
    function anotherTest() public payable returns (uint256) {
        return foo(address(this)).test.value(msg.value / 2)();
    }
}

Ahora llamar a bar.test() con 6 wei devuelve 6 y llamar a bar.anotherTest() devuelve 3. Pero esto no es exactamente lo que quiero, ya que todavía expone test() a través de bar.

Entonces, ¿qué estoy haciendo mal, o es esto por diseño? Realmente me gustaría entender por qué Solidity se comporta de esta manera y si hay una solución para lograr lo que quiero. ¡gracias!

Respuestas (1)

Ya que fooes el contrato base de barcuando llamas super.test()te estás llamando a ti mismo dentro del mismo contrato.

Ahora está tratando de enviarse la mitad msg.valuey la otra mitad seguirá estando en su contrato.

Recomiendo pasar el valor deseado como parámetro de la función.

Sí, finalmente lo descubrí. Como explicaste, estoy llamando dentro del mismo contrato y realmente no hay razón para reenviar ether al mismo bolsillo, simplemente llamando super.test()sin .valueo con un parámetro sería suficiente. ¡Gracias!