Skip to content

Commit 4f63c9a

Browse files
committed
Update currency creator curve and estimate functions
1 parent 6dbaee9 commit 4f63c9a

File tree

4 files changed

+87
-33
lines changed

4 files changed

+87
-33
lines changed

pkg/solana/currencycreator/estimate.go

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package currencycreator
33
import (
44
"math"
55
"math/big"
6-
7-
"github.com/code-payments/code-server/pkg/usdc"
86
)
97

108
func EstimateCurrentPrice(currentSupplyInQuarks uint64) *big.Float {
@@ -14,14 +12,38 @@ func EstimateCurrentPrice(currentSupplyInQuarks uint64) *big.Float {
1412
return DefaultExponentialCurve().SpotPriceAtSupply(scaledCurrentSupply)
1513
}
1614

17-
type EstimateBuyInUsdcArgs struct {
15+
type EstimateValueExchangeArgs struct {
16+
ValueInQuarks uint64
17+
CurrentSupplyInQuarks uint64
18+
ValueMintDecimals uint8
19+
}
20+
21+
func EstimateValueExchange(args *EstimateValueExchangeArgs) uint64 {
22+
scale := big.NewFloat(math.Pow10(int(args.ValueMintDecimals))).SetPrec(defaultCurvePrec)
23+
unscaledValue := big.NewFloat(float64(args.ValueInQuarks)).SetPrec(defaultCurvePrec)
24+
scaledValue := new(big.Float).Quo(unscaledValue, scale)
25+
26+
scale = big.NewFloat(math.Pow10(int(DefaultMintDecimals))).SetPrec(defaultCurvePrec)
27+
unscaledCurrentSupply := big.NewFloat(float64(args.CurrentSupplyInQuarks)).SetPrec(defaultCurvePrec)
28+
scaledCurrentSupply := new(big.Float).Quo(unscaledCurrentSupply, scale)
29+
30+
scale = big.NewFloat(math.Pow10(int(DefaultMintDecimals))).SetPrec(defaultCurvePrec)
31+
scaledTokens := DefaultExponentialCurve().TokensForValueExchange(scaledCurrentSupply, scaledValue)
32+
unscaledTokens := new(big.Float).Mul(scaledTokens, scale)
33+
34+
quarks, _ := unscaledTokens.Int64()
35+
return uint64(quarks)
36+
}
37+
38+
type EstimateBuyArgs struct {
1839
BuyAmountInQuarks uint64
1940
CurrentSupplyInQuarks uint64
41+
ValueMintDecimals uint8
2042
BuyFeeBps uint16
2143
}
2244

23-
func EstimateBuyInUsdc(args *EstimateBuyInUsdcArgs) (uint64, uint64) {
24-
scale := big.NewFloat(math.Pow10(int(usdc.Decimals))).SetPrec(defaultCurvePrec)
45+
func EstimateBuy(args *EstimateBuyArgs) (uint64, uint64) {
46+
scale := big.NewFloat(math.Pow10(int(args.ValueMintDecimals))).SetPrec(defaultCurvePrec)
2547
unscaledBuyAmount := big.NewFloat(float64(args.BuyAmountInQuarks)).SetPrec(defaultCurvePrec)
2648
scaledBuyAmount := new(big.Float).Quo(unscaledBuyAmount, scale)
2749

@@ -30,7 +52,7 @@ func EstimateBuyInUsdc(args *EstimateBuyInUsdcArgs) (uint64, uint64) {
3052
scaledCurrentSupply := new(big.Float).Quo(unscaledCurrentSupply, scale)
3153

3254
scale = big.NewFloat(math.Pow10(int(DefaultMintDecimals))).SetPrec(defaultCurvePrec)
33-
scaledTokens := DefaultExponentialCurve().ValueToTokens(scaledCurrentSupply, scaledBuyAmount)
55+
scaledTokens := DefaultExponentialCurve().TokensBoughtForValue(scaledCurrentSupply, scaledBuyAmount)
3456
unscaledTokens := new(big.Float).Mul(scaledTokens, scale)
3557

3658
scale = big.NewFloat(math.Pow10(int(DefaultMintDecimals))).SetPrec(defaultCurvePrec)
@@ -43,26 +65,27 @@ func EstimateBuyInUsdc(args *EstimateBuyInUsdcArgs) (uint64, uint64) {
4365
return uint64(tokens - fees), uint64(fees)
4466
}
4567

46-
type EstimateSellInUsdcArgs struct {
68+
type EstimateSellArgs struct {
4769
SellAmountInQuarks uint64
4870
CurrentValueInQuarks uint64
71+
ValueMintDecimals uint8
4972
SellFeeBps uint16
5073
}
5174

52-
func EstimateSellInUsdc(args *EstimateSellInUsdcArgs) (uint64, uint64) {
75+
func EstimateSell(args *EstimateSellArgs) (uint64, uint64) {
5376
scale := big.NewFloat(math.Pow10(int(DefaultMintDecimals))).SetPrec(defaultCurvePrec)
5477
unscaledSellAmount := big.NewFloat(float64(args.SellAmountInQuarks)).SetPrec(defaultCurvePrec)
5578
scaledSellAmount := new(big.Float).Quo(unscaledSellAmount, scale)
5679

57-
scale = big.NewFloat(math.Pow10(int(usdc.Decimals))).SetPrec(defaultCurvePrec)
80+
scale = big.NewFloat(math.Pow10(int(args.ValueMintDecimals))).SetPrec(defaultCurvePrec)
5881
unscaledCurrentValue := big.NewFloat(float64(args.CurrentValueInQuarks)).SetPrec(defaultCurvePrec)
5982
scaledCurrentValue := new(big.Float).Quo(unscaledCurrentValue, scale)
6083

61-
scale = big.NewFloat(math.Pow10(int(usdc.Decimals))).SetPrec(defaultCurvePrec)
62-
scaledValue := DefaultExponentialCurve().TokensToValueFromCurrentValue(scaledCurrentValue, scaledSellAmount)
84+
scale = big.NewFloat(math.Pow10(int(args.ValueMintDecimals))).SetPrec(defaultCurvePrec)
85+
scaledValue := DefaultExponentialCurve().ValueFromSellingTokens(scaledCurrentValue, scaledSellAmount)
6386
unscaledValue := new(big.Float).Mul(scaledValue, scale)
6487

65-
scale = big.NewFloat(math.Pow10(int(usdc.Decimals))).SetPrec(defaultCurvePrec)
88+
scale = big.NewFloat(math.Pow10(int(args.ValueMintDecimals))).SetPrec(defaultCurvePrec)
6689
feePctValue := new(big.Float).SetPrec(defaultCurvePrec).Quo(big.NewFloat(float64(args.SellFeeBps)), big.NewFloat(10000))
6790
scaledFees := new(big.Float).Mul(scaledValue, feePctValue)
6891
unscaledFees := new(big.Float).Mul(scaledFees, scale)

pkg/solana/currencycreator/estimate_test.go

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,52 @@ import (
66
)
77

88
func TestEstimateCurrentPrice(t *testing.T) {
9-
t.Skip()
10-
119
fmt.Println(EstimateCurrentPrice(0).Text('f', DefaultCurveDecimals))
1210
fmt.Println(EstimateCurrentPrice(DefaultMintMaxQuarkSupply).Text('f', DefaultCurveDecimals))
1311
}
1412

15-
func TestEstimateBuyInUsdc(t *testing.T) {
16-
t.Skip()
13+
func TestEstimatValueExchange(t *testing.T) {
14+
quarks := EstimateValueExchange(&EstimateValueExchangeArgs{
15+
ValueInQuarks: 5_000_000,
16+
CurrentSupplyInQuarks: 7_232_649_000_000_000,
17+
ValueMintDecimals: 6,
18+
})
19+
20+
fmt.Printf("%d quarks\n", quarks)
21+
}
1722

18-
received, fees := EstimateBuyInUsdc(&EstimateBuyInUsdcArgs{
23+
func TestEstimateBuy(t *testing.T) {
24+
received, fees := EstimateBuy(&EstimateBuyArgs{
1925
BuyAmountInQuarks: 50_000_000,
2026
CurrentSupplyInQuarks: 0,
27+
ValueMintDecimals: 6,
2128
BuyFeeBps: 0,
2229
})
2330
fmt.Printf("%d total, %d received, %d fees\n", received+fees, received, fees)
2431

25-
received, fees = EstimateBuyInUsdc(&EstimateBuyInUsdcArgs{
26-
BuyAmountInQuarks: 50_000_000,
32+
received, fees = EstimateBuy(&EstimateBuyArgs{
33+
BuyAmountInQuarks: 50_000_000,
34+
2735
CurrentSupplyInQuarks: 4_989_067_263,
36+
ValueMintDecimals: 6,
2837
BuyFeeBps: 100,
2938
})
3039
fmt.Printf("%d total, %d received, %d fees\n", received+fees, received, fees)
3140
}
3241

33-
func TestEstimateSellInUsdc(t *testing.T) {
34-
t.Skip()
35-
36-
received, fees := EstimateSellInUsdc(&EstimateSellInUsdcArgs{
42+
func TestEstimateSell(t *testing.T) {
43+
received, fees := EstimateSell(&EstimateSellArgs{
3744
SellAmountInQuarks: 12_345_678_900_000,
3845
CurrentValueInQuarks: 50_000_000,
46+
ValueMintDecimals: 6,
3947
SellFeeBps: 0,
4048
})
4149
fmt.Printf("%d total, %d received, %d fees\n", received+fees, received, fees)
4250

43-
received, fees = EstimateSellInUsdc(&EstimateSellInUsdcArgs{
51+
received, fees = EstimateSell(&EstimateSellArgs{
4452
SellAmountInQuarks: 12_345_678_900_000,
4553
CurrentValueInQuarks: 50_000_000,
54+
ValueMintDecimals: 6,
4655
SellFeeBps: 100,
4756
})
4857
fmt.Printf("%d total, %d received, %d fees\n", received+fees, received, fees)

pkg/solana/currencycreator/exponential_curve.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ func (curve *ExponentialCurve) SpotPriceAtSupply(currentSupply *big.Float) *big.
2929
return new(big.Float).Mul(new(big.Float).Mul(curve.a, curve.b), exp)
3030
}
3131

32-
func (curve *ExponentialCurve) TokensToValueFromCurrentSupply(currentSupply, tokens *big.Float) *big.Float {
33-
newSupply := new(big.Float).Add(currentSupply, tokens)
32+
// What is the cost to buy tokensToBuy given the currentSupply?
33+
func (curve *ExponentialCurve) CostToBuyTokens(currentSupply, tokensToBuy *big.Float) *big.Float {
34+
newSupply := new(big.Float).Add(currentSupply, tokensToBuy)
3435
cs := new(big.Float).Mul(curve.c, currentSupply)
3536
ns := new(big.Float).Mul(curve.c, newSupply)
3637
expCS := expBig(cs)
@@ -40,16 +41,18 @@ func (curve *ExponentialCurve) TokensToValueFromCurrentSupply(currentSupply, tok
4041
return new(big.Float).Mul(abOverC, diff)
4142
}
4243

43-
func (curve *ExponentialCurve) TokensToValueFromCurrentValue(currentValue, tokens *big.Float) *big.Float {
44+
// How much value is received when selling tokensToSell with currentValueLocked in the reserves?
45+
func (curve *ExponentialCurve) ValueFromSellingTokens(currentValue, tokensToSell *big.Float) *big.Float {
4446
abOverC := new(big.Float).Quo(new(big.Float).Mul(curve.a, curve.b), curve.c)
4547
cvPlusAbOverC := new(big.Float).Add(currentValue, abOverC)
46-
cTimesTokens := new(big.Float).Mul(curve.c, tokens)
47-
exp := expBig(new(big.Float).Neg(cTimesTokens))
48+
cTimesTokensToSell := new(big.Float).Mul(curve.c, tokensToSell)
49+
exp := expBig(new(big.Float).Neg(cTimesTokensToSell))
4850
oneMinusExp := new(big.Float).Sub(big.NewFloat(1.0), exp)
4951
return new(big.Float).Mul(cvPlusAbOverC, oneMinusExp)
5052
}
5153

52-
func (curve *ExponentialCurve) ValueToTokens(currentSupply, value *big.Float) *big.Float {
54+
// How many tokens will be bought for a value given the currentSupply?
55+
func (curve *ExponentialCurve) TokensBoughtForValue(currentSupply, value *big.Float) *big.Float {
5356
abOverC := new(big.Float).Quo(new(big.Float).Mul(curve.a, curve.b), curve.c)
5457
expCS := expBig(new(big.Float).Mul(curve.c, currentSupply))
5558
term := new(big.Float).Add(new(big.Float).Quo(value, abOverC), expCS)
@@ -58,6 +61,27 @@ func (curve *ExponentialCurve) ValueToTokens(currentSupply, value *big.Float) *b
5861
return new(big.Float).Sub(result, currentSupply)
5962
}
6063

64+
// How many tokens should be exchanged for a value given the currentSupply?
65+
//
66+
// Note: This function assumes the default curve, and is not present in the currency creator program.
67+
func (curve *ExponentialCurve) TokensForValueExchange(currentSupply, value *big.Float) *big.Float {
68+
hundred := big.NewFloat(100)
69+
oneOverHundred := new(big.Float).Quo(big.NewFloat(1), hundred)
70+
71+
hundredTimesA := new(big.Float).Mul(hundred, curve.a)
72+
negativeHundredTimesA := new(big.Float).Mul(big.NewFloat(-1), hundredTimesA)
73+
74+
valueTimesB := new(big.Float).Mul(value, curve.b)
75+
76+
expCsTimesB := expBig(new(big.Float).Mul(currentSupply, curve.b))
77+
oneOverHundredTimesExpCsTimesB := new(big.Float).Mul(oneOverHundred, expCsTimesB)
78+
79+
lnInput := new(big.Float).Quo(valueTimesB, oneOverHundredTimesExpCsTimesB)
80+
lnInput = new(big.Float).Sub(big.NewFloat(1), lnInput)
81+
82+
return new(big.Float).Mul(negativeHundredTimesA, logBig(lnInput))
83+
}
84+
6185
func DefaultExponentialCurve() *ExponentialCurve {
6286
scale, ok := new(big.Float).SetPrec(defaultCurvePrec).SetString(DefaultCurveScaleString)
6387
if !ok {

pkg/solana/currencycreator/exponential_curve_test.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ func TestCalculateCurveConstants(t *testing.T) {
3030
}
3131

3232
func TestGenerateCurveTable(t *testing.T) {
33-
t.Skip()
34-
3533
curve := DefaultExponentialCurve()
3634

3735
fmt.Println("|------|----------------|----------------------------------|----------------------------|")
@@ -43,7 +41,7 @@ func TestGenerateCurveTable(t *testing.T) {
4341
supply := new(big.Float).Copy(zero)
4442

4543
for i := 0; i <= 100; i++ {
46-
cost := curve.TokensToValueFromCurrentSupply(zero, supply)
44+
cost := curve.CostToBuyTokens(zero, supply)
4745
spotPrice := curve.SpotPriceAtSupply(supply)
4846

4947
fmt.Printf("| %3d%% | %14s | %32s | %26s |\n",

0 commit comments

Comments
 (0)