es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La prevención de delegación de llamadas (delegatecall) en Solidity no funciona.

Soy un traductor de español que traduce documentos de TI. Traduce lo siguiente al español. No traduzcas el código y la salida en markdown.

Soy un principiante estudiando el código de Github de Uniswap V3. Encontré el archivo “noDelegateCall.sol” en este enlace y descubrí una forma de evitar que un contrato sea llamado por delegación desde otro contrato. Sin embargo, al intentar implementar esto, me encontré con un problema.

pragma solidity >0.8.0;

contract Receiver {
    string greeting = "Hola";
    address private immutable original;
    event Greeting(string greeting, address original, address addressThis);

    constructor() {
        original = address(this);
    }

    function checkNotDelegateCall() private view {
        require(address(this) == original);
    }

    modifier noDelegateCall() {
        checkNotDelegateCall();
        _;
    }

    function greet() external noDelegateCall {
        emit Greeting(greeting, original, address(this));
    }
}

contract Sender {
    string greeting = "Hola";

    function delegatedGreeting(address _contract) external {
        (bool success,) = _contract.delegatecall(
            abi.encodeWithSignature("greet()")
        );
    }
}

Si llamo a la función delegatedGreeting, espero que la función se revierta porque las variables original y address(this) son diferentes. Sin embargo, aunque emite un evento vacío, aún no se revierte. ¿Por qué ocurre esto?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    La razón por la que la función delegatedGreeting no revierte es que la función delegatecall permite al contrato llamado acceder al almacenamiento del contrato llamante. En este caso, las variables original y address(this) se almacenan en el almacenamiento del contrato Receiver. Cuando delegatedGreeting llama a la función greet a través de delegatecall, se ejecuta en el contexto del contrato Sender, que no tiene las variables original y address(this) en su almacenamiento. Sin embargo, aún puede acceder a esas variables en el almacenamiento del contrato Receiver debido a delegatecall. Por lo tanto, la función checkNotDelegateCall() en el modificador noDelegateCall sigue pasando y la función no revierte.

    Para asegurarse de que el modificador noDelegateCall funcione como se espera, debe utilizar el opcode CALL en lugar de DELEGATECALL. El opcode CALL no permite que el contrato llamado acceda al almacenamiento del contrato llamante. Puede modificar la función delegatedGreeting de la siguiente manera:

    function delegatedGreeting(address _contract) external {
        (bool success,) = _contract.call(
            abi.encodeWithSignature("greet()")
        );
        require(success, "Call failed");
    }
    

    Con esta implementación, la llamada a delegatedGreeting revertirá como se espera, ya que las variables original y address(this) no coincidirán debido a la ausencia de acceso al almacenamiento del contrato llamado.

Comments are closed.