/
liquidityprotection.go
82 lines (69 loc) · 3.54 KB
/
liquidityprotection.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package keeper
import (
"errors"
"github.com/Sifchain/sifnode/x/clp/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func (k Keeper) SetLiquidityProtectionParams(ctx sdk.Context, params *types.LiquidityProtectionParams) {
store := ctx.KVStore(k.storeKey)
store.Set(types.LiquidityProtectionParamsPrefix, k.cdc.MustMarshal(params))
}
func (k Keeper) GetLiquidityProtectionParams(ctx sdk.Context) *types.LiquidityProtectionParams {
params := types.LiquidityProtectionParams{}
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.LiquidityProtectionParamsPrefix)
k.cdc.MustUnmarshal(bz, ¶ms)
return ¶ms
}
// This method should only be called if buying or selling native asset.
// If sellNative is false then this method assumes that buyNative is true.
// The nativePrice should be in MaxRowanLiquidityThresholdAsset
// NOTE: this method panics if sellNative is true and the value of the sell amount
// is greater than the value of currentRowanLiquidityThreshold. Call IsBlockedByLiquidityProtection
// before if unsure.
func (k Keeper) MustUpdateLiquidityProtectionThreshold(ctx sdk.Context, sellNative bool, nativeAmount sdk.Uint, nativePrice sdk.Dec) {
liquidityProtectionParams := k.GetLiquidityProtectionParams(ctx)
maxRowanLiquidityThreshold := liquidityProtectionParams.MaxRowanLiquidityThreshold
currentRowanLiquidityThreshold := k.GetLiquidityProtectionRateParams(ctx).CurrentRowanLiquidityThreshold
if liquidityProtectionParams.IsActive {
nativeValue := CalcRowanValue(nativeAmount, nativePrice)
var updatedRowanLiquidityThreshold sdk.Uint
if sellNative {
if currentRowanLiquidityThreshold.LT(nativeValue) {
panic(errors.New("expect sell native value to be less than currentRowanLiquidityThreshold"))
} else {
updatedRowanLiquidityThreshold = currentRowanLiquidityThreshold.Sub(nativeValue)
}
} else {
// This is equivalent to currentRowanLiquidityThreshold := sdk.MinUint(currentRowanLiquidityThreshold.Add(nativeValue), maxRowanLiquidityThreshold)
// except it prevents any overflows when adding the nativeValue
// Assume that maxRowanLiquidityThreshold >= currentRowanLiquidityThreshold
if maxRowanLiquidityThreshold.Sub(currentRowanLiquidityThreshold).LT(nativeValue) {
updatedRowanLiquidityThreshold = maxRowanLiquidityThreshold
} else {
updatedRowanLiquidityThreshold = currentRowanLiquidityThreshold.Add(nativeValue)
}
}
k.SetLiquidityProtectionCurrentRowanLiquidityThreshold(ctx, updatedRowanLiquidityThreshold)
}
}
// Currently this calculates the native price on the fly
// Calculates the price of the native token in MaxRowanLiquidityThresholdAsset
func (k Keeper) GetNativePrice(ctx sdk.Context) (sdk.Dec, error) {
liquidityProtectionParams := k.GetLiquidityProtectionParams(ctx)
maxRowanLiquidityThresholdAsset := liquidityProtectionParams.MaxRowanLiquidityThresholdAsset
if types.StringCompare(maxRowanLiquidityThresholdAsset, types.NativeSymbol) {
return sdk.OneDec(), nil
}
pool, err := k.GetPool(ctx, maxRowanLiquidityThresholdAsset)
if err != nil {
return sdk.Dec{}, types.ErrMaxRowanLiquidityThresholdAssetPoolDoesNotExist
}
return CalcRowanSpotPrice(&pool, k.GetPmtpRateParams(ctx).PmtpCurrentRunningRate)
}
// The nativePrice should be in MaxRowanLiquidityThresholdAsset
func (k Keeper) IsBlockedByLiquidityProtection(ctx sdk.Context, nativeAmount sdk.Uint, nativePrice sdk.Dec) bool {
value := CalcRowanValue(nativeAmount, nativePrice)
currentRowanLiquidityThreshold := k.GetLiquidityProtectionRateParams(ctx).CurrentRowanLiquidityThreshold
return currentRowanLiquidityThreshold.LT(value)
}