Protocolos de seguridad

Además de la protección contra ataques externos, los contratos del protocolo Geminon incorporan protección contra ataques internos, que son aquellos que podría llevar a cabo un miembro del equipo malicioso o un atacante que se hiciera con el control de las claves del protocolo. Todas las funciones administrativas de los GLP cuyo uso malicioso pueda tener algún impacto sobre los fondos que custodia el contrato, están protegidos con sistemas de seguridad adicionales.

Cambios de parámetros

Los parámetros básicos de un pool solo pueden ser cambiados por el propietario del contrato. Las funciones involucradas tienen algunos mecanismos de seguridad adicionales:

Comisiones de acuñación y canjeo (setMintFee() / setRedeemFee())

Permite cambiar la comisión base que cobra el pool a los usuarios. El acceso malicioso a estas funciones no presenta riesgos significativos, por lo que la única medida de seguridad adicional es que su valor máximo está limitado al 0,5%.

Peso del pool (setPoolWeight())

Permite cambiar el peso objetivo del pool, que influye en el ratio de peso que es un componente de los ratios de acuñación y quema de tokens. El uso malintencionado de la función no tendría un impacto significativo. Incorpora varias comprobaciones adicionales:

  • El nuevo peso no puede ser cero.

  • No puede aumentarse el peso si se ha solicitado la migración o la eliminación del pool.

  • La diferencia entre el nuevo objetivo y el anterior no puede ser mayor al 5%.

  • La diferencia entre el nuevo objetivo y el peso actual del pool no puede ser mayor al 10%.

Cambios de infraestructura

La infraestructura de un pool está constituida por otros contratos del protocolo Geminon o externos con los que el pool interactúa para su funcionamiento. Solo el propietario puede acceder a estas funciones, pero dado que se trata de funciones importantes, todas cuentan con bloqueos temporales de seguridad.

El sistema de bloqueos temporales de cambio de contratos requiere dos pasos: una primera transacción en la que se hace la solicitud de cambio de la dirección del contrato y se especifica la dirección del nuevo contrato usando la función requestAddressChange(), lo cual inicia el contador de tiempo del bloqueo, y una segunda transacción que verifica que ha transcurrido el tiempo de bloqueo (varios días o semanas) y aplica los cambios. El propietario del contrato puede cancelar la solicitud en ese tiempo. Este sistema garantiza que todo cambio es público y se puedan observar las características de los nuevos contratos antes de que entren en funcionamiento.

Cambio del alimentador de precios (applyPriceFeedChange())

El alimentador de precios es un contrato de la red Chainlink que proporciona el precio del colateral en dólares. Este precio se utiliza de forma informativa para las transacciones de los usuarios y en el cálculo de los pesos relativos de los pools, que a su vez influyen en los ratios de acuñación y quema de tokens. Un cambio no autorizado tendría un impacto moderado en el protocolo, aunque no pondría en riesgo fondos de los usuarios, por lo que se emplea un bloqueo intermedio.

Protegido por un bloqueo temporal de 7 días.

Cambio del acuñador de moneda estable (applySCMinterChange())

El acuñador de moneda estable puede pedir tokens GEX aun GLP si se queda sin liquidez para atender los canjeos de moneda estable. Aunque la función de rescate está protegida (ver más adelante), se considera que la introducción de un contrato malicioso en el rol de acuñador de estables presentaría un riesgo alto para los fondos de un GLP, por lo que se emplea un bloqueo largo.

Protegido por un bloqueo temporal de 30 días.

Cambio del oráculo (applyOracleChange())

El oráculo del protocolo (no confundir con el oráculo interno del pool) realiza importantes funciones en la gestión y coordinación de los diferentes contratos del protocolo. También interviene en determinadas comprobaciones de seguridad, además de proporcionar los precios del token GEX a otros contratos. Se considera una función crítica del protocolo, por lo que se emplea un bloqueo largo.

Protegido por un bloqueo temporal de 30 días.

Cambio del contrato de préstamo (applyLenderChange())

El protocolo se diseñó con la idea de que el contrato de préstamos (todavía en desarrollo) pudiera utilizar parcialmente los fondos de los GLP aumentando la eficiencia del capital del protocolo. Por este motivo, se dejó habilitada una función que permitiría realizar estos préstamos. Previamente, es necesario dar de alta la dirección del contrato de préstamos en el GLP. Esta función se considera crítica para la seguridad del protocolo, por lo que se emplea un bloqueo largo.

Protegido por un bloqueo temporal de 30 días.

Migración / eliminación del pool

Los pools de Geminon no utilizan proveedores de liquidez, por lo que toda la liquidez es propiedad del protocolo y no puede ser retirada. Sin embargo, podrían darse situaciones en el futuro en las que fuera necesario cambiar la liquidez a un nuevo contrato: descubrimiento de vulnerabilidades, actualizaciones del protocolo, cambios en el colateral aceptado, etc. Para cubrir estas eventualidades, se diseñaron procedimientos que permitían mover el colateral a un nuevo pool (migración) o bien retirarlo manualmente (eliminación). Ambos procedimientos son evidentemente críticos desde la perspectiva de la seguridad de los fondos y por tanto están protegidos con los procedimientos de seguridad más complejos de todo el protocolo. Los procesos son ligeramente distintos para cada uno:

Migración

El procedimiento de migración requiere tres pasos:

  1. Solicitar en el contrato del oráculo el cambio de dirección del pool con la función requestAddressChange(), lo que inicia un bloqueo temporal de 7 días.

  2. Solicitar en el contrato del pool el inicio del procedimiento de migración con la función requestMigration(). Esto inicia un bloqueo temporal de 30 días. Adicionalmente, se tienen que cumplir varios requisitos para poder ejecutar la función:

    • No puede haber otra migración o eliminación de pool solicitada, ni del pool objetivo ni de otro pool de la red.

    • La dirección del oráculo Geminon no puede ser nula, tiene que haberse conectado el pool al oráculo del protocolo.

    • Tienen que haber transcurrido al menos 30 días desde que se conectó el pool al oráculo.

    • En el oráculo tiene que figurar registrada la solicitud de migración del pool desde 7 días antes.

    • El peso objetivo del pool tiene que estar fijado por debajo del 5%.

    • El peso actual del colateral del pool en la red tiene que ser menor al 5%.

    • La acuñación de tokens GEX en el pool queda en pausa y no se puede reanudar si no se cancela la solicitud de eliminación.

  3. Realizar la migración del pool usando la función migratePool(). Esta función realiza varias comprobaciones adicionales:

    • La migración del pool tiene que figurar solicitada en el pool desde hace al menos 30 días.

    • La migración del pool debe figurar solicitada el contrato del oráculo.

    • La dirección del oráculo Geminon no puede ser nula, tiene que haberse conectado el pool al oráculo del protocolo.

    • Tienen que haber transcurrido al menos 60 días desde que se conectó el pool al oráculo.

    • El peso objetivo del pool tiene que estar fijado por debajo del 2%.

    • El peso actual del colateral del pool en la red tiene que ser menor al 2%.

El procedimiento de migración transfiere automáticamente al nuevo pool todo el colateral y los tokens GEX que contiene el pool migrado. En este procedimiento los fondos son manejados internamente por los contratos del protocolo.

Eliminación

El procedimiento de eliminación requiere tres pasos, y es más restrictivo que el de migración en cuanto a los pesos máximos del colateral requeridos. El resto de requisitos son idénticos:

  1. Solicitar en el contrato del oráculo la eliminación de la dirección del pool con la función requestRemoveAddress(), lo que inicia un bloqueo temporal de 7 días.

  2. Solicitar en el contrato del pool el inicio del procedimiento de eliminación con la función requestRemove(). Esto inicia un bloqueo temporal de 30 días. Adicionalmente, se tienen que cumplir varios requisitos para poder ejecutar la función:

    • No puede haber otra migración o eliminación de pool solicitada, ni del pool objetivo ni de otro pool de la red.

    • La dirección del oráculo Geminon no puede ser nula, tiene que haberse conectado el pool al oráculo del protocolo.

    • Tienen que haber transcurrido al menos 30 días desde que se conectó el pool al oráculo.

    • En el oráculo tiene que figurar registrada la solicitud de migración del pool desde 7 días antes.

    • El peso objetivo del pool tiene que estar fijado por debajo del 5%.

    • El peso actual del colateral del pool en la red tiene que ser menor al 5%.

    • La acuñación de tokens GEX en el pool queda en pausa y no se puede reanudar si no se cancela la solicitud de eliminación.

  3. Realizar la eliminación del pool usando la función removePool(). Esta función realiza varias comprobaciones adicionales:

    • La migración del pool tiene que figurar solicitada en el pool desde hace al menos 30 días.

    • La migración del pool debe figurar solicitada el contrato del oráculo.

    • La dirección del oráculo Geminon no puede ser nula, tiene que haberse conectado el pool al oráculo del protocolo.

    • Tienen que haber transcurrido al menos 60 días desde que se conectó el pool al oráculo.

    • El peso objetivo del pool tiene que estar fijado por debajo del 1%.

    • El peso actual del colateral del pool en la red tiene que ser menor al 1%.

Al contrario que en la migración, el procedimiento de eliminación de un pool transfiere los fondos restantes del pool al propietario del contrato, que debe encargarse manualmente de convertirlos a otro tipo de colateral y reintegrarlos a otro pool del protocolo. Por este motivo se requiere que el pool contenga menos del 1% de todo el colateral del protocolo para permitir su eliminación. A pesar de todas las medidas de seguridad, este procedimiento requiere confianza y no debería llevarse a cabo salvo en circunstancias extremas.

Funciones del protocolo

Pausar / reanudar acuñación (pauseMint() / unpauseMint())

Estas funciones permiten pausar y reanudar la función de acuñación del token GEX en el pool. El canjeo de tokens no se puede pausar. Solo el propietario puede invocar estas funciones. La reanudación no puede llevarse a cabo si está solicitada la migración o eliminación del pool.

Hacer coincidir balances (matchBalances())

Permite hacer que los balances internos de token GEX y colateral del pool coincidan con el balance de los respectivos tokens en la dirección del contrato del pool. Esta función se utiliza para recuperar tokens enviados por error directamente al contrato. Solo el propietario puede usar la función. Como medida de seguridad adicional para evitar variaciones bruscas de precios, la función requiere que la diferencia entre el balance interno del pool y la cantidad real de tokens que contiene la dirección sea inferior al 1%.

Rescate del acuñador de moneda estable (bailoutMinter())

Esta función permite al contrato del acuñador recibir tokens GEX del pool en caso de que no tenga liquidez suficiente para canjear moneda estable de los usuarios. Dado que reduce el balance de tokens GEX del pool, tiene como efecto una subida del precio del token. La función puede llamarla manualmente el propietario del contrato, o puede ser invocada automáticamente por el contrato del acuñador. Para que la transacción no revierta, deben cumplirse varias condiciones:

  • El contrato del acuñador tiene que estar dado de alta en el pool que recibe la solicitud.

  • El oráculo Geminon tiene que estar dado de alta en el pool desde hace más de 30 días.

  • El contrato del acuñador tiene que estar dado de alta en el oráculo Geminon desde hace más de 7 días.

  • El contrato del acuñador tiene que tener menos de un 5% de los tokens GEX que hay en el balance del pool.

  • La cantidad máxima que puede ceder el pool es el 5% de su balance de tokens GEX.

Préstamo de colateral (lendCollateral())

Esta función permite al contrato de préstamos utilizar una parte del colateral de un pool para entregar un préstamo sobrecolateralizado. El colateral del préstamo debe ser un colateral válido de los GLP de la red, de forma que incluso en caso de liquidación del prestatario el colateral pueda ser reintegrado al pool. La función sola la puede invocar el contrato de préstamos, y requiere muchas condiciones:

  • El contrato de préstamos tiene que estar dado de alta en el pool que recibe la solicitud.

  • El oráculo Geminon tiene que estar dado de alta en el pool desde hace más de 30 días.

  • El contrato de préstamos tiene que estar dado de alta en el oráculo Geminon desde hace más de 7 días.

  • El contrato del acuñador tiene que estar dado de alta en el pool que recibe la solicitud.

  • No puede haberse solicitado la migración o eliminación del pool.

  • El valor total acumulado de los préstamos del pool no puede ser mayor al 5% del valor total de los tokens GEX bloqueados en contratos del protocolo.

  • La cantidad máxima que puede ceder el pool es el 25% de su balance de colateral.

El requerimiento más restrictivo es el del 5% del valor de los tokens GEX bloqueados en otros contratos, usualmente en la acuñación de moneda estable. Este requerimiento será el que limite habitualmente el uso de capital de los pools para préstamos.

Última actualización