Contratos Proxy: Flexibilidad en un mundo inmutable


Hace unos años, cuando empecé a trabajar en un gran proyecto de smart contracts, me enfrenté a una situación desconcertante: ¿qué sucede si necesitamos actualizar la lógica de un contrato inteligente ya desplegado?.

En aquel entonces, cambiar la dirección de un contrato no solo era un dolor de cabeza técnico, porque significaba tener que reiniciar el la aplicación para poner las nuevas direcciones como variables de entorno, sino que también significaba perder todos los datos que tuviera ese contrato.

Esto era particularmente problemático porque siempre había entendido que los smart contracts eran, por definición, inmutables, piezas fijas en la blockchain.

Sin embargo, al adentrarme más en el mundo de los smart contracts, descubrí algo que desafió esa noción. Con un proxy, esa inmutabilidad puede “perderse en parte”, ya que estos contratos introducen una capa de abstracción que permite cambiar la lógica subyacente sin alterar la dirección del contrato.

Esto para mi fue un cambio de paradigma que revolucionó mi forma de pensar sobre el diseño de contratos y abrió un nuevo abanico de posibilidades.

¿Qué es un contrato proxy?

Los contratos proxy funcionan como intermediarios que delegan las llamadas de los usuarios a un contrato de implementación, permitiendo así cambiar o actualizar la lógica del contrato sin necesidad de modificar su dirección en la blockchain.

¿Cómo funciona un contrato proxy?

Imagina un contrato proxy como un centro de atención al cliente.

Similar a cómo las antiguas teleoperadoras redirigían las llamadas de los usuarios a la extensión o departamento adecuado, un contrato proxy redirige las interacciones de los usuarios a un contrato de implementación específico que contiene la lógica deseada.

  1. Interacción del usuario: Cuando un usuario envía una transacción para ejecutar alguna función en un contrato proxy, este no realiza la acción directamente. En lugar de eso, redirige la solicitud al contrato de implementación que contiene la lógica correspondiente.

  2. Delegación con delegatecall: Este redireccionamiento se realiza mediante una operación especial llamada delegatecall. El delegatecall permite que el contrato proxy ejecute el código del contrato de implementación usando su propio almacenamiento (el del proxy). Esto significa que la lógica del contrato de implementación se ejecuta en el contexto del proxy usando su almacenamiento.

  3. Almacenamiento persistente: El contrato proxy también asegura que la información se mantenga aunque la lógica cambie. Gracias a su almacenamiento independiente, incluso si la lógica del contrato de implementación se actualiza o se reemplaza, la información en el proxy no se pierde.

  4. Actualización segura: Los contratos proxy permiten una actualización segura de la lógica del contrato sin necesidad de cambiar la dirección del contrato. Los usuarios seguirán interactuando con la misma dirección, proporcionando una experiencia continua incluso cuando se implemente una nueva versión de la lógica.

Ventajas de los contratos proxy

  • Actualizaciones sin interrupciones: Facilitan la modificación de la lógica sin necesidad de desplegar un nuevo contrato y sin afectar a los usuarios.

  • Optimización de costos: La lógica puede residir en múltiples contratos reutilizables, ahorrando gas en despliegues.

  • Separación de almacenamiento y lógica: Permiten mantener los datos en el proxy mientras se actualiza la funcionalidad de forma independiente.

Inconvenientes de los contratos proxy

Complejidad adicional: Introducen una capa extra de abstracción que puede complicar el desarrollo y las auditorías.

Riesgos de seguridad: Implementaciones incorrectas pueden dar lugar a vulnerabilidades como ataques de reentrancia o errores en la gestión del almacenamiento.

Costos adicionales de gas: El uso del delegatecall pueden aumentar los costos en comparación con los contratos simples.

Tipos de contratos proxy

Hay varias formas de implementar contratos proxy en la EVM. Cada una tiene sus propias ventajas y desventajas:

  • Transparent Proxy: Este modelo, popularizado por OpenZeppelin, garantiza que solo los administradores puedan llamar a funciones específicas para actualizaciones. Las llamadas de los administradores no se delegan, lo que evita posibles conflictos.

  • UUPS (Upgradeable Proxy): Simplifica la arquitectura incluyendo la lógica de actualización directamente en el contrato de implementación. Es más flexible, pero requiere mayor cuidado en la seguridad, ya que el control de las actualizaciones recae en el contrato.

  • Minimal Proxy (Clones): Basado en el estándar EIP-1167, permite crear proxies que comparten la misma lógica. Es ideal para aplicaciones que necesitan desplegar múltiples instancias con bajos costos de gas.

  • Beacon Proxy: Utiliza un contrato “beacon” que apunta a la lógica de implementación. Esto permite actualizar varios proxies simultáneamente al modificar solo el beacon, ofreciendo una gran escalabilidad.

Conclusión

Los contratos proxy son una solución para superar las limitaciones de la inmutabilidad en los smart contracts. Aunque introducen complejidad y ciertos riesgos, ofrecen flexibilidad y escalabilidad que son clave en muchos casos de uso.

Elegir el tipo de proxy adecuado dependerá de las necesidades de tu aplicación y del equilibrio que busques entre seguridad, costos y facilidad de uso.

Próximamente, exploraremos con más detalle cómo implementar cada una de estas estrategias y sus mejores prácticas.