mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 08:15:19 +00:00
update endblocker test
This commit is contained in:
parent
0d72f47bc2
commit
8a4109ff26
@ -4,40 +4,53 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
|
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/supply"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
"github.com/kava-labs/kava/app"
|
"github.com/kava-labs/kava/app"
|
||||||
"github.com/kava-labs/kava/x/auction"
|
"github.com/kava-labs/kava/x/auction"
|
||||||
|
"github.com/kava-labs/kava/x/liquidator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestKeeper_EndBlocker(t *testing.T) {
|
func TestKeeper_EndBlocker(t *testing.T) {
|
||||||
// Setup
|
// Setup
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(1)
|
_, addrs := app.GeneratePrivKeyAddressPairs(2)
|
||||||
seller := addrs[0]
|
buyer := addrs[0]
|
||||||
|
recipient := addrs[1]
|
||||||
|
sellerModName := liquidator.ModuleName
|
||||||
|
//sellerAddr := supply.NewModuleAddress(sellerModName)
|
||||||
|
|
||||||
tApp := app.NewTestApp()
|
tApp := app.NewTestApp()
|
||||||
|
sellerAcc := supply.NewEmptyModuleAccount(sellerModName)
|
||||||
|
require.NoError(t, sellerAcc.SetCoins(cs(c("token1", 100), c("token2", 100))))
|
||||||
tApp.InitializeFromGenesisStates(
|
tApp.InitializeFromGenesisStates(
|
||||||
app.NewAuthGenState(addrs, []sdk.Coins{cs(c("token1", 100), c("token2", 100))}),
|
NewAuthGenStateFromAccs(authexported.GenesisAccounts{
|
||||||
|
auth.NewBaseAccount(buyer, cs(c("token1", 100), c("token2", 100)), nil, 0, 0),
|
||||||
|
sellerAcc,
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
ctx := tApp.NewContext(true, abci.Header{})
|
ctx := tApp.NewContext(true, abci.Header{})
|
||||||
keeper := tApp.GetAuctionKeeper()
|
keeper := tApp.GetAuctionKeeper()
|
||||||
|
|
||||||
auctionID, err := keeper.StartForwardAuction(ctx, seller, c("token1", 20), c("token2", 0))
|
auctionID, err := keeper.StartForwardReverseAuction(ctx, sellerModName, c("token1", 20), c("token2", 50), recipient)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, keeper.PlaceBid(ctx, auctionID, buyer, c("token2", 30), c("token1", 20)))
|
||||||
|
|
||||||
// Run the endblocker, simulating a block height just before auction expiry
|
// Run the endblocker, simulating a block time 1ns before auction expiry
|
||||||
preExpiryHeight := ctx.BlockHeight() + int64(auction.DefaultMaxAuctionDuration) - 1
|
preExpiryTime := ctx.BlockTime().Add(auction.DefaultBidDuration - 1)
|
||||||
auction.EndBlocker(ctx.WithBlockHeight(preExpiryHeight), keeper)
|
auction.EndBlocker(ctx.WithBlockTime(preExpiryTime), keeper)
|
||||||
|
|
||||||
// Check auction has not been closed yet
|
// Check auction has not been closed yet
|
||||||
_, found := keeper.GetAuction(ctx, auctionID)
|
_, found := keeper.GetAuction(ctx, auctionID)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
|
|
||||||
// Run the endblocker, simulating a block height just after auction expiry
|
// Run the endblocker, simulating a block time equal to auction expiry
|
||||||
expiryHeight := preExpiryHeight + 1
|
expiryTime := ctx.BlockTime().Add(auction.DefaultBidDuration)
|
||||||
auction.EndBlocker(ctx.WithBlockHeight(expiryHeight), keeper)
|
auction.EndBlocker(ctx.WithBlockTime(expiryTime), keeper)
|
||||||
|
|
||||||
// Check auction has been closed
|
// Check auction has been closed
|
||||||
_, found = keeper.GetAuction(ctx, auctionID)
|
_, found = keeper.GetAuction(ctx, auctionID)
|
||||||
@ -46,3 +59,8 @@ func TestKeeper_EndBlocker(t *testing.T) {
|
|||||||
|
|
||||||
func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) }
|
func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) }
|
||||||
func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }
|
func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) }
|
||||||
|
|
||||||
|
func NewAuthGenStateFromAccs(accounts authexported.GenesisAccounts) app.GenesisState {
|
||||||
|
authGenesis := auth.NewGenesisState(auth.DefaultParams(), accounts)
|
||||||
|
return app.GenesisState{auth.ModuleName: auth.ModuleCdc.MustMarshalJSON(authGenesis)}
|
||||||
|
}
|
||||||
|
@ -16,7 +16,7 @@ const (
|
|||||||
RouterKey = types.RouterKey
|
RouterKey = types.RouterKey
|
||||||
DefaultParamspace = types.DefaultParamspace
|
DefaultParamspace = types.DefaultParamspace
|
||||||
DefaultMaxAuctionDuration = types.DefaultMaxAuctionDuration
|
DefaultMaxAuctionDuration = types.DefaultMaxAuctionDuration
|
||||||
DefaultMaxBidDuration = types.DefaultMaxBidDuration
|
DefaultBidDuration = types.DefaultBidDuration
|
||||||
QueryGetAuction = types.QueryGetAuction
|
QueryGetAuction = types.QueryGetAuction
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
/*
|
|
||||||
Package auction is a module for creating generic auctions and allowing users to place bids until a timeout is reached.
|
|
||||||
|
|
||||||
TODO
|
|
||||||
- investigate when exactly auctions close and verify queue/endblocker logic is ok
|
|
||||||
- add more test cases, add stronger validation to user inputs
|
|
||||||
- add minimum bid increment
|
|
||||||
- decided whether to put auction params like default timeouts into the auctions themselves
|
|
||||||
- add docs
|
|
||||||
- Add constants for the module and route names
|
|
||||||
- user facing things like cli, rest, querier, tags
|
|
||||||
- custom error types, codespace
|
|
||||||
*/
|
|
||||||
package auction
|
|
@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/kava-labs/kava/x/auction/types"
|
"github.com/kava-labs/kava/x/auction/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StartForwardAuction starts a normal auction.
|
// StartForwardAuction starts a normal auction that mints the sold coins.
|
||||||
func (k Keeper) StartForwardAuction(ctx sdk.Context, seller string, lot sdk.Coin, bidDenom string) (types.ID, sdk.Error) {
|
func (k Keeper) StartForwardAuction(ctx sdk.Context, seller string, lot sdk.Coin, bidDenom string) (types.ID, sdk.Error) {
|
||||||
// create auction
|
// create auction
|
||||||
auction := types.NewForwardAuction(seller, lot, bidDenom, ctx.BlockTime().Add(types.DefaultMaxAuctionDuration))
|
auction := types.NewForwardAuction(seller, lot, bidDenom, ctx.BlockTime().Add(types.DefaultMaxAuctionDuration))
|
||||||
@ -108,7 +108,12 @@ func (k Keeper) PlaceBid(ctx sdk.Context, auctionID types.ID, bidder sdk.AccAddr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// store updated auction
|
// store updated auction
|
||||||
k.SetAuction(ctx, a) // TODO maybe move into above funcs
|
existing, found := k.GetAuction(ctx, a.GetID())
|
||||||
|
if found {
|
||||||
|
k.RemoveFromQueue(ctx, existing.GetEndTime(), existing.GetID())
|
||||||
|
}
|
||||||
|
k.SetAuction(ctx, a)
|
||||||
|
k.InsertIntoQueue(ctx, a.GetEndTime(), a.GetID())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -149,7 +154,7 @@ func (k Keeper) PlaceBidForward(ctx sdk.Context, a types.ForwardAuction, bidder
|
|||||||
a.Bidder = bidder
|
a.Bidder = bidder
|
||||||
a.Bid = bid
|
a.Bid = bid
|
||||||
// increment timeout
|
// increment timeout
|
||||||
a.EndTime = earliestTime(ctx.BlockTime().Add(types.DefaultMaxBidDuration), a.MaxEndTime) // TODO write a min func for time types
|
a.EndTime = earliestTime(ctx.BlockTime().Add(types.DefaultBidDuration), a.MaxEndTime)
|
||||||
|
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
@ -211,7 +216,7 @@ func (k Keeper) PlaceBidForwardReverse(ctx sdk.Context, a types.ForwardReverseAu
|
|||||||
a.Lot = lot
|
a.Lot = lot
|
||||||
a.Bid = bid
|
a.Bid = bid
|
||||||
// increment timeout
|
// increment timeout
|
||||||
a.EndTime = earliestTime(ctx.BlockTime().Add(types.DefaultMaxBidDuration), a.MaxEndTime)
|
a.EndTime = earliestTime(ctx.BlockTime().Add(types.DefaultBidDuration), a.MaxEndTime)
|
||||||
|
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
@ -245,7 +250,7 @@ func (k Keeper) PlaceBidReverse(ctx sdk.Context, a types.ReverseAuction, bidder
|
|||||||
a.Bidder = bidder
|
a.Bidder = bidder
|
||||||
a.Lot = lot
|
a.Lot = lot
|
||||||
// increment timeout
|
// increment timeout
|
||||||
a.EndTime = earliestTime(ctx.BlockTime().Add(types.DefaultMaxBidDuration), a.MaxEndTime)
|
a.EndTime = earliestTime(ctx.BlockTime().Add(types.DefaultBidDuration), a.MaxEndTime)
|
||||||
|
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
@ -282,6 +287,7 @@ func (k Keeper) CloseAuction(ctx sdk.Context, auctionID types.ID) sdk.Error {
|
|||||||
|
|
||||||
// Delete auction from store (and queue)
|
// Delete auction from store (and queue)
|
||||||
k.DeleteAuction(ctx, auctionID)
|
k.DeleteAuction(ctx, auctionID)
|
||||||
|
k.RemoveFromQueue(ctx, auction.GetEndTime(), auction.GetID())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -297,7 +303,6 @@ func (k Keeper) MintAndPayoutAuctionLot(ctx sdk.Context, a types.ReverseAuction)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (k Keeper) PayoutAuctionLot(ctx sdk.Context, a types.Auction) sdk.Error {
|
func (k Keeper) PayoutAuctionLot(ctx sdk.Context, a types.Auction) sdk.Error {
|
||||||
// TODO this function is responsible for the addition of GetBidder and GetLot to auction interface. Could be split in to two funcs that operate on concrete auction types
|
|
||||||
err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, a.GetBidder(), sdk.NewCoins(a.GetLot()))
|
err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, a.GetBidder(), sdk.NewCoins(a.GetLot()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -48,7 +48,7 @@ func TestForwardAuctionBasic(t *testing.T) {
|
|||||||
tApp.CheckBalance(t, ctx, sellerAddr, cs(c("token1", 80), c("token2", 100)))
|
tApp.CheckBalance(t, ctx, sellerAddr, cs(c("token1", 80), c("token2", 100)))
|
||||||
|
|
||||||
// Close auction at just at auction expiry time
|
// Close auction at just at auction expiry time
|
||||||
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(types.DefaultMaxBidDuration))
|
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(types.DefaultBidDuration))
|
||||||
require.NoError(t, keeper.CloseAuction(ctx, auctionID))
|
require.NoError(t, keeper.CloseAuction(ctx, auctionID))
|
||||||
// Check buyer's coins increased
|
// Check buyer's coins increased
|
||||||
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 120), c("token2", 90)))
|
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 120), c("token2", 90)))
|
||||||
@ -86,7 +86,7 @@ func TestReverseAuctionBasic(t *testing.T) {
|
|||||||
tApp.CheckBalance(t, ctx, buyerAddr, cs(c("token1", 20)))
|
tApp.CheckBalance(t, ctx, buyerAddr, cs(c("token1", 20)))
|
||||||
|
|
||||||
// Close auction at just after auction expiry
|
// Close auction at just after auction expiry
|
||||||
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(types.DefaultMaxBidDuration))
|
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(types.DefaultBidDuration))
|
||||||
require.NoError(t, keeper.CloseAuction(ctx, auctionID))
|
require.NoError(t, keeper.CloseAuction(ctx, auctionID))
|
||||||
// Check seller's coins increased
|
// Check seller's coins increased
|
||||||
tApp.CheckBalance(t, ctx, seller, cs(c("token1", 80), c("token2", 110)))
|
tApp.CheckBalance(t, ctx, seller, cs(c("token1", 80), c("token2", 110)))
|
||||||
@ -138,7 +138,7 @@ func TestForwardReverseAuctionBasic(t *testing.T) {
|
|||||||
tApp.CheckBalance(t, ctx, recipient, cs(c("token1", 105), c("token2", 100)))
|
tApp.CheckBalance(t, ctx, recipient, cs(c("token1", 105), c("token2", 100)))
|
||||||
|
|
||||||
// Close auction at just after auction expiry
|
// Close auction at just after auction expiry
|
||||||
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(types.DefaultMaxBidDuration))
|
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(types.DefaultBidDuration))
|
||||||
require.NoError(t, keeper.CloseAuction(ctx, auctionID))
|
require.NoError(t, keeper.CloseAuction(ctx, auctionID))
|
||||||
// Check buyer's coins increased
|
// Check buyer's coins increased
|
||||||
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 115), c("token2", 50)))
|
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 115), c("token2", 50)))
|
||||||
|
@ -66,6 +66,7 @@ func (k Keeper) storeNewAuction(ctx sdk.Context, auction types.Auction) (types.I
|
|||||||
auction = auction.WithID(newAuctionID)
|
auction = auction.WithID(newAuctionID)
|
||||||
|
|
||||||
k.SetAuction(ctx, auction)
|
k.SetAuction(ctx, auction)
|
||||||
|
k.InsertIntoQueue(ctx, auction.GetEndTime(), auction.GetID())
|
||||||
|
|
||||||
err = k.IncrementNextAuctionID(ctx)
|
err = k.IncrementNextAuctionID(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -94,40 +94,40 @@ func TestIterateAuctionsByTime(t *testing.T) {
|
|||||||
keeper := tApp.GetAuctionKeeper()
|
keeper := tApp.GetAuctionKeeper()
|
||||||
ctx := tApp.NewContext(true, abci.Header{})
|
ctx := tApp.NewContext(true, abci.Header{})
|
||||||
|
|
||||||
// create a list of times
|
// setup byTime index
|
||||||
queue := []struct {
|
byTimeIndex := []struct {
|
||||||
endTime time.Time
|
endTime time.Time
|
||||||
auctionID types.ID
|
auctionID types.ID
|
||||||
}{
|
}{
|
||||||
{time.Date(84, time.January, 1, 0, 0, 0, 0, time.UTC), 34345345},
|
{time.Date(0, time.January, 1, 0, 0, 0, 0, time.UTC), 9999}, // distant past
|
||||||
{time.Date(98, time.January, 2, 0, 0, 0, 0, time.UTC), 5},
|
{time.Date(1998, time.January, 1, 11, 59, 59, 999999999, time.UTC), 1}, // just before cutoff
|
||||||
{time.Date(98, time.January, 2, 13, 5, 0, 0, time.UTC), 6},
|
{time.Date(1998, time.January, 1, 11, 59, 59, 999999999, time.UTC), 2}, //
|
||||||
{time.Date(98, time.January, 2, 16, 0, 0, 0, time.UTC), 1},
|
{time.Date(1998, time.January, 1, 12, 0, 0, 0, time.UTC), 3}, // equal to cutoff
|
||||||
{time.Date(98, time.January, 2, 16, 0, 0, 0, time.UTC), 3},
|
{time.Date(1998, time.January, 1, 12, 0, 0, 0, time.UTC), 4}, //
|
||||||
{time.Date(98, time.January, 2, 16, 0, 0, 0, time.UTC), 4},
|
{time.Date(1998, time.January, 1, 12, 0, 0, 1, time.UTC), 5}, // just after cutoff
|
||||||
{time.Date(98, time.January, 2, 16, 0, 0, 1, time.UTC), 0}, // TODO tidy up redundant entries
|
{time.Date(1998, time.January, 1, 12, 0, 0, 1, time.UTC), 6}, //
|
||||||
|
{time.Date(9999, time.January, 1, 0, 0, 0, 0, time.UTC), 0}, // distant future
|
||||||
}
|
}
|
||||||
cutoffTime := time.Date(98, time.January, 2, 16, 0, 0, 0, time.UTC)
|
for _, v := range byTimeIndex {
|
||||||
|
|
||||||
var expectedQueue []types.ID
|
|
||||||
for _, i := range queue {
|
|
||||||
if i.endTime.After(cutoffTime) { // only append items where endTime ≤ cutoffTime
|
|
||||||
break
|
|
||||||
}
|
|
||||||
expectedQueue = append(expectedQueue, i.auctionID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// write and read queue
|
|
||||||
for _, v := range queue {
|
|
||||||
keeper.InsertIntoQueue(ctx, v.endTime, v.auctionID)
|
keeper.InsertIntoQueue(ctx, v.endTime, v.auctionID)
|
||||||
}
|
}
|
||||||
var readQueue []types.ID
|
|
||||||
|
// read out values from index up to a cutoff time and check they are as expected
|
||||||
|
cutoffTime := time.Date(1998, time.January, 1, 12, 0, 0, 0, time.UTC)
|
||||||
|
var expectedIndex []types.ID
|
||||||
|
for _, v := range byTimeIndex {
|
||||||
|
if v.endTime.Before(cutoffTime) || v.endTime.Equal(cutoffTime) { // endTime ≤ cutoffTime
|
||||||
|
expectedIndex = append(expectedIndex, v.auctionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
var readIndex []types.ID
|
||||||
keeper.IterateAuctionsByTime(ctx, cutoffTime, func(id types.ID) bool {
|
keeper.IterateAuctionsByTime(ctx, cutoffTime, func(id types.ID) bool {
|
||||||
readQueue = append(readQueue, id)
|
readIndex = append(readIndex, id)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
require.Equal(t, expectedQueue, readQueue)
|
require.Equal(t, expectedIndex, readIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertIteratorToSlice(keeper keeper.Keeper, iterator sdk.Iterator) []types.ID {
|
func convertIteratorToSlice(keeper keeper.Keeper, iterator sdk.Iterator) []types.ID {
|
||||||
|
@ -13,7 +13,7 @@ const (
|
|||||||
// DefaultMaxAuctionDuration max length of auction
|
// DefaultMaxAuctionDuration max length of auction
|
||||||
DefaultMaxAuctionDuration time.Duration = 2 * 24 * time.Hour
|
DefaultMaxAuctionDuration time.Duration = 2 * 24 * time.Hour
|
||||||
// DefaultBidDuration how long an auction gets extended when someone bids, roughly 3 hours in blocks
|
// DefaultBidDuration how long an auction gets extended when someone bids, roughly 3 hours in blocks
|
||||||
DefaultMaxBidDuration time.Duration = 3 * time.Hour
|
DefaultBidDuration time.Duration = 3 * time.Hour
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parameter keys
|
// Parameter keys
|
||||||
@ -43,7 +43,7 @@ func NewAuctionParams(maxAuctionDuration time.Duration, bidDuration time.Duratio
|
|||||||
func DefaultAuctionParams() AuctionParams {
|
func DefaultAuctionParams() AuctionParams {
|
||||||
return NewAuctionParams(
|
return NewAuctionParams(
|
||||||
DefaultMaxAuctionDuration,
|
DefaultMaxAuctionDuration,
|
||||||
DefaultMaxBidDuration,
|
DefaultBidDuration,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user