Prefacio
Con el rápido desarrollo de las finanzas descentralizadas (DeFi), Uniswap, como intercambio descentralizado líder, ha estado a la vanguardia de la innovación. Este artículo proporcionará un análisis en profundidad del mecanismo central del protocolo Uniswap v3 y una explicación detallada de su diseño funcional, incluidas funciones clave como liquidez centralizada, tasas múltiples, intercambio de tokens y préstamos rápidos, al tiempo que proporciona puntos de auditoría relevantes para auditores. (Nota: las imágenes de este artículo se pueden ver en alta definición en https://www.figma.com/board/QyIpAUR93MxZ4XZZf2QjDk/uniswap-v3).
Breve análisis de la arquitectura.
El protocolo Uniswap v3 consta principalmente de cuatro módulos:
POSITIONMANAGER: La interfaz principal del usuario realiza operaciones de liquidez. Los usuarios pueden crear grupos de tokens, proporcionar/eliminar liquidez a través de ellos y utilizar ERC721 como cupón para proveedores de liquidez (LP).
SwapRouter: la entrada para que los usuarios intercambien tokens. Los usuarios pueden completar operaciones de intercambio de tokens a través de este módulo.
Pool: Responsable de implementar transacciones de tokens, gestión de liquidez, cobrar tarifas de transacción y funciones de gestión de datos de Oracle. Entre ellos, el mecanismo Tick divide el rango de precios en múltiples escalas finas.
Factory: se utiliza para crear y gestionar contratos de Pool.
Clasificación de procesos
Crear un par de tokens
用户可以通过 createAndInitializePoolIfNecessary 函数来完成。用户需传入代币对的 token0、token1、手续费(fee) 以及初始价格()。 Primero, el sistema verificará si el par token ya existe a través de la función getpool.最后,通过 initialize 函数完成价格、手续费、tick、预言机等相关参数的初始化。
提供流动性
Los usuarios pueden crear nuevas posiciones de liquidez y generar NFT correspondientes a través de la función Mint, o agregar liquidez a posiciones de liquidez NFT existentes a través de la función de aumento de liquidez. Primero, el sistema verificará si la transacción se ejecuta dentro del rango de tiempo especificado y luego llamará a la función addLiquidity para completar la operación específica. En esta función, primero se calculan la dirección y la liquidez del grupo, y luego se llama a updatePosition para actualizar la posición del usuario, modificar el tick inferior y superior y la tarifa de manejo total acumulada. Posteriormente, el sistema agrega liquidez a través de modifiquePosition, garantiza que tick cumpla con las condiciones de los límites superior e inferior, devuelve el número calculado de token0 y token1 (int256) y lo envía al grupo. Finalmente, el sistema actualiza la información de Posición correspondiente en función del tokenId del usuario.
Eliminar liquidez
用户可以通过 decreaseLiquidity 函数来移除流动性。 Primero, el sistema verifica la autoridad del certificado LP y la validez de tiempo de la transacción. Según la premisa de garantizar que la piscina tenga suficiente liquidez, llame a la función de quemaduras para eliminar la liquidez. Posteriormente, el sistema verificará si la cantidad real de tokens que se eliminan cumple con los requisitos mínimos establecidos por el usuario, y la información de POSICIÓN del usuario se actualizará en consecuencia.
intercambio
Los usuarios pueden especificar la cantidad de tokens pagados por la función ExactinPut y el número mínimo de tokens que se espera obtener, o el número máximo de tokens pagados por la función ExactoutPut y establecer el número esperado de tokens obtenidos.系统首先解析路径(path),然后依次调用 exactInputInternal 或 exactOutputInternal 函数完成每一步的 swap 操作。
En la función de intercambio, el sistema primero bloquea el estado desbloqueado para evitar que otras transacciones interfieran con la actualización de las variables de estado. Después de ingresar al bucle, el sistema encuentra el siguiente precio de transacción a través de Tick y llama a la función ComputeswapStep para calcular el intercambio en cada paso hasta que Tokenin o Tokenout alcanza las expectativas del usuario. Al mismo tiempo, el sistema actualizará los valores relacionados de tarifas, liquidez, ticks y precios. Si la marca cambia, los datos de Oracle también deben actualizarse. Después de completar estas operaciones, el sistema paga tokeut al usuario, y el usuario paga tokenina a través de la función de devolución de llamada uniswapv3swapCallback. Posteriormente, el sistema verificará si el saldo del contrato coincide y desbloqueará el estado desbloqueado después de la confirmación.
Una transacción finaliza con éxito cuando todas las operaciones de intercambio en la ruta se han completado y la transacción cumple con las expectativas del usuario.
destello
Los usuarios pueden realizar operaciones de préstamos flash a través de funciones flash. Primero, el sistema calculará la tarifa de préstamo y luego enviará el token requerido por el usuario a la dirección de préstamo designada.接下来,系统回调用户实现的 uniswapV3FlashCallback 函数,用户在此函数中完成还款操作。系统会在回调后检查合约余额的变化,确保其与用户借贷的数量相符,同时更新相应的手续费。除了 flash 函数,用户也可以通过 swap 操作实现类似的闪电贷功能,即在交易过程中先借入再偿还 token。
审计要点
1. Verifique si se llama a refundETH después de la operación de intercambio
在 exactInput 函数中,用户需要指定支付的 token 数量和预期获得的最小 token 数量。在调用 uniswapV3SwapCallback 之前,系统会重新计算 amount0 和 amount1,以确保用户可以精确地发送 token。然而,当使用 ETH 进行交换时,用户需要随交易一起发送 ETH。即便在交易过程中未使用完所有的 ETH,函数不会自动退回多余部分。exactInput 函数仅返回 amountOut,因此交易者无法直接得知此次交换实际消耗了多少 ETH。
Además, cualquiera puede llamar a la función refundETH para retirar el ETH no utilizado del contrato. Por lo tanto, se recomienda verificar si se llama a refundETH después de la operación de intercambio para evitar que los usuarios dejen ETH sin usar en el protocolo, o usar la función MultiCall para completar múltiples llamadas a funciones en una sola operación.
2. Verifique si TWAP está implementado para obtener el precio de Oracle.
Cuando se utiliza Uniswap como fuente de precios, puede existir un riesgo de manipulación de precios si el protocolo externo accede directamente a Slot0 para obtener sqrtPriceX96. Los atacantes pueden manipular el estado del fondo de liquidez mediante swaps y otros métodos para obtener precios favorables al ejecutar transacciones.
Para reducir este riesgo, se recomienda que los desarrolladores obtengan precios promedio ponderados en el tiempo (TWAP), porque TWAP puede reducir efectivamente los efectos de las fluctuaciones severas en el precio a corto plazo y aumentar la dificultad de manipular los precios.
3. Se recomienda permitir que los usuarios establezcan los parámetros de deslizamiento por sí mismos.
Cuando otros protocolos utilizan Uniswap v3 para operaciones de intercambio, se recomienda a los desarrolladores establecer una protección contra deslizamientos basada en escenarios comerciales y permitir a los usuarios ajustar los parámetros ellos mismos para evitar ataques tipo sándwich. En esta función de swap, el cuarto parámetro sqrtPriceLimitX96 se utiliza para especificar el precio mínimo o máximo al que el usuario está dispuesto a realizar el swap. Este parámetro puede prevenir eficazmente fluctuaciones extremas de precios durante el proceso de transacción, reduciendo así las pérdidas de los usuarios debido a un deslizamiento excesivo.
4. Se recomienda introducir un mecanismo de lista blanca de fondos de liquidez.
En Uniswap v3, el mismo par de tokens ERC20 puede existir en múltiples fondos de liquidez (Pools) al mismo tiempo según diferentes tarifas. Por lo general, unos pocos grupos de liquidez poseen la mayor parte de la liquidez, mientras que otros grupos pueden tener muy poco volumen total bloqueado (TVL) o ni siquiera se han creado todavía. Es más probable que estos grupos de TVL más bajos sean objetivos de manipulación de precios.
Por lo tanto, cuando las partes del proyecto optan por utilizar datos del fondo de liquidez, deben evitar simplemente utilizar LP como fuente de datos. Para garantizar la confiabilidad de los datos, se recomienda introducir un mecanismo de lista blanca para descartar los grupos con suficiente liquidez y dificultad de manipulación. Este mecanismo reduce significativamente el riesgo, garantizando la seguridad y precisión de los datos de referencia de precios, al tiempo que evita pérdidas potenciales por la manipulación de pools con un TVL demasiado bajo.
5. Verifique si se usa sin marcar en TickMath.sol, FullMath.sol y Position.sol
Tickmath, Fullmath y Position y otros módulos se utilizan para realizar cálculos matemáticos complejos en Uniswap V3, que dependen del mecanismo de procesamiento de desbordamiento en solidez. En versiones anteriores de Solidity (<0.8.0), el comportamiento de desbordamiento y desbordamiento de enteros por defecto no generaba excepciones, por lo que el código podía ejecutarse normalmente según esta suposición. Sin embargo, a partir de la versión 0.8.0 de Solidity, el desbordamiento y el desbordamiento insuficiente generan automáticamente excepciones, lo que afecta la ejecución del código existente. Para garantizar que estos módulos funcionen correctamente en Solidity 0.8.0 y superiores, los desarrolladores deben deshabilitar manualmente la verificación de desbordamiento utilizando bloques de código no verificados en funciones específicas. Esto puede restaurar el comportamiento de la versión anterior y garantizar la ejecución eficiente de la operación sensible de desbordamiento.
Se han realizado ajustes y soporte oficial para Solidity 0.8.0 y versiones posteriores. Para obtener más detalles, consulte esta actualización (https://github.com/Uniswap/v3-core/commit/6562c52e8f75f0c10f9deaf44861847585fc8129). Este cambio garantiza que TickMath, FullMath y otros módulos relacionados seguirán ejecutándose correctamente en las nuevas versiones del compilador.
6. Compruebe si los métodos de codificación y decodificación de ruta son los mismos
在 Uniswap v3 的 exactInput 和 exactOutput 函数中,用户需要输入 path 参数,该路径必须按照固定格式进行编码和解码,即 tokenA-fee-tokenB,用于逐步进行代币交换操作。 Esta estructura de ruta especifica explícitamente los dos tokens involucrados en cada salto de la transacción y el nivel de tarifa entre ellos.如果外部协议在使用 Uniswap v3 的代币交换功能时选择了不同的路径解码方式,可能会导致与 Uniswap 预期的路径格式不符。 En este caso, es posible que el protocolo no pueda resolver correctamente la ruta y, por lo tanto, no pueda realizar con éxito la operación de intercambio de tokens prevista.
Por lo tanto, se recomienda que los desarrolladores se aseguren de que los protocolos externos sigan estrictamente las reglas de codificación de rutas de Uniswap al integrar la función de intercambio de tokens de Uniswap v3. Para evitar errores de decodificación de rutas, los protocolos externos deben verificar cuidadosamente el formato del parámetro de ruta al llamar a exactitudInput y exactitudExactOutput para evitar fallas en las transacciones o resultados inesperados.
7. Compruebe si el orden de los tokens afecta la lógica del proyecto.
En UNISWAP, token0 son tokens con un orden inferior para tokens básicos (Token base), y token1 son tokens con secuencias de orden superior para tokens de cotización. Uniswap 会根据两个代币的地址按字典序进行排序,确保代币对的顺序在池子中始终保持一致。
Sin embargo, debido a la dirección del contrato en diferentes redes blockchain, especialmente para contratos de implementación entre cadenas, la secuencia de los tokens puede cambiar. Este cambio hará que las funciones de token0 y token1 se inviertan, lo que afectará el rendimiento del precio. Por ejemplo, en algunas cadenas, los tokens específicos pueden ser token0, pero en otras cadenas, pueden ordenarse como Token1, lo que da como resultado diferentes relaciones entre tokens y tokens de cotización y, en última instancia, afecta el precio de la visualización. Por lo tanto, se recomienda que los desarrolladores verifiquen si la secuencia de los tokens afectará la lógica del proyecto, especialmente en el entorno de cadenas cruzadas, es necesario considerar el problema de precio que los tokens pueden causar, para evitar efectos adversos en el precio. Lógica de transacciones y rendimiento.
Resumir
上述基础检查项基于 Uniswap v3 当前版本,供审计人员对与 Uniswap v3 有交互的项目进行检查。不同项目的实现各具特点,因此审计人员需深入理解协议,并根据实际情况进行严格检查。 Para los proyectos que se están desarrollando, el equipo de seguridad de Slow Fog recomienda que los desarrolladores consideren cuidadosamente estos elementos de inspección en el proceso de desarrollo para garantizar la seguridad y confiabilidad del acuerdo.
Autor |
编辑 | Liz