From ba80b508ab1f5bc58a50e1b26c4036f92efd390b Mon Sep 17 00:00:00 2001 From: Denali Marsh Date: Wed, 15 Jan 2020 11:39:55 +0100 Subject: [PATCH] [R4R] Custom sdk.Error types for the auction module (#285) * Custom sdk.Error types for the auction module * Requested changes: naming conventions, error message text --- x/auction/alias.go | 27 +++++++--- x/auction/handler.go | 3 +- x/auction/keeper/auctions.go | 36 ++++++------- x/auction/keeper/bidding_test.go | 48 ++++++++--------- x/auction/keeper/keeper.go | 3 +- x/auction/keeper/querier.go | 2 +- x/auction/types/errors.go | 92 ++++++++++++++++++++++++++++++++ x/auction/types/msg.go | 2 +- 8 files changed, 159 insertions(+), 54 deletions(-) create mode 100644 x/auction/types/errors.go diff --git a/x/auction/alias.go b/x/auction/alias.go index 7b8ece33..dc79f6fa 100644 --- a/x/auction/alias.go +++ b/x/auction/alias.go @@ -11,13 +11,26 @@ import ( ) const ( - ModuleName = types.ModuleName - StoreKey = types.StoreKey - RouterKey = types.RouterKey - DefaultParamspace = types.DefaultParamspace - DefaultMaxAuctionDuration = types.DefaultMaxAuctionDuration - DefaultBidDuration = types.DefaultBidDuration - QueryGetAuction = types.QueryGetAuction + DefaultCodespace = types.DefaultCodespace + CodeInvalidInitialAuctionID = types.CodeInvalidInitialAuctionID + CodeUnrecognizedAuctionType = types.CodeUnrecognizedAuctionType + CodeAuctionNotFound = types.CodeAuctionNotFound + CodeAuctionHasNotExpired = types.CodeAuctionHasNotExpired + CodeAuctionHasExpired = types.CodeAuctionHasExpired + CodeInvalidBidDenom = types.CodeInvalidBidDenom + CodeInvalidLotDenom = types.CodeInvalidLotDenom + CodeBidTooSmall = types.CodeBidTooSmall + CodeBidTooLarge = types.CodeBidTooLarge + CodeLotTooLarge = types.CodeLotTooLarge + CodeCollateralAuctionIsInReversePhase = types.CodeCollateralAuctionIsInReversePhase + CodeCollateralAuctionIsInForwardPhase = types.CodeCollateralAuctionIsInForwardPhase + ModuleName = types.ModuleName + StoreKey = types.StoreKey + RouterKey = types.RouterKey + DefaultParamspace = types.DefaultParamspace + DefaultMaxAuctionDuration = types.DefaultMaxAuctionDuration + DefaultBidDuration = types.DefaultBidDuration + QueryGetAuction = types.QueryGetAuction ) var ( diff --git a/x/auction/handler.go b/x/auction/handler.go index be5f9d30..2ac42e36 100644 --- a/x/auction/handler.go +++ b/x/auction/handler.go @@ -17,8 +17,7 @@ func NewHandler(keeper Keeper) sdk.Handler { case MsgPlaceBid: return handleMsgPlaceBid(ctx, keeper, msg) default: - errMsg := fmt.Sprintf("Unrecognized auction msg type: %T", msg) - return sdk.ErrUnknownRequest(errMsg).Result() + return sdk.ErrUnknownRequest(fmt.Sprintf("Unrecognized auction msg type: %T", msg)).Result() } } } diff --git a/x/auction/keeper/auctions.go b/x/auction/keeper/auctions.go index e1465668..0c69c231 100644 --- a/x/auction/keeper/auctions.go +++ b/x/auction/keeper/auctions.go @@ -53,7 +53,7 @@ func (k Keeper) StartDebtAuction(ctx sdk.Context, buyer string, bid sdk.Coin, in // 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) if !macc.HasPermission(supply.Minter) { - return 0, sdk.ErrInternal("module does not have minting permissions") + return 0, types.ErrInvalidModulePermissions(k.codespace, supply.Minter) } err := k.supplyKeeper.SendCoinsFromModuleToModule(ctx, buyer, types.ModuleName, sdk.NewCoins(debt)) @@ -124,12 +124,12 @@ func (k Keeper) PlaceBid(ctx sdk.Context, auctionID uint64, bidder sdk.AccAddres auction, found := k.GetAuction(ctx, auctionID) if !found { - return sdk.ErrInternal("auction doesn't exist") + return types.ErrAuctionNotFound(k.codespace, auctionID) } // validation common to all auctions if ctx.BlockTime().After(auction.GetEndTime()) { - return sdk.ErrInternal("auction has closed") + return types.ErrAuctionHasExpired(k.codespace, auctionID) } // move coins and return updated auction @@ -154,7 +154,7 @@ func (k Keeper) PlaceBid(ctx sdk.Context, auctionID uint64, bidder sdk.AccAddres return err } default: - panic(fmt.Sprintf("unrecognized auction type: %T", auction)) + return types.ErrUnrecognizedAuctionType(k.codespace) } k.SetAuction(ctx, updatedAuction) @@ -166,10 +166,10 @@ func (k Keeper) PlaceBid(ctx sdk.Context, auctionID uint64, bidder sdk.AccAddres func (k Keeper) PlaceBidSurplus(ctx sdk.Context, a types.SurplusAuction, bidder sdk.AccAddress, bid sdk.Coin) (types.SurplusAuction, sdk.Error) { // Validate new bid if bid.Denom != a.Bid.Denom { - return a, sdk.ErrInternal("bid denom doesn't match auction") + return a, types.ErrInvalidBidDenom(k.codespace, bid.Denom, a.Bid.Denom) } if !a.Bid.IsLT(bid) { - return a, sdk.ErrInternal("bid not greater than last bid") + return a, types.ErrBidTooSmall(k.codespace, bid, a.Bid) } // New bidder pays back old bidder @@ -220,16 +220,16 @@ func (k Keeper) PlaceBidSurplus(ctx sdk.Context, a types.SurplusAuction, bidder func (k Keeper) PlaceForwardBidCollateral(ctx sdk.Context, a types.CollateralAuction, bidder sdk.AccAddress, bid sdk.Coin) (types.CollateralAuction, sdk.Error) { // Validate new bid if bid.Denom != a.Bid.Denom { - return a, sdk.ErrInternal("bid denom doesn't match auction") + return a, types.ErrInvalidBidDenom(k.codespace, bid.Denom, a.Bid.Denom) } if a.IsReversePhase() { - return a, sdk.ErrInternal("auction is not in forward phase") + return a, types.ErrCollateralAuctionIsInReversePhase(k.codespace, a.ID) } if !a.Bid.IsLT(bid) { - return a, sdk.ErrInternal("auction in forward phase, new bid not higher than last bid") + return a, types.ErrBidTooSmall(k.codespace, bid, a.Bid) } if a.MaxBid.IsLT(bid) { - return a, sdk.ErrInternal("bid higher than max bid") + return a, types.ErrBidTooLarge(k.codespace, bid, a.MaxBid) } // New bidder pays back old bidder @@ -289,13 +289,13 @@ func (k Keeper) PlaceForwardBidCollateral(ctx sdk.Context, a types.CollateralAuc func (k Keeper) PlaceReverseBidCollateral(ctx sdk.Context, a types.CollateralAuction, bidder sdk.AccAddress, lot sdk.Coin) (types.CollateralAuction, sdk.Error) { // Validate new bid if lot.Denom != a.Lot.Denom { - return a, sdk.ErrInternal("lot denom doesn't match auction") + return a, types.ErrInvalidLotDenom(k.codespace, lot.Denom, a.Lot.Denom) } if !a.IsReversePhase() { - return a, sdk.ErrInternal("auction not in reverse phase") + return a, types.ErrCollateralAuctionIsInForwardPhase(k.codespace, a.ID) } if !lot.IsLT(a.Lot) { - return a, sdk.ErrInternal("auction in reverse phase, new bid not less than previous amount") + return a, types.ErrLotTooLarge(k.codespace, lot, a.Lot) } // New bidder pays back old bidder @@ -349,10 +349,10 @@ func (k Keeper) PlaceReverseBidCollateral(ctx sdk.Context, a types.CollateralAuc func (k Keeper) PlaceBidDebt(ctx sdk.Context, a types.DebtAuction, bidder sdk.AccAddress, lot sdk.Coin) (types.DebtAuction, sdk.Error) { // Validate new bid if lot.Denom != a.Lot.Denom { - return a, sdk.ErrInternal("lot denom doesn't match auction") + return a, types.ErrInvalidLotDenom(k.codespace, lot.Denom, a.Lot.Denom) } if !lot.IsLT(a.Lot) { - return a, sdk.ErrInternal("lot not smaller than last lot") + return a, types.ErrLotTooLarge(k.codespace, lot, a.Lot) } // New bidder pays back old bidder @@ -407,11 +407,11 @@ func (k Keeper) CloseAuction(ctx sdk.Context, auctionID uint64) sdk.Error { auction, found := k.GetAuction(ctx, auctionID) if !found { - return sdk.ErrInternal("auction doesn't exist") + return types.ErrAuctionNotFound(k.codespace, auctionID) } 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 types.ErrAuctionHasNotExpired(k.codespace, ctx.BlockTime(), auction.GetEndTime()) } // payout to the last bidder @@ -429,7 +429,7 @@ func (k Keeper) CloseAuction(ctx sdk.Context, auctionID uint64) sdk.Error { return err } default: - panic("unrecognized auction type") + return types.ErrUnrecognizedAuctionType(k.codespace) } k.DeleteAuction(ctx, auctionID) diff --git a/x/auction/keeper/bidding_test.go b/x/auction/keeper/bidding_test.go index 7703f86e..56cea3f2 100644 --- a/x/auction/keeper/bidding_test.go +++ b/x/auction/keeper/bidding_test.go @@ -76,7 +76,7 @@ func TestAuctionBidding(t *testing.T) { name string auctionArgs auctionArgs bidArgs bidArgs - expectedError string + expectedError sdk.CodeType expectedEndTime time.Time expectedBidder sdk.AccAddress expectedBid sdk.Coin @@ -86,7 +86,7 @@ func TestAuctionBidding(t *testing.T) { "basic: auction doesn't exist", auctionArgs{Surplus, "", c("token1", 1), c("token2", 1), sdk.Coin{}, []sdk.AccAddress{}, []sdk.Int{}}, bidArgs{buyer, c("token2", 10), nil}, - "auction doesn't exist", + types.CodeAuctionNotFound, someTime.Add(types.DefaultBidDuration), buyer, c("token2", 10), @@ -96,7 +96,7 @@ func TestAuctionBidding(t *testing.T) { "surplus: normal", auctionArgs{Surplus, modName, c("token1", 100), c("token2", 10), sdk.Coin{}, []sdk.AccAddress{}, []sdk.Int{}}, bidArgs{buyer, c("token2", 10), nil}, - "", + sdk.CodeType(0), someTime.Add(types.DefaultBidDuration), buyer, c("token2", 10), @@ -106,7 +106,7 @@ func TestAuctionBidding(t *testing.T) { "surplus: second bidder", auctionArgs{Surplus, modName, c("token1", 100), c("token2", 10), sdk.Coin{}, []sdk.AccAddress{}, []sdk.Int{}}, bidArgs{buyer, c("token2", 10), secondBuyer}, - "", + sdk.CodeType(0), someTime.Add(types.DefaultBidDuration), secondBuyer, c("token2", 11), @@ -116,7 +116,7 @@ func TestAuctionBidding(t *testing.T) { "surplus: invalid bid denom", auctionArgs{Surplus, modName, c("token1", 100), c("token2", 10), sdk.Coin{}, []sdk.AccAddress{}, []sdk.Int{}}, bidArgs{buyer, c("badtoken", 10), nil}, - "bid denom doesn't match auction", + types.CodeInvalidBidDenom, someTime.Add(types.DefaultBidDuration), buyer, c("token2", 10), @@ -126,7 +126,7 @@ func TestAuctionBidding(t *testing.T) { "surplus: invalid bid (equal)", auctionArgs{Surplus, modName, c("token1", 100), c("token2", 0), sdk.Coin{}, []sdk.AccAddress{}, []sdk.Int{}}, bidArgs{buyer, c("token2", 0), nil}, - "bid not greater than last bid", + types.CodeBidTooSmall, someTime.Add(types.DefaultBidDuration), buyer, c("token2", 10), @@ -136,7 +136,7 @@ func TestAuctionBidding(t *testing.T) { "debt: normal", auctionArgs{Debt, modName, c("token1", 20), c("token2", 100), c("debt", 20), []sdk.AccAddress{}, []sdk.Int{}}, // initial bid, lot bidArgs{buyer, c("token1", 10), nil}, - "", + sdk.CodeType(0), someTime.Add(types.DefaultBidDuration), buyer, c("token2", 100), @@ -146,7 +146,7 @@ func TestAuctionBidding(t *testing.T) { "debt: second bidder", auctionArgs{Debt, modName, c("token1", 20), c("token2", 100), c("debt", 20), []sdk.AccAddress{}, []sdk.Int{}}, // initial bid, lot bidArgs{buyer, c("token1", 10), secondBuyer}, - "", + sdk.CodeType(0), someTime.Add(types.DefaultBidDuration), secondBuyer, c("token2", 100), @@ -156,7 +156,7 @@ func TestAuctionBidding(t *testing.T) { "debt: invalid lot denom", auctionArgs{Debt, modName, c("token1", 20), c("token2", 100), c("debt", 20), []sdk.AccAddress{}, []sdk.Int{}}, // initial bid, lot bidArgs{buyer, c("badtoken", 10), nil}, - "lot denom doesn't match auction", + types.CodeInvalidLotDenom, someTime.Add(types.DefaultBidDuration), buyer, c("token1", 20), @@ -166,7 +166,7 @@ func TestAuctionBidding(t *testing.T) { "debt: invalid lot size (larger)", auctionArgs{Debt, modName, c("token1", 20), c("token2", 100), c("debt", 20), []sdk.AccAddress{}, []sdk.Int{}}, bidArgs{buyer, c("token1", 21), nil}, - "lot not smaller than last lot", + types.CodeLotTooLarge, someTime.Add(types.DefaultBidDuration), buyer, c("token1", 20), @@ -176,7 +176,7 @@ func TestAuctionBidding(t *testing.T) { "collateral [forward]: normal", auctionArgs{CollateralPhase1, modName, c("token1", 20), c("token2", 100), c("debt", 50), collateralAddrs, collateralWeights}, // lot, max bid bidArgs{buyer, c("token2", 10), nil}, - "", + sdk.CodeType(0), someTime.Add(types.DefaultBidDuration), buyer, c("token2", 10), @@ -186,7 +186,7 @@ func TestAuctionBidding(t *testing.T) { "collateral [forward]: second bidder", auctionArgs{CollateralPhase1, modName, c("token1", 20), c("token2", 100), c("debt", 50), collateralAddrs, collateralWeights}, // lot, max bid bidArgs{buyer, c("token2", 10), secondBuyer}, - "", + sdk.CodeType(0), someTime.Add(types.DefaultBidDuration), secondBuyer, c("token2", 11), @@ -196,7 +196,7 @@ func TestAuctionBidding(t *testing.T) { "collateral [forward]: invalid bid denom", auctionArgs{CollateralPhase1, modName, c("token1", 20), c("token2", 100), c("debt", 50), collateralAddrs, collateralWeights}, // lot, max bid bidArgs{buyer, c("badtoken", 10), nil}, - "bid denom doesn't match auction", + types.CodeInvalidBidDenom, someTime.Add(types.DefaultBidDuration), buyer, c("token2", 10), @@ -206,7 +206,7 @@ func TestAuctionBidding(t *testing.T) { "collateral [forward]: invalid bid size (smaller)", auctionArgs{CollateralPhase1, modName, c("token1", 20), c("token2", 100), c("debt", 50), collateralAddrs, collateralWeights}, // lot, max bid bidArgs{buyer, c("token2", 0), nil}, // lot, bid - "auction in forward phase, new bid not higher than last bid", + types.CodeBidTooSmall, someTime.Add(types.DefaultBidDuration), buyer, c("token2", 10), @@ -216,7 +216,7 @@ func TestAuctionBidding(t *testing.T) { "collateral [forward]: invalid bid size (greater than max)", auctionArgs{CollateralPhase1, modName, c("token1", 20), c("token2", 100), c("debt", 50), collateralAddrs, collateralWeights}, // lot, max bid bidArgs{buyer, c("token2", 101), nil}, // lot, bid - "bid higher than max bid", + types.CodeBidTooLarge, someTime.Add(types.DefaultBidDuration), buyer, c("token2", 10), @@ -226,7 +226,7 @@ func TestAuctionBidding(t *testing.T) { "collateral [reverse]: normal", auctionArgs{CollateralPhase2, modName, c("token1", 20), c("token2", 50), c("debt", 50), collateralAddrs, collateralWeights}, // lot, max bid bidArgs{buyer, c("token1", 15), nil}, - "", + sdk.CodeType(0), someTime.Add(types.DefaultBidDuration), buyer, c("token2", 50), @@ -236,7 +236,7 @@ func TestAuctionBidding(t *testing.T) { "collateral [reverse]: second bidder", auctionArgs{CollateralPhase2, modName, c("token1", 20), c("token2", 50), c("debt", 50), collateralAddrs, collateralWeights}, // lot, max bid bidArgs{buyer, c("token1", 15), secondBuyer}, - "", + sdk.CodeType(0), someTime.Add(types.DefaultBidDuration), secondBuyer, c("token2", 50), @@ -246,7 +246,7 @@ func TestAuctionBidding(t *testing.T) { "collateral [reverse]: invalid lot denom", auctionArgs{CollateralPhase2, modName, c("token1", 20), c("token2", 50), c("debt", 50), collateralAddrs, collateralWeights}, // lot, max bid bidArgs{buyer, c("badtoken", 15), nil}, - "lot denom doesn't match auction", + types.CodeInvalidLotDenom, someTime.Add(types.DefaultBidDuration), buyer, c("token2", 50), @@ -256,7 +256,7 @@ func TestAuctionBidding(t *testing.T) { "collateral [reverse]: invalid lot size (equal)", auctionArgs{CollateralPhase2, modName, c("token1", 20), c("token2", 50), c("debt", 50), collateralAddrs, collateralWeights}, // lot, max bid bidArgs{buyer, c("token1", 20), nil}, - "auction in reverse phase, new bid not less than previous amount", + types.CodeLotTooLarge, someTime.Add(types.DefaultBidDuration), buyer, c("token2", 50), @@ -266,7 +266,7 @@ func TestAuctionBidding(t *testing.T) { "collateral [reverse]: invalid lot size (greater)", auctionArgs{CollateralPhase2, modName, c("token1", 20), c("token2", 50), c("debt", 50), collateralAddrs, collateralWeights}, // lot, max bid bidArgs{buyer, c("token1", 21), nil}, - "auction in reverse phase, new bid not less than previous amount", + types.CodeLotTooLarge, someTime.Add(types.DefaultBidDuration), buyer, c("token2", 50), @@ -276,7 +276,7 @@ func TestAuctionBidding(t *testing.T) { "basic: closed auction", auctionArgs{Surplus, modName, c("token1", 100), c("token2", 10), sdk.Coin{}, []sdk.AccAddress{}, []sdk.Int{}}, bidArgs{buyer, c("token2", 10), nil}, - "auction has closed", + types.CodeAuctionHasExpired, someTime.Add(types.DefaultBidDuration), buyer, c("token2", 10), @@ -287,7 +287,7 @@ func TestAuctionBidding(t *testing.T) { t.Run(tc.name, func(t *testing.T) { // Start Auction var id uint64 - var err error + var err sdk.Error switch tc.auctionArgs.auctionType { case Surplus: id, _ = keeper.StartSurplusAuction(ctx, tc.auctionArgs.seller, tc.auctionArgs.lot, tc.auctionArgs.bid.Denom) @@ -341,8 +341,8 @@ func TestAuctionBidding(t *testing.T) { require.Equal(t, tc.expectedBid, auction.GetBid()) require.Equal(t, tc.expectedEndTime, auction.GetEndTime()) } else { - // Check expected error message - require.Contains(t, err.Error(), tc.expectedError) + // Check expected error code type + require.Equal(t, tc.expectedError, err.Result().Code) } }) } diff --git a/x/auction/keeper/keeper.go b/x/auction/keeper/keeper.go index cd0b01c2..49229461 100644 --- a/x/auction/keeper/keeper.go +++ b/x/auction/keeper/keeper.go @@ -18,6 +18,7 @@ type Keeper struct { storeKey sdk.StoreKey cdc *codec.Codec paramSubspace subspace.Subspace + codespace sdk.CodespaceType } // NewKeeper returns a new auction keeper. @@ -46,7 +47,7 @@ func (k Keeper) GetNextAuctionID(ctx sdk.Context) (uint64, sdk.Error) { store := ctx.KVStore(k.storeKey) bz := store.Get(types.NextAuctionIDKey) if bz == nil { - return 0, sdk.ErrInternal("initial auction ID hasn't been set") + return 0, types.ErrInvalidInitialAuctionID(k.codespace) } return types.Uint64FromBytes(bz), nil } diff --git a/x/auction/keeper/querier.go b/x/auction/keeper/querier.go index 50afa363..9fe384c8 100644 --- a/x/auction/keeper/querier.go +++ b/x/auction/keeper/querier.go @@ -29,7 +29,7 @@ func queryAuctions(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) (res [ bz, err2 := codec.MarshalJSONIndent(keeper.cdc, auctionsList) if err2 != nil { - panic("could not marshal result to JSON") + return nil, sdk.ErrInternal("could not marshal result to JSON") } return bz, nil diff --git a/x/auction/types/errors.go b/x/auction/types/errors.go new file mode 100644 index 00000000..f5b427aa --- /dev/null +++ b/x/auction/types/errors.go @@ -0,0 +1,92 @@ +// DONTCOVER +package types + +import ( + "fmt" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Error codes specific to auction module +const ( + DefaultCodespace sdk.CodespaceType = ModuleName + CodeInvalidInitialAuctionID sdk.CodeType = 1 + CodeInvalidModulePermissions sdk.CodeType = 2 + CodeUnrecognizedAuctionType sdk.CodeType = 3 + CodeAuctionNotFound sdk.CodeType = 4 + CodeAuctionHasNotExpired sdk.CodeType = 5 + CodeAuctionHasExpired sdk.CodeType = 6 + CodeInvalidBidDenom sdk.CodeType = 7 + CodeInvalidLotDenom sdk.CodeType = 8 + CodeBidTooSmall sdk.CodeType = 9 + CodeBidTooLarge sdk.CodeType = 10 + CodeLotTooLarge sdk.CodeType = 11 + CodeCollateralAuctionIsInReversePhase sdk.CodeType = 12 + CodeCollateralAuctionIsInForwardPhase sdk.CodeType = 13 +) + +// ErrInvalidInitialAuctionID error for when the initial auction ID hasn't been set +func ErrInvalidInitialAuctionID(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidInitialAuctionID, fmt.Sprintf("initial auction ID hasn't been set")) +} + +// ErrInvalidModulePermissions error for when module doesn't have valid permissions +func ErrInvalidModulePermissions(codespace sdk.CodespaceType, permission string) sdk.Error { + return sdk.NewError(codespace, CodeInvalidModulePermissions, fmt.Sprintf("module does not have required permission '%s'", permission)) +} + +// ErrUnrecognizedAuctionType error for unrecognized auction type +func ErrUnrecognizedAuctionType(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeUnrecognizedAuctionType, fmt.Sprintf("unrecognized auction type")) +} + +// ErrAuctionNotFound error for when an auction is not found +func ErrAuctionNotFound(codespace sdk.CodespaceType, id uint64) sdk.Error { + return sdk.NewError(codespace, CodeAuctionNotFound, fmt.Sprintf("auction %d was not found", id)) +} + +// ErrAuctionHasNotExpired error for attempting to close an auction that has not passed its end time +func ErrAuctionHasNotExpired(codespace sdk.CodespaceType, blockTime time.Time, endTime time.Time) sdk.Error { + return sdk.NewError(codespace, CodeAuctionHasNotExpired, fmt.Sprintf("auction can't be closed as curent block time (%v) has not passed auction end time (%v)", blockTime, endTime)) +} + +// ErrAuctionHasExpired error for when an auction is closed and unavailable for bidding +func ErrAuctionHasExpired(codespace sdk.CodespaceType, id uint64) sdk.Error { + return sdk.NewError(codespace, CodeAuctionHasExpired, fmt.Sprintf("auction %d has closed", id)) +} + +// ErrInvalidBidDenom error for when bid denom doesn't match auction bid denom +func ErrInvalidBidDenom(codespace sdk.CodespaceType, bidDenom string, auctionBidDenom string) sdk.Error { + return sdk.NewError(codespace, CodeInvalidBidDenom, fmt.Sprintf("bid denom %s doesn't match auction bid denom %s", bidDenom, auctionBidDenom)) +} + +// ErrInvalidLotDenom error for when lot denom doesn't match auction lot denom +func ErrInvalidLotDenom(codespace sdk.CodespaceType, lotDenom string, auctionLotDenom string) sdk.Error { + return sdk.NewError(codespace, CodeInvalidLotDenom, fmt.Sprintf("lot denom %s doesn't match auction lot denom %s", lotDenom, auctionLotDenom)) +} + +// ErrBidTooSmall error for when bid is not greater than auction's last bid +func ErrBidTooSmall(codespace sdk.CodespaceType, bid sdk.Coin, lastBid sdk.Coin) sdk.Error { + return sdk.NewError(codespace, CodeBidTooSmall, fmt.Sprintf("bid %s is smaller than auction's last bid %s", bid.String(), lastBid.String())) +} + +// ErrBidTooLarge error for when bid is larger than auction's maximum allowed bid +func ErrBidTooLarge(codespace sdk.CodespaceType, bid sdk.Coin, maxBid sdk.Coin) sdk.Error { + return sdk.NewError(codespace, CodeBidTooLarge, fmt.Sprintf("bid %s is greater than auction's max bid %s", bid.String(), maxBid.String())) +} + +// ErrLotTooLarge error for when lot is not smaller than auction's last lot +func ErrLotTooLarge(codespace sdk.CodespaceType, lot sdk.Coin, lastLot sdk.Coin) sdk.Error { + return sdk.NewError(codespace, CodeLotTooLarge, fmt.Sprintf("lot %s is not less than auction's last lot %s", lot.String(), lastLot.String())) +} + +// ErrCollateralAuctionIsInReversePhase error for when attempting to place a forward bid on a collateral auction in reverse phase +func ErrCollateralAuctionIsInReversePhase(codespace sdk.CodespaceType, id uint64) sdk.Error { + return sdk.NewError(codespace, CodeCollateralAuctionIsInReversePhase, fmt.Sprintf("invalid bid - auction %d is in reverse phase", id)) +} + +// ErrCollateralAuctionIsInForwardPhase error for when attempting to place a reverse bid on a collateral auction in forward phase +func ErrCollateralAuctionIsInForwardPhase(codespace sdk.CodespaceType, id uint64) sdk.Error { + return sdk.NewError(codespace, CodeCollateralAuctionIsInForwardPhase, fmt.Sprintf("invalid bid - auction %d is in forward phase", id)) +} diff --git a/x/auction/types/msg.go b/x/auction/types/msg.go index 976aedb1..ed18d84b 100644 --- a/x/auction/types/msg.go +++ b/x/auction/types/msg.go @@ -33,7 +33,7 @@ func (msg MsgPlaceBid) ValidateBasic() sdk.Error { return sdk.ErrInternal("invalid (empty) bidder address") } if !msg.Amount.IsValid() { - return sdk.ErrInternal("invalid bid amount") + return sdk.ErrInvalidCoins(msg.Amount.String()) } return nil }