mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-27 00:35:18 +00:00
code cleanup, address review comments
This commit is contained in:
parent
00c1a371d2
commit
d03509a17a
@ -6,17 +6,8 @@ import (
|
|||||||
|
|
||||||
// EndBlocker runs at the end of every block.
|
// EndBlocker runs at the end of every block.
|
||||||
func EndBlocker(ctx sdk.Context, k Keeper) {
|
func EndBlocker(ctx sdk.Context, k Keeper) {
|
||||||
|
err := k.CloseExpiredAuctions(ctx)
|
||||||
var expiredAuctions []uint64
|
if err != nil {
|
||||||
k.IterateAuctionsByTime(ctx, ctx.BlockTime(), func(id uint64) bool {
|
panic(err)
|
||||||
expiredAuctions = append(expiredAuctions, id)
|
|
||||||
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 {
|
|
||||||
err := k.CloseAuction(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ func TestKeeper_EndBlocker(t *testing.T) {
|
|||||||
returnAddrs := addrs[1:]
|
returnAddrs := addrs[1:]
|
||||||
returnWeights := []sdk.Int{sdk.NewInt(1)}
|
returnWeights := []sdk.Int{sdk.NewInt(1)}
|
||||||
sellerModName := liquidator.ModuleName
|
sellerModName := liquidator.ModuleName
|
||||||
//sellerAddr := supply.NewModuleAddress(sellerModName)
|
|
||||||
|
|
||||||
tApp := app.NewTestApp()
|
tApp := app.NewTestApp()
|
||||||
sellerAcc := supply.NewEmptyModuleAccount(sellerModName)
|
sellerAcc := supply.NewEmptyModuleAccount(sellerModName)
|
||||||
|
@ -11,15 +11,18 @@ import (
|
|||||||
|
|
||||||
// StartSurplusAuction starts a new surplus (forward) auction.
|
// StartSurplusAuction starts a new surplus (forward) auction.
|
||||||
func (k Keeper) StartSurplusAuction(ctx sdk.Context, seller string, lot sdk.Coin, bidDenom string) (uint64, sdk.Error) {
|
func (k Keeper) StartSurplusAuction(ctx sdk.Context, seller string, lot sdk.Coin, bidDenom string) (uint64, sdk.Error) {
|
||||||
// create auction
|
|
||||||
auction := types.NewSurplusAuction(seller, lot, bidDenom, ctx.BlockTime().Add(types.DefaultMaxAuctionDuration))
|
|
||||||
|
|
||||||
// take coins from module account
|
auction := types.NewSurplusAuction(
|
||||||
|
seller,
|
||||||
|
lot,
|
||||||
|
bidDenom,
|
||||||
|
ctx.BlockTime().Add(k.GetParams(ctx).MaxAuctionDuration))
|
||||||
|
|
||||||
err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, seller, types.ModuleName, sdk.NewCoins(lot))
|
err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, seller, types.ModuleName, sdk.NewCoins(lot))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
// store the auction
|
|
||||||
auctionID, err := k.StoreNewAuction(ctx, auction)
|
auctionID, err := k.StoreNewAuction(ctx, auction)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@ -29,15 +32,19 @@ func (k Keeper) StartSurplusAuction(ctx sdk.Context, seller string, lot sdk.Coin
|
|||||||
|
|
||||||
// StartDebtAuction starts a new debt (reverse) auction.
|
// StartDebtAuction starts a new debt (reverse) auction.
|
||||||
func (k Keeper) StartDebtAuction(ctx sdk.Context, buyer string, bid sdk.Coin, initialLot sdk.Coin) (uint64, sdk.Error) {
|
func (k Keeper) StartDebtAuction(ctx sdk.Context, buyer string, bid sdk.Coin, initialLot sdk.Coin) (uint64, sdk.Error) {
|
||||||
// create auction
|
|
||||||
auction := types.NewDebtAuction(buyer, bid, initialLot, ctx.BlockTime().Add(types.DefaultMaxAuctionDuration))
|
auction := types.NewDebtAuction(
|
||||||
|
buyer,
|
||||||
|
bid,
|
||||||
|
initialLot,
|
||||||
|
ctx.BlockTime().Add(k.GetParams(ctx).MaxAuctionDuration))
|
||||||
|
|
||||||
// This auction type mints coins at close. Need to check module account has minting privileges to avoid potential err in endblocker.
|
// This auction type mints coins at close. Need to check module account has minting privileges to avoid potential err in endblocker.
|
||||||
macc := k.supplyKeeper.GetModuleAccount(ctx, buyer)
|
macc := k.supplyKeeper.GetModuleAccount(ctx, buyer)
|
||||||
if !macc.HasPermission(supply.Minter) {
|
if !macc.HasPermission(supply.Minter) {
|
||||||
return 0, sdk.ErrInternal("module does not have minting permissions")
|
return 0, sdk.ErrInternal("module does not have minting permissions")
|
||||||
}
|
}
|
||||||
// store the auction
|
|
||||||
auctionID, err := k.StoreNewAuction(ctx, auction)
|
auctionID, err := k.StoreNewAuction(ctx, auction)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@ -45,21 +52,20 @@ func (k Keeper) StartDebtAuction(ctx sdk.Context, buyer string, bid sdk.Coin, in
|
|||||||
return auctionID, nil
|
return auctionID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartCollateralAuction starts a new collateral (2-phase) auction where bidders bid up to a maxBid, then switch to bidding down on the Lot.
|
// StartCollateralAuction starts a new collateral (2-phase) auction.
|
||||||
func (k Keeper) StartCollateralAuction(ctx sdk.Context, seller string, lot sdk.Coin, maxBid sdk.Coin, lotReturnAddrs []sdk.AccAddress, lotReturnWeights []sdk.Int) (uint64, sdk.Error) {
|
func (k Keeper) StartCollateralAuction(ctx sdk.Context, seller string, lot sdk.Coin, maxBid sdk.Coin, lotReturnAddrs []sdk.AccAddress, lotReturnWeights []sdk.Int) (uint64, sdk.Error) {
|
||||||
// create auction
|
|
||||||
weightedAddresses, err := types.NewWeightedAddresses(lotReturnAddrs, lotReturnWeights)
|
weightedAddresses, err := types.NewWeightedAddresses(lotReturnAddrs, lotReturnWeights)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
auction := types.NewCollateralAuction(seller, lot, ctx.BlockTime().Add(types.DefaultMaxAuctionDuration), maxBid, weightedAddresses)
|
auction := types.NewCollateralAuction(seller, lot, ctx.BlockTime().Add(types.DefaultMaxAuctionDuration), maxBid, weightedAddresses)
|
||||||
|
|
||||||
// take coins from module account
|
|
||||||
err = k.supplyKeeper.SendCoinsFromModuleToModule(ctx, seller, types.ModuleName, sdk.NewCoins(lot))
|
err = k.supplyKeeper.SendCoinsFromModuleToModule(ctx, seller, types.ModuleName, sdk.NewCoins(lot))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
// store the auction
|
|
||||||
auctionID, err := k.StoreNewAuction(ctx, auction)
|
auctionID, err := k.StoreNewAuction(ctx, auction)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@ -70,18 +76,17 @@ func (k Keeper) StartCollateralAuction(ctx sdk.Context, seller string, lot sdk.C
|
|||||||
// PlaceBid places a bid on any auction.
|
// PlaceBid places a bid on any auction.
|
||||||
func (k Keeper) PlaceBid(ctx sdk.Context, auctionID uint64, bidder sdk.AccAddress, newAmount sdk.Coin) sdk.Error {
|
func (k Keeper) PlaceBid(ctx sdk.Context, auctionID uint64, bidder sdk.AccAddress, newAmount sdk.Coin) sdk.Error {
|
||||||
|
|
||||||
// get auction from store
|
|
||||||
auction, found := k.GetAuction(ctx, auctionID)
|
auction, found := k.GetAuction(ctx, auctionID)
|
||||||
if !found {
|
if !found {
|
||||||
return sdk.ErrInternal("auction doesn't exist")
|
return sdk.ErrInternal("auction doesn't exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate
|
// validation common to all auctions
|
||||||
if ctx.BlockTime().After(auction.GetEndTime()) {
|
if ctx.BlockTime().After(auction.GetEndTime()) {
|
||||||
return sdk.ErrInternal("auction has closed")
|
return sdk.ErrInternal("auction has closed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// place bid
|
// move coins and return updated auction
|
||||||
var err sdk.Error
|
var err sdk.Error
|
||||||
var updatedAuction types.Auction
|
var updatedAuction types.Auction
|
||||||
switch a := auction.(type) {
|
switch a := auction.(type) {
|
||||||
@ -106,14 +111,13 @@ func (k Keeper) PlaceBid(ctx sdk.Context, auctionID uint64, bidder sdk.AccAddres
|
|||||||
panic(fmt.Sprintf("unrecognized auction type: %T", auction))
|
panic(fmt.Sprintf("unrecognized auction type: %T", auction))
|
||||||
}
|
}
|
||||||
|
|
||||||
// store updated auction
|
|
||||||
k.SetAuction(ctx, updatedAuction)
|
k.SetAuction(ctx, updatedAuction)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PlaceBidSurplus places a forward bid on a surplus auction, moving coins and returning the updated auction.
|
// PlaceBidSurplus places a forward bid on a surplus auction, moving coins and returning the updated auction.
|
||||||
func (k Keeper) PlaceBidSurplus(ctx sdk.Context, a types.SurplusAuction, bidder sdk.AccAddress, bid sdk.Coin) (types.SurplusAuction, sdk.Error) {
|
func (k Keeper) PlaceBidSurplus(ctx sdk.Context, a types.SurplusAuction, bidder sdk.AccAddress, bid sdk.Coin) (types.SurplusAuction, sdk.Error) {
|
||||||
// Validate New Bid
|
// Validate new bid
|
||||||
if bid.Denom != a.Bid.Denom {
|
if bid.Denom != a.Bid.Denom {
|
||||||
return a, sdk.ErrInternal("bid denom doesn't match auction")
|
return a, sdk.ErrInternal("bid denom doesn't match auction")
|
||||||
}
|
}
|
||||||
@ -121,9 +125,9 @@ func (k Keeper) PlaceBidSurplus(ctx sdk.Context, a types.SurplusAuction, bidder
|
|||||||
return a, sdk.ErrInternal("bid not greater than last bid")
|
return a, sdk.ErrInternal("bid not greater than last bid")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move Coins
|
// New bidder pays back old bidder
|
||||||
if !bidder.Equals(a.Bidder) && !a.Bid.IsZero() { // catch edge case of someone updating their bid with a low balance, also don't send if amt is zero
|
// Catch edge cases of a bidder replacing their own bid, and the amount being zero (sending zero coins produces meaningless send events).
|
||||||
// pay back previous bidder
|
if !bidder.Equals(a.Bidder) && !a.Bid.IsZero() {
|
||||||
err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, bidder, types.ModuleName, sdk.NewCoins(a.Bid))
|
err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, bidder, types.ModuleName, sdk.NewCoins(a.Bid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return a, err
|
return a, err
|
||||||
@ -133,7 +137,7 @@ func (k Keeper) PlaceBidSurplus(ctx sdk.Context, a types.SurplusAuction, bidder
|
|||||||
return a, err
|
return a, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// burn increase in bid
|
// Increase in bid is burned
|
||||||
err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, bidder, a.Initiator, sdk.NewCoins(bid.Sub(a.Bid)))
|
err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, bidder, a.Initiator, sdk.NewCoins(bid.Sub(a.Bid)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return a, err
|
return a, err
|
||||||
@ -146,8 +150,7 @@ func (k Keeper) PlaceBidSurplus(ctx sdk.Context, a types.SurplusAuction, bidder
|
|||||||
// Update Auction
|
// Update Auction
|
||||||
a.Bidder = bidder
|
a.Bidder = bidder
|
||||||
a.Bid = bid
|
a.Bid = bid
|
||||||
// increment timeout
|
a.EndTime = earliestTime(ctx.BlockTime().Add(k.GetParams(ctx).BidDuration), a.MaxEndTime) // increment timeout
|
||||||
a.EndTime = earliestTime(ctx.BlockTime().Add(types.DefaultBidDuration), a.MaxEndTime)
|
|
||||||
|
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
@ -167,9 +170,10 @@ func (k Keeper) PlaceForwardBidCollateral(ctx sdk.Context, a types.CollateralAuc
|
|||||||
if a.MaxBid.IsLT(bid) {
|
if a.MaxBid.IsLT(bid) {
|
||||||
return a, sdk.ErrInternal("bid higher than max bid")
|
return a, sdk.ErrInternal("bid higher than max bid")
|
||||||
}
|
}
|
||||||
// Move Coins
|
|
||||||
// pay back previous bidder
|
// New bidder pays back old bidder
|
||||||
if !bidder.Equals(a.Bidder) && !a.Bid.IsZero() { // catch edge case of someone updating their bid with a low balance, also don't send if amt is zero
|
// Catch edge cases of a bidder replacing their own bid, and the amount being zero (sending zero coins produces meaningless send events).
|
||||||
|
if !bidder.Equals(a.Bidder) && !a.Bid.IsZero() {
|
||||||
err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, bidder, types.ModuleName, sdk.NewCoins(a.Bid))
|
err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, bidder, types.ModuleName, sdk.NewCoins(a.Bid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return a, err
|
return a, err
|
||||||
@ -179,7 +183,7 @@ func (k Keeper) PlaceForwardBidCollateral(ctx sdk.Context, a types.CollateralAuc
|
|||||||
return a, err
|
return a, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// pay increase in bid to auction initiator
|
// Increase in bid sent to auction initiator
|
||||||
err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, bidder, a.Initiator, sdk.NewCoins(bid.Sub(a.Bid)))
|
err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, bidder, a.Initiator, sdk.NewCoins(bid.Sub(a.Bid)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return a, err
|
return a, err
|
||||||
@ -188,15 +192,14 @@ func (k Keeper) PlaceForwardBidCollateral(ctx sdk.Context, a types.CollateralAuc
|
|||||||
// Update Auction
|
// Update Auction
|
||||||
a.Bidder = bidder
|
a.Bidder = bidder
|
||||||
a.Bid = bid
|
a.Bid = bid
|
||||||
// increment timeout
|
a.EndTime = earliestTime(ctx.BlockTime().Add(k.GetParams(ctx).BidDuration), a.MaxEndTime) // increment timeout
|
||||||
a.EndTime = earliestTime(ctx.BlockTime().Add(types.DefaultBidDuration), a.MaxEndTime)
|
|
||||||
|
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PlaceReverseBidCollateral places a reverse bid on a collateral auction, moving coins and returning the updated auction.
|
// PlaceReverseBidCollateral places a reverse bid on a collateral auction, moving coins and returning the updated auction.
|
||||||
func (k Keeper) PlaceReverseBidCollateral(ctx sdk.Context, a types.CollateralAuction, bidder sdk.AccAddress, lot sdk.Coin) (types.CollateralAuction, sdk.Error) {
|
func (k Keeper) PlaceReverseBidCollateral(ctx sdk.Context, a types.CollateralAuction, bidder sdk.AccAddress, lot sdk.Coin) (types.CollateralAuction, sdk.Error) {
|
||||||
// Validate bid
|
// Validate new bid
|
||||||
if lot.Denom != a.Lot.Denom {
|
if lot.Denom != a.Lot.Denom {
|
||||||
return a, sdk.ErrInternal("lot denom doesn't match auction")
|
return a, sdk.ErrInternal("lot denom doesn't match auction")
|
||||||
}
|
}
|
||||||
@ -210,8 +213,9 @@ func (k Keeper) PlaceReverseBidCollateral(ctx sdk.Context, a types.CollateralAuc
|
|||||||
return a, sdk.ErrInternal("auction in reverse phase, new bid not less than previous amount")
|
return a, sdk.ErrInternal("auction in reverse phase, new bid not less than previous amount")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move Coins
|
// New bidder pays back old bidder
|
||||||
if !bidder.Equals(a.Bidder) { // catch edge case of someone updating their bid with a low balance
|
// Catch edge cases of a bidder replacing their own bid
|
||||||
|
if !bidder.Equals(a.Bidder) {
|
||||||
err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, bidder, types.ModuleName, sdk.NewCoins(a.Bid))
|
err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, bidder, types.ModuleName, sdk.NewCoins(a.Bid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return a, err
|
return a, err
|
||||||
@ -221,7 +225,8 @@ func (k Keeper) PlaceReverseBidCollateral(ctx sdk.Context, a types.CollateralAuc
|
|||||||
return a, err
|
return a, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME paying out rateably to cdp depositors is vulnerable to errors compounding over multiple bids
|
// Decrease in lot is sent to weighted addresses (normally the CDP depositors)
|
||||||
|
// TODO paying out rateably to cdp depositors is vulnerable to errors compounding over multiple bids - check this can't be gamed.
|
||||||
lotPayouts, err := splitCoinIntoWeightedBuckets(a.Lot.Sub(lot), a.LotReturns.Weights)
|
lotPayouts, err := splitCoinIntoWeightedBuckets(a.Lot.Sub(lot), a.LotReturns.Weights)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return a, err
|
return a, err
|
||||||
@ -236,15 +241,14 @@ func (k Keeper) PlaceReverseBidCollateral(ctx sdk.Context, a types.CollateralAuc
|
|||||||
// Update Auction
|
// Update Auction
|
||||||
a.Bidder = bidder
|
a.Bidder = bidder
|
||||||
a.Lot = lot
|
a.Lot = lot
|
||||||
// increment timeout
|
a.EndTime = earliestTime(ctx.BlockTime().Add(k.GetParams(ctx).BidDuration), a.MaxEndTime) // increment timeout
|
||||||
a.EndTime = earliestTime(ctx.BlockTime().Add(types.DefaultBidDuration), a.MaxEndTime)
|
|
||||||
|
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PlaceBidDebt places a reverse bid on a debt auction, moving coins and returning the updated auction.
|
// PlaceBidDebt places a reverse bid on a debt auction, moving coins and returning the updated auction.
|
||||||
func (k Keeper) PlaceBidDebt(ctx sdk.Context, a types.DebtAuction, bidder sdk.AccAddress, lot sdk.Coin) (types.DebtAuction, sdk.Error) {
|
func (k Keeper) PlaceBidDebt(ctx sdk.Context, a types.DebtAuction, bidder sdk.AccAddress, lot sdk.Coin) (types.DebtAuction, sdk.Error) {
|
||||||
// Validate New Bid
|
// Validate new bid
|
||||||
if lot.Denom != a.Lot.Denom {
|
if lot.Denom != a.Lot.Denom {
|
||||||
return a, sdk.ErrInternal("lot denom doesn't match auction")
|
return a, sdk.ErrInternal("lot denom doesn't match auction")
|
||||||
}
|
}
|
||||||
@ -255,8 +259,9 @@ func (k Keeper) PlaceBidDebt(ctx sdk.Context, a types.DebtAuction, bidder sdk.Ac
|
|||||||
return a, sdk.ErrInternal("lot not smaller than last lot")
|
return a, sdk.ErrInternal("lot not smaller than last lot")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move Coins
|
// New bidder pays back old bidder
|
||||||
if !bidder.Equals(a.Bidder) { // catch edge case of someone updating their bid with a low balance
|
// Catch edge cases of a bidder replacing their own bid
|
||||||
|
if !bidder.Equals(a.Bidder) {
|
||||||
err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, bidder, types.ModuleName, sdk.NewCoins(a.Bid))
|
err := k.supplyKeeper.SendCoinsFromAccountToModule(ctx, bidder, types.ModuleName, sdk.NewCoins(a.Bid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return a, err
|
return a, err
|
||||||
@ -270,8 +275,7 @@ func (k Keeper) PlaceBidDebt(ctx sdk.Context, a types.DebtAuction, bidder sdk.Ac
|
|||||||
// Update Auction
|
// Update Auction
|
||||||
a.Bidder = bidder
|
a.Bidder = bidder
|
||||||
a.Lot = lot
|
a.Lot = lot
|
||||||
// increment timeout
|
a.EndTime = earliestTime(ctx.BlockTime().Add(k.GetParams(ctx).BidDuration), a.MaxEndTime) // increment timeout
|
||||||
a.EndTime = earliestTime(ctx.BlockTime().Add(types.DefaultBidDuration), a.MaxEndTime)
|
|
||||||
|
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
@ -279,12 +283,11 @@ func (k Keeper) PlaceBidDebt(ctx sdk.Context, a types.DebtAuction, bidder sdk.Ac
|
|||||||
// 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) sdk.Error {
|
func (k Keeper) CloseAuction(ctx sdk.Context, auctionID uint64) sdk.Error {
|
||||||
|
|
||||||
// get the auction from the store
|
|
||||||
auction, found := k.GetAuction(ctx, auctionID)
|
auction, found := k.GetAuction(ctx, auctionID)
|
||||||
if !found {
|
if !found {
|
||||||
return sdk.ErrInternal("auction doesn't exist")
|
return sdk.ErrInternal("auction doesn't exist")
|
||||||
}
|
}
|
||||||
// error if auction has not reached the end time
|
|
||||||
if ctx.BlockTime().Before(auction.GetEndTime()) {
|
if ctx.BlockTime().Before(auction.GetEndTime()) {
|
||||||
return sdk.ErrInternal(fmt.Sprintf("auction can't be closed as curent block time (%v) is under auction end time (%v)", ctx.BlockTime(), auction.GetEndTime()))
|
return sdk.ErrInternal(fmt.Sprintf("auction can't be closed as curent block time (%v) is under auction end time (%v)", ctx.BlockTime(), auction.GetEndTime()))
|
||||||
}
|
}
|
||||||
@ -342,6 +345,22 @@ func (k Keeper) PayoutCollateralAuction(ctx sdk.Context, a types.CollateralAucti
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloseExpiredAuctions finds all auctions that are past (or at) their ending times and closes them, paying out to the highest bidder.
|
||||||
|
func (k Keeper) CloseExpiredAuctions(ctx sdk.Context) sdk.Error {
|
||||||
|
var expiredAuctions []uint64
|
||||||
|
k.IterateAuctionsByTime(ctx, ctx.BlockTime(), func(id uint64) bool {
|
||||||
|
expiredAuctions = append(expiredAuctions, id)
|
||||||
|
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 {
|
||||||
|
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.
|
||||||
func earliestTime(t1, t2 time.Time) time.Time {
|
func earliestTime(t1, t2 time.Time) time.Time {
|
||||||
if t1.Before(t2) {
|
if t1.Before(t2) {
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
package keeper
|
package keeper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/params/subspace"
|
"github.com/cosmos/cosmos-sdk/x/params/subspace"
|
||||||
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
|
|
||||||
"github.com/kava-labs/kava/x/auction/types"
|
"github.com/kava-labs/kava/x/auction/types"
|
||||||
)
|
)
|
||||||
@ -29,6 +31,11 @@ func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, supplyKeeper types.Suppl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
}
|
||||||
|
|
||||||
// SetNextAuctionID stores an ID to be used for the next created auction
|
// SetNextAuctionID stores an ID to be used for the next created auction
|
||||||
func (k Keeper) SetNextAuctionID(ctx sdk.Context, id uint64) {
|
func (k Keeper) SetNextAuctionID(ctx sdk.Context, id uint64) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
@ -79,16 +86,14 @@ func (k Keeper) SetAuction(ctx sdk.Context, auction types.Auction) {
|
|||||||
// remove the auction from the byTime index if it is already in there
|
// remove the auction from the byTime index if it is already in there
|
||||||
existingAuction, found := k.GetAuction(ctx, auction.GetID())
|
existingAuction, found := k.GetAuction(ctx, auction.GetID())
|
||||||
if found {
|
if found {
|
||||||
k.removeFromIndex(ctx, existingAuction.GetEndTime(), existingAuction.GetID())
|
k.removeFromByTimeIndex(ctx, existingAuction.GetEndTime(), existingAuction.GetID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// store auction
|
|
||||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AuctionKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AuctionKeyPrefix)
|
||||||
bz := k.cdc.MustMarshalBinaryLengthPrefixed(auction)
|
bz := k.cdc.MustMarshalBinaryLengthPrefixed(auction)
|
||||||
store.Set(types.GetAuctionKey(auction.GetID()), bz)
|
store.Set(types.GetAuctionKey(auction.GetID()), bz)
|
||||||
|
|
||||||
// add to index
|
k.InsertIntoByTimeIndex(ctx, auction.GetEndTime(), auction.GetID())
|
||||||
k.insertIntoIndex(ctx, auction.GetEndTime(), auction.GetID())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAuction gets an auction from the store.
|
// GetAuction gets an auction from the store.
|
||||||
@ -107,25 +112,23 @@ func (k Keeper) GetAuction(ctx sdk.Context, auctionID uint64) (types.Auction, bo
|
|||||||
|
|
||||||
// DeleteAuction removes an auction from the store, and any indexes.
|
// DeleteAuction removes an auction from the store, and any indexes.
|
||||||
func (k Keeper) DeleteAuction(ctx sdk.Context, auctionID uint64) {
|
func (k Keeper) DeleteAuction(ctx sdk.Context, auctionID uint64) {
|
||||||
// remove from index
|
|
||||||
auction, found := k.GetAuction(ctx, auctionID)
|
auction, found := k.GetAuction(ctx, auctionID)
|
||||||
if found {
|
if found {
|
||||||
k.removeFromIndex(ctx, auction.GetEndTime(), auctionID)
|
k.removeFromByTimeIndex(ctx, auction.GetEndTime(), auctionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete auction
|
|
||||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AuctionKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AuctionKeyPrefix)
|
||||||
store.Delete(types.GetAuctionKey(auctionID))
|
store.Delete(types.GetAuctionKey(auctionID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertIntoIndex adds an auction ID and end time into the byTime index.
|
// InsertIntoByTimeIndex adds an auction ID and end time into the byTime index.
|
||||||
func (k Keeper) insertIntoIndex(ctx sdk.Context, endTime time.Time, auctionID uint64) {
|
func (k Keeper) InsertIntoByTimeIndex(ctx sdk.Context, endTime time.Time, auctionID uint64) { // TODO make private, and find way to make tests work
|
||||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AuctionByTimeKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AuctionByTimeKeyPrefix)
|
||||||
store.Set(types.GetAuctionByTimeKey(endTime, auctionID), types.Uint64ToBytes(auctionID))
|
store.Set(types.GetAuctionByTimeKey(endTime, auctionID), types.Uint64ToBytes(auctionID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// removeFromIndex removes an auction ID and end time from the byTime index.
|
// removeFromByTimeIndex removes an auction ID and end time from the byTime index.
|
||||||
func (k Keeper) removeFromIndex(ctx sdk.Context, endTime time.Time, auctionID uint64) {
|
func (k Keeper) removeFromByTimeIndex(ctx sdk.Context, endTime time.Time, auctionID uint64) {
|
||||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AuctionByTimeKeyPrefix)
|
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AuctionByTimeKeyPrefix)
|
||||||
store.Delete(types.GetAuctionByTimeKey(endTime, auctionID))
|
store.Delete(types.GetAuctionByTimeKey(endTime, auctionID))
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ func TestIterateAuctionsByTime(t *testing.T) {
|
|||||||
{time.Date(9999, time.January, 1, 0, 0, 0, 0, time.UTC), 0}, // distant future
|
{time.Date(9999, time.January, 1, 0, 0, 0, 0, time.UTC), 0}, // distant future
|
||||||
}
|
}
|
||||||
for _, v := range byTimeIndex {
|
for _, v := range byTimeIndex {
|
||||||
keeper.InsertIntoIndex(ctx, v.endTime, v.auctionID)
|
keeper.InsertIntoByTimeIndex(ctx, v.endTime, v.auctionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// read out values from index up to a cutoff time and check they are as expected
|
// read out values from index up to a cutoff time and check they are as expected
|
||||||
|
@ -46,7 +46,8 @@ func (a BaseAuction) String() string {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SurplusAuction is a forward auction that burns what it receives as bids.
|
// SurplusAuction is a forward auction that burns what it receives from bids.
|
||||||
|
// It is normally used to sell off excess pegged asset acquired by the CDP system.
|
||||||
type SurplusAuction struct {
|
type SurplusAuction struct {
|
||||||
BaseAuction
|
BaseAuction
|
||||||
}
|
}
|
||||||
@ -69,6 +70,7 @@ func NewSurplusAuction(seller string, lot sdk.Coin, bidDenom string, endTime tim
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DebtAuction is a reverse auction that mints what it pays out.
|
// DebtAuction is a reverse auction that mints what it pays out.
|
||||||
|
// It is normally used to acquire pegged asset to cover the CDP system's debts that were not covered by selling collateral.
|
||||||
type DebtAuction struct {
|
type DebtAuction struct {
|
||||||
BaseAuction
|
BaseAuction
|
||||||
}
|
}
|
||||||
@ -86,7 +88,7 @@ func NewDebtAuction(buyerModAccName string, bid sdk.Coin, initialLot sdk.Coin, E
|
|||||||
Initiator: buyerModAccName,
|
Initiator: buyerModAccName,
|
||||||
Lot: initialLot,
|
Lot: initialLot,
|
||||||
Bidder: supply.NewModuleAddress(buyerModAccName), // send proceeds from the first bid to the buyer.
|
Bidder: supply.NewModuleAddress(buyerModAccName), // send proceeds from the first bid to the buyer.
|
||||||
Bid: bid, // amount that the buyer it buying - doesn't change over course of auction
|
Bid: bid, // amount that the buyer is buying - doesn't change over course of auction
|
||||||
EndTime: EndTime,
|
EndTime: EndTime,
|
||||||
MaxEndTime: EndTime,
|
MaxEndTime: EndTime,
|
||||||
}}
|
}}
|
||||||
@ -95,8 +97,9 @@ func NewDebtAuction(buyerModAccName string, bid sdk.Coin, initialLot sdk.Coin, E
|
|||||||
|
|
||||||
// CollateralAuction is a two phase auction.
|
// CollateralAuction is a two phase auction.
|
||||||
// Initially, in forward auction phase, bids can be placed up to a max bid.
|
// Initially, in forward auction phase, bids can be placed up to a max bid.
|
||||||
// Then it switches to a reverse auction phase, where the initial amount up for auction is bidded down.
|
// Then it switches to a reverse auction phase, where the initial amount up for auction is bid down.
|
||||||
// Unsold Lot is sent to LotReturns, being divided among the addresses by weight.
|
// Unsold Lot is sent to LotReturns, being divided among the addresses by weight.
|
||||||
|
// Collateral auctions are normally used to sell off collateral seized from CDPs.
|
||||||
type CollateralAuction struct {
|
type CollateralAuction struct {
|
||||||
BaseAuction
|
BaseAuction
|
||||||
MaxBid sdk.Coin
|
MaxBid sdk.Coin
|
||||||
|
@ -1,396 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
// // TODO can this be less verbose? Should PlaceBid() be split into smaller functions?
|
|
||||||
// // It would be possible to combine all auction tests into one test runner.
|
|
||||||
// func TesSurplusAuction_PlaceBid(t *testing.T) {
|
|
||||||
// seller := sdk.AccAddress([]byte("a_seller"))
|
|
||||||
// buyer1 := sdk.AccAddress([]byte("buyer1"))
|
|
||||||
// buyer2 := sdk.AccAddress([]byte("buyer2"))
|
|
||||||
// end := EndTime(10000)
|
|
||||||
// now := EndTime(10)
|
|
||||||
|
|
||||||
// type args struct {
|
|
||||||
// currentBlockHeight EndTime
|
|
||||||
// bidder sdk.AccAddress
|
|
||||||
// lot sdk.Coin
|
|
||||||
// bid sdk.Coin
|
|
||||||
// }
|
|
||||||
// tests := []struct {
|
|
||||||
// name string
|
|
||||||
// auction SurplusAuction
|
|
||||||
// args args
|
|
||||||
// expectedOutputs []BankOutput
|
|
||||||
// expectedInputs []BankInput
|
|
||||||
// expectedEndTime EndTime
|
|
||||||
// expectedBidder sdk.AccAddress
|
|
||||||
// expectedBid sdk.Coin
|
|
||||||
// expectpass bool
|
|
||||||
// }{
|
|
||||||
// {
|
|
||||||
// "normal",
|
|
||||||
// SurplusAuction{BaseAuction{
|
|
||||||
// Initiator: seller,
|
|
||||||
// Lot: c("usdx", 100),
|
|
||||||
// Bidder: buyer1,
|
|
||||||
// Bid: c("kava", 6),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end,
|
|
||||||
// }},
|
|
||||||
// args{now, buyer2, c("usdx", 100), c("kava", 10)},
|
|
||||||
// []BankOutput{{buyer2, c("kava", 10)}},
|
|
||||||
// []BankInput{{buyer1, c("kava", 6)}, {seller, c("kava", 4)}},
|
|
||||||
// now + DefaultMaxBidDuration,
|
|
||||||
// buyer2,
|
|
||||||
// c("kava", 10),
|
|
||||||
// true,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "lowBid",
|
|
||||||
// SurplusAuction{BaseAuction{
|
|
||||||
// Initiator: seller,
|
|
||||||
// Lot: c("usdx", 100),
|
|
||||||
// Bidder: buyer1,
|
|
||||||
// Bid: c("kava", 6),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end,
|
|
||||||
// }},
|
|
||||||
// args{now, buyer2, c("usdx", 100), c("kava", 5)},
|
|
||||||
// []BankOutput{},
|
|
||||||
// []BankInput{},
|
|
||||||
// end,
|
|
||||||
// buyer1,
|
|
||||||
// c("kava", 6),
|
|
||||||
// false,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "equalBid",
|
|
||||||
// SurplusAuction{BaseAuction{
|
|
||||||
// Initiator: seller,
|
|
||||||
// Lot: c("usdx", 100),
|
|
||||||
// Bidder: buyer1,
|
|
||||||
// Bid: c("kava", 6),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end,
|
|
||||||
// }},
|
|
||||||
// args{now, buyer2, c("usdx", 100), c("kava", 6)},
|
|
||||||
// []BankOutput{},
|
|
||||||
// []BankInput{},
|
|
||||||
// end,
|
|
||||||
// buyer1,
|
|
||||||
// c("kava", 6),
|
|
||||||
// false,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "timeout",
|
|
||||||
// SurplusAuction{BaseAuction{
|
|
||||||
// Initiator: seller,
|
|
||||||
// Lot: c("usdx", 100),
|
|
||||||
// Bidder: buyer1,
|
|
||||||
// Bid: c("kava", 6),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end,
|
|
||||||
// }},
|
|
||||||
// args{end + 1, buyer2, c("usdx", 100), c("kava", 10)},
|
|
||||||
// []BankOutput{},
|
|
||||||
// []BankInput{},
|
|
||||||
// end,
|
|
||||||
// buyer1,
|
|
||||||
// c("kava", 6),
|
|
||||||
// false,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "hitMaxEndTime",
|
|
||||||
// SurplusAuction{BaseAuction{
|
|
||||||
// Initiator: seller,
|
|
||||||
// Lot: c("usdx", 100),
|
|
||||||
// Bidder: buyer1,
|
|
||||||
// Bid: c("kava", 6),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end,
|
|
||||||
// }},
|
|
||||||
// args{end - 1, buyer2, c("usdx", 100), c("kava", 10)},
|
|
||||||
// []BankOutput{{buyer2, c("kava", 10)}},
|
|
||||||
// []BankInput{{buyer1, c("kava", 6)}, {seller, c("kava", 4)}},
|
|
||||||
// end, // end time should be capped at MaxEndTime
|
|
||||||
// buyer2,
|
|
||||||
// c("kava", 10),
|
|
||||||
// true,
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
// for _, tc := range tests {
|
|
||||||
// t.Run(tc.name, func(t *testing.T) {
|
|
||||||
// // update auction and return in/outputs
|
|
||||||
// outputs, inputs, err := tc.auction.PlaceBid(tc.args.currentBlockHeight, tc.args.bidder, tc.args.lot, tc.args.bid)
|
|
||||||
|
|
||||||
// // check for err
|
|
||||||
// if tc.expectpass {
|
|
||||||
// require.Nil(t, err)
|
|
||||||
// } else {
|
|
||||||
// require.NotNil(t, err)
|
|
||||||
// }
|
|
||||||
// // check for correct in/outputs
|
|
||||||
// require.Equal(t, tc.expectedOutputs, outputs)
|
|
||||||
// require.Equal(t, tc.expectedInputs, inputs)
|
|
||||||
// // check for correct EndTime, bidder, bid
|
|
||||||
// require.Equal(t, tc.expectedEndTime, tc.auction.EndTime)
|
|
||||||
// require.Equal(t, tc.expectedBidder, tc.auction.Bidder)
|
|
||||||
// require.Equal(t, tc.expectedBid, tc.auction.Bid)
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestDebtAuction_PlaceBid(t *testing.T) {
|
|
||||||
// buyer := sdk.AccAddress([]byte("a_buyer"))
|
|
||||||
// seller1 := sdk.AccAddress([]byte("seller1"))
|
|
||||||
// seller2 := sdk.AccAddress([]byte("seller2"))
|
|
||||||
// end := EndTime(10000)
|
|
||||||
// now := EndTime(10)
|
|
||||||
|
|
||||||
// type args struct {
|
|
||||||
// currentBlockHeight EndTime
|
|
||||||
// bidder sdk.AccAddress
|
|
||||||
// lot sdk.Coin
|
|
||||||
// bid sdk.Coin
|
|
||||||
// }
|
|
||||||
// tests := []struct {
|
|
||||||
// name string
|
|
||||||
// auction DebtAuction
|
|
||||||
// args args
|
|
||||||
// expectedOutputs []BankOutput
|
|
||||||
// expectedInputs []BankInput
|
|
||||||
// expectedEndTime EndTime
|
|
||||||
// expectedBidder sdk.AccAddress
|
|
||||||
// expectedLot sdk.Coin
|
|
||||||
// expectpass bool
|
|
||||||
// }{
|
|
||||||
// {
|
|
||||||
// "normal",
|
|
||||||
// DebtAuction{BaseAuction{
|
|
||||||
// Initiator: buyer,
|
|
||||||
// Lot: c("kava", 10),
|
|
||||||
// Bidder: seller1,
|
|
||||||
// Bid: c("usdx", 100),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end,
|
|
||||||
// }},
|
|
||||||
// args{now, seller2, c("kava", 9), c("usdx", 100)},
|
|
||||||
// []BankOutput{{seller2, c("usdx", 100)}},
|
|
||||||
// []BankInput{{seller1, c("usdx", 100)}, {buyer, c("kava", 1)}},
|
|
||||||
// now + DefaultMaxBidDuration,
|
|
||||||
// seller2,
|
|
||||||
// c("kava", 9),
|
|
||||||
// true,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "highBid",
|
|
||||||
// DebtAuction{BaseAuction{
|
|
||||||
// Initiator: buyer,
|
|
||||||
// Lot: c("kava", 10),
|
|
||||||
// Bidder: seller1,
|
|
||||||
// Bid: c("usdx", 100),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end,
|
|
||||||
// }},
|
|
||||||
// args{now, seller2, c("kava", 11), c("usdx", 100)},
|
|
||||||
// []BankOutput{},
|
|
||||||
// []BankInput{},
|
|
||||||
// end,
|
|
||||||
// seller1,
|
|
||||||
// c("kava", 10),
|
|
||||||
// false,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "equalBid",
|
|
||||||
// DebtAuction{BaseAuction{
|
|
||||||
// Initiator: buyer,
|
|
||||||
// Lot: c("kava", 10),
|
|
||||||
// Bidder: seller1,
|
|
||||||
// Bid: c("usdx", 100),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end,
|
|
||||||
// }},
|
|
||||||
// args{now, seller2, c("kava", 10), c("usdx", 100)},
|
|
||||||
// []BankOutput{},
|
|
||||||
// []BankInput{},
|
|
||||||
// end,
|
|
||||||
// seller1,
|
|
||||||
// c("kava", 10),
|
|
||||||
// false,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "timeout",
|
|
||||||
// DebtAuction{BaseAuction{
|
|
||||||
// Initiator: buyer,
|
|
||||||
// Lot: c("kava", 10),
|
|
||||||
// Bidder: seller1,
|
|
||||||
// Bid: c("usdx", 100),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end,
|
|
||||||
// }},
|
|
||||||
// args{end + 1, seller2, c("kava", 9), c("usdx", 100)},
|
|
||||||
// []BankOutput{},
|
|
||||||
// []BankInput{},
|
|
||||||
// end,
|
|
||||||
// seller1,
|
|
||||||
// c("kava", 10),
|
|
||||||
// false,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "hitMaxEndTime",
|
|
||||||
// DebtAuction{BaseAuction{
|
|
||||||
// Initiator: buyer,
|
|
||||||
// Lot: c("kava", 10),
|
|
||||||
// Bidder: seller1,
|
|
||||||
// Bid: c("usdx", 100),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end,
|
|
||||||
// }},
|
|
||||||
// args{end - 1, seller2, c("kava", 9), c("usdx", 100)},
|
|
||||||
// []BankOutput{{seller2, c("usdx", 100)}},
|
|
||||||
// []BankInput{{seller1, c("usdx", 100)}, {buyer, c("kava", 1)}},
|
|
||||||
// end, // end time should be capped at MaxEndTime
|
|
||||||
// seller2,
|
|
||||||
// c("kava", 9),
|
|
||||||
// true,
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
// for _, tc := range tests {
|
|
||||||
// t.Run(tc.name, func(t *testing.T) {
|
|
||||||
// // update auction and return in/outputs
|
|
||||||
// outputs, inputs, err := tc.auction.PlaceBid(tc.args.currentBlockHeight, tc.args.bidder, tc.args.lot, tc.args.bid)
|
|
||||||
|
|
||||||
// // check for err
|
|
||||||
// if tc.expectpass {
|
|
||||||
// require.Nil(t, err)
|
|
||||||
// } else {
|
|
||||||
// require.NotNil(t, err)
|
|
||||||
// }
|
|
||||||
// // check for correct in/outputs
|
|
||||||
// require.Equal(t, tc.expectedOutputs, outputs)
|
|
||||||
// require.Equal(t, tc.expectedInputs, inputs)
|
|
||||||
// // check for correct EndTime, bidder, bid
|
|
||||||
// require.Equal(t, tc.expectedEndTime, tc.auction.EndTime)
|
|
||||||
// require.Equal(t, tc.expectedBidder, tc.auction.Bidder)
|
|
||||||
// require.Equal(t, tc.expectedLot, tc.auction.Lot)
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestCollateralAuction_PlaceBid(t *testing.T) {
|
|
||||||
// cdpOwner := sdk.AccAddress([]byte("a_cdp_owner"))
|
|
||||||
// seller := sdk.AccAddress([]byte("a_seller"))
|
|
||||||
// buyer1 := sdk.AccAddress([]byte("buyer1"))
|
|
||||||
// buyer2 := sdk.AccAddress([]byte("buyer2"))
|
|
||||||
// end := EndTime(10000)
|
|
||||||
// now := EndTime(10)
|
|
||||||
|
|
||||||
// type args struct {
|
|
||||||
// currentBlockHeight EndTime
|
|
||||||
// bidder sdk.AccAddress
|
|
||||||
// lot sdk.Coin
|
|
||||||
// bid sdk.Coin
|
|
||||||
// }
|
|
||||||
// tests := []struct {
|
|
||||||
// name string
|
|
||||||
// auction CollateralAuction
|
|
||||||
// args args
|
|
||||||
// expectedOutputs []BankOutput
|
|
||||||
// expectedInputs []BankInput
|
|
||||||
// expectedEndTime EndTime
|
|
||||||
// expectedBidder sdk.AccAddress
|
|
||||||
// expectedLot sdk.Coin
|
|
||||||
// expectedBid sdk.Coin
|
|
||||||
// expectpass bool
|
|
||||||
// }{
|
|
||||||
// {
|
|
||||||
// "normalForwardBid",
|
|
||||||
// CollateralAuction{BaseAuction: BaseAuction{
|
|
||||||
// Initiator: seller,
|
|
||||||
// Lot: c("xrp", 100),
|
|
||||||
// Bidder: buyer1,
|
|
||||||
// Bid: c("usdx", 5),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end},
|
|
||||||
// MaxBid: c("usdx", 10),
|
|
||||||
// OtherPerson: cdpOwner,
|
|
||||||
// },
|
|
||||||
// args{now, buyer2, c("xrp", 100), c("usdx", 6)},
|
|
||||||
// []BankOutput{{buyer2, c("usdx", 6)}},
|
|
||||||
// []BankInput{{buyer1, c("usdx", 5)}, {seller, c("usdx", 1)}},
|
|
||||||
// now + DefaultMaxBidDuration,
|
|
||||||
// buyer2,
|
|
||||||
// c("xrp", 100),
|
|
||||||
// c("usdx", 6),
|
|
||||||
// true,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "normalSwitchOverBid",
|
|
||||||
// CollateralAuction{BaseAuction: BaseAuction{
|
|
||||||
// Initiator: seller,
|
|
||||||
// Lot: c("xrp", 100),
|
|
||||||
// Bidder: buyer1,
|
|
||||||
// Bid: c("usdx", 5),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end},
|
|
||||||
// MaxBid: c("usdx", 10),
|
|
||||||
// OtherPerson: cdpOwner,
|
|
||||||
// },
|
|
||||||
// args{now, buyer2, c("xrp", 99), c("usdx", 10)},
|
|
||||||
// []BankOutput{{buyer2, c("usdx", 10)}},
|
|
||||||
// []BankInput{{buyer1, c("usdx", 5)}, {seller, c("usdx", 5)}, {cdpOwner, c("xrp", 1)}},
|
|
||||||
// now + DefaultMaxBidDuration,
|
|
||||||
// buyer2,
|
|
||||||
// c("xrp", 99),
|
|
||||||
// c("usdx", 10),
|
|
||||||
// true,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "normalDebtBid",
|
|
||||||
// CollateralAuction{BaseAuction: BaseAuction{
|
|
||||||
// Initiator: seller,
|
|
||||||
// Lot: c("xrp", 99),
|
|
||||||
// Bidder: buyer1,
|
|
||||||
// Bid: c("usdx", 10),
|
|
||||||
// EndTime: end,
|
|
||||||
// MaxEndTime: end},
|
|
||||||
// MaxBid: c("usdx", 10),
|
|
||||||
// OtherPerson: cdpOwner,
|
|
||||||
// },
|
|
||||||
// args{now, buyer2, c("xrp", 90), c("usdx", 10)},
|
|
||||||
// []BankOutput{{buyer2, c("usdx", 10)}},
|
|
||||||
// []BankInput{{buyer1, c("usdx", 10)}, {cdpOwner, c("xrp", 9)}},
|
|
||||||
// now + DefaultMaxBidDuration,
|
|
||||||
// buyer2,
|
|
||||||
// c("xrp", 90),
|
|
||||||
// c("usdx", 10),
|
|
||||||
// true,
|
|
||||||
// },
|
|
||||||
// // TODO more test cases
|
|
||||||
// }
|
|
||||||
// for _, tc := range tests {
|
|
||||||
// t.Run(tc.name, func(t *testing.T) {
|
|
||||||
// // update auction and return in/outputs
|
|
||||||
// outputs, inputs, err := tc.auction.PlaceBid(tc.args.currentBlockHeight, tc.args.bidder, tc.args.lot, tc.args.bid)
|
|
||||||
|
|
||||||
// // check for err
|
|
||||||
// if tc.expectpass {
|
|
||||||
// require.Nil(t, err)
|
|
||||||
// } else {
|
|
||||||
// require.NotNil(t, err)
|
|
||||||
// }
|
|
||||||
// // check for correct in/outputs
|
|
||||||
// require.Equal(t, tc.expectedOutputs, outputs)
|
|
||||||
// require.Equal(t, tc.expectedInputs, inputs)
|
|
||||||
// // check for correct EndTime, bidder, bid
|
|
||||||
// require.Equal(t, tc.expectedEndTime, tc.auction.EndTime)
|
|
||||||
// require.Equal(t, tc.expectedBidder, tc.auction.Bidder)
|
|
||||||
// require.Equal(t, tc.expectedLot, tc.auction.Lot)
|
|
||||||
// require.Equal(t, tc.expectedBid, tc.auction.Bid)
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // defined to avoid cluttering test cases with long function name
|
|
||||||
// func c(denom string, amount int64) sdk.Coin {
|
|
||||||
// return sdk.NewInt64Coin(denom, amount)
|
|
||||||
// }
|
|
@ -21,7 +21,6 @@ const (
|
|||||||
DefaultParamspace = ModuleName
|
DefaultParamspace = ModuleName
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO use cont to keep immutability?
|
|
||||||
var (
|
var (
|
||||||
AuctionKeyPrefix = []byte{0x00} // prefix for keys that store auctions
|
AuctionKeyPrefix = []byte{0x00} // prefix for keys that store auctions
|
||||||
AuctionByTimeKeyPrefix = []byte{0x01} // prefix for keys that are part of the auctionsByTime index
|
AuctionByTimeKeyPrefix = []byte{0x01} // prefix for keys that are part of the auctionsByTime index
|
||||||
@ -37,14 +36,14 @@ func GetAuctionByTimeKey(endTime time.Time, auctionID uint64) []byte {
|
|||||||
return append(sdk.FormatTimeBytes(endTime), Uint64ToBytes(auctionID)...)
|
return append(sdk.FormatTimeBytes(endTime), Uint64ToBytes(auctionID)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint64FromBytes converts some fixed length bytes back into a uint64.
|
|
||||||
func Uint64FromBytes(bz []byte) uint64 {
|
|
||||||
return binary.BigEndian.Uint64(bz)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64ToBytes converts a uint64 into fixed length bytes for use in store keys.
|
// Uint64ToBytes converts a uint64 into fixed length bytes for use in store keys.
|
||||||
func Uint64ToBytes(id uint64) []byte {
|
func Uint64ToBytes(id uint64) []byte {
|
||||||
bz := make([]byte, 8)
|
bz := make([]byte, 8)
|
||||||
binary.BigEndian.PutUint64(bz, uint64(id))
|
binary.BigEndian.PutUint64(bz, uint64(id))
|
||||||
return bz
|
return bz
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Uint64FromBytes converts some fixed length bytes back into a uint64.
|
||||||
|
func Uint64FromBytes(bz []byte) uint64 {
|
||||||
|
return binary.BigEndian.Uint64(bz)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user