Uniswap V2 fue diseñado para recaudar 1/6 de las tarifas de intercambio para el protocolo. Dado que una tarifa de intercambio es del 0.3%, 1/6 de eso es el 0.05%, por lo que el 0.05% de cada transacción iría al protocolo.
Aunque esta característica nunca se activó realmente, la discutimos de todos modos, ya que algunos forks pueden usarla. También es muy fácil equivocarse en el cálculo, por lo que invertir tiempo ahora para entenderlo te ayudará a detectar errores en cálculos similares más adelante.
Requisitos previos
Necesitas estar familiarizado con todos los capítulos anteriores en el Uniswap V2 Book para poder seguir este contenido.
Recaudar tarifas del protocolo durante los intercambios es ineficiente
Sería ineficiente recaudar el 0.05% de la tarifa en cada transacción porque requeriría transferencias de tokens adicionales. Transferir tokens ERC20 requiere una actualización del almacenamiento, por lo que transferir a dos direcciones en lugar de una sería considerablemente más costoso.
Por lo tanto, la tarifa se recauda cuando un proveedor de liquidez llama a burn o mint. Dado que estas operaciones son poco frecuentes en comparación con el [intercambio de tokens](swapping tokens), esto conducirá a ahorros de gas. Para recaudar el mintFee, el contrato calcula la cantidad de tarifas recaudadas desde la última vez que esto ocurrió, y acuña suficientes tokens LP para la dirección del beneficiario de tal manera que este tenga derecho a 1/6 de la tarifa.
Terminología de fee y mintFee
Para evitar confusiones en la terminología, nos referimos a “fee” como el 0.3% recaudado de los traders durante el intercambio, y al “mintFee” como el 1/6 de la tarifa del 0.3%. Sí, tener “fee” en ambos términos no es una gran nomenclatura, pero es con lo que tenemos que trabajar.
La liquidez es la raíz cuadrada de los productos de los balances de tokens en el pool. La justificación de esta fórmula se discutió en el artículo sobre la función swap de Uniswap V2. Parte de la literatura se refiere a esto como donde y tanto como son los balances de tokens en el pool (las reservas de e ). Nos referimos a la liquidez con ya que es más corto de escribir que .
Suposiciones para calcular el mintFee
Para que esto funcione, Uniswap V2 se basa en las siguientes dos invariantes:
- Si no se llama a
mint()ni aburn(), la liquidez del pool solo puede aumentar. - El aumento en la liquidez se debe puramente a las tarifas (o donaciones).
Al medir el aumento en la liquidez desde la última transacción demint()oburn(), el pool sabe cuántas tarifas se recaudaron.
Estas serían buenas pruebas de invariantes para escribir, pero por ahora daremos por sentado que son ciertas.
Ejemplo de cálculo de mintFee
Supongamos que en el pool comienza con 10 token0 y 10 token1.
Después de mucho intercambio y recaudación de tarifas, el nuevo balance del pool es de 40 token0 y 40 token1 en .
La liquidez se mide como la raíz cuadrada del producto de los dos tokens, es decir, . La liquidez era 10 en y 40 en . Dicho de otra manera, y . Vamos a cobrar una tarifa sobre el crecimiento de 10 a 40.
30 unidades de liquidez del total de 40 en se deben a las tarifas de intercambio.
Queremos acuñar suficientes tokens LP, el “mintFee”, de tal manera que el beneficiario reciba 1/6 de la “porción de tarifas” del pool. Es decir, deberían tener derecho a 5 unidades de liquidez (30 / 6) que provinieron de las ganancias.
El protocolo no debería recaudar tarifas sobre ninguna “liquidez original”, es decir, . El protocolo solo debería recaudar tarifas sobre el delta, es decir, .
Cuando se llama a mint() o burn(), Uniswap acuña tokens LP para el destinatario de la tarifa del protocolo. Esto causa una dilución tal que el suministro actual de tokens LP puede canjear la liquidez original más 5/6 de la “liquidez de ganancias” (liquidez de las tarifas de intercambio).
Derivando la fórmula del mintFee
Usemos la siguiente notación:
-
suministro de tokens LP antes de que se acuñen los tokens LP dilusivos de la tarifa del protocolo.
-
es la cantidad de tokens LP que se acuñarán para el protocolo. Debería ser suficiente para canjear 1/6 de la liquidez de ganancias.
-
es la liquidez del depósito original, es decir, la liquidez que proporcionaron los LPs.
-
es la liquidez de los depósitos originales y la liquidez que resulta de las tarifas de intercambio.
-
es la cantidad de liquidez adeudada a los LPs neta de la tarifa del protocolo. Es decir, los LPs deberían tener derecho a su depósito original y 5/6 de las ganancias.
-
es la cantidad de liquidez adeudada al protocolo. Esto es 1/6 de .
Para calcular observamos que la siguiente invariante debe ser cierta:
En otras palabras, el suministro total anterior de tokens LP puede canjear la liquidez correspondiente a los LPs, y tokens LP pueden canjear la cantidad correspondiente al protocolo.
El siguiente gráfico despeja en función del cambio en la liquidez.

El código _mintFee() de Uniswap V2
Con esa derivación en mente, la mayor parte de la función _mintFee de Uniswap V2 debería explicarse por sí misma. Aquí hay algunos cambios en la notación:
- la liquidez actual después de las tarifas es
rootK - la liquidez previa es
kLast - el suministro de tokens LP antes de la dilución es
totalSupply - la función cambia el estado, acuña el mintFee dentro de la función en lugar de devolver el cálculo del mintFee (resaltado en azul)
- la tarifa se puede encender y apagar con la bandera
feeOnque aún no hemos discutido

Profundizaremos un poco más en esta función, pero primero queremos notar dónde se actualiza kLast.
Dónde se actualiza klast
En el código anterior, kLast no se establece a menos que feeOn se cambie a false. Se establece al finalizar el mint y burn, pero no en el swap porque estamos interesados en medir el crecimiento de las tarifas debido a los intercambios entre eventos de depósito y retiro de liquidez. El lugar donde se establece kLast está marcado con un cuadro amarillo.
Función Mint actualizando klast

Función Burn actualizando klast

Condiciones del código _mintFee
Ahora que entendemos cómo se actualiza kLast, podemos explicar completamente la función _mintFee.

Consideremos las posibilidades en el fragmento de código anterior, repetido por conveniencia.
- El
feeOnesfalse, no se acuña nada (resaltado en verde) - El
feeOnesfalse,kLastes cero (resaltado en amarillo) - El
feeOnesfalse,kLastno es cero (resaltado en amarillo) - El
feeOnestrue, pero no hubo crecimiento en la liquidez (resaltado en naranja) - El
feeOnestrue, y hubo crecimiento de liquidez (resaltado en naranja), por lo que se aplica el mint fee (resaltado en azul)
Es más fácil ver la lógica en un árbol de decisión, así que aquí está el árbol de decisión con las ramas coloreadas igual que las declaraciones if.

Aprende más con RareSkills
Por favor, consulta nuestro bootcamp de blockchain para ver nuestra oferta de cursos.
Publicado originalmente el 14 de noviembre de 2023