mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-25 07:45:18 +00:00
Add liquid bkava support to savings (#1309)
* Add savings support for bkava deposits * Update savings tests with valid validator * Add invalid bkava deposit test * Remove test logs * Add bkava withdraw test
This commit is contained in:
parent
651de460ca
commit
50fdebe657
13
app/app.go
13
app/app.go
@ -584,18 +584,19 @@ func NewApp(
|
||||
app.pricefeedKeeper,
|
||||
app.auctionKeeper,
|
||||
)
|
||||
app.liquidKeeper = liquidkeeper.NewDefaultKeeper(
|
||||
appCodec,
|
||||
app.accountKeeper,
|
||||
app.bankKeeper,
|
||||
&app.stakingKeeper,
|
||||
)
|
||||
savingsKeeper := savingskeeper.NewKeeper(
|
||||
appCodec,
|
||||
keys[savingstypes.StoreKey],
|
||||
savingsSubspace,
|
||||
app.accountKeeper,
|
||||
app.bankKeeper,
|
||||
)
|
||||
app.liquidKeeper = liquidkeeper.NewDefaultKeeper(
|
||||
appCodec,
|
||||
app.accountKeeper,
|
||||
app.bankKeeper,
|
||||
&app.stakingKeeper,
|
||||
app.liquidKeeper,
|
||||
)
|
||||
earnKeeper := earnkeeper.NewKeeper(
|
||||
appCodec,
|
||||
|
@ -1,9 +1,12 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
@ -13,6 +16,15 @@ import (
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestDeposit() {
|
||||
_, addrs := app.GeneratePrivKeyAddressPairs(5)
|
||||
valAccAddr, delegator := addrs[0], addrs[1]
|
||||
|
||||
valAddr := sdk.ValAddress(valAccAddr)
|
||||
initialBalance := sdk.NewInt(1e9)
|
||||
|
||||
bkavaDenom := fmt.Sprintf("bkava-%s", valAddr.String())
|
||||
invalidBkavaDenom := fmt.Sprintf("bkava-%s", sdk.ValAddress(addrs[2]).String())
|
||||
|
||||
type args struct {
|
||||
allowedDenoms []string
|
||||
depositor sdk.AccAddress
|
||||
@ -67,6 +79,23 @@ func (suite *KeeperTestSuite) TestDeposit() {
|
||||
contains: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
"valid bkava",
|
||||
args{
|
||||
allowedDenoms: []string{"bnb", "btcb", "ukava", "bkava"},
|
||||
depositor: sdk.AccAddress(crypto.AddressHash([]byte("test"))),
|
||||
initialDepositorBalance: sdk.NewCoins(sdk.NewCoin(bkavaDenom, sdk.NewInt(1000)), sdk.NewCoin("btcb", sdk.NewInt(1000))),
|
||||
depositAmount: sdk.NewCoins(sdk.NewCoin(bkavaDenom, sdk.NewInt(100))),
|
||||
numberDeposits: 1,
|
||||
expectedAccountBalance: sdk.NewCoins(sdk.NewCoin(bkavaDenom, sdk.NewInt(900)), sdk.NewCoin("btcb", sdk.NewInt(1000))),
|
||||
expectedModAccountBalance: sdk.NewCoins(sdk.NewCoin(bkavaDenom, sdk.NewInt(100))),
|
||||
expectedDepositCoins: sdk.NewCoins(sdk.NewCoin(bkavaDenom, sdk.NewInt(100))),
|
||||
},
|
||||
errArgs{
|
||||
expectPass: true,
|
||||
contains: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid deposit denom",
|
||||
args{
|
||||
@ -84,6 +113,23 @@ func (suite *KeeperTestSuite) TestDeposit() {
|
||||
contains: "invalid deposit denom",
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid bkava",
|
||||
args{
|
||||
allowedDenoms: []string{"bnb", "btcb", "ukava", "bkava"},
|
||||
depositor: sdk.AccAddress(crypto.AddressHash([]byte("test"))),
|
||||
initialDepositorBalance: sdk.NewCoins(sdk.NewCoin(invalidBkavaDenom, sdk.NewInt(1000)), sdk.NewCoin("btcb", sdk.NewInt(1000))),
|
||||
depositAmount: sdk.NewCoins(sdk.NewCoin(invalidBkavaDenom, sdk.NewInt(100))),
|
||||
numberDeposits: 1,
|
||||
expectedAccountBalance: sdk.Coins{},
|
||||
expectedModAccountBalance: sdk.Coins{},
|
||||
expectedDepositCoins: sdk.Coins{},
|
||||
},
|
||||
errArgs{
|
||||
expectPass: false,
|
||||
contains: "invalid deposit denom",
|
||||
},
|
||||
},
|
||||
{
|
||||
"insufficient funds",
|
||||
args{
|
||||
@ -119,14 +165,26 @@ func (suite *KeeperTestSuite) TestDeposit() {
|
||||
types.Deposits{},
|
||||
)
|
||||
|
||||
stakingParams := stakingtypes.DefaultParams()
|
||||
stakingParams.BondDenom = "ukava"
|
||||
|
||||
tApp.InitializeFromGenesisStates(authGS,
|
||||
app.GenesisState{types.ModuleName: tApp.AppCodec().MustMarshalJSON(&savingsGS)},
|
||||
app.GenesisState{stakingtypes.ModuleName: tApp.AppCodec().MustMarshalJSON(stakingtypes.NewGenesisState(stakingParams, nil, nil))},
|
||||
)
|
||||
keeper := tApp.GetSavingsKeeper()
|
||||
suite.app = tApp
|
||||
suite.ctx = ctx
|
||||
suite.keeper = keeper
|
||||
|
||||
// Create validator and delegate for bkava
|
||||
suite.CreateAccountWithAddress(valAccAddr, cs(c("ukava", 100e10)))
|
||||
suite.CreateAccountWithAddress(delegator, cs(c("ukava", 100e10)))
|
||||
|
||||
suite.CreateNewUnbondedValidator(valAddr, initialBalance)
|
||||
suite.CreateDelegation(valAddr, delegator, initialBalance)
|
||||
staking.EndBlocker(suite.ctx, suite.app.GetStakingKeeper())
|
||||
|
||||
// run the test
|
||||
var err error
|
||||
for i := 0; i < tc.args.numberDeposits; i++ {
|
||||
|
@ -19,13 +19,14 @@ type Keeper struct {
|
||||
paramSubspace paramtypes.Subspace
|
||||
accountKeeper types.AccountKeeper
|
||||
bankKeeper types.BankKeeper
|
||||
liquidKeeper types.LiquidKeeper
|
||||
hooks types.SavingsHooks
|
||||
}
|
||||
|
||||
// NewKeeper returns a new keeper for the savings module.
|
||||
func NewKeeper(
|
||||
cdc codec.Codec, key sdk.StoreKey, paramstore paramtypes.Subspace,
|
||||
ak types.AccountKeeper, bk types.BankKeeper,
|
||||
ak types.AccountKeeper, bk types.BankKeeper, lk types.LiquidKeeper,
|
||||
) Keeper {
|
||||
if !paramstore.HasKeyTable() {
|
||||
paramstore = paramstore.WithKeyTable(types.ParamKeyTable())
|
||||
@ -37,6 +38,7 @@ func NewKeeper(
|
||||
paramSubspace: paramstore,
|
||||
accountKeeper: ak,
|
||||
bankKeeper: bk,
|
||||
liquidKeeper: lk,
|
||||
hooks: nil,
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,14 @@ import (
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
"github.com/kava-labs/kava/app"
|
||||
"github.com/kava-labs/kava/x/savings/keeper"
|
||||
"github.com/kava-labs/kava/x/savings/types"
|
||||
@ -39,6 +44,10 @@ func (suite *KeeperTestSuite) SetupTest() {
|
||||
suite.ctx = ctx
|
||||
suite.keeper = keeper
|
||||
suite.addrs = addrs
|
||||
|
||||
stakingParams := stakingtypes.DefaultParams()
|
||||
stakingParams.BondDenom = "ukava"
|
||||
suite.app.GetStakingKeeper().SetParams(suite.ctx, stakingParams)
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGetSetDeleteDeposit() {
|
||||
@ -99,3 +108,87 @@ func (suite *KeeperTestSuite) getModuleAccountAtCtx(name string, ctx sdk.Context
|
||||
func TestKeeperTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(KeeperTestSuite))
|
||||
}
|
||||
|
||||
// CreateAccount creates a new account from the provided balance and address
|
||||
func (suite *KeeperTestSuite) CreateAccountWithAddress(addr sdk.AccAddress, initialBalance sdk.Coins) authtypes.AccountI {
|
||||
ak := suite.app.GetAccountKeeper()
|
||||
|
||||
acc := ak.NewAccountWithAddress(suite.ctx, addr)
|
||||
ak.SetAccount(suite.ctx, acc)
|
||||
|
||||
err := simapp.FundAccount(suite.app.GetBankKeeper(), suite.ctx, acc.GetAddress(), initialBalance)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return acc
|
||||
}
|
||||
|
||||
// CreateVestingAccount creates a new vesting account. `vestingBalance` should be a fraction of `initialBalance`.
|
||||
func (suite *KeeperTestSuite) CreateVestingAccountWithAddress(addr sdk.AccAddress, initialBalance sdk.Coins, vestingBalance sdk.Coins) authtypes.AccountI {
|
||||
if vestingBalance.IsAnyGT(initialBalance) {
|
||||
panic("vesting balance must be less than initial balance")
|
||||
}
|
||||
acc := suite.CreateAccountWithAddress(addr, initialBalance)
|
||||
bacc := acc.(*authtypes.BaseAccount)
|
||||
|
||||
periods := vestingtypes.Periods{
|
||||
vestingtypes.Period{
|
||||
Length: 31556952,
|
||||
Amount: vestingBalance,
|
||||
},
|
||||
}
|
||||
vacc := vestingtypes.NewPeriodicVestingAccount(bacc, vestingBalance, suite.ctx.BlockTime().Unix(), periods)
|
||||
suite.app.GetAccountKeeper().SetAccount(suite.ctx, vacc)
|
||||
return vacc
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) deliverMsgCreateValidator(ctx sdk.Context, address sdk.ValAddress, selfDelegation sdk.Coin) error {
|
||||
msg, err := stakingtypes.NewMsgCreateValidator(
|
||||
address,
|
||||
ed25519.GenPrivKey().PubKey(),
|
||||
selfDelegation,
|
||||
stakingtypes.Description{},
|
||||
stakingtypes.NewCommissionRates(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
|
||||
sdk.NewInt(1e6),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msgServer := stakingkeeper.NewMsgServerImpl(suite.app.GetStakingKeeper())
|
||||
_, err = msgServer.CreateValidator(sdk.WrapSDKContext(suite.ctx), msg)
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateNewUnbondedValidator creates a new validator in the staking module.
|
||||
// New validators are unbonded until the end blocker is run.
|
||||
func (suite *KeeperTestSuite) CreateNewUnbondedValidator(addr sdk.ValAddress, selfDelegation sdk.Int) stakingtypes.Validator {
|
||||
// Create a validator
|
||||
err := suite.deliverMsgCreateValidator(suite.ctx, addr, sdk.NewCoin("ukava", selfDelegation))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// New validators are created in an unbonded state. Note if the end blocker is run later this validator could become bonded.
|
||||
|
||||
validator, found := suite.app.GetStakingKeeper().GetValidator(suite.ctx, addr)
|
||||
suite.Require().True(found)
|
||||
return validator
|
||||
}
|
||||
|
||||
// CreateDelegation delegates tokens to a validator.
|
||||
func (suite *KeeperTestSuite) CreateDelegation(valAddr sdk.ValAddress, delegator sdk.AccAddress, amount sdk.Int) sdk.Dec {
|
||||
sk := suite.app.GetStakingKeeper()
|
||||
|
||||
stakingDenom := sk.BondDenom(suite.ctx)
|
||||
msg := stakingtypes.NewMsgDelegate(
|
||||
delegator,
|
||||
valAddr,
|
||||
sdk.NewCoin(stakingDenom, amount),
|
||||
)
|
||||
|
||||
msgServer := stakingkeeper.NewMsgServerImpl(sk)
|
||||
_, err := msgServer.Delegate(sdk.WrapSDKContext(suite.ctx), msg)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
del, found := sk.GetDelegation(suite.ctx, delegator, valAddr)
|
||||
suite.Require().True(found)
|
||||
return del.Shares
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package keeper
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
liquidtypes "github.com/kava-labs/kava/x/liquid/types"
|
||||
"github.com/kava-labs/kava/x/savings/types"
|
||||
)
|
||||
|
||||
@ -25,6 +26,13 @@ func (k Keeper) IsDenomSupported(ctx sdk.Context, denom string) bool {
|
||||
if supportedDenom == denom {
|
||||
return true
|
||||
}
|
||||
|
||||
if supportedDenom == liquidtypes.DefaultDerivativeDenom {
|
||||
if k.liquidKeeper.IsDerivativeDenom(ctx, denom) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
@ -13,6 +16,14 @@ import (
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestWithdraw() {
|
||||
_, addrs := app.GeneratePrivKeyAddressPairs(5)
|
||||
valAccAddr, delegator := addrs[0], addrs[1]
|
||||
|
||||
valAddr := sdk.ValAddress(valAccAddr)
|
||||
initialBalance := sdk.NewInt(1e9)
|
||||
|
||||
bkavaDenom := fmt.Sprintf("bkava-%s", valAddr.String())
|
||||
|
||||
type args struct {
|
||||
allowedDenoms []string
|
||||
depositor sdk.AccAddress
|
||||
@ -52,6 +63,24 @@ func (suite *KeeperTestSuite) TestWithdraw() {
|
||||
contains: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
"valid: partial bkava",
|
||||
args{
|
||||
allowedDenoms: []string{"bnb", "btcb", "ukava", "bkava"},
|
||||
depositor: sdk.AccAddress(crypto.AddressHash([]byte("test"))),
|
||||
initialDepositorBalance: sdk.NewCoins(sdk.NewCoin(bkavaDenom, sdk.NewInt(1000)), sdk.NewCoin("btcb", sdk.NewInt(1000))),
|
||||
depositAmount: sdk.NewCoins(sdk.NewCoin(bkavaDenom, sdk.NewInt(200))),
|
||||
withdrawAmount: sdk.NewCoins(sdk.NewCoin(bkavaDenom, sdk.NewInt(100))),
|
||||
expectedAccountBalance: sdk.NewCoins(sdk.NewCoin(bkavaDenom, sdk.NewInt(900)), sdk.NewCoin("btcb", sdk.NewInt(1000))),
|
||||
expectedModAccountBalance: sdk.NewCoins(sdk.NewCoin(bkavaDenom, sdk.NewInt(100))),
|
||||
expectedDepositCoins: sdk.NewCoins(sdk.NewCoin(bkavaDenom, sdk.NewInt(100))),
|
||||
},
|
||||
errArgs{
|
||||
expectPass: true,
|
||||
expectDelete: false,
|
||||
contains: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
"valid: full withdraw",
|
||||
args{
|
||||
@ -122,8 +151,12 @@ func (suite *KeeperTestSuite) TestWithdraw() {
|
||||
types.Deposits{},
|
||||
)
|
||||
|
||||
stakingParams := stakingtypes.DefaultParams()
|
||||
stakingParams.BondDenom = "ukava"
|
||||
|
||||
tApp.InitializeFromGenesisStates(authGS,
|
||||
app.GenesisState{types.ModuleName: tApp.AppCodec().MustMarshalJSON(&savingsGS)},
|
||||
app.GenesisState{stakingtypes.ModuleName: tApp.AppCodec().MustMarshalJSON(stakingtypes.NewGenesisState(stakingParams, nil, nil))},
|
||||
)
|
||||
keeper := tApp.GetSavingsKeeper()
|
||||
suite.app = tApp
|
||||
@ -131,6 +164,14 @@ func (suite *KeeperTestSuite) TestWithdraw() {
|
||||
suite.keeper = keeper
|
||||
bankKeeper := tApp.GetBankKeeper()
|
||||
|
||||
// Create validator and delegate for bkava
|
||||
suite.CreateAccountWithAddress(valAccAddr, cs(c("ukava", 100e10)))
|
||||
suite.CreateAccountWithAddress(delegator, cs(c("ukava", 100e10)))
|
||||
|
||||
suite.CreateNewUnbondedValidator(valAddr, initialBalance)
|
||||
suite.CreateDelegation(valAddr, delegator, initialBalance)
|
||||
staking.EndBlocker(suite.ctx, suite.app.GetStakingKeeper())
|
||||
|
||||
err := suite.keeper.Deposit(suite.ctx, tc.args.depositor, tc.args.depositAmount)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
|
@ -31,3 +31,7 @@ type SavingsHooks interface {
|
||||
AfterSavingsDepositCreated(ctx sdk.Context, deposit Deposit)
|
||||
BeforeSavingsDepositModified(ctx sdk.Context, deposit Deposit, incomingDenoms []string)
|
||||
}
|
||||
|
||||
type LiquidKeeper interface {
|
||||
IsDerivativeDenom(ctx sdk.Context, denom string) bool
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user