emit hard liquidation event (#790)

This commit is contained in:
Denali Marsh 2021-02-03 23:23:17 +01:00 committed by GitHub
parent 7be0c8b48e
commit 0c1fa5d27b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 31 deletions

View File

@ -23,7 +23,7 @@ const (
DefaultParamspace = types.DefaultParamspace DefaultParamspace = types.DefaultParamspace
DelegatorAccount = types.DelegatorAccount DelegatorAccount = types.DelegatorAccount
EventTypeDeleteHardDeposit = types.EventTypeDeleteHardDeposit EventTypeDeleteHardDeposit = types.EventTypeDeleteHardDeposit
EventTypeDepositLiquidation = types.EventTypeDepositLiquidation EventTypeHardLiquidation = types.EventTypeHardLiquidation
EventTypeHardBorrow = types.EventTypeHardBorrow EventTypeHardBorrow = types.EventTypeHardBorrow
EventTypeHardDelegatorDistribution = types.EventTypeHardDelegatorDistribution EventTypeHardDelegatorDistribution = types.EventTypeHardDelegatorDistribution
EventTypeHardDeposit = types.EventTypeHardDeposit EventTypeHardDeposit = types.EventTypeHardDeposit

View File

@ -95,29 +95,28 @@ func (k Keeper) SeizeDeposits(ctx sdk.Context, keeper sdk.AccAddress, deposit ty
} }
// Seize % of every deposit and send to the keeper // Seize % of every deposit and send to the keeper
aucDeposits := sdk.Coins{} keeperRewardCoins := sdk.Coins{}
for _, depCoin := range deposit.Amount { for _, depCoin := range deposit.Amount {
denom := depCoin.Denom mm, _ := k.GetMoneyMarket(ctx, depCoin.Denom)
amount := depCoin.Amount
mm, _ := k.GetMoneyMarket(ctx, denom)
// No keeper rewards if liquidated by LTV index // No keeper rewards if liquidated by LTV index
if !keeper.Equals(sdk.AccAddress(types.LiquidatorAccount)) { if !keeper.Equals(sdk.AccAddress(types.LiquidatorAccount)) {
keeperReward := mm.KeeperRewardPercentage.MulInt(amount).TruncateInt() keeperReward := mm.KeeperRewardPercentage.MulInt(depCoin.Amount).TruncateInt()
if keeperReward.GT(sdk.ZeroInt()) { if keeperReward.GT(sdk.ZeroInt()) {
// Send keeper their reward // Send keeper their reward
keeperCoin := sdk.NewCoin(denom, keeperReward) keeperCoin := sdk.NewCoin(depCoin.Denom, keeperReward)
err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleAccountName, keeper, sdk.NewCoins(keeperCoin)) keeperRewardCoins = append(keeperRewardCoins, keeperCoin)
}
}
}
if !keeperRewardCoins.Empty() {
err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleAccountName, keeper, keeperRewardCoins)
if err != nil { if err != nil {
return err return err
} }
amount = amount.Sub(keeperReward)
}
} }
// Add remaining deposit coin to aucDeposits // All deposit amounts not given to keeper as rewards are eligible to be auctioned off
aucDeposits = aucDeposits.Add(sdk.NewCoin(denom, amount)) aucDeposits := deposit.Amount.Sub(keeperRewardCoins)
}
// Build valuation map to hold deposit coin USD valuations // Build valuation map to hold deposit coin USD valuations
depositCoinValues := types.NewValuationMap() depositCoinValues := types.NewValuationMap()
@ -138,17 +137,26 @@ func (k Keeper) SeizeDeposits(ctx sdk.Context, keeper sdk.AccAddress, deposit ty
// Loan-to-Value ratio after sending keeper their reward // Loan-to-Value ratio after sending keeper their reward
ltv := borrowCoinValues.Sum().Quo(depositCoinValues.Sum()) ltv := borrowCoinValues.Sum().Quo(depositCoinValues.Sum())
err = k.StartAuctions(ctx, deposit.Depositor, borrow.Amount, aucDeposits, depositCoinValues, borrowCoinValues, ltv, liqMap) liquidatedCoins, err := k.StartAuctions(ctx, deposit.Depositor, borrow.Amount, aucDeposits, depositCoinValues, borrowCoinValues, ltv, liqMap)
if err != nil { // If some coins were liquidated and sent to auction prior to error, still need to emit liquidation event
return err if !liquidatedCoins.Empty() {
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeHardLiquidation,
sdk.NewAttribute(types.AttributeKeyLiquidatedOwner, deposit.Depositor.String()),
sdk.NewAttribute(types.AttributeKeyLiquidatedCoins, liquidatedCoins.String()),
sdk.NewAttribute(types.AttributeKeyKeeper, keeper.String()),
sdk.NewAttribute(types.AttributeKeyKeeperRewardCoins, keeperRewardCoins.String()),
),
)
} }
// Returns nil if there's no error
return nil return err
} }
// StartAuctions attempts to start auctions for seized assets // StartAuctions attempts to start auctions for seized assets
func (k Keeper) StartAuctions(ctx sdk.Context, borrower sdk.AccAddress, borrows, deposits sdk.Coins, func (k Keeper) StartAuctions(ctx sdk.Context, borrower sdk.AccAddress, borrows, deposits sdk.Coins,
depositCoinValues, borrowCoinValues types.ValuationMap, ltv sdk.Dec, liqMap map[string]LiqData) error { depositCoinValues, borrowCoinValues types.ValuationMap, ltv sdk.Dec, liqMap map[string]LiqData) (sdk.Coins, error) {
// Sort keys to ensure deterministic behavior // Sort keys to ensure deterministic behavior
bKeys := borrowCoinValues.GetSortedKeys() bKeys := borrowCoinValues.GetSortedKeys()
dKeys := depositCoinValues.GetSortedKeys() dKeys := depositCoinValues.GetSortedKeys()
@ -161,6 +169,7 @@ func (k Keeper) StartAuctions(ctx sdk.Context, borrower sdk.AccAddress, borrows,
macc := k.supplyKeeper.GetModuleAccount(ctx, types.ModuleAccountName) macc := k.supplyKeeper.GetModuleAccount(ctx, types.ModuleAccountName)
maccCoins := macc.SpendableCoins(ctx.BlockTime()) maccCoins := macc.SpendableCoins(ctx.BlockTime())
var liquidatedCoins sdk.Coins
for _, bKey := range bKeys { for _, bKey := range bKeys {
bValue := borrowCoinValues.Get(bKey) bValue := borrowCoinValues.Get(bKey)
maxLotSize := bValue.Quo(ltv) maxLotSize := bValue.Quo(ltv)
@ -188,18 +197,20 @@ func (k Keeper) StartAuctions(ctx sdk.Context, borrower sdk.AccAddress, borrows,
// Sanity check that we can deliver coins to the liquidator account // Sanity check that we can deliver coins to the liquidator account
if deposits.AmountOf(dKey).LT(lot.Amount) { if deposits.AmountOf(dKey).LT(lot.Amount) {
return types.ErrInsufficientCoins return liquidatedCoins, types.ErrInsufficientCoins
} }
// Start auction: bid = full borrow amount, lot = maxLotSize // Start auction: bid = full borrow amount, lot = maxLotSize
err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleAccountName, types.LiquidatorAccount, sdk.NewCoins(lot)) err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleAccountName, types.LiquidatorAccount, sdk.NewCoins(lot))
if err != nil { if err != nil {
return err return liquidatedCoins, err
} }
_, err = k.auctionKeeper.StartCollateralAuction(ctx, types.LiquidatorAccount, lot, bid, returnAddrs, weights, debt) _, err = k.auctionKeeper.StartCollateralAuction(ctx, types.LiquidatorAccount, lot, bid, returnAddrs, weights, debt)
if err != nil { if err != nil {
return err return liquidatedCoins, err
} }
// Add lot to liquidated coins
liquidatedCoins = liquidatedCoins.Add(lot)
// Update USD valuation maps // Update USD valuation maps
borrowCoinValues.SetZero(bKey) borrowCoinValues.SetZero(bKey)
@ -231,18 +242,20 @@ func (k Keeper) StartAuctions(ctx sdk.Context, borrower sdk.AccAddress, borrows,
// Sanity check that we can deliver coins to the liquidator account // Sanity check that we can deliver coins to the liquidator account
if deposits.AmountOf(dKey).LT(lot.Amount) { if deposits.AmountOf(dKey).LT(lot.Amount) {
return types.ErrInsufficientCoins return liquidatedCoins, types.ErrInsufficientCoins
} }
// Start auction: bid = maxBid, lot = whole deposit amount // Start auction: bid = maxBid, lot = whole deposit amount
err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleAccountName, types.LiquidatorAccount, sdk.NewCoins(lot)) err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleAccountName, types.LiquidatorAccount, sdk.NewCoins(lot))
if err != nil { if err != nil {
return err return liquidatedCoins, err
} }
_, err = k.auctionKeeper.StartCollateralAuction(ctx, types.LiquidatorAccount, lot, bid, returnAddrs, weights, debt) _, err = k.auctionKeeper.StartCollateralAuction(ctx, types.LiquidatorAccount, lot, bid, returnAddrs, weights, debt)
if err != nil { if err != nil {
return err return liquidatedCoins, err
} }
// Add lot to liquidated coins
liquidatedCoins = liquidatedCoins.Add(lot)
// Update variables to account for partial auction // Update variables to account for partial auction
borrowCoinValues.Decrement(bKey, maxBid) borrowCoinValues.Decrement(bKey, maxBid)
@ -268,12 +281,12 @@ func (k Keeper) StartAuctions(ctx sdk.Context, borrower sdk.AccAddress, borrows,
returnCoin := sdk.NewCoins(sdk.NewCoin(dKey, remaining)) returnCoin := sdk.NewCoins(sdk.NewCoin(dKey, remaining))
err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleAccountName, borrower, returnCoin) err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleAccountName, borrower, returnCoin)
if err != nil { if err != nil {
return err return liquidatedCoins, err
} }
} }
} }
return nil return liquidatedCoins, nil
} }
// IsWithinValidLtvRange compares a borrow and deposit to see if it's within a valid LTV range at current prices // IsWithinValidLtvRange compares a borrow and deposit to see if it's within a valid LTV range at current prices

View File

@ -8,7 +8,7 @@ const (
EventTypeDeleteHardDeposit = "delete_hard_deposit" EventTypeDeleteHardDeposit = "delete_hard_deposit"
EventTypeHardWithdrawal = "hard_withdrawal" EventTypeHardWithdrawal = "hard_withdrawal"
EventTypeHardBorrow = "hard_borrow" EventTypeHardBorrow = "hard_borrow"
EventTypeDepositLiquidation = "hard_liquidation" EventTypeHardLiquidation = "hard_liquidation"
EventTypeHardRepay = "hard_repay" EventTypeHardRepay = "hard_repay"
AttributeValueCategory = ModuleName AttributeValueCategory = ModuleName
AttributeKeyBlockHeight = "block_height" AttributeKeyBlockHeight = "block_height"
@ -22,4 +22,8 @@ const (
AttributeKeyBorrowCoins = "borrow_coins" AttributeKeyBorrowCoins = "borrow_coins"
AttributeKeySender = "sender" AttributeKeySender = "sender"
AttributeKeyRepayCoins = "repay_coins" AttributeKeyRepayCoins = "repay_coins"
AttributeKeyLiquidatedOwner = "liquidated_owner"
AttributeKeyLiquidatedCoins = "liquidated_coins"
AttributeKeyKeeper = "keeper"
AttributeKeyKeeperRewardCoins = "keeper_reward_coins"
) )