﻿---
title: "Colisión de almacenamiento del proxy: cómo una actualización corrompe el estado"
description: "El proxy conserva el estado mientras cambia el código de implementación. Vea cómo un layout incompatible sobrescribe saldos, propietarios y controles, y cómo validar una actualización."
image: "https://wiki.fcontext.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://wiki.fcontext.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Colisión de almacenamiento del proxy: cómo una actualización corrompe el estado

> Solo con fines educativos; no constituye asesoramiento de inversión. Invertir puede causar pérdidas.

<a id="answer"></a>

## Respuesta directa

Una colisión de almacenamiento de proxy ocurre cuando el código de implementación lee o escribe un slot del proxy con un significado distinto del definido por el layout que creó el estado existente. Una actualización puede hacer que un saldo se interprete como una dirección, borrar al propietario, corromper el slot base de un mapping o sobrescribir datos de control de actualización.

Con `delegatecall`, el bytecode de implementación se ejecuta en el contexto del proxy: el almacenamiento, el saldo y `address(this)` pertenecen al proxy. Los nombres de variables no se guardan en la cadena; la EVM solo sigue el slot y el desplazamiento de bytes calculados por el código nuevo.

Por eso, una actualización debe conservar el layout desplegado, no limitarse a compilar correctamente o exponer las mismas funciones. Antes de autorizarla, hay que comparar los layouts generados por el compilador con la versión exacta desplegada.

<a id="mechanism"></a>

## Cómo funciona

Solidity normalmente coloca las variables de estado desde el slot `0`, en orden de declaración tras la linealización C3 de la herencia. Los valores menores de 32 bytes pueden compartir slot; las estructuras y matrices tienen reglas adicionales, mientras que los mappings y matrices dinámicas derivan la ubicación de sus datos de un slot base. Si el slot base se desplaza, también cambia la ubicación de sus datos derivados.

Hay cuatro límites de colisión distintos que deben auditarse:

- **Proxy frente a implementación:** los campos propios del proxy, como la implementación o el administrador, no deben ocupar slots usados por el estado de la aplicación. ERC-1967 asigna slots normalizados, evitados por el compilador, para implementación, beacon y administrador.
- **Implementación anterior frente a nueva:** las variables existentes deben conservar slots, desplazamientos y tipos compatibles. Añadir una variable al final puede ser seguro; insertarla, reordenarla, eliminarla o cambiar su tipo puede reinterpretar palabras existentes.
- **Herencia:** añadir estado a un contrato base o cambiar el orden de herencia puede desplazar el almacenamiento de los descendientes aunque su código fuente no cambie.
- **Almacenamiento reservado o con namespaces:** un gap bien consumido reserva espacio para un contrato base y los namespaces tipo ERC-7201 aíslan layouts. Ninguna técnica permite cambios arbitrarios dentro de un layout existente.

<a id="example"></a>

## Ejemplo

Supongamos que la versión 1 tiene este layout:

```solidity
uint256 totalAssets; // slot 0
address owner;       // slot 1
```

La versión 2 inserta incorrectamente una variable al principio:

```solidity
bool paused;         // slot 0, offset 0
uint256 totalAssets; // slot 1
address owner;       // slot 2
```

Tras la actualización, `paused` lee el byte bajo del antiguo `totalAssets`, el nuevo `totalAssets` lee la palabra del antiguo `owner` como entero y `owner` lee lo que ya había en el slot `2`, normalmente cero. Las palabras originales siguen almacenadas, pero el código nuevo les da otros significados. Una transacción puede completarse mientras aplica autorización o contabilidad sobre interpretaciones corruptas.

<a id="risks"></a>

## Riesgos y comprobaciones de actualización

- Genere el layout de almacenamiento de ambas implementaciones y compare slot, desplazamiento, tipo y herencia con el contrato de referencia realmente desplegado.
- En un layout lineal convencional, añada variables solo al final. No reordene campos, cambie sus tipos, los elimine y reutilice ni modifique contratos base sin demostrar compatibilidad.
- Al consumir un gap, redúzcalo por el número exacto de slots reservados usados. Con namespaces, mantenga identificadores únicos y valide los cambios dentro de cada namespace existente.
- No considere ERC-1967 una protección completa. Separa los metadatos del proxy de los slots de aplicación asignados por el compilador, pero no vuelve compatibles dos layouts de implementación.
- Pruebe la actualización y cualquier reinicializador en un fork o una instantánea de estado. Verifique antes y después propietarios, roles, saldos, allowances, entradas de mappings, pausa, slots de implementación y controles de reversión o emergencia.

Si una actualización ya pudo causar una colisión, detenga nuevas actualizaciones y llamadas que cambien estado cuando la gobernanza lo permita. Conserve el número de bloque previo y el bytecode, compare el almacenamiento bruto de los slots afectados y encargue a especialistas un plan de migración con revisión independiente. Repetir actualizaciones sin un mapa de almacenamiento demostrado puede destruir más estado recuperable.

<a id="misconceptions"></a>

## Errores frecuentes

- **«Los nombres no cambiaron, así que el layout es seguro».** Los nombres no determinan posiciones. Las determinan los tipos, el orden, el empaquetado, la herencia y los namespaces.
- **«Eliminar una variable libera su slot».** El almacenamiento del proxy persiste. Reutilizarlo da un significado nuevo a la palabra anterior, salvo que una migración revisada la borre o transforme.
- **«Una transacción de prueba exitosa demuestra compatibilidad».** Puede tocar pocos slots. La validación y las pruebas de diferencias de estado deben cubrir campos privilegiados, valores empaquetados, mappings, matrices y almacenamiento heredado.

<a id="related"></a>

## Temas relacionados

- [Riesgo de almacenamiento de delegatecall](/es/crypto/delegatecall-storage-risk/)
- [Toma de control del inicializador](/es/crypto/initializer-takeover/)
- [Contrato proxy](/es/crypto/proxy-contract/)
- [Supervisión de actualizaciones del proxy](/es/crypto/proxy-upgrade-monitoring/)
- [Contrato actualizable](/es/crypto/upgradeable-contract/)

<a id="sources"></a>

## Fuentes

- [Introducción a los contratos inteligentes](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html) - Solidity Documentation (consulta: 2026-08-21)
- [Layout de variables de estado en almacenamiento](https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html) - Solidity Documentation (consulta: 2026-08-21)
- [ERC-1967: slots de almacenamiento de proxy](https://eips.ethereum.org/EIPS/eip-1967) - Ethereum Improvement Proposals (consulta: 2026-08-21)
- [Cómo escribir contratos actualizables](https://docs.openzeppelin.com/upgrades-plugins/writing-upgradeable) - OpenZeppelin Documentation (consulta: 2026-08-21)

Source: https://wiki.fcontext.com/es/crypto/proxy-storage-collision/index.mdx
