mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-09-20 22:57:32 +00:00
ae181604ff
* Add basic earn types and interfaces * Add VaultStrategy type * Update params with allowedVaults, deposit/withdraw msgs * Fill in Deposit method, add keeper methods * Add testutil, params, codec * Add withdraw * emit vault events * Implement vault viewer methods * Update doc comments, strategies * Add earn cli query/tx commands * Add successfull balance withdraw tests * Add ukava vault to dev genesis * Add vault keeper method doc comments * Update stablecoin strategy to only accept usdx * Vault state tests * VaultTotalSupplied tests * msg server test
216 lines
6.7 KiB
Go
216 lines
6.7 KiB
Go
package keeper
|
|
|
|
import (
|
|
"github.com/cosmos/cosmos-sdk/store/prefix"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/kava-labs/kava/x/earn/types"
|
|
)
|
|
|
|
// ViewVaultKeeper defines the read-only methods used for querying vaults.
|
|
type ViewVaultKeeper interface {
|
|
// GetVaultTotalSupplied returns the total balance supplied to a vault. This
|
|
// may not necessarily be the current value of the vault, as it is the sum
|
|
// of the supplied denom.
|
|
GetVaultTotalSupplied(ctx sdk.Context, denom string) (sdk.Coin, error)
|
|
|
|
// GetVaultTotalValue returns the total **value** of all coins in a vault,
|
|
// i.e. the realizable total value denominated by GetDenom() if the vault
|
|
// were to liquidate its entire strategies.
|
|
GetVaultTotalValue(ctx sdk.Context, denom string) (sdk.Coin, error)
|
|
|
|
// GetVaultAccountSupplied returns the supplied amount for a single address
|
|
// within the vault.
|
|
GetVaultAccountSupplied(ctx sdk.Context, denom string, acc sdk.AccAddress) (sdk.Coin, error)
|
|
|
|
// GetVaultAccountValue returns the value of a single address within a vault
|
|
// if the account were to withdraw their entire balance.
|
|
GetVaultAccountValue(ctx sdk.Context, denom string, acc sdk.AccAddress) (sdk.Coin, error)
|
|
}
|
|
|
|
var _ ViewVaultKeeper = (*Keeper)(nil)
|
|
|
|
// GetVaultTotalSupplied returns the total balance supplied to the vault. This
|
|
// may not necessarily be the current value of the vault, as it is the sum
|
|
// of the supplied denom and the value may be higher due to accumulated APYs.
|
|
func (k *Keeper) GetVaultTotalSupplied(
|
|
ctx sdk.Context,
|
|
denom string,
|
|
) (sdk.Coin, error) {
|
|
vault, found := k.GetVaultRecord(ctx, denom)
|
|
if !found {
|
|
return sdk.Coin{}, types.ErrVaultRecordNotFound
|
|
}
|
|
|
|
return vault.TotalSupply, nil
|
|
}
|
|
|
|
// GetTotalValue returns the total **value** of all coins in this vault,
|
|
// i.e. the realizable total value denominated by GetDenom() if the vault
|
|
// were to liquidate its entire strategies.
|
|
func (k *Keeper) GetVaultTotalValue(
|
|
ctx sdk.Context,
|
|
denom string,
|
|
) (sdk.Coin, error) {
|
|
enabledVault, found := k.GetAllowedVault(ctx, denom)
|
|
if !found {
|
|
return sdk.Coin{}, types.ErrVaultRecordNotFound
|
|
}
|
|
|
|
strategy, err := k.GetStrategy(enabledVault.VaultStrategy)
|
|
if err != nil {
|
|
return sdk.Coin{}, types.ErrInvalidVaultStrategy
|
|
}
|
|
|
|
return strategy.GetEstimatedTotalAssets(enabledVault.Denom)
|
|
}
|
|
|
|
// GetVaultAccountSupplied returns the supplied amount for a single address
|
|
// within a vault.
|
|
func (k *Keeper) GetVaultAccountSupplied(
|
|
ctx sdk.Context,
|
|
denom string,
|
|
acc sdk.AccAddress,
|
|
) (sdk.Coin, error) {
|
|
vaultShareRecord, found := k.GetVaultShareRecord(ctx, denom, acc)
|
|
if !found {
|
|
return sdk.Coin{}, types.ErrVaultShareRecordNotFound
|
|
}
|
|
|
|
return vaultShareRecord.AmountSupplied, nil
|
|
}
|
|
|
|
// GetVaultAccountValue returns the value of a single address within a vault
|
|
// if the account were to withdraw their entire balance.
|
|
func (k *Keeper) GetVaultAccountValue(
|
|
ctx sdk.Context,
|
|
denom string,
|
|
acc sdk.AccAddress,
|
|
) (sdk.Coin, error) {
|
|
totalSupplied, err := k.GetVaultTotalSupplied(ctx, denom)
|
|
if err != nil {
|
|
return sdk.Coin{}, err
|
|
}
|
|
|
|
accSupplied, err := k.GetVaultAccountSupplied(ctx, denom, acc)
|
|
if err != nil {
|
|
return sdk.Coin{}, err
|
|
}
|
|
|
|
vaultTotalValue, err := k.GetVaultTotalValue(ctx, denom)
|
|
if err != nil {
|
|
return sdk.Coin{}, err
|
|
}
|
|
|
|
// percent of vault account ownership = accountSupply / totalSupply
|
|
// value of vault account ownership = percentOwned * totalValue
|
|
vaultShare := accSupplied.Amount.Quo(totalSupplied.Amount)
|
|
shareValue := vaultTotalValue.Amount.Mul(vaultShare)
|
|
|
|
return sdk.NewCoin(denom, shareValue), nil
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// VaultRecord -- vault total supplies
|
|
|
|
// GetVaultRecord returns the vault record for a given denom.
|
|
func (k *Keeper) GetVaultRecord(
|
|
ctx sdk.Context,
|
|
vaultDenom string,
|
|
) (types.VaultRecord, bool) {
|
|
store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
|
|
|
|
bz := store.Get(types.VaultKey(vaultDenom))
|
|
if bz == nil {
|
|
return types.VaultRecord{}, false
|
|
}
|
|
|
|
var record types.VaultRecord
|
|
k.cdc.MustUnmarshal(bz, &record)
|
|
|
|
return record, true
|
|
}
|
|
|
|
// UpdateVaultRecord updates the vault record in state for a given denom. This
|
|
// deletes it if the supply is zero and updates the state if supply is non-zero.
|
|
func (k *Keeper) UpdateVaultRecord(
|
|
ctx sdk.Context,
|
|
vaultRecord types.VaultRecord,
|
|
) {
|
|
if vaultRecord.TotalSupply.IsZero() {
|
|
k.DeleteVaultRecord(ctx, vaultRecord.Denom)
|
|
} else {
|
|
k.SetVaultRecord(ctx, vaultRecord)
|
|
}
|
|
}
|
|
|
|
// DeleteVaultRecord deletes the vault record for a given denom.
|
|
func (k *Keeper) DeleteVaultRecord(ctx sdk.Context, vaultDenom string) {
|
|
store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
|
|
store.Delete(types.VaultKey(vaultDenom))
|
|
}
|
|
|
|
// SetVaultRecord sets the vault record for a given denom.
|
|
func (k *Keeper) SetVaultRecord(ctx sdk.Context, record types.VaultRecord) {
|
|
store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
|
|
bz := k.cdc.MustMarshal(&record)
|
|
store.Set(types.VaultKey(record.Denom), bz)
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// VaultShare -- user shares per vault
|
|
|
|
// GetVaultShareRecord returns the vault share record for a given denom and
|
|
// account.
|
|
func (k *Keeper) GetVaultShareRecord(
|
|
ctx sdk.Context,
|
|
vaultDenom string,
|
|
acc sdk.AccAddress,
|
|
) (types.VaultShareRecord, bool) {
|
|
store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
|
|
|
|
bz := store.Get(types.DepositorVaultSharesKey(acc, vaultDenom))
|
|
if bz == nil {
|
|
return types.VaultShareRecord{}, false
|
|
}
|
|
|
|
var record types.VaultShareRecord
|
|
k.cdc.MustUnmarshal(bz, &record)
|
|
|
|
return record, true
|
|
}
|
|
|
|
// UpdateVaultShareRecord updates the vault share record in state for a given
|
|
// denom and account. This deletes it if the supply is zero and updates the
|
|
// state if supply is non-zero.
|
|
func (k *Keeper) UpdateVaultShareRecord(
|
|
ctx sdk.Context,
|
|
record types.VaultShareRecord,
|
|
) {
|
|
if record.AmountSupplied.IsZero() {
|
|
k.DeleteVaultShareRecord(ctx, record.AmountSupplied.Denom, record.Depositor)
|
|
} else {
|
|
k.SetVaultShareRecord(ctx, record)
|
|
}
|
|
}
|
|
|
|
// DeleteVaultShareRecord deletes the vault share record for a given denom and
|
|
// account.
|
|
func (k *Keeper) DeleteVaultShareRecord(
|
|
ctx sdk.Context,
|
|
vaultDenom string,
|
|
acc sdk.AccAddress,
|
|
) {
|
|
store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
|
|
store.Delete(types.DepositorVaultSharesKey(acc, vaultDenom))
|
|
}
|
|
|
|
// SetVaultShareRecord sets the vault share record for a given denom and account.
|
|
func (k *Keeper) SetVaultShareRecord(
|
|
ctx sdk.Context,
|
|
record types.VaultShareRecord,
|
|
) {
|
|
store := prefix.NewStore(ctx.KVStore(k.key), types.VaultRecordKeyPrefix)
|
|
bz := k.cdc.MustMarshal(&record)
|
|
store.Set(types.DepositorVaultSharesKey(record.Depositor, record.AmountSupplied.Denom), bz)
|
|
}
|