Contratos para GMX Synthetics.
Esta sección proporciona una descripción general de cómo funciona el sistema.
Para obtener una descripción general técnica, consulte la sección más abajo.
Los mercados admiten tanto el comercio al contado como el de perpetradores, y se crean especificando un token de garantía largo, un token de garantía corto y un token de índice.
Ejemplos:
Los proveedores de liquidez pueden depositar el token de garantía largo o corto, o ambos, para acuñar tokens de liquidez.
El token de garantía largo se utiliza para respaldar posiciones largas, mientras que el token de garantía corto se utiliza para respaldar posiciones cortas.
Los proveedores de liquidez asumen las ganancias y pérdidas de los comerciantes para el mercado al que proporcionan liquidez.
Tener mercados separados permite aislar el riesgo, los proveedores de liquidez solo están expuestos a los mercados en los que depositan, lo que potencialmente permite cotizaciones sin permiso.
Los comerciantes pueden utilizar el token largo o corto como garantía para el mercado.
Los contratos soportan las siguientes características principales:
Para evitar problemas iniciales, la mayoría de las acciones requieren dos pasos para ejecutarse:
Los precios los proporciona un sistema Oracle fuera de la cadena, que firma continuamente los precios en función del momento en que se consultaron.
Se firma tanto un precio mínimo como un precio máximo, esto permite incluir información sobre los diferenciales de oferta y demanda.
Los precios almacenados dentro del contrato de Oracle representan el precio de una unidad del token utilizando un valor con 30 decimales de precisión.
Representar los precios de esta manera permite simplificar las conversiones entre cantidades de tokens y valores fiduciarios, por ejemplo, para calcular el valor fiduciario de un número determinado de tokens, el cálculo sería simplemente: cantidad de tokens * precio de Oracle, para calcular la cantidad de tokens para un valor fiduciario sería: valor fiduciario / precio de Oracle.
Las tarifas de financiación y el impacto en los precios mantienen equilibrados los largos y cortos, al tiempo que reducen el riesgo de manipulación de precios.
Hay algunos guardianes y nodos en el sistema:
Hay algunos tipos principales de contratos:
Los contratos se dividen en estos tipos para permitir una mejora gradual.
La mayoría de los datos se almacenan mediante el contrato DataStore.
*Los contratos storeUtils almacenan datos de estructuras utilizando DataStore, lo que permite agregar nuevas claves a las estructuras.
Los EnnumberableSets se utilizan para permitir que las interfaces o los guardianes consulten fácilmente las listas de pedidos y las listas de posiciones; esto se utiliza sobre los indexadores, ya que puede haber un retraso para que los indexadores sincronicen el último bloque. Tener las listas almacenadas directamente en el contrato también ayuda a garantizar que se puedan recuperar y verificar datos precisos cuando sea necesario.
*Los contratos eventUtils emiten eventos utilizando el emisor de eventos, los eventos se generalizan para permitir que se agreguen nuevos valores-clave a los eventos sin requerir una actualización de las ABI.
Abreviatura de GMX Liquidity Vault: un contenedor de múltiples mercados con los mismos tokens largos y cortos. La liquidez se reequilibra automáticamente entre los mercados subyacentes en función de la utilización de los mercados.
Esta sección proporciona una descripción técnica de los contratos.
Los mercados se crean usando MarketFactory.createMarket
, esto crea un MarketToken y almacena una estructura Market.Props en MarketStore.
El MarketToken se utiliza para realizar un seguimiento de la participación de los proveedores de liquidez en el mercado y para almacenar los tokens para cada mercado.
En cualquier momento, el precio de un MarketToken es (worth of market pool) / MarketToken.totalSupply()
, la función MarketUtils.getMarketTokenPrice
se puede utilizar para recuperar este valor.
El valor del mercado común es la suma de
Los depósitos agregan tokens largos/cortos al grupo del mercado y acuñan MarketTokens al depositante.
Las solicitudes de depósitos se crean llamando a ExchangeRouter.createDeposit, especificando:
Las solicitudes de depósito se ejecutan utilizando DepositHandler.executeDeposit; si el depósito se creó en la marca de tiempo n
, debe ejecutarse con los precios de Oracle después de la marca de tiempo n
.
La cantidad de MarketTokens que se acuñarán, antes de las tarifas y el impacto en el precio, se calcula como (worth of tokens deposited) / (worth of market pool) * MarketToken.totalSupply()
.
Los retiros queman MarketTokens a cambio de los tokens largos/cortos del grupo de un mercado.
Las solicitudes de retiro se crean llamando a ExchangeRouter.createWithdrawal, especificando:
Las solicitudes de retiro se ejecutan usando WithdrawalHandler.executeWithdrawal; si el retiro se creó en la marca de tiempo n
, debe ejecutarse con los precios de Oracle después de la marca de tiempo n
.
La cantidad de tokens largos o cortos que se canjearán, antes de las tarifas y el impacto en el precio, se calcula como (worth of market tokens) / (long / short token price)
.
Los tokens largos y cortos de un mercado se pueden intercambiar entre sí.
Por ejemplo, si el mercado ETH/USD tiene WETH como token largo y USDC como token corto, WETH se puede enviar al mercado para intercambiarlo por USDC y USDC se puede enviar al mercado para intercambiarlo por WETH.
Las solicitudes de órdenes de intercambio se crean llamando a ExchangeRouter.createOrder, especificando:
El monto de salida del swap, antes de tarifas e impacto en el precio, (amount of tokens in) * (token in price) / (token out price)
.
Las solicitudes de órdenes de intercambio de mercado se ejecutan utilizando OrderHandler.executeOrder; si la orden se creó en la marca de tiempo n
, debe ejecutarse con los precios de Oracle después de la marca de tiempo n
.
Órdenes de swap pasivas que deben ejecutarse cuando el monto de salida coincida con el monto de salida mínimo especificado por el usuario.
Las solicitudes de orden de swap de límite se ejecutan utilizando OrderHandler.executeOrder; si la orden se creó en la marca de tiempo n
, debe ejecutarse con los precios de Oracle después de la marca de tiempo n
.
Abra o aumente una posición de perpetrador larga/corta.
Las solicitudes de órdenes de aumento de mercado se crean llamando a ExchangeRouter.createOrder, especificando:
Las solicitudes de orden de aumento del mercado se ejecutan utilizando OrderHandler.executeOrder; si la orden se creó en la marca de tiempo n
, debe ejecutarse con los precios de Oracle después de la marca de tiempo n
.
Órdenes pasivas de aumento de posición que deben ejecutarse cuando el precio del token índice coincida con el precio aceptable especificado por el usuario.
Ejemplo de posición larga: si el precio actual del token de índice es $5000, se puede crear una orden de aumento de límite con un precio aceptable de $4990, la orden se puede ejecutar cuando el precio del token de índice sea <= $4990.
Ejemplo de posición corta: si el precio actual del token de índice es $5000, se puede crear una orden de aumento de límite con un precio aceptable de $5010, la orden se puede ejecutar cuando el precio del token de índice sea >= $5010.
Las solicitudes de orden de aumento de límite se ejecutan utilizando OrderHandler.executeOrder; si la orden se creó en la marca de tiempo n
, debe ejecutarse con los precios de Oracle después de la marca de tiempo n
.
Cerrar o disminuir una posición de delincuente larga/corta.
Las solicitudes de orden de disminución del mercado se crean llamando a ExchangeRouter.createOrder, especificando:
Las solicitudes de órdenes de disminución del mercado se ejecutan utilizando OrderHandler.executeOrder; si la orden se creó en la marca de tiempo n
, debe ejecutarse con los precios de Oracle después de la marca de tiempo n
.
Órdenes pasivas de disminución de posición que deben ejecutarse cuando el precio del token índice coincida con el precio aceptable especificado por el usuario.
Ejemplo de posición larga: si el precio actual del token de índice es $5000, se puede crear una orden de disminución de límite con un precio aceptable de $5010, la orden se puede ejecutar cuando el precio del token de índice sea >= $5010.
Ejemplo de posición corta: si el precio actual del token de índice es $5000, se puede crear una orden de disminución de límite con un precio aceptable de $4990, la orden se puede ejecutar cuando el precio del token de índice sea <= $4990.
Las solicitudes de orden de reducción de límite se ejecutan utilizando OrderHandler.executeOrder; si la orden se creó en la marca de tiempo n
, debe ejecutarse con los precios de Oracle después de la marca de tiempo n
.
Órdenes pasivas de disminución de posición que deben ejecutarse cuando el precio del token índice cruza el precio aceptable especificado por el usuario.
Ejemplo de posición larga: si el precio actual del token de índice es $5000, se puede crear una orden de reducción de pérdidas con un precio aceptable de $4990, la orden se puede ejecutar cuando el precio del token de índice sea <= $4990.
Ejemplo de posición corta: si el precio actual del token de índice es $5000, se puede crear una orden de reducción de pérdidas con un precio aceptable de $5010, la orden se puede ejecutar cuando el precio del token de índice sea >= $5010.
Las solicitudes de orden de reducción de stop-loss se ejecutan utilizando OrderHandler.executeOrder; si la orden se creó en la marca de tiempo n
, debe ejecutarse con los precios de Oracle después de la marca de tiempo n
.
El precio de ETH es 5000 y ETH tiene 18 decimales.
El precio de una unidad de ETH es 5000 / (10 ^ 18), 5 * (10 ^ -15)
.
Para manejar los decimales, multiplica el valor por (10 ^ 30)
.
El precio se almacenaría como 5000 / (10 ^ 18) * (10 ^ 30) => 5000 * (10 ^ 12)
.
Para la optimización del gas, estos precios se envían al Oracle en forma de un valor multiplicador decimal uint8 y un valor de precio uint32.
Si el valor del multiplicador decimal se establece en 8, el valor de uint32 sería 5000 * (10 ^ 12) / (10 ^ 8) => 5000 * (10 ^ 4)
.
Con esta configuración, los precios de ETH pueden tener un valor máximo de (2 ^ 32) / (10 ^ 4) => 4,294,967,296 / (10 ^ 4) => 429,496.7296
con 4 decimales de precisión.
El precio de BTC es 60.000 y BTC tiene 8 decimales.
El precio de una unidad de BTC es 60,000 / (10 ^ 8), 6 * (10 ^ -4)
.
El precio se almacenaría como 60,000 / (10 ^ 8) * (10 ^ 30) => 6 * (10 ^ 26) => 60,000 * (10 ^ 22)
.
Valor máximo de precios de BTC: (2 ^ 64) / (10 ^ 2) => 4,294,967,296 / (10 ^ 2) => 42,949,672.96
.
Decimales de precisión: 2.
El precio del USDC es 1 y el USDC tiene 6 decimales.
El precio de una unidad de USDC es 1 / (10 ^ 6), 1 * (10 ^ -6)
.
El precio se almacenaría como 1 / (10 ^ 6) * (10 ^ 30) => 1 * (10 ^ 24)
.
Valor máximo de precios USDC: (2 ^ 64) / (10 ^ 6) => 4,294,967,296 / (10 ^ 6) => 4294.967296
.
Decimales de precisión: 6.
El precio de DG es 0,00000001 y DG tiene 18 decimales.
El precio de una unidad de DG es 0.00000001 / (10 ^ 18), 1 * (10 ^ -26)
.
El precio se almacenaría como 1 * (10 ^ -26) * (10 ^ 30) => 1 * (10 ^ 3)
.
Valor máximo de precios DG: (2 ^ 64) / (10 ^ 11) => 4,294,967,296 / (10 ^ 11) => 0.04294967296
.
Decimales de precisión: 11.
La fórmula para calcular cuál debe ser el valor del multiplicador decimal:
Decimales: 30 - (decimales simbólicos) - (número de decimales deseados para mayor precisión)
Ejemplo de cálculo para WNT:
dataStreamPrice / (10 ^ 8) / (10 ^ 18) * (10 ^ 30)
(5000 * (10 ^ 8)) / (10 ^ 8) / (10 ^ 18) * (10 ^ 30) = 5000 * (10 ^ 12)
dataStreamPrice * multiplier / (10 ^ 30)
(5000 * (10 ^ 8)) * (10 ^ 34) / (10 ^ 30) = 5000 * (10 ^ 12)
Ejemplo de cálculo para WBTC:
dataStreamPrice / (10 ^ 8) / (10 ^ 8) * (10 ^ 30)
(50,000 * (10 ^ 8)) / (10 ^ 8) / (10 ^ 8) * (10 ^ 30) = 50,000 * (10 ^ 22)
dataStreamPrice * multiplier / (10 ^ 30)
(50,000 * (10 ^ 8)) * (10 ^ 44) / (10 ^ 30) = 50,000 * (10 ^ 22)
La fórmula para el multiplicador es: 10 ^ (60 - dataStreamDecimals - tokenDecimals)
Las tarifas de financiación incentivan el equilibrio de las posiciones largas y cortas; el lado con el interés abierto más grande paga una tarifa de financiación al lado con el interés abierto más pequeño.
Las tarifas de financiación para el lado más grande se calculan como (funding factor per second) * (open interest imbalance) ^ (funding exponent factor) / (total open interest)
.
Por ejemplo, si el factor de financiación por segundo es 1/50 000, el factor exponente de financiación es 1, el interés abierto largo es 150 000 $ y el interés abierto corto es 50 000 $, entonces la tarifa de financiación por segundo para posiciones largas sería (1 / 50,000) * 100,000 / 200,000 => 0.00001 => 0.001%
.
La tarifa de financiación por segundo para cortos sería -0.00001 * 150,000 / 50,000 => 0.00003 => -0.003%
.
También es posible establecer un valor de financiaciónIncreaseFactorPerSecond, lo que daría como resultado la siguiente lógica de financiación:
longShortImbalance
se calcula como [abs(longOpenInterest - shortOpenInterest) / totalOpenInterest] ^ fundingExponentFactor
longShortImbalance
actual es mayor que el thresholdForStableFunding
, entonces la tasa de financiación aumentará en longShortImbalance * fundingIncreaseFactorPerSecond
longShortImbalance
actual es mayor que thresholdForDecreaseFunding
y menor que thresholdForStableFunding
y el sesgo está en la misma dirección que la financiación, entonces la tasa de financiación no cambiarálongShortImbalance
actual es menor que thresholdForDecreaseFunding
y el sesgo está en la misma dirección que el financiamiento, entonces la tasa de financiamiento disminuirá en fundingDecreaseFactorPerSecond
Dado que longShortImbalance > umbralForStableFunding, saveFundingFactorPerSecond debería aumentar en 0.0001% * 6% * 600 = 0.0036%
Dado que los largos ya están pagando cortos, el sesgo es el mismo y longShortImbalance <umbralForStableFunding, saveFundingFactorPerSecond no debería cambiar
Dado que longShortImbalance <umbralForDecreaseFunding, saveFundingFactorPerSecond debería disminuir en un 0.000002% * 600 = 0.0012%
Dado que el sesgo está en la otra dirección, saveFundingFactorPerSecond debería disminuir en 0.0001% * 1% * 600 = 0.0006%
Tenga en cuenta que existen posibles formas de jugar con las tarifas de financiación; los factores de financiación deben ajustarse para minimizar esta posibilidad:
Si longOpenInterest > shortOpenInterest y longShortImbalance están dentro del umbral de StableFunding, un usuario que tenga una posición corta podría abrir una posición larga para aumentar el longShortImbalance e intentar hacer que aumente la tarifa de financiación. En un mercado activo, debería ser difícil predecir cuándo alguien más abriría una posición corta contraria para ganar la mayor tarifa de financiación, lo que debería dificultar este juego; los factores de financiación también se pueden ajustar para ayudar a minimizar el beneficio de este juego. .
Si longOpenInterest > shortOpenInterest y longShortImbalance > umbralForStableFunding, un operador que mantenga una posición larga podría realizar múltiples operaciones pequeñas durante este tiempo para garantizar que el factor de financiación se actualice continuamente en lugar de utilizar un valor mayor durante toda la duración, esto debería minimizar el comisión de financiación para posiciones largas, pero no debe reducir la comisión de financiación por debajo de las tasas esperadas.
Se paga una tarifa de préstamo a los proveedores de liquidez, lo que ayuda a evitar que los usuarios abran posiciones largas y cortas para aprovechar la capacidad del fondo sin pagar ninguna tarifa.
Las tarifas de endeudamiento pueden utilizar un modelo de curva o un modelo de torsión.
Para utilizar el modelo de curva, las claves a configurar serían BORROWING_FACTOR
y BORROWING_EXPONENT_FACTOR
, el factor de endeudamiento por segundo se calcularía como:
// reservedUsd is the total USD value reserved for positions
reservedUsd = MarketUtils.getReservedUsd(...)
// poolUsd is the USD value of the pool excluding pending trader PnL
poolUsd = MarketUtils.getPoolUsdWithoutPnl(...)
// reservedUsdAfterExponent is the reservedUsd after applying the borrowingExponentFactor for the market
reservedUsdAfterExponent = applyExponentFactor(reservedUsd, borrowingExponentFactor)
borrowingFactorPerSecond = borrowingFactor * reservedUsdAfterExponent / poolUsd
Para usar el modelo kink, las claves a configurar serían OPTIMAL_USAGE_FACTOR
, BASE_BORROWING_FACTOR
y ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR
, el factor de endeudamiento por segundo se calcularía como:
// usageFactor is the ratio of value reserved for positions to available value that can be reserved
usageFactor = MarketUtils.getUsageFactor(...)
borrowingFactorPerSecond = baseBorrowingFactor * usageFactor
if (usageFactor > optimalUsageFactor) {
diff = usageFactor - optimalUsageFactor
additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor
borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / (Precision.FLOAT_PRECISION - optimalUsageFactor)
}
También existe una opción para establecer un indicador skipBorrowingFeeForSmallerSide, lo que daría como resultado que la tarifa de préstamo para el lado más pequeño se establezca en cero. Por ejemplo, si hay más posiciones largas que cortas y skipBorrowingFeeForSmallerSide es verdadero, entonces la tarifa de préstamo para las posiciones cortas sería cero.
El código para el impacto del precio se puede encontrar en los contratos /pricing
.
El impacto en el precio se calcula como:
(initial USD difference) ^ (price impact exponent) * (price impact factor) - (next USD difference) ^ (price impact exponent) * (price impact factor)
Para los swaps, el desequilibrio se calcula como la diferencia en el valor de los tokens largos y cortos.
Por ejemplo:
price impact exponent
se establece en 2 y price impact factor
se establece en 0.01 / 50,000
0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500
50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375
Para acciones de posición (aumentar/disminuir posición), el desequilibrio se calcula como la diferencia en el interés abierto largo y corto.
price impact exponents
y price impact factors
se configuran por mercado y pueden diferir para acciones al contado y de posición.
Tenga en cuenta que este cálculo es el impacto en el precio de la operación de un usuario, no el impacto en el precio en el conjunto. Por ejemplo, la operación de un usuario puede tener un impacto en el precio del 0,25%, la siguiente operación por una cantidad muy pequeña puede tener un impacto en el precio del 0,5%.
El propósito del impacto en el precio es:
Dado que los contratos utilizan un precio oráculo que sería un precio promedio o mediano de múltiples intercambios de referencia. Sin un impacto en los precios, puede resultar rentable manipular los precios en las bolsas de referencia mientras se ejecutan órdenes sobre los contratos.
Este riesgo también estará presente si los valores de impacto positivo y negativo en el precio son similares, por esa razón el impacto positivo en el precio debe establecerse en un valor bajo en tiempos de volatilidad o movimientos irregulares de precios.
Para el impacto del precio en los aumentos/disminuciones de la posición, si el impacto negativo en el precio se deduce como garantía de la posición, esto podría llevar a que la posición tenga un apalancamiento diferente al que pretendía el usuario, por lo que en lugar de deducir la garantía, se calcula el precio de entrada/salida de la posición. ajustado en función del impacto en el precio.
Por ejemplo:
Si el token de índice es diferente tanto del token largo como del token corto del mercado, entonces es posible que el valor del pool se vea afectado significativamente por el pool de impacto de posición, si el pool de impacto de posición es muy grande y el token de índice tiene un precio alto. aumentar. Se puede agregar una opción para reducir gradualmente el tamaño del grupo de impacto de posición si esto se convierte en un problema.
El impacto en el precio también se rastrea utilizando un valor de inventario virtual para posiciones y swaps, esto rastrea el desequilibrio de tokens en mercados similares, por ejemplo, ETH/USDC, ETH/USDT.
En caso de un gran movimiento de precios, es posible que una gran cantidad de posiciones se reduzcan o liquiden en un lado, causando un desequilibrio significativo entre el interés abierto largo y corto, lo que podría llevar a valores de impacto de precio muy altos. Para mitigar esto, se puede configurar un valor de factor de impacto de posición máximo. Si el impacto en el precio actual excede el impacto máximo en el precio negativo, entonces cualquier exceso de garantía deducido más allá del impacto máximo en el precio negativo se mantendría dentro del contrato; si no se detectó manipulación del precio, esta garantía se puede entregar al usuario. Cuando el impacto negativo en el precio está limitado, puede ser rentable abrir y cerrar posiciones inmediatamente, ya que el impacto positivo en el precio ahora puede ser mayor que el impacto negativo limitado en el precio. Para evitar esto, el impacto máximo positivo en el precio debe configurarse para que esté por debajo del impacto máximo negativo en el precio.
Hay tarifas de swap y tarifas de posición configurables y por mercado.
Las tarifas de ejecución también se estiman y contabilizan al crear solicitudes de depósito, retiro y orden para que los poseedores puedan ejecutar transacciones a un costo neto cercano a cero.
Si un mercado tiene monedas estables como token de garantía corta, debería poder pagar la totalidad de las ganancias a corto plazo si el interés abierto máximo en corto no excede la cantidad de monedas estables en el grupo.
Si un mercado tiene un token de garantía largo que es diferente del token de índice, es posible que las ganancias largas no se paguen en su totalidad si el aumento de precio del token de índice excede el aumento de precio del token de garantía largo.
Los mercados tienen un factor de reserva que permite limitar el interés abierto a un porcentaje del tamaño del pool, lo que reduce el impacto de las ganancias de las posiciones cortas y reduce el riesgo de que las posiciones largas no puedan pagarse en su totalidad.
El precio de un token de mercado depende del valor de los activos en el grupo y del PnL neto pendiente de las posiciones abiertas de los comerciantes.
Es posible que se limite el PnL pendiente; los factores utilizados para calcular el precio del token de mercado pueden diferir según la actividad:
Keys.MAX_PNL_FACTOR_FOR_DEPOSITS: este es el límite del factor PnL al calcular el precio del token de mercado para depósitos
Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS: este es el límite del factor PnL al calcular el precio del token de mercado para retiros
Keys.MAX_PNL_FACTOR_FOR_TRADERS: este es el límite del factor PnL al calcular el precio del token de mercado para cerrar una posición
Estos diferentes factores se pueden configurar para ayudar a los proveedores de liquidez a gestionar el riesgo e incentivar los depósitos cuando sea necesario, por ejemplo, la limitación del PnL del comerciante ayuda a limitar la cantidad en la que se puede reducir el precio del token de mercado debido al PnL del comerciante, la limitación del PnL para depósitos y retiros puede llevar a a un precio de token de mercado más bajo para los depósitos en comparación con los retiros, lo que puede incentivar los depósitos cuando el PnL pendiente es alto.
minCollateralFactor: Determina la relación mínima permitida de (garantía de la posición) / (tamaño de la posición)
maxPoolAmount: la cantidad máxima de tokens que se pueden depositar en un mercado
maxOpenInterest: El interés abierto máximo que se puede abrir para un mercado
reserveFactor: Esto determina la proporción máxima permitida de (valor de tokens reservados para posiciones) / (tokens en el grupo)
maxPnlFactor: la proporción máxima de (PnL / valor de tokens en el grupo)
positionFeeFactor: Esto determina el monto porcentual de las tarifas que se deducirán por las acciones de aumento/disminución de la posición, el monto de la tarifa se basa en el cambio en el tamaño de la posición.
positionImpactFactor: este es el "factor de impacto en el precio" para las posiciones descritas en la sección "Impacto en el precio".
maxPositionImpactFactor: este es el "impacto máximo en el precio" para las posiciones descritas en la sección "Impacto en el precio".
positionImpactExponentFactor: este es el valor del "exponente de impacto en el precio" para las acciones de posición, descrito en la sección "Impacto en el precio".
swapFeeFactor: esto determina el monto porcentual de las tarifas que se deducirán para los swaps, el monto de la tarifa se basa en el monto del swap.
swapImpactFactor: este es el "factor de impacto en el precio" descrito en la sección "Impacto en el precio".
swapImpactExponentFactor: este es el valor del "exponente de impacto en el precio" para depósitos y swaps, descrito en la sección "Impacto en el precio" anterior.
FundingFactor: este es el valor del "factor de financiación por segundo" descrito en la sección "Tarifas de financiación".
lendingFactorForLongs: este es el "factor de endeudamiento" para posiciones largas descrito en la sección "Comisiones de endeudamiento".
lendingFactorForShorts: este es el "factor de endeudamiento" para posiciones cortas que se describe en la sección "Comisiones de endeudamiento".
lendingExponentFactorForLongs: este es el "factor exponente de préstamo" para posiciones largas descritas en la sección "Comisiones de préstamo".
lendingExponentFactorForShorts: este es el "factor exponente de endeudamiento" para posiciones largas descritas en la sección "Comisiones de endeudamiento".
Los roles se administran en RoleStore, RoleAdmin tiene acceso para otorgar y revocar cualquier rol.
El RoleAdmin será el implementador inicialmente, pero debe eliminarse una vez que se hayan configurado los roles.
Después de la configuración inicial:
Sólo el contrato Timelock debe tener el rol RoleAdmin
Los administradores de bloqueo de tiempo pueden otorgar nuevos roles con un retraso de tiempo
Los valores del sistema solo deben establecerse mediante el contrato de configuración
Ninguna EOA debería tener una función de controlador
Los encargados de la configuración y los administradores de bloqueo de tiempo podrían potencialmente interrumpir el funcionamiento normal mediante la desactivación de funciones, la configuración incorrecta de valores, la inclusión de tokens maliciosos en la lista blanca, el abuso del valor de impacto positivo en el precio, etc.
Se espera que el timelock multisig revoque los permisos de cuentas maliciosas o comprometidas.
Los encargados de las órdenes y los encargados de las órdenes congeladas podrían potencialmente extraer valor a través de pedidos de transacciones, ejecución retrasada de transacciones, ejecución de ADL, etc., esto se mitigará parcialmente con una red de guardianes.
Se espera que los firmantes de Oracle informen con precisión el precio de los tokens
Los tokens colaterales deben incluirse en la lista blanca con un TOKEN_TRANSFER_GAS_LIMIT configurado
Los tokens de rebase, los tokens que cambian el saldo en la transferencia, los tokens con quema de tokens, los tokens con devoluciones de llamada, por ejemplo, los tokens ERC-777, etc., no son compatibles con el sistema y no deben incluirse en la lista blanca.
Los encargados de las órdenes pueden utilizar precios de diferentes marcas de tiempo para las órdenes limitadas con un swap, lo que daría lugar a diferentes cantidades de producción.
Se espera que los encargados de los pedidos validen si una transacción se revertirá antes de enviarla para minimizar el desperdicio de gas.
Los encargados de las órdenes pueden hacer que las solicitudes se cancelen en lugar de ejecutarse al ejecutar la solicitud sin suficiente gas.
Si una transacción de ejecución requiere una gran cantidad de gas cercana al límite máximo de gas del bloque, es posible rellenar bloques para evitar que la transacción se incluya en bloques.
En ciertas cadenas de bloques, es posible que el poseedor tenga control sobre el tx.gasprice utilizado para ejecutar una transacción, lo que afectaría la tarifa de ejecución pagada al poseedor.
Un usuario malintencionado puede evitar que las órdenes se ejecuten intencionalmente, lo que provoca que el mercado se desequilibre y tenga como resultado un alto impacto en el precio; esto debería ser costoso y difícil de aprovechar.
El impacto en los precios se puede reducir mediante el uso de posiciones y swaps y el comercio entre mercados, cadenas, bifurcaciones y otros protocolos; esto se mitiga parcialmente con el seguimiento virtual del inventario.
Un usuario puede reducir el impacto en el precio mediante el uso de posiciones de alto apalancamiento, esto se mitiga parcialmente con el valor MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER.
El cálculo de los valores de impacto del precio no tiene en cuenta las tarifas y los efectos resultantes del impacto en el precio en sí, para la mayoría de los casos, el efecto sobre el cálculo del impacto del precio debe ser pequeño
Es raro pero posible que el valor de una piscina se vuelva negativo, esto puede suceder ya que el PNL impactante y pendiente se resta del valor de las tokens en la piscina
Debido a la diferencia en el impacto positivo y negativo del precio de la posición, puede haber una acumulación de cantidades de token virtual en el grupo de impacto de posición que afectaría el precio de los tokens de mercado, el grupo de impacto de posición debe distribuirse gradualmente si es necesario
El inventario virtual rastrea la cantidad de tokens en las piscinas, debe asegurarse de que los tokens en cada agrupación sean del mismo tipo y tienen los mismos decimales, es decir, los tokens largos en las piscinas en el grupo deben tener los mismos decimales, las fichas cortas en las piscinas En el grupo debe tener los mismos decimales, suponiendo que el USDC tenga 6 decimales y DAI tiene 18 decimales, mercados como ETH-USDC, ETHAI no debe agruparse
Las ID virtuales deben establecerse antes de la creación de mercado / token Whiteisting, si se establece después de que se realiza el comercio de token / mercado, el seguimiento no sería preciso y es posible que deba ajustarse
Para L2s con secuenciadores, no hay validación de contrato para verificar si el secuenciador L2 está activo, los guardianes de Oracle deben dejar de firmar precios si el secuenciador no crea bloques, si el secuenciador reanuda la operación regular, los guardianes de Oracle deben firmar precios para los precios de los Últimos bloques utilizando los últimos precios recuperados
En caso de que un secuenciador L2 esté abajo, puede evitar depósitos en posiciones para evitar liquidaciones
Para las transacciones que se pueden ejecutar completamente utilizando alimentos en el precio en la cadena, puede ser posible aprovechar los precios obsoletos debido a la latencia de los precios o la cadena que está disminuyendo, el uso de los alimentos de los precios en la cadena debe ser temporal y los alimentos de baja latencia deben ser utilizado en su lugar una vez que todos los tokens son compatibles
Los reorgs de bloque podrían permitir que un usuario cancele retroactivamente un pedido después de que se haya ejecutado si el precio no se movía favorablemente para el usuario, se debe tener cuidado para manejar este caso si se usa los contratos en las cadenas donde es posible reorganizar largos reorganización
La actualización y la cancelación de los pedidos podrían estar en primera ejecución para evitar la ejecución del pedido, esto no debería ser un problema si la probabilidad de una carrera frontal exitosa es inferior o igual al 50%, si la probabilidad es superior al 50%, tarifas y tarifas y tarifas El impacto del precio debe ajustarse para garantizar que la estrategia no sea rentable neta, ajustar la tarifa de la interfaz de usuario o el descuento de referencia podría usarse de manera similar para causar cancelaciones de pedidos
En caso de tiempo de inactividad de la cadena de bloques u oráculo, los pedidos pueden ejecutarse a precios significativamente diferentes o no ejecutar si el precio aceptable de la orden no se puede cumplir
Existe una dependencia de la precisión de la marca de tiempo de bloque porque los precios de Oracle se validan contra este valor, para blockchains donde los nodos de blockchain tienen cierto control sobre la marca de tiempo, se debe tener cuidado para establecer el oracletimestampadjustment a un valor que haría que la manipulación de la manipulación de la manipulación de la manipulación de la manipulación de la manipulación marca de tiempo no rentable
La función de cambio GLV puede explotarse aumentando temporalmente la utilización en un mercado que generalmente tiene una baja utilización. Una vez que el guardián ejecuta el cambio, el atacante puede reducir la utilización de regreso a sus niveles normales. Las tarifas de posición y el impacto en el precio deben configurarse de una manera que haga que este ataque sea lo suficientemente costoso como para cubrir la pérdida de GLV.
En GLV puede haber mercados GM que estén por encima de sus máximos pnltopoolfactorfortraders. Si el maxpnlfactorfordeposits de este mercado GM es más alto que maxpnlfactorforTraders, entonces el mercado de GM se valora durante los depósitos de lo que serán una vez que los comerciantes se hayan dado cuenta de sus ganancias limitadas. El usuario malicioso puede observar un mercado de GM en tal condición y depositar en el GLV que contenga para ganar de ADL que pronto seguirá. Para evitar esto, maxpnlfactorfordeposits debe ser menor o igual a maxpnlfactorforTraders.
Técnicamente es posible que el valor de mercado se vuelva negativo. En este caso, el GLV sería inutilizable hasta que el valor de mercado se vuelva positivo.
Los tokens GM podrían volverse ilíquidos debido al alto factor PNL o al alto USD reservado. Los usuarios pueden depositar tokens GM ilíquidos en GVL y retirar liquidez de un mercado diferente, dejando el GLV con tokens ilíquidos. Los parámetros GlvmaxMarketTokenBalanceusd y GlvmaxMarketTokenBalanCeAlount deberían tener en cuenta el riesgo de un mercado para evitar tener demasiados tokens GM de un mercado arriesgado.
scripts/verifyFallback.ts
se puede usar para verificar los contratosnpx hardhat verify
, a partir de entonces, todos los contratos de MarketToken deberían verificarse ya que el código fuente sería el mismo Si se agregan nuevos contratos que pueden conducir a una diferencia en los precios, por ejemplo, tokens de mercado entre los contratos antiguos y nuevos, entonces se debe tener cuidado para deshabilitar los contratos antiguos antes de que los nuevos contratos estén habilitados
Se debe recordar a los protocolos externos que usen el contrato del lector o cálculos potencialmente obsoletos para el precio que usen los últimos contratos y cálculos, por ejemplo, el precio de la cadena para los tokens GM
Se recomienda publicar un mejor esfuerzo en ChangeLog que documente cambios importantes que las integraciones deben tener en cuenta, por ejemplo, si se agrega un campo a una estructura que se pasa a una función de devolución de llamada, este cambio puede no ser obvio para las integraciones
Si los contratos se utilizan para apoyar los mercados sintéticos de capital, se debe tener cuidado para garantizar que se puedan manejar divisiones de acciones y cambios similares
Los contratos con el rol del "controlador" tienen acceso a funciones importantes, como establecer los valores de los correos de datos, debido a esto, se debe tener cuidado para garantizar que dichos contratos no tengan funciones o funciones genéricas que puedan usarse para cambiar los valores importantes
Se deben agregar pruebas para los diferentes tipos de mercado, por ejemplo, mercados de solo spot, mercados de tokens individuales
El orden de los valores en el evento event para devoluciones de llamada no debe modificarse a menos que sea estrictamente necesario, ya que los contratos de devolución de llamada pueden hacer referencia a los valores por un índice fijo
Tenga en cuenta que si se cambia una estructura que se pasa a devoluciones de llamada, por ejemplo, depósito, retiro, estructuras de pedidos, esto causaría las funciones de los contratos de devolución de llamada que esperan que la estructura anterior deje de funcionar, debido a esto, los cambios en las estructuras deben destacarse a las integraciones
Si se utiliza el sistema de referencia, el orden de la orden se debe dar acceso a actualizar el código de referencia para los operadores
Los depósitos, retiros y pedidos pueden cancelarse si los requisitos especificados en la solicitud no se pueden cumplir, por ejemplo, la cantidad mínima. Verifique dónde se enviarán fondos y reembolsos de gas en la cancelación para garantizar que coincida con las expectativas.
La disminución de los pedidos de posición puede generar dos tokens en lugar de un solo token, en caso de que el intercambio de posición de disminución falle, también es posible que el monto de la salida y la garantía no sean suficientes para cubrir las tarifas, lo que hace que la orden no se ejecute
Si hay una gran extensión, es posible que abrir / cerrar una posición pueda cambiar significativamente el precio mínimo y máximo del token del mercado, esto no debe ser manipulable de manera rentable
Cambios en valores de configuración como Funding_Factor, stable_funding_factor, préstamo_factor, skip_borrowing_fee_for_smaller_side, préstamos_fee_receiver_factor, podría conducir a cargos adicionales para los usuarios, también podría dar lugar a un cambio en el precio de los tokens de mercado
Si el comerciante PNL está limitado debido a max_pnl_factor_for_traders, el porcentaje de ganancias pagado a los comerciantes puede diferir dependiendo del orden de cuándo se reducen / cerran las posiciones ya que el límite se vuelve a calcular en función del estado actual del grupo
Los datos del evento se pueden pasar a los contratos de devolución de llamada, el orden de los parámetros en el evento eventData se intentará sin cambios, por lo que se puede acceder a los parámetros por índice, por seguridad, la clave del parámetro aún se debe validar antes de usar si coincide con el valor esperado
Algunos parámetros como orden.sizeelta y orden.initialCollateralDeltaMount pueden actualizarse durante la ejecución, los valores actualizados pueden no pasar al contrato de devolución de llamada
Al crear un contrato de devolución de llamada, el contrato de devolución de llamada puede necesitar que la preparación blanca de depósitos, OrderHandler o RephirdalHandler, debe tenerse en cuenta que se pueden implementar nuevas versiones de estos manejadores a medida que se agrega un nuevo código, también es posible que dos manejadores sean dos manejadores. Existen temporalmente al mismo tiempo, por ejemplo, OrderHandler (1), OrderHandler (2), debido a esto, el contrato de devolución de llamada debe poder la lista blanca y aceptar simultáneamente las devoluciones de llamada de múltiples depósitos, Orderhandlers y Retraídos
Para los contratos de devolución de llamada en lugar de mantener una lista blanca separada para depósitos de depósitos, controladores de orden, retiros de RoleStore.hasRole(msg.sender, Role.CONTROLLER)
, una posible solución sería validar el papel de los msg. Verifique que el sendero de msg. sea un controlador válido
Si usa contratos como el intercambiouter, Oracle o el lector tienen en cuenta que sus direcciones cambiarán a medida que se agrega una nueva lógica
Si se actualizan contratos como el intercambiouter, Oracle o el lector, se debe hacer un esfuerzo para mantener los parámetros de la función iguales, sin embargo, esto no siempre es posible, por ejemplo, si se debe admitir una nueva propiedad de pedido, el intercambiouter.createRoorder params tendrá que ser cambiado
El Rolestore y el almacén de datos para las implementaciones no deberían cambiar, si se cambian, probablemente se necesitarán una migración de fondos de los contratos anteriores a los nuevos contratos.
Si bien el código se ha estructurado para minimizar el riesgo de reentrado de solo lectura, se debe tener cuidado para protegerse contra esta posibilidad
Las drogas de tokens pueden ocurrir en las cuentas de los titulares de tokens GM, la integración de contratos que tengan tokens GM deben poder reclamar estos tokens de otra manera los tokens estarían bloqueados, la implementación exacta para esto variará según el contrato integrador, una posibilidad es permitir reclamar de tokens que no son tokens de mercado, esto se puede verificar utilizando el valor de Keys.MARKET_LIST
Las transferencias ETH se envían con national_token_transfer_gas_limit para el límite de gas, si la transferencia falla debido a un gas insuficiente u otros errores, el ETH se envía como Weth en su lugar
Las cuentas pueden recibir ETH para ADL / liquidaciones, si la cuenta no puede recibir ETH, entonces se enviaría en su lugar
El impacto positivo en el precio está limitado por la cantidad de tokens en los grupos de impacto y se basa en valores configurados
El impacto negativo del precio puede ser limitado por valores configurados
Si se limita el impacto del precio negativo, la cantidad adicional se mantendría en el grupo de garantías reclamables, esto debe reclamarse manualmente utilizando el intercambiouter.
Las tarifas de financiamiento positivas deben reclamarse manualmente utilizando el intercambiouter.
Las recompensas de afiliados deben ser reclamadas manualmente utilizando el intercambiouter.
Los mercados o características pueden estar deshabilitados
La ejecución aún continuará incluso si una devolución de llamada se vuelve
Asegúrese de que las devoluciones de llamada tengan suficiente gas
Los subcuenta pueden crear, actualizar y cancelar cualquier pedido para una cuenta
Los subcuenta pueden gastar Wnt y colateral desde la cuenta
Las tarifas de la interfaz de usuario se pueden cambiar
Se pueden cambiar los descuentos de referencia
Los fondos para direcciones en la lista negra se mantendrán dentro del protocolo
El token de índice no siempre se garantiza que sea el token largo
Las tasas de tarifas cambian dependiendo de si existe un impacto positivo o negativo
Considere el factor PNL al estimar el precio GM
Manejar cancelaciones de depósito
Asegúrese de que solo los controladores con el rol del controlador puedan llamar a las funciones de devolución de llamada AfterDeposteXecution y After -DepositCancellation
Asegúrese de que solo la ejecución correcta de depósitos pueda llamar a las funciones de devolución de llamada
Considere los mercados con el mismo token largo y corto, los swaps no son compatibles con estos mercados
Considere el impacto de precio positivo y negativo
Hay un período de cancelación de solicitud para un retraso configurado donde las solicitudes de depósito no se pueden cancelar
Los montos de producción están sujetos al impacto y tarifas de los precios
Los depósitos no están permitidos por encima del max_pnl_factor_for_deposits
El primer depósito en cualquier mercado debe ir al receptor_for_first_deposit
Se deben usar dos salidas mínimas para retiros
Manejar cancelaciones de retiro
Asegúrese de que solo los manejadores con el rol del controlador puedan llamar a las funciones de devolución de llamada después de la medición de calificación de After WithDrawalExecution
Asegúrese de que solo la ejecución correcta de retiro pueda llamar a las funciones de devolución de llamada
Considere los mercados con el mismo token largo y corto, los swaps no son compatibles con estos mercados
Considere el impacto de precio positivo y negativo
Hay un período de cancelación de solicitud para un retraso configurado donde las solicitudes de retiro no se pueden cancelar
Los montos de producción están sujetos al impacto y tarifas de los precios
Los retiros no están permitidos por encima del max_pnl_factor_for_withdrawals
Manejar las cancelaciones de pedidos
Las liquidaciones y los ADL pueden activar el contrato de devolución de llamada guardado
Los pedidos pueden congelarse
Asegúrese de que solo los manejadores con el rol del controlador puedan llamar a las funciones de la devolución de llamada AfterorderExecution, AfterOrderCancelation y AfterOrderFrozen
Asegúrese de que solo la ejecución correcta del pedido pueda llamar a las funciones de devolución de llamada
Considere los mercados con el mismo token largo y corto, los swaps no son compatibles con estos mercados
Considere el impacto de precio positivo y negativo
Se pueden cambiar los contratos de devolución de llamada guardados
Hay un período de cancelación de solicitud para un retraso configurado donde las solicitudes de pedido no se pueden cancelar
Los montos de producción están sujetos al impacto y tarifas de los precios
El grupo de impacto de posición se distribuye a los proveedores de liquidez a lo largo del tiempo
Si intenta calcular el impacto en el precio, se debe consultar el inventario virtual
Trader PNL está limitado por encima del max_pnl_factor_for_traders
El impacto negativo del precio se puede limitar en la disminución de la posición
Disminuir el tamaño del orden del orden y la colaceraldelta se actualizarán automáticamente si son mayores de lo que la posición puede manejar
Considere la validación de WillpositionCollateralBeSciente
Considere la disminución de los respaldos
Considere la cantidad colateral mínima
Las referencias aún se pagan durante la liquidación
Es posible que las posiciones tengan cero garantías
Las posiciones con tamaño cero no pueden existir
Para compilar contratos:
npx hardhat compile
Para ejecutar todas las pruebas:
npx hardhat test
export NODE_OPTIONS=--max_old_space_size=4096
puede ser necesario para ejecutar pruebas.
Para imprimir métricas de código:
npx ts-node metrics.ts
Para imprimir cobertura de prueba:
npx hardhat coverage