BDS
smart-contracts, security-audits, ethereum-solidity

Actualización de contratos inteligentes mediante patrones proxy: guía completa

February 23, 2026
12 min
c
Arquitectura de patrón proxy que muestra la interacción entre el contrato proxy, el contrato de implementación y las interfaces de usuario.

Introducción

Los contratos inteligentes están programados para ser permanentes e inmutables una vez que se implementan en una red blockchain. Esta inmutabilidad es una fuente de seguridad y confianza, pero también presenta desafíos cuando los desarrolladores necesitan corregir errores o añadir nuevas funciones.

Cuando se requieren modificaciones, los desarrolladores tienen que publicar un contrato completamente nuevo con una dirección diferente. Si bien esta permanencia es excelente para la seguridad, puede ser limitante en situaciones en las que las cosas salen mal o es necesario realizar mejoras.

La historia ha demostrado que las vulnerabilidades de los contratos inteligentes pueden provocar pérdidas financieras catastróficas. Un ejemplo concreto es un incidente grave en el que se perdieron millones de dólares debido a un fallo explotable.

Estos incidentes ponen de manifiesto la importancia de poder abordar los problemas de seguridad y los errores después de la implementación. Hacer que los contratos sean actualizables permite disponer de un mecanismo para corregir los problemas sin perder el estado actual y la experiencia del usuario, lo cual es un aspecto clave de la capacidad de actualización de los contratos inteligentes.

Esta capacidad puede ser importante para evitar pérdidas significativas y preservar la integridad del sistema.

Hay varias formas de implementar contratos inteligentes actualizables, como los patrones de proxy de contratos inteligentes y las técnicas de separación de datos. Este artículo trata específicamente sobre cómo implementar la capacidad de actualización mediante el uso de patrones de proxy, que es una forma popular de resolver esto en el ámbito del desarrollo de cadenas de bloques.

Comprensión del patrón proxy

El patrón proxy es un patrón de diseño estructural en el que un contrato implementa una interfaz para otro contrato. Esta arquitectura tiene dos partes principales: el contrato proxy y el contrato de implementación.

En lugar de comunicarte directamente con el contrato de implementación, te comunicarás con el contrato proxy, que a continuación transmitirá las solicitudes según corresponda.

En esta configuración, tanto el contrato proxy como el contrato de implementación permanecen inalterados tras su implementación. Sin embargo, la capacidad de actualización se logra permitiendo que el proxy haga referencia a diferentes contratos de implementación a lo largo del tiempo.

Esto significa que los usuarios pueden seguir utilizando la misma dirección e interfaz mientras se actualiza la funcionalidad subyacente. Desde el punto de vista del usuario, la aplicación sigue funcionando perfectamente aunque cambie la lógica del backend.

El contrato proxy es responsable de las interacciones de los usuarios y del almacenamiento de todos los datos. Mantiene la dirección del contrato de implementación en un lugar de almacenamiento especial.

Cuando los usuarios invocan funciones en el contrato proxy, se invoca una función de respaldo. La siguiente función utiliza un mecanismo delegatecall ethereum para invocar el código desde el contrato de implementación, pero cualquier cambio de estado se guarda en el almacenamiento del contrato proxy.

Implementaciones principales de patrones proxy

Patrón de proxy transparente

El patrón de proxy transparente coloca la funcionalidad de actualización en el propio contrato de proxy. El proxy tiene un método upgradeTo que se utiliza para actualizar la dirección que apunta al contrato de implementación.

Esto plantea un problema potencial: si tanto el contrato proxy como el de implementación contienen un método upgradeTo, no queda claro cuál de ellos debe invocarse cuando un usuario llama a esta función.

Para resolver esta ambigüedad, se ha ideado una solución en la que la decisión sobre a quién delegar se basa en quién llama al contrato.

Si quien realiza la llamada es el administrador del proxy, las llamadas son gestionadas por el propio contrato del proxy. De lo contrario, las llamadas se delegan al contrato de implementación. Este enfoque garantiza que las funciones se ejecuten con claridad y que no haya confusión entre las operaciones administrativas y las operaciones habituales de los usuarios.

Estándar universal de proxy actualizable

El estándar universal de proxy actualizable tiene un enfoque diferente, ya que coloca la funcionalidad de actualización en el contrato de implementación, no en el proxy. El proxy delega todas las llamadas al contrato de implementación, que tiene el método upgradeTo para apuntar a versiones más recientes.

Este patrón ofrece a los desarrolladores un mayor control sobre la ruta de actualización. Si un desarrollador decide dejar de incluir el método upgradeTo en una versión futura, el contrato pasa a ser inmutable de forma permanente y no se puede actualizar más.

Esto puede resultar útil cuando un contrato ha sido bien probado y el equipo de desarrollo quiere congelarlo en su estado final.

Dado que la lógica de actualización se encuentra en el contrato de implementación, no es necesario que la función de respaldo del proxy compruebe si el autor de la llamada es un administrador antes de delegar las llamadas.

Esto hace que el patrón sea más eficiente que el patrón de proxy transparente. También se elimina el posible conflicto de nombres, ya que el método upgradeTo solo existe en el contrato de implementación.

Patrón de proxy de baliza

El patrón Beacon Proxy introduce una arquitectura de tres componentes: el contrato proxy, un contrato beacon y el contrato de implementación. En lugar de guardar la dirección de la implementación, el proxy guarda la dirección del contrato beacon.

El contrato de baliza, a su vez, contiene la dirección del contrato de implementación.

Cuando un usuario llama al proxy, primero obtendrá la dirección del contrato de baliza y, a continuación, llamará a la baliza para obtener la dirección del contrato de implementación. Por último, deja la llamada al contrato de implementación.

Esta capa adicional de indirección tiene un propósito muy específico.

Este patrón es especialmente útil cuando varios contratos proxy deben utilizar la misma implementación. En patrones más simples, para actualizar la implementación, habría que actualizar la dirección en cada contrato proxy individualmente. Con el patrón beacon, solo es necesario actualizar el contrato beacon y todos los proxies asociados a él apuntan automáticamente a la nueva implementación.

Implementaciones principales de patrones proxy

Patrón Diamond Proxy

El patrón Diamond Proxy resuelve el problema de la limitación de tamaño de los contratos inteligentes, que suelen estar limitados a unos 24 kilobytes. Este patrón separa la funcionalidad en varios contratos más pequeños conocidos como facetas.

El contrato proxy mantiene una correspondencia entre los selectores de funciones y la dirección de las facetas que contienen esas funciones.

Cuando se invoca una función en el proxy, este utiliza el selector de funciones para buscar la faceta que contiene la función y delega la invocación de la función a la faceta adecuada.

Las actualizaciones se realizan modificando las direcciones de las facetas en el proxy. Este patrón permite una funcionalidad total mucho mayor al distribuir la funcionalidad entre varios contratos, y cada faceta permanece por debajo del límite de tamaño.

Comparación de enfoques de patrones proxy

Cada patrón de proxy tiene características diferentes que lo hacen adecuado para distintos casos de uso. Los cuatro patrones necesitan un contrato de proxy y utilizan la delegación para reenviar las llamadas a los contratos de implementación.

El patrón Proxy transparente localiza las funciones de actualización en el contrato proxy y UUPS localiza las funciones de actualización en el contrato de implementación. El patrón Beacon coloca la capacidad de actualización en su propio contrato beacon y el patrón Diamond suele colocar la capacidad de actualización en los contratos de implementación, pero no está estrictamente especificado.

En lo que respecta a la inmutabilidad, los patrones UUPS y Diamond pueden hacer que los contratos sean permanentemente inmutables al eliminar la función de actualización de las versiones futuras. Los patrones Transparent y Beacon no ofrecen esta flexibilidad.

Cuando se trata de múltiples proxies, el patrón Beacon tiene una ventaja definitiva. Con los patrones Transparent, UUPS y Diamond, cada proxy debe cambiarse individualmente al implementar una nueva implementación.

Con el patrón Beacon, solo hay que actualizar el contrato Beacon y todos los proxies utilizarán automáticamente la nueva implementación.

La eficiencia de gas es diferente para cada patrón. El patrón transparente requiere que compruebes si el autor de la llamada es un administrador antes de cada delegación, por lo que es más costoso.

UUPS es más eficiente, ya que no requiere esta comprobación. Todos los patrones, excepto Diamond, tienen costes de gas adicionales por las operaciones de búsqueda adicionales.

Todos los patrones, excepto Diamond, están limitados a 24 kilobytes por contrato. El patrón Diamond permite que cada faceta tenga un tamaño de hasta 24 kilobytes, lo que hace posible tener una funcionalidad total mucho mayor en múltiples facetas.

Domina la seguridad de los contratos inteligentes.

Aprende técnicas avanzadas para crear contratos seguros y actualizables con nuestros cursos impartidos por expertos.

Consideraciones importantes y riesgos

Problemas de colisión de almacenamiento

Las colisiones de almacenamiento son un riesgo grave al implementar patrones proxy. Las variables de contrato se almacenan en ranuras de almacenamiento específicas y, si las variables del contrato proxy y las variables del contrato de implementación se almacenan en las mismas ranuras de almacenamiento, interferirán entre sí.

Además, si el orden de las variables en el contrato de implementación cambia de una versión a otra, las ranuras de almacenamiento pueden reasignarse, lo que provocaría la corrupción de los datos.

Contratos de implementación no inicializados

Los contratos de implementación deben inicializarse exactamente una vez mediante una función de inicialización, que es un concepto similar al constructor en los contratos tradicionales.

Los desarrolladores también olvidan inicializar la implementación o no incluyen protecciones para evitar que la función de inicialización se llame más de una vez.

Cuando esto ocurre, los atacantes pueden invocar la función de inicialización por sí mismos y, potencialmente, tomar el control del contrato o manipular su estado.

Incidentes de seguridad en el mundo real

Un programa de recompensa por errores encontró una vulnerabilidad crítica en los contratos proxy de Vault, donde los contratos de implementación no se inicializaban correctamente. Este fallo podría haber sido utilizado por un atacante para destruir el contrato de implementación, dejando inútiles los contratos proxy asociados. En otro incidente ocurrido en un determinado periodo de tiempo en julio, los contratos inteligentes fueron pirateados debido a una vulnerabilidad en el código de inicialización, en el que la función de inicialización podía llamarse varias veces.

Enfoques alternativos para la capacidad de actualización

Patrón de separación de datos

Una alternativa a los patrones proxy es el enfoque de separación de datos. Este enfoque se basa en el uso de contratos separados para el almacenamiento y la lógica. El contrato lógico se comunica con el contrato de almacenamiento para leer o actualizar datos.

Si bien es posible sustituir el contrato lógico por nuevas versiones, el contrato de almacenamiento es fijo e inmutable. Esto ofrece un modelo diferente de actualizabilidad que puede ser adecuado en algunas circunstancias.

Capas de verificación

Ninguno de los patrones proxy que se utilizan habitualmente cuenta con mecanismos para verificar que un nuevo contrato de implementación es válido antes de realizar la actualización.

Es imprescindible que las nuevas versiones incluyan toda la lógica empresarial necesaria, las funciones de respaldo y otros componentes esenciales.

Esto se puede lograr introduciendo una capa de verificación junto a la capa proxy, la capa de lógica empresarial y la capa de almacenamiento. Esta capa adicional garantiza que las actualizaciones cumplan con ciertos criterios antes de que se permita su ejecución.

Mejores prácticas para contratos actualizables

Los desarrolladores que diseñen contratos actualizables deben seguir algunas pautas clave para garantizar la seguridad y la fiabilidad:

  • En su lugar, confía en implementaciones bien probadas de bibliotecas bien probadas que hayan sido revisadas y auditadas minuciosamente.
  • Asegúrate siempre de inicializar correctamente los contratos de implementación y de que las funciones de inicialización solo se puedan llamar una vez.
  • Nunca inicialices variables de estado en su declaración o en un constructor; utiliza la función de inicialización para toda la configuración de estado.
  • No cambies el orden ni los tipos de variables de estado al crear nuevas versiones de contratos de implementación.
  • Si se requieren nuevas variables, deben añadirse después de todas las variables existentes.
  • Para implementaciones del patrón Diamond, utiliza métodos de almacenamiento especiales optimizados para ese patrón.
  • Se prefiere el método UUPS al patrón de proxy transparente siempre que sea posible, ya que requiere menos gas para las operaciones rutinarias.
  • Asegúrate de que la cuenta de administrador del proxy sea muy segura, ya que esta cuenta controla el proceso de actualización y es un punto crítico para la seguridad.
  • Por último, haz que todos los contratos sean auditados profesionalmente por expertos en seguridad de contratos inteligentes antes de implementarlos.

Reflexiones finales

Los patrones proxy proporcionan un potente mecanismo para actualizar los contratos inteligentes, al tiempo que mantienen la misma dirección y el mismo estado. El contrato proxy utiliza delegateCall para pasar la ejecución a los contratos de implementación, de modo que se pueda cambiar la lógica subyacente sin modificar la interfaz de usuario.

Sin embargo, si los contratos actualizables no se implementan correctamente, pueden suponer graves vulnerabilidades de seguridad.

Los desarrolladores deben considerar cuidadosamente las ventajas e inconvenientes de los diferentes tipos de patrones proxy, adherirse a las mejores prácticas establecidas y garantizar que se realicen las auditorías de seguridad adecuadas para crear contratos inteligentes fiables, seguros y actualizables.

Comparación de patrones proxy

A la hora de comparar qué patrón proxy utilizar, hay varios factores que debes tener en cuenta:

Comparación de patrones proxy

CaracterísticaTransparenteUUPSBeaconDiamante
Actualizar ubicaciónContrato de representaciónContrato de implementaciónContrato BeaconContratos de implementación
Inmutabilidad permanenteNoSí.NoSí.
Proxies múltiplesActualizaciones individualesActualizaciones individualesActualización de baliza únicaActualizaciones individuales
Eficiencia de combustibleMayor coste (comprobación administrativa)Menor costeMedio (búsqueda adicional)Medio (búsqueda por facetas)
Límite de tamaño del contrato24 KB24 KB24 KB24 KB por faceta.
Complejidad de la implementaciónMedioMedioMedioMedio

Consideraciones sobre la selección de patrones

Consideraciones clave para la selección de patrones:

  • Todos los patrones necesitan un contrato proxy y utilizan la delegación para transmitir las llamadas.
  • El patrón de proxy transparente se utiliza para almacenar las funciones de actualización en el propio contrato de proxy.
  • UUPS incluye las funciones de actualización en el contrato de implementación.
  • El patrón Beacon utiliza un contrato Beacon independiente para las actualizaciones.
  • El patrón Diamond suele colocar las funciones de actualización en los contratos de implementación, pero la especificación no exige que se haga así.
  • Solo los patrones UUPS y Diamond tienen la opción de hacer que los contratos sean permanentemente inmutables eliminando la función de actualización de las versiones futuras.
  • El patrón Beacon es ideal si tienes varios proxies que actualizar al mismo tiempo, ya que solo es necesario actualizar el beacon y no cada proxy.
  • El tamaño máximo del contrato es de 24 kilobytes para los patrones Transparent, UUPS y Beacon.
  • El patrón Diamond admite que cada faceta tenga un tamaño de hasta 24 kilobytes, por lo que se puede admitir una funcionalidad total mucho mayor.
  • Todos los patrones tienen una complejidad de implementación media y existen bibliotecas bien establecidas para los patrones Transparent, UUPS y Beacon.

FAQ

#proxy patterns
#smart contract upgradeability
#blockchain security
BDS

Pioneros en el futuro de la tecnología blockchain con soluciones innovadoras que empoderan a empresas e individuos en todo el mundo.

+1 929 560 3730 (EE.UU.)
+44 2045 771515 (Reino Unido)
+372 603 92 65 (Estonia)
Condado de Harju, Tallin, Lasnamäe, Katusepapi tn 6-502, 11412, Estonia

Mantente actualizado

Recibe las últimas noticias de blockchain directamente en tu correo.