En 2017 la biblioteca de la billetera multi-sig de Parity — usada como contrato subyacente para muchas de las mayores tesorerías de Ethereum — sufrió dos incidentes catastróficos distintos con cuatro meses de diferencia. El impacto combinado: aproximadamente $30 M robados y otros $150 M+ permanentemente congelados sin ruta on-chain hacia la recuperación.
Qué ocurrió
19 de julio de 2017 — El drenaje (~$30 M)
El multi-sig de Parity era un proxy delgado que llamaba a un contrato de biblioteca compartido vía delegatecall. La biblioteca exponía una función initWallet que, al ser llamada en una billetera, establecía los propietarios de la billetera. La función era llamable por cualquiera, en cualquier billetera, incluso después de que la billetera hubiera sido inicializada.
Un atacante recorrió Ethereum, llamando a initWallet en billeteras Parity que no le pertenecían — sobrescribiendo sus propietarios con su propia dirección — y luego retiró los saldos. Aproximadamente 150.000 ETH (~$30 M) fueron drenados de tres grandes billeteras, incluyendo las de los ICOs de Edgeless Casino, Swarm City y æternity. Un grupo white-hat se adelantó al atacante en varias otras billeteras y rescató un estimado de $200 M.
Parity desplegó un contrato de biblioteca parcheado.
6 de noviembre de 2017 — La congelación (~$150 M+)
La biblioteca parcheada aún contenía un problema sutil: initWallet aún podía llamarse en el propio contrato de biblioteca, convirtiendo la biblioteca en una billetera multi-sig propiedad del llamador. Un usuario — devops199 en GitHub — hizo exactamente eso, reclamando accidentalmente la propiedad del contrato de biblioteca, luego llamó a la función kill de la biblioteca (un selfdestruct) para "deshacer" su error.
Selfdestruct eliminó el bytecode de la biblioteca permanentemente. Cada multi-sig de Parity existente dependía del delegatecall a esa biblioteca para funcionar. Con la biblioteca desaparecida, todas esas billeteras se convirtieron en ladrillos — podían recibir ETH y tokens, pero nada dentro de ellas podía retirarse jamás.
Aproximadamente 513.743 ETH ($150 M en ese momento, varios miles de millones a precios máximos) quedaron congelados en 151 billeteras, incluyendo la tesorería del ICO de Polkadot (el mismo equipo de Parity).
Consecuencias
- Parity propuso EIP-999 para recuperar los fondos congelados mediante un hard fork que modificara el estado. La comunidad lo rechazó; Ethereum eligió la inmutabilidad sobre la restitución esta vez, a pesar de haber hecho lo opuesto para The DAO dieciocho meses antes.
- Los fondos permanecen congelados en la mainnet de Ethereum hasta el día de hoy — un monumento permanente al patrón de biblioteca
delegatecall.
Por qué importa
Parity estableció dos prácticas duraderas: nunca exponer funciones de inicialización que puedan ser reinvocadas, y no poner implementación crítica en una biblioteca compartida y killable. El equivalente moderno — proxies actualizables UUPS — prohíbe explícitamente selfdestruct en el contrato de implementación por exactamente la razón que Parity demostró.
El resultado asimétrico — DAO recuperado, Parity no — también mostró cómo el consenso de la comunidad sobre intervenciones de emergencia es fundamentalmente arbitrario, y depende de quién pregunta, cuán grande es la pérdida y cuán político es el momento.
Fuentes y evidencia on-chain
- [01]openzeppelin.comhttps://www.openzeppelin.com/news/on-the-parity-wallet-multisig-hack-405a8c12e8f7
- [02]techcrunch.comhttps://techcrunch.com/2017/11/07/a-major-vulnerability-has-frozen-hundreds-of-millions-of-dollars-of-ethereum/
- [03]theregister.comhttps://www.theregister.com/2017/11/10/parity_280m_ethereum_wallet_lockdown_hack/