|
| 1 | +package currencycreator |
| 2 | + |
| 3 | +import ( |
| 4 | + "math" |
| 5 | + "math/big" |
| 6 | +) |
| 7 | + |
| 8 | +// Note: Generated with Grok 4 based on curve.rs, and not 100% accurate with on-chain program |
| 9 | + |
| 10 | +const defaultPrec = 192 |
| 11 | + |
| 12 | +type ExponentialCurve struct { |
| 13 | + a *big.Float |
| 14 | + b *big.Float |
| 15 | + c *big.Float |
| 16 | +} |
| 17 | + |
| 18 | +func expBig(x *big.Float) *big.Float { |
| 19 | + prec := x.Prec() |
| 20 | + result := big.NewFloat(1).SetPrec(prec) |
| 21 | + term := big.NewFloat(1).SetPrec(prec) |
| 22 | + for i := 1; i < 1000; i++ { |
| 23 | + term = term.Mul(term, x) |
| 24 | + term = term.Quo(term, big.NewFloat(float64(i))) |
| 25 | + old := new(big.Float).Copy(result) |
| 26 | + result = result.Add(result, term) |
| 27 | + if term.Cmp(new(big.Float).SetFloat64(0)) == 0 { |
| 28 | + break |
| 29 | + } |
| 30 | + if old.Cmp(result) == 0 { |
| 31 | + break |
| 32 | + } |
| 33 | + } |
| 34 | + return result |
| 35 | +} |
| 36 | + |
| 37 | +func logBig(y *big.Float) *big.Float { |
| 38 | + if y.Sign() <= 0 { |
| 39 | + panic("log of non-positive number") |
| 40 | + } |
| 41 | + yf, _ := y.Float64() |
| 42 | + z := big.NewFloat(math.Log(yf)).SetPrec(y.Prec()) |
| 43 | + for range 50 { |
| 44 | + expz := expBig(z) |
| 45 | + adjustment := new(big.Float).Quo(y, expz) |
| 46 | + z = z.Add(z, adjustment) |
| 47 | + z = z.Sub(z, big.NewFloat(1)) |
| 48 | + } |
| 49 | + return z |
| 50 | +} |
| 51 | + |
| 52 | +func (curve *ExponentialCurve) SpotPriceAtSupply(currentSupply *big.Float) *big.Float { |
| 53 | + cTimesS := new(big.Float).Mul(curve.c, currentSupply) |
| 54 | + exp := expBig(cTimesS) |
| 55 | + return new(big.Float).Mul(new(big.Float).Mul(curve.a, curve.b), exp) |
| 56 | +} |
| 57 | + |
| 58 | +func (curve *ExponentialCurve) TokensToValue(currentSupply, tokens *big.Float) *big.Float { |
| 59 | + newSupply := new(big.Float).Add(currentSupply, tokens) |
| 60 | + cs := new(big.Float).Mul(curve.c, currentSupply) |
| 61 | + ns := new(big.Float).Mul(curve.c, newSupply) |
| 62 | + expCS := expBig(cs) |
| 63 | + expNS := expBig(ns) |
| 64 | + abOverC := new(big.Float).Quo(new(big.Float).Mul(curve.a, curve.b), curve.c) |
| 65 | + diff := new(big.Float).Sub(expNS, expCS) |
| 66 | + return new(big.Float).Mul(abOverC, diff) |
| 67 | +} |
| 68 | + |
| 69 | +func (curve *ExponentialCurve) ValueToTokens(currentSupply, value *big.Float) *big.Float { |
| 70 | + abOverC := new(big.Float).Quo(new(big.Float).Mul(curve.a, curve.b), curve.c) |
| 71 | + expCS := expBig(new(big.Float).Mul(curve.c, currentSupply)) |
| 72 | + term := new(big.Float).Add(new(big.Float).Quo(value, abOverC), expCS) |
| 73 | + lnTerm := logBig(term) |
| 74 | + result := new(big.Float).Quo(lnTerm, curve.c) |
| 75 | + return new(big.Float).Sub(result, currentSupply) |
| 76 | +} |
| 77 | + |
| 78 | +func DefaultExponentialCurve() ExponentialCurve { |
| 79 | + scale, ok := new(big.Float).SetPrec(defaultPrec).SetString("1000000000000000000") // 10^18 |
| 80 | + if !ok { |
| 81 | + panic("Invalid scale string") |
| 82 | + } |
| 83 | + |
| 84 | + aInt, ok := new(big.Int).SetString("11400230149967394933471", 10) |
| 85 | + if !ok { |
| 86 | + panic("Invalid CURVE_A string") |
| 87 | + } |
| 88 | + |
| 89 | + bInt, ok := new(big.Int).SetString("877175273521", 10) |
| 90 | + if !ok { |
| 91 | + panic("Invalid CURVE_B string") |
| 92 | + } |
| 93 | + |
| 94 | + a := new(big.Float).Quo(new(big.Float).SetInt(aInt).SetPrec(defaultPrec), scale) |
| 95 | + b := new(big.Float).Quo(new(big.Float).SetInt(bInt).SetPrec(defaultPrec), scale) |
| 96 | + c := new(big.Float).Copy(b) |
| 97 | + |
| 98 | + return ExponentialCurve{a: a, b: b, c: c} |
| 99 | +} |
0 commit comments