Contratos de Intercambio Descentralizado en Ergo

This page is machine-translated.
Denys Zadorozhnyi

31 de julio de 2020

Ergo tiene contratos inteligentes expresivos y un modelo transaccional que permite la implementación de un protocolo DEX sin confianza, en el que las órdenes de compra y venta firmadas pueden ser introducidas en la blockchain de forma independiente por compradores y vendedores. Un servicio de emparejamiento fuera de la cadena puede observar la blockchain de Ergo, encontrar órdenes coincidentes y enviar la transacción de intercambio sin conocer ningún secreto. El emparejamiento puede ser incentivado por una recompensa DEX pagada como parte de una transacción de intercambio. Cualquiera que descubra primero el emparejamiento de las dos órdenes puede crear la transacción de intercambio y obtener una recompensa en ERGs. Se admite el emparejamiento parcial, lo que significa que la orden objetivo (compra/venta) puede ejecutarse parcialmente, en cuyo caso se debe crear una nueva orden "residual" (caja) en la misma transacción de intercambio. Cualquier orden puede ser cancelada en cualquier momento por el "propietario".

Contrato de orden de venta fuente.

Contrato de orden de compra fuente.

Emparejamiento parcial

Ambos contratos tienen parámetros de precio de token y tarifa DEX codificados en una compilación. Esto nos permite verificar los activos de la orden "residual", ERGs para una orden de compra y tokens para una orden de venta.

En el contrato de orden de compra, buscamos una caja residual, verificando que tiene los parámetros y activos correctos.

// en caso de emparejamiento parcial, se debe crear una nueva caja de orden de compra con fondos que no están emparejados en esta transacción
val foundResidualOrderBoxes = OUTPUTS.filter { (b: Box) => 
  val tokenIdParamIsCorrect = b.R4[Coll[Byte]].isDefined && b.R4[Coll[Byte]].get == tokenId 
  val tokenPriceParamIsCorrect = b.R5[Long].isDefined && b.R5[Long].get == tokenPrice
  val dexFeePerTokenParamIsCorrect = b.R6[Long].isDefined && b.R6[Long].get == dexFeePerToken
  val contractParamsAreCorrect = tokenIdParamIsCorrect && 
    tokenPriceParamIsCorrect && dexFeePerTokenParamIsCorrect
  val referenceMe = b.R7[Coll[Byte]].isDefined && b.R7[Coll[Byte]].get == SELF.id 
  val guardedByTheSameContract = b.propositionBytes == SELF.propositionBytes
  contractParamsAreCorrect && referenceMe && guardedByTheSameContract
}

fuente

Luego, verificamos que se cumplan las siguientes propiedades:

  • El valor (ERGs) de la caja de orden "residual" es el valor de la caja actual (orden) menos el valor en ERGs de los tokens que estamos recibiendo en esta transacción de intercambio y menos la tarifa DEX para esta transacción de intercambio.
  • Solo se crea una caja de orden "residual" en esta transacción de intercambio.
// ERGs pagados por los tokens comprados
val returnTokenValue = returnTokenAmount * tokenPrice
// rama para emparejamiento total (todos los ERGs se gastan y se compra la cantidad correcta de tokens)
val totalMatching = (SELF.value - expectedDexFee) == returnTokenValue && 
  returnBox.value >= fullSpread
// rama para emparejamiento parcial, por ejemplo, además de los tokens comprados, exigimos una nueva orden de compra con ERGs para 
// la parte no emparejada de esta orden
val partialMatching = {
  val correctResidualOrderBoxValue = (SELF.value - returnTokenValue - expectedDexFee)
  foundResidualOrderBoxes.size == 1 && 
    foundResidualOrderBoxes(0).value == correctResidualOrderBoxValue && 
    returnBox.value >= fullSpread
}

fuente

En el contrato de orden de venta, buscamos una caja residual, verificando que tiene los parámetros y activos correctos.

// en caso de emparejamiento parcial, se debe crear una nueva caja de orden de venta con tokens que no están emparejados en esta transacción
// verificar que solo se crea una caja de este tipo más adelante en el código
val foundResidualOrderBoxes = OUTPUTS.filter { (b: Box) => 
  val tokenIdParamIsCorrect = b.R4[Coll[Byte]].isDefined && b.R4[Coll[Byte]].get == tokenId 
  val tokenPriceParamIsCorrect = b.R5[Long].isDefined && b.R5[Long].get == tokenPrice
  val dexFeePerTokenParamIsCorrect = b.R6[Long].isDefined && b.R6[Long].get == dexFeePerToken
  val contractParamsAreCorrect = tokenIdParamIsCorrect && 
    tokenPriceParamIsCorrect && 
    dexFeePerTokenParamIsCorrect
  val referenceMe = b.R7[Coll[Byte]].isDefined && b.R7[Coll[Byte]].get == SELF.id 
  val guardedByTheSameContract = b.propositionBytes == SELF.propositionBytes
  contractParamsAreCorrect && referenceMe && guardedByTheSameContract
}

fuente

Luego, verificamos que se cumplan las siguientes propiedades:

  • La diferencia entre la cantidad de tokens en la caja actual (orden) y la caja de orden "residual" determina la cantidad de ERGs que el vendedor recibe por los tokens "vendidos" en esta transacción de intercambio (soldTokenAmount * tokenPrice).
  • El valor (ERGs) de la caja de orden "residual" es el valor de la caja actual (orden) menos la tarifa DEX para esta transacción de intercambio.
  • Solo se crea una caja de orden "residual" en esta transacción de intercambio.
// rama para emparejamiento parcial, por ejemplo, además de los ERGs recibidos, exigimos una nueva orden de venta con tokens para 
// la parte no emparejada de esta orden
val partialMatching = {
  foundResidualOrderBoxes.size == 1 && {
    val residualOrderBox = foundResidualOrderBoxes(0)
    val residualOrderTokenData = residualOrderBox.tokens(0)
    val residualOrderTokenAmount = residualOrderTokenData._2
    val soldTokenAmount = selfTokenAmount - residualOrderTokenAmount
    val soldTokenErgValue = soldTokenAmount * tokenPrice
    val expectedDexFee = dexFeePerToken * soldTokenAmount

    val residualOrderTokenId = residualOrderTokenData._1
    val tokenIdIsCorrect = residualOrderTokenId == tokenId

    val residualOrderValueIsCorrect = residualOrderBox.value == (SELF.value - expectedDexFee)
    val returnBoxValueIsCorrect = returnBox.value == soldTokenErgValue + fullSpread(soldTokenAmount)
    tokenIdIsCorrect && 
      soldTokenAmount >= 1 && 
      residualOrderValueIsCorrect && 
      returnBoxValueIsCorrect
  }
}

fuente

Emparejamiento total

Tanto las órdenes de venta como las de compra pueden ejecutarse en la transacción de intercambio en su totalidad. En este caso, no hay requisito para la caja de orden "residual".
Para este camino, verificamos que se cumplan las siguientes propiedades.
Para la orden de venta:

  • La cantidad de ERGs que el vendedor recibe en esta transacción de intercambio debe ser igual a la cantidad de tokens en la orden actual multiplicada por el precio del token.
    val totalMatching = (returnBox.value == selfTokenAmount * tokenPrice + fullSpread(selfTokenAmount))
    fuente

Para la orden de compra:

  • El valor del token (cantidad de token * precio del token, en ERGs) que el comprador recibe en esta transacción de intercambio debe ser igual al valor de la caja actual (orden) menos la tarifa DEX.
    val totalMatching = (SELF.value - expectedDexFee) == (returnTokenAmount * tokenPrice) && returnBox.value >= fullSpread
    fuente

Diferencial de oferta-demanda

Verificación de orden de contrapartida

El diferencial es la diferencia entre el precio de la orden de compra (oferta) y el precio de la orden de venta (demanda). Queremos asegurarnos de que si hay un diferencial, la orden "más antigua" lo obtenga.
Para este contrato, se requiere que las órdenes de contrapartida (órdenes de gasto) estén ordenadas por la cantidad de diferencial. De modo que las que tienen un mayor diferencial se "consuman" primero.
En el contrato de orden de compra:

// verificar si esta orden debe obtener el diferencial para una orden de contrapartida dada (altura)
val spreadIsMine = { (counterOrderBoxHeight: Int) => 
// mayor o igual ya que solo un mayor estricto da la victoria en el contrato de orden de venta
// Denys: tenemos que decidir quién obtiene el diferencial si la altura es igual, sin ninguna razón elegí la orden de compra
counterOrderBoxHeight >= SELF.creationInfo._1 
}

// verificar que las órdenes de contrapartida (venta) están ordenadas por diferencial en INPUTS
// para que el diferencial más grande (superior) se "consuma" primero
val sellOrderBoxesAreSortedBySpread = { (boxes: Coll[Box]) => 
boxes.size > 0 && {
  val alledgedlyTopSpread = if (spreadIsMine(boxes(0).creationInfo._1)) { 
    tokenPrice - boxes(0).R5[Long].getOrElse(0L)
  } else { 0L }
  boxes.fold((alledgedlyTopSpread, true), { (t: (Long, Boolean), box: Box) => 
    val prevSpread = t._1
    val isSorted = t._2
    val boxTokenPrice = box.R5[Long].getOrElse(0L)
    val boxTokenPriceIsCorrect = boxTokenPrice > 0 && boxTokenPrice <= tokenPrice
    val spread = if (spreadIsMine(box.creationInfo._1)) { 
      tokenPrice - boxTokenPrice 
    } else { 0L }
    (spread, isSorted && boxTokenPriceIsCorrect && spread <= prevSpread)
  })._2 
}
}

fuente

También verificamos que el precio de token declarado en el registro R5 de las órdenes de venta de contrapartida esté en el rango correcto para prevenir la explotación de desbordamientos aritméticos y otros ataques similares.

En el contrato de orden de venta:

// verificar si esta orden debe obtener el diferencial para una orden de contrapartida dada (altura)
val spreadIsMine = { (counterOrderBoxHeight: Int) => 
// estrictamente mayor ya que la igualdad da la victoria en el contrato de orden de compra
// Denys: tenemos que decidir quién obtiene el diferencial si la altura es igual, sin ninguna razón elegí la orden de compra
counterOrderBoxHeight > SELF.creationInfo._1 
}

// verificar que las órdenes de contrapartida (compra) están ordenadas por diferencial en INPUTS
// para que el diferencial más grande (superior) se "consuma" primero
val buyOrderBoxesAreSortedBySpread = { (boxes: Coll[Box]) => 
boxes.size > 0 && {
  val alledgedlyTopSpread = if (spreadIsMine(boxes(0).creationInfo._1)) { 
    boxes(0).R5[Long].getOrElse(0L) - tokenPrice 
  } else { 0L }
  boxes.fold((alledgedlyTopSpread, true), { (t: (Long, Boolean), box: Box) => 
    val prevSpread = t._1
    val isSorted = t._2
    val boxTokenPrice = box.R5[Long].getOrElse(0L)
    // aunque la tarifa DEX de la orden de compra no se utiliza aquí, verificamos si es positiva como parte de la verificación de cordura
    val boxDexFeePerToken = box.R6[Long].getOrElse(0L)
    val spread = if (spreadIsMine(box.creationInfo._1)) { boxTokenPrice - tokenPrice } else { 0L }
    (spread, isSorted && boxTokenPrice >= tokenPrice && boxDexFeePerToken > 0L && spread <= prevSpread)
  })._2 
}
}

fuente

También verificamos que el precio de token declarado en el registro R5, y la tarifa DEX por token en R6 de las órdenes de compra de contrapartida esté en el rango correcto.

Cálculo del diferencial

Para verificar que la orden actual obtenga su diferencial, primero necesitamos calcularlo. Con las órdenes de contrapartida ordenadas por la cantidad de diferencial, comenzamos a "consumirlas" en ese orden, disminuyendo el número de tokens restantes en este emparejamiento.
En el contrato de orden de compra:

// diferencial agregado que obtenemos de todas las órdenes de contrapartida (venta)
val fullSpread = {
  spendingSellOrders.fold((returnTokenAmount, 0L), { (t: (Long, Long), sellOrder: Box) => 
    val returnTokensLeft = t._1
    val accumulatedFullSpread = t._2
    val sellOrderTokenPrice = sellOrder.R5[Long].get
    val sellOrderTokenAmount = sellOrder.tokens(0)._2
    val tokenAmountFromThisOrder = min(returnTokensLeft, sellOrderTokenAmount)
    if (spreadIsMine(sellOrder.creationInfo._1)) {
      // el diferencial es nuestro
      val spreadPerToken = tokenPrice - sellOrderTokenPrice
      val sellOrderSpread = spreadPerToken * tokenAmountFromThisOrder
      (returnTokensLeft - tokenAmountFromThisOrder, accumulatedFullSpread + sellOrderSpread)
    }
    else {
      // el diferencial no es nuestro
      (returnTokensLeft - tokenAmountFromThisOrder, accumulatedFullSpread)
    }
  })._2
}

fuente

En el contrato de orden de venta, necesitamos depender tanto del precio del token como de la cantidad de tarifa DEX para calcular cuántos tokens hay en esa orden de compra. Además de eso, dado que no podemos deducir la cantidad de tokens "vendidos" en esta transacción de intercambio del valor de la caja de retorno, hacemos el cálculo del diferencial parametrizado con la cantidad concreta de tokens que conoceremos más adelante en el código:

// diferencial agregado que obtenemos de todas las órdenes de contrapartida (compra)
val fullSpread = { (tokenAmount: Long) =>
  spendingBuyOrders.fold((tokenAmount, 0L), { (t: (Long, Long), buyOrder: Box) => 
    val returnTokensLeft = t._1
    val accumulatedFullSpread = t._2
    val buyOrderTokenPrice = buyOrder.R5[Long].get
    val buyOrderDexFeePerToken = buyOrder.R6[Long].get
    val buyOrderTokenAmountCapacity = buyOrder.value / (buyOrderTokenPrice + buyOrderDexFeePerToken)
    val tokenAmountInThisOrder = min(returnTokensLeft, buyOrderTokenAmountCapacity)
    if (spreadIsMine(buyOrder.creationInfo._1)) {
      // el diferencial es nuestro
      val spreadPerToken = buyOrderTokenPrice - tokenPrice
      val buyOrderSpread = spreadPerToken * tokenAmountInThisOrder
      (returnTokensLeft - tokenAmountInThisOrder, accumulatedFullSpread + buyOrderSpread)
    }
    else {
      // el diferencial no es nuestro
      (returnTokensLeft - tokenAmountInThisOrder, accumulatedFullSpread)
    }
  })._2
}

fuente

Verificación del diferencial recibido

Con la cantidad de diferencial determinada, necesitamos verificar si la orden actual ha recibido efectivamente el diferencial.
En el contrato de orden de compra, verificamos que esté incluido en el valor de la caja de retorno:

// rama para emparejamiento total (todos los ERGs se gastan y se compra la cantidad correcta de tokens)
val totalMatching = (SELF.value - expectedDexFee) == returnTokenValue && 
  returnBox.value >= fullSpread
// rama para emparejamiento parcial, por ejemplo, además de los tokens comprados, exigimos una nueva orden de compra con ERGs para 
// la parte no emparejada de esta orden
val partialMatching = {
  val correctResidualOrderBoxValue = (SELF.value - returnTokenValue - expectedDexFee)
  foundResidualOrderBoxes.size == 1 && 
    foundResidualOrderBoxes(0).value == correctResidualOrderBoxValue && 
    returnBox.value >= fullSpread
}

fuente

En el contrato de orden de venta, tan pronto como sepamos la cantidad de tokens "vendidos" en esta transacción de intercambio, verificamos que el valor de la caja de retorno tenga incluido el diferencial.
En el caso de emparejamiento total, utilizamos la cantidad total de tokens en la orden actual:

// rama para emparejamiento total (todos los tokens se venden y se reciben la cantidad total de ERGs)
val totalMatching = (returnBox.value == selfTokenAmount * tokenPrice + fullSpread(selfTokenAmount))

fuente

En el caso de emparejamiento parcial, sabemos la cantidad de tokens "vendidos" de la orden residual (val soldTokenAmount = selfTokenAmount - residualOrderTokenAmount) y verificamos que el diferencial esté incluido en el valor de la caja de retorno:

val returnBoxValueIsCorrect = returnBox.value == soldTokenErgValue + fullSpread(soldTokenAmount)

fuente

Share post

Ergo Infrastructure DAO: Descentralizando la columna vertebral del ecosistema Ergo

Ergo Infrastructure DAO: Descentralizando la columna vertebral del ecosistema Ergo

La misión de Ergo siempre ha estado arraigada en la descentralización, no solo en la capa de consenso, sino en toda la pila.

Ergo Platform

13 de agosto de 2025

Mew Finance: Un Kit de Herramientas DeFi Divertido para el Ecosistema Ergo

Mew Finance: Un Kit de Herramientas DeFi Divertido para el Ecosistema Ergo

Mew Finance es un conjunto de aplicaciones descentralizadas en la Blockchain de Ergo.

Ergo Platform

12 de agosto de 2025

Lithos: Descentralizando la Minería con Pools On-Chain

Lithos: Descentralizando la Minería con Pools On-Chain

Lithos es un nuevo protocolo diseñado para reformar cómo funcionan los pools de minería al trasladarlos a la cadena, dando a los m.

Ergo Platform

24 de julio de 2025

Sigma 6.0: Un Ergo Más Inteligente y Flexible

Sigma 6.0: Un Ergo Más Inteligente y Flexible

Sigma 6.0 es una importante actualización propuesta para la blockchain de Ergo.

Ergo Platform

23 de julio de 2025

Dando forma al futuro de Rosen: Una llamada comunitaria sobre cinco propuestas clave del Tesoro

Dando forma al futuro de Rosen: Una llamada comunitaria sobre cinco propuestas clave del Tesoro

El cofundador de Rosen, Armeanio, ha presentado cinco nuevas propuestas al Tesoro de Rosen.

Ergo Platform

9 de julio de 2025

El UTXO Ampliado de Ergo y el Auge de la Inteligencia Económica Artificial

El UTXO Ampliado de Ergo y el Auge de la Inteligencia Económica Artificial

Una Visión Práctica para Agentes Económicos Autónomos Los agentes económicos autónomos en la blockchain de Ergo realizan trabajos.

Ergo Platform

12 de mayo de 2025

ErgoHACK X: Inteligencia Artificial en la Blockchain de Ergo

ErgoHACK X: Inteligencia Artificial en la Blockchain de Ergo

Celebrando una Década de Innovación Descentralizada ¡Únete al décimo aniversario de ErgoHACK y sé parte de la revolución de la IA .

Ergo Platform

10 de abril de 2025

Introduccion a Privacidad y Seguridad en la Blockchain

Introduccion a Privacidad y Seguridad en la Blockchain

Luego del primer whitepaper que apareció en Internet en el 2008, la tecnología blockchain evoluciono enormemente.

Ergo Platform

17 de febrero de 2022

Método híbrido de calcular costes de Ergo

Método híbrido de calcular costes de Ergo

Introducción Verificar la validez de los contratos inteligentes en una blockchain de Prueba de trabajo (PoW) tiene costos, tanto.

Ergo Platform (Translated by Darkkknight, original version will always prevail)

9 de febrero de 2022

Ergo: una respuesta a los fallos de la teoría monetaria moderna

Ergo: una respuesta a los fallos de la teoría monetaria moderna

En 2008, un grupo o persona desconocida lanzó un depósito de valor peer-to-peer y lo llamó Bitcoin.

Ergo Platform (Translated by Comet Community, original version will always prevail)

8 de febrero de 2022

Summit de Ergo : Evento para la privacidad

Summit de Ergo : Evento para la privacidad

Únase a nosotros del 17 al 23 de febrero de 2022 para este evento.

Ergo Foundation (translated by Daniu, original version will always prevail)

5 de febrero de 2022

Finanza descentralizada y privacidad opcional en Ergo

Finanza descentralizada y privacidad opcional en Ergo

Privacidad financial y blockchains públicas Bitcoin es una red de contabilidad distribuida pública a la que pueden acceder todos.

Ergo Platform (translated by Daniu, original version will always prevail)

1 de febrero de 2022

Alquiler por almacenamiento y el futuro de la minería

Alquiler por almacenamiento y el futuro de la minería

Terminología Storage Rent: Alquiler por almacenamiento (se entenderá más adelante) Introducción Los mineros son la capa de con.

Ergo Platform (translated by Daniu, original version will always prevail)

27 de enero de 2022

ErgoHack III: Construyendo la privacidad y seguridad del mañana

ErgoHack III: Construyendo la privacidad y seguridad del mañana

Ergo es una plataforma PoW de contratos inteligentes de código abierto basada en principios económicos de base.

Ergo Foundation (translated by Daniu, original version will always prevail)

20 de enero de 2022

Ergo & Blockchain: Escalabilidad y adopción

Ergo & Blockchain: Escalabilidad y adopción

En este episodio de la serie Ergo & Blockchain, veremos varios aspectos de escalabilidad y por qué son cruciales para la adopció.

Ergo Platform (translated by Daniu, original version will always prevail)

18 de enero de 2022

ErgoHack III Información para registrarse

ErgoHack III Información para registrarse

ErgoHack III tendrá lugar en Febrero 11-13, 2022 Registros abiertos hasta el 31 de Enero, 2022 Con el registro ya abierto, exi.

Ergo Foundation (translated by Daniu, original version will always prevail)

6 de enero de 2022

Ergo Rewards de minería: primera reducción de la emisión

Ergo Rewards de minería: primera reducción de la emisión

Las recompensas de la minería Ergo experimentaron su primera caída en el calendario de emisiones el 2 de enero de 2022 con el bl.

Ergo Platform (translated by Daniu, original version will always prevail)

4 de enero de 2022

¡Hola! soy nuevo, ¿por qué es Ergo un buen proyecto?

¡Hola! soy nuevo, ¿por qué es Ergo un buen proyecto?

¿Qué encontrarás en este artículo? Son numerosas las veces que un nuevo ergonauta en potencia entra a uno de los grupos en españo.

Daniu

1 de enero de 2022

Ergo Platform 2021: Resumen de este año

Ergo Platform 2021: Resumen de este año

A medida que el mundo intenta recuperarse de los efectos de Covid y las diferentes etapas de las restricciones de bloqueo, las c.

Ergo Platform (translated by Daniu, original version will always prevail)

30 de diciembre de 2021

Ergo y Blockchain: Tecnología e Innovación

Ergo y Blockchain: Tecnología e Innovación

La idea inicial detrás de Bitcoin se basó en la promesa de un comercio protegido de puntos centralizados de falla.

Ergo Platform (translated by Daniu, original version will always prevail)

28 de diciembre de 2021

Minería en Ergo: Herramientas de descentralización

Minería en Ergo: Herramientas de descentralización

Ergo es una cadena de bloques PoW (Prueba de trabajo) en el modelo de consenso llamado Autolykos.

Ergo Platform (translated by Daniu, original version will always prevail)

23 de diciembre de 2021