ERC-4626 es una extensión de ERC-20 que define una API estándar para bóvedas tokenizadas que contienen un único activo subyacente ERC-20. La bóveda en sí es un token cuyas participaciones representan un derecho proporcional sobre los activos de la bóveda, y el estándar fija las funciones de depósito, acuñación, retiro, canje y conversión con las que los integradores pueden contar. Este artículo explica el modelo mental de participaciones y activos, recorre una bóveda ejecutable basada en OpenZeppelin, muestra cómo verificar un despliegue mediante JSON-RPC y cubre el ataque de inflación y los estándares de extensión (ERC-7540, ERC-7575) que manejan casos asíncronos y multi-activo. Separa lo que la especificación exige de lo que debes medir en tu propio despliegue.
Qué estandariza ERC-4626 y qué deja a tu criterio
ERC-4626, finalizado como EIP-4626, es una API estándar para bóvedas tokenizadas que representan participaciones de un único token subyacente ERC-20. El contrato de la bóveda debe implementar ERC-20, por lo que las unidades de la bóveda —llamadas participaciones— son tokens transferibles cuyos titulares tienen derecho sobre las tenencias subyacentes de la bóveda. El estándar define las funciones para depositar y retirar activos, acuñar y canjear participaciones, y leer las tasas de conversión entre ambos.
Lo que el estándar no define es la estrategia. Una bóveda conforme puede prestar en un mercado monetario, mantener bonos del tesoro tokenizados o simplemente permanecer inactiva; ERC-4626 solo fija la interfaz y la semántica contable en torno a totalAssets, totalSupply y las funciones de conversión. Las comisiones, los límites, el control de acceso y la fuente de rendimiento son decisiones de implementación. Por eso dos bóvedas ERC-4626 con la misma interfaz pueden comportarse de manera muy diferente bajo estrés.
Esta guía asume que puedes leer Solidity, tienes conocimientos prácticos de las aprobaciones ERC-20 y puedes acceder a un endpoint JSON-RPC de EVM. Para la selección de endpoints en lugar del diseño de interfaces, la descripción general de la API RPC de Ethereum y la guía de endpoints RPC cubren la conectividad; esta página se centra en el contrato de la bóveda en sí.
- La bóveda DEBE implementar ERC-20 y sus extensiones de metadatos opcionales (name, symbol, decimals).
- La bóveda gestiona exactamente un token subyacente
asset(). - Las funciones de conversión deben ser coherentes con
totalAssets()ytotalSupply()en el momento de la llamada. - La estrategia, las comisiones, los límites y el comportamiento de pausa quedan fuera del estándar.
El modelo mental de participaciones y activos
Piensa en una bóveda como una clase de participaciones de un fondo mutuo en la cadena. Un depositante aporta activos y recibe participaciones. El tipo de cambio es la relación entre los activos bajo gestión y las participaciones en circulación: si una bóveda tiene 100 activos que respaldan 200 participaciones, cada participación vale 0,5 activos. El rendimiento se acumula aumentando totalAssets mientras totalSupply permanece constante, de modo que el valor del activo por participación sube en lugar del número de participaciones.
El estándar expone esta relación mediante dos funciones de conversión y dos funciones de previsualización. convertToShares(assets) y convertToAssets(shares) informan la tasa en el estado actual. previewDeposit, previewMint, previewWithdraw y previewRedeem informan lo que haría una operación específica, incluido el redondeo. Los integradores deben usar las funciones de previsualización para las cotizaciones de cara al usuario porque tienen en cuenta la dirección del redondeo que aplica la bóveda.
El redondeo importa. Una bóveda debe redondear a favor de la bóveda, no del usuario, para que las operaciones pequeñas repetidas no puedan drenar valor. La especificación exige que previewDeposit y previewMint redondeen hacia abajo las participaciones emitidas, y que previewWithdraw y previewRedeem redondeen hacia arriba los activos requeridos. Una bóveda que redondea al revés es una señal de alerta durante la revisión de integración.
// Read-only checks any integrator can run against a deployed vault
interface IERC4626View {
function asset() external view returns (address);
function totalAssets() external view returns (uint256);
function convertToShares(uint256 assets) external view returns (uint256);
function convertToAssets(uint256 shares) external view returns (uint256);
function previewDeposit(uint256 assets) external view returns (uint256);
function maxDeposit(address receiver) external view returns (uint256);
}La interfaz completa en una sola pasada
El estándar agrupa sus funciones en cuatro rutas de escritura y un conjunto de rutas de lectura. Las cuatro rutas de escritura existen porque los usuarios pueden especificar la cantidad de activos o la cantidad de participaciones, y porque el llamador y el receptor pueden ser diferentes. deposit(assets, receiver) extrae una cantidad fija de activos y emite participaciones a receiver. mint(shares, receiver) emite un número fijo de participaciones y extrae los activos necesarios. withdraw(assets, receiver, owner) quema suficientes participaciones de owner para liberar una cantidad fija de activos. redeem(shares, receiver, owner) quema un número fijo de participaciones y libera los activos correspondientes.
Cada ruta de escritura tiene una vista max* correspondiente —maxDeposit, maxMint, maxWithdraw, maxRedeem— que informa el límite para una dirección dada. Los integradores deben verificarlas antes de enviar una transacción, porque una bóveda puede limitar los depósitos, pausar los retiros o restringir ciertas direcciones. Una transacción que ignora maxDeposit se revertirá y desperdiciará gas.
Las rutas de lectura incluyen asset, totalAssets, las dos funciones de conversión y las cuatro funciones de previsualización. El estándar también define los eventos Deposit y Withdraw, que los indexadores y sistemas contables usan para reconstruir la propiedad de las participaciones sin reproducir cada transferencia.
- Rutas de escritura: deposit, mint, withdraw, redeem.
- Vistas de límite: maxDeposit, maxMint, maxWithdraw, maxRedeem.
- Vistas de tasa: convertToShares, convertToAssets.
- Vistas de previsualización: previewDeposit, previewMint, previewWithdraw, previewRedeem.
- Eventos: Deposit(sender, owner, assets, shares) y Withdraw(sender, receiver, owner, assets, shares).
Construir una bóveda mínima conforme con OpenZeppelin
OpenZeppelin Contracts incluye una base ERC4626 que implementa la interfaz sobre ERC20 y SafeERC20. La base maneja las matemáticas de participaciones, las funciones de previsualización y la defensa de desplazamiento virtual contra el ataque de inflación. Una bóveda mínima solo necesita proporcionar la dirección del activo subyacente y un nombre y símbolo para las participaciones.
El siguiente ejemplo es un punto de partida, no una bóveda de producción. Mantiene los activos inactivos; una bóveda real añadiría una estrategia que aumente totalAssets con el tiempo y sobrescribiría totalAssets() para informar el valor de la estrategia. También hereda el desplazamiento virtual predeterminado de OpenZeppelin, que es la defensa base recomendada que se analiza más adelante.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {ERC4626} from "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract SimpleVault is ERC4626 {
constructor(IERC20 asset_)
ERC20("Simple Vault Share", "svSHARE")
ERC4626(asset_)
{}
// Idle vault: totalAssets() defaults to asset.balanceOf(address(this)).
// Override totalAssets() when a strategy holds the assets elsewhere.
}Verificar un despliegue mediante JSON-RPC
Antes de integrar una bóveda, confirma que su estado reportado coincide con la cadena. El procedimiento siguiente usa eth_call contra una dirección de bóveda y un titular conocido. Reemplaza RPC_URL con el endpoint de tu proveedor y VAULT_ADDRESS con la bóveda desplegada. Los selectores mostrados son los selectores estándar de cuatro bytes para asset(), totalAssets() y totalSupply(); puedes regenerarlos con cast sig o cualquier codificador ABI.
Ejecuta las llamadas en orden y registra los resultados en una tabla. La verificación esperada es que asset() devuelva el token subyacente que esperas, que totalAssets() sea al menos la suma de activos que puedes contabilizar, y que convertToShares(totalAssets()) se acerque a totalSupply() dentro del redondeo. Una gran discrepancia entre ambos es una señal para inspeccionar las sobrescrituras contables de la bóveda antes de depositar.
curl -s RPC_URL \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_call",
"params": [
{"to": "VAULT_ADDRESS", "data": "0x38d52e0f"},
"latest"
]
}'
# 0x38d52e0f = asset()
# 0x01e1d114 = totalAssets()
# 0x18160ddd = totalSupply()Registrar mediciones de integración
El cumplimiento de la interfaz no te dice si una bóveda es segura o líquida. Crea una pequeña hoja de medición y complétala con llamadas en vivo en lugar de con documentación. La siguiente tabla es una plantilla; cada valor debe provenir de tus propios resultados de eth_call o de un indexador de confianza, y deberías volver a ejecutarla en cada bloque que te interese.
| Comprobación | Método | Resultado esperado |
|---|---|---|
| Activo subyacente | asset() | Coincide con el token que pretendes depositar |
| Activos bajo gestión | totalAssets() | Coherente con los saldos de la estrategia que puedes verificar |
| Oferta de participaciones | totalSupply() | Distinta de cero tras el primer depósito |
| Cotización de depósito | previewDeposit(amount) | Participaciones redondeadas hacia abajo, distintas de cero |
| Cotización de canje | previewRedeem(shares) | Activos redondeados hacia abajo, como máximo totalAssets() |
| Límite de depósito | maxDeposit(you) | Al menos tu cantidad prevista |
| Límite de retiro | maxWithdraw(you) | Al menos tu cantidad prevista |
| Pérdida de ida y vuelta | previsualización de depósito y luego canje | Pequeña y explicable por redondeo y comisiones |
La comprobación de ida y vuelta es el número individual más útil. Previsualiza un depósito de un tamaño realista, luego previsualiza el canje de las participaciones que emitiría y compara los activos devueltos con los activos depositados. Una gran diferencia que no se explique por comisiones documentadas o redondeo es motivo para detenerse. No asumas un valor; mídalo en el bloque contra el que vas a transaccionar.
El ataque de inflación y la defensa de desplazamiento virtual
El escollo más conocido de ERC-4626 es el ataque de inflación, también llamado ataque de donación. Un atacante deposita una cantidad mínima para recibir una participación, luego dona una gran cantidad del subyacente directamente a la bóveda, inflando el valor del activo por participación. Un depositante posterior cuyos activos sean menores que el precio inflado de la participación puede ser redondeado a cero participaciones, y el atacante canjea la donación más el depósito de la víctima.
La defensa recomendada por OpenZeppelin es un desplazamiento virtual: las matemáticas de participaciones añaden una pequeña cantidad virtual de activos y una pequeña cantidad virtual de participaciones al numerador y al denominador, de modo que el primer depositante no puede hacer que una participación sea arbitrariamente cara. El contrato base lo aplica por defecto. Las bóvedas que sobrescriben las funciones internas de conversión deben preservar una defensa equivalente o documentar por qué su diseño hace que el ataque no sea rentable.
El ataque no es el único escollo. Los tokens subyacentes con comisión por transferencia rompen la suposición de que la bóveda recibe exactamente la cantidad depositada. Los tokens de rebase cambian totalAssets sin una transferencia. Las bóvedas que informan el valor de la estrategia deben manejar una pérdida de la estrategia sin permitir que los primeros en canjear salgan a la tasa anterior. Cada uno de estos es un motivo para leer las sobrescrituras de la bóveda en lugar de confiar solo en la interfaz.
- Mantén el desplazamiento virtual a menos que tengas una alternativa revisada.
- Rechaza o maneja especialmente los tokens subyacentes con comisión por transferencia y de rebase.
- Limita los depósitos hasta que la estrategia y la contabilidad estén auditadas.
- Prueba explícitamente la ruta del primer depositante en una prueba de fork.
Extensiones asíncronas y multi-activo
ERC-4626 asume depósitos y canjes atómicos hasta un límite. Esa suposición falla para protocolos de activos del mundo real, préstamos entre cadenas, staking líquido con colas de desvinculación y módulos de seguros donde la liquidación se retrasa. ERC-7540 extiende el estándar para bóvedas asíncronas: las solicitudes se envían y luego se reclaman más tarde, mientras que las funciones existentes de depósito, acuñación, retiro y canje se reutilizan para reclamar la solicitud liquidada.
ERC-7575 aborda bóvedas con múltiples activos o puntos de entrada, como los tokens de proveedor de liquidez. Dado que ERC-4626 exige que la bóveda misma sea un ERC-20, las bóvedas multi-activo son incómodas o no conformes bajo el estándar base; ERC-7575 externaliza el token de participaciones de la implementación de la bóveda para que esta pueda gestionar varios activos mientras sigue exponiendo una superficie compatible.
Si estás integrando una bóveda que anuncia ERC-4626 pero liquida de forma asíncrona, comprueba si implementa ERC-7540 y lee el ciclo de vida de la solicitud antes de construir una interfaz de usuario en torno a ella. Tratar una bóveda asíncrona como atómica producirá cotizaciones incorrectas y reclamaciones fallidas.
Solución de problemas comunes de integración
La mayoría de los errores de integración de ERC-4626 siguen unos pocos patrones. Un depósito se revierte porque el llamador no aprobó a la bóveda por la cantidad de activos, o aprobó al gastador equivocado. Un retiro se revierte porque maxWithdraw era cero debido a una pausa o un límite, o porque el llamador pasó un owner que no controla y no tenía asignación. Una cotización es incorrecta porque el integrador usó convertToShares en lugar de previewDeposit, ignorando el redondeo y las comisiones.
Un fallo más sutil es el estado obsoleto. Las cotizaciones calculadas en un bloque pueden ser inválidas cuando se confirma la transacción, especialmente en bóvedas cuyo totalAssets se mueve con una tasa de préstamo. Usa una fecha límite o un límite de deslizamiento donde la bóveda lo admita, y vuelve a comprobar los límites inmediatamente antes de enviar. Si el totalAssets de una bóveda salta sin un evento Deposit o Withdraw correspondiente, investiga donaciones o informes de estrategia antes de tratar la tasa como fiable.
Cuando una llamada falla en la capa RPC en lugar de en el contrato, confirma que el endpoint está sincronizado y que el ID de cadena coincide con el despliegue. Una dirección de bóveda de una red devolverá datos vacíos en otra. El directorio de redes enumera las cadenas compatibles, y el acceso a nodos dedicados merece consideración cuando necesitas lecturas de estado consistentes en muchas bóvedas.
- Comprueba la asignación y el gastador antes de cada depósito o acuñación.
- Lee los límites max* en el mismo bloque que la transacción.
- Prefiere las funciones de previsualización a la conversión directa para las cotizaciones.
- Confirma el ID de cadena y la sincronización del endpoint antes de depurar la lógica del contrato.
Limitaciones y compensaciones del estándar
ERC-4626 aporta composabilidad a costa de ocultar el riesgo de la estrategia tras una interfaz uniforme. Dos bóvedas con ABI idénticos pueden tener perfiles de riesgo completamente diferentes, y el estándar no ofrece a los integradores ninguna forma de expresar esa diferencia. Los agregadores que enrutan entre muchas bóvedas deben añadir su propia puntuación de riesgo, límites y monitorización sobre la interfaz.
El estándar también asume un único ERC-20 subyacente y liquidación atómica. Los proyectos que necesitan múltiples activos o liquidación diferida deben adoptar extensiones, y los proyectos con tokens no estándar deben manejar los casos límite por sí mismos. Nada de esto es un defecto del estándar; es el límite de lo que una interfaz mínima puede prometer.
Por último, el cumplimiento es necesario pero no suficiente. Una bóveda puede superar todas las comprobaciones de interfaz y seguir siendo económicamente insegura. Trata la interfaz como el billete de entrada y la hoja de medición como la verdadera diligencia debida.
Próximos pasos para constructores e integradores
Si estás construyendo una bóveda, parte de la base de OpenZeppelin, mantén el desplazamiento virtual, añade una estrategia con una sobrescritura explícita de totalAssets y escribe pruebas de fork para la ruta del primer depositante, los activos con comisión por transferencia y la pérdida de la estrategia. Si estás integrando, incorpora la hoja de medición a tu monitorización para que se ejecute en cada bloque contra el que cotizas, y alerta sobre cambios inexplicables en totalAssets.
Para el lado de la infraestructura, revisa los precios de RPC para dimensionar tu volumen de lectura, y usa el servicio de API cuando necesites acceso gestionado en lugar de ejecutar tus propios nodos. Para un contexto más amplio del protocolo, la biblioteca Learn cubre estándares relacionados y guías operativas. Las elecciones concretas de endpoint y proveedor se manejan mejor con el Asistente de RPC, que mantiene las recomendaciones breves y actuales separadas de esta guía de implementación.