Consejos de desarrollo de contratos: experiencias aprendidas del código de Uniswap
Recientemente, al escribir un tutorial sobre el desarrollo de intercambios descentralizados, hice referencia a la implementación de Uniswap V3 y aprendí varios puntos interesantes. Como principiante que intenta desarrollar contratos DeFi por primera vez, estas técnicas deberían ser muy útiles para otros que quieran aprender sobre el desarrollo de contratos.
Dirección de despliegue de contrato predecible
Normalmente, las direcciones obtenidas al desplegar contratos parecen aleatorias y son difíciles de predecir. Sin embargo, en ciertos casos, necesitamos inferir la dirección del contrato a través de la información de la transacción, como determinar los permisos de la transacción o obtener la dirección del pool.
Uniswap utiliza el método CREATE2 para crear contratos, añadiendo el parámetro salt para que la dirección sea predecible. La nueva lógica de generación de direcciones es: hash("0xFF", dirección del creador, salt, initcode). Este método hace que la dirección del contrato sea predecible, lo cual es muy útil.
Uso inteligente de funciones de callback
En Solidity, los contratos pueden llamarse entre sí. En ciertos escenarios, A llama al método de B, y B hace una llamada de regreso a A en el método llamado; este patrón es muy útil.
El intercambio de Uniswap utiliza un mecanismo de callback. El método swap de UniswapV3Pool llama a swapCallback, pasando la cantidad real de tokens necesarios. El llamador debe transferir los tokens en el callback, asegurando así la ejecución completa y la seguridad del método swap, sin necesidad de registros de variables complicados.
Pasar información mediante excepciones, implementar la estimación de transacciones con try catch
En el contrato Quoter de Uniswap, se utiliza try catch para ejecutar el método swap de UniswapV3Pool. Esto es para simular el swap y estimar los tokens necesarios para la transacción, pero durante la estimación no se intercambiarán realmente los tokens, por lo que se producirá un error.
Uniswap lanza un error especial dentro de la función de callback y luego captura ese error para extraer la información necesaria. Este método puede parecer ingenioso, pero es muy práctico, ya que no requiere modificar específicamente el método de swap para estimar la demanda, lo que hace que la lógica sea más sencilla.
Resolver problemas de precisión con grandes números
El código de Uniswap implica una gran cantidad de cálculos, como calcular la cantidad de tokens a intercambiar según el precio actual y la liquidez. Para evitar la pérdida de precisión durante las operaciones de división, el proceso de cálculo a menudo utiliza la operación "<< FixedPoint96.RESOLUTION", que equivale a desplazar a la izquierda 96 lugares, lo que equivale a multiplicar por 2^96.
Desplazar a la izquierda y luego hacer división puede garantizar la precisión en condiciones de transacciones normales sin desbordamiento. Aunque teóricamente seguirá habiendo una pequeña pérdida de precisión, ya es aceptable.
Cálculo de ganancias mediante Share
Uniswap necesita registrar las ganancias por comisiones de los proveedores de liquidez LP(. Evidentemente, no se puede registrar la comisión para cada LP en cada transacción, ya que consumiría una gran cantidad de Gas.
La solución es registrar feeGrowthInside0LastX128 y feeGrowthInside1LastX128 en la estructura Position, que representan la tarifa que debe recibir cada unidad de liquidez cuando se retira la tarifa de cada posición por última vez.
Solo necesita registrar la tarifa total y la tarifa asignada por unidad de liquidez. Al retirar LP, la tarifa que se puede retirar se puede calcular según la liquidez que se posee. Es similar a poseer acciones; al retirar ganancias, solo necesita conocer las ganancias históricas por acción y las ganancias de la última retirada.
![Serie para novatos en Web3: Consejos de desarrollo de contratos que aprendí del código de Uniswap])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
No toda la información necesita obtenerse de la cadena.
El almacenamiento en la cadena es relativamente costoso, no toda la información debe estar en la cadena o recuperarse de ella. Por ejemplo, muchas de las interfaces llamadas por el front-end de Uniswap son interfaces tradicionales de Web2.
La lista de pools de negociación, información, etc., se puede almacenar en una base de datos normal, y parte de ello necesita sincronizarse periódicamente desde la cadena, pero no es necesario llamar en tiempo real a la cadena o a la interfaz RPC del nodo para obtener datos.
Muchos proveedores de RPC de blockchain también ofrecen interfaces avanzadas que permiten obtener ciertos datos de manera más rápida y económica. Estas interfaces suelen utilizar cachés para mejorar el rendimiento y la eficiencia.
Por supuesto, las operaciones clave siguen realizándose en la cadena.
Aprender a dividir contratos y utilizar contratos estándar existentes
Un proyecto puede incluir varios contratos desplegados en la práctica. Incluso si solo se despliega un contrato, el código se puede dividir en varios contratos mediante la herencia para su mantenimiento.
El contrato NonfungiblePositionManager de Uniswap hereda múltiples contratos. El contrato ERC721Permit utiliza directamente la implementación ERC721 de OpenZeppelin, lo que facilita la gestión de posiciones con NFT y mejora la eficiencia del desarrollo.
Resumen
Desarrollar manualmente una versión simplificada de un intercambio descentralizado te permitirá comprender más a fondo la implementación de Uniswap y aprender más puntos de conocimiento en proyectos prácticos. Si bien el aprendizaje teórico es importante, la experiencia práctica es aún más valiosa. Espero que estos pequeños consejos te sean útiles en tu camino de desarrollo de contratos.
![Serie para principiantes en Web3: Consejos pequeños de desarrollo de contratos que aprendí del código de Uniswap])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(
Esta página puede contener contenido de terceros, que se proporciona únicamente con fines informativos (sin garantías ni declaraciones) y no debe considerarse como un respaldo por parte de Gate a las opiniones expresadas ni como asesoramiento financiero o profesional. Consulte el Descargo de responsabilidad para obtener más detalles.
19 me gusta
Recompensa
19
7
Compartir
Comentar
0/400
GasWaster
· 07-16 11:49
Los que estudian contratos deben mirar
Ver originalesResponder0
MissedAirdropAgain
· 07-16 07:39
No hay tiempo para aprender el contrato...
Ver originalesResponder0
YieldWhisperer
· 07-14 20:20
vi este patrón exacto en dyydx en 2020... nada nuevo, para ser honesto
Análisis del código de Uniswap: 7 consejos para el desarrollo de contratos inteligentes
Consejos de desarrollo de contratos: experiencias aprendidas del código de Uniswap
Recientemente, al escribir un tutorial sobre el desarrollo de intercambios descentralizados, hice referencia a la implementación de Uniswap V3 y aprendí varios puntos interesantes. Como principiante que intenta desarrollar contratos DeFi por primera vez, estas técnicas deberían ser muy útiles para otros que quieran aprender sobre el desarrollo de contratos.
Dirección de despliegue de contrato predecible
Normalmente, las direcciones obtenidas al desplegar contratos parecen aleatorias y son difíciles de predecir. Sin embargo, en ciertos casos, necesitamos inferir la dirección del contrato a través de la información de la transacción, como determinar los permisos de la transacción o obtener la dirección del pool.
Uniswap utiliza el método CREATE2 para crear contratos, añadiendo el parámetro salt para que la dirección sea predecible. La nueva lógica de generación de direcciones es: hash("0xFF", dirección del creador, salt, initcode). Este método hace que la dirección del contrato sea predecible, lo cual es muy útil.
Uso inteligente de funciones de callback
En Solidity, los contratos pueden llamarse entre sí. En ciertos escenarios, A llama al método de B, y B hace una llamada de regreso a A en el método llamado; este patrón es muy útil.
El intercambio de Uniswap utiliza un mecanismo de callback. El método swap de UniswapV3Pool llama a swapCallback, pasando la cantidad real de tokens necesarios. El llamador debe transferir los tokens en el callback, asegurando así la ejecución completa y la seguridad del método swap, sin necesidad de registros de variables complicados.
Pasar información mediante excepciones, implementar la estimación de transacciones con try catch
En el contrato Quoter de Uniswap, se utiliza try catch para ejecutar el método swap de UniswapV3Pool. Esto es para simular el swap y estimar los tokens necesarios para la transacción, pero durante la estimación no se intercambiarán realmente los tokens, por lo que se producirá un error.
Uniswap lanza un error especial dentro de la función de callback y luego captura ese error para extraer la información necesaria. Este método puede parecer ingenioso, pero es muy práctico, ya que no requiere modificar específicamente el método de swap para estimar la demanda, lo que hace que la lógica sea más sencilla.
Resolver problemas de precisión con grandes números
El código de Uniswap implica una gran cantidad de cálculos, como calcular la cantidad de tokens a intercambiar según el precio actual y la liquidez. Para evitar la pérdida de precisión durante las operaciones de división, el proceso de cálculo a menudo utiliza la operación "<< FixedPoint96.RESOLUTION", que equivale a desplazar a la izquierda 96 lugares, lo que equivale a multiplicar por 2^96.
Desplazar a la izquierda y luego hacer división puede garantizar la precisión en condiciones de transacciones normales sin desbordamiento. Aunque teóricamente seguirá habiendo una pequeña pérdida de precisión, ya es aceptable.
Cálculo de ganancias mediante Share
Uniswap necesita registrar las ganancias por comisiones de los proveedores de liquidez LP(. Evidentemente, no se puede registrar la comisión para cada LP en cada transacción, ya que consumiría una gran cantidad de Gas.
La solución es registrar feeGrowthInside0LastX128 y feeGrowthInside1LastX128 en la estructura Position, que representan la tarifa que debe recibir cada unidad de liquidez cuando se retira la tarifa de cada posición por última vez.
Solo necesita registrar la tarifa total y la tarifa asignada por unidad de liquidez. Al retirar LP, la tarifa que se puede retirar se puede calcular según la liquidez que se posee. Es similar a poseer acciones; al retirar ganancias, solo necesita conocer las ganancias históricas por acción y las ganancias de la última retirada.
![Serie para novatos en Web3: Consejos de desarrollo de contratos que aprendí del código de Uniswap])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
No toda la información necesita obtenerse de la cadena.
El almacenamiento en la cadena es relativamente costoso, no toda la información debe estar en la cadena o recuperarse de ella. Por ejemplo, muchas de las interfaces llamadas por el front-end de Uniswap son interfaces tradicionales de Web2.
La lista de pools de negociación, información, etc., se puede almacenar en una base de datos normal, y parte de ello necesita sincronizarse periódicamente desde la cadena, pero no es necesario llamar en tiempo real a la cadena o a la interfaz RPC del nodo para obtener datos.
Muchos proveedores de RPC de blockchain también ofrecen interfaces avanzadas que permiten obtener ciertos datos de manera más rápida y económica. Estas interfaces suelen utilizar cachés para mejorar el rendimiento y la eficiencia.
Por supuesto, las operaciones clave siguen realizándose en la cadena.
Aprender a dividir contratos y utilizar contratos estándar existentes
Un proyecto puede incluir varios contratos desplegados en la práctica. Incluso si solo se despliega un contrato, el código se puede dividir en varios contratos mediante la herencia para su mantenimiento.
El contrato NonfungiblePositionManager de Uniswap hereda múltiples contratos. El contrato ERC721Permit utiliza directamente la implementación ERC721 de OpenZeppelin, lo que facilita la gestión de posiciones con NFT y mejora la eficiencia del desarrollo.
Resumen
Desarrollar manualmente una versión simplificada de un intercambio descentralizado te permitirá comprender más a fondo la implementación de Uniswap y aprender más puntos de conocimiento en proyectos prácticos. Si bien el aprendizaje teórico es importante, la experiencia práctica es aún más valiosa. Espero que estos pequeños consejos te sean útiles en tu camino de desarrollo de contratos.
![Serie para principiantes en Web3: Consejos pequeños de desarrollo de contratos que aprendí del código de Uniswap])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(