Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backedloan-refactor #659

Merged
merged 4 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions proto/ununifi/nftbackedloan/nftbackedloan.proto
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,11 @@ message Liquidation {
message Liquidations {
Liquidation liquidation = 1 [(gogoproto.nullable) = true];
repeated Liquidation next_liquidation = 2 [(gogoproto.nullable) = false];
}

message RepayInfo {
cosmos.base.v1beta1.Coin repaid_amount = 1 [(gogoproto.nullable) = false];
cosmos.base.v1beta1.Coin repaid_interest_amount = 2 [(gogoproto.nullable) = false];
cosmos.base.v1beta1.Coin remaining_amount = 3 [(gogoproto.nullable) = false];
google.protobuf.Timestamp last_repaid_at = 4[(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
}
2 changes: 1 addition & 1 deletion x/nftbackedloan/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
func EndBlocker(ctx sdk.Context, k keeper.Keeper) {

// process liquidation of expired bids
k.ProcessLiquidateExpiredBids(ctx)
k.LiquidateExpiredBids(ctx)

// handle full payment period endings
k.HandleFullPaymentsPeriodEndings(ctx)
Expand Down
45 changes: 2 additions & 43 deletions x/nftbackedloan/keeper/bid.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,46 +377,7 @@ func (k Keeper) PayRemainder(ctx sdk.Context, msg *types.MsgPayRemainder) error
return nil
}

// func CheckBidParams(listing types.NftListing, bid, deposit sdk.Coin, bids []types.NftBid) error {
// c := listing.MinimumDepositRate
// p := sdk.NewDecFromInt(bid.Amount)
// cp := c.Mul(p)
// depositDec := sdk.NewDecFromInt(deposit.Amount)
// if cp.GT(depositDec) {
// return types.ErrNotEnoughDeposit
// }
// q := bid
// s := deposit
// for _, bid := range bids {
// q = q.Add(bid.Price)
// s = s.Add(bid.Deposit)
// }

// bidLen := 1
// if len(bids) > 0 {
// // sum new bid and old bids
// bidLen = len(bids) + 1
// }
// q.Amount = q.Amount.Quo(sdk.NewInt(int64(bidLen)))
// if q.IsLTE(s) {
// fmt.Println("q", q.String())
// fmt.Println("s", s.String())
// return types.ErrBidParamInvalid
// }
// q_s := q.Sub(s)
// q_s_dec := sdk.NewDecFromInt(q_s.Amount)
// // todo implement min{bid, q-s}

// if depositDec.GT(q_s_dec) {
// fmt.Println("depositDec", depositDec.String())
// fmt.Println("q_s_dec", q_s_dec.String())
// // deposit amount bigger
// return types.ErrBidParamInvalid
// }
// return nil
// }

func (k Keeper) GetActiveNftBiddingsExpired(ctx sdk.Context, endTime time.Time) []types.NftBid {
func (k Keeper) GetExpiredBids(ctx sdk.Context, endTime time.Time) []types.NftBid {
store := ctx.KVStore(k.storeKey)
timeKey := getTimeKey(types.KeyPrefixEndTimeNftBid, endTime)
it := store.Iterator([]byte(types.KeyPrefixEndTimeNftBid), storetypes.InclusiveEndBytes(timeKey))
Expand All @@ -425,8 +386,6 @@ func (k Keeper) GetActiveNftBiddingsExpired(ctx sdk.Context, endTime time.Time)
bids := []types.NftBid{}
for ; it.Valid(); it.Next() {
bidId := types.NftBidBytesToBidId(it.Value())
fmt.Println("GetActiveNftBiddingsExpired")
fmt.Println(bidId)
bidder, _ := sdk.AccAddressFromBech32(bidId.Bidder)
bid, err := k.GetBid(ctx, bidId.NftId.IdBytes(), bidder)
if err != nil {
Expand All @@ -446,7 +405,7 @@ func (k Keeper) DeleteBidsWithoutBorrowing(ctx sdk.Context, bids []types.NftBid)
continue
}
if listing.IsBidding() {
if !bid.IsBorrowing() {
if !bid.IsBorrowed() {
err := k.SafeCloseBid(ctx, bid)
if err != nil {
fmt.Println(err)
Expand Down
56 changes: 0 additions & 56 deletions x/nftbackedloan/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,18 +185,6 @@ func (k Keeper) GetListedClass(ctx sdk.Context, classId string, limit int) (*typ
}, nil
}

// func (k Keeper) Loans(c context.Context, req *types.QueryLoansRequest) (*types.QueryLoansResponse, error) {
// if req == nil {
// return nil, status.Error(codes.InvalidArgument, "invalid request")
// }

// // ctx := sdk.UnwrapSDKContext(c)
// return &types.QueryLoansResponse{
// // todo impl
// Loans: []types.Loan{},
// }, nil
// }

func (k Keeper) Loan(c context.Context, req *types.QueryLoanRequest) (*types.QueryLoanResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
Expand Down Expand Up @@ -278,50 +266,6 @@ func (k Keeper) Rewards(c context.Context, req *types.QueryRewardsRequest) (*typ
return &types.QueryRewardsResponse{}, nil
}

// func (k Keeper) PaymentStatus(c context.Context, req *types.QueryPaymentStatusRequest) (*types.QueryPaymentStatusResponse, error) {
// if req == nil {
// return nil, status.Error(codes.InvalidArgument, "invalid request")
// }

// ctx := sdk.UnwrapSDKContext(c)
// nft := types.NftIdentifier{
// ClassId: req.ClassId,
// NftId: req.NftId,
// }
// listing, err := k.GetNftListingByIdBytes(ctx, nft.IdBytes())
// if err != nil {
// return &types.QueryPaymentStatusResponse{}, err
// }
// bids := k.GetBidsByNft(ctx, nft.IdBytes())
// if len(bids) == 0 {
// return nil, status.Error(codes.InvalidArgument, "not existing bidder")
// }

// var bidderBid types.NftBid
// for _, v := range bids {
// if v.Id.Bidder == req.Bidder {
// bidderBid = v
// }
// }
// if (bidderBid.Equal(types.NftBid{})) {
// return nil, status.Error(codes.InvalidArgument, "does not match bidder")
// }

// allPaid := listing.State >= types.ListingState_LIQUIDATION && bidderBid.Price.Amount.Equal(bidderBid.Deposit.Amount)
// return &types.QueryPaymentStatusResponse{
// PaymentStatus: types.PaymentStatus{
// NftId: listing.NftId,
// State: listing.State,
// Bidder: bidderBid.Id.Bidder,
// Amount: bidderBid.Price,
// AutomaticPayment: bidderBid.AutomaticPayment,
// PaidAmount: bidderBid.Deposit.Amount,
// CreatedAt: bidderBid.CreatedAt,
// AllPaid: allPaid,
// },
// }, nil
// }

func (k Keeper) Liquidation(c context.Context, req *types.QueryLiquidationRequest) (*types.QueryLiquidationResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
Expand Down
40 changes: 13 additions & 27 deletions x/nftbackedloan/keeper/liquidation.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,6 @@ func (k Keeper) SetLiquidation(ctx sdk.Context, msg *types.MsgEndNftListing) err

bids := k.GetBidsByNft(ctx, listing.NftId.IdBytes())
if len(bids) == 0 {
// sender, err := sdk.AccAddressFromBech32(msg.Sender)
// if err != nil {
// return err
// }
// err = k.nftKeeper.Transfer(ctx, listing.NftId.ClassId, listing.NftId.NftId, sender)
// if err != nil {
// return err
// }

// enable NFT transfer
data, found := k.nftKeeper.GetNftData(ctx, msg.NftId.ClassId, msg.NftId.NftId)
Expand Down Expand Up @@ -104,16 +96,16 @@ func (k Keeper) SetLiquidation(ctx sdk.Context, msg *types.MsgEndNftListing) err
return nil
}

func (k Keeper) ProcessLiquidateExpiredBids(ctx sdk.Context) {
func (k Keeper) LiquidateExpiredBids(ctx sdk.Context) {
fmt.Println("---Block time---")
fmt.Println(ctx.BlockTime())
bids := k.GetActiveNftBiddingsExpired(ctx, ctx.BlockTime())
bids := k.GetExpiredBids(ctx, ctx.BlockTime())
fmt.Println("---expired bids---")
fmt.Println(bids)
k.DeleteBidsWithoutBorrowing(ctx, bids)
checkListingsWithBorrowedBids := map[types.NftListing][]types.NftBid{}
for _, bid := range bids {
if !bid.IsBorrowing() {
if !bid.IsBorrowed() {
continue
}

Expand Down Expand Up @@ -147,7 +139,7 @@ func (k Keeper) ProcessLiquidateExpiredBids(ctx sdk.Context) {
}
}

func (k Keeper) LiquidationProcess(ctx sdk.Context, bids types.NftBids, listing types.NftListing, params types.Params) error {
func (k Keeper) RunLiquidationProcess(ctx sdk.Context, bids types.NftBids, listing types.NftListing, params types.Params) error {
// loop to find winner bid (collect deposits + bid amount > repay amount)
bidsSortedByDeposit := bids.SortHigherDeposit()
winnerBid, forfeitedBids, refundBids, err := types.LiquidationBid(bidsSortedByDeposit, listing, listing.LiquidatedAt)
Expand All @@ -158,15 +150,15 @@ func (k Keeper) LiquidationProcess(ctx sdk.Context, bids types.NftBids, listing
cacheCtx, write := ctx.CacheContext()
if winnerBid.IsNil() {
// No one has PayRemainder.
err := k.LiquidationProcessNoWinner(cacheCtx, bidsSortedByDeposit, listing)
err := k.LiquidateWithoutWinner(cacheCtx, bidsSortedByDeposit, listing)
if err != nil {
fmt.Println("failed to liquidation process with no winner: %w", err)
return err
}
k.DeleteNftListings(ctx, listing)
} else {
// forfeitedBids, refundBids := types.ForfeitedBidsAndRefundBids(bidsSortedByDeposit, winnerBid)
err := k.LiquidationProcessWithWinner(cacheCtx, forfeitedBids, refundBids, listing)
err := k.LiquidateWithWinner(cacheCtx, forfeitedBids, refundBids, listing)
if err != nil {
fmt.Println("failed to liquidation process with winner: %w", err)
return err
Expand All @@ -181,20 +173,20 @@ func (k Keeper) LiquidationProcess(ctx sdk.Context, bids types.NftBids, listing
}

// todo add test
func (k Keeper) LiquidationProcessNoWinner(ctx sdk.Context, bids types.NftBids, listing types.NftListing) error {
func (k Keeper) LiquidateWithoutWinner(ctx sdk.Context, bids types.NftBids, listing types.NftListing) error {
listingOwner, err := sdk.AccAddressFromBech32(listing.Owner)
if err != nil {
return err
}

// collect deposit from all bids
forfeitedDeposit, err := k.CollectedDepositFromBids(ctx, bids, listing)
forfeitedDeposit, err := k.ForfeitDepositsFromBids(ctx, bids, listing)
if err != nil {
return err
}
listing = listing.AddCollectedAmount(forfeitedDeposit)

borrowAmount := bids.TotalBorrowAmount()
borrowAmount := bids.TotalBorrowedAmount()
// pay fee
if listing.IsNegativeCollectedAmount() {
return types.ErrNegativeCollectedAmount
Expand All @@ -208,12 +200,6 @@ func (k Keeper) LiquidationProcessNoWinner(ctx sdk.Context, bids types.NftBids,
return err
}

// transfer nft to listing owner
// err = k.nftKeeper.Transfer(ctx, listing.NftId.ClassId, listing.NftId.NftId, listingOwner)
// if err != nil {
// return err
// }

// enable NFT transfer
data, found := k.nftKeeper.GetNftData(ctx, listing.NftId.ClassId, listing.NftId.NftId)
if !found {
Expand All @@ -228,8 +214,8 @@ func (k Keeper) LiquidationProcessNoWinner(ctx sdk.Context, bids types.NftBids,
}

// todo add test
func (k Keeper) LiquidationProcessWithWinner(ctx sdk.Context, forfeitedBids, refundBids types.NftBids, listing types.NftListing) error {
forfeitedDeposit, err := k.CollectedDepositFromBids(ctx, forfeitedBids, listing)
func (k Keeper) LiquidateWithWinner(ctx sdk.Context, forfeitedBids, refundBids types.NftBids, listing types.NftListing) error {
forfeitedDeposit, err := k.ForfeitDepositsFromBids(ctx, forfeitedBids, listing)
if err != nil {
fmt.Println("failed to collect deposit from bids: %w", err)
return err
Expand All @@ -244,7 +230,7 @@ func (k Keeper) LiquidationProcessWithWinner(ctx sdk.Context, forfeitedBids, ref
// refund bids
if len(refundBids) > 0 {
refundInterestAmount := refundBids.TotalCompoundInterest(listing.LiquidatedAt)
refundBorrowedAmount := refundBids.TotalBorrowAmount()
refundBorrowedAmount := refundBids.TotalBorrowedAmount()
totalSubAmount = totalSubAmount.Add(refundInterestAmount).Add(refundBorrowedAmount)
}

Expand All @@ -271,7 +257,7 @@ func (k Keeper) RefundBids(ctx sdk.Context, refundBids types.NftBids, time time.
}

// todo add test
func (k Keeper) CollectedDepositFromBids(ctx sdk.Context, bids types.NftBids, listing types.NftListing) (sdk.Coin, error) {
func (k Keeper) ForfeitDepositsFromBids(ctx sdk.Context, bids types.NftBids, listing types.NftListing) (sdk.Coin, error) {
result := sdk.NewCoin(listing.BidDenom, sdk.ZeroInt())
for _, bid := range bids {
// not pay bidder amount, collected deposit
Expand Down
14 changes: 7 additions & 7 deletions x/nftbackedloan/keeper/loan.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ func (k Keeper) ManualRepay(ctx sdk.Context, nft types.NftIdentifier, repays []t
continue
}

repaidResult := bid.RepaidResult(repay.Amount, ctx.BlockTime())
bid.Borrow.Amount = repaidResult.RemainingBorrowAmount
repaidResult := bid.RepayInfo(repay.Amount, ctx.BlockTime())
bid.Borrow.Amount = repaidResult.RemainingAmount
bid.Borrow.LastRepaidAt = repaidResult.LastRepaidAt
repaidAmount = repaidAmount.Add(repaidResult.RepaidAmount)

Expand Down Expand Up @@ -208,18 +208,18 @@ func (k Keeper) AutoRepay(ctx sdk.Context, nft types.NftIdentifier, bids types.N
continue
}

repaidResult := bid.FullRepaidResult(ctx.BlockTime())
bid.Borrow.Amount = repaidResult.RemainingBorrowAmount
bid.Borrow.LastRepaidAt = repaidResult.LastRepaidAt
repaidAmount = repaidAmount.Add(repaidResult.RepaidAmount)
repaidInfo := bid.RepayInfoInFull(ctx.BlockTime())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InFull seems not good

bid.Borrow.Amount = repaidInfo.RemainingAmount
bid.Borrow.LastRepaidAt = repaidInfo.LastRepaidAt
repaidAmount = repaidAmount.Add(repaidInfo.RepaidAmount)

err = k.SetBid(ctx, bid)
if err != nil {
return err
}

// send interest to bidder
err = k.SendInterestToBidder(ctx, bid, repaidResult.RepaidInterestAmount)
err = k.SendInterestToBidder(ctx, bid, repaidInfo.RepaidInterestAmount)
if err != nil {
return err
}
Expand Down
11 changes: 1 addition & 10 deletions x/nftbackedloan/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,13 @@ func (k msgServer) CancelBid(c context.Context, msg *types.MsgCancelBid) (*types

func (k msgServer) SellingDecision(c context.Context, msg *types.MsgSellingDecision) (*types.MsgSellingDecisionResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
err := k.keeper.SellingDecision(ctx, msg)
err := k.keeper.SetSellingDecision(ctx, msg)
if err != nil {
return nil, err
}
return &types.MsgSellingDecisionResponse{}, nil
}

// func (k msgServer) EndNftListing(c context.Context, msg *types.MsgEndNftListing) (*types.MsgEndNftListingResponse, error) {
// ctx := sdk.UnwrapSDKContext(c)
// err := k.keeper.EndNftListing(ctx, msg)
// if err != nil {
// return nil, err
// }
// return &types.MsgEndNftListingResponse{}, nil
// }

func (k msgServer) PayRemainder(c context.Context, msg *types.MsgPayRemainder) (*types.MsgPayRemainderResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
err := k.keeper.PayRemainder(ctx, msg)
Expand Down
Loading