Ethereum: de historia a labs
Artículo 42 de 48
88%
completado al llegar aquí
Sistemas distribuidosNota de investigación14 min de lectura
Uniswap v3: liquidez concentrada y ticks
Uniswap v3 con números: rangos de precio, ticks de 1.0001, liquidez L, cuánto capital ahorra un rango y por qué el LP asume más riesgo por dólar.
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.
En un pool v2 de DAI/USDC, dos monedas estables que casi siempre valen lo mismo, el capital se reparte sobre todos los precios posibles, de cero a infinito. La documentación de Uniswap estima que ese par usa alrededor del 0,50 % del capital disponible para operar entre 0,99 y 1,01, que es donde ocurre casi todo el volumen. El 99,5 % restante espera precios que casi nunca llegan. [1]
Uniswap v3 deja que cada proveedor de liquidez (LP) elija el rango donde su capital trabaja. Dentro de ese rango, el pool se comporta como si tuviera mucha más liquidez; fuera de él, la posición no opera ni cobra comisiones. El capítulo anterior explicó la curva x · y = k; aquí veremos cómo v3 la recorta y qué cuesta ese recorte.
Brújula de lectura
Actor, evidencia y estado
Actor
LP con rango propioCada posición elige tick inferior y superior; el resultado depende de esa decisión.
Evidencia
slot0, ticks y posición NFTsqrtPriceX96 y tick actual en slot0; la posición se identifica como un NFT ERC-721.
Estado
Liquidez activa LSolo la liquidez de los rangos que contienen el precio actual participa en un swap.
Preguntas guía
- ¿Qué pasa con una posición cuando el precio sale de su rango?
- ¿Por qué el precio se guarda como raíz cuadrada y en una cuadrícula de ticks?
- ¿Cuánto capital ahorra un rango estrecho para ofrecer la misma profundidad?
- Si el capital es menor, ¿el riesgo por unidad de capital también es menor?
Del rango infinito al rango elegido
En v2, la liquidez se distribuye de forma uniforme sobre el intervalo de precios (0, ∞). En v3, el LP asigna su capital a un intervalo finito, y esa asignación se llama posición. Un LP puede tener muchas posiciones en el mismo pool, cada una con su rango. [1]
La liquidez de una posición es activa mientras el precio está dentro de su rango. A medida que el precio se mueve en una dirección, los traders se llevan uno de los tokens y la posición acumula el otro, hasta que, en el borde, queda formada por un solo activo. Si el precio sale del rango, la posición deja de cobrar comisiones; si vuelve a entrar, se reactiva.
Hay una diferencia de representación con v2. Allí, la participación del LP es un ERC-20 fungible. En v3, cada posición tiene sus propios límites y se representa como un NFT ERC-721 a través del contrato NonfungiblePositionManager; en v4 la gestión pasa a un PositionManager que usa ERC-6909 para su contabilidad interna. [2] Para un equipo de custodia, eso significa que una posición v3 se custodia como un NFT, no como un saldo.
Ticks: la cuadrícula de precios
El espacio de precios de v3 está dividido en ticks. El tick i corresponde al precio 1,0001^i, así que subir un tick sube el precio un 0,01 %. La biblioteca TickMath calcula sqrt(1,0001^tick) como número de punto fijo Q64.96 (64 bits enteros y 96 fraccionarios) y acota los ticks entre MIN_TICK = -887272 y MAX_TICK = 887272, derivados del logaritmo en base 1,0001 de 2^-128 y 2^128. [3]
Por eso el estado principal del pool, en la estructura slot0, guarda sqrtPriceX96 (la raíz cuadrada del precio en Q64.96) y el tick actual. Trabajar con la raíz del precio simplifica las fórmulas de cantidades, como veremos enseguida. Un ejemplo: un precio de 2.000 unidades de token1 por unidad de token0, en unidades mínimas de cada token, cae cerca del tick 76.012, porque log(2000) / log(1,0001) ≈ 76.012,8.
No todos los ticks pueden ser bordes de posición. La fábrica asocia cada nivel de comisión con un espaciado de ticks: 0,05 % con 10, 0,30 % con 60 y 1 % con 200, fijados en su constructor. [4] La documentación de comisiones agrega que la gobernanza puede habilitar niveles nuevos y que en diciembre de 2021 se añadió el de 0,01 %. [5]
Cruzar un tick inicializado tiene costo. Cuando un swap llega al borde de un rango, el contrato debe activar o desactivar la liquidez que empieza o termina ahí, y esa operación aumenta el gas de la transacción que la cruza. Un espaciado menor da más granularidad a los LPs y puede encarecer los swaps que atraviesan muchos bordes.
Invariante dentro de un rango: la liquidez L
En v2, con reservas x e y y precio P = y / x, se puede definir L = sqrt(x · y). Despejando, x = L / sqrt(P) e y = L · sqrt(P). v3 reutiliza esa L pero la aplica solo a un intervalo [Pa, Pb]. La biblioteca SqrtPriceMath calcula las cantidades de cada token entre dos precios con estas fórmulas, que conviene leer como "cuánto token hace falta para recorrer ese tramo de la curva": [6]
amount0 entre sqrt(Pa) y sqrt(Pb) = L · (1/sqrt(Pa) − 1/sqrt(Pb))
amount1 entre sqrt(Pa) y sqrt(Pb) = L · (sqrt(Pb) − sqrt(Pa))Con el precio actual P dentro del rango, la posición contiene L · (1/sqrt(P) − 1/sqrt(Pb)) de token0 y L · (sqrt(P) − sqrt(Pa)) de token1. Si P está por debajo de Pa, solo tiene token0; si está por encima de Pb, solo token1.
Ahora el cálculo que justifica todo el diseño. Supón token0 = ETH, token1 = USDC, precio 2.000 y un rango de 1.800 a 2.200 (±10 %). Para aportar 1 ETH hace falta L ≈ 960,98, y con esa L la posición necesita unos 2.205,40 USDC: en total, unos 4.205 USDC de valor. Una posición de rango completo con la misma L necesitaría L / sqrt(2000) ≈ 21,49 ETH y L · sqrt(2000) ≈ 42.976 USDC, unos 85.952 USDC de valor. Para la misma profundidad cerca de 2.000, el rango estrecho usa unas 20 veces menos capital.
Una posición v3 entre dos ticks
Fuentes:
[6]Cómo leer esta figura
Un eje horizontal de precio con marcas de ticks. Un rango sombreado va de Pa igual a 1800 a Pb igual a 2200, y una línea vertical marca el precio actual P igual a 2000. A la izquierda del rango, una caja indica que la posición es solo token0 por L por la diferencia entre uno sobre raíz de Pa y uno sobre raíz de Pb, unos 2,16 ETH, y no cobra comisiones. Dentro del rango, una caja indica que la liquidez está activa, contiene ambos tokens, en el ejemplo 1 ETH y unos 2205 USDC, y cobra comisiones. A la derecha, una caja indica que la posición es solo token1, unos 4303 USDC, y no cobra comisiones. Debajo, una nota compara el capital: unos 4205 USDC en el rango contra unos 85952 USDC en rango completo para la misma liquidez L.
Traza de ejecución: un swap que cruza ticks
El pool guarda la liquidez activa total en una variable y, para cada tick inicializado, un liquidityNet: cuánto cambia la liquidez activa al cruzar ese tick de izquierda a derecha. Durante un swap, el contrato consume la liquidez del intervalo actual hasta llegar al siguiente tick inicializado; si todavía queda cantidad por intercambiar, llama a ticks.cross, suma liquidityNet (con el signo invertido si el precio baja) y continúa con la nueva liquidez. [7]
Las comisiones tampoco se reparten por posición en cada swap, porque sería imposible recorrer miles de posiciones. El pool acumula feeGrowthGlobal0X128 y feeGrowthGlobal1X128, la comisión cobrada por unidad de liquidez, y cada tick guarda cuánto creció "fuera" de él. Con eso, cualquier posición calcula cuánto creció dentro de su rango restando lo de abajo y lo de arriba. Es contabilidad perezosa: el costo se paga cuando el LP consulta o retira, no en cada swap.
Riesgo operativo: más capital eficiente, más riesgo por dólar
El ejemplo de las 20 veces tiene una contracara que pocas veces se muestra. Mientras el precio está dentro del rango, la posición de rango completo con la misma L equivale a la posición concentrada más una cesta fija de tokens: L / sqrt(Pb) de token0 y L · sqrt(Pa) de token1, que no cambian mientras el precio no salga del rango. Esa cesta se comporta como tokens guardados, así que no aporta pérdida frente a mantener. Por tanto, la pérdida frente a mantener es la misma en términos absolutos para las dos posiciones.
Pero la posición concentrada puso unas 20 veces menos capital, así que, medida como porcentaje de lo invertido, su pérdida frente a mantener los tokens también es unas 20 veces mayor. Las comisiones se multiplican igual, y por eso la decisión depende de la volatilidad y del volumen, no solo del APR.
El estudio de loss-versus-rebalancing descompone el retorno del LP en exposición al mercado más comisiones menos pérdidas frente a arbitrajistas. [8] Concentrar liquidez amplifica ambos lados de esa resta para el mismo capital.
Fuera de rango, la posición queda entera en el activo que perdió valor relativo y no cobra nada. Esa propiedad permite las range orders: aportar un solo activo en un rango por encima o por debajo del precio actual se parece a una orden límite. La documentación advierte la diferencia clave: si el precio cruza todo el rango y luego vuelve antes de que el LP retire, la orden queda deshecha, así que hay que vigilarla o delegar el retiro. [9]
v3 también mejora el oráculo. Cada pool guarda observaciones con un acumulador tickCumulative, y cualquiera puede pagar para ampliar el historial hasta 65.535 observaciones. Dividir la diferencia de dos acumuladores por el tiempo da un tick medio aritmético, que corresponde a un precio medio geométrico. La documentación aclara que v4 ya no incluye oráculo integrado. [10]
Elegir el ancho del rango
Lab propuesto: medir capital y composición de una posición
Con un fork local de mainnet o un despliegue de v3-core en Anvil, el lab crea dos posiciones con la misma L: una de rango completo y otra entre 1.800 y 2.200. La validación observable es comparar los tokens que exige cada mint con los valores calculados arriba (salvo redondeo y decimales de cada token), mover el precio con swaps hasta salir del rango y comprobar que la posición estrecha queda con un solo token y deja de acumular comisiones. Como teardown basta detener Anvil.
Conexiones dentro de la serie
- Antes: AMMs desde cero explica la curva
x · y = kque v3 recorta por rangos. - Relacionado: MEV y PBS sobre arbitrajistas y orden de transacciones; oráculos y price feeds sobre el uso de TWAPs.
- Después: préstamos y liquidaciones, donde el precio de estos pools alimenta decisiones de solvencia.
Bibliografía académica
- [1]
Uniswap Labs, "Concentrated Liquidity," Uniswap Docs (repositorio Uniswap/docs).
Rangos de precio, liquidez activa, ticks de 0,01 % y costo de cruzar ticks.
- [2]
Uniswap Labs, "How Uniswap Works," Uniswap Docs (repositorio Uniswap/docs).
Representación de posiciones: ERC-20 en v2, NFT ERC-721 en v3, ERC-6909 en v4.
- [3]
Uniswap, "TickMath.sol," Uniswap/v3-core, GitHub.
Precio por tick de 1,0001, formato Q64.96 y límites MIN_TICK y MAX_TICK.
- [4]
Uniswap, "UniswapV3Factory.sol," Uniswap/v3-core, GitHub.
Niveles de comisión iniciales y espaciado de ticks; enableFeeAmount para añadir niveles.
- [5]
Uniswap Labs, "Fees," Uniswap Docs, archivo de conceptos de protocolo (repositorio Uniswap/docs).
Niveles de comisión de v3 y alta del nivel de 0,01 % por gobernanza en diciembre de 2021.
- [6]
Uniswap, "SqrtPriceMath.sol," Uniswap/v3-core, GitHub.
getAmount0Delta y getAmount1Delta a partir de la liquidez y la raíz del precio.
- [7]
Uniswap, "UniswapV3Pool.sol," Uniswap/v3-core, GitHub.
slot0 con sqrtPriceX96 y tick, cruce de ticks con liquidityNet y acumuladores de comisiones.
- [8]
J. Milionis, C. C. Moallemi, T. Roughgarden y A. L. Zhang, "Automated Market Making and Loss-Versus-Rebalancing," arXiv:2208.06046, 2022.
Retorno del LP: exposición al mercado más comisiones menos pérdidas frente a arbitrajistas (LVR).
- [9]
Uniswap Labs, "Range Orders," Uniswap Docs, archivo de conceptos de protocolo (repositorio Uniswap/docs).
Órdenes por rango con un solo activo y el riesgo de que el precio vuelva a cruzar el rango.
- [10]
Uniswap Labs, "Oracle," Uniswap Docs, archivo de conceptos de protocolo (repositorio Uniswap/docs).
Observaciones con tickCumulative, máximo de 65.535 y media geométrica; v4 sin oráculo integrado.
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.
Lending y liquidaciones: cuando el colateral respira mal
Collateral, borrow, health factor, liquidations, oracle dependency y diseño básico de mercados lending.