2020-01-14 15:04:47 +00:00
package keeper_test
import (
"strings"
"testing"
"time"
2020-04-30 14:23:41 +00:00
"github.com/stretchr/testify/require"
2020-01-14 15:04:47 +00:00
sdk "github.com/cosmos/cosmos-sdk/types"
2022-01-08 00:39:27 +00:00
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
2020-01-14 15:04:47 +00:00
"github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/x/auction/types"
)
type AuctionType int
const (
2020-02-28 22:16:22 +00:00
Invalid AuctionType = 0
Surplus AuctionType = 1
Debt AuctionType = 2
Collateral AuctionType = 3
2020-01-14 15:04:47 +00:00
)
func TestAuctionBidding ( t * testing . T ) {
2022-01-08 00:39:27 +00:00
config := sdk . GetConfig ( )
app . SetBech32AddressPrefixes ( config )
2020-01-14 15:04:47 +00:00
someTime := time . Date ( 0001 , time . January , 1 , 0 , 0 , 0 , 0 , time . UTC )
_ , addrs := app . GeneratePrivKeyAddressPairs ( 5 )
buyer := addrs [ 0 ]
secondBuyer := addrs [ 1 ]
modName := "liquidator"
collateralAddrs := addrs [ 2 : ]
collateralWeights := is ( 30 , 20 , 10 )
2022-02-08 16:42:00 +00:00
initialBalance := cs ( c ( "token1" , 1000 ) , c ( "token2" , 1000 ) )
2020-01-14 15:04:47 +00:00
type auctionArgs struct {
auctionType AuctionType
seller string
lot sdk . Coin
bid sdk . Coin
debt sdk . Coin
addresses [ ] sdk . AccAddress
weights [ ] sdk . Int
}
type bidArgs struct {
2020-02-28 22:16:22 +00:00
bidder sdk . AccAddress
amount sdk . Coin
2020-01-14 15:04:47 +00:00
}
tests := [ ] struct {
name string
auctionArgs auctionArgs
2020-02-28 22:16:22 +00:00
setupBids [ ] bidArgs
2020-01-14 15:04:47 +00:00
bidArgs bidArgs
2020-04-23 16:35:58 +00:00
expectedError error
2020-01-14 15:04:47 +00:00
expectedEndTime time . Time
expectedBidder sdk . AccAddress
expectedBid sdk . Coin
2020-04-23 16:35:58 +00:00
expectPass bool
expectPanic bool
2020-01-14 15:04:47 +00:00
} {
{
"basic: auction doesn't exist" ,
auctionArgs { Surplus , "" , c ( "token1" , 1 ) , c ( "token2" , 1 ) , sdk . Coin { } , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } ,
2020-02-28 22:16:22 +00:00
nil ,
bidArgs { buyer , c ( "token2" , 10 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrAuctionNotFound ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultForwardBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
c ( "token2" , 10 ) ,
false ,
2020-04-23 16:35:58 +00:00
true ,
2020-01-14 15:04:47 +00:00
} ,
2020-02-28 22:16:22 +00:00
{
"basic: closed auction" ,
auctionArgs { Surplus , modName , c ( "token1" , 100 ) , c ( "token2" , 10 ) , sdk . Coin { } , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } ,
nil ,
bidArgs { buyer , c ( "token2" , 10 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrAuctionHasExpired ,
2020-02-28 22:16:22 +00:00
types . DistantFuture ,
nil ,
c ( "token2" , 0 ) ,
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-02-28 22:16:22 +00:00
} ,
2020-01-14 15:04:47 +00:00
{
2022-01-08 00:39:27 +00:00
// This is the first bid on an auction with NO bids
2020-01-14 15:04:47 +00:00
"surplus: normal" ,
auctionArgs { Surplus , modName , c ( "token1" , 100 ) , c ( "token2" , 10 ) , sdk . Coin { } , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } ,
2020-02-28 22:16:22 +00:00
nil ,
bidArgs { buyer , c ( "token2" , 10 ) } ,
2020-04-23 16:35:58 +00:00
nil ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultForwardBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
c ( "token2" , 10 ) ,
true ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
"surplus: second bidder" ,
auctionArgs { Surplus , modName , c ( "token1" , 100 ) , c ( "token2" , 10 ) , sdk . Coin { } , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } ,
2020-02-28 22:16:22 +00:00
[ ] bidArgs { { buyer , c ( "token2" , 10 ) } } ,
bidArgs { secondBuyer , c ( "token2" , 11 ) } ,
2020-04-23 16:35:58 +00:00
nil ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultForwardBidDuration ) ,
2020-01-14 15:04:47 +00:00
secondBuyer ,
c ( "token2" , 11 ) ,
true ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
"surplus: invalid bid denom" ,
auctionArgs { Surplus , modName , c ( "token1" , 100 ) , c ( "token2" , 10 ) , sdk . Coin { } , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } ,
2020-02-28 22:16:22 +00:00
nil ,
bidArgs { buyer , c ( "badtoken" , 10 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrInvalidBidDenom ,
2020-02-28 22:16:22 +00:00
types . DistantFuture ,
nil , // surplus auctions are created with initial bidder as a nil address
c ( "token2" , 0 ) ,
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-02-28 22:16:22 +00:00
} ,
{
"surplus: invalid bid (less than)" ,
auctionArgs { Surplus , modName , c ( "token1" , 100 ) , c ( "token2" , 0 ) , sdk . Coin { } , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } ,
[ ] bidArgs { { buyer , c ( "token2" , 100 ) } } ,
bidArgs { buyer , c ( "token2" , 99 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrBidTooSmall ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultForwardBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
2020-02-28 22:16:22 +00:00
c ( "token2" , 100 ) ,
2020-01-14 15:04:47 +00:00
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
"surplus: invalid bid (equal)" ,
auctionArgs { Surplus , modName , c ( "token1" , 100 ) , c ( "token2" , 0 ) , sdk . Coin { } , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } ,
2020-02-28 22:16:22 +00:00
nil ,
bidArgs { buyer , c ( "token2" , 0 ) } , // min bid is technically 0 at default 5%, but it's capped at 1
2020-04-23 16:35:58 +00:00
types . ErrBidTooSmall ,
2020-02-28 22:16:22 +00:00
types . DistantFuture ,
nil , // surplus auctions are created with initial bidder as a nil address
c ( "token2" , 0 ) ,
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-02-28 22:16:22 +00:00
} ,
{
"surplus: invalid bid (less than min increment)" ,
auctionArgs { Surplus , modName , c ( "token1" , 100 ) , c ( "token2" , 0 ) , sdk . Coin { } , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } ,
[ ] bidArgs { { buyer , c ( "token2" , 100 ) } } ,
bidArgs { buyer , c ( "token2" , 104 ) } , // min bid is 105 at default 5%
2020-04-23 16:35:58 +00:00
types . ErrBidTooSmall ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultForwardBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
2020-02-28 22:16:22 +00:00
c ( "token2" , 100 ) ,
2020-01-14 15:04:47 +00:00
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
"debt: normal" ,
2020-02-28 22:16:22 +00:00
auctionArgs { Debt , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 100 ) , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } , // initial bid, lot
nil ,
bidArgs { buyer , c ( "token1" , 10 ) } ,
2020-04-23 16:35:58 +00:00
nil ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultForwardBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
c ( "token2" , 100 ) ,
true ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
"debt: second bidder" ,
2020-02-28 22:16:22 +00:00
auctionArgs { Debt , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 100 ) , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } , // initial bid, lot
[ ] bidArgs { { buyer , c ( "token1" , 10 ) } } ,
bidArgs { secondBuyer , c ( "token1" , 9 ) } ,
2020-04-23 16:35:58 +00:00
nil ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultForwardBidDuration ) ,
2020-01-14 15:04:47 +00:00
secondBuyer ,
c ( "token2" , 100 ) ,
true ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
"debt: invalid lot denom" ,
2020-02-28 22:16:22 +00:00
auctionArgs { Debt , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 100 ) , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } , // initial bid, lot
nil ,
bidArgs { buyer , c ( "badtoken" , 10 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrInvalidLotDenom ,
2020-02-28 22:16:22 +00:00
types . DistantFuture ,
2022-01-08 00:39:27 +00:00
authtypes . NewModuleAddress ( modName ) ,
2020-02-28 22:16:22 +00:00
c ( "token2" , 100 ) ,
2020-01-14 15:04:47 +00:00
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
"debt: invalid lot size (larger)" ,
2020-02-28 22:16:22 +00:00
auctionArgs { Debt , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 100 ) , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } ,
nil ,
bidArgs { buyer , c ( "token1" , 21 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrLotTooLarge ,
2020-02-28 22:16:22 +00:00
types . DistantFuture ,
2022-01-08 00:39:27 +00:00
authtypes . NewModuleAddress ( modName ) ,
2020-02-28 22:16:22 +00:00
c ( "token2" , 100 ) ,
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-02-28 22:16:22 +00:00
} ,
{
"debt: invalid lot size (equal)" ,
auctionArgs { Debt , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 100 ) , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } ,
nil ,
bidArgs { buyer , c ( "token1" , 20 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrLotTooLarge ,
2020-02-28 22:16:22 +00:00
types . DistantFuture ,
2022-01-08 00:39:27 +00:00
authtypes . NewModuleAddress ( modName ) ,
2020-02-28 22:16:22 +00:00
c ( "token2" , 100 ) ,
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-02-28 22:16:22 +00:00
} ,
{
"debt: invalid lot size (larger than min increment)" ,
auctionArgs { Debt , modName , c ( "token1" , 60 ) , c ( "token2" , 100 ) , c ( "debt" , 100 ) , [ ] sdk . AccAddress { } , [ ] sdk . Int { } } ,
nil ,
bidArgs { buyer , c ( "token1" , 58 ) } , // max lot at default 5% is 57
2020-04-23 16:35:58 +00:00
types . ErrLotTooLarge ,
2020-02-28 22:16:22 +00:00
types . DistantFuture ,
2022-01-08 00:39:27 +00:00
authtypes . NewModuleAddress ( modName ) ,
2020-02-28 22:16:22 +00:00
c ( "token2" , 100 ) ,
2020-04-23 16:35:58 +00:00
false , false ,
2020-01-14 15:04:47 +00:00
} ,
{
"collateral [forward]: normal" ,
2020-02-28 22:16:22 +00:00
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
nil ,
bidArgs { buyer , c ( "token2" , 10 ) } ,
2020-04-23 16:35:58 +00:00
nil ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultForwardBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
c ( "token2" , 10 ) ,
true ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
"collateral [forward]: second bidder" ,
2020-02-28 22:16:22 +00:00
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 10 ) } } ,
bidArgs { secondBuyer , c ( "token2" , 11 ) } ,
2020-04-23 16:35:58 +00:00
nil ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultForwardBidDuration ) ,
2020-01-14 15:04:47 +00:00
secondBuyer ,
c ( "token2" , 11 ) ,
true ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
2022-02-08 17:03:47 +00:00
{
"collateral [forward]: convert to reverse (reach maxBid)" ,
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 10 ) } } ,
bidArgs { secondBuyer , c ( "token2" , 100 ) } ,
nil ,
someTime . Add ( types . DefaultReverseBidDuration ) ,
secondBuyer ,
c ( "token2" , 100 ) ,
true ,
false ,
} ,
2020-01-14 15:04:47 +00:00
{
"collateral [forward]: invalid bid denom" ,
2020-02-28 22:16:22 +00:00
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
nil ,
bidArgs { buyer , c ( "badtoken" , 10 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrInvalidBidDenom ,
2020-02-28 22:16:22 +00:00
types . DistantFuture ,
nil ,
c ( "token2" , 0 ) ,
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-02-28 22:16:22 +00:00
} ,
{
"collateral [forward]: invalid bid size (smaller)" ,
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 10 ) } } ,
bidArgs { buyer , c ( "token2" , 9 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrBidTooSmall ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultForwardBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
c ( "token2" , 10 ) ,
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
2020-02-28 22:16:22 +00:00
"collateral [forward]: invalid bid size (equal)" ,
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
nil ,
bidArgs { buyer , c ( "token2" , 0 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrBidTooSmall ,
2020-02-28 22:16:22 +00:00
types . DistantFuture ,
nil ,
c ( "token2" , 0 ) ,
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-02-28 22:16:22 +00:00
} ,
{
"collateral [forward]: invalid bid size (less than min increment)" ,
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 50 ) } } ,
bidArgs { buyer , c ( "token2" , 51 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrBidTooSmall ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultForwardBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
2020-02-28 22:16:22 +00:00
c ( "token2" , 50 ) ,
2020-01-14 15:04:47 +00:00
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
2020-02-28 22:16:22 +00:00
"collateral [forward]: less than min increment but equal to maxBid" ,
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 99 ) } } ,
bidArgs { buyer , c ( "token2" , 100 ) } , // min bid at default 5% is 104
2020-04-23 16:35:58 +00:00
nil ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultReverseBidDuration ) , // Converts to a reverse bid when max reached
2020-01-14 15:04:47 +00:00
buyer ,
2020-02-28 22:16:22 +00:00
c ( "token2" , 100 ) ,
true ,
2020-04-23 16:35:58 +00:00
false ,
2020-02-28 22:16:22 +00:00
} ,
{
"collateral [forward]: invalid bid size (greater than max)" ,
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 100 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
nil ,
bidArgs { buyer , c ( "token2" , 101 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrBidTooLarge ,
2020-02-28 22:16:22 +00:00
types . DistantFuture ,
nil ,
c ( "token2" , 0 ) ,
2020-01-14 15:04:47 +00:00
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
2022-02-08 16:42:00 +00:00
{
"collateral [forward]: bidder replaces previous bid with only funds for difference" ,
auctionArgs { Collateral , modName , c ( "token1" , 1000 ) , c ( "token2" , 2000 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 900 ) } } ,
bidArgs { buyer , c ( "token2" , 1000 ) } , // buyer only has enough to cover the increase from previous bid
nil ,
2022-02-08 17:33:42 +00:00
someTime . Add ( types . DefaultForwardBidDuration ) ,
2022-02-08 16:42:00 +00:00
buyer ,
c ( "token2" , 1000 ) ,
true ,
false ,
} ,
2020-01-14 15:04:47 +00:00
{
"collateral [reverse]: normal" ,
2020-02-28 22:16:22 +00:00
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 50 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 50 ) } } , // put auction into reverse phase
bidArgs { buyer , c ( "token1" , 15 ) } ,
2020-04-23 16:35:58 +00:00
nil ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultReverseBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
c ( "token2" , 50 ) ,
true ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
"collateral [reverse]: second bidder" ,
2020-02-28 22:16:22 +00:00
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 50 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 50 ) } , { buyer , c ( "token1" , 15 ) } } , // put auction into reverse phase, and add a reverse phase bid
bidArgs { secondBuyer , c ( "token1" , 14 ) } ,
2020-04-23 16:35:58 +00:00
nil ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultReverseBidDuration ) ,
2020-01-14 15:04:47 +00:00
secondBuyer ,
c ( "token2" , 50 ) ,
true ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
"collateral [reverse]: invalid lot denom" ,
2020-02-28 22:16:22 +00:00
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 50 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 50 ) } } , // put auction into reverse phase
bidArgs { buyer , c ( "badtoken" , 15 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrInvalidLotDenom ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultReverseBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
c ( "token2" , 50 ) ,
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
2020-02-28 22:16:22 +00:00
"collateral [reverse]: invalid lot size (greater)" ,
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 50 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 50 ) } } , // put auction into reverse phase
bidArgs { buyer , c ( "token1" , 21 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrLotTooLarge ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultReverseBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
c ( "token2" , 50 ) ,
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
2020-02-28 22:16:22 +00:00
"collateral [reverse]: invalid lot size (equal)" ,
auctionArgs { Collateral , modName , c ( "token1" , 20 ) , c ( "token2" , 50 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 50 ) } } , // put auction into reverse phase
bidArgs { buyer , c ( "token1" , 20 ) } ,
2020-04-23 16:35:58 +00:00
types . ErrLotTooLarge ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultReverseBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
c ( "token2" , 50 ) ,
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
{
2020-02-28 22:16:22 +00:00
"collateral [reverse]: invalid lot size (larger than min increment)" ,
auctionArgs { Collateral , modName , c ( "token1" , 60 ) , c ( "token2" , 50 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 50 ) } } , // put auction into reverse phase
bidArgs { buyer , c ( "token1" , 58 ) } , // max lot at default 5% is 57
2020-04-23 16:35:58 +00:00
types . ErrLotTooLarge ,
2022-02-08 17:03:47 +00:00
someTime . Add ( types . DefaultReverseBidDuration ) ,
2020-01-14 15:04:47 +00:00
buyer ,
2020-02-28 22:16:22 +00:00
c ( "token2" , 50 ) ,
2020-01-14 15:04:47 +00:00
false ,
2020-04-23 16:35:58 +00:00
false ,
2020-01-14 15:04:47 +00:00
} ,
2022-02-08 16:42:00 +00:00
{
"collateral [reverse]: bidder replaces previous bid without funds" ,
auctionArgs { Collateral , modName , c ( "token1" , 1000 ) , c ( "token2" , 1000 ) , c ( "debt" , 50 ) , collateralAddrs , collateralWeights } , // lot, max bid
[ ] bidArgs { { buyer , c ( "token2" , 1000 ) } } ,
bidArgs { buyer , c ( "token1" , 100 ) } , // buyer has already bid all of their token2
nil ,
2022-02-08 17:33:42 +00:00
someTime . Add ( types . DefaultReverseBidDuration ) ,
2022-02-08 16:42:00 +00:00
buyer ,
c ( "token2" , 1000 ) ,
true ,
false ,
} ,
2020-01-14 15:04:47 +00:00
}
for _ , tc := range tests {
t . Run ( tc . name , func ( t * testing . T ) {
2020-01-21 10:06:07 +00:00
// Setup test
tApp := app . NewTestApp ( )
2022-01-08 00:39:27 +00:00
// Set up module account
modName := "liquidator"
modBaseAcc := authtypes . NewBaseAccount ( authtypes . NewModuleAddress ( modName ) , nil , 0 , 0 )
modAcc := authtypes . NewModuleAccount ( modBaseAcc , modName , [ ] string { authtypes . Minter , authtypes . Burner } ... )
// Set up normal accounts
addrs := [ ] sdk . AccAddress { buyer , secondBuyer , collateralAddrs [ 0 ] , collateralAddrs [ 1 ] , collateralAddrs [ 2 ] }
// Initialize app
2022-02-08 16:42:00 +00:00
authGS := app . NewFundedGenStateWithSameCoinsWithModuleAccount ( tApp . AppCodec ( ) , initialBalance , addrs , modAcc )
2022-01-08 00:39:27 +00:00
params := types . NewParams (
types . DefaultMaxAuctionDuration ,
2022-02-08 17:03:47 +00:00
types . DefaultForwardBidDuration ,
types . DefaultReverseBidDuration ,
2022-01-08 00:39:27 +00:00
types . DefaultIncrement ,
types . DefaultIncrement ,
types . DefaultIncrement ,
2020-01-21 10:06:07 +00:00
)
2022-01-08 00:39:27 +00:00
auctionGs , err := types . NewGenesisState ( types . DefaultNextAuctionID , params , [ ] types . GenesisAuction { } )
require . NoError ( t , err )
moduleGs := tApp . AppCodec ( ) . MustMarshalJSON ( auctionGs )
gs := app . GenesisState { types . ModuleName : moduleGs }
tApp . InitializeFromGenesisStates ( authGS , gs )
ctx := tApp . NewContext ( true , tmproto . Header { Height : 1 , Time : someTime } )
2020-01-21 10:06:07 +00:00
keeper := tApp . GetAuctionKeeper ( )
2020-02-28 22:16:22 +00:00
bank := tApp . GetBankKeeper ( )
2020-01-21 10:06:07 +00:00
2022-01-08 00:39:27 +00:00
err = tApp . FundModuleAccount ( ctx , modName , cs ( c ( "token1" , 1000 ) , c ( "token2" , 1000 ) , c ( "debt" , 1000 ) ) )
require . NoError ( t , err )
2020-01-14 15:04:47 +00:00
// Start Auction
var id uint64
switch tc . auctionArgs . auctionType {
case Surplus :
2020-04-23 16:35:58 +00:00
if tc . expectPanic {
require . Panics ( t , func ( ) {
id , err = keeper . StartSurplusAuction ( ctx , tc . auctionArgs . seller , tc . auctionArgs . lot , tc . auctionArgs . bid . Denom )
} )
} else {
id , err = keeper . StartSurplusAuction ( ctx , tc . auctionArgs . seller , tc . auctionArgs . lot , tc . auctionArgs . bid . Denom )
}
2020-01-14 15:04:47 +00:00
case Debt :
2020-04-23 16:35:58 +00:00
id , err = keeper . StartDebtAuction ( ctx , tc . auctionArgs . seller , tc . auctionArgs . bid , tc . auctionArgs . lot , tc . auctionArgs . debt )
2020-02-28 22:16:22 +00:00
case Collateral :
2020-04-23 16:35:58 +00:00
id , err = keeper . StartCollateralAuction ( ctx , tc . auctionArgs . seller , tc . auctionArgs . lot , tc . auctionArgs . bid , tc . auctionArgs . addresses , tc . auctionArgs . weights , tc . auctionArgs . debt ) // seller, lot, maxBid, otherPerson
2020-01-14 15:04:47 +00:00
default :
t . Fail ( )
}
2020-04-23 16:35:58 +00:00
require . NoError ( t , err )
2020-02-28 22:16:22 +00:00
// Place setup bids
for _ , b := range tc . setupBids {
require . NoError ( t , keeper . PlaceBid ( ctx , id , b . bidder , b . amount ) )
}
2020-01-14 15:04:47 +00:00
// Close the auction early to test late bidding (if applicable)
if strings . Contains ( tc . name , "closed" ) {
ctx = ctx . WithBlockTime ( types . DistantFuture . Add ( 1 ) )
}
2020-02-28 22:16:22 +00:00
// Store some state for use in checks
oldAuction , found := keeper . GetAuction ( ctx , id )
var oldBidder sdk . AccAddress
if found {
oldBidder = oldAuction . GetBidder ( )
}
2022-01-08 00:39:27 +00:00
oldBidderOldCoins := bank . GetAllBalances ( ctx , oldBidder )
newBidderOldCoins := bank . GetAllBalances ( ctx , tc . bidArgs . bidder )
2020-02-28 22:16:22 +00:00
2020-01-14 15:04:47 +00:00
// Place bid on auction
err = keeper . PlaceBid ( ctx , id , tc . bidArgs . bidder , tc . bidArgs . amount )
// Check success/failure
2020-04-23 16:35:58 +00:00
if tc . expectPass {
2022-02-08 16:42:00 +00:00
require . NoError ( t , err )
2020-02-28 22:16:22 +00:00
// Check auction was found
newAuction , found := keeper . GetAuction ( ctx , id )
2020-01-14 15:04:47 +00:00
require . True ( t , found )
// Check auction values
2020-02-28 22:16:22 +00:00
require . Equal ( t , modName , newAuction . GetInitiator ( ) )
require . Equal ( t , tc . expectedBidder , newAuction . GetBidder ( ) )
require . Equal ( t , tc . expectedBid , newAuction . GetBid ( ) )
require . Equal ( t , tc . expectedEndTime , newAuction . GetEndTime ( ) )
// Check coins have moved between bidder and previous bidder
bidAmt := tc . bidArgs . amount
switch tc . auctionArgs . auctionType {
case Debt :
bidAmt = oldAuction . GetBid ( )
case Collateral :
2022-01-08 00:39:27 +00:00
collatAuction , ok := oldAuction . ( * types . CollateralAuction )
2020-04-23 16:35:58 +00:00
require . True ( t , ok , tc . name )
2020-02-28 22:16:22 +00:00
if collatAuction . IsReversePhase ( ) {
bidAmt = oldAuction . GetBid ( )
}
}
if oldBidder . Equals ( tc . bidArgs . bidder ) { // same bidder
2022-01-08 00:39:27 +00:00
require . Equal ( t , newBidderOldCoins . Sub ( cs ( bidAmt . Sub ( oldAuction . GetBid ( ) ) ) ) , bank . GetAllBalances ( ctx , tc . bidArgs . bidder ) )
} else { // different bidder
require . Equal ( t , newBidderOldCoins . Sub ( cs ( bidAmt ) ) , bank . GetAllBalances ( ctx , tc . bidArgs . bidder ) ) // wrapping in cs() to avoid comparing nil and empty coins
// handle checking debt coins for case debt auction has had no bids placed yet TODO make this less confusing
if oldBidder . Equals ( authtypes . NewModuleAddress ( oldAuction . GetInitiator ( ) ) ) {
require . Equal ( t , oldBidderOldCoins . Add ( oldAuction . GetBid ( ) ) . Add ( c ( "debt" , oldAuction . GetBid ( ) . Amount . Int64 ( ) ) ) , bank . GetAllBalances ( ctx , oldBidder ) )
} else if oldBidder . Empty ( ) {
require . Equal ( t , oldBidderOldCoins . Add ( oldAuction . GetBid ( ) ) . Add ( c ( "debt" , oldAuction . GetBid ( ) . Amount . Int64 ( ) ) ) , oldBidderOldCoins )
2020-02-28 22:16:22 +00:00
} else {
2022-01-08 00:39:27 +00:00
require . Equal ( t , cs ( oldBidderOldCoins . Add ( oldAuction . GetBid ( ) ) ... ) , bank . GetAllBalances ( ctx , oldBidder ) )
2020-02-28 22:16:22 +00:00
}
}
2020-01-14 15:04:47 +00:00
} else {
2020-01-15 10:39:55 +00:00
// Check expected error code type
2022-02-08 16:42:00 +00:00
require . Error ( t , err , "PlaceBid did not return an error" )
require . ErrorIs ( t , err , tc . expectedError )
2020-02-28 22:16:22 +00:00
// Check auction values
newAuction , found := keeper . GetAuction ( ctx , id )
if found {
require . Equal ( t , modName , newAuction . GetInitiator ( ) )
require . Equal ( t , tc . expectedBidder , newAuction . GetBidder ( ) )
require . Equal ( t , tc . expectedBid , newAuction . GetBid ( ) )
require . Equal ( t , tc . expectedEndTime , newAuction . GetEndTime ( ) )
}
// Check coins have not moved
2022-01-08 00:39:27 +00:00
require . Equal ( t , newBidderOldCoins , bank . GetAllBalances ( ctx , tc . bidArgs . bidder ) )
require . Equal ( t , oldBidderOldCoins , bank . GetAllBalances ( ctx , oldBidder ) )
2020-01-14 15:04:47 +00:00
}
} )
}
}