Un test de Foundry muestra cómo un donante deja a otro sin acciones en un vault ERC-4626
El proyecto Vault Price Honesty convierte cinco casos límite de ERC-4626 en pruebas reproducibles y encuentra un depósito de 50 tokens que recibe cero acciones.

Un desarrollador ha publicado un conjunto de pruebas en Foundry que documenta cinco casos límite del estándar ERC-4626, y uno de ellos se lee entero en dos líneas: un usuario deposita 50 tokens en un vault y recibe cero acciones. No hay un fallo de implementación detrás. Alguien había depositado antes una unidad base y después transfirió 10.000 tokens directamente al contrato.
El proyecto se llama Vault Price Honesty y el repositorio incluye los tests y los informes. ERC-4626 define una interfaz común para vaults tokenizados: el usuario mete un ERC-20 y recibe acciones que representan una parte de los activos, que el vault puede prestar, poner en staking o mandar a otra estrategia de rendimiento. El tipo construyó el proyecto pensando en un contrato base reutilizable y acabó reconvirtiéndolo en una batería de pruebas, porque el comportamiento depende demasiado del diseño de cada vault.
Tres fixtures, tres resultados
El caso más citado usa un vault basado en OpenZeppelin con offset de decimales cero. El atacante deposita una unidad base de un token de 18 decimales y transfiere 10.000 tokens al vault. La víctima deposita 50 y se queda a cero. El atacante puso 10.000 más 1 wei y puede retirar unos 5.025, así que su resultado neto es de aproximadamente −4.975 tokens. Sale perdiendo: la secuencia demuestra griefing, no beneficio. Provocar la pérdida de 50 tokens le cuesta cerca de 4.975.
Con offset de decimales tres, el mismo guion cambia. La víctima recibe acciones redimibles por unos 45,02 tokens, casi un 10% por debajo de lo aportado. Un test que solo compruebe que la víctima obtuvo acciones se perdería esa merma, y comparar el número bruto de acciones entre los dos vaults engaña, porque el offset altera la precisión. Lo que se compara es cuántos activos subyacentes recuperan esas acciones.
El tercer fixture parte de cero acciones y 500 tokens donados ya dentro. El siguiente usuario deposita 1.000 y recibe acciones que redimen 750. Otra vez, un saldo de acciones distinto de cero esconde una pérdida considerable. Ese escenario dona activos a un vault vacío a propósito y no debe confundirse con el redondeo que deja una redención normal.
Lo que no demuestra
El autor insiste en separar la observación de la conclusión. En una ejecución contra un fork, transferir tokens a sUSDe elevó sus activos declarados y el valor de cada acción, pero eso no basta para afirmar que hay daño: haría falta seguir una consecuencia concreta, como el ida y vuelta de un depositante, el cálculo de una comisión o una integración que use ese precio como valor de colateral. Con totalAssets() pasa lo mismo; una estrategia puede custodiar los activos fuera de la dirección del vault, así que la diferencia entre lo declarado y el saldo real no implica error de valoración.
Los previews sí tienen referencia explícita en la especificación ERC-4626: si a un preview le sigue su operación en la misma transacción y sin cambios en las condiciones, deposit y redeem deben devolver al menos lo anticipado, y mint y withdraw no deben exigir más. Cualquier discrepancia se contrasta contra ese texto antes de llamarla incumplimiento.
Lo que queda abierto es lo de siempre en este tipo de contabilidad: la economía con otros importes donados, con varias víctimas o sobre implementaciones distintas. Las protecciones compartidas sirven, pero no resuelven esas decisiones de diseño.

