package keeper import ( colinearmath "colinear/x/colinearcore/math" "colinear/x/colinearcore/memdb" "colinear/x/colinearcore/types" "log" "math/big" "time" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/pkg/errors" ) func (k Keeper) AuctionIsExpired(ctx sdk.Context, auctionId string) (bool, error) { auction, found := k.GetAuction(ctx, auctionId) // make sure the auction exists on-chain if !found { return true, errors.Errorf("auction %s not found", auctionId) } return uint64(ctx.BlockHeight()) >= auction.Deadline, nil } func (k Keeper) FinalizeExpiredAuctions(ctx sdk.Context) { memdb.AuctionDB.ForEachAuctionBidList(func(auctionId string) error { auction, found := k.GetAuction(ctx, auctionId) // make sure the auction exists on-chain if !found { return errors.Errorf("auction %s not found", auctionId) } if uint64(ctx.BlockHeight()) >= auction.Deadline { var err error auction.Best, err = memdb.AuctionDB.GetLowestBid(auctionId) if err != nil { return errors.Errorf("could not get highest bid for auction %s: %s", auctionId, err) } // Remaining Unpaid: Full bid amount auction.Remaining = auction.Best.Amount // clear auction bids if err := memdb.AuctionDB.ClearAuctionBids(auctionId); err != nil { return errors.Errorf("failed to clear auction from memcache: %s", err) } // clear verified provider list; swallow error since this isn't critical for now _ = memdb.AuctionDB.ClearVerifiedProviders(auctionId) // if err := memdb.AuctionDB.ClearVerifiedProviders(auctionId); err != nil { // return errors.Errorf("failed to clear verified providers for auction %s: %s", auctionId, err) // } // pay out unpaid remainder to auction creator ceiling := new(big.Int) ceiling.SetString(auction.Ceiling, 10) lowestBidAmt := new(big.Int) lowestBidAmt.SetString(auction.Best.Amount, 10) // only pay out if there is a difference if ceiling.Cmp(lowestBidAmt) == 1 { amtRemaining := new(big.Int) amtRemaining.Sub(ceiling, lowestBidAmt) coins := sdk.NewCoins(sdk.NewCoin( auction.Denom, sdk.NewIntFromBigInt(amtRemaining), )) recipAddr, err := sdk.AccAddressFromBech32(auction.Owner) if err != nil { return errors.Errorf("failed to parse address %s", auction.Owner) } if err := k.bank.SendCoinsFromModuleToAccount(ctx, types.ModuleName, recipAddr, coins); err != nil { log.Printf("Failed to send coins from module: %s\n", err) // log.Fatalf("Failed to send coins from module: %s\n", err) } } // lease period starts now auction.LeaseStart = uint64(ctx.BlockTime().Unix()) // end auction k.SetAuction(ctx, auction) } return nil }) } func (k *Keeper) PayAuctionAmountDue(ctx sdk.Context, auctionId string) error { auction, found := k.GetAuction(ctx, auctionId) if !found { return errors.Errorf("auction %s not found", auctionId) } blockTime := ctx.BlockTime() deadline := time.Unix(int64(auction.Deadline), 0) if blockTime.After(deadline) { return nil } else { amtTotal := new(big.Int) amtTotal.SetString(auction.Best.Amount, 10) amtRemaining := new(big.Int) amtTotal.SetString(auction.Remaining, 10) amt, err := colinearmath.CalcAmountVestableLinear( amtTotal, amtRemaining, ctx.BlockTime(), time.Unix(int64(auction.LeaseStart), 0), time.Unix(int64(auction.LeaseEnd), 0), ) if err != nil { return err } coins := sdk.NewCoins(sdk.NewCoin(auction.Denom, sdk.NewIntFromBigInt(amt))) err = k.bank.SendCoinsFromModuleToAccount(ctx, "colinear", sdk.AccAddress(auction.Best.Owner), coins) return err } }