From 01bc492371e7186611a079eb39e33cefc0914ab7 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Mon, 23 Sep 2024 18:00:15 +0530 Subject: [PATCH] Add method to release provider funds after auction completion --- x/auction/events.go | 1 + x/auction/keeper/keeper.go | 76 ++++++++++++++++++++++++++-------- x/auction/keeper/msg_server.go | 37 +++++++++++++++++ x/auction/msgs.go | 39 +++++++++++++---- x/auction/types.go | 3 ++ 5 files changed, 129 insertions(+), 27 deletions(-) diff --git a/x/auction/events.go b/x/auction/events.go index b60264f5..3807b3c0 100644 --- a/x/auction/events.go +++ b/x/auction/events.go @@ -4,6 +4,7 @@ const ( EventTypeCreateAuction = "create-auction" EventTypeCommitBid = "commit-bid" EventTypeRevealBid = "reveal-bid" + EventTypeReleaseFunds = "release-funds" AttributeKeyCommitsDuration = "commits-duration" AttributeKeyRevealsDuration = "reveals-duration" diff --git a/x/auction/keeper/keeper.go b/x/auction/keeper/keeper.go index 05e99473..babdebfa 100644 --- a/x/auction/keeper/keeper.go +++ b/x/auction/keeper/keeper.go @@ -886,24 +886,6 @@ func (k Keeper) pickProviderAuctionWinners(ctx sdk.Context, auction *auctiontype } } - // Process winner accounts (if nobody bids, there won't be a winner). - if len(winnerBids) > 0 { - for _, bid := range winnerBids { - winnerAddress, err := sdk.AccAddressFromBech32(bid.BidderAddress) - if err != nil { - k.Logger(ctx).Error(fmt.Sprintf("Invalid winner address. %v", err)) - panic("Invalid winner address.") - } - - // Send winning price to bidders - sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, auctiontypes.ModuleName, winnerAddress, sdk.NewCoins(auction.WinningPrice)) - if sdkErr != nil { - k.Logger(ctx).Error(fmt.Sprintf("Auction error sending funds to winner: %v", sdkErr)) - panic(sdkErr) - } - } - } - // Send back any leftover locked amount to auction creator // All of it in case of no winners totalLockedAmount := auction.MaxPrice.Amount.Mul(math.NewInt(int64(auction.NumProviders))) @@ -936,3 +918,61 @@ func (k Keeper) pickProviderAuctionWinners(ctx sdk.Context, auction *auctiontype return nil } + +func (k Keeper) ReleaseFunds(ctx sdk.Context, msg auctiontypes.MsgReleaseFunds) (*auctiontypes.Auction, error) { + if has, err := k.HasAuction(ctx, msg.AuctionId); !has { + if err != nil { + return nil, err + } + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Auction not found.") + } + + auction, err := k.GetAuctionById(ctx, msg.AuctionId) + if err != nil { + return nil, err + } + + if auction.Kind != auctiontypes.AuctionKindProvider { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Auction kind must be provider.") + } + + if auction.Status != auctiontypes.AuctionStatusCompleted { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Auction is not completed.") + } + + if auction.Status == auctiontypes.AuctionStatusFundsReleased { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Funds have already been released.") + } + + // Only the auction owner can release funds. + if msg.Signer != auction.OwnerAddress { + return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "Auction owner mismatch.") + } + + // Process winner accounts (if nobody bids, there won't be a winner). + if len(auction.WinnerAddresses) > 0 { + for _, winnerAddress := range auction.WinnerAddresses { + winnerAccAddress, err := sdk.AccAddressFromBech32(winnerAddress) + if err != nil { + k.Logger(ctx).Error(fmt.Sprintf("Invalid winner address. %v", err)) + panic("Invalid winner address.") + } + + // Send winning price to bidders + sdkErr := k.bankKeeper.SendCoinsFromModuleToAccount( + ctx, + auctiontypes.ModuleName, + winnerAccAddress, + sdk.NewCoins(auction.WinningPrice), + ) + if sdkErr != nil { + k.Logger(ctx).Error(fmt.Sprintf("Auction error sending funds to winner: %v", sdkErr)) + panic(sdkErr) + } + } + } + + auction.FundsReleased = true + + return &auction, err +} diff --git a/x/auction/keeper/msg_server.go b/x/auction/keeper/msg_server.go index 0a5fc447..7cc9ff30 100644 --- a/x/auction/keeper/msg_server.go +++ b/x/auction/keeper/msg_server.go @@ -149,3 +149,40 @@ func (ms msgServer) UpdateParams(c context.Context, msg *auctiontypes.MsgUpdateP return &auctiontypes.MsgUpdateParamsResponse{}, nil } + +// ReleaseFunds is the command to pay the winning amounts to provider auction winners +// nolint: all +func (ms msgServer) ReleaseFunds(c context.Context, msg *auctiontypes.MsgReleaseFunds) (*auctiontypes.MsgReleaseFundsResponse, error) { + if err := msg.ValidateBasic(); err != nil { + return nil, err + } + + ctx := sdk.UnwrapSDKContext(c) + ctx = *utils.CtxWithCustomKVGasConfig(&ctx) + + signerAddress, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, err + } + + resp, err := ms.k.ReleaseFunds(ctx, *msg) + if err != nil { + return nil, err + } + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + auctiontypes.EventTypeReleaseFunds, + sdk.NewAttribute(auctiontypes.AttributeKeyAuctionId, msg.AuctionId), + ), + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, auctiontypes.AttributeValueCategory), + sdk.NewAttribute(auctiontypes.AttributeKeySigner, signerAddress.String()), + ), + }) + + utils.LogTxGasConsumed(ctx, ms.k.Logger(ctx), "ReleaseFunds") + + return &auctiontypes.MsgReleaseFundsResponse{Auction: resp}, nil +} diff --git a/x/auction/msgs.go b/x/auction/msgs.go index 2945ca35..c35c7eda 100644 --- a/x/auction/msgs.go +++ b/x/auction/msgs.go @@ -49,6 +49,23 @@ func NewMsgCommitBid(auctionId string, commitHash string, signer sdk.AccAddress) } } +// NewMsgRevealBid is the constructor function for MsgRevealBid. +func NewMsgRevealBid(auctionId string, reveal string, signer sdk.AccAddress) MsgRevealBid { + return MsgRevealBid{ + AuctionId: auctionId, + Reveal: reveal, + Signer: signer.String(), + } +} + +// NewMsgReleaseFunds is the constructor function for MsgReleaseFunds. +func NewMsgReleaseFunds(auctionId string, signer sdk.AccAddress) MsgReleaseFunds { + return MsgReleaseFunds{ + AuctionId: auctionId, + Signer: signer.String(), + } +} + // ValidateBasic Implements Msg. func (msg MsgCreateAuction) ValidateBasic() error { if msg.Signer == "" { @@ -101,15 +118,6 @@ func (msg MsgCommitBid) ValidateBasic() error { return nil } -// NewMsgRevealBid is the constructor function for MsgRevealBid. -func NewMsgRevealBid(auctionId string, reveal string, signer sdk.AccAddress) MsgRevealBid { - return MsgRevealBid{ - AuctionId: auctionId, - Reveal: reveal, - Signer: signer.String(), - } -} - // ValidateBasic Implements Msg. func (msg MsgRevealBid) ValidateBasic() error { if msg.Signer == "" { @@ -126,3 +134,16 @@ func (msg MsgRevealBid) ValidateBasic() error { return nil } + +// ValidateBasic Implements Msg. +func (msg MsgReleaseFunds) ValidateBasic() error { + if msg.Signer == "" { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid signer address") + } + + if msg.AuctionId == "" { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid auction id") + } + + return nil +} diff --git a/x/auction/types.go b/x/auction/types.go index 266f0c32..17eaef2a 100644 --- a/x/auction/types.go +++ b/x/auction/types.go @@ -21,6 +21,9 @@ const ( // Auction has completed (winner selected). AuctionStatusCompleted = "completed" + + // Auction has completed (winner selected). + AuctionStatusFundsReleased = "funds_released" ) // Bid status values.