
Evaluación de seguridad del protocolo Garden: Trail of Bits
Técnico
TL;DR, Trail of Bits auditó los contratos GardenStaker, HTLC y FEEAccount de Garden a lo largo de un encargo de dos semanas. Se identificaron nueve hallazgos con severidad High, Medium, Low e Informational; ningún problema Critical. Seis se resolvieron directamente en el código; tres se abordaron mediante cambios operativos a nivel de protocolo.
Garden contrató a Trail of Bits para realizar una evaluación de seguridad de los contratos onchain del protocolo que implementan swaps cross-chain de BTC mediante HTLCs, la distribución de comisiones a los fillers y las mecánicas de staking y delegación que sustentan la participación de los solvers. La revisión estuvo a cargo de Richie Humphrey y Vara Prasad Bandaru, con Josselin Feist como director de ingeniería, a lo largo de dos semanas-ingeniero. Posteriormente se realizó una revisión de las correcciones y el informe resumen se entregó en abril de 2024.
Trail of Bits señaló que el código en sí era de alta calidad, con una clara atención a la seguridad en su diseño. El principal reto de la revisión no fue entender los contratos de forma individual, sino entender cómo interactuaban con el sistema en su conjunto, en particular la lógica de coordinación entre el libro de órdenes, la firma de comisiones y la selección de fillers que determina cómo se usan realmente los contratos onchain.
Alcance
Tres contratos onchain estaban dentro del alcance:
- GardenStaker: gestiona el registro de fillers, el staking de los delegadores, el poder de voto y el ciclo de vida del stake
- GardenHTLC: implementa el mecanismo HTLC para la iniciación, la redención y el reembolso del swap
- FEEAccount: gestiona los canales de pago de comisiones entre el fee manager, los fillers y los delegadores (anteriormente llamado GardenFEEAccount)
Trail of Bits usó Slither para el análisis estático y Echidna para el fuzzing de invariantes con estado sobre GardenStaker. Se probaron dos propiedades y ambas se superaron: que el saldo de tokens SEED del contrato staker es igual a la suma neta de todos los stakes, y que todos los fillers ostentan el rol de filler de forma exclusiva.
Hallazgos
Trail of Bits identificó nueve hallazgos. El desglose por severidad: tres High, tres Medium, dos Low, uno Informational. No se identificó ningún problema de severidad Critical.
TOB-CATALOG-1; Liquidez de los fillers vulnerable a un ataque DoS | High
Como no hay penalización por reembolsar órdenes, un atacante puede iniciar órdenes de swap sin intención de completarlas, bloqueando la liquidez de los fillers durante todo el timelock del HTLC y llamando después a refund tras el vencimiento. Repetido a escala, esto agotaría la capacidad disponible de los fillers y desactivaría en la práctica el sistema de swaps.
La dificultad de explotación se califica como High, ya que el atacante debe bloquear sus propios fondos durante el doble de la duración del timelock del filler, lo que hace que el ataque sea intensivo en capital. Trail of Bits propuso varias vías de mitigación: exigir depósitos del iniciador que se devuelvan tras una redención exitosa, cobrar comisiones de iniciación o exigir stakes de SEED a los iniciadores.
TOB-CATALOG-2; Cualquiera puede provocar la autodestrucción de la plantilla FeeAccount | High
El constructor de GardenFEEAccountFactory despliega un contrato plantilla GardenFEEAccount (ahora llamado FEEAccount) sin inicializarlo ni deshabilitar sus initializers. Como FEEAccount.close y .settle llaman ambos a closeChannel, que activa selfdestruct, un atacante podría inicializar la plantilla con sus propias direcciones y llamar a close sobre ella, destruyendo la plantilla. Dado que los clones hacen delegate-call a la plantilla, todas las llamadas posteriores a canales de comisiones activos se convertirían en no-operaciones y los tokens depositados se perderían de forma permanente.
TOB-CATALOG-3; Las comisiones pueden retirarse antes de iniciar una orden | Medium
El fee manager prefirma los mensajes de reclamación para los delegadores antes de que una orden de swap se inicie onchain, usando el secretHash que proporciona el creador. Un delegador malicioso que tenga acceso a ese mensaje prefirmado y conozca el secreto puede reclamar comisiones sin que el swap correspondiente llegue a iniciarse nunca. Se trata de un problema de ordenación del flujo del protocolo: la vulnerabilidad reside en cómo el sistema secuencia sus operaciones de firma en relación con la iniciación onchain.
TOB-CATALOG-4; Un creador puede reclamar comisiones sin redimir la orden | Medium
Los HTLCs de pago de comisiones y los HTLCs de swap comparten la misma duración de timelock (48 horas) y el mismo secreto. Como el secreto solo lo conoce el creador, este puede esperar a que venza el HTLC del swap, llamar a refund para recuperar sus tokens bloqueados y después usar el secreto para reclamar las comisiones de los delegadores por una orden que nunca completó. Garden identificó este problema de forma independiente durante la revisión.
TOB-CATALOG-5; Los delegadores pueden extender su stake con un multiplicador de voto más alto | Low
La función extend de DelegateManager sube correctamente el multiplicador de voto de un delegador cuando la extensión es por un periodo más largo, pero no lo baja cuando la extensión es por un periodo más corto. Un delegador que originalmente hizo stake por cuatro años podría extenderlo seis meses cerca del final de su periodo de bloqueo y conservar el multiplicador de cuatro años indefinidamente.
Garden reconoció que esto es intencionado: el protocolo está diseñado para recompensar a los stakers de larga duración, y conservar el multiplicador por periodos de bloqueo completados es coherente con ese objetivo. Garden añadió documentación para aclarar el comportamiento previsto.
TOB-CATALOG-6; Uso inconsistente del término "expiry" | Informational
El término expiry se usaba con el significado de número de bloque absoluto en GardenStaker, pero de duración relativa (número de bloques) en GardenHTLC. Los comentarios NatSpec y el README agravaban la confusión al describir incorrectamente expiry como un número de bloque en todo el código. Esta inconsistencia semántica crea un riesgo de mantenibilidad: un desarrollador que razone sobre expiry en ambos contratos podría introducir un comportamiento incorrecto.
TOB-CATALOG-7; El manejo incorrecto de delegateStakeIDs deshabilita funcionalidad crítica | High
Cuando un filler se da de baja y llama a refund, la struct Filler se elimina del mapping fillers mediante el delete de Solidity. Sin embargo, el campo delegateStakeIDs es un EnumerableSet de OpenZeppelin, que internamente usa tanto un array como un mapping. El delete de Solidity pone a cero la longitud del array, pero no borra las entradas de índice del mapping. Cuando llamadas posteriores intentan eliminar entradas del set, leen un valueIndex distinto de cero del mapping obsoleto pero encuentran un array de longitud cero, lo que provoca un panic revert.
La consecuencia práctica: cualquier delegador cuyo filler se dé de baja y llame a refund pierde de forma permanente la capacidad de llamar a changeVote o refund sobre su propio stake. Incluso si el filler se vuelve a registrar, las asociaciones de stake existentes no se restauran: los stakes quedan bloqueados de forma permanente. Este problema se identificó mediante Slither.
TOB-CATALOG-8; Un usuario no puede renovar su stake por la duración máxima | Low
La función renew calcula el nuevo expiry como block.number + newLockBlocks. Cuando un usuario pasa el valor máximo de uint256 para representar un staking indefinido, esta suma se desborda y hace que la transacción revierta. Un usuario cuyo stake vence no puede renovarlo por la duración máxima.
TOB-CATALOG-9; Los delegadores pierden recompensas cuando unos HTLCs vencen antes que otros en un canal | Medium
La función claim de GardenFEEAccount itera sobre un array de HTLCs y excluye en silencio los que hayan vencido, sin revertir ni registrar el déficit. En un canal de pago con varios HTLCs activos, si uno vence antes de que el delegador reclame debido a retrasos en la finalización del swap, las recompensas asociadas se pierden de forma irrecuperable. La dificultad de explotación se califica como High porque desencadenar la condición requiere una secuencia específica de eventos temporales a lo largo de varios swaps.
Acción
Seis de los nueve hallazgos se resolvieron en el código. Tres se abordaron mediante cambios operativos a nivel de protocolo.
Resueltos en el código:
- TOB-CATALOG-2 se corrigió añadiendo una función initialize a la implementación de GardenFEEAccount que llama a _disableInitializers, impidiendo cualquier inicialización futura del contrato plantilla.
- TOB-CATALOG-5 se reconoció como una decisión de diseño intencionada y se resolvió añadiendo documentación que aclara el comportamiento previsto de conservación del multiplicador.
- TOB-CATALOG-6 se resolvió renombrando la variable; expiry ahora se refiere de forma consistente a un número de bloque absoluto, y timelock se refiere a una duración relativa en ambos contratos. (a fecha de 23 de abril de 2026, el vencimiento de la orden se determina mediante timelock en lugar de expiry)
- TOB-CATALOG-7 se resolvió cambiando la lógica de baja del filler para restablecer los miembros de datos individuales en lugar de eliminar toda la struct, dejando delegateStakeIDs intacto. Esto permite que los delegadores existentes sigan llamando a changeVote y refund, y garantiza que el nuevo registro reactive automáticamente sus asociaciones de stake.
- TOB-CATALOG-8 se resolvió añadiendo una comprobación de la condición de duración máxima en la función renew, que fija stake.expiry directamente en type(uint).max cuando se selecciona el periodo de bloqueo máximo.
- TOB-CATALOG-9 se resolvió actualizando la función claim para almacenar en mappings tanto los secretos reclamados como los enviados, permitiendo que las reclamaciones parciales se completen sin perder las recompensas de otros HTLCs del mismo canal.
TOB-CATALOG-1, TOB-CATALOG-3 y TOB-CATALOG-4 se abordaron mediante cambios operativos a nivel de protocolo. Para TOB-CATALOG-1, Garden implementó un límite de 1.5 BTC/WBTC por dirección cada 24 horas durante el periodo beta, con una comisión de plataforma no reembolsable prevista para el lanzamiento público (actualmente activa). Para TOB-CATALOG-3, Garden reordenó el flujo de firma de comisiones para que los fillers entreguen su firma a FeeHub solo después de que el usuario inicie en la cadena de origen. Para TOB-CATALOG-4, Garden endureció las restricciones de tiempo entre la iniciación del swap y la firma del HTLC de comisiones. Trail of Bits confirmó que estas mitigaciones estaban descritas y eran plausibles.
Resumen
Nueve hallazgos: tres de severidad High, tres Medium, dos Low y uno Informational. Ningún problema Critical. Todos los problemas se resolvieron.
Desde esta evaluación, Garden ha completado una evaluación de seguridad de la aplicación Move con Zellic (junio de 2025) y ha realizado un bug bounty competitivo a través de Code4rena con $37,500 en recompensas repartidas en 813 propuestas, dirigido a la arquitectura HTLC en EVM, Solana, Sui y Starknet.
Last updated