0g-chain/x/liquid/keeper/derivative_test.go

551 lines
18 KiB
Go
Raw Normal View History

liquid staking (#1273) * proto types * proto generated types * liquidstaking top level files: module, genesis * liquidstaking types * liquidstaking keeper * liquidstaking client/cli * add liquidstaking to app, simapp * implement mint derivative * set up liquidstaking keeper test suite * test mint derivative * rename module to liquid * rename proto types, app.go to liquid * use sdk.Coin instead of shares * mint liquid tokens to delegator * burn derivative tokens to receive delegation * use conversion method instead of type cast * simplify delegation transfer logic * broaden delegation transfer tests * simplify transfer delegation method This removes a source of rounding errors * move derivative denom to keeper config * check for invalid coins in msg validation * block 0share transfers to avoid handling edge case * refactor MintDerivative to test calculations * simplify burn method so shares and tokens equal * convert TransferShares back to old design this makes handling vesting tokens easier * fix missed merge conflict * remove deprecated constants * tidy up msg.go * add msg tests * remove unused store key * fix msg event sender * remove unused params * tidy up documentation and errors * remove unused mocks * remove unused keepers from AppModule * tidy up msg return values keeper return values to be used in router msgs * reinstate unintentionally removed interface check * catch invalid input for MnitDerivative clear up test TODOs * clear up InitGenesis TODO * Update x/liquid/client/cli/tx.go Co-authored-by: Derrick Lee <derrick@dlee.dev> * Update x/liquid/client/cli/tx.go Co-authored-by: Derrick Lee <derrick@dlee.dev> * show error logs in devnet * unblock mod account so it can receive dist rewards * catch zero amout msgs early * minor cli fixes Co-authored-by: rhuairahrighairigh <ruaridh.odonnell@gmail.com> Co-authored-by: Ruaridh <rhuairahrighairidh@users.noreply.github.com> Co-authored-by: Derrick Lee <derrick@dlee.dev>
2022-09-15 22:00:32 +00:00
package keeper_test
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/staking"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/x/liquid/types"
)
func (suite *KeeperTestSuite) TestBurnDerivative() {
_, addrs := app.GeneratePrivKeyAddressPairs(5)
valAccAddr, user := addrs[0], addrs[1]
valAddr := sdk.ValAddress(valAccAddr)
liquidDenom := suite.Keeper.GetLiquidStakingTokenDenom(valAddr)
testCases := []struct {
name string
balance sdk.Coin
moduleDelegation sdk.Int
burnAmount sdk.Coin
expectedErr error
}{
{
name: "user can burn their entire balance",
balance: c(liquidDenom, 1e9),
moduleDelegation: i(1e9),
burnAmount: c(liquidDenom, 1e9),
},
{
name: "user can burn minimum derivative unit",
balance: c(liquidDenom, 1e9),
moduleDelegation: i(1e9),
burnAmount: c(liquidDenom, 1),
},
{
name: "error when denom cannot be parsed",
balance: c(liquidDenom, 1e9),
moduleDelegation: i(1e9),
burnAmount: c(fmt.Sprintf("ckava-%s", valAddr), 1e6),
expectedErr: types.ErrInvalidDenom,
},
{
name: "error when burn amount is 0",
balance: c(liquidDenom, 1e9),
moduleDelegation: i(1e9),
burnAmount: c(liquidDenom, 0),
expectedErr: types.ErrUntransferableShares,
},
{
name: "error when user doesn't have enough funds",
balance: c("ukava", 10),
moduleDelegation: i(1e9),
burnAmount: c(liquidDenom, 1e9),
expectedErr: sdkerrors.ErrInsufficientFunds,
},
{
name: "error when backing delegation isn't large enough",
balance: c(liquidDenom, 1e9),
moduleDelegation: i(999_999_999),
burnAmount: c(liquidDenom, 1e9),
expectedErr: stakingtypes.ErrNotEnoughDelegationShares,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()
suite.CreateAccountWithAddress(valAccAddr, suite.NewBondCoins(i(1e6)))
suite.CreateAccountWithAddress(user, sdk.NewCoins(tc.balance))
suite.AddCoinsToModule(types.ModuleAccountName, suite.NewBondCoins(tc.moduleDelegation))
// create delegation from module account to back the derivatives
moduleAccAddress := authtypes.NewModuleAddress(types.ModuleAccountName)
suite.CreateNewUnbondedValidator(valAddr, i(1e6))
suite.CreateDelegation(valAddr, moduleAccAddress, tc.moduleDelegation)
staking.EndBlocker(suite.Ctx, suite.StakingKeeper)
modBalance := suite.BankKeeper.GetAllBalances(suite.Ctx, moduleAccAddress)
_, err := suite.Keeper.BurnDerivative(suite.Ctx, user, valAddr, tc.burnAmount)
suite.Require().ErrorIs(err, tc.expectedErr)
if tc.expectedErr != nil {
// if an error is expected, state should be reverted so don't need to test state is unchanged
return
}
suite.AccountBalanceEqual(user, sdk.NewCoins(tc.balance.Sub(tc.burnAmount)))
suite.AccountBalanceEqual(moduleAccAddress, modBalance) // ensure derivatives are burned, and not in module account
feat: upgrade to Cosmos v0.46 (#1477) * Update cosmos-sdk to v0.45.10-kava * Add RegisterNodeService to app * Update cosmos proto files * Update cosmos proto files * Use tagged v0.45.10-kava-v0.19-0.21 cosmos version * update x/auth/legacy to x/auth/migrations * Delete rest packages and registration * Remove rest from proposal handlers * Remove legacy types referencing removed sdk types * Remove legacy tx broadcast handler * Update incentive staking hooks to return error * Remove grpc replace directive, use new grpc version * Fix storetypes import * Update tally_handler with updated gov types * Delete legacy types * Use new gov default config * Update RegisterTendermintService params Signed-off-by: drklee3 <derrick@dlee.dev> * Replace sdk.StoreKey with storetypes.StoreKey * Replace sdk.Int#ToDec with sdk.NewDecFromInt * Replace sdk.NewUintFromBigInt with sdkmath.NewUintFromBigInt Signed-off-by: drklee3 <derrick@dlee.dev> * Update most intances of govtypes to govv1beta1 * Unpack coin slice for Coins#Sub and Coins#SafeSub Signed-off-by: drklee3 <derrick@dlee.dev> * Update committee gov codec registration Signed-off-by: drklee3 <derrick@dlee.dev> * Update migrate utils period_vesting Coins#Sub Signed-off-by: drklee3 <derrick@dlee.dev> * Update Coin#Sub in community proposal handler Signed-off-by: drklee3 <derrick@dlee.dev> * Update Coin#Sub, FundModuleAccount/FundAccount in banktestutil Signed-off-by: drklee3 <derrick@dlee.dev> * Update community, earn, kavadist proposal gov registration * Update evm cli client EthSecp256k1Type check * AccAddressFromHex to AccAddressFromHexUnsafe * Add mint DefaultInflationCalculationFn to earn test * Update use of removed staking.NewHandler * Rename FlagIAVLFastNode -> FlagDisableIAVLFastNode * cmd: Update new snapshot app option Signed-off-by: drklee3 <derrick@dlee.dev> * cmd: Add tendermint default config, use cosmos rpc status command Signed-off-by: drklee3 <derrick@dlee.dev> * Update ethermint import path github.com/tharsis/ethermint -> github.com/evmos/ethermint * Upgrade ibc-go to v6 * Update proto dependencies Signed-off-by: drklee3 <derrick@dlee.dev> * Update Tally handler test with new gov types * Update helpers.GenTx -> helpers.GenSignedMockTx * Update evmkeeper.NewKeeper params Signed-off-by: drklee3 <derrick@dlee.dev> * Update ante authz, tests * Add feemarket transient key, pass subspaces to evm/feemarket keepers * Update new ante decorators * Add new addModuleInitFlags to server commands * Pass codec to keyring.New in genaccounts * Pass codec to client keys add * Add SendCoins to evmutil bank_keeper * Use github.com/cosmos/iavl@v0.19.5 * Add ante HandlerOptions * Add unimplemented SendCoins to evmutil bank keeper Ethermint x/evm does not use this method * Update init-new-chain script to disable post-london blocks * Modify test genesis states to append 1 validator * Update tally handler test to use string values * Prevent querying balance for empty sdk.AccAddress in auction bidding test * Set default bond denom to ukava * Remove overwritten bank genesis total supply in committee proposal test Signed-off-by: drklee3 <derrick@dlee.dev> * Use ukava for testing staked balance * Disable minting in community proposal handler test Previously stake denom is used, which resulted in 0 minted coins * Update hard APYToSPY test expected value Increased iterations in sdk.ApproxRoot, updated closer to real value * Fix NewDecCoinsFromCoins bug in incentive collectDerivativeStakingRewards * Allow bkava earn incentive test values to match within small margin for rounding Signed-off-by: drklee3 <derrick@dlee.dev> * Update invalid denom in issuance message coin validation Colons are now valid in denoms Signed-off-by: drklee3 <derrick@dlee.dev> * Remove genesis validator in incentive delegation tests * Update pricefeed market test for invalid denom Signed-off-by: drklee3 <derrick@dlee.dev> * Update incentive delegator rewards test without genesis validator Signed-off-by: drklee3 <derrick@dlee.dev> * Add validator to export test * Clear bank state in minting tests Signed-off-by: drklee3 <derrick@dlee.dev> * Remove validator for no stake tally test Signed-off-by: drklee3 <derrick@dlee.dev> * Clear incentive state before InitGenesis in incentive genesis export test * Update swagger Signed-off-by: drklee3 <derrick@dlee.dev> * Update ethermint version to match replaced version * Remove legacy swagger * Add NewEthEmitEventDecorator * Remove redundant func for AddModuleInitFlags * Remove unused addBankBalanceForAddress func * Add SetIAVLLazyLoading option to app cmd * Use legacy.RegisterAminoMsg for committee msg concrete registration * Remove unnecessary Amino field * Add evm_util bankkeeper SendCoins comment * Update test method ResetBankState to DeleteGenesisValidatorCoins to be more clear * Validate incentive params.RewardsPerSecond to be non-zero * Validate swap pools to disallow colons in token denoms * Register all legacy amino types on gov modulecdc * Remove redundant Comittee interface registration * Pin goleveldb to v1.0.1-0.20210819022825-2ae1ddf74ef7 Causes failed to load state at height errors * Update ethermint to new pinned version with minGasPrices parse error fix * Update cosmos fork dependcy commit to include reverted account constructor patch * Update Cosmos v0.46.11 and cometbft v0.34.27 * Bump minimum go version to 1.19 * Update tendermint proto * Update internal testnet genesis * Move NewCanTransferDecorator before NewEthGasConsumeDecorator * Add hard borrow store tests (#1514) * add store tests for Borrow type * refactor Deposit tests to match * Fix old bep3 tests (#1515) * Update Ethermint to 1b17445 to fix duplicate proto registration * Add custom status command to use snake_case and stdout * Add SetInflation helper * Reduce ambiguity with evm CanSignEthTx error * Remove init genesis validator claim in test * Add disabled evmante.NewMinGasPriceDecorator with x/feemarket note * chore: use tagged versions for Cosmos and Ethermint forks * update kvtool & increase wait for ibc transfer test --------- Signed-off-by: drklee3 <derrick@dlee.dev> Co-authored-by: Ruaridh <rhuairahrighairidh@users.noreply.github.com> Co-authored-by: Robert Pirtle <astropirtle@gmail.com>
2023-04-04 00:08:45 +00:00
sharesTransferred := sdk.NewDecFromInt(tc.burnAmount.Amount)
liquid staking (#1273) * proto types * proto generated types * liquidstaking top level files: module, genesis * liquidstaking types * liquidstaking keeper * liquidstaking client/cli * add liquidstaking to app, simapp * implement mint derivative * set up liquidstaking keeper test suite * test mint derivative * rename module to liquid * rename proto types, app.go to liquid * use sdk.Coin instead of shares * mint liquid tokens to delegator * burn derivative tokens to receive delegation * use conversion method instead of type cast * simplify delegation transfer logic * broaden delegation transfer tests * simplify transfer delegation method This removes a source of rounding errors * move derivative denom to keeper config * check for invalid coins in msg validation * block 0share transfers to avoid handling edge case * refactor MintDerivative to test calculations * simplify burn method so shares and tokens equal * convert TransferShares back to old design this makes handling vesting tokens easier * fix missed merge conflict * remove deprecated constants * tidy up msg.go * add msg tests * remove unused store key * fix msg event sender * remove unused params * tidy up documentation and errors * remove unused mocks * remove unused keepers from AppModule * tidy up msg return values keeper return values to be used in router msgs * reinstate unintentionally removed interface check * catch invalid input for MnitDerivative clear up test TODOs * clear up InitGenesis TODO * Update x/liquid/client/cli/tx.go Co-authored-by: Derrick Lee <derrick@dlee.dev> * Update x/liquid/client/cli/tx.go Co-authored-by: Derrick Lee <derrick@dlee.dev> * show error logs in devnet * unblock mod account so it can receive dist rewards * catch zero amout msgs early * minor cli fixes Co-authored-by: rhuairahrighairigh <ruaridh.odonnell@gmail.com> Co-authored-by: Ruaridh <rhuairahrighairidh@users.noreply.github.com> Co-authored-by: Derrick Lee <derrick@dlee.dev>
2022-09-15 22:00:32 +00:00
suite.DelegationSharesEqual(valAddr, user, sharesTransferred)
feat: upgrade to Cosmos v0.46 (#1477) * Update cosmos-sdk to v0.45.10-kava * Add RegisterNodeService to app * Update cosmos proto files * Update cosmos proto files * Use tagged v0.45.10-kava-v0.19-0.21 cosmos version * update x/auth/legacy to x/auth/migrations * Delete rest packages and registration * Remove rest from proposal handlers * Remove legacy types referencing removed sdk types * Remove legacy tx broadcast handler * Update incentive staking hooks to return error * Remove grpc replace directive, use new grpc version * Fix storetypes import * Update tally_handler with updated gov types * Delete legacy types * Use new gov default config * Update RegisterTendermintService params Signed-off-by: drklee3 <derrick@dlee.dev> * Replace sdk.StoreKey with storetypes.StoreKey * Replace sdk.Int#ToDec with sdk.NewDecFromInt * Replace sdk.NewUintFromBigInt with sdkmath.NewUintFromBigInt Signed-off-by: drklee3 <derrick@dlee.dev> * Update most intances of govtypes to govv1beta1 * Unpack coin slice for Coins#Sub and Coins#SafeSub Signed-off-by: drklee3 <derrick@dlee.dev> * Update committee gov codec registration Signed-off-by: drklee3 <derrick@dlee.dev> * Update migrate utils period_vesting Coins#Sub Signed-off-by: drklee3 <derrick@dlee.dev> * Update Coin#Sub in community proposal handler Signed-off-by: drklee3 <derrick@dlee.dev> * Update Coin#Sub, FundModuleAccount/FundAccount in banktestutil Signed-off-by: drklee3 <derrick@dlee.dev> * Update community, earn, kavadist proposal gov registration * Update evm cli client EthSecp256k1Type check * AccAddressFromHex to AccAddressFromHexUnsafe * Add mint DefaultInflationCalculationFn to earn test * Update use of removed staking.NewHandler * Rename FlagIAVLFastNode -> FlagDisableIAVLFastNode * cmd: Update new snapshot app option Signed-off-by: drklee3 <derrick@dlee.dev> * cmd: Add tendermint default config, use cosmos rpc status command Signed-off-by: drklee3 <derrick@dlee.dev> * Update ethermint import path github.com/tharsis/ethermint -> github.com/evmos/ethermint * Upgrade ibc-go to v6 * Update proto dependencies Signed-off-by: drklee3 <derrick@dlee.dev> * Update Tally handler test with new gov types * Update helpers.GenTx -> helpers.GenSignedMockTx * Update evmkeeper.NewKeeper params Signed-off-by: drklee3 <derrick@dlee.dev> * Update ante authz, tests * Add feemarket transient key, pass subspaces to evm/feemarket keepers * Update new ante decorators * Add new addModuleInitFlags to server commands * Pass codec to keyring.New in genaccounts * Pass codec to client keys add * Add SendCoins to evmutil bank_keeper * Use github.com/cosmos/iavl@v0.19.5 * Add ante HandlerOptions * Add unimplemented SendCoins to evmutil bank keeper Ethermint x/evm does not use this method * Update init-new-chain script to disable post-london blocks * Modify test genesis states to append 1 validator * Update tally handler test to use string values * Prevent querying balance for empty sdk.AccAddress in auction bidding test * Set default bond denom to ukava * Remove overwritten bank genesis total supply in committee proposal test Signed-off-by: drklee3 <derrick@dlee.dev> * Use ukava for testing staked balance * Disable minting in community proposal handler test Previously stake denom is used, which resulted in 0 minted coins * Update hard APYToSPY test expected value Increased iterations in sdk.ApproxRoot, updated closer to real value * Fix NewDecCoinsFromCoins bug in incentive collectDerivativeStakingRewards * Allow bkava earn incentive test values to match within small margin for rounding Signed-off-by: drklee3 <derrick@dlee.dev> * Update invalid denom in issuance message coin validation Colons are now valid in denoms Signed-off-by: drklee3 <derrick@dlee.dev> * Remove genesis validator in incentive delegation tests * Update pricefeed market test for invalid denom Signed-off-by: drklee3 <derrick@dlee.dev> * Update incentive delegator rewards test without genesis validator Signed-off-by: drklee3 <derrick@dlee.dev> * Add validator to export test * Clear bank state in minting tests Signed-off-by: drklee3 <derrick@dlee.dev> * Remove validator for no stake tally test Signed-off-by: drklee3 <derrick@dlee.dev> * Clear incentive state before InitGenesis in incentive genesis export test * Update swagger Signed-off-by: drklee3 <derrick@dlee.dev> * Update ethermint version to match replaced version * Remove legacy swagger * Add NewEthEmitEventDecorator * Remove redundant func for AddModuleInitFlags * Remove unused addBankBalanceForAddress func * Add SetIAVLLazyLoading option to app cmd * Use legacy.RegisterAminoMsg for committee msg concrete registration * Remove unnecessary Amino field * Add evm_util bankkeeper SendCoins comment * Update test method ResetBankState to DeleteGenesisValidatorCoins to be more clear * Validate incentive params.RewardsPerSecond to be non-zero * Validate swap pools to disallow colons in token denoms * Register all legacy amino types on gov modulecdc * Remove redundant Comittee interface registration * Pin goleveldb to v1.0.1-0.20210819022825-2ae1ddf74ef7 Causes failed to load state at height errors * Update ethermint to new pinned version with minGasPrices parse error fix * Update cosmos fork dependcy commit to include reverted account constructor patch * Update Cosmos v0.46.11 and cometbft v0.34.27 * Bump minimum go version to 1.19 * Update tendermint proto * Update internal testnet genesis * Move NewCanTransferDecorator before NewEthGasConsumeDecorator * Add hard borrow store tests (#1514) * add store tests for Borrow type * refactor Deposit tests to match * Fix old bep3 tests (#1515) * Update Ethermint to 1b17445 to fix duplicate proto registration * Add custom status command to use snake_case and stdout * Add SetInflation helper * Reduce ambiguity with evm CanSignEthTx error * Remove init genesis validator claim in test * Add disabled evmante.NewMinGasPriceDecorator with x/feemarket note * chore: use tagged versions for Cosmos and Ethermint forks * update kvtool & increase wait for ibc transfer test --------- Signed-off-by: drklee3 <derrick@dlee.dev> Co-authored-by: Ruaridh <rhuairahrighairidh@users.noreply.github.com> Co-authored-by: Robert Pirtle <astropirtle@gmail.com>
2023-04-04 00:08:45 +00:00
suite.DelegationSharesEqual(valAddr, moduleAccAddress, sdk.NewDecFromInt(tc.moduleDelegation).Sub(sharesTransferred))
liquid staking (#1273) * proto types * proto generated types * liquidstaking top level files: module, genesis * liquidstaking types * liquidstaking keeper * liquidstaking client/cli * add liquidstaking to app, simapp * implement mint derivative * set up liquidstaking keeper test suite * test mint derivative * rename module to liquid * rename proto types, app.go to liquid * use sdk.Coin instead of shares * mint liquid tokens to delegator * burn derivative tokens to receive delegation * use conversion method instead of type cast * simplify delegation transfer logic * broaden delegation transfer tests * simplify transfer delegation method This removes a source of rounding errors * move derivative denom to keeper config * check for invalid coins in msg validation * block 0share transfers to avoid handling edge case * refactor MintDerivative to test calculations * simplify burn method so shares and tokens equal * convert TransferShares back to old design this makes handling vesting tokens easier * fix missed merge conflict * remove deprecated constants * tidy up msg.go * add msg tests * remove unused store key * fix msg event sender * remove unused params * tidy up documentation and errors * remove unused mocks * remove unused keepers from AppModule * tidy up msg return values keeper return values to be used in router msgs * reinstate unintentionally removed interface check * catch invalid input for MnitDerivative clear up test TODOs * clear up InitGenesis TODO * Update x/liquid/client/cli/tx.go Co-authored-by: Derrick Lee <derrick@dlee.dev> * Update x/liquid/client/cli/tx.go Co-authored-by: Derrick Lee <derrick@dlee.dev> * show error logs in devnet * unblock mod account so it can receive dist rewards * catch zero amout msgs early * minor cli fixes Co-authored-by: rhuairahrighairigh <ruaridh.odonnell@gmail.com> Co-authored-by: Ruaridh <rhuairahrighairidh@users.noreply.github.com> Co-authored-by: Derrick Lee <derrick@dlee.dev>
2022-09-15 22:00:32 +00:00
suite.EventsContains(suite.Ctx.EventManager().Events(), sdk.NewEvent(
types.EventTypeBurnDerivative,
sdk.NewAttribute(types.AttributeKeyDelegator, user.String()),
sdk.NewAttribute(types.AttributeKeyValidator, valAddr.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, tc.burnAmount.String()),
sdk.NewAttribute(types.AttributeKeySharesTransferred, sharesTransferred.String()),
))
})
}
}
func (suite *KeeperTestSuite) TestCalculateShares() {
_, addrs := app.GeneratePrivKeyAddressPairs(5)
valAccAddr, delegator := addrs[0], addrs[1]
valAddr := sdk.ValAddress(valAccAddr)
type returns struct {
derivatives sdk.Int
shares sdk.Dec
err error
}
type validator struct {
tokens sdk.Int
delegatorShares sdk.Dec
}
testCases := []struct {
name string
validator *validator
delegation sdk.Dec
transfer sdk.Int
expected returns
}{
{
name: "error when validator not found",
validator: nil,
delegation: d("1000000000"),
transfer: i(500e6),
expected: returns{
err: stakingtypes.ErrNoValidatorFound,
},
},
{
name: "error when delegation not found",
validator: &validator{i(1e9), d("1000000000")},
delegation: sdk.Dec{},
transfer: i(500e6),
expected: returns{
err: stakingtypes.ErrNoDelegation,
},
},
{
name: "error when transfer < 0",
validator: &validator{i(10), d("10")},
delegation: d("10"),
transfer: i(-1),
expected: returns{
err: types.ErrUntransferableShares,
},
},
{ // disallow zero transfers
name: "error when transfer = 0",
validator: &validator{i(10), d("10")},
delegation: d("10"),
transfer: i(0),
expected: returns{
err: types.ErrUntransferableShares,
},
},
{
name: "error when transfer > delegated shares",
validator: &validator{i(10), d("10")},
delegation: d("10"),
transfer: i(11),
expected: returns{
err: sdkerrors.ErrInvalidRequest,
},
},
{
name: "error when validator has no tokens",
validator: &validator{i(0), d("10")},
delegation: d("10"),
transfer: i(5),
expected: returns{
err: stakingtypes.ErrInsufficientShares,
},
},
{
name: "shares and derivatives are truncated",
validator: &validator{i(3), d("4")},
delegation: d("4"),
transfer: i(2),
expected: returns{
derivatives: i(2), // truncated down
shares: d("2.666666666666666666"), // 2/3 * 4 not rounded to ...667
},
},
{
name: "error if calculated shares > shares in delegation",
validator: &validator{i(3), d("4")},
delegation: d("2.666666666666666665"), // one less than 2/3 * 4
transfer: i(2),
expected: returns{
err: sdkerrors.ErrInvalidRequest,
},
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()
if tc.validator != nil {
suite.StakingKeeper.SetValidator(suite.Ctx, stakingtypes.Validator{
OperatorAddress: valAddr.String(),
Tokens: tc.validator.tokens,
DelegatorShares: tc.validator.delegatorShares,
})
}
if !tc.delegation.IsNil() {
suite.StakingKeeper.SetDelegation(suite.Ctx, stakingtypes.Delegation{
DelegatorAddress: delegator.String(),
ValidatorAddress: valAddr.String(),
Shares: tc.delegation,
})
}
derivatives, shares, err := suite.Keeper.CalculateDerivativeSharesFromTokens(suite.Ctx, delegator, valAddr, tc.transfer)
if tc.expected.err != nil {
suite.ErrorIs(err, tc.expected.err)
} else {
suite.NoError(err)
suite.Equal(tc.expected.derivatives, derivatives, "expected '%s' got '%s'", tc.expected.derivatives, derivatives)
suite.Equal(tc.expected.shares, shares)
}
})
}
}
func (suite *KeeperTestSuite) TestMintDerivative() {
_, addrs := app.GeneratePrivKeyAddressPairs(5)
valAccAddr, delegator := addrs[0], addrs[1]
valAddr := sdk.ValAddress(valAccAddr)
moduleAccAddress := authtypes.NewModuleAddress(types.ModuleAccountName)
initialBalance := i(1e9)
vestedBalance := i(500e6)
testCases := []struct {
name string
amount sdk.Coin
expectedDerivatives sdk.Int
expectedSharesRemaining sdk.Dec
expectedSharesAdded sdk.Dec
expectedErr error
}{
{
name: "derivative is minted",
amount: suite.NewBondCoin(vestedBalance),
expectedDerivatives: i(500e6),
expectedSharesRemaining: d("500000000.0"),
expectedSharesAdded: d("500000000.0"),
},
{
name: "error when the input denom isn't correct",
amount: sdk.NewCoin("invalid", i(1000)),
expectedErr: types.ErrInvalidDenom,
},
{
name: "error when shares cannot be calculated",
amount: suite.NewBondCoin(initialBalance.Mul(i(100))),
expectedErr: sdkerrors.ErrInvalidRequest,
},
{
name: "error when shares cannot be transferred",
amount: suite.NewBondCoin(initialBalance), // trying to move vesting coins will fail in `TransferShares`
expectedErr: sdkerrors.ErrInsufficientFunds,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()
suite.CreateAccountWithAddress(valAccAddr, suite.NewBondCoins(initialBalance))
suite.CreateVestingAccountWithAddress(delegator, suite.NewBondCoins(initialBalance), suite.NewBondCoins(vestedBalance))
suite.CreateNewUnbondedValidator(valAddr, initialBalance)
suite.CreateDelegation(valAddr, delegator, initialBalance)
staking.EndBlocker(suite.Ctx, suite.StakingKeeper)
_, err := suite.Keeper.MintDerivative(suite.Ctx, delegator, valAddr, tc.amount)
suite.Require().ErrorIs(err, tc.expectedErr)
if tc.expectedErr != nil {
// if an error is expected, state should be reverted so don't need to test state is unchanged
return
}
derivative := sdk.NewCoins(sdk.NewCoin(fmt.Sprintf("bkava-%s", valAddr), tc.expectedDerivatives))
suite.AccountBalanceEqual(delegator, derivative)
suite.DelegationSharesEqual(valAddr, delegator, tc.expectedSharesRemaining)
suite.DelegationSharesEqual(valAddr, moduleAccAddress, tc.expectedSharesAdded)
feat: upgrade to Cosmos v0.46 (#1477) * Update cosmos-sdk to v0.45.10-kava * Add RegisterNodeService to app * Update cosmos proto files * Update cosmos proto files * Use tagged v0.45.10-kava-v0.19-0.21 cosmos version * update x/auth/legacy to x/auth/migrations * Delete rest packages and registration * Remove rest from proposal handlers * Remove legacy types referencing removed sdk types * Remove legacy tx broadcast handler * Update incentive staking hooks to return error * Remove grpc replace directive, use new grpc version * Fix storetypes import * Update tally_handler with updated gov types * Delete legacy types * Use new gov default config * Update RegisterTendermintService params Signed-off-by: drklee3 <derrick@dlee.dev> * Replace sdk.StoreKey with storetypes.StoreKey * Replace sdk.Int#ToDec with sdk.NewDecFromInt * Replace sdk.NewUintFromBigInt with sdkmath.NewUintFromBigInt Signed-off-by: drklee3 <derrick@dlee.dev> * Update most intances of govtypes to govv1beta1 * Unpack coin slice for Coins#Sub and Coins#SafeSub Signed-off-by: drklee3 <derrick@dlee.dev> * Update committee gov codec registration Signed-off-by: drklee3 <derrick@dlee.dev> * Update migrate utils period_vesting Coins#Sub Signed-off-by: drklee3 <derrick@dlee.dev> * Update Coin#Sub in community proposal handler Signed-off-by: drklee3 <derrick@dlee.dev> * Update Coin#Sub, FundModuleAccount/FundAccount in banktestutil Signed-off-by: drklee3 <derrick@dlee.dev> * Update community, earn, kavadist proposal gov registration * Update evm cli client EthSecp256k1Type check * AccAddressFromHex to AccAddressFromHexUnsafe * Add mint DefaultInflationCalculationFn to earn test * Update use of removed staking.NewHandler * Rename FlagIAVLFastNode -> FlagDisableIAVLFastNode * cmd: Update new snapshot app option Signed-off-by: drklee3 <derrick@dlee.dev> * cmd: Add tendermint default config, use cosmos rpc status command Signed-off-by: drklee3 <derrick@dlee.dev> * Update ethermint import path github.com/tharsis/ethermint -> github.com/evmos/ethermint * Upgrade ibc-go to v6 * Update proto dependencies Signed-off-by: drklee3 <derrick@dlee.dev> * Update Tally handler test with new gov types * Update helpers.GenTx -> helpers.GenSignedMockTx * Update evmkeeper.NewKeeper params Signed-off-by: drklee3 <derrick@dlee.dev> * Update ante authz, tests * Add feemarket transient key, pass subspaces to evm/feemarket keepers * Update new ante decorators * Add new addModuleInitFlags to server commands * Pass codec to keyring.New in genaccounts * Pass codec to client keys add * Add SendCoins to evmutil bank_keeper * Use github.com/cosmos/iavl@v0.19.5 * Add ante HandlerOptions * Add unimplemented SendCoins to evmutil bank keeper Ethermint x/evm does not use this method * Update init-new-chain script to disable post-london blocks * Modify test genesis states to append 1 validator * Update tally handler test to use string values * Prevent querying balance for empty sdk.AccAddress in auction bidding test * Set default bond denom to ukava * Remove overwritten bank genesis total supply in committee proposal test Signed-off-by: drklee3 <derrick@dlee.dev> * Use ukava for testing staked balance * Disable minting in community proposal handler test Previously stake denom is used, which resulted in 0 minted coins * Update hard APYToSPY test expected value Increased iterations in sdk.ApproxRoot, updated closer to real value * Fix NewDecCoinsFromCoins bug in incentive collectDerivativeStakingRewards * Allow bkava earn incentive test values to match within small margin for rounding Signed-off-by: drklee3 <derrick@dlee.dev> * Update invalid denom in issuance message coin validation Colons are now valid in denoms Signed-off-by: drklee3 <derrick@dlee.dev> * Remove genesis validator in incentive delegation tests * Update pricefeed market test for invalid denom Signed-off-by: drklee3 <derrick@dlee.dev> * Update incentive delegator rewards test without genesis validator Signed-off-by: drklee3 <derrick@dlee.dev> * Add validator to export test * Clear bank state in minting tests Signed-off-by: drklee3 <derrick@dlee.dev> * Remove validator for no stake tally test Signed-off-by: drklee3 <derrick@dlee.dev> * Clear incentive state before InitGenesis in incentive genesis export test * Update swagger Signed-off-by: drklee3 <derrick@dlee.dev> * Update ethermint version to match replaced version * Remove legacy swagger * Add NewEthEmitEventDecorator * Remove redundant func for AddModuleInitFlags * Remove unused addBankBalanceForAddress func * Add SetIAVLLazyLoading option to app cmd * Use legacy.RegisterAminoMsg for committee msg concrete registration * Remove unnecessary Amino field * Add evm_util bankkeeper SendCoins comment * Update test method ResetBankState to DeleteGenesisValidatorCoins to be more clear * Validate incentive params.RewardsPerSecond to be non-zero * Validate swap pools to disallow colons in token denoms * Register all legacy amino types on gov modulecdc * Remove redundant Comittee interface registration * Pin goleveldb to v1.0.1-0.20210819022825-2ae1ddf74ef7 Causes failed to load state at height errors * Update ethermint to new pinned version with minGasPrices parse error fix * Update cosmos fork dependcy commit to include reverted account constructor patch * Update Cosmos v0.46.11 and cometbft v0.34.27 * Bump minimum go version to 1.19 * Update tendermint proto * Update internal testnet genesis * Move NewCanTransferDecorator before NewEthGasConsumeDecorator * Add hard borrow store tests (#1514) * add store tests for Borrow type * refactor Deposit tests to match * Fix old bep3 tests (#1515) * Update Ethermint to 1b17445 to fix duplicate proto registration * Add custom status command to use snake_case and stdout * Add SetInflation helper * Reduce ambiguity with evm CanSignEthTx error * Remove init genesis validator claim in test * Add disabled evmante.NewMinGasPriceDecorator with x/feemarket note * chore: use tagged versions for Cosmos and Ethermint forks * update kvtool & increase wait for ibc transfer test --------- Signed-off-by: drklee3 <derrick@dlee.dev> Co-authored-by: Ruaridh <rhuairahrighairidh@users.noreply.github.com> Co-authored-by: Robert Pirtle <astropirtle@gmail.com>
2023-04-04 00:08:45 +00:00
sharesTransferred := sdk.NewDecFromInt(initialBalance).Sub(tc.expectedSharesRemaining)
liquid staking (#1273) * proto types * proto generated types * liquidstaking top level files: module, genesis * liquidstaking types * liquidstaking keeper * liquidstaking client/cli * add liquidstaking to app, simapp * implement mint derivative * set up liquidstaking keeper test suite * test mint derivative * rename module to liquid * rename proto types, app.go to liquid * use sdk.Coin instead of shares * mint liquid tokens to delegator * burn derivative tokens to receive delegation * use conversion method instead of type cast * simplify delegation transfer logic * broaden delegation transfer tests * simplify transfer delegation method This removes a source of rounding errors * move derivative denom to keeper config * check for invalid coins in msg validation * block 0share transfers to avoid handling edge case * refactor MintDerivative to test calculations * simplify burn method so shares and tokens equal * convert TransferShares back to old design this makes handling vesting tokens easier * fix missed merge conflict * remove deprecated constants * tidy up msg.go * add msg tests * remove unused store key * fix msg event sender * remove unused params * tidy up documentation and errors * remove unused mocks * remove unused keepers from AppModule * tidy up msg return values keeper return values to be used in router msgs * reinstate unintentionally removed interface check * catch invalid input for MnitDerivative clear up test TODOs * clear up InitGenesis TODO * Update x/liquid/client/cli/tx.go Co-authored-by: Derrick Lee <derrick@dlee.dev> * Update x/liquid/client/cli/tx.go Co-authored-by: Derrick Lee <derrick@dlee.dev> * show error logs in devnet * unblock mod account so it can receive dist rewards * catch zero amout msgs early * minor cli fixes Co-authored-by: rhuairahrighairigh <ruaridh.odonnell@gmail.com> Co-authored-by: Ruaridh <rhuairahrighairidh@users.noreply.github.com> Co-authored-by: Derrick Lee <derrick@dlee.dev>
2022-09-15 22:00:32 +00:00
suite.EventsContains(suite.Ctx.EventManager().Events(), sdk.NewEvent(
types.EventTypeMintDerivative,
sdk.NewAttribute(types.AttributeKeyDelegator, delegator.String()),
sdk.NewAttribute(types.AttributeKeyValidator, valAddr.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, derivative.String()),
sdk.NewAttribute(types.AttributeKeySharesTransferred, sharesTransferred.String()),
))
})
}
}
func (suite *KeeperTestSuite) TestIsDerivativeDenom() {
_, addrs := app.GeneratePrivKeyAddressPairs(5)
valAccAddr1, delegator, valAccAddr2 := addrs[0], addrs[1], addrs[2]
valAddr1 := sdk.ValAddress(valAccAddr1)
// Validator addr that has **not** delegated anything
valAddr2 := sdk.ValAddress(valAccAddr2)
initialBalance := i(1e9)
vestedBalance := i(500e6)
suite.CreateAccountWithAddress(valAccAddr1, suite.NewBondCoins(initialBalance))
suite.CreateVestingAccountWithAddress(delegator, suite.NewBondCoins(initialBalance), suite.NewBondCoins(vestedBalance))
suite.CreateNewUnbondedValidator(valAddr1, initialBalance)
suite.CreateDelegation(valAddr1, delegator, initialBalance)
staking.EndBlocker(suite.Ctx, suite.StakingKeeper)
testCases := []struct {
name string
denom string
wantIsDenom bool
}{
{
name: "valid derivative denom",
denom: suite.Keeper.GetLiquidStakingTokenDenom(valAddr1),
wantIsDenom: true,
},
{
name: "invalid - undelegated validator addr",
denom: suite.Keeper.GetLiquidStakingTokenDenom(valAddr2),
wantIsDenom: false,
},
{
name: "invalid - invalid val addr",
denom: "bkava-asdfasdf",
wantIsDenom: false,
},
{
name: "invalid - ukava",
denom: "ukava",
wantIsDenom: false,
},
{
name: "invalid - plain bkava",
denom: "bkava",
wantIsDenom: false,
},
{
name: "invalid - bkava prefix",
denom: "bkava-",
wantIsDenom: false,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
isDenom := suite.Keeper.IsDerivativeDenom(suite.Ctx, tc.denom)
suite.Require().Equal(tc.wantIsDenom, isDenom)
})
}
}
func (suite *KeeperTestSuite) TestGetStakedTokensForDerivatives() {
_, addrs := app.GeneratePrivKeyAddressPairs(5)
valAccAddr1, delegator, valAccAddr2, valAccAddr3 := addrs[0], addrs[1], addrs[2], addrs[3]
valAddr1 := sdk.ValAddress(valAccAddr1)
// Validator addr that has **not** delegated anything
valAddr2 := sdk.ValAddress(valAccAddr2)
valAddr3 := sdk.ValAddress(valAccAddr3)
initialBalance := i(1e9)
vestedBalance := i(500e6)
delegateAmount := i(100e6)
suite.CreateAccountWithAddress(valAccAddr1, suite.NewBondCoins(initialBalance))
suite.CreateVestingAccountWithAddress(delegator, suite.NewBondCoins(initialBalance), suite.NewBondCoins(vestedBalance))
suite.CreateNewUnbondedValidator(valAddr1, initialBalance)
suite.CreateDelegation(valAddr1, delegator, delegateAmount)
suite.CreateAccountWithAddress(valAccAddr3, suite.NewBondCoins(initialBalance))
suite.CreateNewUnbondedValidator(valAddr3, initialBalance)
suite.CreateDelegation(valAddr3, delegator, delegateAmount)
staking.EndBlocker(suite.Ctx, suite.StakingKeeper)
suite.SlashValidator(valAddr3, d("0.05"))
_, err := suite.Keeper.MintDerivative(suite.Ctx, delegator, valAddr1, suite.NewBondCoin(delegateAmount))
suite.Require().NoError(err)
testCases := []struct {
name string
derivatives sdk.Coins
wantKavaAmount sdk.Int
err error
}{
{
name: "valid derivative denom",
derivatives: sdk.NewCoins(
sdk.NewCoin(suite.Keeper.GetLiquidStakingTokenDenom(valAddr1), vestedBalance),
),
wantKavaAmount: vestedBalance,
},
{
name: "valid - slashed validator",
derivatives: sdk.NewCoins(
sdk.NewCoin(suite.Keeper.GetLiquidStakingTokenDenom(valAddr3), vestedBalance),
),
// vestedBalance * 95%
wantKavaAmount: vestedBalance.Mul(sdk.NewInt(95)).Quo(sdk.NewInt(100)),
},
{
name: "valid - sum",
derivatives: sdk.NewCoins(
sdk.NewCoin(suite.Keeper.GetLiquidStakingTokenDenom(valAddr3), vestedBalance),
sdk.NewCoin(suite.Keeper.GetLiquidStakingTokenDenom(valAddr1), vestedBalance),
),
// vestedBalance + (vestedBalance * 95%)
wantKavaAmount: vestedBalance.Mul(sdk.NewInt(95)).Quo(sdk.NewInt(100)).Add(vestedBalance),
},
{
name: "invalid - undelegated validator address denom",
derivatives: sdk.NewCoins(
sdk.NewCoin(suite.Keeper.GetLiquidStakingTokenDenom(valAddr2), vestedBalance),
),
err: fmt.Errorf("invalid derivative denom %s: validator not found", suite.Keeper.GetLiquidStakingTokenDenom(valAddr2)),
},
{
name: "invalid - denom",
derivatives: sdk.NewCoins(
sdk.NewCoin("kava", vestedBalance),
),
err: fmt.Errorf("invalid derivative denom: cannot parse denom kava"),
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
kavaAmount, err := suite.Keeper.GetStakedTokensForDerivatives(suite.Ctx, tc.derivatives)
if tc.err != nil {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
suite.Require().Equal(suite.NewBondCoin(tc.wantKavaAmount), kavaAmount)
}
})
}
}
func (suite *KeeperTestSuite) TestGetDerivativeValue() {
_, addrs := app.GeneratePrivKeyAddressPairs(5)
valAccAddr1, delegator, valAccAddr2 := addrs[0], addrs[1], addrs[2]
valAddr1 := sdk.ValAddress(valAccAddr1)
valAddr2 := sdk.ValAddress(valAccAddr2)
initialBalance := i(1e9)
vestedBalance := i(500e6)
delegateAmount := i(100e6)
suite.CreateAccountWithAddress(valAccAddr1, suite.NewBondCoins(initialBalance))
suite.CreateVestingAccountWithAddress(delegator, suite.NewBondCoins(initialBalance), suite.NewBondCoins(vestedBalance))
suite.CreateNewUnbondedValidator(valAddr1, initialBalance)
suite.CreateDelegation(valAddr1, delegator, delegateAmount)
suite.CreateAccountWithAddress(valAccAddr2, suite.NewBondCoins(initialBalance))
suite.CreateNewUnbondedValidator(valAddr2, initialBalance)
suite.CreateDelegation(valAddr2, delegator, delegateAmount)
staking.EndBlocker(suite.Ctx, suite.StakingKeeper)
_, err := suite.Keeper.MintDerivative(suite.Ctx, delegator, valAddr1, suite.NewBondCoin(delegateAmount))
suite.Require().NoError(err)
_, err = suite.Keeper.MintDerivative(suite.Ctx, delegator, valAddr2, suite.NewBondCoin(delegateAmount))
suite.Require().NoError(err)
suite.SlashValidator(valAddr2, d("0.05"))
suite.Run("total value", func() {
totalValue, err := suite.Keeper.GetTotalDerivativeValue(suite.Ctx)
suite.Require().NoError(err)
suite.Require().Equal(
// delegateAmount + (delegateAmount * 95%)
delegateAmount.Add(delegateAmount.MulRaw(95).QuoRaw(100)),
totalValue.Amount,
)
})
suite.Run("1:1 derivative value", func() {
derivativeValue, err := suite.Keeper.GetDerivativeValue(suite.Ctx, suite.Keeper.GetLiquidStakingTokenDenom(valAddr1))
suite.Require().NoError(err)
suite.Require().Equal(suite.NewBondCoin(delegateAmount), derivativeValue)
})
suite.Run("slashed derivative value", func() {
derivativeValue, err := suite.Keeper.GetDerivativeValue(suite.Ctx, suite.Keeper.GetLiquidStakingTokenDenom(valAddr2))
suite.Require().NoError(err)
// delegateAmount * 95%
suite.Require().Equal(delegateAmount.MulRaw(95).QuoRaw(100), derivativeValue.Amount)
})
}
func (suite *KeeperTestSuite) TestDerivativeFromTokens() {
_, addrs := app.GeneratePrivKeyAddressPairs(1)
valAccAddr := addrs[0]
valAddr := sdk.ValAddress(valAccAddr)
moduleAccAddress := authtypes.NewModuleAddress(types.ModuleAccountName)
initialBalance := i(1e9)
suite.CreateAccountWithAddress(valAccAddr, suite.NewBondCoins(initialBalance))
suite.AddCoinsToModule(types.ModuleAccountName, suite.NewBondCoins(initialBalance))
suite.CreateNewUnbondedValidator(valAddr, initialBalance)
suite.CreateDelegation(valAddr, moduleAccAddress, initialBalance)
staking.EndBlocker(suite.Ctx, suite.StakingKeeper)
_, err := suite.Keeper.DerivativeFromTokens(suite.Ctx, valAddr, sdk.NewCoin("invalid", initialBalance))
suite.ErrorIs(err, types.ErrInvalidDenom)
derivatives, err := suite.Keeper.DerivativeFromTokens(suite.Ctx, valAddr, suite.NewBondCoin(initialBalance))
suite.NoError(err)
expected := sdk.NewCoin(fmt.Sprintf("bkava-%s", valAddr), initialBalance)
suite.Equal(expected, derivatives)
}