Ethereum: de historia a labs
Artículo 43 de 48
90%
completado al llegar aquí
Sistemas distribuidosNota de investigación13 min de lectura
Lending y liquidaciones: cuando el colateral respira mal
Cómo se presta contra colateral: health factor, close factor y bonus de liquidación en Aave V3, y por qué oráculo y liquidador sostienen la solvencia.
Ruta Ethereum: 0/48
Prerequisitos recomendados
Si alguno de estos conceptos todavía está medio nebuloso, empieza por aquí. Te ahorra tropiezos y un par de cejas fruncidas.
Oráculos: datos externos con dientes
Cómo llega un precio a un contrato: feeds agregados de Chainlink, heartbeat y desviación, chequeos de frescura, TWAP frente a precio spot y manipulación en una transacción.
Blockchain16 min de lectura→AMMs: x*y=k sin vender humo matemático
Un AMM de producto constante con números reales: invariante x·y=k, comisión, LP shares, por qué el precio spot no es un oráculo y qué pierde el LP.
Blockchain13 min de lectura→
Imagina que depositas 10 ETH en un protocolo de préstamos y pides 12 000 USDC contra ellos. Nadie revisó tu historial crediticio y nadie te llamará si no pagas. Entonces, ¿qué protege a quienes pusieron esos USDC en el pool? La respuesta es una regla que cualquiera puede ejecutar: si el valor de tu colateral cae demasiado, un tercero puede pagar parte de tu deuda y quedarse con parte de tu colateral, con descuento.
Esa regla es la liquidación. Este capítulo la recorre con el código de Aave V3 como referencia: cómo se mide la salud de una posición, qué puede hacer un liquidador y qué partes del sistema (el oráculo de precios y el propio liquidador) pueden fallar. Los números del ejemplo son hipotéticos y sirven solo para seguir la aritmética.
Flujo visual
De posición sana a liquidación
Brújula de lectura
Actor, evidencia y estado
Actor
LiquidadorCualquier cuenta que llame a liquidationCall cuando el health factor está bajo 1.
Evidencia
Precio del oráculoEl protocolo no ve el mercado; ve el número que le entrega su oráculo en ese bloque.
Estado
Colateral y deudaSaldos del usuario en el pool, expresados en la moneda base para calcular el health factor.
Preguntas guía
Usa estas preguntas para leer el capítulo como un diseñador del sistema, no como usuario:
- ¿Qué número exacto decide que una posición es liquidable, y quién lo calcula?
- ¿Por qué un tercero querría pagar la deuda de otro?
- ¿Cuánta deuda puede repagar un liquidador en una sola llamada, y por qué no toda?
- ¿Qué pasa si el precio que ve el contrato está desactualizado o fue manipulado?
- ¿Cuándo una liquidación llega tarde y el pool termina con deuda incobrable?
Conexiones dentro de la serie
- Antes: Uniswap v3: liquidez concentrada y ticks, porque el liquidador suele vender el colateral en un AMM.
- Después: Indexadores: eventos, reorgs e idempotencia, que explica cómo leer de forma fiable los eventos de liquidación.
Prerequisitos internos recomendados:
- Oráculos: datos externos con dientes, para el origen del precio.
- AMMs: x*y=k sin vender humo matemático, para entender la liquidez donde se vende el colateral.
- MEV y PBS: quién arma el bloque importa, porque las liquidaciones compiten por espacio en el bloque.
Invariante de solvencia: qué mide el health factor
Empecemos con vocabulario. El colateral es lo que depositas como garantía. La deuda es lo que pides prestado. Cada activo de colateral tiene un umbral de liquidación (liquidation threshold, LT): la fracción de su valor que cuenta para sostener deuda. Un LT de 80 % significa que 100 USD de colateral sostienen como máximo 80 USD de deuda antes de que la posición sea liquidable.
El health factor (HF) junta todo en un número. En Aave V3 se calcula como la suma del colateral en moneda base, ponderada por su umbral de liquidación medio, dividida por la deuda total en moneda base. Si no hay deuda, el HF es el máximo representable. [2]
Aquí es el valor del colateral en moneda base, su umbral y la deuda total en moneda base. La posición es liquidable cuando : la validación de liquidationCall exige que el health factor esté por debajo de HEALTH_FACTOR_LIQUIDATION_THRESHOLD, que vale 1e18 (es decir, 1,0 con 18 decimales). [3]
Con el ejemplo hipotético: 10 ETH a 2000 USD, LT de 80 % y deuda de 12 000 USDC dan . Si ETH baja a 1450 USD, . Nadie movió un token, pero la posición ya es liquidable.
El invariante que el protocolo intenta sostener es más amplio que el HF de una cuenta: el valor del colateral recuperable debe cubrir la deuda total del pool. El HF es la alarma temprana. Si nadie actúa a tiempo, el colateral puede caer por debajo de la deuda y aparece la deuda incobrable (bad debt): préstamos que ya nadie tiene incentivo para repagar.
Traza de ejecución de una liquidación en Aave V3
El punto de entrada es una función pública del pool. Cualquiera puede llamarla; no hay lista de liquidadores autorizados. [4]
// Firma tomada de IPool.sol (aave-v3-core).
function liquidationCall(
address collateralAsset, // colateral que el liquidador quiere recibir
address debtAsset, // deuda que el liquidador repaga
address user, // posición a liquidar
uint256 debtToCover, // cuánta deuda quiere cubrir
bool receiveAToken // recibir aTokens o el activo subyacente
) external;La ejecución sigue cuatro pasos. Primero, valida que el HF del usuario esté por debajo de 1 y que las reservas estén activas y no pausadas. Segundo, fija el close factor, la fracción máxima de deuda que se puede repagar en una llamada: 50 % si el HF está por encima de 0,95 y 100 % si está en 0,95 o menos. [1]
Tercero, calcula cuánto colateral entrega. Convierte la deuda cubierta a unidades de colateral con los precios del oráculo y la multiplica por el bonus de liquidación, un parámetro por activo expresado como porcentaje sobre 100 % (por ejemplo, 10 500 equivale a 105 %). Si el usuario no tiene tanto colateral, se entrega todo el disponible y se reduce la deuda cubierta en proporción. Cuarto, si el activo tiene configurada una fee de liquidación, una parte del bonus va al tesoro del protocolo y no al liquidador. [1]
Sigamos el ejemplo con un bonus hipotético de 5 % y sin fee. Con HF de 0,97 el close factor es 50 %: el liquidador repaga 6000 USDC y recibe colateral por USD, unos 4,34 ETH a 1450 USD. Quedan unos 5,66 ETH (8200 USD) contra 6000 de deuda, y el HF sube a . La posición vuelve a estar sana, más pequeña.
Las versiones posteriores del código, en el repositorio aave-v3-origin, añaden una regla para posiciones pequeñas: si el colateral o la deuda de la reserva quedan bajo un umbral en moneda base, se permite liquidar el 100 %, para que no queden restos que a nadie le conviene liquidar. [5] Antes de integrar, lee la versión desplegada en la red que uses; los parámetros cambian por gobernanza.
Health factor antes y después de una liquidación
Cómo leer esta figura
Tres columnas. A la izquierda, posición sana: colateral C por umbral LT sobre deuda D da HF mayor o igual a 1. En el centro, el precio del oráculo cae y el HF queda bajo 1; la posición es liquidable por cualquiera. A la derecha, el liquidador repaga una deuda d como máximo igual al close factor por D, y recibe colateral por valor d por uno más el bonus; colateral y deuda bajan y el HF vuelve a ser mayor o igual a 1. Una nota al pie indica que el close factor es 50 por ciento con HF sobre 0,95 y 100 por ciento con HF en 0,95 o menos.
Riesgo operativo del oráculo: precio viejo o precio equivocado
Toda la aritmética anterior usa precios que el contrato recibe de un oráculo: un contrato que publica datos externos en la cadena. Si el oráculo entrega un precio viejo, el protocolo liquida tarde o no liquida. Si entrega un precio manipulado, liquida posiciones sanas o presta contra colateral inflado.
Los feeds de Chainlink exponen latestRoundData(), que devuelve roundId, answer, startedAt, updatedAt y answeredInRound. La documentación indica que latestAnswer no incluye marca de tiempo para comprobar frescura, y que la responsabilidad de monitorear y mitigar riesgos de mercado y de código recae en quien integra el feed. [6] [7]
El siguiente contrato es ilustrativo, no auditado. Muestra los dos controles mínimos al leer un feed: precio positivo y antigüedad acotada.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function latestRoundData()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}
/// Ilustrativo: lectura de precio con controles mínimos. No es código auditado.
contract PriceGuard {
AggregatorV3Interface public immutable feed;
uint256 public immutable maxAge; // segundos; se fija a partir del heartbeat publicado del feed
error StalePrice(uint256 updatedAt);
error InvalidPrice(int256 answer);
constructor(AggregatorV3Interface feed_, uint256 maxAge_) {
feed = feed_;
maxAge = maxAge_;
}
function price() external view returns (uint256 value, uint8 decimals) {
(, int256 answer, , uint256 updatedAt, ) = feed.latestRoundData();
if (answer <= 0) revert InvalidPrice(answer);
if (block.timestamp - updatedAt > maxAge) revert StalePrice(updatedAt);
return (uint256(answer), feed.decimals());
}
}Aave añade otra defensa pensada para redes de capa 2. Si el pool tiene configurado un PriceOracleSentinel y este indica que las liquidaciones no están permitidas (por ejemplo, tras una caída del secuenciador), solo se pueden liquidar posiciones con HF por debajo de 0,95. [3] La idea general: cuando no confías en el precio, reduces lo que el precio puede disparar.
Un precio tomado directamente del estado de un AMM en el mismo bloque es fácil de mover con un préstamo flash. Ese riesgo ya se trató en el capítulo de oráculos; aquí basta recordar que el health factor hereda cualquier debilidad del precio que lo alimenta.
Cuello de botella del liquidador: cuando la transacción no llega
El protocolo no liquida solo. Depende de que alguien vea la posición, construya la transacción, pague gas y logre incluirla en un bloque. Ese alguien solo actúa si el bonus supera sus costos: gas, deslizamiento al vender el colateral y riesgo de que el precio siga cayendo.
Tres situaciones rompen esa cadena, y conviene simularlas antes de fijar parámetros:
- Congestión. Muchas posiciones caen a la vez, el gas sube y las liquidaciones pequeñas dejan de ser rentables.
- Competencia por el bloque. Varios liquidadores apuntan a la misma posición; solo una transacción gana y el resto revierte o paga sin resultado.
- Mercado ilíquido. Si vender el colateral mueve mucho el precio, el bonus no compensa y nadie liquida hasta que la posición tiene más deuda que colateral.
Qué revisar en un mercado de lending
Reglas de decisión rápida
¿El precio puede estar viejo?
updatedAt lejano o feed sin marca de tiempo
→ Exigir antigüedad máxima y pausar préstamos si se supera.
¿El precio puede moverse dentro de un bloque?
lectura directa de reservas de un AMM
→ Usar feeds agregados o precios promediados en el tiempo.
¿El bonus cubre gas y deslizamiento?
liquidez del colateral en los mercados donde se vende
→ Simular caídas fuertes con liquidez real antes de listar el activo.
¿Quedan restos sin incentivo?
posiciones pequeñas tras liquidaciones parciales
→ Permitir liquidación completa bajo un umbral de tamaño.
Lo que sostiene la solvencia
Quédate con una frase: un protocolo de lending es solvente mientras exista un precio confiable y alguien con incentivo para liquidar a tiempo. El health factor es solo el número que dice cuándo empieza esa carrera. En la ruta de práctica, este mecanismo se vuelve un ejercicio local: un oráculo que puedes mover a mano y una liquidación que ejecutas tú mismo.
Bibliografía académica
- [1]
Aave, "LiquidationLogic.sol," aave-v3-core, GitHub repository.
Close factor, bonus de liquidación y fee del protocolo.
- [2]
Aave, "GenericLogic.sol," aave-v3-core, GitHub repository.
calculateUserAccountData: fórmula del health factor.
- [3]
Aave, "ValidationLogic.sol," aave-v3-core, GitHub repository.
validateLiquidationCall y umbral HF = 1e18.
- [4]
Aave, "IPool.sol," aave-v3-core, GitHub repository.
Firma de liquidationCall y getUserAccountData.
- [5]
Aave DAO, "LiquidationLogic.sol," aave-v3-origin, GitHub repository.
MIN_BASE_MAX_CLOSE_FACTOR_THRESHOLD y MIN_LEFTOVER_BASE.
- [6]
Chainlink, "Data Feeds API Reference."
latestRoundData, updatedAt y advertencia sobre latestAnswer.
- [7]
Chainlink, "Developer Responsibilities."
Riesgos de integridad de mercado y de código a cargo del integrador.
Rutas vecinas
Si este tema te abrió hambre, sigue por aquí.
Series y labs que comparten área o dependen de esta ruta. Pocas opciones, para no convertir la curiosidad en menú infinito.
Series relacionadas
HotStuff: de cero a estado del arte
Ruta progresiva para entender consenso BFT moderno: quórums, sincronía parcial, locks, taxonomía one/two/three-chain, QC/highQC, multipipeline, view-change, responsiveness, AggQC, Fast-HotStuff, sync y frontera DAG-BFT.
Substrate: del runtime al consenso propio
Serie de 20 capítulos, de neófito a experto, sobre Substrate (Polkadot SDK): runtime en Wasm, FRAME, extrinsics, estado, pesos, actualizaciones sin fork, Aura, BABE, GRANDPA, sincronización, parachains, XCM, Sassafras, BEEFY y cómo conectar un consenso BFT propio a un nodo.
Ruta práctica: activos digitales en la operación
Nueve módulos, de menor a mayor dependencia, para decidir cómo usar custodia, wallets, llaves, firmas multifirma y MPC, AML/KYT y stablecoins con Fireblocks, BitGo, Kaleido, Circle y Tether.
Labs para convertir lectura en práctica
Prueba de trabajo y reajuste de dificultad
Laboratorio determinista para medir el costo de la prueba de trabajo y ver cómo el reajuste por altura de bloque estabiliza el tiempo entre bloques.
Consensus benchmark
Banco reproducible para comparar consenso BFT y documentar los trade-offs de HotStuff-2.
Ethereum local: Anvil, wallet y primera transacción
Laboratorio base para levantar una red local, crear cuentas, firmar transacciones y observar receipts sin gastar ETH real.
RPC y Cast: leer Ethereum con lupa
Ejercicios con JSON-RPC y Cast para consultar bloques, nonces, gas, receipts, logs y errores reproducibles.
Sigue leyendo
Ideas conectadas con este artículo
Una ruta corta para continuar sin abrir veinte pestañas y perder el hilo.
ERC-4626: vaults, shares y contabilidad peligrosa
Tokenized vaults, assets, shares, exchange rate, rounding y ataques de inflación en vaults.
Oráculos: datos externos con dientes
Price feeds, stale data, TWAP, manipulación, dependencia de oráculos y diseño defensivo.
AMMs: x*y=k sin vender humo matemático
Automated market makers, constant product, pools, LP shares, slippage, fees y riesgos básicos.
Uniswap v3: liquidez concentrada y ticks
Rangos, ticks, capital efficiency, posiciones LP y nuevos riesgos de liquidez concentrada.