Decentralizált Tőzsdei Szerződések az Ergo-n

This page is machine-translated.
Denys Zadorozhnyi

2020. július 31.

Az Ergo kifejező okos szerződésekkel és tranzakciós modellel rendelkezik, amely lehetővé teszi a bizalom nélküli DEX protokoll megvalósítását, amelyben az aláírt vételi és eladási megbízásokat függetlenül helyezhetik el a blokkláncon a vásárlók és az eladók. Egy off-chain egyeztető szolgáltatás figyelheti az Ergo blokkláncot, megtalálhatja a megfelelő megbízásokat, és benyújthatja a csere tranzakciót anélkül, hogy bármilyen titkot ismerne. Az egyeztetést DEX jutalommal lehet ösztönözni, amelyet a csere tranzakció részeként fizetnek. Bárki, aki először felfedezi a két megbízás egyezését, létrehozhatja a csere tranzakciót, és jutalmat kaphat ERG-ben. A részleges egyeztetés támogatott, ami azt jelenti, hogy a cél (vételi/eladási) megbízás részben végrehajtható, ilyenkor egy új "maradvány" megbízást (doboz) kell létrehozni ugyanabban a csere tranzakcióban. Bármely megbízás bármikor törölhető az "tulajdonos" által.

Eladási megbízás szerződés forrás.

Vételi megbízás szerződés forrás.

Részleges egyeztetés

Mindkét szerződés tartalmazza a token árát és a DEX díj paramétereit, amelyek a fordítás során kódolva vannak. Ez lehetővé teszi számunkra, hogy ellenőrizzük a "maradvány" megbízás eszközeit, ERG-t egy vételi megbízás esetén, és tokeneket egy eladási megbízás esetén.

A vételi megbízás szerződésben keresünk egy maradvány dobozt, ellenőrizve, hogy helyes paraméterekkel és eszközökkel rendelkezik.

// részleges egyeztetés esetén új vételi megbízás dobozt kell létrehozni a tranzakcióban nem egyeztetett alapokkal
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
}

forrás

Ezután ellenőrizzük, hogy a következő tulajdonságok érvényesek-e:

  • A "maradvány" megbízás dobozának értéke (ERG) a jelenlegi doboz (megbízás) értéke mínusz az ERG értéke a tokenekért, amelyeket ebben a csere tranzakcióban kapunk, és mínusz a DEX díj a csere tranzakcióhoz.
  • Csak egy "maradvány" megbízás doboz jön létre ebben a csere tranzakcióban.
// ERG, amelyet a vásárolt tokenekért fizettek
val returnTokenValue = returnTokenAmount * tokenPrice
// ág a teljes egyeztetéshez (minden ERG elköltve és a helyes mennyiségű token megvásárolva)
val totalMatching = (SELF.value - expectedDexFee) == returnTokenValue && 
  returnBox.value >= fullSpread
// ág a részleges egyeztetéshez, pl. a vásárolt tokenek mellett új vételi megbízást követelünk ERG-ért a 
// megbízás nem egyeztetett részéért
val partialMatching = {
  val correctResidualOrderBoxValue = (SELF.value - returnTokenValue - expectedDexFee)
  foundResidualOrderBoxes.size == 1 && 
    foundResidualOrderBoxes(0).value == correctResidualOrderBoxValue && 
    returnBox.value >= fullSpread
}

forrás

Az eladási megbízás szerződésben keresünk egy maradvány dobozt, ellenőrizve, hogy helyes paraméterekkel és eszközökkel rendelkezik.

// részleges egyeztetés esetén új eladási megbízás dobozt kell létrehozni a tranzakcióban nem egyeztetett tokenekkel
// ellenőrizni kell, hogy csak egy ilyen doboz készült-e később a kódban
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
}

forrás

Ezután ellenőrizzük, hogy a következő tulajdonságok érvényesek-e:

  • A különbség a jelenlegi doboz (megbízás) token mennyisége és a "maradvány" megbízás doboz között meghatározza az ERG mennyiségét, amelyet az eladó kap a tokenek "eladásáért" ebben a csere tranzakcióban (soldTokenAmount * tokenPrice).
  • A "maradvány" megbízás dobozának értéke (ERG) a jelenlegi doboz (megbízás) értéke mínusz a DEX díj a csere tranzakcióhoz.
  • Csak egy "maradvány" megbízás doboz jön létre ebben a csere tranzakcióban.
// ág a részleges egyeztetéshez, pl. a kapott ERG mellett új eladási megbízást követelünk tokenekért a 
// megbízás nem egyeztetett részéért
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
  }
}

forrás

Teljes egyeztetés

Mind az eladási, mind a vételi megbízások teljes mértékben végrehajthatók a csere tranzakcióban. Ebben az esetben nincs szükség a "maradvány" megbízás dobozra.
Ehhez az úthoz ellenőrizzük, hogy a következő tulajdonságok érvényesek-e.
Eladási megbízás esetén:

  • Az ERG mennyiség, amelyet az eladó kap ebben a csere tranzakcióban, meg kell, hogy egyezzen a jelenlegi megbízásban lévő tokenek mennyiségével, szorozva a token árával.
    val totalMatching = (returnBox.value == selfTokenAmount * tokenPrice + fullSpread(selfTokenAmount))
    forrás

Vételi megbízás esetén:

  • A token értéke (token mennyiség * token ár, ERG-ben), amelyet a vásárló kap ebben a csere tranzakcióban, meg kell, hogy egyezzen a jelenlegi doboz (megbízás) értékével mínusz a DEX díj.
    val totalMatching = (SELF.value - expectedDexFee) == (returnTokenAmount * tokenPrice) && returnBox.value >= fullSpread
    forrás

Kereslet-Kínálat különbség

Ellenkező megbízások rendezési ellenőrzése

A különbség a vételi (ajánlati) megbízás ára és az eladási (kínálati) megbízás ára között. Biztosítani szeretnénk, hogy ha van különbség, az "idősebb" megbízás kapja meg azt.
Ehhez a szerződés megköveteli, hogy az ellenkező megbízások (kiadási megbízások) a különbség mértéke szerint legyenek rendezve. Így azok, amelyek nagyobb különbséggel rendelkeznek, "fogyasztódnak" először.
A vételi megbízás szerződésében:

// ellenőrizni, hogy ez a megbízás megkapja-e a különbséget egy adott ellenkező megbízás (magasság) esetén
val spreadIsMine = { (counterOrderBoxHeight: Int) => 
// nagyobb vagy egyenlő, mivel csak a szigorúan nagyobb ad győzelmet az eladási megbízás szerződésben
// Denys: el kell döntenünk, ki kapja a különbséget, ha a magasság egyenlő, ok nélkül a vételi megbízást választottam
counterOrderBoxHeight >= SELF.creationInfo._1 
}

// ellenőrizni, hogy az ellenkező (eladási) megbízások a különbség szerint rendezettek az INPUTS-ben
// így a nagyobb (felső) különbség "fogyasztódik" először
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 
}
}

forrás

Ellenőrizzük azt is, hogy a deklarált token ár a R5 regiszterben az ellenkező eladási megbízások esetén a helyes tartományban van, hogy megakadályozzuk a matematikai túlcsordulás és más hasonló támadások kihasználását.

Az eladási megbízás szerződésében:

// ellenőrizni, hogy ez a megbízás megkapja-e a különbséget egy adott ellenkező megbízás (magasság) esetén
val spreadIsMine = { (counterOrderBoxHeight: Int) => 
// szigorúan nagyobb, mivel az egyenlőség győzelmet ad a vételi megbízás szerződésben
// Denys: el kell döntenünk, ki kapja a különbséget, ha a magasság egyenlő, ok nélkül a vételi megbízást választottam
counterOrderBoxHeight > SELF.creationInfo._1 
}

// ellenőrizni, hogy az ellenkező (vételi) megbízások a különbség szerint rendezettek az INPUTS-ben
// így a nagyobb (felső) különbség "fogyasztódik" először
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)
    // bár a vételi megbízás DEX díját itt nem használják, ellenőrizzük, hogy pozitív-e, mint a szanálási ellenőrzés része
    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 
}
}

forrás

Ellenőrizzük a deklarált token árat a R5 regiszterben, és a DEX díjat tokenenként az R6 regiszterben az ellenkező vételi megbízások esetén, hogy a helyes tartományban legyenek.

Különbség kiszámítása

Azt, hogy a jelenlegi megbízás megkapja a különbségét, először ki kell számítanunk. Az ellenkező megbízások rendezésével a különbség mértéke szerint kezdjük "fogyasztani" őket abban a sorrendben, csökkentve a megbízásban maradt tokenek számát.
A vételi megbízás szerződésében:

// az összes ellenkező (eladási) megbízásból származó összesített különbség
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)) {
      // a különbség a miénk
      val spreadPerToken = tokenPrice - sellOrderTokenPrice
      val sellOrderSpread = spreadPerToken * tokenAmountFromThisOrder
      (returnTokensLeft - tokenAmountFromThisOrder, accumulatedFullSpread + sellOrderSpread)
    }
    else {
      // a különbség nem a miénk
      (returnTokensLeft - tokenAmountFromThisOrder, accumulatedFullSpread)
    }
  })._2
}

forrás

Az eladási megbízás szerződésében támaszkodnunk kell mind a token árra, mind a DEX díj összegére, hogy kiszámítsuk, hány token van abban a vételi megbízásban. Ezen kívül, mivel nem tudjuk levonni a csere tranzakcióban "eladott" token mennyiséget a visszatérő doboz értékéből, a különbség kiszámítását parametrizáljuk a konkrét token mennyiséggel, amelyet később tudni fogunk a kódban:

// az összesített különbség, amelyet az összes ellenkező (vételi) megbízásból kapunk
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)) {
      // a különbség a miénk
      val spreadPerToken = buyOrderTokenPrice - tokenPrice
      val buyOrderSpread = spreadPerToken * tokenAmountInThisOrder
      (returnTokensLeft - tokenAmountInThisOrder, accumulatedFullSpread + buyOrderSpread)
    }
    else {
      // a különbség nem a miénk
      (returnTokensLeft - tokenAmountInThisOrder, accumulatedFullSpread)
    }
  })._2
}

forrás

Kaptuk-e a különbséget

A különbség mértékének meghatározásával ellenőriznünk kell, hogy a jelenlegi megbízás valóban megkapta-e a különbséget.
A vételi megbízás szerződésében ellenőrizzük, hogy ez benne van a visszatérő doboz értékében:

// ág a teljes egyeztetéshez (minden ERG elköltve és a helyes mennyiségű token megvásárolva)
val totalMatching = (SELF.value - expectedDexFee) == returnTokenValue && 
  returnBox.value >= fullSpread
// ág a részleges egyeztetéshez, pl. a vásárolt tokenek mellett új vételi megbízást követelünk ERG-ért a 
// megbízás nem egyeztetett részéért
val partialMatching = {
  val correctResidualOrderBoxValue = (SELF.value - returnTokenValue - expectedDexFee)
  foundResidualOrderBoxes.size == 1 && 
    foundResidualOrderBoxes(0).value == correctResidualOrderBoxValue && 
    returnBox.value >= fullSpread
}

forrás

Az eladási megbízás szerződésében, amint tudjuk a token mennyiséget, amely "eladásra került" ebben a csere tranzakcióban, ellenőrizzük, hogy a visszatérő doboz értéke tartalmazza-e a különbséget.
Teljes egyeztetés esetén a jelenlegi megbízásban lévő teljes token mennyiséget használjuk:

// ág a teljes egyeztetéshez (minden token eladva és teljes mennyiségű ERG-t kapva)
val totalMatching = (returnBox.value == selfTokenAmount * tokenPrice + fullSpread(selfTokenAmount))

forrás

Részleges egyeztetés esetén tudjuk a "eladott" token mennyiségét a maradvány megbízásból (val soldTokenAmount = selfTokenAmount - residualOrderTokenAmount), és ellenőrizzük, hogy a különbség benne van a visszatérő doboz értékében:

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

forrás

Share post

Ergo Infrastructure DAO: Az Ergo Ökoszisztéma Gerincének Decentralizálása

Ergo Infrastructure DAO: Az Ergo Ökoszisztéma Gerincének Decentralizálása

Az Ergo küldetése mindig is a decentralizáción alapult, nemcsak a konszenzus rétegén, hanem az egész stack-en.

Ergo Platform

2025. augusztus 13.

Mew Finance: Egy Játékos DeFi Eszközkészlet az Ergo Ökoszisztémához

Mew Finance: Egy Játékos DeFi Eszközkészlet az Ergo Ökoszisztémához

A Mew Finance egy decentralizált alkalmazáscsomag az Ergo Blockchain-en.

Ergo Platform

2025. augusztus 12.

Lithos: A Bányászat Decentralizálása On-Chain Poolokkal

Lithos: A Bányászat Decentralizálása On-Chain Poolokkal

A Lithos egy új protokoll, amely a bányászati poolok működésének átalakítására készült azáltal, hogy azokat on-chain helyezi, telj.

Ergo Platform

2025. július 24.

Sigma 6.0: Egy Okosabb, Rugalmasabb Ergo

Sigma 6.0: Egy Okosabb, Rugalmasabb Ergo

Sigma 6.0 egy jelentős javasolt frissítés az Ergo blokklánc számára.

Ergo Platform

2025. július 23.

Rosen Jövőjének Formálása: Közösségi Felhívás Öt Kulcsfontosságú Kincstári Javaslatra

Rosen Jövőjének Formálása: Közösségi Felhívás Öt Kulcsfontosságú Kincstári Javaslatra

A Rosen társalapítója, Armeanio, öt új javaslatot nyújtott be a Rosen Kincstárhoz.

Ergo Platform

2025. július 9.

Ergo kibővített UTXO-ja és a mesterséges gazdasági intelligencia felemelkedése

Ergo kibővített UTXO-ja és a mesterséges gazdasági intelligencia felemelkedése

Gyakorlati vízió az autonóm gazdasági ügynökök számára Az autonóm gazdasági ügynökök az Ergo blokkláncon hasznos munkát végeznek .

Ergo Platform

2025. május 12.

ErgoHACK X: Mesterséges Intelligencia az Ergo Blockchain-en

ErgoHACK X: Mesterséges Intelligencia az Ergo Blockchain-en

Ünnepeljük a Decentralizált Innováció Egy Évtizedét Csatlakozz a 10.

Ergo Platform

2025. április 10.