Skip to content

Commit

Permalink
feat(amm): weight recovery reward applied to weight balance bonuses (#…
Browse files Browse the repository at this point in the history
…870)

* feat(amm): weight recovery reward applied to weight balance bonuses

* test(amm): fix tests

* test(amm): fix tests

* fix: setup handler

* test(amm): fix tests

* test(perpetual): fix test
  • Loading branch information
cosmic-vagabond authored Oct 24, 2024
1 parent 933d2c6 commit 9482221
Show file tree
Hide file tree
Showing 22 changed files with 1,310 additions and 137 deletions.
3 changes: 2 additions & 1 deletion app/setup_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const (
)

// make sure to update these when you upgrade the version
var NextVersion = "v0.48.0"
var NextVersion = "v0.49.0"

func SetupHandlers(app *ElysApp) {
setUpgradeHandler(app)
Expand All @@ -30,6 +30,7 @@ func setUpgradeHandler(app *ElysApp) {
app.Logger().Info("Running upgrade handler for " + version.Version)

if version.Version == NextVersion || version.Version == LocalNetVersion {

// Add any logic here to run when the chain is upgraded to the new version
}

Expand Down
13 changes: 13 additions & 0 deletions proto/elys/amm/pool.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@ import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos_proto/cosmos.proto";

message LegacyPool {
uint64 pool_id = 1;
string address = 2;
LegacyPoolParams pool_params = 3 [(gogoproto.nullable) = false];
cosmos.base.v1beta1.Coin total_shares = 4 [(gogoproto.nullable) = false];
repeated PoolAsset pool_assets = 5 [(gogoproto.nullable) = false];
string total_weight = 6 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
string rebalance_treasury = 7;
}

message Pool {
uint64 pool_id = 1;
string address = 2;
Expand Down
39 changes: 38 additions & 1 deletion proto/elys/amm/pool_params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "cosmos_proto/cosmos.proto";

option go_package = "github.com/elys-network/elys/x/amm/types";

message PoolParams {
message LegacyPoolParams {
string swap_fee = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
Expand Down Expand Up @@ -38,3 +38,40 @@ message PoolParams {
];
string fee_denom = 8; // denom for fee collection
}

message PoolParams {
string swap_fee = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
string exit_fee = 2 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
bool use_oracle = 3;
string weight_breaking_fee_multiplier = 4 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
string weight_breaking_fee_exponent = 5 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
string external_liquidity_ratio = 6 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
string weight_recovery_fee_portion = 7 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
string threshold_weight_difference = 8 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
string weight_breaking_fee_portion = 9 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
string fee_denom = 10; // denom for fee collection
}
1 change: 1 addition & 0 deletions x/amm/client/cli/query_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func networkWithPoolObjects(t *testing.T, n int) (*network.Network, []types.Pool
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
}
Expand Down
5 changes: 5 additions & 0 deletions x/amm/keeper/msg_server_create_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func (suite *KeeperTestSuite) TestMsgServerCreatePool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
poolAssets: []types.PoolAsset{
Expand Down Expand Up @@ -63,6 +64,7 @@ func (suite *KeeperTestSuite) TestMsgServerCreatePool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
poolAssets: []types.PoolAsset{
Expand Down Expand Up @@ -92,6 +94,7 @@ func (suite *KeeperTestSuite) TestMsgServerCreatePool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
poolAssets: []types.PoolAsset{
Expand Down Expand Up @@ -121,6 +124,7 @@ func (suite *KeeperTestSuite) TestMsgServerCreatePool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
poolAssets: []types.PoolAsset{
Expand Down Expand Up @@ -150,6 +154,7 @@ func (suite *KeeperTestSuite) TestMsgServerCreatePool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
poolAssets: []types.PoolAsset{
Expand Down
8 changes: 6 additions & 2 deletions x/amm/keeper/msg_server_exit_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func (suite *KeeperTestSuite) TestMsgServerExitPool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
shareInAmount: types.OneShare.Quo(sdk.NewInt(5)),
Expand All @@ -56,6 +57,7 @@ func (suite *KeeperTestSuite) TestMsgServerExitPool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
shareInAmount: types.OneShare.Quo(sdk.NewInt(5)),
Expand All @@ -76,6 +78,7 @@ func (suite *KeeperTestSuite) TestMsgServerExitPool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.NewDecWithPrec(2, 1), // 20%
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
shareInAmount: types.OneShare.Quo(sdk.NewInt(10)),
Expand All @@ -97,13 +100,14 @@ func (suite *KeeperTestSuite) TestMsgServerExitPool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.NewDecWithPrec(2, 1), // 20%
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
shareInAmount: types.OneShare.Quo(sdk.NewInt(10)),
tokenOutDenom: ptypes.BaseCurrency,
minAmountsOut: sdk.Coins{sdk.NewInt64Coin(ptypes.BaseCurrency, 100000)},
minAmountsOut: sdk.Coins{sdk.NewInt64Coin(ptypes.BaseCurrency, 86881)},
// expSenderBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.BaseCurrency, 99197)}, // slippage enabled
expSenderBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.BaseCurrency, 100000)}, // slippage disabled
expSenderBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.BaseCurrency, 86881)}, // slippage disabled
expPass: true,
},
} {
Expand Down
5 changes: 5 additions & 0 deletions x/amm/keeper/msg_server_join_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func (suite *KeeperTestSuite) TestMsgServerJoinPool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
shareOutAmount: types.OneShare.Quo(sdk.NewInt(5)),
Expand All @@ -55,6 +56,7 @@ func (suite *KeeperTestSuite) TestMsgServerJoinPool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
shareOutAmount: types.OneShare.Quo(sdk.NewInt(5)),
Expand All @@ -75,6 +77,7 @@ func (suite *KeeperTestSuite) TestMsgServerJoinPool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.NewDecWithPrec(2, 1), // 20%
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
// shareOutAmount: sdk.NewInt(694444166666666666), // weight breaking fee - slippage enable
Expand All @@ -96,6 +99,7 @@ func (suite *KeeperTestSuite) TestMsgServerJoinPool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.NewDecWithPrec(2, 1), // 20%
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
// shareOutAmount: sdk.NewInt(805987500000000000), // weight recovery direction - slippage enable
Expand All @@ -117,6 +121,7 @@ func (suite *KeeperTestSuite) TestMsgServerJoinPool() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.NewDecWithPrec(2, 1), // 20%
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
shareOutAmount: sdk.NewInt(2000000000000000000),
Expand Down
5 changes: 5 additions & 0 deletions x/amm/keeper/msg_server_update_pool_params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func (suite *KeeperTestSuite) TestMsgServerUpdatePoolParams() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
updatedPoolParams: types.PoolParams{
Expand All @@ -45,6 +46,7 @@ func (suite *KeeperTestSuite) TestMsgServerUpdatePoolParams() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: "feedenom",
},
poolAssets: []types.PoolAsset{
Expand Down Expand Up @@ -73,6 +75,7 @@ func (suite *KeeperTestSuite) TestMsgServerUpdatePoolParams() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
updatedPoolParams: types.PoolParams{
Expand All @@ -84,6 +87,7 @@ func (suite *KeeperTestSuite) TestMsgServerUpdatePoolParams() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
poolAssets: []types.PoolAsset{
Expand Down Expand Up @@ -112,6 +116,7 @@ func (suite *KeeperTestSuite) TestMsgServerUpdatePoolParams() {
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
},
poolAssets: []types.PoolAsset{
Expand Down
16 changes: 16 additions & 0 deletions x/amm/keeper/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ func (k Keeper) GetAllPool(ctx sdk.Context) (list []types.Pool) {
return
}

// GetAllLegacyPool returns all legacy pool
func (k Keeper) GetAllLegacyPool(ctx sdk.Context) (list []types.LegacyPool) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.PoolKeyPrefix))
iterator := sdk.KVStorePrefixIterator(store, []byte{})

defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
var val types.LegacyPool
k.cdc.MustUnmarshal(iterator.Value(), &val)
list = append(list, val)
}

return
}

// GetLatestPool retrieves the latest pool item from the list of pools
func (k Keeper) GetLatestPool(ctx sdk.Context) (val types.Pool, found bool) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.PoolKeyPrefix))
Expand Down
1 change: 1 addition & 0 deletions x/amm/keeper/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func createNPool(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.Pool {
ExternalLiquidityRatio: sdk.ZeroDec(),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: ptypes.BaseCurrency,
}

Expand Down
29 changes: 28 additions & 1 deletion x/amm/migrations/v5_migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,37 @@ import (
)

func (m Migrator) V5Migration(ctx sdk.Context) error {
m.keeper.SetParams(ctx, types.Params{
m.keeper.SetParams(ctx, types.Params{
PoolCreationFee: math.NewInt(10_000_000),
SlippageTrackDuration: 86400*7,
EnableBaseCurrencyPairedPoolOnly: false,
})

pools := m.keeper.GetAllLegacyPool(ctx)
for _, pool := range pools {
newPool := types.Pool{
PoolId: pool.PoolId,
Address: pool.Address,
PoolParams: types.PoolParams{
SwapFee: pool.PoolParams.SwapFee,
ExitFee: pool.PoolParams.ExitFee,
UseOracle: pool.PoolParams.UseOracle,
WeightBreakingFeeMultiplier: pool.PoolParams.WeightBreakingFeeMultiplier,
WeightBreakingFeeExponent: pool.PoolParams.WeightBreakingFeeExponent,
ExternalLiquidityRatio: pool.PoolParams.ExternalLiquidityRatio,
WeightRecoveryFeePortion: pool.PoolParams.WeightRecoveryFeePortion,
ThresholdWeightDifference: pool.PoolParams.ThresholdWeightDifference,
WeightBreakingFeePortion: sdk.NewDecWithPrec(50, 2), // 50%
FeeDenom: pool.PoolParams.FeeDenom,
},
TotalShares: pool.TotalShares,
PoolAssets: pool.PoolAssets,
TotalWeight: pool.TotalWeight,
RebalanceTreasury: pool.RebalanceTreasury,
}

m.keeper.RemovePool(ctx, pool.PoolId)
m.keeper.SetPool(ctx, newPool)
}
return nil
}
23 changes: 8 additions & 15 deletions x/amm/types/calc_exit_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ func CalcExitPool(

// refundedShares = exitingShares * (1 - exit fee)
// with 0 exit fee optimization
var refundedShares sdk.Dec
refundedShares = sdk.NewDecFromInt(exitingShares)
refundedShares := sdk.NewDecFromInt(exitingShares)

shareOutRatio := refundedShares.QuoInt(totalShares.Amount)
// exitedCoins = shareOutRatio * pool liquidity
Expand Down Expand Up @@ -133,21 +132,15 @@ func CalcExitPool(

weightDistance := pool.WeightDistanceFromTarget(ctx, oracleKeeper, newAssetPools)
distanceDiff := weightDistance.Sub(initialWeightDistance)
weightBreakingFee := sdk.ZeroDec()
if distanceDiff.IsPositive() {
// old weight breaking fee implementation
// weightBreakingFee = pool.PoolParams.WeightBreakingFeeMultiplier.Mul(distanceDiff)

// target weight
targetWeightOut := NormalizedWeight(ctx, pool.PoolAssets, tokenOutDenom)
targetWeightIn := sdk.OneDec().Sub(targetWeightOut)
// target weight
targetWeightOut := NormalizedWeight(ctx, pool.PoolAssets, tokenOutDenom)
targetWeightIn := sdk.OneDec().Sub(targetWeightOut)

// weight breaking fee as in Plasma pool
weightOut := OracleAssetWeight(ctx, oracleKeeper, newAssetPools, tokenOutDenom)
weightIn := sdk.OneDec().Sub(weightOut)

weightBreakingFee = GetWeightBreakingFee(weightIn, weightOut, targetWeightIn, targetWeightOut, pool.PoolParams)
}
// weight breaking fee as in Plasma pool
weightOut := OracleAssetWeight(ctx, oracleKeeper, newAssetPools, tokenOutDenom)
weightIn := sdk.OneDec().Sub(weightOut)
weightBreakingFee := GetWeightBreakingFee(weightIn, weightOut, targetWeightIn, targetWeightOut, pool.PoolParams, distanceDiff)

tokenOutAmount := oracleOutAmount.Mul(sdk.OneDec().Sub(weightBreakingFee)).RoundInt()
return sdk.Coins{sdk.NewCoin(tokenOutDenom, tokenOutAmount)}, weightBreakingFee.Neg(), nil
Expand Down
Loading

0 comments on commit 9482221

Please sign in to comment.