mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 23:35:19 +00:00
cleanup begin/end block (#553)
* cleanup begin/end block * update cdp BeginBlocker * update dist mint * fix tests * typo * add comment on CloseExpiredAuctions * fix tests
This commit is contained in:
parent
f0e73e4aa8
commit
bfb9f7e20a
@ -1,13 +1,17 @@
|
|||||||
package auction
|
package auction
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/kava-labs/kava/x/auction/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BeginBlocker runs at the start of every block.
|
// BeginBlocker closes all expired auctions at the end of each block. It panics if
|
||||||
|
// there's an error other than ErrAuctionNotFound.
|
||||||
func BeginBlocker(ctx sdk.Context, k Keeper) {
|
func BeginBlocker(ctx sdk.Context, k Keeper) {
|
||||||
err := k.CloseExpiredAuctions(ctx)
|
err := k.CloseExpiredAuctions(ctx)
|
||||||
if err != nil {
|
if err != nil && !errors.Is(err, types.ErrAuctionNotFound) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package keeper
|
package keeper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -449,7 +450,6 @@ func (k Keeper) PlaceBidDebt(ctx sdk.Context, auction types.DebtAuction, bidder
|
|||||||
|
|
||||||
// CloseAuction closes an auction and distributes funds to the highest bidder.
|
// CloseAuction closes an auction and distributes funds to the highest bidder.
|
||||||
func (k Keeper) CloseAuction(ctx sdk.Context, auctionID uint64) error {
|
func (k Keeper) CloseAuction(ctx sdk.Context, auctionID uint64) error {
|
||||||
|
|
||||||
auction, found := k.GetAuction(ctx, auctionID)
|
auction, found := k.GetAuction(ctx, auctionID)
|
||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrapf(types.ErrAuctionNotFound, "%d", auctionID)
|
return sdkerrors.Wrapf(types.ErrAuctionNotFound, "%d", auctionID)
|
||||||
@ -460,21 +460,20 @@ func (k Keeper) CloseAuction(ctx sdk.Context, auctionID uint64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// payout to the last bidder
|
// payout to the last bidder
|
||||||
|
var err error
|
||||||
switch auc := auction.(type) {
|
switch auc := auction.(type) {
|
||||||
case types.SurplusAuction:
|
case types.SurplusAuction:
|
||||||
if err := k.PayoutSurplusAuction(ctx, auc); err != nil {
|
err = k.PayoutSurplusAuction(ctx, auc)
|
||||||
return err
|
|
||||||
}
|
|
||||||
case types.DebtAuction:
|
case types.DebtAuction:
|
||||||
if err := k.PayoutDebtAuction(ctx, auc); err != nil {
|
err = k.PayoutDebtAuction(ctx, auc)
|
||||||
return err
|
|
||||||
}
|
|
||||||
case types.CollateralAuction:
|
case types.CollateralAuction:
|
||||||
if err := k.PayoutCollateralAuction(ctx, auc); err != nil {
|
err = k.PayoutCollateralAuction(ctx, auc)
|
||||||
return err
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return sdkerrors.Wrap(types.ErrUnrecognizedAuctionType, auc.GetType())
|
err = sdkerrors.Wrap(types.ErrUnrecognizedAuctionType, auc.GetType())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
k.DeleteAuction(ctx, auctionID)
|
k.DeleteAuction(ctx, auctionID)
|
||||||
@ -502,23 +501,17 @@ func (k Keeper) PayoutDebtAuction(ctx sdk.Context, auction types.DebtAuction) er
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// if there is remaining debt, return it to the calling module to manage
|
// if there is remaining debt, return it to the calling module to manage
|
||||||
if auction.CorrespondingDebt.IsPositive() {
|
if !auction.CorrespondingDebt.IsPositive() {
|
||||||
err = k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, auction.Initiator, sdk.NewCoins(auction.CorrespondingDebt))
|
return nil
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
return k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, auction.Initiator, sdk.NewCoins(auction.CorrespondingDebt))
|
||||||
}
|
}
|
||||||
|
|
||||||
// PayoutSurplusAuction pays out the proceeds for a surplus auction.
|
// PayoutSurplusAuction pays out the proceeds for a surplus auction.
|
||||||
func (k Keeper) PayoutSurplusAuction(ctx sdk.Context, auction types.SurplusAuction) error {
|
func (k Keeper) PayoutSurplusAuction(ctx sdk.Context, auction types.SurplusAuction) error {
|
||||||
// Send the tokens from the auction module account where they are being managed to the bidder who won the auction
|
// Send the tokens from the auction module account where they are being managed to the bidder who won the auction
|
||||||
err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, auction.Bidder, sdk.NewCoins(auction.Lot))
|
return k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, auction.Bidder, sdk.NewCoins(auction.Lot))
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PayoutCollateralAuction pays out the proceeds for a collateral auction.
|
// PayoutCollateralAuction pays out the proceeds for a collateral auction.
|
||||||
@ -530,29 +523,30 @@ func (k Keeper) PayoutCollateralAuction(ctx sdk.Context, auction types.Collatera
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if there is remaining debt after the auction, send it back to the initiating module for management
|
// if there is remaining debt after the auction, send it back to the initiating module for management
|
||||||
if auction.CorrespondingDebt.IsPositive() {
|
if !auction.CorrespondingDebt.IsPositive() {
|
||||||
err = k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, auction.Initiator, sdk.NewCoins(auction.CorrespondingDebt))
|
return nil
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
return k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, auction.Initiator, sdk.NewCoins(auction.CorrespondingDebt))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloseExpiredAuctions finds all auctions that are past (or at) their ending times and closes them, paying out to the highest bidder.
|
// CloseExpiredAuctions iterates over all the auctions stored by until the current
|
||||||
|
// block timestamp and that are past (or at) their ending times and closes them,
|
||||||
|
// paying out to the highest bidder.
|
||||||
func (k Keeper) CloseExpiredAuctions(ctx sdk.Context) error {
|
func (k Keeper) CloseExpiredAuctions(ctx sdk.Context) error {
|
||||||
var expiredAuctions []uint64
|
var err error
|
||||||
k.IterateAuctionsByTime(ctx, ctx.BlockTime(), func(id uint64) bool {
|
k.IterateAuctionsByTime(ctx, ctx.BlockTime(), func(id uint64) (stop bool) {
|
||||||
expiredAuctions = append(expiredAuctions, id)
|
err = k.CloseAuction(ctx, id)
|
||||||
|
if err != nil && !errors.Is(err, types.ErrAuctionNotFound) {
|
||||||
|
// stop iteration
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// reset error in case the last element had an ErrAuctionNotFound
|
||||||
|
err = nil
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
// Note: iteration and auction closing are in separate loops as db should not be modified during iteration // TODO is this correct? gov modifies during iteration
|
|
||||||
for _, id := range expiredAuctions {
|
return err
|
||||||
if err := k.CloseAuction(ctx, id); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// earliestTime returns the earliest of two times.
|
// earliestTime returns the earliest of two times.
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
package cdp
|
package cdp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
|
pricefeedtypes "github.com/kava-labs/kava/x/pricefeed/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BeginBlocker compounds the debt in outstanding cdps and liquidates cdps that are below the required collateralization ratio
|
// BeginBlocker compounds the debt in outstanding cdps and liquidates cdps that are below the required collateralization ratio
|
||||||
@ -17,7 +21,6 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k Keeper) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, cp := range params.CollateralParams {
|
for _, cp := range params.CollateralParams {
|
||||||
|
|
||||||
ok := k.UpdatePricefeedStatus(ctx, cp.SpotMarketID)
|
ok := k.UpdatePricefeedStatus(ctx, cp.SpotMarketID)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
@ -29,26 +32,30 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k Keeper) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := k.UpdateFeesForAllCdps(ctx, cp.Denom)
|
err := k.UpdateFeesForAllCdps(ctx, cp.Denom)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = k.LiquidateCdps(ctx, cp.LiquidationMarketID, cp.Denom, cp.LiquidationRatio)
|
err = k.LiquidateCdps(ctx, cp.LiquidationMarketID, cp.Denom, cp.LiquidationRatio)
|
||||||
if err != nil {
|
if err != nil && !errors.Is(err, pricefeedtypes.ErrNoValidPrice) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := k.RunSurplusAndDebtAuctions(ctx)
|
err := k.RunSurplusAndDebtAuctions(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
distTimeElapsed := sdk.NewInt(ctx.BlockTime().Unix() - previousDistTime.Unix())
|
distTimeElapsed := sdk.NewInt(ctx.BlockTime().Unix() - previousDistTime.Unix())
|
||||||
if !distTimeElapsed.GTE(sdk.NewInt(int64(params.SavingsDistributionFrequency.Seconds()))) {
|
if !distTimeElapsed.GTE(sdk.NewInt(int64(params.SavingsDistributionFrequency.Seconds()))) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = k.DistributeSavingsRate(ctx, params.DebtParam.Denom)
|
err = k.DistributeSavingsRate(ctx, params.DebtParam.Denom)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
k.SetPreviousSavingsDistribution(ctx, ctx.BlockTime())
|
k.SetPreviousSavingsDistribution(ctx, ctx.BlockTime())
|
||||||
}
|
}
|
||||||
|
@ -149,11 +149,13 @@ func (k Keeper) RunSurplusAndDebtAuctions(ctx sdk.Context) error {
|
|||||||
}
|
}
|
||||||
remainingDebt := k.GetTotalDebt(ctx, types.LiquidatorMacc)
|
remainingDebt := k.GetTotalDebt(ctx, types.LiquidatorMacc)
|
||||||
params := k.GetParams(ctx)
|
params := k.GetParams(ctx)
|
||||||
|
|
||||||
if remainingDebt.GTE(params.DebtAuctionThreshold) {
|
if remainingDebt.GTE(params.DebtAuctionThreshold) {
|
||||||
debtLot := sdk.NewCoin(k.GetDebtDenom(ctx), params.DebtAuctionLot)
|
debtLot := sdk.NewCoin(k.GetDebtDenom(ctx), params.DebtAuctionLot)
|
||||||
bidCoin := sdk.NewCoin(params.DebtParam.Denom, debtLot.Amount)
|
bidCoin := sdk.NewCoin(params.DebtParam.Denom, debtLot.Amount)
|
||||||
_, err := k.auctionKeeper.StartDebtAuction(
|
initialLot := sdk.NewCoin(k.GetGovDenom(ctx), debtLot.Amount.Mul(sdk.NewInt(dump)))
|
||||||
ctx, types.LiquidatorMacc, bidCoin, sdk.NewCoin(k.GetGovDenom(ctx), debtLot.Amount.Mul(sdk.NewInt(dump))), debtLot)
|
|
||||||
|
_, err := k.auctionKeeper.StartDebtAuction(ctx, types.LiquidatorMacc, bidCoin, initialLot, debtLot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -163,6 +165,7 @@ func (k Keeper) RunSurplusAndDebtAuctions(ctx sdk.Context) error {
|
|||||||
if !surplus.GTE(params.SurplusAuctionThreshold) {
|
if !surplus.GTE(params.SurplusAuctionThreshold) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
surplusLot := sdk.NewCoin(params.DebtParam.Denom, sdk.MinInt(params.SurplusAuctionLot, surplus))
|
surplusLot := sdk.NewCoin(params.DebtParam.Denom, sdk.MinInt(params.SurplusAuctionLot, surplus))
|
||||||
_, err := k.auctionKeeper.StartSurplusAuction(ctx, types.LiquidatorMacc, surplusLot, k.GetGovDenom(ctx))
|
_, err := k.auctionKeeper.StartSurplusAuction(ctx, types.LiquidatorMacc, surplusLot, k.GetGovDenom(ctx))
|
||||||
return err
|
return err
|
||||||
|
@ -26,8 +26,8 @@ func (k Keeper) CalculateFees(ctx sdk.Context, principal sdk.Coin, periods sdk.I
|
|||||||
func (k Keeper) UpdateFeesForAllCdps(ctx sdk.Context, collateralDenom string) error {
|
func (k Keeper) UpdateFeesForAllCdps(ctx sdk.Context, collateralDenom string) error {
|
||||||
var iterationErr error
|
var iterationErr error
|
||||||
k.IterateCdpsByDenom(ctx, collateralDenom, func(cdp types.CDP) bool {
|
k.IterateCdpsByDenom(ctx, collateralDenom, func(cdp types.CDP) bool {
|
||||||
|
|
||||||
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Principal.Add(cdp.AccumulatedFees))
|
oldCollateralToDebtRatio := k.CalculateCollateralToDebtRatio(ctx, cdp.Collateral, cdp.Principal.Add(cdp.AccumulatedFees))
|
||||||
|
// periods = bblock timestamp - fees updated
|
||||||
periods := sdk.NewInt(ctx.BlockTime().Unix()).Sub(sdk.NewInt(cdp.FeesUpdated.Unix()))
|
periods := sdk.NewInt(ctx.BlockTime().Unix()).Sub(sdk.NewInt(cdp.FeesUpdated.Unix()))
|
||||||
|
|
||||||
newFees := k.CalculateFees(ctx, cdp.Principal, periods, collateralDenom)
|
newFees := k.CalculateFees(ctx, cdp.Principal, periods, collateralDenom)
|
||||||
@ -55,12 +55,14 @@ func (k Keeper) UpdateFeesForAllCdps(ctx sdk.Context, collateralDenom string) er
|
|||||||
if (newFeesSavings.IsZero() && !savingsRate.IsZero()) || (newFeesSurplus.IsZero() && !savingsRate.Equal(sdk.OneDec())) {
|
if (newFeesSavings.IsZero() && !savingsRate.IsZero()) || (newFeesSurplus.IsZero() && !savingsRate.Equal(sdk.OneDec())) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// mint debt coins to the cdp account
|
// mint debt coins to the cdp account
|
||||||
err := k.MintDebtCoins(ctx, types.ModuleName, k.GetDebtDenom(ctx), newFees)
|
err := k.MintDebtCoins(ctx, types.ModuleName, k.GetDebtDenom(ctx), newFees)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
iterationErr = err
|
iterationErr = err
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
previousDebt := k.GetTotalPrincipal(ctx, collateralDenom, dp.Denom)
|
previousDebt := k.GetTotalPrincipal(ctx, collateralDenom, dp.Denom)
|
||||||
newDebt := previousDebt.Add(newFees.Amount)
|
newDebt := previousDebt.Add(newFees.Amount)
|
||||||
k.SetTotalPrincipal(ctx, collateralDenom, dp.Denom, newDebt)
|
k.SetTotalPrincipal(ctx, collateralDenom, dp.Denom, newDebt)
|
||||||
@ -100,17 +102,14 @@ func (k Keeper) IncrementTotalPrincipal(ctx sdk.Context, collateralDenom string,
|
|||||||
total := k.GetTotalPrincipal(ctx, collateralDenom, principal.Denom)
|
total := k.GetTotalPrincipal(ctx, collateralDenom, principal.Denom)
|
||||||
total = total.Add(principal.Amount)
|
total = total.Add(principal.Amount)
|
||||||
k.SetTotalPrincipal(ctx, collateralDenom, principal.Denom, total)
|
k.SetTotalPrincipal(ctx, collateralDenom, principal.Denom, total)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecrementTotalPrincipal decrements the total amount of debt that has been drawn for a particular collateral type
|
// DecrementTotalPrincipal decrements the total amount of debt that has been drawn for a particular collateral type
|
||||||
func (k Keeper) DecrementTotalPrincipal(ctx sdk.Context, collateralDenom string, principal sdk.Coin) {
|
func (k Keeper) DecrementTotalPrincipal(ctx sdk.Context, collateralDenom string, principal sdk.Coin) {
|
||||||
total := k.GetTotalPrincipal(ctx, collateralDenom, principal.Denom)
|
total := k.GetTotalPrincipal(ctx, collateralDenom, principal.Denom)
|
||||||
total = total.Sub(principal.Amount)
|
// NOTE: negative total principal can happen in tests due to rounding errors
|
||||||
if total.IsNegative() {
|
// in fee calculation
|
||||||
// can happen in tests due to rounding errors in fee calculation
|
total = sdk.MaxInt(total.Sub(principal.Amount), sdk.ZeroInt())
|
||||||
total = sdk.ZeroInt()
|
|
||||||
}
|
|
||||||
k.SetTotalPrincipal(ctx, collateralDenom, principal.Denom, total)
|
k.SetTotalPrincipal(ctx, collateralDenom, principal.Denom, total)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ func (k Keeper) DistributeSavingsRate(ctx sdk.Context, debtDenom string) error {
|
|||||||
if !found {
|
if !found {
|
||||||
return sdkerrors.Wrap(types.ErrDebtNotSupported, debtDenom)
|
return sdkerrors.Wrap(types.ErrDebtNotSupported, debtDenom)
|
||||||
}
|
}
|
||||||
|
|
||||||
savingsRateMacc := k.supplyKeeper.GetModuleAccount(ctx, types.SavingsRateMacc)
|
savingsRateMacc := k.supplyKeeper.GetModuleAccount(ctx, types.SavingsRateMacc)
|
||||||
surplusToDistribute := savingsRateMacc.GetCoins().AmountOf(dp.Denom)
|
surplusToDistribute := savingsRateMacc.GetCoins().AmountOf(dp.Denom)
|
||||||
if surplusToDistribute.IsZero() {
|
if surplusToDistribute.IsZero() {
|
||||||
@ -26,21 +27,26 @@ func (k Keeper) DistributeSavingsRate(ctx sdk.Context, debtDenom string) error {
|
|||||||
|
|
||||||
modAccountCoins := k.getModuleAccountCoins(ctx, dp.Denom)
|
modAccountCoins := k.getModuleAccountCoins(ctx, dp.Denom)
|
||||||
totalSupplyLessModAccounts := k.supplyKeeper.GetSupply(ctx).GetTotal().Sub(modAccountCoins)
|
totalSupplyLessModAccounts := k.supplyKeeper.GetSupply(ctx).GetTotal().Sub(modAccountCoins)
|
||||||
|
|
||||||
// values to use in interest calculation
|
// values to use in interest calculation
|
||||||
totalSurplus := sdk.NewDecFromInt(surplusToDistribute)
|
totalSurplus := sdk.NewDecFromInt(surplusToDistribute)
|
||||||
totalSupply := sdk.NewDecFromInt(totalSupplyLessModAccounts.AmountOf(debtDenom))
|
totalSupply := sdk.NewDecFromInt(totalSupplyLessModAccounts.AmountOf(debtDenom))
|
||||||
|
|
||||||
var iterationErr error
|
var iterationErr error
|
||||||
|
// TODO: avoid iterating over all the accounts by keeping the stored stable coin
|
||||||
|
// holders' addresses separately.
|
||||||
k.accountKeeper.IterateAccounts(ctx, func(acc authexported.Account) (stop bool) {
|
k.accountKeeper.IterateAccounts(ctx, func(acc authexported.Account) (stop bool) {
|
||||||
_, ok := acc.(supplyexported.ModuleAccountI)
|
_, ok := acc.(supplyexported.ModuleAccountI)
|
||||||
if ok {
|
if ok {
|
||||||
// don't distribute savings rate to module accounts
|
// don't distribute savings rate to module accounts
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
debtAmount := acc.GetCoins().AmountOf(debtDenom)
|
debtAmount := acc.GetCoins().AmountOf(debtDenom)
|
||||||
if !debtAmount.IsPositive() {
|
if !debtAmount.IsPositive() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// (balance * rewardToDisribute) / totalSupply
|
// (balance * rewardToDisribute) / totalSupply
|
||||||
// interest is the ratable fraction of savings rate owed to that account, rounded using bankers rounding
|
// interest is the ratable fraction of savings rate owed to that account, rounded using bankers rounding
|
||||||
interest := (sdk.NewDecFromInt(debtAmount).Mul(totalSurplus)).Quo(totalSupply).RoundInt()
|
interest := (sdk.NewDecFromInt(debtAmount).Mul(totalSurplus)).Quo(totalSupply).RoundInt()
|
||||||
@ -51,6 +57,7 @@ func (k Keeper) DistributeSavingsRate(ctx sdk.Context, debtDenom string) error {
|
|||||||
if !interest.IsPositive() {
|
if !interest.IsPositive() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
interestCoins := sdk.NewCoins(sdk.NewCoin(debtDenom, interest))
|
interestCoins := sdk.NewCoins(sdk.NewCoin(debtDenom, interest))
|
||||||
err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.SavingsRateMacc, acc.GetAddress(), interestCoins)
|
err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.SavingsRateMacc, acc.GetAddress(), interestCoins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -60,6 +67,7 @@ func (k Keeper) DistributeSavingsRate(ctx sdk.Context, debtDenom string) error {
|
|||||||
surplusToDistribute = surplusToDistribute.Sub(interest)
|
surplusToDistribute = surplusToDistribute.Sub(interest)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
return iterationErr
|
return iterationErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@ func (k Keeper) SeizeCollateral(ctx sdk.Context, cdp types.CDP) error {
|
|||||||
deposits := k.GetDeposits(ctx, cdp.ID)
|
deposits := k.GetDeposits(ctx, cdp.ID)
|
||||||
debt := cdp.Principal.Amount.Add(cdp.AccumulatedFees.Amount)
|
debt := cdp.Principal.Amount.Add(cdp.AccumulatedFees.Amount)
|
||||||
modAccountDebt := k.getModAccountDebt(ctx, types.ModuleName)
|
modAccountDebt := k.getModAccountDebt(ctx, types.ModuleName)
|
||||||
if modAccountDebt.LT(debt) {
|
debt = sdk.MinInt(debt, modAccountDebt)
|
||||||
debt = modAccountDebt
|
|
||||||
}
|
|
||||||
debtCoin := sdk.NewCoin(k.GetDebtDenom(ctx), debt)
|
debtCoin := sdk.NewCoin(k.GetDebtDenom(ctx), debt)
|
||||||
err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, types.LiquidatorMacc, sdk.NewCoins(debtCoin))
|
err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, types.LiquidatorMacc, sdk.NewCoins(debtCoin))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -35,6 +33,12 @@ func (k Keeper) SeizeCollateral(ctx sdk.Context, cdp types.CDP) error {
|
|||||||
|
|
||||||
// liquidate deposits and send collateral from cdp to liquidator
|
// liquidate deposits and send collateral from cdp to liquidator
|
||||||
for _, dep := range deposits {
|
for _, dep := range deposits {
|
||||||
|
err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, types.LiquidatorMacc, sdk.NewCoins(dep.Amount))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
k.DeleteDeposit(ctx, dep.CdpID, dep.Depositor)
|
||||||
|
|
||||||
ctx.EventManager().EmitEvent(
|
ctx.EventManager().EmitEvent(
|
||||||
sdk.NewEvent(
|
sdk.NewEvent(
|
||||||
types.EventTypeCdpLiquidation,
|
types.EventTypeCdpLiquidation,
|
||||||
@ -43,12 +47,8 @@ func (k Keeper) SeizeCollateral(ctx sdk.Context, cdp types.CDP) error {
|
|||||||
sdk.NewAttribute(types.AttributeKeyDeposit, dep.String()),
|
sdk.NewAttribute(types.AttributeKeyDeposit, dep.String()),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, types.LiquidatorMacc, sdk.NewCoins(dep.Amount))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
k.DeleteDeposit(ctx, dep.CdpID, dep.Depositor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = k.AuctionCollateral(ctx, deposits, debt, cdp.Principal.Denom)
|
err = k.AuctionCollateral(ctx, deposits, debt, cdp.Principal.Denom)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -8,9 +8,7 @@ import (
|
|||||||
|
|
||||||
// BeginBlocker runs at the start of every block.
|
// BeginBlocker runs at the start of every block.
|
||||||
func BeginBlocker(ctx sdk.Context, _ abci.RequestBeginBlock, k Keeper) {
|
func BeginBlocker(ctx sdk.Context, _ abci.RequestBeginBlock, k Keeper) {
|
||||||
|
|
||||||
// enact proposals ignoring their expiry time - they could have received enough votes last block before expiring this block
|
// enact proposals ignoring their expiry time - they could have received enough votes last block before expiring this block
|
||||||
k.EnactPassedProposals(ctx)
|
k.EnactPassedProposals(ctx)
|
||||||
|
|
||||||
k.CloseExpiredProposals(ctx)
|
k.CloseExpiredProposals(ctx)
|
||||||
}
|
}
|
||||||
|
@ -207,9 +207,7 @@ func (k Keeper) GetProposalsByCommittee(ctx sdk.Context, committeeID uint64) []t
|
|||||||
|
|
||||||
// DeleteProposalAndVotes removes a proposal and its associated votes.
|
// DeleteProposalAndVotes removes a proposal and its associated votes.
|
||||||
func (k Keeper) DeleteProposalAndVotes(ctx sdk.Context, proposalID uint64) {
|
func (k Keeper) DeleteProposalAndVotes(ctx sdk.Context, proposalID uint64) {
|
||||||
|
|
||||||
votes := k.GetVotesByProposal(ctx, proposalID)
|
votes := k.GetVotesByProposal(ctx, proposalID)
|
||||||
|
|
||||||
k.DeleteProposal(ctx, proposalID)
|
k.DeleteProposal(ctx, proposalID)
|
||||||
for _, v := range votes {
|
for _, v := range votes {
|
||||||
k.DeleteVote(ctx, v.ProposalID, v.Voter)
|
k.DeleteVote(ctx, v.ProposalID, v.Voter)
|
||||||
|
@ -138,7 +138,9 @@ func (k Keeper) EnactPassedProposals(ctx sdk.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !passes {
|
if !passes {
|
||||||
|
// continue to next proposal
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +166,6 @@ func (k Keeper) EnactPassedProposals(ctx sdk.Context) {
|
|||||||
|
|
||||||
// CloseExpiredProposals removes proposals (and associated votes) that have past their deadline.
|
// CloseExpiredProposals removes proposals (and associated votes) that have past their deadline.
|
||||||
func (k Keeper) CloseExpiredProposals(ctx sdk.Context) {
|
func (k Keeper) CloseExpiredProposals(ctx sdk.Context) {
|
||||||
|
|
||||||
k.IterateProposals(ctx, func(proposal types.Proposal) bool {
|
k.IterateProposals(ctx, func(proposal types.Proposal) bool {
|
||||||
if !proposal.HasExpiredBy(ctx.BlockTime()) {
|
if !proposal.HasExpiredBy(ctx.BlockTime()) {
|
||||||
return false
|
return false
|
||||||
|
@ -48,7 +48,8 @@ func (k Keeper) CreateAndDeleteRewardPeriods(ctx sdk.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyRewardsToCdps iterates over the reward periods and creates a claim for each cdp owner that created usdx with the collateral specified in the reward period
|
// ApplyRewardsToCdps iterates over the reward periods and creates a claim for each
|
||||||
|
// cdp owner that created usdx with the collateral specified in the reward period.
|
||||||
func (k Keeper) ApplyRewardsToCdps(ctx sdk.Context) {
|
func (k Keeper) ApplyRewardsToCdps(ctx sdk.Context) {
|
||||||
previousBlockTime, found := k.GetPreviousBlockTime(ctx)
|
previousBlockTime, found := k.GetPreviousBlockTime(ctx)
|
||||||
if !found {
|
if !found {
|
||||||
@ -56,6 +57,7 @@ func (k Keeper) ApplyRewardsToCdps(ctx sdk.Context) {
|
|||||||
k.SetPreviousBlockTime(ctx, previousBlockTime)
|
k.SetPreviousBlockTime(ctx, previousBlockTime)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
k.IterateRewardPeriods(ctx, func(rp types.RewardPeriod) bool {
|
k.IterateRewardPeriods(ctx, func(rp types.RewardPeriod) bool {
|
||||||
expired := false
|
expired := false
|
||||||
// the total amount of usdx created with the collateral type being incentivized
|
// the total amount of usdx created with the collateral type being incentivized
|
||||||
@ -66,6 +68,7 @@ func (k Keeper) ApplyRewardsToCdps(ctx sdk.Context) {
|
|||||||
timeElapsed = sdk.NewInt(rp.End.Unix() - previousBlockTime.Unix())
|
timeElapsed = sdk.NewInt(rp.End.Unix() - previousBlockTime.Unix())
|
||||||
expired = true
|
expired = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// the amount of rewards to pay (rewardAmount * timeElapsed)
|
// the amount of rewards to pay (rewardAmount * timeElapsed)
|
||||||
rewardsThisPeriod := rp.Reward.Amount.Mul(timeElapsed)
|
rewardsThisPeriod := rp.Reward.Amount.Mul(timeElapsed)
|
||||||
id := k.GetNextClaimPeriodID(ctx, rp.Denom)
|
id := k.GetNextClaimPeriodID(ctx, rp.Denom)
|
||||||
@ -85,6 +88,7 @@ func (k Keeper) ApplyRewardsToCdps(ctx sdk.Context) {
|
|||||||
k.HandleRewardPeriodExpiry(ctx, rp)
|
k.HandleRewardPeriodExpiry(ctx, rp)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
k.SetPreviousBlockTime(ctx, ctx.BlockTime())
|
k.SetPreviousBlockTime(ctx, ctx.BlockTime())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,42 +19,44 @@ func (k Keeper) MintPeriodInflation(ctx sdk.Context) error {
|
|||||||
)
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
previousBlockTime, found := k.GetPreviousBlockTime(ctx)
|
previousBlockTime, found := k.GetPreviousBlockTime(ctx)
|
||||||
if !found {
|
if !found {
|
||||||
previousBlockTime = ctx.BlockTime()
|
previousBlockTime = ctx.BlockTime()
|
||||||
k.SetPreviousBlockTime(ctx, previousBlockTime)
|
k.SetPreviousBlockTime(ctx, previousBlockTime)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
for _, period := range params.Periods {
|
for _, period := range params.Periods {
|
||||||
|
switch {
|
||||||
// Case 1 - period is fully expired
|
// Case 1 - period is fully expired
|
||||||
if period.End.Before(previousBlockTime) {
|
case period.End.Before(previousBlockTime):
|
||||||
continue
|
continue
|
||||||
}
|
|
||||||
// Case 2 - period has ended since the previous block time
|
// Case 2 - period has ended since the previous block time
|
||||||
if period.End.After(previousBlockTime) && period.End.Before(ctx.BlockTime()) {
|
case period.End.After(previousBlockTime) && period.End.Before(ctx.BlockTime()):
|
||||||
// calculate time elapsed relative to the periods end time
|
// calculate time elapsed relative to the periods end time
|
||||||
timeElapsed := sdk.NewInt(period.End.Unix() - previousBlockTime.Unix())
|
timeElapsed := sdk.NewInt(period.End.Unix() - previousBlockTime.Unix())
|
||||||
err := k.mintInflationaryCoins(ctx, period.Inflation, timeElapsed, types.GovDenom)
|
err = k.mintInflationaryCoins(ctx, period.Inflation, timeElapsed, types.GovDenom)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// update the value of previousBlockTime so that the next period starts from the end of the last
|
// update the value of previousBlockTime so that the next period starts from the end of the last
|
||||||
// period and not the original value of previousBlockTime
|
// period and not the original value of previousBlockTime
|
||||||
previousBlockTime = period.End
|
previousBlockTime = period.End
|
||||||
}
|
|
||||||
// Case 3 - period is ongoing
|
// Case 3 - period is ongoing
|
||||||
if (period.Start.Before(previousBlockTime) || period.Start.Equal(previousBlockTime)) && period.End.After(ctx.BlockTime()) {
|
case (period.Start.Before(previousBlockTime) || period.Start.Equal(previousBlockTime)) && period.End.After(ctx.BlockTime()):
|
||||||
// calculate time elapsed relative to the current block time
|
// calculate time elapsed relative to the current block time
|
||||||
timeElapsed := sdk.NewInt(ctx.BlockTime().Unix() - previousBlockTime.Unix())
|
timeElapsed := sdk.NewInt(ctx.BlockTime().Unix() - previousBlockTime.Unix())
|
||||||
err := k.mintInflationaryCoins(ctx, period.Inflation, timeElapsed, types.GovDenom)
|
err = k.mintInflationaryCoins(ctx, period.Inflation, timeElapsed, types.GovDenom)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Case 4 - period hasn't started
|
// Case 4 - period hasn't started
|
||||||
if period.Start.After(ctx.BlockTime()) || period.Start.Equal(ctx.BlockTime()) {
|
case period.Start.After(ctx.BlockTime()) || period.Start.Equal(ctx.BlockTime()):
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
k.SetPreviousBlockTime(ctx, ctx.BlockTime())
|
k.SetPreviousBlockTime(ctx, ctx.BlockTime())
|
||||||
return nil
|
return nil
|
||||||
@ -78,11 +80,13 @@ func (k Keeper) mintInflationaryCoins(ctx sdk.Context, inflationRate sdk.Dec, ti
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.EventManager().EmitEvent(
|
ctx.EventManager().EmitEvent(
|
||||||
sdk.NewEvent(
|
sdk.NewEvent(
|
||||||
types.EventTypeKavaDist,
|
types.EventTypeKavaDist,
|
||||||
sdk.NewAttribute(types.AttributeKeyInflation, sdk.NewCoin(denom, amountToMint).String()),
|
sdk.NewAttribute(types.AttributeKeyInflation, sdk.NewCoin(denom, amountToMint).String()),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,23 @@
|
|||||||
package pricefeed
|
package pricefeed
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/kava-labs/kava/x/pricefeed/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EndBlocker updates the current pricefeed
|
// EndBlocker updates the current pricefeed
|
||||||
func EndBlocker(ctx sdk.Context, k Keeper) {
|
func EndBlocker(ctx sdk.Context, k Keeper) {
|
||||||
// Update the current price of each asset.
|
// Update the current price of each asset.
|
||||||
for _, market := range k.GetMarkets(ctx) {
|
for _, market := range k.GetMarkets(ctx) {
|
||||||
if market.Active {
|
if !market.Active {
|
||||||
err := k.SetCurrentPrices(ctx, market.MarketID)
|
continue
|
||||||
if err != nil {
|
}
|
||||||
// In the event of failure, emit an event.
|
|
||||||
ctx.EventManager().EmitEvent(
|
err := k.SetCurrentPrices(ctx, market.MarketID)
|
||||||
sdk.NewEvent(
|
if err != nil && !errors.Is(err, types.ErrNoValidPrice) {
|
||||||
EventTypeNoValidPrices,
|
panic(err)
|
||||||
sdk.NewAttribute(AttributeMarketID, fmt.Sprintf("%s", market.MarketID)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
package keeper
|
package keeper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
@ -37,6 +40,11 @@ func NewKeeper(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Logger returns a module-specific logger.
|
||||||
|
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
|
||||||
|
return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
|
||||||
|
}
|
||||||
|
|
||||||
// SetPrice updates the posted price for a specific oracle
|
// SetPrice updates the posted price for a specific oracle
|
||||||
func (k Keeper) SetPrice(
|
func (k Keeper) SetPrice(
|
||||||
ctx sdk.Context,
|
ctx sdk.Context,
|
||||||
@ -111,40 +119,41 @@ func (k Keeper) SetCurrentPrices(ctx sdk.Context, marketID string) error {
|
|||||||
notExpiredPrices = append(notExpiredPrices, types.NewCurrentPrice(v.MarketID, v.Price))
|
notExpiredPrices = append(notExpiredPrices, types.NewCurrentPrice(v.MarketID, v.Price))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(notExpiredPrices) == 0 {
|
if len(notExpiredPrices) == 0 {
|
||||||
store := ctx.KVStore(k.key)
|
// NOTE: The current price stored will continue storing the most recent (expired)
|
||||||
store.Set(
|
// price if this is not set.
|
||||||
types.CurrentPriceKey(marketID), k.cdc.MustMarshalBinaryBare(types.CurrentPrice{}),
|
// This zero's out the current price stored value for that market and ensures
|
||||||
)
|
// that CDP methods that GetCurrentPrice will return error.
|
||||||
|
k.setCurrentPrice(ctx, marketID, types.CurrentPrice{})
|
||||||
return types.ErrNoValidPrice
|
return types.ErrNoValidPrice
|
||||||
}
|
}
|
||||||
|
|
||||||
medianPrice := k.CalculateMedianPrice(ctx, notExpiredPrices)
|
medianPrice := k.CalculateMedianPrice(ctx, notExpiredPrices)
|
||||||
|
|
||||||
// check case that market price was not set in genesis
|
// check case that market price was not set in genesis
|
||||||
if validPrevPrice {
|
if validPrevPrice && !medianPrice.Equal(prevPrice.Price) {
|
||||||
// only emit event if price has changed
|
// only emit event if price has changed
|
||||||
if !medianPrice.Equal(prevPrice.Price) {
|
ctx.EventManager().EmitEvent(
|
||||||
ctx.EventManager().EmitEvent(
|
sdk.NewEvent(
|
||||||
sdk.NewEvent(
|
types.EventTypeMarketPriceUpdated,
|
||||||
types.EventTypeMarketPriceUpdated,
|
sdk.NewAttribute(types.AttributeMarketID, marketID),
|
||||||
sdk.NewAttribute(types.AttributeMarketID, marketID),
|
sdk.NewAttribute(types.AttributeMarketPrice, medianPrice.String()),
|
||||||
sdk.NewAttribute(types.AttributeMarketPrice, medianPrice.String()),
|
),
|
||||||
),
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
store := ctx.KVStore(k.key)
|
|
||||||
currentPrice := types.NewCurrentPrice(marketID, medianPrice)
|
currentPrice := types.NewCurrentPrice(marketID, medianPrice)
|
||||||
|
k.setCurrentPrice(ctx, marketID, currentPrice)
|
||||||
store.Set(
|
|
||||||
types.CurrentPriceKey(marketID), k.cdc.MustMarshalBinaryBare(currentPrice),
|
|
||||||
)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k Keeper) setCurrentPrice(ctx sdk.Context, marketID string, currentPrice types.CurrentPrice) {
|
||||||
|
store := ctx.KVStore(k.key)
|
||||||
|
store.Set(types.CurrentPriceKey(marketID), k.cdc.MustMarshalBinaryBare(currentPrice))
|
||||||
|
}
|
||||||
|
|
||||||
// CalculateMedianPrice calculates the median prices for the input prices.
|
// CalculateMedianPrice calculates the median prices for the input prices.
|
||||||
func (k Keeper) CalculateMedianPrice(ctx sdk.Context, prices types.CurrentPrices) sdk.Dec {
|
func (k Keeper) CalculateMedianPrice(ctx sdk.Context, prices types.CurrentPrices) sdk.Dec {
|
||||||
l := len(prices)
|
l := len(prices)
|
||||||
|
@ -24,34 +24,35 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper)
|
|||||||
var voteInfos VoteInfos
|
var voteInfos VoteInfos
|
||||||
voteInfos = req.LastCommitInfo.GetVotes()
|
voteInfos = req.LastCommitInfo.GetVotes()
|
||||||
validatorVestingKeys := k.GetAllAccountKeys(ctx)
|
validatorVestingKeys := k.GetAllAccountKeys(ctx)
|
||||||
|
|
||||||
for _, key := range validatorVestingKeys {
|
for _, key := range validatorVestingKeys {
|
||||||
acc := k.GetAccountFromAuthKeeper(ctx, key)
|
acc := k.GetAccountFromAuthKeeper(ctx, key)
|
||||||
if k.AccountIsVesting(ctx, acc.GetAddress()) {
|
if !k.AccountIsVesting(ctx, acc.GetAddress()) {
|
||||||
vote, found := voteInfos.FilterByValidatorAddress(acc.ValidatorAddress)
|
continue
|
||||||
if !found || !vote.SignedLastBlock {
|
|
||||||
if ctx.BlockHeight() <= 1 {
|
|
||||||
// don't count missed blocks on block 1 since there is no vote history
|
|
||||||
k.UpdateMissingSignCount(ctx, acc.GetAddress(), false)
|
|
||||||
} else {
|
|
||||||
// if the validator was not found or explicitly didn't sign, increment the missing sign count
|
|
||||||
k.UpdateMissingSignCount(ctx, acc.GetAddress(), true)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
k.UpdateMissingSignCount(ctx, acc.GetAddress(), false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if a period ended in the last block
|
|
||||||
endTimes := k.GetPeriodEndTimes(ctx, key)
|
|
||||||
|
|
||||||
for i, t := range endTimes {
|
|
||||||
if currentBlockTime.Unix() >= t && previousBlockTime.Unix() < t {
|
|
||||||
k.UpdateVestedCoinsProgress(ctx, key, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// handle any new/remaining debt on the account
|
|
||||||
k.HandleVestingDebt(ctx, key, currentBlockTime)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vote, found := voteInfos.FilterByValidatorAddress(acc.ValidatorAddress)
|
||||||
|
|
||||||
|
var missedBlock bool
|
||||||
|
// if the validator was not found or explicitly didn't sign, increment the missing sign count
|
||||||
|
if (!found || !vote.SignedLastBlock) && ctx.BlockHeight() > 1 {
|
||||||
|
missedBlock = true
|
||||||
|
}
|
||||||
|
|
||||||
|
k.UpdateMissingSignCount(ctx, acc.GetAddress(), missedBlock)
|
||||||
|
|
||||||
|
// check if a period ended in the last block
|
||||||
|
endTimes := k.GetPeriodEndTimes(ctx, key)
|
||||||
|
|
||||||
|
for i, t := range endTimes {
|
||||||
|
if currentBlockTime.Unix() >= t && previousBlockTime.Unix() < t {
|
||||||
|
k.UpdateVestedCoinsProgress(ctx, key, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// handle any new/remaining debt on the account
|
||||||
|
k.HandleVestingDebt(ctx, key, currentBlockTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
k.SetPreviousBlockTime(ctx, currentBlockTime)
|
k.SetPreviousBlockTime(ctx, currentBlockTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ func TestBeginBlockerZeroHeight(t *testing.T) {
|
|||||||
|
|
||||||
vva = vvk.GetAccountFromAuthKeeper(ctx, vva.Address)
|
vva = vvk.GetAccountFromAuthKeeper(ctx, vva.Address)
|
||||||
// require missed block counter doesn't increment because there's no voting history
|
// require missed block counter doesn't increment because there's no voting history
|
||||||
require.Equal(t, types.CurrentPeriodProgress{0, 1}, vva.CurrentPeriodProgress)
|
require.Equal(t, types.CurrentPeriodProgress{MissedBlocks: 0, TotalBlocks: 1}, vva.CurrentPeriodProgress)
|
||||||
|
|
||||||
// mark the validator as having missed
|
// mark the validator as having missed
|
||||||
req = abci.RequestBeginBlock{
|
req = abci.RequestBeginBlock{
|
||||||
@ -90,7 +90,7 @@ func TestBeginBlockerZeroHeight(t *testing.T) {
|
|||||||
BeginBlocker(ctx, req, vvk)
|
BeginBlocker(ctx, req, vvk)
|
||||||
|
|
||||||
vva = vvk.GetAccountFromAuthKeeper(ctx, vva.Address)
|
vva = vvk.GetAccountFromAuthKeeper(ctx, vva.Address)
|
||||||
require.Equal(t, types.CurrentPeriodProgress{0, 2}, vva.CurrentPeriodProgress)
|
require.Equal(t, types.CurrentPeriodProgress{MissedBlocks: 0, TotalBlocks: 2}, vva.CurrentPeriodProgress)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBeginBlockerSignedBlock(t *testing.T) {
|
func TestBeginBlockerSignedBlock(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user