WEB3DEV Español

Cover image for Construyendo el Contrato Inteligente de una Piscina de Liquidez para el Intercambio de Token
Delia Viloria T
Delia Viloria T

Posted on

Construyendo el Contrato Inteligente de una Piscina de Liquidez para el Intercambio de Token

Explorando la Administración de la Liquidez del Contrato Inteligente: Desglose de la Función

En el mundo de las finanzas descentralizadas (DeFi), los contratos inteligentes juegan un rol crucial en permitir diferentes actividades financieras. Un contrato es la Liquidity del contrato inteligente, diseñado para administrar la previsión de liquidez y el intercambio de token entre dos tokens ERC-20: DOGE y USDT. En este blog, vamos a diseccionar las funciones claves de entre contrato para entender sus sus funciones internas y las funcionalidades que ofrece.

Image description

Foto por Jievani Weerasinghe en Unsplash

Función setAddresses(address _DOGE, address _usdt)

La función setAddresses() es usada por el titular del contrato para configurar las direcciones de los tokens DOGE y USDT. Este paso es vital porque establece la conexión entre el contrato y los tokens que manejará. Las interfaces IERC20 son utilizadas para crear instancias de los contratos del token.

function setAddresses(address _DOGE, address _usdt) public onlyOwner {
       DOGE = IERC20(_DOGE);
       USDT = IERC20(_usdt);
   }
Enter fullscreen mode Exit fullscreen mode

Función getReserves()

La función getReserves() permite a terceros retirar las reservas actuales de los tokens DOGE y USDT dentro del contrato. Estas reservas son cruciales para varios cálculos a través de las operaciones del contrato, asegurando la provisión de liquidez certera y el intercambio de tokens.

function getReserves()
       public
       view
       returns (uint256 _reserve1, uint256 _reserve2)
   {
       _reserve1 = reserve1;
       _reserve2 = reserve2;
   }
Enter fullscreen mode Exit fullscreen mode

Función quote(uint256 amountA, uint256 reserveA, uint256 reserveB)

La función quote() es usada internamente para calcular la cotización para el intercambio de token. Dado la amountA deseada para intercambiar y las reservas actuales de tokens A (reserveA) y B (reserveB), esta función computa la cantidad correspondiente de token B que será recibida luego del intercambio. Asegura que hay suficiente liquidez para que el intercambio suceda.

function quote(
       uint256 amountA,
       uint256 reserveA,
       uint256 reserveB
   ) internal pure returns (uint256) {
       require(amountA > 0, "UniswapV2Library: INSUFFICIENT_AMOUNT");
       require(
           reserveA > 0 && reserveB > 0,
           "UniswapV2Library: INSUFFICIENT_LIQUIDITY"
       );
       uint256 amountB = amountA.mul(reserveB) / reserveA;
       return amountB;
   }
Enter fullscreen mode Exit fullscreen mode

Función _addLiquidity(uint256 _DOGEQuantity, uint256 _USDTQuantity)

La función _addLiquidity() calcula las cantidades óptimas de DOGE y USDT para que sean añadidos a la provisión de liquidez. Considera las reservas y balances actuales, así como las cantidades deseadas de ambos tokens. Las cantidades calculadas asegurando que la piscina de la liquidez sea eficiente y se mantenga balanceada.

function _addLiquidity(
       uint256 _DOGEQuantity,
       uint256 _USDTQuantity
   ) internal view returns (uint256 amountA, uint256 amountB) {
       require(
           _DOGEQuantity != 0 && _USDTQuantity != 0,
           "token quantity could not be zero"
       );
       (uint256 reserveA, uint256 reserveB) = getReserves();
       if (reserveA == 0 && reserveB == 0) {
           (amountA, amountB) = (_DOGEQuantity, _USDTQuantity);
       } else {
           uint256 amount2Optimal = quote(_DOGEQuantity, reserveA, reserveB);
           if (amount2Optimal <= _USDTQuantity) {
               (amountA, amountB) = (_DOGEQuantity, amount2Optimal);
           } else {
               uint256 amountAOptimal = quote(
                   _USDTQuantity,
                   reserveB,
                   reserveA
               );
               assert(amountAOptimal <= _DOGEQuantity);
               (amountA, amountB) = (amountAOptimal, _USDTQuantity);
           }
       }
   }
Enter fullscreen mode Exit fullscreen mode

Función addLiquidity(uint256 amountDOGE, uint256 amountUSDT, address to)

La función addLiquidity() permite a los usuarios depositar tokens DOGE y USDT para proporcionar liquidez. Calcula las cantidades óptimas de tokens para añadir usando la función _addLiquidity(), transfiere los tokens desde la dirección del usuario al del contrato, y acuña los tokens LP representados en la liquidez proporcionada.

function addLiquidity(
       uint256 amountDOGE,
       uint256 amountUSDT,
       address to
   ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity) {
       (amountA, amountB) = _addLiquidity(amountDOGE, amountUSDT);
       DOGE.safeTransferFrom(msg.sender, address(this), amountA);
       USDT.safeTransferFrom(msg.sender, address(this), amountB);
       liquidity = mintLPToken(to);
   }
Enter fullscreen mode Exit fullscreen mode

Función mintLPToken(address to)

La función mintLPToken() calcula la cantidad de tokens LP para acuñar cuando la liquidez se añade. Asegura que la cantidad de liquidez inicial cumpla con los requisitos mínimos y distribuye proporcionalmente los tokens LP a los usuarios.

function mintLPToken(address to) internal returns (uint256 liquidity) {
       (uint256 _reserve0, uint256 _reserve1) = getReserves(); // gas savings
       uint256 balance0 = DOGE.balanceOf(address(this));
       uint256 balance1 = USDT.balanceOf(address(this));
       uint256 amount0 = balance0.sub(_reserve0);
       uint256 amount1 = balance1.sub(_reserve1);

       uint256 _totalLiquidity = totalLiquidity;
       if (_totalLiquidity == 0) {
           liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
           userLiquidity[address(0)] = MINIMUM_LIQUIDITY;
       } else {
           liquidity = Math.min(
               amount0.mul(_totalLiquidity) / _reserve0,
               amount1.mul(_totalLiquidity) / _reserve1
           );
       }
       require(liquidity > 0, "INSUFFICIENT_LIQUIDITY_MINTED");
       userLiquidity[to] += liquidity;
       totalLiquidity += liquidity;
       reserve1 = DOGE.balanceOf(address(this));
       reserve2 = USDT.balanceOf(address(this));
   }
Enter fullscreen mode Exit fullscreen mode

Función burn(uint256 liquidity)

La función burn() calcula las cantidades de tokens DOGE y USDT para regresar a los usuarios cuando la liquidez se remueve. Determina la distribución proporcionada basada en la liquidez proporcionada y asegura que ambos tokens retornen en cantidades adecuadas.

function burn(
       uint256 liquidity
   ) internal returns (uint256 amount0, uint256 amount1) {
       uint256 balance0 = DOGE.balanceOf(address(this));
       uint256 balance1 = USDT.balanceOf(address(this));
       uint256 _totalLiquidity = totalLiquidity;
       amount0 = liquidity.mul(balance0) / _totalLiquidity;
       amount1 = liquidity.mul(balance1) / _totalLiquidity; // using balances ensures pro-rata distribution
       require(
           amount0 > 0 && amount1 > 0,
           "INSUFFICIENT_LIQUIDITY_BURNED: Increase Liquidity amount"
       );
       totalLiquidity -= liquidity;
   }
Enter fullscreen mode Exit fullscreen mode

Función removeLiquidity(uint256 liquidity, address to)

La función removeLiquidity() permite a los usuarios remover liquidez desde la piscina. Calcula la cantidad de tokens DOGE y USDT para que regresen al usuario y consecuentemente, transfiere los tokens. La liquidez del usuario es actualizada y la liquidez y reserva totales son ajustadas.

function removeLiquidity(
       uint256 liquidity,
       address to
   ) public returns (uint256 amountA, uint256 amountB) {
       require(
           userLiquidity[msg.sender] >= liquidity,
           "INSUFFICIENT_LIQUIDITY"
       );
       (amountA, amountB) = burn(liquidity);

       DOGE.safeTransfer(to, amountA);

       USDT.safeTransfer(to, amountB);
       userLiquidity[msg.sender] -= liquidity;
       reserve1 = DOGE.balanceOf(address(this));
       reserve2 = USDT.balanceOf(address(this));

   }
Enter fullscreen mode Exit fullscreen mode

Función swapDOGEForUSDT(uint256 amountIn, address _to)

La función swapDOGEForUSDT() facilita el intercambio de tokens DOGE por tokens USDT. Calcula la cantidad de salida de los tokens USDT basado en la cantidad de entrada de tokens DOGE y realiza el intercambio. Las reservas del contrato son consecuentemente actualizadas.

function swapDOGEForUSDT(uint256 amountIn, address _to) external {
       require(amountIn > 0, "INSUFFICIENT_INPUT_AMOUNT");
       (uint256 reserveIn, uint256 reserveOut) = getReserves();

       require(
           reserveIn > 0 && reserveOut > 0,
           "UniswapV2Library: INSUFFICIENT_LIQUIDITY"
       );
       uint256 amountInWithFee = amountIn.mul(997);
       uint256 numerator = amountInWithFee.mul(reserveOut);
       uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);
       uint256 amountOut = numerator / denominator;
       require(amountOut <= reserveOut, "UniswapV2: INSUFFICIENT_LIQUIDITY");
       DOGE.safeTransferFrom(_to, address(this), amountIn);
       USDT.safeTransfer(_to, amountOut);
       reserve1 = DOGE.balanceOf(address(this));
       reserve2 = USDT.balanceOf(address(this));

   }
Enter fullscreen mode Exit fullscreen mode

Función swapUSDTForDOGE(uint256 amountIn, address _to)

La función swapUSDTForDOGE() permite a los usuarios intercambiar tokens USDT por tokens DOGE. Similar a las funciones previas, calcula la cantidad de salida de los tokens DOGE, basados en la cantidad de entrada de los tokens USDT y realiza el intercambio, actualizando las reservas del contrato.

function swapUSDTForDOGE(uint256 amountIn, address _to) external {
       require(amountIn > 0, "INSUFFICIENT_INPUT_AMOUNT");
       (uint256 reserveOut, uint256 reserveIn) = getReserves();
       require(
           reserveIn > 0 && reserveOut > 0,
           "UniswapV2Library: INSUFFICIENT_LIQUIDITY"
       );
       uint256 amountInWithFee = amountIn.mul(997);
       uint256 numerator = amountInWithFee.mul(reserveOut);
       uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);
       uint256 amountOut = numerator / denominator;
       require(amountOut <= reserveOut, "UniswapV2: INSUFFICIENT_LIQUIDITY");
       USDT.safeTransferFrom(_to, address(this), amountIn);
       DOGE.safeTransfer(_to, amountOut);
       reserve1 = DOGE.balanceOf(address(this));
       reserve2 = USDT.balanceOf(address(this));

   }
Enter fullscreen mode Exit fullscreen mode

Conclusión

El contrato inteligente Liquidity encapsula las funcionalidades requeridas para la provisión de liquidez y el intercambio de tokens dentro del ecosistema DeFi. Explorando el propósito y operación de cada función, ganamos conocimiento sobre las capacidades del contrato. Es importante tomar en cuenta que este desglose proporciona un alto nivel de entendimiento, y la implementación que pueda envolver consideraciones adicionales, como las medidas de seguridad y la eficiencia de gas. El contrato Liquidity ejemplifica el poder de los contratos inteligentes en revolucionar las transacciones financieras en la blockchain.

Puedes ver el código entero aquí.

Apóyanos aquí. ¡Gracias!

Este artículo fue escrito por Rohit Goyal y traducido por Delia Viloria T. Su original se puede leer aquí.

Sería genial escucharte en nuestro Discord, puedes contarnos tus ideas, comentarios, sugerencias y dejarnos saber lo que necesitas.
Si prefieres puedes escribirnos a @web3dev_eshttps://twitter.com/web3dev_es en Twitter.

Discussion (0)