diff --git a/proto/elys/leveragelp/pool.proto b/proto/elys/leveragelp/pool.proto index f82ebff0e..ca7dc0fa7 100644 --- a/proto/elys/leveragelp/pool.proto +++ b/proto/elys/leveragelp/pool.proto @@ -19,7 +19,7 @@ message Pool { (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; - string max_leveragelp_percent = 5 [ + string max_leveragelp_ratio = 5 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; diff --git a/proto/elys/perpetual/query.proto b/proto/elys/perpetual/query.proto index a36404cb2..ba44182f8 100644 --- a/proto/elys/perpetual/query.proto +++ b/proto/elys/perpetual/query.proto @@ -251,6 +251,8 @@ message QueryOpenEstimationResponse { string borrow_interest_rate = 13 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; string funding_rate = 14 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; string price_impact = 15 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; + cosmos.base.v1beta1.Coin custody = 16 [(gogoproto.nullable) = false] ; + cosmos.base.v1beta1.Coin liabilities = 17 [(gogoproto.nullable) = false] ; } message QueryGetAllToPayRequest {} diff --git a/x/accountedpool/keeper/hooks_leveragelp.go b/x/accountedpool/keeper/hooks_leveragelp.go index 1d7281f54..7e2463032 100644 --- a/x/accountedpool/keeper/hooks_leveragelp.go +++ b/x/accountedpool/keeper/hooks_leveragelp.go @@ -14,7 +14,7 @@ func (k Keeper) OnLeverageLpPoolEnable(ctx sdk.Context, ammPool ammtypes.Pool) e // Check if already exists exists := k.PoolExists(ctx, poolId) if exists { - return nil //TODO types.ErrPoolAlreadyExist correct this, failing in workflow + return types.ErrPoolAlreadyExist } // Initiate pool diff --git a/x/amm/types/params.go b/x/amm/types/params.go index 5dd734fbd..461695a98 100644 --- a/x/amm/types/params.go +++ b/x/amm/types/params.go @@ -9,8 +9,8 @@ import ( // NewParams creates a new Params instance func NewParams(poolCreationFee math.Int, slippageTrackDuration uint64, enable bool) Params { return Params{ - PoolCreationFee: poolCreationFee, - SlippageTrackDuration: slippageTrackDuration, + PoolCreationFee: poolCreationFee, + SlippageTrackDuration: slippageTrackDuration, EnableBaseCurrencyPairedPoolOnly: enable, } } diff --git a/x/leveragelp/keeper/msg_server_open.go b/x/leveragelp/keeper/msg_server_open.go index 79e0fe4b9..6e5bd6c7d 100644 --- a/x/leveragelp/keeper/msg_server_open.go +++ b/x/leveragelp/keeper/msg_server_open.go @@ -35,7 +35,7 @@ func (k Keeper) Open(ctx sdk.Context, msg *types.MsgOpen) (*types.MsgOpenRespons Quo(params.TotalValue.ToLegacyDec()) } - var pool_leveragelp sdk.Dec + var poolLeveragelpRatio sdk.Dec pool, found := k.GetPool(ctx, msg.AmmPoolId) if !found { return nil, errorsmod.Wrap(types.ErrPoolDoesNotExist, fmt.Sprintf("poolId: %d", msg.AmmPoolId)) @@ -44,9 +44,9 @@ func (k Keeper) Open(ctx sdk.Context, msg *types.MsgOpen) (*types.MsgOpenRespons if !found { return nil, errorsmod.Wrap(types.ErrPoolDoesNotExist, fmt.Sprintf("poolId: %d", msg.AmmPoolId)) } - pool_leveragelp = pool.LeveragedLpAmount.ToLegacyDec().Quo(amm_pool.TotalShares.Amount.ToLegacyDec()).Mul(sdk.NewDec(100)) + poolLeveragelpRatio = pool.LeveragedLpAmount.ToLegacyDec().Quo(amm_pool.TotalShares.Amount.ToLegacyDec()) - if pool_leveragelp.GTE(pool.MaxLeveragelpPercent) || borrowRatio.GTE(params.MaxLeverageRatio) { + if poolLeveragelpRatio.GTE(pool.MaxLeveragelpRatio) || borrowRatio.GTE(params.MaxLeverageRatio) { return nil, errorsmod.Wrap(types.ErrMaxLeverageLpExists, "no new position can be open") } diff --git a/x/leveragelp/migrations/v13_migration.go b/x/leveragelp/migrations/v13_migration.go index 5929e7c15..058410905 100644 --- a/x/leveragelp/migrations/v13_migration.go +++ b/x/leveragelp/migrations/v13_migration.go @@ -2,21 +2,9 @@ package migrations import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/elys-network/elys/x/leveragelp/types" ) func (m Migrator) V13Migration(ctx sdk.Context) error { - legacyPools := m.keeper.GetAllLegacyPools(ctx) - - for _, legacyPool := range legacyPools { - newPool := types.Pool{ - AmmPoolId: legacyPool.AmmPoolId, - Health: legacyPool.Health, - LeveragedLpAmount: legacyPool.LeveragedLpAmount, - LeverageMax: legacyPool.LeverageMax, - } - m.keeper.SetPool(ctx, newPool) - } return nil } diff --git a/x/leveragelp/migrations/v14_migration.go b/x/leveragelp/migrations/v14_migration.go index 13b6f9ee7..b8599c5c0 100644 --- a/x/leveragelp/migrations/v14_migration.go +++ b/x/leveragelp/migrations/v14_migration.go @@ -5,21 +5,6 @@ import ( ) func (m Migrator) V14Migration(ctx sdk.Context) error { - pools := m.keeper.GetAllPools(ctx) - - for _, pool := range pools { - - ammPool, err := m.keeper.GetAmmPool(ctx, pool.AmmPoolId) - if err != nil { - return err - } - if m.keeper.GetHooks() != nil { - err = m.keeper.GetHooks().AfterEnablingPool(ctx, ammPool) - if err != nil { - return err - } - } - } return nil } diff --git a/x/leveragelp/migrations/v15_migration.go b/x/leveragelp/migrations/v15_migration.go index d551f2a79..3aa825c23 100644 --- a/x/leveragelp/migrations/v15_migration.go +++ b/x/leveragelp/migrations/v15_migration.go @@ -1,6 +1,7 @@ package migrations import ( + "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/elys-network/elys/x/leveragelp/types" ) @@ -10,11 +11,11 @@ func (m Migrator) V15Migration(ctx sdk.Context) error { for _, legacyPool := range legacyPools { newPool := types.Pool{ - AmmPoolId: legacyPool.AmmPoolId, - Health: legacyPool.Health, - LeveragedLpAmount: legacyPool.LeveragedLpAmount, - LeverageMax: legacyPool.LeverageMax, - MaxLeveragelpPercent: sdk.NewDec(60), + AmmPoolId: legacyPool.AmmPoolId, + Health: legacyPool.Health, + LeveragedLpAmount: legacyPool.LeveragedLpAmount, + LeverageMax: legacyPool.LeverageMax, + MaxLeveragelpRatio: math.LegacyMustNewDecFromStr("0.6"), } m.keeper.SetPool(ctx, newPool) } diff --git a/x/leveragelp/types/pool.go b/x/leveragelp/types/pool.go index 93e17db19..bcc99f5e8 100644 --- a/x/leveragelp/types/pool.go +++ b/x/leveragelp/types/pool.go @@ -10,11 +10,11 @@ import ( func NewPool(poolId uint64, maxLeverage math.LegacyDec) Pool { return Pool{ - AmmPoolId: poolId, - Health: sdk.NewDec(100), - LeveragedLpAmount: sdk.ZeroInt(), - LeverageMax: sdk.NewDec(10), - MaxLeveragelpPercent: sdk.NewDec(60), + AmmPoolId: poolId, + Health: sdk.NewDec(100), + LeveragedLpAmount: sdk.ZeroInt(), + LeverageMax: sdk.NewDec(10), + MaxLeveragelpRatio: sdk.MustNewDecFromStr("0.6"), } } diff --git a/x/leveragelp/types/pool.pb.go b/x/leveragelp/types/pool.pb.go index dd9ece96d..32cd103d9 100644 --- a/x/leveragelp/types/pool.pb.go +++ b/x/leveragelp/types/pool.pb.go @@ -25,11 +25,11 @@ var _ = math.Inf const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type Pool struct { - AmmPoolId uint64 `protobuf:"varint,1,opt,name=amm_pool_id,json=ammPoolId,proto3" json:"amm_pool_id,omitempty"` - Health github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=health,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"health"` - LeveragedLpAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=leveraged_lp_amount,json=leveragedLpAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"leveraged_lp_amount"` - LeverageMax github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=leverage_max,json=leverageMax,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"leverage_max"` - MaxLeveragelpPercent github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=max_leveragelp_percent,json=maxLeveragelpPercent,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_leveragelp_percent"` + AmmPoolId uint64 `protobuf:"varint,1,opt,name=amm_pool_id,json=ammPoolId,proto3" json:"amm_pool_id,omitempty"` + Health github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=health,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"health"` + LeveragedLpAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=leveraged_lp_amount,json=leveragedLpAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"leveraged_lp_amount"` + LeverageMax github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=leverage_max,json=leverageMax,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"leverage_max"` + MaxLeveragelpRatio github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=max_leveragelp_ratio,json=maxLeveragelpRatio,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_leveragelp_ratio"` } func (m *Pool) Reset() { *m = Pool{} } @@ -127,11 +127,11 @@ func init() { func init() { proto.RegisterFile("elys/leveragelp/pool.proto", fileDescriptor_c3d30fce7b985054) } var fileDescriptor_c3d30fce7b985054 = []byte{ - // 331 bytes of a gzipped FileDescriptorProto + // 329 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4a, 0xcd, 0xa9, 0x2c, 0xd6, 0xcf, 0x49, 0x2d, 0x4b, 0x2d, 0x4a, 0x4c, 0x4f, 0xcd, 0x29, 0xd0, 0x2f, 0xc8, 0xcf, 0xcf, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x07, 0xc9, 0xe9, 0x21, 0xe4, 0xa4, 0x44, 0xd2, - 0xf3, 0xd3, 0xf3, 0xc1, 0x72, 0xfa, 0x20, 0x16, 0x44, 0x99, 0x52, 0x3b, 0x33, 0x17, 0x4b, 0x40, + 0xf3, 0xd3, 0xf3, 0xc1, 0x72, 0xfa, 0x20, 0x16, 0x44, 0x99, 0x52, 0x33, 0x33, 0x17, 0x4b, 0x40, 0x7e, 0x7e, 0x8e, 0x90, 0x1c, 0x17, 0x77, 0x62, 0x6e, 0x6e, 0x3c, 0xc8, 0x84, 0xf8, 0xcc, 0x14, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x96, 0x20, 0xce, 0xc4, 0xdc, 0x5c, 0x90, 0xac, 0x67, 0x8a, 0x90, 0x1b, 0x17, 0x5b, 0x46, 0x6a, 0x62, 0x4e, 0x49, 0x86, 0x04, 0x93, 0x02, 0xa3, 0x06, 0xa7, 0x93, @@ -141,14 +141,14 @@ var fileDescriptor_c3d30fce7b985054 = []byte{ 0x61, 0x98, 0xa3, 0x52, 0xe2, 0x73, 0x0a, 0xe2, 0x13, 0x73, 0xf3, 0x4b, 0xf3, 0x4a, 0x24, 0x98, 0x49, 0x36, 0xd4, 0x33, 0xaf, 0x24, 0x48, 0x10, 0x6e, 0x94, 0x4f, 0x81, 0x23, 0xd8, 0x20, 0xa1, 0x40, 0x2e, 0x1e, 0x98, 0x60, 0x7c, 0x6e, 0x62, 0x85, 0x04, 0x0b, 0x59, 0xae, 0xe5, 0x86, 0x99, - 0xe1, 0x9b, 0x58, 0x21, 0x94, 0xc2, 0x25, 0x96, 0x9b, 0x58, 0x11, 0x8f, 0x08, 0xcb, 0xf8, 0x82, - 0xd4, 0xa2, 0xe4, 0xd4, 0xbc, 0x12, 0x09, 0x56, 0xb2, 0x0c, 0x17, 0xc9, 0x4d, 0xac, 0xf0, 0x81, - 0x1b, 0x16, 0x00, 0x31, 0x4b, 0x69, 0x39, 0x13, 0x17, 0x97, 0x4f, 0x6a, 0x7a, 0x62, 0x72, 0xe5, - 0x68, 0x7c, 0xe0, 0x8d, 0x0f, 0x27, 0xcf, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, - 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, - 0x88, 0xd2, 0x47, 0x32, 0x0e, 0x94, 0xfe, 0x75, 0xf3, 0x52, 0x4b, 0xca, 0xf3, 0x8b, 0xb2, 0xc1, - 0x1c, 0xfd, 0x0a, 0xe4, 0xac, 0x02, 0x36, 0x3b, 0x89, 0x0d, 0x9c, 0x0b, 0x8c, 0x01, 0x01, 0x00, - 0x00, 0xff, 0xff, 0x85, 0x80, 0xbd, 0xf0, 0x4a, 0x03, 0x00, 0x00, + 0xe1, 0x9b, 0x58, 0x21, 0x94, 0xc0, 0x25, 0x92, 0x9b, 0x58, 0x11, 0x8f, 0x08, 0xcb, 0xf8, 0xa2, + 0xc4, 0x92, 0xcc, 0x7c, 0x09, 0x56, 0xb2, 0x8c, 0x16, 0xca, 0x4d, 0xac, 0xf0, 0x81, 0x1b, 0x15, + 0x04, 0x32, 0x49, 0x69, 0x39, 0x13, 0x17, 0x97, 0x4f, 0x6a, 0x7a, 0x62, 0x72, 0xe5, 0x68, 0x5c, + 0xe0, 0x8d, 0x0b, 0x27, 0xcf, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, + 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xd2, + 0x47, 0x32, 0x0e, 0x94, 0xf6, 0x75, 0xf3, 0x52, 0x4b, 0xca, 0xf3, 0x8b, 0xb2, 0xc1, 0x1c, 0xfd, + 0x0a, 0xe4, 0x6c, 0x02, 0x36, 0x3b, 0x89, 0x0d, 0x9c, 0x03, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, + 0xff, 0x54, 0x46, 0x0e, 0x9d, 0x46, 0x03, 0x00, 0x00, } func (m *Pool) Marshal() (dAtA []byte, err error) { @@ -172,9 +172,9 @@ func (m *Pool) MarshalToSizedBuffer(dAtA []byte) (int, error) { var l int _ = l { - size := m.MaxLeveragelpPercent.Size() + size := m.MaxLeveragelpRatio.Size() i -= size - if _, err := m.MaxLeveragelpPercent.MarshalTo(dAtA[i:]); err != nil { + if _, err := m.MaxLeveragelpRatio.MarshalTo(dAtA[i:]); err != nil { return 0, err } i = encodeVarintPool(dAtA, i, uint64(size)) @@ -303,7 +303,7 @@ func (m *Pool) Size() (n int) { n += 1 + l + sovPool(uint64(l)) l = m.LeverageMax.Size() n += 1 + l + sovPool(uint64(l)) - l = m.MaxLeveragelpPercent.Size() + l = m.MaxLeveragelpRatio.Size() n += 1 + l + sovPool(uint64(l)) return n } @@ -484,7 +484,7 @@ func (m *Pool) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 5: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MaxLeveragelpPercent", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field MaxLeveragelpRatio", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -512,7 +512,7 @@ func (m *Pool) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.MaxLeveragelpPercent.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.MaxLeveragelpRatio.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/x/perpetual/keeper/mtp.go b/x/perpetual/keeper/mtp.go index 60f5afd17..77ffc9725 100644 --- a/x/perpetual/keeper/mtp.go +++ b/x/perpetual/keeper/mtp.go @@ -188,7 +188,7 @@ func (k Keeper) fillMTPData(ctx sdk.Context, mtp types.MTP, baseCurrency string) fundingFeesInBaseCurrency = fundingFeesInBaseCurrency.ToLegacyDec().Mul(tradingAssetPrice).TruncateInt() } - effectiveLeverage, err := k.UpdatedLeverage(ctx, mtp) + effectiveLeverage, err := k.GetEffectiveLeverage(ctx, mtp) if err != nil { return nil, err } @@ -348,8 +348,8 @@ func (k Keeper) GetEstimatedPnL(ctx sdk.Context, mtp types.MTP, baseCurrency str // estimated_pnl = (custody_amount - collateral_amount) * market_price - totalLiabilities // For long position, convert both custody and collateral to base currency - custodyAfterCollateralInBaseCurrecy := (custodyAmtAfterFunding.Sub(collateralAmt)).ToLegacyDec().Mul(tradingAssetPrice).TruncateInt() - estimatedPnL = custodyAfterCollateralInBaseCurrecy.Sub(totalLiabilities) + custodyAfterCollateralInBaseCurrency := (custodyAmtAfterFunding.Sub(collateralAmt)).ToLegacyDec().Mul(tradingAssetPrice).TruncateInt() + estimatedPnL = custodyAfterCollateralInBaseCurrency.Sub(totalLiabilities) } else { // estimated_pnl = custody_amount * market_price - totalLiabilities - collateral_amount diff --git a/x/perpetual/keeper/mtp_leverage.go b/x/perpetual/keeper/mtp_leverage.go new file mode 100644 index 000000000..1e0cc94a8 --- /dev/null +++ b/x/perpetual/keeper/mtp_leverage.go @@ -0,0 +1,31 @@ +package keeper + +import ( + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/elys-network/elys/x/perpetual/types" +) + +// GetEffectiveLeverage = custody / (custody - liabilities), has to be dimensionless +func (k Keeper) GetEffectiveLeverage(ctx sdk.Context, mtp types.MTP) (math.LegacyDec, error) { + + // using swaps will have fees but this is just user facing value for a query + tradingAssetPrice, err := k.GetAssetPrice(ctx, mtp.TradingAsset) + if err != nil { + return math.LegacyDec{}, err + } + + if mtp.Position == types.Position_LONG { + // custody is trading asset, liabilities are in usdc + custodyInLiabilitiesAsset := mtp.Custody.ToLegacyDec().Mul(tradingAssetPrice) + denominator := custodyInLiabilitiesAsset.Sub(mtp.Liabilities.ToLegacyDec()) + effectiveLeverage := custodyInLiabilitiesAsset.Quo(denominator) + return effectiveLeverage, nil + } else { + // custody is usdc, liabilities are in trading asset + liabilitiesInCustodyAsset := mtp.Liabilities.ToLegacyDec().Mul(tradingAssetPrice) + denominator := mtp.Custody.ToLegacyDec().Sub(liabilitiesInCustodyAsset) + effectiveLeverage := mtp.Custody.ToLegacyDec().Quo(denominator) + return effectiveLeverage, nil + } +} diff --git a/x/perpetual/keeper/mtp_leverage_test.go b/x/perpetual/keeper/mtp_leverage_test.go new file mode 100644 index 000000000..2a0da40b4 --- /dev/null +++ b/x/perpetual/keeper/mtp_leverage_test.go @@ -0,0 +1,73 @@ +package keeper_test + +import ( + "cosmossdk.io/math" + ptypes "github.com/elys-network/elys/x/parameter/types" + "github.com/elys-network/elys/x/perpetual/types" +) + +func (suite *PerpetualKeeperTestSuite) TestGetEffectiveLeverage() { + var mtp types.MTP + mtp.TradingAsset = ptypes.ATOM + testCases := []struct { + name string + expectErrMsg string + result math.LegacyDec + prerequisiteFunction func() + }{ + { + "price not set", + "asset price uatom not found", + math.LegacyDec{}, + func() { + }, + }, + { + "LONG", + "", + math.LegacyMustNewDecFromStr("1.176470588235294118"), + func() { + suite.SetupCoinPrices() + mtp.Position = types.Position_LONG + mtp.Custody = math.NewInt(100) + mtp.Liabilities = math.NewInt(75) + }, + }, + { + "SHORT", + "", + math.LegacyMustNewDecFromStr("2.666666666666666667"), + func() { + suite.SetupCoinPrices() + mtp.Position = types.Position_SHORT + mtp.Custody = math.NewInt(600) + mtp.Liabilities = math.NewInt(75) + }, + }, + { + "SHORT, bot should liquidate before leverage goes negative", + "", + math.LegacyMustNewDecFromStr("-0.363636363636363636"), + func() { + suite.SetupCoinPrices() + mtp.Position = types.Position_SHORT + mtp.Custody = math.NewInt(100) + mtp.Liabilities = math.NewInt(75) + }, + }, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + tc.prerequisiteFunction() + effectiveLeverage, err := suite.app.PerpetualKeeper.GetEffectiveLeverage(suite.ctx, mtp) + suite.Require().Equal(tc.result, effectiveLeverage) + if tc.expectErrMsg != "" { + suite.Require().Error(err) + suite.Require().Contains(err.Error(), tc.expectErrMsg) + } else { + suite.Require().NoError(err) + } + }) + } +} diff --git a/x/perpetual/keeper/mtp_open_price.go b/x/perpetual/keeper/mtp_open_price.go index 0b14b00a2..ddbaaa710 100644 --- a/x/perpetual/keeper/mtp_open_price.go +++ b/x/perpetual/keeper/mtp_open_price.go @@ -1,56 +1,14 @@ package keeper import ( - "fmt" - - "cosmossdk.io/errors" - "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - ammtypes "github.com/elys-network/elys/x/amm/types" "github.com/elys-network/elys/x/perpetual/types" ) -func (k Keeper) CalOpenPrice(ctx sdk.Context, mtp *types.MTP, ammPool ammtypes.Pool, baseCurrency string) (math.LegacyDec, error) { - collateralAmountInBaseCurrency := mtp.Collateral - if mtp.CollateralAsset != baseCurrency && !mtp.Collateral.IsZero() { - C, _, err := k.EstimateSwapGivenIn(ctx, sdk.NewCoin(mtp.CollateralAsset, mtp.Collateral), baseCurrency, ammPool) - if err != nil { - return math.LegacyDec{}, errors.Wrap(err, fmt.Sprintf("error estimating swap: %s %s", mtp.CollateralAsset, mtp.Collateral)) - } - collateralAmountInBaseCurrency = C - } - - liabilitiesAmountInBaseCurrency := mtp.Liabilities - if mtp.LiabilitiesAsset != baseCurrency && !mtp.Liabilities.IsZero() { - L, _, err := k.EstimateSwapGivenIn(ctx, sdk.NewCoin(mtp.LiabilitiesAsset, mtp.Liabilities), baseCurrency, ammPool) - if err != nil { - return math.LegacyDec{}, errors.Wrap(err, fmt.Sprintf("error estimating swap: %s %s", mtp.LiabilitiesAsset, mtp.Liabilities)) - } - liabilitiesAmountInBaseCurrency = L - } - - custodyAmountInTradingAsset := mtp.Custody - if mtp.CustodyAsset != mtp.TradingAsset && !mtp.Custody.IsZero() { - C, _, err := k.EstimateSwapGivenIn(ctx, sdk.NewCoin(mtp.CustodyAsset, mtp.Custody), mtp.TradingAsset, ammPool) - if err != nil { - return math.LegacyDec{}, errors.Wrap(err, fmt.Sprintf("error estimating swap: %s %s", mtp.CustodyAsset, mtp.Custody)) - } - custodyAmountInTradingAsset = C - } - - // open price = (collateral + liabilities) / custody - openPrice := collateralAmountInBaseCurrency.ToLegacyDec().Add(liabilitiesAmountInBaseCurrency.ToLegacyDec()).Quo(custodyAmountInTradingAsset.ToLegacyDec()) - return openPrice, nil -} - -func (k Keeper) UpdateOpenPrice(ctx sdk.Context, mtp *types.MTP, ammPool ammtypes.Pool, baseCurrency string) error { - openPrice, err := k.CalOpenPrice(ctx, mtp, ammPool, baseCurrency) - if err != nil { - return err - } - mtp.OpenPrice = openPrice +func (k Keeper) UpdateOpenPrice(ctx sdk.Context, mtp *types.MTP) error { + mtp.GetAndSetOpenPrice() - err = k.SetMTP(ctx, mtp) + err := k.SetMTP(ctx, mtp) if err != nil { return err } diff --git a/x/perpetual/keeper/open.go b/x/perpetual/keeper/open.go index 5d044dc32..2ce63ab06 100644 --- a/x/perpetual/keeper/open.go +++ b/x/perpetual/keeper/open.go @@ -98,7 +98,7 @@ func (k Keeper) Open(ctx sdk.Context, msg *types.MsgOpen, isBroker bool) (*types } // calc and update open price - err = k.UpdateOpenPrice(ctx, mtp, ammPool, baseCurrency) + err = k.UpdateOpenPrice(ctx, mtp) if err != nil { return nil, err } diff --git a/x/perpetual/keeper/query_open_estimation.go b/x/perpetual/keeper/query_open_estimation.go index ff21e141f..10b8cc5ca 100644 --- a/x/perpetual/keeper/query_open_estimation.go +++ b/x/perpetual/keeper/query_open_estimation.go @@ -99,7 +99,6 @@ func (k Keeper) HandleOpenEstimation(ctx sdk.Context, req *types.QueryOpenEstima custodyAmount := leveragedAmount slippage := math.LegacyZeroDec() mtp.Collateral = req.Collateral.Amount - executionPrice := math.LegacyZeroDec() eta := req.Leverage.Sub(math.LegacyOneDec()) if req.Position == types.Position_LONG { //getting custody @@ -111,8 +110,6 @@ func (k Keeper) HandleOpenEstimation(ctx sdk.Context, req *types.QueryOpenEstima } mtp.Liabilities = req.Collateral.Amount.ToLegacyDec().Mul(eta).TruncateInt() - // executionPrice = leveragedAmount / Custody - executionPrice = leveragedAmount.ToLegacyDec().Quo(custodyAmount.ToLegacyDec()) } mtp.Custody = custodyAmount @@ -123,9 +120,6 @@ func (k Keeper) HandleOpenEstimation(ctx sdk.Context, req *types.QueryOpenEstima if err != nil { return nil, err } - - // executionPrice = (Liabilities in base currency) / Custody - executionPrice = mtp.Liabilities.ToLegacyDec().Quo(amountIn.ToLegacyDec()) } } @@ -133,21 +127,18 @@ func (k Keeper) HandleOpenEstimation(ctx sdk.Context, req *types.QueryOpenEstima if req.Position == types.Position_SHORT { mtp.Custody = custodyAmount // Collateral will be in base currency - custodyTokenIn := sdk.NewCoin(baseCurrency, mtp.Custody) - mtp.Liabilities, slippage, err = k.EstimateSwapGivenOut(ctx, custodyTokenIn, mtp.LiabilitiesAsset, ammPool) + amountOut := req.Collateral.Amount.ToLegacyDec().Mul(eta).TruncateInt() + tokenOut := sdk.NewCoin(baseCurrency, amountOut) + mtp.Liabilities, slippage, err = k.EstimateSwapGivenOut(ctx, tokenOut, mtp.LiabilitiesAsset, ammPool) if err != nil { return nil, err } - - executionPrice = mtp.Custody.ToLegacyDec().Quo(mtp.Liabilities.ToLegacyDec()) } mtp.TakeProfitCustody = types.CalcMTPTakeProfitCustody(*mtp) mtp.TakeProfitLiabilities, err = k.CalcMTPTakeProfitLiability(ctx, mtp, baseCurrency) mtp.TakeProfitPrice = req.TakeProfitPrice - mtp.OpenPrice, err = k.CalOpenPrice(ctx, mtp, ammPool, baseCurrency) - if err != nil { - return nil, err - } + mtp.GetAndSetOpenPrice() + executionPrice := mtp.OpenPrice k.UpdateMTPBorrowInterestUnpaidLiability(ctx, mtp) @@ -184,11 +175,13 @@ func (k Keeper) HandleOpenEstimation(ctx sdk.Context, req *types.QueryOpenEstima OpenPrice: mtp.OpenPrice, TakeProfitPrice: req.TakeProfitPrice, LiquidationPrice: liquidationPrice, - EstimatedPnl: sdk.NewCoin(baseCurrency, estimatedPnLAmount), + EstimatedPnl: sdk.Coin{baseCurrency, estimatedPnLAmount}, AvailableLiquidity: availableLiquidity, Slippage: slippage, PriceImpact: priceImpact, BorrowInterestRate: borrowInterestRate, FundingRate: fundingRate, + Custody: sdk.NewCoin(mtp.CustodyAsset, mtp.Custody), + Liabilities: sdk.NewCoin(mtp.LiabilitiesAsset, mtp.Liabilities), }, nil } diff --git a/x/perpetual/keeper/query_open_estimation_test.go b/x/perpetual/keeper/query_open_estimation_test.go index e0d03aca0..d9ffded41 100644 --- a/x/perpetual/keeper/query_open_estimation_test.go +++ b/x/perpetual/keeper/query_open_estimation_test.go @@ -110,7 +110,7 @@ func TestOpenEstimation_Long5XAtom100Usdc(t *testing.T) { Position: types.Position_LONG, Leverage: sdk.MustNewDecFromStr("5.0"), TradingAsset: ptypes.ATOM, - Collateral: sdk.NewCoin(ptypes.BaseCurrency, sdk.NewInt(100000000)), + Collateral: sdk.NewCoin(ptypes.BaseCurrency, sdk.NewInt(100_000_000)), Discount: sdk.MustNewDecFromStr("0.0"), TakeProfitPrice: tradingAssetPrice.MulInt64(3), }) @@ -122,16 +122,18 @@ func TestOpenEstimation_Long5XAtom100Usdc(t *testing.T) { TradingAsset: ptypes.ATOM, Collateral: sdk.NewCoin(ptypes.BaseCurrency, sdk.NewInt(100_000_000)), InterestAmount: sdk.NewCoin(ptypes.BaseCurrency, math.NewInt(0)), // Need to increase block height to have non zero value - PositionSize: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(99835589)), + PositionSize: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(99_835_589)), OpenPrice: sdk.MustNewDecFromStr("5.008234087746004083"), TakeProfitPrice: tradingAssetPrice.MulInt64(3), LiquidationPrice: sdk.MustNewDecFromStr("4.206916633706643430"), - EstimatedPnl: sdk.NewCoin(ptypes.BaseCurrency, sdk.NewInt(997533835)), + EstimatedPnl: sdk.NewCoin(ptypes.BaseCurrency, sdk.NewInt(997_533_835)), AvailableLiquidity: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(600000000000)), Slippage: sdk.MustNewDecFromStr("0.000644750000000000"), BorrowInterestRate: sdk.MustNewDecFromStr("0.000000000000000000"), FundingRate: sdk.MustNewDecFromStr("0.000000000000000000"), PriceImpact: sdk.MustNewDecFromStr("-0.001646817549200817"), + Custody: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(99_835_589)), + Liabilities: sdk.NewCoin(ptypes.BaseCurrency, sdk.NewInt(400_000_000)), }, res) } @@ -234,7 +236,7 @@ func TestOpenEstimation_Long5XAtom10Atom(t *testing.T) { Position: types.Position_LONG, Leverage: sdk.MustNewDecFromStr("5.0"), TradingAsset: ptypes.ATOM, - Collateral: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(10000000)), + Collateral: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(10_000_000)), Discount: sdk.MustNewDecFromStr("0.0"), TakeProfitPrice: tradingAssetPrice.MulInt64(3), }) @@ -245,7 +247,7 @@ func TestOpenEstimation_Long5XAtom10Atom(t *testing.T) { TradingAsset: ptypes.ATOM, Collateral: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(10_000_000)), PositionSize: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(50_000_000)), - OpenPrice: sdk.MustNewDecFromStr("5.005824760000000000"), + OpenPrice: sdk.MustNewDecFromStr("5.008765025000000000"), TakeProfitPrice: tradingAssetPrice.MulInt64(3), LiquidationPrice: sdk.MustNewDecFromStr("4.207362621000000000"), EstimatedPnl: sdk.NewCoin(ptypes.BaseCurrency, sdk.NewInt(399649399)), @@ -255,6 +257,8 @@ func TestOpenEstimation_Long5XAtom10Atom(t *testing.T) { BorrowInterestRate: sdk.MustNewDecFromStr("0.000000000000000000"), FundingRate: sdk.MustNewDecFromStr("0.000000000000000000"), PriceImpact: sdk.MustNewDecFromStr("-0.001753005000000000"), + Custody: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(50_000_000)), + Liabilities: sdk.NewCoin(ptypes.BaseCurrency, sdk.NewInt(200_350_601)), }, res) } @@ -382,6 +386,8 @@ func TestOpenEstimation_Long10XAtom1000Usdc(t *testing.T) { BorrowInterestRate: sdk.MustNewDecFromStr("0.000000000000000000"), FundingRate: sdk.MustNewDecFromStr("0.000000000000000000"), PriceImpact: sdk.MustNewDecFromStr("-0.013723200471188736"), + Custody: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(2_247_067_372)), + Liabilities: sdk.NewCoin(ptypes.BaseCurrency, sdk.NewInt(9000000000)), }, res) } @@ -509,17 +515,19 @@ func TestOpenEstimation_Short5XAtom10Usdc(t *testing.T) { Leverage: sdk.MustNewDecFromStr("5.0"), TradingAsset: ptypes.ATOM, Collateral: sdk.NewCoin(ptypes.BaseCurrency, sdk.NewInt(100_000_000)), - PositionSize: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(100288415)), - OpenPrice: sdk.MustNewDecFromStr("6.017276740861142217"), + PositionSize: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(80200521)), + OpenPrice: sdk.MustNewDecFromStr("4.987498771984286735"), TakeProfitPrice: tradingAssetPrice.QuoInt64(3), - LiquidationPrice: sdk.MustNewDecFromStr("4.748210211423484861"), - EstimatedPnl: sdk.Coin{ptypes.BaseCurrency, sdk.NewInt(232852642)}, + LiquidationPrice: sdk.MustNewDecFromStr("5.937498538076531828"), + EstimatedPnl: sdk.Coin{ptypes.BaseCurrency, sdk.NewInt(266332466)}, InterestAmount: sdk.NewCoin(ptypes.ATOM, math.NewInt(0)), // Need to increase block height to have non zero value AvailableLiquidity: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(10000000000)), - Slippage: sdk.MustNewDecFromStr("0.001877737468832010"), + Slippage: sdk.MustNewDecFromStr("0.001501753843447532"), BorrowInterestRate: sdk.MustNewDecFromStr("0.000000000000000000"), FundingRate: sdk.MustNewDecFromStr("0.000000000000000000"), - PriceImpact: sdk.MustNewDecFromStr("0.002875855601068179"), + PriceImpact: sdk.MustNewDecFromStr("0.002500245603142653"), + Custody: sdk.NewCoin(ptypes.BaseCurrency, sdk.NewInt(500000000)), + Liabilities: sdk.NewCoin(ptypes.ATOM, sdk.NewInt(80_200_521)), } require.Equal(t, expectedRes, res) } diff --git a/x/perpetual/keeper/updated_leverage.go b/x/perpetual/keeper/updated_leverage.go deleted file mode 100644 index f7e31cc69..000000000 --- a/x/perpetual/keeper/updated_leverage.go +++ /dev/null @@ -1,37 +0,0 @@ -package keeper - -import ( - errorsmod "cosmossdk.io/errors" - sdk "github.com/cosmos/cosmos-sdk/types" - assetprofiletypes "github.com/elys-network/elys/x/assetprofile/types" - ptypes "github.com/elys-network/elys/x/parameter/types" - "github.com/elys-network/elys/x/perpetual/types" -) - -func (k Keeper) UpdatedLeverage(ctx sdk.Context, mtp types.MTP) (sdk.Dec, error) { - - entry, found := k.assetProfileKeeper.GetEntry(ctx, ptypes.BaseCurrency) - if !found { - return sdk.ZeroDec(), errorsmod.Wrapf(assetprofiletypes.ErrAssetProfileNotFound, "asset %s not found", ptypes.BaseCurrency) - } - baseCurrency := entry.Denom - - custodyInUsdc := mtp.Custody.ToLegacyDec() - if mtp.CustodyAsset != baseCurrency { - priceCustodyAsset := k.oracleKeeper.GetAssetPriceFromDenom(ctx, mtp.CustodyAsset) - custodyInUsdc = mtp.Custody.ToLegacyDec().Mul(priceCustodyAsset) - } - var denominator sdk.Dec - if mtp.LiabilitiesAsset != baseCurrency { - priceLiablitiesAsset := k.oracleKeeper.GetAssetPriceFromDenom(ctx, mtp.LiabilitiesAsset) - denominator = custodyInUsdc.Sub(mtp.Liabilities.ToLegacyDec().Mul(priceLiablitiesAsset)) - } else { - denominator = custodyInUsdc.Sub(mtp.Liabilities.ToLegacyDec()) - } - if denominator.IsZero() { - return sdk.ZeroDec(), nil - } - effectiveLeverage := custodyInUsdc.Quo(denominator) - - return effectiveLeverage, nil -} diff --git a/x/perpetual/migrations/v10_migration.go b/x/perpetual/migrations/v10_migration.go index f80d655b0..c63e55c07 100644 --- a/x/perpetual/migrations/v10_migration.go +++ b/x/perpetual/migrations/v10_migration.go @@ -2,19 +2,8 @@ package migrations import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/elys-network/elys/x/perpetual/types" ) func (m Migrator) V10Migration(ctx sdk.Context) error { - m.keeper.NukeDB(ctx) - params := types.DefaultParams() - err := m.keeper.SetParams(ctx, ¶ms) - if err != nil { - return err - } - - // using previous values - params.IncrementalBorrowInterestPaymentFundAddress = "elys1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnrec2l" - params.ForceCloseFundAddress = "elys1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnrec2l" return nil } diff --git a/x/perpetual/types/query.pb.go b/x/perpetual/types/query.pb.go index bee061a04..ae7088373 100644 --- a/x/perpetual/types/query.pb.go +++ b/x/perpetual/types/query.pb.go @@ -1170,6 +1170,8 @@ type QueryOpenEstimationResponse struct { BorrowInterestRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,13,opt,name=borrow_interest_rate,json=borrowInterestRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"borrow_interest_rate"` FundingRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,14,opt,name=funding_rate,json=fundingRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"funding_rate"` PriceImpact github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,15,opt,name=price_impact,json=priceImpact,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"price_impact"` + Custody types.Coin `protobuf:"bytes,16,opt,name=custody,proto3" json:"custody"` + Liabilities types.Coin `protobuf:"bytes,17,opt,name=liabilities,proto3" json:"liabilities"` } func (m *QueryOpenEstimationResponse) Reset() { *m = QueryOpenEstimationResponse{} } @@ -1254,6 +1256,20 @@ func (m *QueryOpenEstimationResponse) GetAvailableLiquidity() types.Coin { return types.Coin{} } +func (m *QueryOpenEstimationResponse) GetCustody() types.Coin { + if m != nil { + return m.Custody + } + return types.Coin{} +} + +func (m *QueryOpenEstimationResponse) GetLiabilities() types.Coin { + if m != nil { + return m.Liabilities + } + return types.Coin{} +} + type QueryGetAllToPayRequest struct { } @@ -1595,144 +1611,145 @@ func init() { func init() { proto.RegisterFile("elys/perpetual/query.proto", fileDescriptor_9a2c961615c1b7fe) } var fileDescriptor_9a2c961615c1b7fe = []byte{ - // 2180 bytes of a gzipped FileDescriptorProto + // 2205 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5a, 0x4f, 0x6f, 0x1b, 0xc7, - 0x15, 0xf7, 0x8a, 0x14, 0x6d, 0x3e, 0x4a, 0xa4, 0x34, 0x56, 0x6c, 0x8a, 0x52, 0x68, 0x77, 0x2d, - 0xff, 0x49, 0x64, 0x91, 0x95, 0x62, 0x24, 0xe8, 0x3f, 0x04, 0x92, 0x5c, 0x5b, 0x72, 0xac, 0x94, - 0xa1, 0x5d, 0x24, 0x50, 0x91, 0x6e, 0x47, 0xe4, 0x88, 0x5a, 0x68, 0xb9, 0xb3, 0xde, 0x1d, 0x5a, - 0xa6, 0x0d, 0x05, 0x41, 0xd1, 0x4b, 0x0f, 0x2d, 0x5a, 0x24, 0x45, 0x8e, 0xfd, 0x04, 0x3d, 0xf4, - 0x94, 0x0f, 0xd0, 0x1e, 0xd2, 0x5b, 0xd0, 0x5e, 0x8a, 0x1e, 0x82, 0xc2, 0xee, 0x07, 0x29, 0xe6, - 0xcf, 0x2e, 0x77, 0xb9, 0xa4, 0x48, 0xaf, 0x55, 0xe4, 0xd0, 0x93, 0xc4, 0x9d, 0xf7, 0x7e, 0xef, - 0x37, 0xef, 0xbd, 0x79, 0xf3, 0xf6, 0x91, 0x50, 0x22, 0x56, 0xd7, 0xab, 0x3a, 0xc4, 0x75, 0x08, - 0xeb, 0x60, 0xab, 0xfa, 0xa8, 0x43, 0xdc, 0x6e, 0xc5, 0x71, 0x29, 0xa3, 0x28, 0xcf, 0xd7, 0x2a, - 0xc1, 0x5a, 0x69, 0xae, 0x45, 0x5b, 0x54, 0x2c, 0x55, 0xf9, 0x7f, 0x52, 0xaa, 0xb4, 0xd8, 0xa2, - 0xb4, 0x65, 0x91, 0x2a, 0x76, 0xcc, 0x2a, 0xb6, 0x6d, 0xca, 0x30, 0x33, 0xa9, 0xed, 0xa9, 0xd5, - 0x37, 0x1b, 0xd4, 0x6b, 0x53, 0xaf, 0xba, 0x87, 0x3d, 0x22, 0xc1, 0xab, 0x8f, 0x57, 0xf7, 0x08, - 0xc3, 0xab, 0x55, 0x07, 0xb7, 0x4c, 0x5b, 0x08, 0x2b, 0xd9, 0x85, 0x3e, 0x2e, 0x0e, 0x76, 0x71, - 0xdb, 0x07, 0xea, 0x27, 0xca, 0xba, 0x0e, 0xf1, 0xd7, 0xe6, 0xfb, 0x15, 0x29, 0xb5, 0xd4, 0x52, - 0x39, 0x6c, 0xdf, 0xb7, 0xdc, 0xa0, 0xa6, 0xb2, 0xa9, 0xff, 0x2d, 0x0d, 0xe9, 0x3b, 0x84, 0x78, - 0xa8, 0x05, 0x45, 0x46, 0x19, 0xb6, 0x8c, 0x7d, 0x42, 0x3c, 0x83, 0x8b, 0x1b, 0x8d, 0x8e, 0xeb, - 0x12, 0xbb, 0xd1, 0x2d, 0x6a, 0x97, 0xb5, 0x1b, 0xd9, 0x8d, 0xca, 0x57, 0xdf, 0x5c, 0x3a, 0xf3, - 0xaf, 0x6f, 0x2e, 0x5d, 0x6b, 0x99, 0xec, 0xa0, 0xb3, 0x57, 0x69, 0xd0, 0x76, 0x55, 0xa1, 0xcb, - 0x3f, 0x2b, 0x5e, 0xf3, 0x50, 0xf1, 0xda, 0xb6, 0x59, 0xfd, 0x35, 0x81, 0xc7, 0xc1, 0x37, 0xb0, - 0x47, 0x36, 0x15, 0x18, 0xfa, 0x04, 0x96, 0xf6, 0xa8, 0xeb, 0xd2, 0x23, 0xc3, 0xb4, 0x19, 0x71, - 0x89, 0xc7, 0xa4, 0x49, 0xcb, 0xc4, 0x7b, 0xa6, 0x65, 0xb2, 0xae, 0x81, 0x3d, 0x8f, 0xb0, 0xe2, - 0x44, 0x22, 0xa3, 0x97, 0x25, 0xf6, 0xb6, 0x82, 0xe6, 0xd6, 0xef, 0xfb, 0xc0, 0xeb, 0x1c, 0x17, - 0x3d, 0x05, 0x7d, 0xa0, 0xfd, 0xe8, 0x96, 0x53, 0x89, 0xac, 0x97, 0xe3, 0xd6, 0x23, 0x7b, 0xa7, - 0xb0, 0xb8, 0xdf, 0xb1, 0x9b, 0xa6, 0xdd, 0xf2, 0xf7, 0xfc, 0xa8, 0x63, 0x36, 0x7b, 0x7b, 0x4e, - 0x27, 0xb2, 0x3a, 0xaf, 0x30, 0xe5, 0x66, 0x15, 0xa2, 0xdc, 0xec, 0x21, 0x94, 0x22, 0x06, 0xa3, - 0x9b, 0x9c, 0x4c, 0x64, 0xee, 0x62, 0xc8, 0x5c, 0x78, 0x77, 0xfa, 0x9f, 0x52, 0x90, 0xdb, 0x61, - 0xce, 0xba, 0xdd, 0xac, 0xb9, 0x66, 0x83, 0xa0, 0xab, 0x90, 0x6a, 0x33, 0x47, 0x64, 0x4f, 0x6e, - 0xed, 0x7c, 0x25, 0x7a, 0x9a, 0x2a, 0x3b, 0x0f, 0x6b, 0x75, 0xbe, 0x8e, 0x7e, 0x0e, 0xe7, 0x99, - 0x8b, 0x05, 0x47, 0xe1, 0x05, 0xc3, 0xe1, 0xda, 0x09, 0xe2, 0x7f, 0x9b, 0x34, 0xea, 0xb3, 0x0a, - 0x4a, 0x6c, 0x5f, 0xd2, 0x58, 0x85, 0x94, 0x63, 0x5b, 0x22, 0xa2, 0xb9, 0xb5, 0xf9, 0x8a, 0x54, - 0xab, 0x70, 0x4f, 0x54, 0xd4, 0x81, 0xa8, 0x6c, 0x52, 0xd3, 0xde, 0x48, 0x73, 0x53, 0x75, 0x2e, - 0x8b, 0x3e, 0x06, 0x44, 0xf6, 0xf7, 0x49, 0x83, 0x99, 0x8f, 0x89, 0x61, 0x91, 0xc7, 0xc4, 0xc5, - 0x2d, 0x92, 0x20, 0x3a, 0x82, 0x51, 0x80, 0x74, 0x5f, 0x01, 0xa1, 0x9f, 0xc1, 0xac, 0x8c, 0xbc, - 0x38, 0xfd, 0x6a, 0xbf, 0x93, 0x89, 0xd0, 0x67, 0x42, 0x40, 0x72, 0xbb, 0x37, 0x20, 0xcd, 0x43, - 0x5d, 0xcc, 0x88, 0xfd, 0xce, 0xf5, 0xbb, 0x9d, 0x47, 0xad, 0x2e, 0x24, 0xf4, 0x02, 0x4c, 0xd7, - 0x44, 0x89, 0xa9, 0x93, 0x47, 0x1d, 0xe2, 0x31, 0xfd, 0x0e, 0xe4, 0xfd, 0x07, 0x9e, 0x43, 0x6d, - 0x8f, 0xa0, 0x5b, 0x90, 0x91, 0x55, 0x48, 0x45, 0xf1, 0x42, 0x3f, 0x9c, 0x94, 0x57, 0xbe, 0x53, - 0xb2, 0xfa, 0x2e, 0xcc, 0xd4, 0xa8, 0x67, 0x8a, 0x3a, 0xa8, 0xb0, 0xd1, 0x1d, 0x80, 0x5e, 0xc1, - 0x53, 0x68, 0xd7, 0x22, 0xc1, 0x90, 0xa5, 0xd7, 0x0f, 0x49, 0x0d, 0xb7, 0x88, 0xd2, 0xad, 0x87, - 0x34, 0xf5, 0xdf, 0x68, 0x30, 0x1b, 0x02, 0x57, 0x3c, 0xab, 0x90, 0x6e, 0x33, 0x87, 0xb3, 0x4c, - 0xdd, 0xc8, 0xad, 0x2d, 0xc4, 0x72, 0xad, 0x97, 0x95, 0x75, 0x21, 0x88, 0xee, 0x46, 0xe8, 0x4c, - 0x08, 0x3a, 0xd7, 0x47, 0xd2, 0x91, 0xd6, 0x22, 0x7c, 0x3e, 0xd5, 0xe0, 0x42, 0xc0, 0x67, 0xa3, - 0x5b, 0xa3, 0xd4, 0xf2, 0xb7, 0x5c, 0x86, 0x1c, 0x6e, 0xb7, 0x0d, 0x5e, 0x8d, 0x0d, 0xb3, 0x29, - 0xf6, 0x9c, 0xae, 0x67, 0x71, 0xbb, 0xcd, 0x85, 0xb6, 0x9b, 0x7d, 0x2e, 0x99, 0x48, 0xec, 0x92, - 0xcf, 0x34, 0xb8, 0x18, 0xa3, 0xf0, 0xad, 0x3b, 0xa6, 0x00, 0xd3, 0x0f, 0x18, 0x66, 0x9d, 0x20, - 0xbb, 0x9a, 0x90, 0xf7, 0x1f, 0x28, 0x72, 0x4b, 0x90, 0xa7, 0x0e, 0xb1, 0x8d, 0x36, 0x73, 0x8c, - 0x06, 0xed, 0xd8, 0x4c, 0xf9, 0x68, 0x8a, 0x3f, 0xdd, 0x61, 0xce, 0x26, 0x7f, 0x86, 0x6e, 0x02, - 0xb2, 0xcc, 0x7d, 0xc2, 0xcc, 0x36, 0x09, 0x49, 0x4e, 0x08, 0xc9, 0x19, 0x7f, 0xc5, 0x97, 0xd6, - 0x3f, 0x81, 0x52, 0xe0, 0x8b, 0x3b, 0xd4, 0x5d, 0x6f, 0x36, 0x5d, 0xe2, 0x05, 0x59, 0x58, 0x84, - 0xb3, 0x58, 0x3e, 0x91, 0x97, 0x5a, 0xdd, 0xff, 0x78, 0x6a, 0xc1, 0xf8, 0x42, 0x83, 0x85, 0x81, - 0x04, 0xbe, 0xf5, 0x80, 0xec, 0xc2, 0xcc, 0x87, 0x07, 0x26, 0x23, 0x96, 0xe9, 0xb1, 0xd3, 0x3e, - 0x95, 0x4f, 0x61, 0x36, 0x84, 0xad, 0xb6, 0xba, 0x08, 0xd9, 0x23, 0xff, 0xa1, 0xd8, 0x6f, 0xb6, - 0xde, 0x7b, 0x70, 0x7a, 0xfb, 0xfa, 0x2e, 0xcc, 0x6d, 0x7b, 0x81, 0x75, 0xd2, 0x1c, 0x19, 0x6b, - 0xfd, 0x23, 0x78, 0xad, 0x4f, 0x43, 0x31, 0x1e, 0x9e, 0x1e, 0x57, 0x21, 0x6f, 0x7a, 0xc6, 0x51, - 0x4f, 0x47, 0x30, 0x3e, 0x57, 0x9f, 0x36, 0xc3, 0x40, 0xfa, 0x32, 0x9c, 0xff, 0x80, 0xb3, 0xbe, - 0x4b, 0x58, 0xb8, 0x12, 0xcc, 0xc1, 0xa4, 0x69, 0x37, 0xc9, 0x13, 0x95, 0xdf, 0xf2, 0x83, 0xfe, - 0x3e, 0xcc, 0x45, 0x85, 0x15, 0x8b, 0xb7, 0x21, 0xcd, 0x6b, 0x86, 0x0a, 0xc7, 0x62, 0xac, 0xe4, - 0x86, 0x64, 0x55, 0xe1, 0x15, 0xf2, 0xfa, 0xc7, 0xca, 0xf8, 0xba, 0x65, 0x85, 0x8d, 0x9f, 0x56, - 0x8c, 0xbf, 0xd0, 0x14, 0xdf, 0x00, 0x3f, 0xc6, 0x37, 0xf5, 0x32, 0x7c, 0x4f, 0x2f, 0x03, 0xde, - 0x06, 0xe0, 0xdd, 0xc4, 0xc8, 0x33, 0x9e, 0x87, 0x09, 0xb3, 0xa9, 0x2a, 0xc7, 0x84, 0xd9, 0xd4, - 0x7f, 0x08, 0x39, 0xa1, 0xa7, 0xf6, 0xb1, 0x12, 0xee, 0x57, 0x4e, 0x3c, 0x99, 0x5c, 0x4e, 0xff, - 0x6b, 0x0a, 0x4a, 0xc2, 0x1f, 0x3f, 0x71, 0x88, 0xfd, 0x63, 0x8f, 0x99, 0x6d, 0xc1, 0xc6, 0xa7, - 0x71, 0x0b, 0xce, 0x39, 0xaa, 0x0e, 0x08, 0xc8, 0xfc, 0x5a, 0x31, 0xee, 0x19, 0xb9, 0x5e, 0x0f, - 0x24, 0xd1, 0x3d, 0x38, 0x17, 0xf4, 0x1b, 0xc9, 0x3a, 0xa0, 0x40, 0x1f, 0x5d, 0x81, 0xe9, 0x48, - 0x63, 0x25, 0x9b, 0xda, 0xfa, 0x54, 0xb8, 0x45, 0x42, 0xef, 0x02, 0x34, 0xa8, 0x65, 0x61, 0x46, - 0x5c, 0x6c, 0x89, 0x16, 0x67, 0x8c, 0x26, 0x29, 0xa4, 0xc2, 0x19, 0x37, 0x4d, 0x4f, 0x16, 0xe5, - 0x64, 0x3d, 0x4c, 0xa0, 0x8f, 0x76, 0x61, 0x96, 0xe1, 0x43, 0x62, 0x38, 0x2e, 0xdd, 0x37, 0xfd, - 0x46, 0x30, 0x93, 0x08, 0xb4, 0xc0, 0x81, 0x6a, 0x02, 0x47, 0xf6, 0x45, 0x17, 0x20, 0xe3, 0x88, - 0x7b, 0xb7, 0x78, 0x56, 0x24, 0x80, 0xfa, 0xa4, 0xff, 0x3a, 0x0b, 0x0b, 0x03, 0xc3, 0x18, 0xb4, - 0x40, 0xff, 0x1f, 0x71, 0xdc, 0x82, 0x42, 0xf0, 0x42, 0x84, 0xdb, 0x41, 0x38, 0xc7, 0x40, 0xc9, - 0xfb, 0x7a, 0xeb, 0x42, 0x0d, 0xdd, 0x86, 0x69, 0xdf, 0x0f, 0x86, 0x67, 0x3e, 0x25, 0xaa, 0x15, - 0x1d, 0x89, 0x33, 0xe5, 0x6b, 0x3d, 0x30, 0x9f, 0x12, 0xb4, 0x03, 0x20, 0x9a, 0x03, 0x99, 0x04, - 0x67, 0x13, 0xf9, 0x30, 0xcb, 0x11, 0x64, 0xf8, 0x07, 0xa6, 0xd6, 0xb9, 0xd3, 0x49, 0xad, 0x81, - 0xfd, 0x7c, 0xf6, 0x94, 0xfa, 0xf9, 0xdb, 0x30, 0x4d, 0x64, 0x56, 0x92, 0xa6, 0xc1, 0x5f, 0x64, - 0x60, 0x4c, 0x6f, 0x06, 0x5a, 0x35, 0xdb, 0x42, 0x35, 0x38, 0x8f, 0x1f, 0x63, 0xd3, 0xc2, 0x7b, - 0x16, 0xe9, 0xbd, 0x76, 0x16, 0x73, 0xe3, 0x61, 0xa1, 0x40, 0x37, 0x78, 0xbf, 0xe4, 0x19, 0xee, - 0x59, 0xa6, 0xe3, 0xf0, 0x0c, 0x9f, 0x4a, 0x96, 0xe1, 0xbe, 0x3e, 0xfa, 0x05, 0xcc, 0xf5, 0xbf, - 0x93, 0xbb, 0x98, 0x91, 0xe2, 0x74, 0x22, 0x5c, 0x14, 0x7d, 0x0b, 0xaf, 0x63, 0x46, 0xd0, 0x07, - 0x30, 0xe5, 0xbf, 0x08, 0x0b, 0xe4, 0x7c, 0x22, 0xe4, 0x9c, 0xc2, 0xf0, 0x21, 0x45, 0xa4, 0x0d, - 0xb3, 0xed, 0xe0, 0x06, 0x2b, 0x16, 0x92, 0x41, 0x0a, 0x8c, 0x6d, 0x01, 0xa1, 0xcf, 0xc3, 0x45, - 0xbf, 0x23, 0x58, 0xb7, 0xac, 0x87, 0xb4, 0x86, 0xbb, 0x7e, 0xf7, 0xbc, 0x05, 0xc5, 0xf8, 0x92, - 0x2a, 0x51, 0x37, 0x21, 0xc3, 0xa8, 0xe1, 0xe0, 0xae, 0xba, 0x82, 0x5f, 0xeb, 0x2f, 0x50, 0x52, - 0x7c, 0x92, 0xf1, 0x3f, 0xfa, 0xe7, 0x19, 0x98, 0x8a, 0xdc, 0xdf, 0xa3, 0xdf, 0x53, 0x32, 0x07, - 0x04, 0x5b, 0xec, 0x20, 0x61, 0x25, 0x53, 0xda, 0x43, 0xa3, 0x9c, 0x3a, 0xb5, 0x28, 0x6f, 0xc3, - 0x8c, 0xd8, 0x85, 0x28, 0x93, 0x9e, 0x61, 0x51, 0xbb, 0x55, 0x4c, 0x0b, 0x97, 0xcc, 0x0f, 0xea, - 0x4a, 0x44, 0xe5, 0xf4, 0x8b, 0x98, 0xe3, 0x3f, 0xf0, 0xee, 0x53, 0xbb, 0x85, 0xde, 0x83, 0xd9, - 0x30, 0x94, 0x77, 0x40, 0x5d, 0x5e, 0x10, 0xc7, 0xc2, 0x2a, 0xf4, 0xb0, 0x1e, 0x70, 0x3d, 0xf4, - 0x21, 0xbc, 0x61, 0x61, 0x8f, 0x19, 0x07, 0xc4, 0x6c, 0x1d, 0x30, 0x63, 0x90, 0x17, 0x8c, 0x06, - 0x6d, 0x3b, 0x1d, 0xde, 0x58, 0xf2, 0x6a, 0x99, 0xaa, 0x2f, 0x71, 0x85, 0x2d, 0x21, 0xbf, 0x11, - 0xdb, 0xe8, 0xa6, 0x92, 0x8d, 0xa5, 0xf5, 0xd9, 0x57, 0x4f, 0xeb, 0x5d, 0x98, 0xb5, 0x09, 0x33, - 0x44, 0xed, 0xf5, 0x19, 0x26, 0x28, 0x94, 0xdb, 0x36, 0xab, 0x17, 0x6c, 0xc2, 0xf8, 0xad, 0xea, - 0x53, 0x47, 0xef, 0x41, 0x96, 0xc7, 0x44, 0x72, 0xcd, 0x26, 0xbc, 0x16, 0xa9, 0x22, 0xba, 0x03, - 0x20, 0xa2, 0x22, 0xd1, 0x20, 0xd9, 0x05, 0x21, 0x10, 0x38, 0x9c, 0xfe, 0xe9, 0x84, 0xea, 0x03, - 0x36, 0x2d, 0xea, 0x91, 0x78, 0x3f, 0x37, 0xbc, 0xad, 0xbc, 0x04, 0xb9, 0xe0, 0xbe, 0x0b, 0xfa, - 0x4b, 0xf0, 0x1f, 0x6d, 0x8b, 0x28, 0x35, 0x38, 0xa8, 0x7f, 0xaf, 0x26, 0x1b, 0x2e, 0xe6, 0x04, - 0x86, 0xba, 0x63, 0x1f, 0xc0, 0x34, 0xff, 0xc8, 0x03, 0x2f, 0xaf, 0x9b, 0x64, 0xc3, 0xa9, 0x29, - 0x05, 0x22, 0xae, 0x1a, 0xfd, 0xef, 0x19, 0x58, 0x1c, 0xec, 0x82, 0x57, 0xea, 0x85, 0x62, 0xfd, - 0xc0, 0x44, 0x92, 0x7e, 0x60, 0x1d, 0x72, 0xfe, 0x88, 0xd8, 0x24, 0xde, 0xb8, 0xe3, 0xbc, 0xb0, - 0x4e, 0xac, 0x62, 0xa7, 0x5f, 0xb9, 0x62, 0xff, 0x6f, 0x47, 0x79, 0x1f, 0xc1, 0x4c, 0x1b, 0x3f, - 0x31, 0x22, 0xb9, 0x93, 0x49, 0x94, 0x3b, 0xf9, 0x36, 0x7e, 0xb2, 0x19, 0x4a, 0x9f, 0x03, 0xb8, - 0xdc, 0x5f, 0x84, 0x3a, 0xb6, 0x83, 0xcd, 0x66, 0x6f, 0x0c, 0x2f, 0x6a, 0xc9, 0x18, 0x1e, 0x7e, - 0x3d, 0x5a, 0x87, 0x7f, 0x2a, 0x60, 0x82, 0x99, 0x3b, 0xba, 0x07, 0x33, 0x2e, 0x61, 0x1d, 0xd7, - 0x16, 0xed, 0xab, 0xdc, 0xc3, 0xb9, 0xf1, 0x90, 0x0b, 0x81, 0xa2, 0x62, 0xfd, 0x3e, 0x20, 0x07, - 0x77, 0x39, 0x50, 0x38, 0x13, 0xb2, 0xe3, 0xa1, 0xcd, 0x4a, 0xd5, 0xfb, 0xa1, 0x7c, 0x68, 0x40, - 0x59, 0x9a, 0x50, 0xc4, 0x0c, 0xcc, 0x8c, 0xe8, 0xa9, 0x1a, 0xb3, 0xd7, 0x2a, 0x49, 0x18, 0x49, - 0x73, 0x9d, 0x6d, 0x86, 0x0e, 0xd5, 0xda, 0x97, 0x05, 0x98, 0x14, 0x87, 0x0a, 0x31, 0xc8, 0xc8, - 0x71, 0x29, 0x7a, 0x7d, 0xf0, 0x18, 0x55, 0x95, 0x9a, 0x52, 0x79, 0xd8, 0xb2, 0x3c, 0x86, 0xfa, - 0xf2, 0x2f, 0xff, 0xf1, 0x9f, 0xcf, 0x26, 0xae, 0xa2, 0x2b, 0x55, 0x2e, 0xb7, 0x62, 0x13, 0x76, - 0x44, 0xdd, 0xc3, 0xea, 0xc0, 0xaf, 0x8f, 0xd0, 0xe7, 0x1a, 0x4c, 0x89, 0x09, 0x83, 0x9a, 0x49, - 0xa1, 0xcb, 0xc3, 0x8e, 0x6c, 0x60, 0xff, 0x3b, 0x27, 0x48, 0x28, 0x0a, 0xef, 0x0a, 0x0a, 0xdf, - 0x43, 0xef, 0x9c, 0x4c, 0xc1, 0xd7, 0xab, 0x3e, 0x0b, 0x7d, 0xdb, 0x75, 0x48, 0xba, 0xc7, 0xe8, - 0x4b, 0x0d, 0x50, 0x98, 0x96, 0x9c, 0x5b, 0xa2, 0x6b, 0x43, 0x4d, 0x47, 0x66, 0xab, 0xa5, 0xeb, - 0x23, 0xe5, 0x14, 0xd1, 0x9a, 0x20, 0x7a, 0x0f, 0x6d, 0x9d, 0x48, 0xb4, 0xcd, 0x1c, 0x6f, 0x65, - 0xaf, 0xbb, 0xc2, 0x2f, 0xee, 0xea, 0xb3, 0x50, 0x37, 0x74, 0x1c, 0x67, 0x7e, 0x04, 0xd9, 0xbb, - 0x84, 0xc9, 0x51, 0x66, 0x3c, 0x92, 0x91, 0x99, 0x67, 0x3c, 0x92, 0xd1, 0x09, 0xe8, 0x98, 0x91, - 0xf4, 0xa4, 0xad, 0xbf, 0x68, 0x70, 0x21, 0xec, 0xb2, 0xde, 0x74, 0x11, 0xbd, 0x39, 0xd4, 0x1d, - 0xb1, 0x19, 0x68, 0x69, 0x79, 0x2c, 0xd9, 0x97, 0x77, 0xdf, 0x3e, 0x75, 0x57, 0xd4, 0x95, 0x58, - 0x7d, 0xa6, 0xfe, 0x19, 0xe0, 0x3e, 0x95, 0x8f, 0xc1, 0xd4, 0x2c, 0x9e, 0x8f, 0xfd, 0x53, 0xca, - 0x78, 0x3e, 0xc6, 0x66, 0x8d, 0x63, 0xe6, 0x63, 0x30, 0xbf, 0x8b, 0xd3, 0xfa, 0xbd, 0x06, 0xd3, - 0x91, 0xa1, 0x20, 0x5a, 0xea, 0xb7, 0x3a, 0x68, 0xca, 0x58, 0xba, 0x3a, 0x42, 0x4a, 0xf1, 0x7b, - 0x4b, 0xf0, 0x5b, 0x41, 0xcb, 0x27, 0xf2, 0x33, 0xbd, 0x95, 0xd0, 0x88, 0x11, 0xfd, 0x4a, 0x83, - 0xb4, 0x38, 0x15, 0x57, 0xfa, 0x8d, 0x0c, 0x18, 0x32, 0x96, 0x96, 0x4e, 0x16, 0x52, 0x44, 0x56, - 0x05, 0x91, 0x65, 0xf4, 0xc6, 0x88, 0x83, 0xcb, 0xcf, 0x81, 0x18, 0x53, 0x1e, 0xa3, 0xdf, 0x6a, - 0x30, 0xc9, 0x31, 0xbc, 0x21, 0x3c, 0xa2, 0xf3, 0xc6, 0x21, 0x3c, 0xfa, 0x86, 0x86, 0xfa, 0xf7, - 0x05, 0x8f, 0x5b, 0x68, 0x6d, 0x0c, 0x1e, 0xf1, 0x13, 0x98, 0xda, 0x79, 0x58, 0x43, 0xa5, 0x41, - 0x5f, 0x29, 0x2a, 0x12, 0x0b, 0x03, 0xd7, 0x94, 0xed, 0x77, 0x84, 0xed, 0x55, 0x54, 0x1d, 0x95, - 0xd4, 0xe1, 0x3c, 0x36, 0x9b, 0xc7, 0xe8, 0x8f, 0x1a, 0xe4, 0xa3, 0x63, 0xa2, 0xf8, 0xc9, 0x1b, - 0x3e, 0x12, 0x8c, 0x9f, 0xbc, 0x13, 0xe6, 0x4e, 0xfa, 0x2d, 0x41, 0xb2, 0x82, 0x6e, 0x9e, 0x48, - 0x92, 0xb7, 0xe9, 0x2b, 0xa4, 0x47, 0xe7, 0x0f, 0x1a, 0xe4, 0x42, 0xaf, 0x88, 0xe8, 0xfa, 0xb0, - 0xa4, 0xe8, 0x7b, 0xbf, 0x2c, 0xdd, 0x18, 0x2d, 0xf8, 0x52, 0xa9, 0xdc, 0x22, 0xcc, 0xc0, 0x96, - 0x65, 0xc8, 0x17, 0x53, 0xf4, 0x67, 0x0d, 0x0a, 0x7d, 0x5d, 0x25, 0x1a, 0xec, 0x8e, 0xc1, 0xed, - 0x77, 0xe9, 0xe6, 0x78, 0xc2, 0x8a, 0xe3, 0xa6, 0xe0, 0xf8, 0x23, 0xf4, 0x83, 0x13, 0x39, 0x8a, - 0xc6, 0x2a, 0xe4, 0xbd, 0xea, 0xb3, 0x50, 0x1f, 0x7f, 0xbc, 0xb1, 0xf5, 0xd5, 0xf3, 0xb2, 0xf6, - 0xf5, 0xf3, 0xb2, 0xf6, 0xef, 0xe7, 0x65, 0xed, 0x77, 0x2f, 0xca, 0x67, 0xbe, 0x7e, 0x51, 0x3e, - 0xf3, 0xcf, 0x17, 0xe5, 0x33, 0xbb, 0x95, 0x50, 0xdb, 0x15, 0x37, 0xf0, 0xa4, 0xff, 0x67, 0x1a, - 0x7b, 0x19, 0xf1, 0x63, 0x8b, 0xb7, 0xfe, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x61, 0xad, 0x9f, 0x08, - 0x6e, 0x22, 0x00, 0x00, + 0x15, 0xf7, 0x8a, 0x14, 0x6d, 0x3e, 0x4a, 0xa4, 0x34, 0x96, 0x6d, 0x9a, 0x52, 0x68, 0x77, 0x2d, + 0xff, 0x49, 0x64, 0x91, 0x95, 0x62, 0x24, 0x48, 0xff, 0x20, 0x90, 0xe4, 0xda, 0x92, 0x63, 0xa5, + 0x0c, 0xed, 0x22, 0x81, 0x8a, 0x74, 0x3b, 0x22, 0x47, 0xd4, 0x42, 0xcb, 0x9d, 0xf5, 0xee, 0xd0, + 0x32, 0x6d, 0x28, 0x08, 0x8a, 0x02, 0x3d, 0xb5, 0x68, 0x91, 0x14, 0x39, 0xf6, 0x13, 0xf4, 0xd0, + 0x53, 0x3e, 0x40, 0x7b, 0x48, 0x6f, 0x41, 0x7b, 0x29, 0x7a, 0x08, 0x0a, 0xbb, 0x1f, 0xa4, 0x98, + 0x3f, 0xbb, 0xdc, 0xe5, 0x92, 0x22, 0xbd, 0x56, 0x91, 0x43, 0x4e, 0x12, 0x77, 0xde, 0xfb, 0xbd, + 0xdf, 0xbc, 0xf7, 0xe6, 0xcd, 0xdb, 0x47, 0x42, 0x89, 0x58, 0x5d, 0xaf, 0xea, 0x10, 0xd7, 0x21, + 0xac, 0x83, 0xad, 0xea, 0xa3, 0x0e, 0x71, 0xbb, 0x15, 0xc7, 0xa5, 0x8c, 0xa2, 0x3c, 0x5f, 0xab, + 0x04, 0x6b, 0xa5, 0xb9, 0x16, 0x6d, 0x51, 0xb1, 0x54, 0xe5, 0xff, 0x49, 0xa9, 0xd2, 0x42, 0x8b, + 0xd2, 0x96, 0x45, 0xaa, 0xd8, 0x31, 0xab, 0xd8, 0xb6, 0x29, 0xc3, 0xcc, 0xa4, 0xb6, 0xa7, 0x56, + 0xdf, 0x68, 0x50, 0xaf, 0x4d, 0xbd, 0xea, 0x2e, 0xf6, 0x88, 0x04, 0xaf, 0x3e, 0x5e, 0xd9, 0x25, + 0x0c, 0xaf, 0x54, 0x1d, 0xdc, 0x32, 0x6d, 0x21, 0xac, 0x64, 0xe7, 0xfb, 0xb8, 0x38, 0xd8, 0xc5, + 0x6d, 0x1f, 0xa8, 0x9f, 0x28, 0xeb, 0x3a, 0xc4, 0x5f, 0xbb, 0xd8, 0xaf, 0x48, 0xa9, 0xa5, 0x96, + 0xca, 0x61, 0xfb, 0xbe, 0xe5, 0x06, 0x35, 0x95, 0x4d, 0xfd, 0xef, 0x69, 0x48, 0xdf, 0x21, 0xc4, + 0x43, 0x2d, 0x28, 0x32, 0xca, 0xb0, 0x65, 0xec, 0x11, 0xe2, 0x19, 0x5c, 0xdc, 0x68, 0x74, 0x5c, + 0x97, 0xd8, 0x8d, 0x6e, 0x51, 0xbb, 0xac, 0xdd, 0xc8, 0xae, 0x57, 0xbe, 0xfa, 0xe6, 0xd2, 0xa9, + 0x7f, 0x7f, 0x73, 0xe9, 0x5a, 0xcb, 0x64, 0xfb, 0x9d, 0xdd, 0x4a, 0x83, 0xb6, 0xab, 0x0a, 0x5d, + 0xfe, 0x59, 0xf6, 0x9a, 0x07, 0x8a, 0xd7, 0x96, 0xcd, 0xea, 0xe7, 0x04, 0x1e, 0x07, 0x5f, 0xc7, + 0x1e, 0xd9, 0x50, 0x60, 0xe8, 0x13, 0x58, 0xdc, 0xa5, 0xae, 0x4b, 0x0f, 0x0d, 0xd3, 0x66, 0xc4, + 0x25, 0x1e, 0x93, 0x26, 0x2d, 0x13, 0xef, 0x9a, 0x96, 0xc9, 0xba, 0x06, 0xf6, 0x3c, 0xc2, 0x8a, + 0x13, 0x89, 0x8c, 0x5e, 0x96, 0xd8, 0x5b, 0x0a, 0x9a, 0x5b, 0xbf, 0xef, 0x03, 0xaf, 0x71, 0x5c, + 0xf4, 0x14, 0xf4, 0x81, 0xf6, 0xa3, 0x5b, 0x4e, 0x25, 0xb2, 0x5e, 0x8e, 0x5b, 0x8f, 0xec, 0x9d, + 0xc2, 0xc2, 0x5e, 0xc7, 0x6e, 0x9a, 0x76, 0xcb, 0xdf, 0xf3, 0xa3, 0x8e, 0xd9, 0xec, 0xed, 0x39, + 0x9d, 0xc8, 0xea, 0x45, 0x85, 0x29, 0x37, 0xab, 0x10, 0xe5, 0x66, 0x0f, 0xa0, 0x14, 0x31, 0x18, + 0xdd, 0xe4, 0x64, 0x22, 0x73, 0x17, 0x42, 0xe6, 0xc2, 0xbb, 0xd3, 0xff, 0x9c, 0x82, 0xdc, 0x36, + 0x73, 0xd6, 0xec, 0x66, 0xcd, 0x35, 0x1b, 0x04, 0x5d, 0x85, 0x54, 0x9b, 0x39, 0x22, 0x7b, 0x72, + 0xab, 0x67, 0x2b, 0xd1, 0xd3, 0x54, 0xd9, 0x7e, 0x58, 0xab, 0xf3, 0x75, 0xf4, 0x0b, 0x38, 0xcb, + 0x5c, 0x2c, 0x38, 0x0a, 0x2f, 0x18, 0x0e, 0xd7, 0x4e, 0x10, 0xff, 0xdb, 0xa4, 0x51, 0x9f, 0x55, + 0x50, 0x62, 0xfb, 0x92, 0xc6, 0x0a, 0xa4, 0x1c, 0xdb, 0x12, 0x11, 0xcd, 0xad, 0x5e, 0xac, 0x48, + 0xb5, 0x0a, 0xf7, 0x44, 0x45, 0x1d, 0x88, 0xca, 0x06, 0x35, 0xed, 0xf5, 0x34, 0x37, 0x55, 0xe7, + 0xb2, 0xe8, 0x63, 0x40, 0x64, 0x6f, 0x8f, 0x34, 0x98, 0xf9, 0x98, 0x18, 0x16, 0x79, 0x4c, 0x5c, + 0xdc, 0x22, 0x09, 0xa2, 0x23, 0x18, 0x05, 0x48, 0xf7, 0x15, 0x10, 0xfa, 0x39, 0xcc, 0xca, 0xc8, + 0x8b, 0xd3, 0xaf, 0xf6, 0x3b, 0x99, 0x08, 0x7d, 0x26, 0x04, 0x24, 0xb7, 0x7b, 0x03, 0xd2, 0x3c, + 0xd4, 0xc5, 0x8c, 0xd8, 0xef, 0x5c, 0xbf, 0xdb, 0x79, 0xd4, 0xea, 0x42, 0x42, 0x2f, 0xc0, 0x74, + 0x4d, 0x94, 0x98, 0x3a, 0x79, 0xd4, 0x21, 0x1e, 0xd3, 0xef, 0x40, 0xde, 0x7f, 0xe0, 0x39, 0xd4, + 0xf6, 0x08, 0xba, 0x05, 0x19, 0x59, 0x85, 0x54, 0x14, 0xcf, 0xf7, 0xc3, 0x49, 0x79, 0xe5, 0x3b, + 0x25, 0xab, 0xef, 0xc0, 0x4c, 0x8d, 0x7a, 0xa6, 0xa8, 0x83, 0x0a, 0x1b, 0xdd, 0x01, 0xe8, 0x15, + 0x3c, 0x85, 0x76, 0x2d, 0x12, 0x0c, 0x59, 0x7a, 0xfd, 0x90, 0xd4, 0x70, 0x8b, 0x28, 0xdd, 0x7a, + 0x48, 0x53, 0xff, 0xad, 0x06, 0xb3, 0x21, 0x70, 0xc5, 0xb3, 0x0a, 0xe9, 0x36, 0x73, 0x38, 0xcb, + 0xd4, 0x8d, 0xdc, 0xea, 0x7c, 0x2c, 0xd7, 0x7a, 0x59, 0x59, 0x17, 0x82, 0xe8, 0x6e, 0x84, 0xce, + 0x84, 0xa0, 0x73, 0x7d, 0x24, 0x1d, 0x69, 0x2d, 0xc2, 0xe7, 0x53, 0x0d, 0xce, 0x07, 0x7c, 0xd6, + 0xbb, 0x35, 0x4a, 0x2d, 0x7f, 0xcb, 0x65, 0xc8, 0xe1, 0x76, 0xdb, 0xe0, 0xd5, 0xd8, 0x30, 0x9b, + 0x62, 0xcf, 0xe9, 0x7a, 0x16, 0xb7, 0xdb, 0x5c, 0x68, 0xab, 0xd9, 0xe7, 0x92, 0x89, 0xc4, 0x2e, + 0xf9, 0x4c, 0x83, 0x0b, 0x31, 0x0a, 0xdf, 0xba, 0x63, 0x0a, 0x30, 0xfd, 0x80, 0x61, 0xd6, 0x09, + 0xb2, 0xab, 0x09, 0x79, 0xff, 0x81, 0x22, 0xb7, 0x08, 0x79, 0xea, 0x10, 0xdb, 0x68, 0x33, 0xc7, + 0x68, 0xd0, 0x8e, 0xcd, 0x94, 0x8f, 0xa6, 0xf8, 0xd3, 0x6d, 0xe6, 0x6c, 0xf0, 0x67, 0xe8, 0x26, + 0x20, 0xcb, 0xdc, 0x23, 0xcc, 0x6c, 0x93, 0x90, 0xe4, 0x84, 0x90, 0x9c, 0xf1, 0x57, 0x7c, 0x69, + 0xfd, 0x13, 0x28, 0x05, 0xbe, 0xb8, 0x43, 0xdd, 0xb5, 0x66, 0xd3, 0x25, 0x5e, 0x90, 0x85, 0x45, + 0x38, 0x8d, 0xe5, 0x13, 0x79, 0xa9, 0xd5, 0xfd, 0x8f, 0x27, 0x16, 0x8c, 0x2f, 0x34, 0x98, 0x1f, + 0x48, 0xe0, 0x5b, 0x0f, 0xc8, 0x0e, 0xcc, 0x7c, 0xb8, 0x6f, 0x32, 0x62, 0x99, 0x1e, 0x3b, 0xe9, + 0x53, 0xf9, 0x14, 0x66, 0x43, 0xd8, 0x6a, 0xab, 0x0b, 0x90, 0x3d, 0xf4, 0x1f, 0x8a, 0xfd, 0x66, + 0xeb, 0xbd, 0x07, 0x27, 0xb7, 0xaf, 0xef, 0xc3, 0xdc, 0x96, 0x17, 0x58, 0x27, 0xcd, 0x91, 0xb1, + 0xd6, 0x3f, 0x82, 0x73, 0x7d, 0x1a, 0x8a, 0xf1, 0xf0, 0xf4, 0xb8, 0x0a, 0x79, 0xd3, 0x33, 0x0e, + 0x7b, 0x3a, 0x82, 0xf1, 0x99, 0xfa, 0xb4, 0x19, 0x06, 0xd2, 0x97, 0xe0, 0xec, 0x07, 0x9c, 0xf5, + 0x5d, 0xc2, 0xc2, 0x95, 0x60, 0x0e, 0x26, 0x4d, 0xbb, 0x49, 0x9e, 0xa8, 0xfc, 0x96, 0x1f, 0xf4, + 0xf7, 0x61, 0x2e, 0x2a, 0xac, 0x58, 0xbc, 0x05, 0x69, 0x5e, 0x33, 0x54, 0x38, 0x16, 0x62, 0x25, + 0x37, 0x24, 0xab, 0x0a, 0xaf, 0x90, 0xd7, 0x3f, 0x56, 0xc6, 0xd7, 0x2c, 0x2b, 0x6c, 0xfc, 0xa4, + 0x62, 0xfc, 0x85, 0xa6, 0xf8, 0x06, 0xf8, 0x31, 0xbe, 0xa9, 0x97, 0xe1, 0x7b, 0x72, 0x19, 0xf0, + 0x16, 0x00, 0xef, 0x26, 0x46, 0x9e, 0xf1, 0x3c, 0x4c, 0x98, 0x4d, 0x55, 0x39, 0x26, 0xcc, 0xa6, + 0xfe, 0x23, 0xc8, 0x09, 0x3d, 0xb5, 0x8f, 0xe5, 0x70, 0xbf, 0x72, 0xec, 0xc9, 0xe4, 0x72, 0xfa, + 0xdf, 0x52, 0x50, 0x12, 0xfe, 0xf8, 0xa9, 0x43, 0xec, 0x9f, 0x78, 0xcc, 0x6c, 0x0b, 0x36, 0x3e, + 0x8d, 0x5b, 0x70, 0xc6, 0x51, 0x75, 0x40, 0x40, 0xe6, 0x57, 0x8b, 0x71, 0xcf, 0xc8, 0xf5, 0x7a, + 0x20, 0x89, 0xee, 0xc1, 0x99, 0xa0, 0xdf, 0x48, 0xd6, 0x01, 0x05, 0xfa, 0xe8, 0x0a, 0x4c, 0x47, + 0x1a, 0x2b, 0xd9, 0xd4, 0xd6, 0xa7, 0xc2, 0x2d, 0x12, 0x7a, 0x17, 0xa0, 0x41, 0x2d, 0x0b, 0x33, + 0xe2, 0x62, 0x4b, 0xb4, 0x38, 0x63, 0x34, 0x49, 0x21, 0x15, 0xce, 0xb8, 0x69, 0x7a, 0xb2, 0x28, + 0x27, 0xeb, 0x61, 0x02, 0x7d, 0xb4, 0x03, 0xb3, 0x0c, 0x1f, 0x10, 0xc3, 0x71, 0xe9, 0x9e, 0xe9, + 0x37, 0x82, 0x99, 0x44, 0xa0, 0x05, 0x0e, 0x54, 0x13, 0x38, 0xb2, 0x2f, 0x3a, 0x0f, 0x19, 0x47, + 0xdc, 0xbb, 0xc5, 0xd3, 0x22, 0x01, 0xd4, 0x27, 0xfd, 0x37, 0x00, 0xf3, 0x03, 0xc3, 0x18, 0xb4, + 0x40, 0xdf, 0x8d, 0x38, 0x6e, 0x42, 0x21, 0x78, 0x21, 0xc2, 0xed, 0x20, 0x9c, 0x63, 0xa0, 0xe4, + 0x7d, 0xbd, 0x35, 0xa1, 0x86, 0x6e, 0xc3, 0xb4, 0xef, 0x07, 0xc3, 0x33, 0x9f, 0x12, 0xd5, 0x8a, + 0x8e, 0xc4, 0x99, 0xf2, 0xb5, 0x1e, 0x98, 0x4f, 0x09, 0xda, 0x06, 0x10, 0xcd, 0x81, 0x4c, 0x82, + 0xd3, 0x89, 0x7c, 0x98, 0xe5, 0x08, 0x32, 0xfc, 0x03, 0x53, 0xeb, 0xcc, 0xc9, 0xa4, 0xd6, 0xc0, + 0x7e, 0x3e, 0x7b, 0x42, 0xfd, 0xfc, 0x6d, 0x98, 0x26, 0x32, 0x2b, 0x49, 0xd3, 0xe0, 0x2f, 0x32, + 0x30, 0xa6, 0x37, 0x03, 0xad, 0x9a, 0x6d, 0xa1, 0x1a, 0x9c, 0xc5, 0x8f, 0xb1, 0x69, 0xe1, 0x5d, + 0x8b, 0xf4, 0x5e, 0x3b, 0x8b, 0xb9, 0xf1, 0xb0, 0x50, 0xa0, 0x1b, 0xbc, 0x5f, 0xf2, 0x0c, 0xf7, + 0x2c, 0xd3, 0x71, 0x78, 0x86, 0x4f, 0x25, 0xcb, 0x70, 0x5f, 0x1f, 0xfd, 0x12, 0xe6, 0xfa, 0xdf, + 0xc9, 0x5d, 0xcc, 0x48, 0x71, 0x3a, 0x11, 0x2e, 0x8a, 0xbe, 0x85, 0xd7, 0x31, 0x23, 0xe8, 0x03, + 0x98, 0xf2, 0x5f, 0x84, 0x05, 0x72, 0x3e, 0x11, 0x72, 0x4e, 0x61, 0xf8, 0x90, 0x22, 0xd2, 0x86, + 0xd9, 0x76, 0x70, 0x83, 0x15, 0x0b, 0xc9, 0x20, 0x05, 0xc6, 0x96, 0x80, 0x40, 0xef, 0xc0, 0xe9, + 0x46, 0xc7, 0x63, 0xb4, 0xd9, 0x2d, 0xce, 0x8c, 0x17, 0x19, 0x5f, 0x1e, 0xad, 0x41, 0xce, 0x9f, + 0xa0, 0x98, 0xc4, 0x2b, 0xce, 0x8e, 0xa7, 0x1e, 0xd6, 0xd1, 0x2f, 0xc2, 0x05, 0xbf, 0x1f, 0x59, + 0xb3, 0xac, 0x87, 0xb4, 0x86, 0xbb, 0x7e, 0xef, 0xbe, 0x09, 0xc5, 0xf8, 0x92, 0x2a, 0x90, 0x37, + 0x21, 0xc3, 0xa8, 0xe1, 0xe0, 0xae, 0x6a, 0x00, 0xce, 0xf5, 0x97, 0x47, 0x29, 0x3e, 0xc9, 0xf8, + 0x1f, 0xfd, 0xf3, 0x0c, 0x4c, 0x45, 0xba, 0x87, 0xd1, 0x6f, 0x49, 0x99, 0x7d, 0x82, 0x2d, 0xb6, + 0x9f, 0xb0, 0x8e, 0x2a, 0xed, 0xa1, 0x39, 0x96, 0x3a, 0xb1, 0x1c, 0xdb, 0x82, 0x19, 0xb1, 0x0b, + 0x51, 0xa4, 0x3d, 0xc3, 0xa2, 0x76, 0xab, 0x98, 0x16, 0x2e, 0xb9, 0x38, 0xa8, 0x27, 0x12, 0x75, + 0xdb, 0x2f, 0xa1, 0x8e, 0xff, 0xc0, 0xbb, 0x4f, 0xed, 0x16, 0x7a, 0x0f, 0x66, 0xc3, 0x50, 0xde, + 0x3e, 0x75, 0x79, 0x39, 0x1e, 0x0b, 0xab, 0xd0, 0xc3, 0x7a, 0xc0, 0xf5, 0xd0, 0x87, 0xf0, 0xba, + 0x85, 0x3d, 0x66, 0xec, 0x13, 0xb3, 0xb5, 0xcf, 0x8c, 0x41, 0x5e, 0x30, 0x1a, 0xb4, 0xed, 0x74, + 0x78, 0x5b, 0xcb, 0x6b, 0x75, 0xaa, 0xbe, 0xc8, 0x15, 0x36, 0x85, 0xfc, 0x7a, 0x6c, 0xa3, 0x1b, + 0x4a, 0x36, 0x76, 0xa8, 0x4e, 0xbf, 0xfa, 0xa1, 0xda, 0x81, 0x59, 0x9b, 0x30, 0x43, 0x54, 0x7e, + 0x9f, 0x61, 0x82, 0x32, 0xbd, 0x65, 0xb3, 0x7a, 0xc1, 0x26, 0x8c, 0xdf, 0xe9, 0x3e, 0x75, 0xf4, + 0x1e, 0x64, 0x79, 0x4c, 0x24, 0xd7, 0x6c, 0xc2, 0x4b, 0x99, 0x2a, 0xa2, 0xdb, 0x00, 0x22, 0x2a, + 0x12, 0x0d, 0x92, 0x5d, 0x4f, 0x02, 0x81, 0xc3, 0xe9, 0x9f, 0x4e, 0xa8, 0x2e, 0x64, 0xc3, 0xa2, + 0x1e, 0x89, 0x77, 0x93, 0xc3, 0x9b, 0xda, 0x4b, 0x90, 0x0b, 0x6e, 0xdb, 0xa0, 0xbb, 0x05, 0xff, + 0xd1, 0x96, 0x88, 0x52, 0x83, 0x83, 0xfa, 0xb7, 0x7a, 0xb2, 0xd1, 0x66, 0x4e, 0x60, 0xa8, 0x1b, + 0xfe, 0x01, 0x4c, 0xf3, 0x8f, 0x3c, 0xf0, 0xf2, 0xb2, 0x4b, 0x36, 0x1a, 0x9b, 0x52, 0x20, 0xe2, + 0xa2, 0xd3, 0xff, 0x91, 0x81, 0x85, 0xc1, 0x2e, 0x78, 0xa5, 0x4e, 0x2c, 0xd6, 0x8d, 0x4c, 0x24, + 0xe9, 0x46, 0xfa, 0xca, 0x6b, 0xea, 0xe5, 0xcb, 0x6b, 0xec, 0xbe, 0x48, 0xbf, 0xfa, 0x7d, 0xf1, + 0x7f, 0x1d, 0x24, 0x7e, 0x04, 0x33, 0x6d, 0xfc, 0xc4, 0x88, 0xe4, 0x4e, 0x26, 0x51, 0xee, 0xe4, + 0xdb, 0xf8, 0xc9, 0x46, 0x28, 0x7d, 0xf6, 0xe1, 0x72, 0x7f, 0x11, 0xea, 0xd8, 0x0e, 0x36, 0x9b, + 0xbd, 0x2f, 0x01, 0x44, 0x2d, 0x19, 0xc3, 0xc3, 0xaf, 0x45, 0xeb, 0xf0, 0xcf, 0x04, 0x4c, 0x30, + 0xf1, 0x47, 0xf7, 0x60, 0xc6, 0x25, 0xac, 0xe3, 0xda, 0xa2, 0x79, 0x96, 0x7b, 0x38, 0x33, 0x1e, + 0x72, 0x21, 0x50, 0x54, 0xac, 0xdf, 0x07, 0xe4, 0xe0, 0x2e, 0x07, 0x0a, 0x67, 0x42, 0x76, 0x3c, + 0xb4, 0x59, 0xa9, 0x7a, 0x3f, 0x94, 0x0f, 0x0d, 0x28, 0x4b, 0x13, 0x8a, 0x98, 0x81, 0x99, 0x11, + 0x3d, 0x55, 0x63, 0x76, 0x7a, 0x25, 0x09, 0x23, 0x69, 0xae, 0xb1, 0x8d, 0xd0, 0xa1, 0x5a, 0xfd, + 0xb2, 0x00, 0x93, 0xe2, 0x50, 0x21, 0x06, 0x19, 0x39, 0xac, 0x45, 0xaf, 0x0d, 0x1e, 0xe2, 0xaa, + 0x52, 0x53, 0x2a, 0x0f, 0x5b, 0x96, 0xc7, 0x50, 0x5f, 0xfa, 0xd5, 0x3f, 0xff, 0xfb, 0xd9, 0xc4, + 0x55, 0x74, 0xa5, 0xca, 0xe5, 0x96, 0x6d, 0xc2, 0x0e, 0xa9, 0x7b, 0x50, 0x1d, 0xf8, 0xe5, 0x15, + 0xfa, 0x5c, 0x83, 0x29, 0x31, 0xdf, 0x50, 0x13, 0x31, 0x74, 0x79, 0xd8, 0x91, 0x0d, 0xec, 0x7f, + 0xef, 0x18, 0x09, 0x45, 0xe1, 0x5d, 0x41, 0xe1, 0x1d, 0xf4, 0xf6, 0xf1, 0x14, 0x7c, 0xbd, 0xea, + 0xb3, 0xd0, 0x77, 0x6d, 0x07, 0xa4, 0x7b, 0x84, 0xbe, 0xd4, 0x00, 0x85, 0x69, 0xc9, 0xa9, 0x29, + 0xba, 0x36, 0xd4, 0x74, 0x64, 0xb2, 0x5b, 0xba, 0x3e, 0x52, 0x4e, 0x11, 0xad, 0x09, 0xa2, 0xf7, + 0xd0, 0xe6, 0xb1, 0x44, 0xdb, 0xcc, 0xf1, 0x96, 0x77, 0xbb, 0xcb, 0xfc, 0xe2, 0xae, 0x3e, 0x0b, + 0x75, 0x43, 0x47, 0x71, 0xe6, 0x87, 0x90, 0xbd, 0x4b, 0x98, 0x1c, 0xa4, 0xc6, 0x23, 0x19, 0x99, + 0xb8, 0xc6, 0x23, 0x19, 0x9d, 0xbf, 0x8e, 0x19, 0x49, 0x4f, 0xda, 0xfa, 0xab, 0x06, 0xe7, 0xc3, + 0x2e, 0xeb, 0xcd, 0x36, 0xd1, 0x1b, 0x43, 0xdd, 0x11, 0x9b, 0xc0, 0x96, 0x96, 0xc6, 0x92, 0x7d, + 0x79, 0xf7, 0xed, 0x51, 0x77, 0x59, 0x5d, 0x89, 0xd5, 0x67, 0xea, 0x9f, 0x01, 0xee, 0x53, 0xf9, + 0x18, 0xcc, 0xec, 0xe2, 0xf9, 0xd8, 0x3f, 0x23, 0x8d, 0xe7, 0x63, 0x6c, 0xd2, 0x39, 0x66, 0x3e, + 0x06, 0xd3, 0xc3, 0x38, 0xad, 0x3f, 0x68, 0x30, 0x1d, 0x19, 0x49, 0xa2, 0xc5, 0x7e, 0xab, 0x83, + 0x66, 0x9c, 0xa5, 0xab, 0x23, 0xa4, 0x14, 0xbf, 0x37, 0x05, 0xbf, 0x65, 0xb4, 0x74, 0x2c, 0x3f, + 0xd3, 0x5b, 0x0e, 0x0d, 0x38, 0xd1, 0xaf, 0x35, 0x48, 0x8b, 0x53, 0x71, 0xa5, 0xdf, 0xc8, 0x80, + 0x11, 0x67, 0x69, 0xf1, 0x78, 0x21, 0x45, 0x64, 0x45, 0x10, 0x59, 0x42, 0xaf, 0x8f, 0x38, 0xb8, + 0xfc, 0x1c, 0x88, 0x21, 0xe9, 0x11, 0xfa, 0x9d, 0x06, 0x93, 0x1c, 0xc3, 0x1b, 0xc2, 0x23, 0x3a, + 0xed, 0x1c, 0xc2, 0xa3, 0x6f, 0x64, 0xa9, 0xff, 0x40, 0xf0, 0xb8, 0x85, 0x56, 0xc7, 0xe0, 0x11, + 0x3f, 0x81, 0xa9, 0xed, 0x87, 0x35, 0x54, 0x1a, 0xf4, 0x85, 0xa6, 0x22, 0x31, 0x3f, 0x70, 0x4d, + 0xd9, 0x7e, 0x5b, 0xd8, 0x5e, 0x41, 0xd5, 0x51, 0x49, 0x1d, 0xce, 0x63, 0xb3, 0x79, 0x84, 0xfe, + 0xa4, 0x41, 0x3e, 0x3a, 0xa4, 0x8a, 0x9f, 0xbc, 0xe1, 0x03, 0xc9, 0xf8, 0xc9, 0x3b, 0x66, 0xea, + 0xa5, 0xdf, 0x12, 0x24, 0x2b, 0xe8, 0xe6, 0xb1, 0x24, 0x79, 0x9b, 0xbe, 0x4c, 0x7a, 0x74, 0xfe, + 0xa8, 0x41, 0x2e, 0xf4, 0x8a, 0x88, 0xae, 0x0f, 0x4b, 0x8a, 0xbe, 0xf7, 0xcb, 0xd2, 0x8d, 0xd1, + 0x82, 0x2f, 0x95, 0xca, 0x2d, 0xc2, 0x0c, 0x6c, 0x59, 0x86, 0x7c, 0x31, 0x45, 0x7f, 0xd1, 0xa0, + 0xd0, 0xd7, 0x55, 0xa2, 0xc1, 0xee, 0x18, 0xdc, 0x7e, 0x97, 0x6e, 0x8e, 0x27, 0xac, 0x38, 0x6e, + 0x08, 0x8e, 0x3f, 0x46, 0x3f, 0x3c, 0x96, 0xa3, 0x68, 0xac, 0x42, 0xde, 0xab, 0x3e, 0x0b, 0xf5, + 0xf1, 0x47, 0xeb, 0x9b, 0x5f, 0x3d, 0x2f, 0x6b, 0x5f, 0x3f, 0x2f, 0x6b, 0xff, 0x79, 0x5e, 0xd6, + 0x7e, 0xff, 0xa2, 0x7c, 0xea, 0xeb, 0x17, 0xe5, 0x53, 0xff, 0x7a, 0x51, 0x3e, 0xb5, 0x53, 0x09, + 0xb5, 0x5d, 0x71, 0x03, 0x4f, 0xfa, 0x7f, 0x24, 0xb2, 0x9b, 0x11, 0x3f, 0xf5, 0x78, 0xf3, 0x7f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0x3e, 0x54, 0x2a, 0xa6, 0xec, 0x22, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -3273,6 +3290,30 @@ func (m *QueryOpenEstimationResponse) MarshalToSizedBuffer(dAtA []byte) (int, er _ = i var l int _ = l + { + size, err := m.Liabilities.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + { + size, err := m.Custody.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 { size := m.PriceImpact.Size() i -= size @@ -4185,6 +4226,10 @@ func (m *QueryOpenEstimationResponse) Size() (n int) { n += 1 + l + sovQuery(uint64(l)) l = m.PriceImpact.Size() n += 1 + l + sovQuery(uint64(l)) + l = m.Custody.Size() + n += 2 + l + sovQuery(uint64(l)) + l = m.Liabilities.Size() + n += 2 + l + sovQuery(uint64(l)) return n } @@ -7429,6 +7474,72 @@ func (m *QueryOpenEstimationResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Custody", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Custody.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Liabilities", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Liabilities.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/x/perpetual/types/types.go b/x/perpetual/types/types.go index 848bcee1f..2fde22651 100644 --- a/x/perpetual/types/types.go +++ b/x/perpetual/types/types.go @@ -69,6 +69,23 @@ func (mtp MTP) Validate() error { return nil } +func (mtp *MTP) GetAndSetOpenPrice() { + openPrice := math.LegacyZeroDec() + // open price = (collateral + liabilities) / custody + if mtp.Position == Position_LONG { + if mtp.CollateralAsset == mtp.TradingAsset { + openPrice = mtp.Liabilities.ToLegacyDec().Quo(mtp.Custody.Sub(mtp.Collateral).ToLegacyDec()) + } else { + openPrice = (mtp.Collateral.Add(mtp.Liabilities)).ToLegacyDec().Quo(mtp.Custody.ToLegacyDec()) + } + } else { + // open price = (custody - collateral) / liabilities + openPrice = (mtp.Custody.Sub(mtp.Collateral)).ToLegacyDec().Quo(mtp.Liabilities.ToLegacyDec()) + } + mtp.OpenPrice = openPrice + return +} + func (mtp MTP) GetAccountAddress() sdk.AccAddress { return sdk.MustAccAddressFromBech32(mtp.Address) } diff --git a/x/stablestake/keeper/params.go b/x/stablestake/keeper/params.go index c1f5a2f87..f93d6900c 100644 --- a/x/stablestake/keeper/params.go +++ b/x/stablestake/keeper/params.go @@ -18,18 +18,6 @@ func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { return } -func (k Keeper) GetLegacyParams(ctx sdk.Context) (params types.LegacyParams) { - store := ctx.KVStore(k.storeKey) - - b := store.Get(types.ParamKeyPrefix) - if b == nil { - return - } - - k.cdc.MustUnmarshal(b, ¶ms) - return -} - // SetParams set the params func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { store := ctx.KVStore(k.storeKey) diff --git a/x/stablestake/migrations/v7_migration.go b/x/stablestake/migrations/v7_migration.go index c320b19fa..53c8d20be 100644 --- a/x/stablestake/migrations/v7_migration.go +++ b/x/stablestake/migrations/v7_migration.go @@ -2,14 +2,8 @@ package migrations import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/elys-network/elys/x/stablestake/types" ) func (m Migrator) V7Migration(ctx sdk.Context) error { - oldParams := m.keeper.GetLegacyParams(ctx) - params := types.DefaultParams() - params.TotalValue = oldParams.TotalValue - params.InterestRate = oldParams.InterestRate - m.keeper.SetParams(ctx, params) return nil }