9.2 Contratos proxy





Contratos Proxy en Solidity

Punto del curso de Solidity: 9.2 Contratos proxy

En el desarrollo de contratos inteligentes en Solidity, los contratos proxy son una técnica avanzada usada para permitir la actualizabilidad de los contratos. Dado que los contratos inteligentes desplegados en la cadena de bloques son inmutables, los contratos proxy ofrecen una manera de actualizar la lógica del contrato sin cambiar su dirección.

Definición y Funcionamiento

Un contrato proxy actúa como intermediario entre los usuarios y la implementación lógica real del contrato. Cuando una función es llamada en el contrato proxy, este redirige la llamada a otro contrato que contiene la lógica (Implementación). Esto se consigue utilizando delegados de llamadas (delegatecall) en Solidity.

Beneficios de los Contratos Proxy

  • Actualización de lógica: Permiten actualizar la lógica del contrato sin cambiar la dirección del contrato, manteniendo intactos los datos almacenados.
  • Modularidad: Separan la lógica del contrato y los datos, facilitando la mantenibilidad.
  • Optimización de costes: Reducen los costes de despliegue ya que sólo se actualiza la implementación lógica en vez de re-desplegar todo el contrato.

Estructura del Contrato Proxy

En una arquitectura de contrato proxy, normalmente encontramos dos contratos principales:

  1. Proxy Contract: El contrato que delega llamadas a la implementación lógica.
  2. Implementation Contract: El contrato que contiene la lógica del negocio real.

Código de Ejemplo

A continuación se muestra un ejemplo básico de un contrato proxy en Solidity.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0

// Implementación lógica del contrato
contract LogicContract {
    uint256 public value
    
    function setValue(uint256 _value) public {
        value = _value
    }
    
    function getValue() public view returns (uint256) {
        return value
    }
}

// Contrato Proxy
contract ProxyContract {
    address public implementation
    
    constructor(address _implementation) {
        implementation = _implementation
    }
    
    fallback() external payable {
        address _impl = implementation
        require(_impl != address(0), Implementation contract address should be set.)
        
        assembly {
            let ptr := mload(0x40)
            calldatacopy(ptr, 0, calldatasize())
            let result := delegatecall(gas(), _impl, ptr, calldatasize(), 0, 0)
            let size := returndatasize()
            returndatacopy(ptr, 0, size)
            switch result
            case 0 { revert(ptr, size) }
            default { return(ptr, size) }
        }
    }
    
    function upgrade(address _newImplementation) public {
        implementation = _newImplementation
    }
}

En este ejemplo, tenemos dos contratos:

  1. LogicContract: Es el contrato que contiene la lógica de un valor simple. Puede establecer y obtener un valor.
  2. ProxyContract: Es el contrato proxy que delega cualquier llamada a la dirección del contrato de implementación a través de la función fallback.

Explicación Detallada del ProxyContract

  • Constructor: Inicializa la dirección de la implementación al desplegar el contrato.
  • Fallback Function: La función fallback se activa cuando se recibe una llamada al contrato proxy. Esta función usa ensamblador para:
    • Copiar los datos de la llamada.
    • Delegar la llamada a la implementación usando delegatecall.
    • Devolver los datos resultantes de la llamada.
  • Upgrade Function: Permite actualizar la dirección de la implementación a una nueva dirección, facilitando así la actualización de la lógica del contrato.

Aspectos Críticos a Considerar

  • Seguridad: Cualquier error en el contrato de implementación puede ser catastrófico. Es crucial asegurar que el nuevo contrato de implementación esté bien auditado.
  • Control de Acceso: Las funciones como upgrade deben estar protegidas para evitar accesos no autorizados. En un entorno de producción, es importante añadir control de acceso mediante modficadores como onlyOwner.
  • Compatibilidad: Al actualizar la implementación, es crucial asegurar que la nueva implementación sea compatible con la estructura de almacenamiento de la anterior.


AnteriorSiguiente

[mwai_chat]

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *