From 7ea6c5dce77993ab996acdcefeff1e4f22a16ada Mon Sep 17 00:00:00 2001 From: Luca D'Angelo Date: Sat, 23 Dec 2023 18:48:02 -0500 Subject: [PATCH 1/2] Apply equation changes and some comments. --- .../BoxGuardScripts/GluonWBoxGuardScript.es | 43 ++++++++----------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/modules/gluonw-base/src/main/resources/ErgoContracts/GluonW/Ergs/BoxGuardScripts/GluonWBoxGuardScript.es b/modules/gluonw-base/src/main/resources/ErgoContracts/GluonW/Ergs/BoxGuardScripts/GluonWBoxGuardScript.es index 8e4ddc4..2b498cd 100644 --- a/modules/gluonw-base/src/main/resources/ErgoContracts/GluonW/Ergs/BoxGuardScripts/GluonWBoxGuardScript.es +++ b/modules/gluonw-base/src/main/resources/ErgoContracts/GluonW/Ergs/BoxGuardScripts/GluonWBoxGuardScript.es @@ -183,6 +183,8 @@ val _fissionedErg: Long = IN_GLUONW_BOX.value - _MinFee val RErg: BigInt = _fissionedErg.toBigInt // Price of Gold + // Gold Oracle data input value has units of: nanoErg / kg + // We want units of: nanoErg / g val Pt: BigInt = CONTEXT.dataInputs(0).R4[Long].get.toBigInt / 1000 // We're using 1,000,000,000 because the precision is based on nanoErgs @@ -447,10 +449,8 @@ val ProtonsActualValue: BigInt = (OUT_GLUONW_PROTONS_TOKEN._2 - IN_GLUONW_PROTONS_TOKEN._2).toBigInt val ErgsActualValue: BigInt = (IN_GLUONW_BOX.value - OUT_GLUONW_BOX.value).toBigInt - // M(1 - phiFusion) = Ergs - // therefore, M = Ergs / (1 - phiFusion) - val M: BigInt = ErgsActualValue * (precision / (precision - PhiFusion)) - + // M = Ergs + val M: BigInt = ErgsActualValue val inProtonsNumerator: BigInt = M * SProtons * precision val inNeutronsNumerator: BigInt = M * SNeutrons * precision @@ -459,7 +459,7 @@ val NeutronsExpectedValue: BigInt = inNeutronsNumerator / denominator val ProtonsExpectedValue: BigInt = inProtonsNumerator / denominator // This will make the outErgsValueValid condition tautological. We could take this and the condition off, but we will keep it for the sake of completeness. - val ErgsExpectedValue: BigInt = ErgsActualValue + val ErgsExpectedValue: BigInt = M // ### The 2 conditions to ensure that the values out is right ### // val __inNeutronsValueValid: Boolean = NeutronsActualValue == NeutronsExpectedValue @@ -598,7 +598,7 @@ val Phi0 = precision / 100 val Phi1 = precision / 2 - val VarPhiBeta: BigInt = Phi0 + Phi1 * volume / RErg + val VarPhiBeta: BigInt = Phi0 + ((Phi1 * volume) / RErg) // Due to some issues with moving towards the next block. We should give it a margin of error of +-3 blocks // There is a tricky situation where if the lastblock is within a day, and if it is always updated, @@ -614,17 +614,14 @@ // ** Fusion Ratio ** // min(q*, (SNeutrons * Pt / R)) // where q* is a constant, Pt is the price of gold in Ergs. - val oneMinusPhiBeta: BigInt = precision - VarPhiBeta - val oneMinusFusionRatio: BigInt = precision - fusionRatio - val minusesMultiplied: BigInt = - oneMinusPhiBeta * oneMinusFusionRatio / precision - val outNeutronsAmount: BigInt = - (((M * minusesMultiplied) / fusionRatio) * SNeutrons) / SProtons - - val outProtonsAmount: BigInt = M.toBigInt + val oneMinusPhiBeta: BigInt = (precision - VarPhiBeta) + val oneMinusFusionRatio: BigInt = (precision - fusionRatio) + val numerator: BigInt = M * oneMinusPhiBeta * oneMinusFusionRatio * SNeutrons + val denominator: BigInt = fusionRatio * SProtons + val outNeutronsAmount: BigInt = (numerator / denominator) / (precision * precision) val NeutronsExpectedValue: BigInt = outNeutronsAmount - val ProtonsExpectedValue: BigInt = outProtonsAmount + val ProtonsExpectedValue: BigInt = M val ErgsExpectedValue: BigInt = (IN_GLUONW_BOX.value).toBigInt // ### The 2 conditions to ensure that the values out is right ### // @@ -642,12 +639,10 @@ __outVolumePlusValidated, __lastBlockPreserved ))) - } - else if (isBetaDecayMinusTx) - { + } else if (isBetaDecayMinusTx) { // ===== BetaDecayMinus Tx ===== // //Equation: M [Neutrons] = M * (1 - PhiBeta(T)) * ((q(R, S neutron)) / 1 - q(R, S neutron)) * (S protons / S neutrons) [Protons] - val M: Long = (OUT_GLUONW_NEUTRONS_TOKEN._2 - IN_GLUONW_NEUTRONS_TOKEN._2) + val M: BigInt = (OUT_GLUONW_NEUTRONS_TOKEN._2 - IN_GLUONW_NEUTRONS_TOKEN._2).toBigInt // ** VarPhiBeta Calculation ** val currentBlockNumber: Long = CONTEXT.HEIGHT @@ -760,13 +755,11 @@ // where q* is a constant, Pt is the price of gold in Ergs. val oneMinusPhiBeta: BigInt = precision - VarPhiBeta val oneMinusFusionRatio: BigInt = precision - fusionRatio - val neutronsToDecayMultiplyOneMinusPhiBeta: BigInt = - M.toBigInt * oneMinusPhiBeta / precision - val outProtonsAmount: BigInt = - ((neutronsToDecayMultiplyOneMinusPhiBeta * SProtons / SNeutrons) * fusionRatio) / oneMinusFusionRatio - val outNeutronsAmount: BigInt = M.toBigInt + val numerator: BigInt = M * oneMinusPhiBeta * fusionRatio * SProtons + val denominator: BigInt = oneMinusFusionRatio * SNeutrons + val outProtonsAmount: BigInt = numerator / denominator - val NeutronsExpectedValue: BigInt = outNeutronsAmount + val NeutronsExpectedValue: BigInt = M val ProtonsExpectedValue: BigInt = outProtonsAmount val ErgsExpectedValue: BigInt = (IN_GLUONW_BOX.value).toBigInt From 3667282165b6c32bd4adfb0bce3f3c8e3f4ed38b Mon Sep 17 00:00:00 2001 From: Luca D'Angelo Date: Mon, 1 Jan 2024 19:54:17 -0500 Subject: [PATCH 2/2] Apply equation changes and some comments. --- .../BoxGuardScripts/GluonWBoxGuardScript.es | 20 ++++++++++--------- .../scala/gluonw/common/GluonWAlgorithm.scala | 16 +++++++-------- .../test/scala/gluonw/common/GluonWBase.scala | 4 ++-- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/modules/gluonw-base/src/main/resources/ErgoContracts/GluonW/Ergs/BoxGuardScripts/GluonWBoxGuardScript.es b/modules/gluonw-base/src/main/resources/ErgoContracts/GluonW/Ergs/BoxGuardScripts/GluonWBoxGuardScript.es index 2b498cd..a739468 100644 --- a/modules/gluonw-base/src/main/resources/ErgoContracts/GluonW/Ergs/BoxGuardScripts/GluonWBoxGuardScript.es +++ b/modules/gluonw-base/src/main/resources/ErgoContracts/GluonW/Ergs/BoxGuardScripts/GluonWBoxGuardScript.es @@ -614,14 +614,15 @@ // ** Fusion Ratio ** // min(q*, (SNeutrons * Pt / R)) // where q* is a constant, Pt is the price of gold in Ergs. + // The steps of multiplication and division done below are to avoid overflow errors. val oneMinusPhiBeta: BigInt = (precision - VarPhiBeta) val oneMinusFusionRatio: BigInt = (precision - fusionRatio) - val numerator: BigInt = M * oneMinusPhiBeta * oneMinusFusionRatio * SNeutrons - val denominator: BigInt = fusionRatio * SProtons - val outNeutronsAmount: BigInt = (numerator / denominator) / (precision * precision) + val ratio1: BigInt = (M.toBigInt * oneMinusPhiBeta) / SProtons + val ratio2: BigInt = (oneMinusFusionRatio * SNeutrons) / precision + val outNeutronsAmount: BigInt = (ratio1 * ratio2) / fusionRatio val NeutronsExpectedValue: BigInt = outNeutronsAmount - val ProtonsExpectedValue: BigInt = M + val ProtonsExpectedValue: BigInt = M.toBigInt val ErgsExpectedValue: BigInt = (IN_GLUONW_BOX.value).toBigInt // ### The 2 conditions to ensure that the values out is right ### // @@ -642,7 +643,7 @@ } else if (isBetaDecayMinusTx) { // ===== BetaDecayMinus Tx ===== // //Equation: M [Neutrons] = M * (1 - PhiBeta(T)) * ((q(R, S neutron)) / 1 - q(R, S neutron)) * (S protons / S neutrons) [Protons] - val M: BigInt = (OUT_GLUONW_NEUTRONS_TOKEN._2 - IN_GLUONW_NEUTRONS_TOKEN._2).toBigInt + val M: Long = (OUT_GLUONW_NEUTRONS_TOKEN._2 - IN_GLUONW_NEUTRONS_TOKEN._2) // ** VarPhiBeta Calculation ** val currentBlockNumber: Long = CONTEXT.HEIGHT @@ -753,13 +754,14 @@ // ** Fusion Ratio ** // min(q*, (SNeutrons * Pt / R)) // where q* is a constant, Pt is the price of gold in Ergs. + // The steps of multiplication and division done below are to avoid overflow errors. val oneMinusPhiBeta: BigInt = precision - VarPhiBeta val oneMinusFusionRatio: BigInt = precision - fusionRatio - val numerator: BigInt = M * oneMinusPhiBeta * fusionRatio * SProtons - val denominator: BigInt = oneMinusFusionRatio * SNeutrons - val outProtonsAmount: BigInt = numerator / denominator + val ratio1: BigInt = (M.toBigInt * oneMinusPhiBeta) / SNeutrons + val ratio2: BigInt = (fusionRatio * SProtons) / precision + val outProtonsAmount: BigInt = (ratio1 * ratio2) / oneMinusFusionRatio - val NeutronsExpectedValue: BigInt = M + val NeutronsExpectedValue: BigInt = M.toBigInt val ProtonsExpectedValue: BigInt = outProtonsAmount val ErgsExpectedValue: BigInt = (IN_GLUONW_BOX.value).toBigInt diff --git a/modules/gluonw-base/src/main/scala/gluonw/common/GluonWAlgorithm.scala b/modules/gluonw-base/src/main/scala/gluonw/common/GluonWAlgorithm.scala index 88e9a6e..83c8fdf 100644 --- a/modules/gluonw-base/src/main/scala/gluonw/common/GluonWAlgorithm.scala +++ b/modules/gluonw-base/src/main/scala/gluonw/common/GluonWAlgorithm.scala @@ -244,10 +244,9 @@ case class GluonWCalculator( ) val oneMinusFusionRatio: BigInt = BigInt(gluonWConstants.precision) - fusionRatio - val minusesMultiplied: BigInt = - oneMinusPhiBeta * oneMinusFusionRatio / gluonWConstants.precision - val outNeutronsAmount: Long = - ((((BigInt(protonsToDecay) * minusesMultiplied) / fusionRatio) * sNeutrons) / sProtons).toLong + val ratio1: BigInt = (BigInt(protonsToDecay) * oneMinusPhiBeta) / BigInt(sProtons) + val ratio2: BigInt = (oneMinusFusionRatio * BigInt(sNeutrons)) / BigInt(gluonWConstants.precision) + val outNeutronsAmount: BigInt = (ratio1 * ratio2) / fusionRatio GluonWBoxOutputAssetAmount( ergAmount = 0, @@ -275,15 +274,14 @@ case class GluonWCalculator( ) val oneMinusFusionRatio: BigInt = BigInt(gluonWConstants.precision) - fusionRatio - val neutronsToDecayMultiplyOneMinusPhiBeta: BigInt = - BigInt(neutronsToDecay) * oneMinusPhiBeta / gluonWConstants.precision - val outProtonsAmount: Long = - (((neutronsToDecayMultiplyOneMinusPhiBeta * sProtons / sNeutrons) * fusionRatio) / oneMinusFusionRatio).toLong + val ratio1: BigInt = (BigInt(neutronsToDecay) * oneMinusPhiBeta) / BigInt(sNeutrons) + val ratio2: BigInt = (fusionRatio * BigInt(sProtons)) / BigInt(gluonWConstants.precision) + val outProtonsAmount: BigInt = (ratio1 * ratio2) / oneMinusFusionRatio GluonWBoxOutputAssetAmount( ergAmount = 0, neutronsAmount = -neutronsToDecay, - protonsAmount = outProtonsAmount + protonsAmount = outProtonsAmount.toLong ) } } diff --git a/modules/gluonw-base/src/test/scala/gluonw/common/GluonWBase.scala b/modules/gluonw-base/src/test/scala/gluonw/common/GluonWBase.scala index a1ef506..46bbb54 100644 --- a/modules/gluonw-base/src/test/scala/gluonw/common/GluonWBase.scala +++ b/modules/gluonw-base/src/test/scala/gluonw/common/GluonWBase.scala @@ -169,8 +169,8 @@ trait GluonWBase extends UnitSpec { def genesisGluonWBox( ergAmount: Double = 200_000L, - neutronAmount: Double = 1_000L, - protonAmount: Double = 1_000L + neutronAmount: Double = 1_000_000L, + protonAmount: Double = 1_000_000L ): GluonWBox = GluonWBox.create( protonAmount = GluonWBoxConstants.PROTONS_TOTAL_CIRCULATING_SUPPLY - (protonAmount * GluonWBoxConstants.PRECISION).toLong,