From cb0f7e7031566457785c761fef405a8687078817 Mon Sep 17 00:00:00 2001 From: sampocs Date: Thu, 6 Jun 2024 22:48:40 -0500 Subject: [PATCH] staketia migration - disable staketia LS (#1213) --- proto/stride/staketia/tx.proto | 4 + x/staketia/client/cli/tx.go | 43 ----- x/staketia/keeper/delegation.go | 104 ---------- x/staketia/keeper/delegation_test.go | 278 --------------------------- x/staketia/keeper/hooks.go | 7 - x/staketia/keeper/msg_server.go | 8 +- x/staketia/keeper/msg_server_test.go | 25 --- x/staketia/types/tx.pb.go | 168 ++++++++-------- 8 files changed, 92 insertions(+), 545 deletions(-) diff --git a/proto/stride/staketia/tx.proto b/proto/stride/staketia/tx.proto index e26666cab..b8e1d3b6a 100644 --- a/proto/stride/staketia/tx.proto +++ b/proto/stride/staketia/tx.proto @@ -75,10 +75,12 @@ service Msg { returns (MsgSetOperatorAddressResponse); } +// Deprecated: Liquid stakes should be handled in stakeibc // LiquidStake message MsgLiquidStake { option (cosmos.msg.v1.signer) = "staker"; option (amino.name) = "staketia/MsgLiquidStake"; + option deprecated = true; string staker = 1; string native_amount = 2 [ @@ -87,6 +89,8 @@ message MsgLiquidStake { ]; } message MsgLiquidStakeResponse { + option deprecated = true; + cosmos.base.v1beta1.Coin st_token = 1 [ (gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" diff --git a/x/staketia/client/cli/tx.go b/x/staketia/client/cli/tx.go index 52bee7cdc..25d7a70b5 100644 --- a/x/staketia/client/cli/tx.go +++ b/x/staketia/client/cli/tx.go @@ -36,7 +36,6 @@ func GetTxCmd() *cobra.Command { } cmd.AddCommand( - CmdLiquidStake(), CmdRedeemStake(), CmdConfirmDelegation(), CmdConfirmUndelegation(), @@ -52,48 +51,6 @@ func GetTxCmd() *cobra.Command { return cmd } -// User transaction to liquid stake native tokens into stTokens -func CmdLiquidStake() *cobra.Command { - cmd := &cobra.Command{ - Use: "liquid-stake [amount]", - Short: "Liquid stakes native tokens and receives stTokens", - Long: strings.TrimSpace( - fmt.Sprintf(`Liquid stakes native tokens and receives stTokens - -Example: - $ %[1]s tx %[2]s liquid-stake 10000 -`, version.AppName, types.ModuleName), - ), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - amount, ok := sdkmath.NewIntFromString(args[0]) - if !ok { - return errors.New("unable to parse amount") - } - - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - - msg := types.NewMsgLiquidStake( - clientCtx.GetFromAddress().String(), - amount, - ) - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - // User transaction to redeem stake stTokens into native tokens func CmdRedeemStake() *cobra.Command { cmd := &cobra.Command{ diff --git a/x/staketia/keeper/delegation.go b/x/staketia/keeper/delegation.go index 69f841fdd..c7ffcca1e 100644 --- a/x/staketia/keeper/delegation.go +++ b/x/staketia/keeper/delegation.go @@ -1,81 +1,16 @@ package keeper import ( - "fmt" "time" errorsmod "cosmossdk.io/errors" - sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" "github.com/Stride-Labs/stride/v22/utils" - stakeibctypes "github.com/Stride-Labs/stride/v22/x/stakeibc/types" "github.com/Stride-Labs/stride/v22/x/staketia/types" ) -// Liquid stakes native tokens and returns stTokens to the user -// The staker's native tokens (which exist as an IBC denom on stride) are escrowed -// in the deposit account -// StTokens are minted at the current redemption rate -func (k Keeper) LiquidStake(ctx sdk.Context, liquidStaker string, nativeAmount sdkmath.Int) (stToken sdk.Coin, err error) { - // Get the host zone and verify it's unhalted - hostZone, err := k.GetUnhaltedHostZone(ctx) - if err != nil { - return stToken, err - } - - // Get user and deposit account addresses - liquidStakerAddress, err := sdk.AccAddressFromBech32(liquidStaker) - if err != nil { - return stToken, errorsmod.Wrapf(err, "user's address is invalid") - } - hostZoneDepositAddress, err := sdk.AccAddressFromBech32(hostZone.DepositAddress) - if err != nil { - return stToken, errorsmod.Wrapf(err, "host zone deposit address is invalid") - } - - // Check redemption rates are within safety bounds - if err := k.CheckRedemptionRateExceedsBounds(ctx); err != nil { - return stToken, err - } - - // The tokens that are sent to the protocol are denominated in the ibc hash of the native token on stride (e.g. ibc/xxx) - nativeToken := sdk.NewCoin(hostZone.NativeTokenIbcDenom, nativeAmount) - if !utils.IsIBCToken(hostZone.NativeTokenIbcDenom) { - return stToken, errorsmod.Wrapf(stakeibctypes.ErrInvalidToken, - "denom is not an IBC token (%s)", hostZone.NativeTokenIbcDenom) - } - - // Determine the amount of stTokens to mint using the redemption rate - stAmount := (sdk.NewDecFromInt(nativeAmount).Quo(hostZone.RedemptionRate)).TruncateInt() - if stAmount.IsZero() { - return stToken, errorsmod.Wrapf(stakeibctypes.ErrInsufficientLiquidStake, - "Liquid stake of %s%s would return 0 stTokens", nativeAmount.String(), hostZone.NativeTokenDenom) - } - - // Transfer the native tokens from the user to module account - if err := k.bankKeeper.SendCoins(ctx, liquidStakerAddress, hostZoneDepositAddress, sdk.NewCoins(nativeToken)); err != nil { - return stToken, errorsmod.Wrapf(err, "failed to send tokens from liquid staker %s to deposit address", liquidStaker) - } - - // Mint the stTokens and transfer them to the user - stDenom := utils.StAssetDenomFromHostZoneDenom(hostZone.NativeTokenDenom) - stToken = sdk.NewCoin(stDenom, stAmount) - if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(stToken)); err != nil { - return stToken, errorsmod.Wrapf(err, "Failed to mint stTokens") - } - if err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, liquidStakerAddress, sdk.NewCoins(stToken)); err != nil { - return stToken, errorsmod.Wrapf(err, "Failed to send %s from deposit address to liquid staker", stToken.String()) - } - - // Emit liquid stake event with the same schema as stakeibc - EmitSuccessfulLiquidStakeEvent(ctx, liquidStaker, hostZone, nativeAmount, stAmount) - - return stToken, nil -} - // IBC transfers all TIA in the deposit account and sends it to the delegation account func (k Keeper) PrepareDelegation(ctx sdk.Context, epochNumber uint64, epochDuration time.Duration) error { k.Logger(ctx).Info(utils.LogWithHostZone(types.CelestiaChainId, "Preparing delegation for epoch %d", epochNumber)) @@ -178,48 +113,9 @@ func (k Keeper) ConfirmDelegation(ctx sdk.Context, recordId uint64, txHash strin return nil } -// Liquid stakes tokens in the fee account and distributes them to the fee collector -func (k Keeper) LiquidStakeAndDistributeFees(ctx sdk.Context) error { - // Get the fee address from the host zone - hostZone, err := k.GetUnhaltedHostZone(ctx) - if err != nil { - return err - } - - // Get the balance of native tokens in the fee address, if there are no tokens, no action is necessary - feeAddress := k.accountKeeper.GetModuleAddress(types.FeeAddress) - feesBalance := k.bankKeeper.GetBalance(ctx, feeAddress, hostZone.NativeTokenIbcDenom) - if feesBalance.IsZero() { - k.Logger(ctx).Info("No fees generated this epoch") - return nil - } - - // Liquid stake those native tokens - stTokens, err := k.LiquidStake(ctx, feeAddress.String(), feesBalance.Amount) - if err != nil { - return errorsmod.Wrapf(err, "unable to liquid stake fees") - } - - // Send the stTokens to the fee collector - err = k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.FeeAddress, authtypes.FeeCollectorName, sdk.NewCoins(stTokens)) - if err != nil { - return errorsmod.Wrapf(err, "unable to send liquid staked tokens to fee collector") - } - k.Logger(ctx).Info(fmt.Sprintf("Liquid staked and sent %v to fee collector", stTokens)) - - return nil -} - // Runs prepare delegations with a cache context wrapper so revert any partial state changes func (k Keeper) SafelyPrepareDelegation(ctx sdk.Context, epochNumber uint64, epochDuration time.Duration) error { return utils.ApplyFuncIfNoError(ctx, func(ctx sdk.Context) error { return k.PrepareDelegation(ctx, epochNumber, epochDuration) }) } - -// Liquid stakes fees with a cache context wrapper so revert any partial state changes -func (k Keeper) SafelyLiquidStakeAndDistributeFees(ctx sdk.Context) error { - return utils.ApplyFuncIfNoError(ctx, func(ctx sdk.Context) error { - return k.LiquidStakeAndDistributeFees(ctx) - }) -} diff --git a/x/staketia/keeper/delegation_test.go b/x/staketia/keeper/delegation_test.go index 2ad2fc330..081e53fcd 100644 --- a/x/staketia/keeper/delegation_test.go +++ b/x/staketia/keeper/delegation_test.go @@ -5,7 +5,6 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" ibctesting "github.com/cosmos/ibc-go/v7/testing" @@ -14,224 +13,6 @@ import ( var InitialDelegation = sdkmath.NewInt(1_000_000) -type LiquidStakeTestCase struct { - liquidStakeAmount sdkmath.Int - expectedStAmount sdkmath.Int - stakerAddress sdk.AccAddress - depositAddress sdk.AccAddress -} - -// ---------------------------------------------------- -// LiquidStake -// ---------------------------------------------------- - -// Helper function to mock relevant state before testing a liquid stake -func (s *KeeperTestSuite) SetupTestLiquidStake( - redemptionRate sdk.Dec, - liquidStakeAmount, - expectedStAmount sdkmath.Int, -) LiquidStakeTestCase { - // Create relevant addresses - stakerAddress := s.TestAccs[0] - depositAddress := s.TestAccs[1] - - // Create a host zone with relevant denom's and addresses - s.App.StaketiaKeeper.SetHostZone(s.Ctx, types.HostZone{ - ChainId: HostChainId, - NativeTokenDenom: HostNativeDenom, - NativeTokenIbcDenom: HostIBCDenom, - DepositAddress: depositAddress.String(), - RedemptionRate: redemptionRate, - MinRedemptionRate: redemptionRate.Sub(sdk.MustNewDecFromStr("0.2")), - MinInnerRedemptionRate: redemptionRate.Sub(sdk.MustNewDecFromStr("0.1")), - MaxInnerRedemptionRate: redemptionRate.Add(sdk.MustNewDecFromStr("0.1")), - MaxRedemptionRate: redemptionRate.Add(sdk.MustNewDecFromStr("0.2")), - }) - - // Fund the staker - liquidStakeToken := sdk.NewCoin(HostIBCDenom, liquidStakeAmount) - s.FundAccount(stakerAddress, liquidStakeToken) - - return LiquidStakeTestCase{ - liquidStakeAmount: liquidStakeAmount, - expectedStAmount: expectedStAmount, - stakerAddress: stakerAddress, - depositAddress: depositAddress, - } -} - -// Helper function to setup the state with default values -// (useful when testing error cases) -func (s *KeeperTestSuite) DefaultSetupTestLiquidStake() LiquidStakeTestCase { - redemptionRate := sdk.MustNewDecFromStr("1.0") - liquidStakeAmount := sdkmath.NewInt(1000) - stAmount := sdkmath.NewInt(1000) - return s.SetupTestLiquidStake(redemptionRate, liquidStakeAmount, stAmount) -} - -// Helper function to confirm balances after a successful liquid stake -func (s *KeeperTestSuite) ConfirmLiquidStakeTokenTransfer(tc LiquidStakeTestCase) { - zeroNativeTokens := sdk.NewCoin(HostIBCDenom, sdk.ZeroInt()) - liquidStakedNativeTokens := sdk.NewCoin(HostIBCDenom, tc.liquidStakeAmount) - - zeroStTokens := sdk.NewCoin(StDenom, sdk.ZeroInt()) - liquidStakedStTokens := sdk.NewCoin(StDenom, tc.expectedStAmount) - - // Confirm native tokens were escrowed - // Staker balance should have decreased to zero - // Deposit balance should have increased by liquid stake amount - stakerNativeBalance := s.App.BankKeeper.GetBalance(s.Ctx, tc.stakerAddress, HostIBCDenom) - s.CompareCoins(zeroNativeTokens, stakerNativeBalance, "staker native balance") - - depositNativeBalance := s.App.BankKeeper.GetBalance(s.Ctx, tc.depositAddress, HostIBCDenom) - s.CompareCoins(liquidStakedNativeTokens, depositNativeBalance, "deposit native balance") - - // Confirm stTokens were minted to the user - // Staker balance should increase by the liquid stake amount - // Deposit balance should still be zero - stakerStBalance := s.App.BankKeeper.GetBalance(s.Ctx, tc.stakerAddress, StDenom) - s.CompareCoins(liquidStakedStTokens, stakerStBalance, "staker stToken balance") - - depositStBalance := s.App.BankKeeper.GetBalance(s.Ctx, tc.depositAddress, StDenom) - s.CompareCoins(zeroStTokens, depositStBalance, "deposit native balance") -} - -func (s *KeeperTestSuite) TestLiquidStake_Successful() { - // Test liquid stake across different redemption rates - testCases := []struct { - name string - redemptionRate sdk.Dec - liquidStakeAmount sdkmath.Int - expectedStAmount sdkmath.Int - }{ - { - // Redemption Rate of 1: - // 1000 native -> 1000 stTokens - name: "redemption rate of 1", - redemptionRate: sdk.MustNewDecFromStr("1.0"), - liquidStakeAmount: sdkmath.NewInt(1000), - expectedStAmount: sdkmath.NewInt(1000), - }, - { - // Redemption Rate of 2: - // 1000 native -> 500 stTokens - name: "redemption rate of 2", - redemptionRate: sdk.MustNewDecFromStr("2.0"), - liquidStakeAmount: sdkmath.NewInt(1000), - expectedStAmount: sdkmath.NewInt(500), - }, - { - // Redemption Rate of 0.5: - // 1000 native -> 2000 stTokens - name: "redemption rate of 0.5", - redemptionRate: sdk.MustNewDecFromStr("0.5"), - liquidStakeAmount: sdkmath.NewInt(1000), - expectedStAmount: sdkmath.NewInt(2000), - }, - { - // Redemption Rate of 1.1: - // 333 native -> 302.72 (302) stTokens - name: "int truncation", - redemptionRate: sdk.MustNewDecFromStr("1.1"), - liquidStakeAmount: sdkmath.NewInt(333), - expectedStAmount: sdkmath.NewInt(302), - }, - } - - for _, testCase := range testCases { - s.Run(testCase.name, func() { - s.SetupTest() // reset state - tc := s.SetupTestLiquidStake(testCase.redemptionRate, testCase.liquidStakeAmount, testCase.expectedStAmount) - - // Confirm liquid stake succeeded - stTokenResponse, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), tc.liquidStakeAmount) - s.Require().NoError(err, "no error expected during liquid stake") - - // Confirm the stToken from the response matches expectations - s.Require().Equal(StDenom, stTokenResponse.Denom, "st token denom in liquid stake response") - s.Require().Equal(tc.expectedStAmount.Int64(), stTokenResponse.Amount.Int64(), - "st token amount in liquid stake response") - - // Confirm the native token escrow and stToken mint succeeded - s.ConfirmLiquidStakeTokenTransfer(tc) - }) - } -} - -func (s *KeeperTestSuite) TestLiquidStake_HostZoneHalted() { - tc := s.DefaultSetupTestLiquidStake() - - // Halt the host zone so the liquid stake fails - hostZone := s.MustGetHostZone() - hostZone.Halted = true - s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) - - _, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), tc.liquidStakeAmount) - s.Require().ErrorContains(err, "host zone is halted") -} - -func (s *KeeperTestSuite) TestLiquidStake_InvalidAddresse() { - tc := s.DefaultSetupTestLiquidStake() - - // Pass an invalid staker address and confirm it fails - _, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, "invalid_address", tc.liquidStakeAmount) - s.Require().ErrorContains(err, "user's address is invalid") - - // Set an invalid deposit address and confirm it fails - hostZone := s.MustGetHostZone() - hostZone.DepositAddress = "invalid_address" - s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) - - _, err = s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), tc.liquidStakeAmount) - s.Require().ErrorContains(err, "host zone deposit address is invalid") -} - -func (s *KeeperTestSuite) TestLiquidStake_InvalidRedemptionRate() { - tc := s.DefaultSetupTestLiquidStake() - - // Update the redemption rate so it exceeds the bounds - hostZone := s.MustGetHostZone() - hostZone.RedemptionRate = hostZone.MaxInnerRedemptionRate.Add(sdk.MustNewDecFromStr("0.01")) - s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) - - _, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), tc.liquidStakeAmount) - s.Require().ErrorContains(err, "redemption rate outside inner safety bounds") -} - -func (s *KeeperTestSuite) TestLiquidStake_InvalidIBCDenom() { - tc := s.DefaultSetupTestLiquidStake() - - // Set an invalid IBC denom on the host so the liquid stake fails - hostZone := s.MustGetHostZone() - hostZone.NativeTokenIbcDenom = "non-ibc-denom" - s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) - - _, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), tc.liquidStakeAmount) - s.Require().ErrorContains(err, "denom is not an IBC token") -} - -func (s *KeeperTestSuite) TestLiquidStake_InsufficientLiquidStake() { - // Adjust redemption rate so that a small liquid stake will result in 0 stTokens - // stTokens = 1(amount) / 1.1(RR) = rounds down to 0 - redemptionRate := sdk.MustNewDecFromStr("1.1") - liquidStakeAmount := sdkmath.NewInt(1) - expectedStAmount := sdkmath.ZeroInt() - tc := s.SetupTestLiquidStake(redemptionRate, liquidStakeAmount, expectedStAmount) - - _, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), tc.liquidStakeAmount) - s.Require().ErrorContains(err, "Liquid staked amount is too small") -} - -func (s *KeeperTestSuite) TestLiquidStake_InsufficientFunds() { - // Attempt to liquid stake more tokens than the staker has available - tc := s.DefaultSetupTestLiquidStake() - - excessiveLiquidStakeAmount := sdkmath.NewInt(10000000000) - _, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), excessiveLiquidStakeAmount) - s.Require().ErrorContains(err, "failed to send tokens from liquid staker") - s.Require().ErrorContains(err, "insufficient funds") -} - // ---------------------------------------------------- // PrepareDelegation // ---------------------------------------------------- @@ -489,62 +270,3 @@ func (s *KeeperTestSuite) TestConfirmDelegation_RecordIncorrectState() { s.VerifyDelegationRecords(true) } } - -// ---------------------------------------------------- -// LiquidStakeAndDistributeFees -// ---------------------------------------------------- - -func (s *KeeperTestSuite) TestLiquidStakeAndDistributeFees() { - // Create relevant addresses - depositAddress := s.TestAccs[0] - feeAddress := s.App.AccountKeeper.GetModuleAddress(types.FeeAddress) - - // Liquid stake 1000 with a RR of 2, should return 500 tokens - liquidStakeAmount := sdkmath.NewInt(1000) - redemptionRate := sdk.NewDec(2) - expectedStTokens := sdkmath.NewInt(500) - - // Create a host zone with relevant denom's and addresses - hostZone := types.HostZone{ - ChainId: HostChainId, - NativeTokenDenom: HostNativeDenom, - NativeTokenIbcDenom: HostIBCDenom, - DepositAddress: depositAddress.String(), - RedemptionRate: redemptionRate, - MinRedemptionRate: redemptionRate.Sub(sdk.MustNewDecFromStr("0.2")), - MinInnerRedemptionRate: redemptionRate.Sub(sdk.MustNewDecFromStr("0.1")), - MaxInnerRedemptionRate: redemptionRate.Add(sdk.MustNewDecFromStr("0.1")), - MaxRedemptionRate: redemptionRate.Add(sdk.MustNewDecFromStr("0.2")), - } - s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) - - // Fund the fee address with native tokens - liquidStakeToken := sdk.NewCoin(HostIBCDenom, liquidStakeAmount) - s.FundAccount(feeAddress, liquidStakeToken) - - // Call liquid stake and distribute - err := s.App.StaketiaKeeper.LiquidStakeAndDistributeFees(s.Ctx) - s.Require().NoError(err, "no error expected when liquid staking fee tokens") - - // Confirm stTokens were sent to the fee collector - feeCollectorAddress := s.App.AccountKeeper.GetModuleAddress(authtypes.FeeCollectorName) - feeCollectorBalance := s.App.BankKeeper.GetBalance(s.Ctx, feeCollectorAddress, StDenom) - s.Require().Equal(expectedStTokens.Int64(), feeCollectorBalance.Amount.Int64(), - "fee collector should have received sttokens") - - // Attempt to liquid stake again when there are no more rewards, it should succeed but do nothing - err = s.App.StaketiaKeeper.LiquidStakeAndDistributeFees(s.Ctx) - s.Require().NoError(err, "no error expected when liquid staking again") - - feeCollectorBalance = s.App.BankKeeper.GetBalance(s.Ctx, feeCollectorAddress, StDenom) - s.Require().Equal(expectedStTokens.Int64(), feeCollectorBalance.Amount.Int64(), - "fee collector should not have changed") - - // Test that if the host zone is halted, it will error - haltedHostZone := hostZone - haltedHostZone.Halted = true - s.App.StaketiaKeeper.SetHostZone(s.Ctx, haltedHostZone) - - err = s.App.StaketiaKeeper.LiquidStakeAndDistributeFees(s.Ctx) - s.Require().ErrorContains(err, "host zone is halted") -} diff --git a/x/staketia/keeper/hooks.go b/x/staketia/keeper/hooks.go index b91efc6ee..9dbe11459 100644 --- a/x/staketia/keeper/hooks.go +++ b/x/staketia/keeper/hooks.go @@ -62,13 +62,6 @@ func (k Keeper) BeforeEpochStart(ctx sdk.Context, epochInfo epochstypes.EpochInf k.Logger(ctx).Error(fmt.Sprintf("Unable to distribute claims for epoch %d: %s", epochNumber, err.Error())) } } - - // Every mint epoch, liquid stake fees and distribute to fee collector - if epochInfo.Identifier == epochstypes.MINT_EPOCH { - if err := k.SafelyLiquidStakeAndDistributeFees(ctx); err != nil { - k.Logger(ctx).Error(fmt.Sprintf("Unable to liquid stake and distribute fees this epoch %d: %s", epochNumber, err.Error())) - } - } } type Hooks struct { diff --git a/x/staketia/keeper/msg_server.go b/x/staketia/keeper/msg_server.go index d5be19939..457825c3f 100644 --- a/x/staketia/keeper/msg_server.go +++ b/x/staketia/keeper/msg_server.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "errors" errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" @@ -25,12 +26,7 @@ var _ types.MsgServer = msgServer{} // User transaction to liquid stake native tokens into stTokens func (k msgServer) LiquidStake(goCtx context.Context, msg *types.MsgLiquidStake) (*types.MsgLiquidStakeResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - stToken, err := k.Keeper.LiquidStake(ctx, msg.Staker, msg.NativeAmount) - if err != nil { - return nil, err - } - return &types.MsgLiquidStakeResponse{StToken: stToken}, nil + return nil, errors.New("Liquid staking is no longer enabled in staketia") } // User transaction to redeem stake stTokens into native tokens diff --git a/x/staketia/keeper/msg_server_test.go b/x/staketia/keeper/msg_server_test.go index 699f36b46..183be6322 100644 --- a/x/staketia/keeper/msg_server_test.go +++ b/x/staketia/keeper/msg_server_test.go @@ -8,31 +8,6 @@ import ( "github.com/Stride-Labs/stride/v22/x/staketia/types" ) -// ---------------------------------------------- -// MsgLiquidStake -// ---------------------------------------------- - -// More granular testing of liquid stake is done in the keeper function -// This just tests the msg server wrapper -func (s *KeeperTestSuite) TestMsgServerLiquidStake() { - tc := s.DefaultSetupTestLiquidStake() - - // Attempt a successful liquid stake - validMsg := types.MsgLiquidStake{ - Staker: tc.stakerAddress.String(), - NativeAmount: tc.liquidStakeAmount, - } - resp, err := s.GetMsgServer().LiquidStake(sdk.UnwrapSDKContext(s.Ctx), &validMsg) - s.Require().NoError(err, "no error expected during liquid stake") - s.Require().Equal(tc.expectedStAmount.Int64(), resp.StToken.Amount.Int64(), "stToken amount") - - s.ConfirmLiquidStakeTokenTransfer(tc) - - // Attempt a liquid stake again, it should fail now that the staker is out of funds - _, err = s.GetMsgServer().LiquidStake(sdk.UnwrapSDKContext(s.Ctx), &validMsg) - s.Require().ErrorContains(err, "insufficient funds") -} - // ---------------------------------------------- // MsgConfirmDelegation // ---------------------------------------------- diff --git a/x/staketia/types/tx.pb.go b/x/staketia/types/tx.pb.go index 329c94fdc..f8c1ef344 100644 --- a/x/staketia/types/tx.pb.go +++ b/x/staketia/types/tx.pb.go @@ -61,7 +61,10 @@ func (OverwritableRecordType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_98ceebce67c1ff4c, []int{0} } +// Deprecated: Liquid stakes should be handled in stakeibc // LiquidStake +// +// Deprecated: Do not use. type MsgLiquidStake struct { Staker string `protobuf:"bytes,1,opt,name=staker,proto3" json:"staker,omitempty"` NativeAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,2,opt,name=native_amount,json=nativeAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"native_amount"` @@ -107,6 +110,7 @@ func (m *MsgLiquidStake) GetStaker() string { return "" } +// Deprecated: Do not use. type MsgLiquidStakeResponse struct { StToken types.Coin `protobuf:"bytes,1,opt,name=st_token,json=stToken,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"st_token"` } @@ -1260,92 +1264,92 @@ func init() { func init() { proto.RegisterFile("stride/staketia/tx.proto", fileDescriptor_98ceebce67c1ff4c) } var fileDescriptor_98ceebce67c1ff4c = []byte{ - // 1355 bytes of a gzipped FileDescriptorProto + // 1358 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0xcf, 0x6f, 0x1b, 0xc5, 0x17, 0xf7, 0xa6, 0x55, 0x7f, 0x8c, 0xbf, 0x6d, 0x9d, 0xfd, 0xb6, 0xae, 0xbd, 0xa5, 0x76, 0xba, 0x6d, 0xd3, 0xd6, 0x6d, 0x76, 0x89, 0xdb, 0x82, 0x64, 0xb8, 0xc4, 0xb5, 0xd5, 0x46, 0xc4, 0x71, 0xe5, 0x24, 0x54, 0x94, 0xc3, 0xb2, 0xf6, 0x4e, 0xd6, 0x4b, 0xe3, 0x1d, 0x77, 0x67, 0xec, 0xb8, - 0x42, 0x42, 0xc0, 0xa9, 0xe2, 0x84, 0xc4, 0x89, 0x03, 0x27, 0x24, 0x24, 0xb8, 0xd0, 0x03, 0x37, - 0x2e, 0x1c, 0x7b, 0xac, 0x38, 0x21, 0x0e, 0x05, 0x25, 0x87, 0x8a, 0x7f, 0x00, 0xae, 0x68, 0x7f, - 0x76, 0x76, 0x77, 0xd6, 0x76, 0x0a, 0xb9, 0xc4, 0xde, 0x79, 0x9f, 0x79, 0xef, 0xf3, 0x3e, 0x6f, - 0xf6, 0xcd, 0x8b, 0x41, 0x0e, 0x13, 0xcb, 0xd0, 0xa0, 0x8c, 0x89, 0xfa, 0x00, 0x12, 0x43, 0x95, - 0xc9, 0x48, 0xea, 0x5b, 0x88, 0x20, 0xfe, 0x84, 0x6b, 0x91, 0x7c, 0x8b, 0x70, 0xba, 0x83, 0x70, - 0x0f, 0x61, 0xb9, 0x87, 0x75, 0x79, 0xb8, 0x68, 0x7f, 0xb8, 0x48, 0x61, 0x56, 0xed, 0x19, 0x26, - 0x92, 0x9d, 0xbf, 0xde, 0xd2, 0x49, 0x1d, 0xe9, 0xc8, 0xf9, 0x2a, 0xdb, 0xdf, 0xbc, 0xd5, 0x82, - 0xe7, 0xa1, 0xad, 0x62, 0x28, 0x0f, 0x17, 0xdb, 0x90, 0xa8, 0x8b, 0x72, 0x07, 0x19, 0xa6, 0x67, - 0xcf, 0xbb, 0x76, 0xc5, 0xdd, 0xe8, 0x3e, 0xf8, 0x5b, 0xa3, 0x3c, 0xfd, 0x2f, 0xae, 0x5d, 0xfc, - 0x96, 0x03, 0xc7, 0x1b, 0x58, 0x5f, 0x31, 0x1e, 0x0e, 0x0c, 0x6d, 0xcd, 0xb6, 0xf1, 0x59, 0x70, - 0xc8, 0x01, 0x59, 0x39, 0x6e, 0x8e, 0xbb, 0x7c, 0xb4, 0xe5, 0x3d, 0xf1, 0x6b, 0xe0, 0x98, 0xa9, - 0x12, 0x63, 0x08, 0x15, 0xb5, 0x87, 0x06, 0x26, 0xc9, 0xcd, 0xd8, 0xe6, 0xaa, 0xf4, 0xf4, 0x79, - 0x31, 0xf5, 0xdb, 0xf3, 0xe2, 0xbc, 0x6e, 0x90, 0xee, 0xa0, 0x2d, 0x75, 0x50, 0xcf, 0xa3, 0xe0, - 0x7d, 0x2c, 0x60, 0xed, 0x81, 0x4c, 0x1e, 0xf5, 0x21, 0x96, 0x96, 0x4d, 0xd2, 0xfa, 0x9f, 0xeb, - 0x64, 0xc9, 0xf1, 0x51, 0xb9, 0xf4, 0xd9, 0x8b, 0x27, 0x25, 0x2f, 0xc2, 0xe7, 0x2f, 0x9e, 0x94, - 0x4e, 0x07, 0x44, 0xc3, 0xac, 0xc4, 0x4f, 0x38, 0x90, 0x0d, 0x2f, 0xb5, 0x20, 0xee, 0x23, 0x13, - 0x43, 0x7e, 0x13, 0x1c, 0xc1, 0x44, 0x21, 0xe8, 0x01, 0x34, 0x1d, 0xca, 0xe9, 0x72, 0x5e, 0xf2, - 0x44, 0xb0, 0x15, 0x93, 0x3c, 0xc5, 0xa4, 0x5b, 0xc8, 0x30, 0xab, 0xaf, 0xdb, 0x74, 0xbf, 0xff, - 0xbd, 0x78, 0x79, 0x0a, 0xba, 0xf6, 0x06, 0xdc, 0x3a, 0x8c, 0xc9, 0xba, 0xed, 0x5b, 0xfc, 0xc1, - 0xd5, 0xaa, 0x05, 0x35, 0x08, 0x7b, 0xae, 0x56, 0x02, 0x38, 0x62, 0x39, 0x8f, 0x81, 0x5a, 0xc1, - 0x33, 0xff, 0x2e, 0x38, 0xe1, 0xd3, 0xfa, 0x77, 0x8a, 0x1d, 0xf3, 0x08, 0x78, 0x92, 0x5d, 0xb1, - 0x25, 0x0b, 0xc2, 0xc4, 0x44, 0xa3, 0xe8, 0x89, 0x8f, 0x5d, 0xd1, 0xa8, 0xa5, 0x40, 0x34, 0x13, - 0x78, 0x85, 0xd8, 0x3f, 0xe1, 0xd2, 0x6e, 0x00, 0x57, 0xbc, 0xaf, 0x38, 0x70, 0xb2, 0x81, 0xf5, - 0x5b, 0xc8, 0xdc, 0x34, 0xac, 0x5e, 0x0d, 0x6e, 0x41, 0x5d, 0x25, 0x06, 0x32, 0x6d, 0x09, 0x51, - 0x1f, 0x5a, 0x2a, 0x41, 0x81, 0x84, 0xfe, 0x33, 0x7f, 0x06, 0x1c, 0xb5, 0x60, 0x07, 0x59, 0x9a, - 0x62, 0x68, 0x8e, 0x78, 0x07, 0x6d, 0x7d, 0xed, 0x85, 0x65, 0x8d, 0x3f, 0x0d, 0x0e, 0x93, 0x91, - 0xd2, 0x55, 0x71, 0x37, 0x77, 0xc0, 0x3d, 0xa8, 0x64, 0x74, 0x47, 0xc5, 0xdd, 0x8a, 0xec, 0x08, - 0xe4, 0x3b, 0xb1, 0x05, 0x3a, 0x4b, 0x0b, 0x14, 0xa3, 0x20, 0x16, 0xc0, 0x6b, 0xac, 0x75, 0x5f, - 0x2b, 0xf1, 0x6b, 0x57, 0x46, 0x0f, 0xb0, 0x61, 0x6a, 0xfb, 0xc9, 0x7e, 0x31, 0xc6, 0xbe, 0xc8, - 0x60, 0x4f, 0x93, 0x10, 0xe7, 0x40, 0x81, 0x6d, 0x09, 0x32, 0xf8, 0x8e, 0xa3, 0x53, 0xdc, 0x30, - 0xdb, 0xc8, 0xd4, 0xa0, 0xe6, 0x54, 0x66, 0x6d, 0x1b, 0xc2, 0xfe, 0x3e, 0xe4, 0xf1, 0x66, 0x2c, - 0x8f, 0x8b, 0xcc, 0x3c, 0xa2, 0x54, 0xc4, 0x79, 0x70, 0x61, 0x9c, 0x3d, 0xc8, 0xe9, 0x6f, 0x0e, - 0xe4, 0x1b, 0x58, 0x5f, 0xd2, 0x3e, 0x1c, 0x60, 0xe2, 0x55, 0x0d, 0x6a, 0x55, 0x75, 0x4b, 0x35, - 0x3b, 0x70, 0x6c, 0x42, 0xef, 0x83, 0xd9, 0x97, 0x1a, 0x29, 0x68, 0x73, 0x13, 0xc3, 0x57, 0x7d, - 0x37, 0x33, 0x2f, 0x1d, 0x35, 0x1d, 0x3f, 0xfc, 0x55, 0x30, 0x3b, 0x54, 0xb7, 0x0c, 0xcd, 0x8e, - 0xa4, 0xa8, 0x9a, 0x66, 0x41, 0x8c, 0x3d, 0x69, 0x32, 0x81, 0x61, 0xc9, 0x5d, 0xaf, 0xdc, 0x88, - 0x89, 0x24, 0xd2, 0x22, 0xb1, 0x73, 0x13, 0xcf, 0x83, 0x73, 0x89, 0xc6, 0x40, 0x9e, 0x3f, 0x67, - 0x80, 0xd8, 0xc0, 0xfa, 0x46, 0x5f, 0x53, 0x09, 0x5c, 0x36, 0x4d, 0x68, 0xd9, 0x6d, 0xa0, 0xd7, - 0x77, 0xce, 0x85, 0x4a, 0x60, 0x15, 0x0d, 0x4c, 0x0d, 0xf3, 0x39, 0x70, 0xb8, 0x63, 0x41, 0x4a, - 0x26, 0xff, 0x91, 0xdf, 0x06, 0xf9, 0x9e, 0x61, 0x2a, 0x86, 0xbd, 0x55, 0xb1, 0x82, 0xbd, 0x8a, - 0xa5, 0x12, 0xe8, 0xa9, 0xf5, 0xf6, 0x1e, 0xd4, 0xaa, 0xc1, 0xce, 0x2f, 0x3f, 0x2e, 0x00, 0xaf, - 0xbf, 0xd4, 0x60, 0xa7, 0x95, 0xed, 0x19, 0x26, 0x83, 0x98, 0x13, 0x58, 0x1d, 0x25, 0x04, 0x3e, - 0xf0, 0x9f, 0x04, 0x56, 0x47, 0x8c, 0xc0, 0xee, 0x91, 0xf5, 0xf3, 0xb7, 0x8b, 0x31, 0x4f, 0x17, - 0xc3, 0x55, 0x92, 0x25, 0xa2, 0x78, 0x0d, 0x94, 0x26, 0x4b, 0x1d, 0x54, 0xe6, 0x3e, 0x98, 0x75, - 0x9a, 0x32, 0x1e, 0xf4, 0xe0, 0x1d, 0x84, 0xc9, 0x7d, 0x64, 0xc2, 0xe4, 0x3a, 0x54, 0xae, 0x46, - 0x59, 0x09, 0xe1, 0x76, 0x4f, 0xbb, 0x11, 0xcf, 0x38, 0xef, 0x44, 0x78, 0x31, 0x08, 0xdc, 0x05, - 0x39, 0xc7, 0xb8, 0x69, 0x41, 0xdc, 0x8d, 0x88, 0x9e, 0x1c, 0xbf, 0x1c, 0x8d, 0x7f, 0x2e, 0x1c, - 0x9f, 0xe1, 0x4d, 0x14, 0xc1, 0x5c, 0x92, 0x2d, 0x60, 0xf3, 0xb3, 0xdb, 0x93, 0x9a, 0x43, 0x68, - 0x6d, 0x5b, 0x06, 0x81, 0x74, 0xe3, 0xb5, 0x9b, 0xcb, 0x98, 0xa3, 0xb9, 0x1a, 0x7a, 0x81, 0xdd, - 0x5e, 0xe4, 0x1c, 0xc9, 0x74, 0xf9, 0x9c, 0x14, 0x99, 0xbf, 0xa4, 0xa8, 0x5f, 0xfa, 0x9d, 0x75, - 0x57, 0x2a, 0x6f, 0x44, 0x53, 0x0c, 0xb5, 0xaa, 0x44, 0x86, 0x5e, 0xab, 0x4a, 0xb4, 0x07, 0xa9, - 0xfe, 0xc4, 0x81, 0x33, 0x34, 0xd0, 0xed, 0x6a, 0x86, 0xa9, 0x4f, 0xcc, 0xf4, 0x1d, 0x90, 0x19, - 0xf8, 0xe0, 0x70, 0xa2, 0x73, 0xb1, 0x44, 0x23, 0x5e, 0x5b, 0x27, 0x06, 0xe1, 0x85, 0xca, 0xcd, - 0x68, 0x9a, 0x17, 0x98, 0x69, 0x46, 0xfc, 0x88, 0x17, 0xc1, 0xf9, 0x31, 0xe6, 0xc4, 0x7a, 0x52, - 0x65, 0x9f, 0xa2, 0x9e, 0xf4, 0x7b, 0x3e, 0xbe, 0x9e, 0x51, 0xbf, 0xad, 0x8c, 0x15, 0x59, 0x99, - 0xb6, 0x9e, 0x51, 0x4f, 0xd1, 0x7a, 0xc6, 0x22, 0xf9, 0xa9, 0x7e, 0x04, 0x4e, 0x35, 0xb0, 0xbe, - 0x06, 0x49, 0xd3, 0xeb, 0xdc, 0x5e, 0x3f, 0x77, 0x66, 0x67, 0x43, 0x37, 0xa9, 0xd9, 0xd9, 0x79, - 0x0a, 0xdd, 0x46, 0x33, 0xe1, 0xdb, 0xa8, 0x22, 0xb9, 0x23, 0xb0, 0x03, 0xb4, 0xb9, 0x16, 0x68, - 0xae, 0xf1, 0x18, 0x62, 0x11, 0x9c, 0x65, 0x1a, 0x7c, 0x76, 0xa5, 0x87, 0x20, 0xeb, 0xa7, 0xa0, - 0xb6, 0xb7, 0xa0, 0xcb, 0x7d, 0xfd, 0x51, 0xdf, 0xbe, 0x14, 0xb3, 0xad, 0xfa, 0xad, 0x66, 0xab, - 0xa6, 0xac, 0xbf, 0x77, 0xb7, 0xae, 0xd4, 0xea, 0x2b, 0xf5, 0xdb, 0x4b, 0xeb, 0xcb, 0xcd, 0xd5, - 0x4c, 0x8a, 0xcf, 0x83, 0x53, 0xb4, 0x6d, 0x63, 0xb5, 0xda, 0x5c, 0xad, 0x2d, 0xaf, 0xde, 0xce, - 0x70, 0xd1, 0x6d, 0xad, 0x7a, 0xad, 0xde, 0xb8, 0xeb, 0x6c, 0x9b, 0x11, 0x0e, 0x3e, 0xfe, 0xa6, - 0x90, 0x2a, 0xff, 0x95, 0x06, 0x07, 0x1a, 0x58, 0xe7, 0xef, 0x81, 0x34, 0xfd, 0xaf, 0x44, 0x31, - 0x56, 0xbc, 0xf0, 0x08, 0x2f, 0x5c, 0x9a, 0x00, 0x08, 0xc6, 0xd5, 0x7b, 0x20, 0x4d, 0xcf, 0xdd, - 0x4c, 0xc7, 0x14, 0x80, 0xed, 0x98, 0x35, 0x07, 0x1b, 0x60, 0x36, 0x3e, 0x93, 0x5e, 0x64, 0xed, - 0x8e, 0xc1, 0x84, 0x85, 0xa9, 0x60, 0x41, 0x28, 0x04, 0xfe, 0xcf, 0x1a, 0x21, 0x2f, 0x8d, 0xf1, - 0x42, 0x03, 0x05, 0x79, 0x4a, 0x60, 0x10, 0xf0, 0x53, 0x0e, 0xe4, 0x93, 0x47, 0xbe, 0x85, 0xb1, - 0xee, 0xa2, 0x70, 0xe1, 0xe6, 0x9e, 0xe0, 0x01, 0x87, 0x11, 0xc8, 0x26, 0x4c, 0x68, 0x25, 0x96, - 0x43, 0x36, 0x56, 0x28, 0x4f, 0x8f, 0x0d, 0x22, 0x7f, 0xc9, 0x81, 0xe2, 0xa4, 0xe9, 0xe7, 0x3a, - 0xcb, 0xef, 0x84, 0x4d, 0xc2, 0x5b, 0xaf, 0xb0, 0x29, 0x60, 0xf5, 0x01, 0x38, 0x1e, 0xb9, 0xf9, - 0x45, 0xf6, 0x51, 0xa5, 0x31, 0x42, 0x69, 0x32, 0x26, 0x88, 0x30, 0x00, 0xa7, 0xd8, 0x57, 0xfc, - 0x15, 0xb6, 0x13, 0x06, 0x54, 0x58, 0x9c, 0x1a, 0x1a, 0x3a, 0x6c, 0xc9, 0x77, 0x39, 0xf3, 0xb0, - 0x25, 0xc2, 0xd9, 0x87, 0x6d, 0xe2, 0x3d, 0xcb, 0x7f, 0x0c, 0x72, 0x89, 0x77, 0xec, 0xb5, 0xb1, - 0x2e, 0x23, 0x68, 0xe1, 0xc6, 0x5e, 0xd0, 0x6c, 0x0d, 0x62, 0xf7, 0xdf, 0x78, 0x0d, 0xa2, 0xf0, - 0x09, 0x1a, 0x24, 0xdd, 0x4d, 0xfc, 0x16, 0xe0, 0x19, 0x17, 0xd3, 0x3c, 0xcb, 0x59, 0x1c, 0x27, - 0x48, 0xd3, 0xe1, 0xfc, 0x68, 0xd5, 0x95, 0xa7, 0x3b, 0x05, 0xee, 0xd9, 0x4e, 0x81, 0xfb, 0x63, - 0xa7, 0xc0, 0x7d, 0xb1, 0x5b, 0x48, 0x3d, 0xdb, 0x2d, 0xa4, 0x7e, 0xdd, 0x2d, 0xa4, 0xee, 0x97, - 0xa9, 0xd1, 0x7c, 0xcd, 0xf1, 0xb9, 0xb0, 0xa2, 0xb6, 0xb1, 0xec, 0xfd, 0x20, 0x35, 0x2c, 0x97, - 0xe5, 0x11, 0xf5, 0xf3, 0x99, 0x3d, 0xaa, 0xb7, 0x0f, 0x39, 0x3f, 0x4a, 0x5d, 0xff, 0x27, 0x00, - 0x00, 0xff, 0xff, 0xae, 0x9c, 0xa1, 0xe8, 0x5e, 0x13, 0x00, 0x00, + 0x42, 0x42, 0x02, 0x71, 0xa8, 0x38, 0x21, 0x71, 0xe2, 0xc0, 0x89, 0x0b, 0x70, 0xa1, 0x07, 0x6e, + 0x5c, 0x38, 0xf6, 0x58, 0x71, 0x42, 0x1c, 0x0a, 0x4a, 0x0e, 0x15, 0xff, 0x00, 0x5c, 0xd1, 0xfe, + 0xec, 0xec, 0xee, 0xac, 0xed, 0x14, 0x72, 0x89, 0xbd, 0xf3, 0x3e, 0xf3, 0xde, 0xe7, 0x7d, 0xde, + 0xec, 0x9b, 0x17, 0x83, 0x1c, 0x26, 0x96, 0xa1, 0x41, 0x19, 0x13, 0xf5, 0x01, 0x24, 0x86, 0x2a, + 0x93, 0x91, 0xd4, 0xb7, 0x10, 0x41, 0xfc, 0x09, 0xd7, 0x22, 0xf9, 0x16, 0xe1, 0x74, 0x07, 0xe1, + 0x1e, 0xc2, 0x72, 0x0f, 0xeb, 0xf2, 0x70, 0xd1, 0xfe, 0x70, 0x91, 0xc2, 0xac, 0xda, 0x33, 0x4c, + 0x24, 0x3b, 0x7f, 0xbd, 0xa5, 0x93, 0x3a, 0xd2, 0x91, 0xf3, 0x55, 0xb6, 0xbf, 0x79, 0xab, 0x05, + 0xcf, 0x43, 0x5b, 0xc5, 0x50, 0x1e, 0x2e, 0xb6, 0x21, 0x51, 0x17, 0xe5, 0x0e, 0x32, 0x4c, 0xcf, + 0x9e, 0x77, 0xed, 0x8a, 0xbb, 0xd1, 0x7d, 0xf0, 0xb7, 0x46, 0x79, 0xfa, 0x5f, 0x5c, 0xbb, 0xf8, + 0x2d, 0x07, 0x8e, 0x37, 0xb0, 0xbe, 0x62, 0x3c, 0x1c, 0x18, 0xda, 0x9a, 0x6d, 0xe3, 0xb3, 0xe0, + 0x90, 0x03, 0xb2, 0x72, 0xdc, 0x1c, 0x77, 0xf9, 0x68, 0xcb, 0x7b, 0xe2, 0xd7, 0xc0, 0x31, 0x53, + 0x25, 0xc6, 0x10, 0x2a, 0x6a, 0x0f, 0x0d, 0x4c, 0x92, 0x9b, 0xb1, 0xcd, 0x55, 0xe9, 0xe9, 0xf3, + 0x62, 0xea, 0xb7, 0xe7, 0xc5, 0x79, 0xdd, 0x20, 0xdd, 0x41, 0x5b, 0xea, 0xa0, 0x9e, 0x47, 0xc1, + 0xfb, 0x58, 0xc0, 0xda, 0x03, 0x99, 0x3c, 0xea, 0x43, 0x2c, 0x2d, 0x9b, 0xa4, 0xf5, 0x3f, 0xd7, + 0xc9, 0x92, 0xe3, 0xa3, 0x72, 0xe5, 0xd3, 0x17, 0x4f, 0x4a, 0x5e, 0x84, 0xcf, 0x5f, 0x3c, 0x29, + 0x9d, 0x0e, 0x88, 0x86, 0x59, 0xe5, 0x38, 0xf1, 0x33, 0x0e, 0x64, 0xc3, 0x8b, 0x2d, 0x88, 0xfb, + 0xc8, 0xc4, 0x90, 0xdf, 0x04, 0x47, 0x30, 0x51, 0x08, 0x7a, 0x00, 0x4d, 0x87, 0x74, 0xba, 0x9c, + 0x97, 0x3c, 0x19, 0x6c, 0xcd, 0x24, 0x4f, 0x33, 0xe9, 0x16, 0x32, 0xcc, 0xea, 0xeb, 0x36, 0xe1, + 0xef, 0x7f, 0x2f, 0x5e, 0x9e, 0x82, 0xb0, 0xbd, 0x01, 0xb7, 0x0e, 0x63, 0xb2, 0x6e, 0xfb, 0xae, + 0xcc, 0xe4, 0x38, 0xf1, 0x07, 0x57, 0xb1, 0x16, 0xd4, 0x20, 0xec, 0xb9, 0x8a, 0x09, 0xe0, 0x88, + 0xe5, 0x3c, 0x06, 0x9a, 0x05, 0xcf, 0xfc, 0xbb, 0xe0, 0x84, 0x4f, 0xed, 0xdf, 0xe9, 0x76, 0xcc, + 0x23, 0x41, 0x0b, 0x17, 0x84, 0x89, 0x49, 0x47, 0xd1, 0x13, 0x1f, 0xbb, 0xc2, 0x51, 0x4b, 0x81, + 0x70, 0x26, 0xf0, 0xca, 0xb1, 0x7f, 0xe2, 0xa5, 0xdd, 0x00, 0x0e, 0x77, 0xf1, 0x2b, 0x0e, 0x9c, + 0x6c, 0x60, 0xfd, 0x16, 0x32, 0x37, 0x0d, 0xab, 0x57, 0x83, 0x5b, 0x50, 0x57, 0x89, 0x81, 0x4c, + 0x5b, 0x42, 0xd4, 0x87, 0x96, 0x4a, 0x50, 0x20, 0xa1, 0xff, 0xcc, 0x9f, 0x01, 0x47, 0x2d, 0xd8, + 0x41, 0x96, 0xa6, 0x18, 0x9a, 0x23, 0xde, 0x41, 0x5b, 0x5f, 0x7b, 0x61, 0x59, 0xe3, 0x4f, 0x83, + 0xc3, 0x64, 0xa4, 0x74, 0x55, 0xdc, 0xcd, 0x1d, 0x70, 0x8f, 0x2b, 0x19, 0xdd, 0x51, 0x71, 0xb7, + 0x22, 0x3b, 0x02, 0xf9, 0x4e, 0x6c, 0x81, 0xce, 0xd2, 0x02, 0xc5, 0x28, 0x88, 0x05, 0xf0, 0x1a, + 0x6b, 0xdd, 0xd7, 0x4a, 0xfc, 0xda, 0x95, 0xd1, 0x03, 0x6c, 0x98, 0xda, 0x7e, 0xb2, 0x5f, 0x8c, + 0xb1, 0x2f, 0x32, 0xd8, 0xd3, 0x24, 0xc4, 0x39, 0x50, 0x60, 0x5b, 0x82, 0x0c, 0xbe, 0xe3, 0xe8, + 0x14, 0x37, 0xcc, 0x36, 0x32, 0x35, 0xa8, 0x39, 0x95, 0x59, 0xdb, 0x86, 0xb0, 0xbf, 0x0f, 0x79, + 0xbc, 0x19, 0xcb, 0xe3, 0x22, 0x33, 0x8f, 0x28, 0x15, 0x71, 0x1e, 0x5c, 0x18, 0x67, 0x0f, 0x72, + 0xfa, 0x9b, 0x03, 0xf9, 0x06, 0xd6, 0x97, 0xb4, 0x0f, 0x07, 0x98, 0x78, 0x55, 0x83, 0x5a, 0x55, + 0xdd, 0x52, 0xcd, 0x0e, 0x1c, 0x9b, 0xd0, 0xfb, 0x60, 0xf6, 0xa5, 0x46, 0x0a, 0xda, 0xdc, 0xc4, + 0xf0, 0x55, 0xdf, 0xcd, 0xcc, 0x4b, 0x47, 0x4d, 0xc7, 0x0f, 0x7f, 0x15, 0xcc, 0x0e, 0xd5, 0x2d, + 0x43, 0xb3, 0x23, 0x29, 0xaa, 0xa6, 0x59, 0x10, 0x63, 0x4f, 0x9a, 0x4c, 0x60, 0x58, 0x72, 0xd7, + 0x2b, 0x37, 0x62, 0x22, 0x89, 0xb4, 0x48, 0xec, 0xdc, 0xc4, 0xf3, 0xe0, 0x5c, 0xa2, 0x31, 0x90, + 0xe7, 0xcf, 0x19, 0x20, 0x36, 0xb0, 0xbe, 0xd1, 0xd7, 0x54, 0x02, 0x97, 0x4d, 0x13, 0x5a, 0x76, + 0x1b, 0xe8, 0xf5, 0x9d, 0x73, 0xa1, 0x12, 0x58, 0x45, 0x03, 0x53, 0xc3, 0x7c, 0x0e, 0x1c, 0xee, + 0x58, 0x90, 0x92, 0xc9, 0x7f, 0xe4, 0xb7, 0x41, 0xbe, 0x67, 0x98, 0x8a, 0x61, 0x6f, 0x55, 0xac, + 0x60, 0xaf, 0x62, 0xa9, 0x04, 0x7a, 0x6a, 0xbd, 0xbd, 0x07, 0xb5, 0x6a, 0xb0, 0xf3, 0xcb, 0x8f, + 0x0b, 0xc0, 0xeb, 0x2f, 0x35, 0xd8, 0x69, 0x65, 0x7b, 0x86, 0xc9, 0x20, 0xe6, 0x04, 0x56, 0x47, + 0x09, 0x81, 0x0f, 0xfc, 0x27, 0x81, 0xd5, 0x11, 0x23, 0xb0, 0x7b, 0x64, 0xfd, 0xfc, 0xed, 0x62, + 0xcc, 0xd3, 0xc5, 0x70, 0x95, 0x64, 0x89, 0x28, 0x5e, 0x03, 0xa5, 0xc9, 0x52, 0x07, 0x95, 0xb9, + 0x0f, 0x66, 0x9d, 0xa6, 0x8c, 0x07, 0x3d, 0x78, 0x07, 0x61, 0x72, 0x1f, 0x99, 0x30, 0xb9, 0x0e, + 0x95, 0xab, 0x51, 0x56, 0x42, 0xb8, 0xdd, 0xd3, 0x6e, 0xc4, 0x33, 0xce, 0x3b, 0x11, 0x5e, 0x0c, + 0x02, 0x77, 0x41, 0xce, 0x31, 0x6e, 0x5a, 0x10, 0x77, 0x23, 0xa2, 0x27, 0xc7, 0x2f, 0x47, 0xe3, + 0x9f, 0x0b, 0xc7, 0x67, 0x78, 0x13, 0x45, 0x30, 0x97, 0x64, 0x0b, 0xd8, 0xfc, 0xec, 0xf6, 0xa4, + 0xe6, 0x10, 0x5a, 0xdb, 0x96, 0x41, 0x20, 0xdd, 0x78, 0xed, 0xe6, 0x32, 0xe6, 0x68, 0xae, 0x86, + 0x5e, 0x60, 0xb7, 0x17, 0x39, 0x47, 0x32, 0x5d, 0x3e, 0x27, 0x45, 0xa6, 0x30, 0x29, 0xea, 0x97, + 0x7e, 0x67, 0xdd, 0x95, 0xca, 0x1b, 0xd1, 0x14, 0x43, 0xad, 0x2a, 0x91, 0xa1, 0xd7, 0xaa, 0x12, + 0xed, 0x41, 0xaa, 0x3f, 0x71, 0xe0, 0x0c, 0x0d, 0x74, 0xbb, 0x9a, 0x61, 0xea, 0x13, 0x33, 0x7d, + 0x07, 0x64, 0x06, 0x3e, 0x38, 0x9c, 0xe8, 0x5c, 0x2c, 0xd1, 0x88, 0xd7, 0xd6, 0x89, 0x41, 0x78, + 0xa1, 0x72, 0x33, 0x9a, 0xe6, 0x05, 0x66, 0x9a, 0x11, 0x3f, 0xe2, 0x45, 0x70, 0x7e, 0x8c, 0x39, + 0xb1, 0x9e, 0x54, 0xd9, 0xa7, 0xa8, 0x27, 0xfd, 0x9e, 0x8f, 0xaf, 0x67, 0xd4, 0x6f, 0x2b, 0x63, + 0x45, 0x56, 0xa6, 0xad, 0x67, 0xd4, 0x53, 0xb4, 0x9e, 0xb1, 0x48, 0x7e, 0xaa, 0x1f, 0x81, 0x53, + 0x0d, 0xac, 0xaf, 0x41, 0xd2, 0xf4, 0x3a, 0xb7, 0xd7, 0xcf, 0x9d, 0x09, 0xda, 0xd0, 0x4d, 0x6a, + 0x82, 0x76, 0x9e, 0x42, 0xb7, 0xd1, 0x4c, 0xf8, 0x36, 0xaa, 0x48, 0xee, 0x20, 0xec, 0x00, 0x6d, + 0xae, 0x05, 0x9a, 0x6b, 0x3c, 0x86, 0x58, 0x04, 0x67, 0x99, 0x06, 0x9f, 0x5d, 0xe9, 0x21, 0xc8, + 0xfa, 0x29, 0xa8, 0xed, 0x2d, 0xe8, 0x72, 0x5f, 0x7f, 0xd4, 0xb7, 0x2f, 0xc5, 0x6c, 0xab, 0x7e, + 0xab, 0xd9, 0xaa, 0x29, 0xeb, 0xef, 0xdd, 0xad, 0x2b, 0xb5, 0xfa, 0x4a, 0xfd, 0xf6, 0xd2, 0xfa, + 0x72, 0x73, 0x35, 0x93, 0xe2, 0xf3, 0xe0, 0x14, 0x6d, 0xdb, 0x58, 0xad, 0x36, 0x57, 0x6b, 0xcb, + 0xab, 0xb7, 0x33, 0x5c, 0x74, 0x5b, 0xab, 0x5e, 0xab, 0x37, 0xee, 0x3a, 0xdb, 0x66, 0x84, 0x83, + 0x8f, 0xbf, 0x29, 0xa4, 0xca, 0x7f, 0xa5, 0xc1, 0x81, 0x06, 0xd6, 0xf9, 0x7b, 0x20, 0x4d, 0xff, + 0x43, 0x51, 0x8c, 0x15, 0x2f, 0x3c, 0xc6, 0x0b, 0x97, 0x26, 0x00, 0x82, 0x71, 0xf5, 0x1e, 0x48, + 0xd3, 0x73, 0x37, 0xd3, 0x31, 0x05, 0x60, 0x3b, 0x66, 0xcd, 0xc1, 0x06, 0x98, 0x8d, 0xcf, 0xa4, + 0x17, 0x59, 0xbb, 0x63, 0x30, 0x61, 0x61, 0x2a, 0x58, 0x10, 0x0a, 0x81, 0xff, 0xb3, 0x46, 0xc8, + 0x4b, 0x63, 0xbc, 0xd0, 0x40, 0x41, 0x9e, 0x12, 0x18, 0x04, 0xfc, 0x84, 0x03, 0xf9, 0xe4, 0x91, + 0x6f, 0x61, 0xac, 0xbb, 0x28, 0x5c, 0xb8, 0xb9, 0x27, 0x78, 0xc0, 0x61, 0x04, 0xb2, 0x09, 0x13, + 0x5a, 0x89, 0xe5, 0x90, 0x8d, 0x15, 0xca, 0xd3, 0x63, 0x83, 0xc8, 0x5f, 0x72, 0xa0, 0x38, 0x69, + 0xfa, 0xb9, 0xce, 0xf2, 0x3b, 0x61, 0x93, 0xf0, 0xd6, 0x2b, 0x6c, 0x0a, 0x58, 0x7d, 0x00, 0x8e, + 0x47, 0x6e, 0x7e, 0x91, 0x7d, 0x54, 0x69, 0x8c, 0x50, 0x9a, 0x8c, 0x09, 0x22, 0x0c, 0xc0, 0x29, + 0xf6, 0x15, 0x7f, 0x85, 0xed, 0x84, 0x01, 0x15, 0x16, 0xa7, 0x86, 0x86, 0x0e, 0x5b, 0xf2, 0x5d, + 0xce, 0x3c, 0x6c, 0x89, 0x70, 0xf6, 0x61, 0x9b, 0x78, 0xcf, 0xf2, 0x1f, 0x83, 0x5c, 0xe2, 0x1d, + 0x7b, 0x6d, 0xac, 0xcb, 0x08, 0x5a, 0xb8, 0xb1, 0x17, 0x34, 0x5b, 0x83, 0xd8, 0xfd, 0x37, 0x5e, + 0x83, 0x28, 0x7c, 0x82, 0x06, 0x49, 0x77, 0x13, 0xbf, 0x05, 0x78, 0xc6, 0xc5, 0x34, 0xcf, 0x72, + 0x16, 0xc7, 0x09, 0xd2, 0x74, 0x38, 0x3f, 0x5a, 0x75, 0xe5, 0xe9, 0x4e, 0x81, 0x7b, 0xb6, 0x53, + 0xe0, 0xfe, 0xd8, 0x29, 0x70, 0x5f, 0xec, 0x16, 0x52, 0xcf, 0x76, 0x0b, 0xa9, 0x5f, 0x77, 0x0b, + 0xa9, 0xfb, 0x65, 0x6a, 0x34, 0x5f, 0x73, 0x7c, 0x2e, 0xac, 0xa8, 0x6d, 0x2c, 0x7b, 0x3f, 0x4b, + 0x0d, 0xcb, 0x65, 0x79, 0x44, 0xfd, 0x88, 0x66, 0x8f, 0xea, 0xed, 0x43, 0xce, 0x4f, 0x53, 0xd7, + 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x22, 0xfe, 0x85, 0x64, 0x13, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used.