Skip to content

Commit

Permalink
feat(x/auction): implement auction finalization (#2498)
Browse files Browse the repository at this point in the history
* feat(x/auction): implement auction finalization

* convert rewards.Bidder from string to bytes

* use module account

* fix

* burn coins

* fix

* review

* lint

* disable x/auction endblocker
  • Loading branch information
robert-zaremba authored Apr 18, 2024
1 parent b0413b6 commit 17a8fd0
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 64 deletions.
2 changes: 1 addition & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ func init() {
leveragetypes.ModuleName: {authtypes.Minter, authtypes.Burner},
wasmtypes.ModuleName: {authtypes.Burner},

auction.ModuleName: nil,
auction.ModuleName: {authtypes.Burner},
incentive.ModuleName: nil,
metoken.ModuleName: {authtypes.Minter, authtypes.Burner},
oracletypes.ModuleName: nil,
Expand Down
2 changes: 1 addition & 1 deletion proto/umee/auction/v1/auction.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ message RewardsParams {

// Bid records a user bid
message Bid {
string bidder = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
bytes bidder = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string amount = 2 [(cosmos_proto.scalar) = "cosmos.Int", (gogoproto.customtype) = "cosmossdk.io/math.Int", (gogoproto.nullable) = false];
}

Expand Down
70 changes: 36 additions & 34 deletions x/auction/auction.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions x/auction/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (

// BankKeeper defines the expected x/bank keeper interface.
type BankKeeper interface {
// SendCoinsFromModuleToAccount(ctx sdk.Context, fromModule string, toAddr sdk.AccAddress, coins sdk.Coins) error
// SendCoinsFromAccountToModule(ctx sdk.Context, fromAddr sdk.AccAddress, toModule string, coins sdk.Coins) error
// SendCoinsFromModuleToModule(ctx sdk.Context, fromModule string, toModule string, coins sdk.Coins) error
SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
SendCoins(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
}
4 changes: 2 additions & 2 deletions x/auction/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ func (q Querier) RewardsAuction(goCtx context.Context, msg *auction.QueryRewards
bid, id := q.Keeper(&ctx).getRewardsBid(msg.Id)
r := &auction.QueryRewardsAuctionResponse{Id: id}
if bid != nil {
r.Bidder = bid.Bidder
r.Bidder = sdk.AccAddress(bid.Bidder).String()
r.Bid = coin.UmeeInt(bid.Amount)
}
rewards, _ := q.Keeper(&ctx).getRewards(msg.Id)
rewards, _ := q.Keeper(&ctx).getRewardsAuction(msg.Id)
if rewards != nil {
r.Rewards = rewards.Rewards
r.EndsAt = rewards.EndsAt
Expand Down
18 changes: 14 additions & 4 deletions x/auction/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
)

type SubAccounts struct {
Rewards []byte
RewardsBid []byte
// Account used to collect rewards
RewardsCollect []byte
}

type Builder struct {
Expand Down Expand Up @@ -54,6 +54,16 @@ type Keeper struct {
ctx *sdk.Context
}

func (k Keeper) sendCoins(from, to sdk.AccAddress, amount sdk.Coins) error {
return k.bank.SendCoins(*k.ctx, from, to, amount)
//
// helper functions
//

func (k Keeper) sendCoins(from, to sdk.AccAddress, amounts sdk.Coins) error {
return k.bank.SendCoins(*k.ctx, from, to, amounts)
}
func (k Keeper) sendFromModule(to sdk.AccAddress, amounts ...sdk.Coin) error {
return k.bank.SendCoinsFromModuleToAccount(*k.ctx, auction.ModuleName, to, amounts)
}
func (k Keeper) sendToModule(from sdk.AccAddress, amounts ...sdk.Coin) error {
return k.bank.SendCoinsFromAccountToModule(*k.ctx, from, auction.ModuleName, amounts)
}
62 changes: 48 additions & 14 deletions x/auction/keeper/rewards.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package keeper

import (
"bytes"
"errors"
"fmt"
"strconv"
"time"

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/umee-network/umee/v6/util"
Expand All @@ -13,8 +15,35 @@ import (
"github.com/umee-network/umee/v6/x/auction"
)

func umeeCoins(amount sdkmath.Int) sdk.Coins {
return sdk.Coins{coin.UmeeInt(amount)}
func (k Keeper) FinalizeRewardsAuction() error {
now := k.ctx.BlockTime()
a, id := k.getRewardsAuction(0)
if !a.EndsAt.After(now) {
return nil
}

newCoins := k.bank.GetAllBalances(*k.ctx, k.accs.RewardsCollect)
bid, _ := k.getRewardsBid(id)
if len(bid.Bidder) == 0 {
err := k.sendCoins(k.accs.RewardsCollect, bid.Bidder, a.Rewards)
if err != nil {
return fmt.Errorf("can't send coins to finalize the auction [%w]", err)
}
err = k.bank.BurnCoins(*k.ctx, auction.ModuleName, sdk.Coins{coin.UmeeInt(bid.Amount)})
if err != nil {
return fmt.Errorf("can't burn rewards auction bid [%w]", err)
}

} else if len(a.Rewards) != 0 {
// rollover the past rewards if there was no bidder
newCoins = newCoins.Add(a.Rewards...)
}

id++
store.SetInteger(k.store, keyRewardsCurrentID, id)
params := k.GetRewardsParams()
endsAt := now.Add(time.Duration(params.BidDuration) * time.Second)
return k.storeNewRewardsAuction(id, endsAt, newCoins)
}

func (k Keeper) currentRewardsAuction() uint32 {
Expand All @@ -41,25 +70,23 @@ func (k Keeper) rewardsBid(msg *auction.MsgRewardsBid) error {

sender, err := sdk.AccAddressFromBech32(msg.Sender)
util.Panic(err)
prevBidder, err := sdk.AccAddressFromBech32(lastBid.Bidder)
util.Panic(err)
vault := k.accs.RewardsBid

if lastBid.Bidder != msg.Sender {
if err = k.sendCoins(vault, prevBidder, umeeCoins(lastBid.Amount)); err != nil {
if !bytes.Equal(sender, lastBid.Bidder) {
returned := coin.UmeeInt(lastBid.Amount)
if err = k.sendFromModule(lastBid.Bidder, returned); err != nil {
return err
}
if err = k.sendCoins(sender, vault, sdk.Coins{msg.Amount}); err != nil {
if err = k.sendToModule(sender, msg.Amount); err != nil {
return err
}
} else {
diff := msg.Amount.SubAmount(minBid)
if err = k.sendCoins(sender, vault, sdk.Coins{diff}); err != nil {
diff := msg.Amount.SubAmount(lastBid.Amount)
if err = k.sendToModule(sender, diff); err != nil {
return err
}
}

bid := auction.Bid{Bidder: msg.Sender, Amount: msg.Amount.Amount}
bid := auction.Bid{Bidder: sender, Amount: msg.Amount.Amount}
return store.SetValue(k.store, key, &bid, keyMsg)
}

Expand All @@ -73,11 +100,18 @@ func (k Keeper) getRewardsBid(id uint32) (*auction.Bid, uint32) {
}

// returns nil if id is not found
func (k Keeper) getRewards(id uint32) (*auction.Rewards, uint32) {
func (k Keeper) getRewardsAuction(id uint32) (*auction.Rewards, uint32) {
if id == 0 {
id = k.currentRewardsAuction()
}
keyMsg := "auction.rewards.coins"
const keyMsg = "auction.rewards.coins"
key := k.keyRewardsCoins(id)
return store.GetValue[*auction.Rewards](k.store, key, keyMsg), id
}

func (k Keeper) storeNewRewardsAuction(id uint32, endsAt time.Time, coins sdk.Coins) error {
newRewards := auction.Rewards{EndsAt: endsAt, Rewards: coins}
const keyMsg = "auction.rewards.coins"
key := k.keyRewardsCoins(id)
return store.SetValue(k.store, key, &newRewards, keyMsg)
}
13 changes: 9 additions & 4 deletions x/auction/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,20 +150,25 @@ func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// EndBlock executes all ABCI EndBlock logic respective to the x/auction module.
// It returns no validator updates.
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
// TODO: enable end blocker
// k := am.kb.Keeper(&ctx)
// if err := k.FinalizeRewardsAuction(); err != nil {
// ctx.Logger().With("module", "x/auction").
// Error("can't finalize rewards auction", "error", err)
// }

return []abci.ValidatorUpdate{}
}

// sub-module accounts
var (
subaccRewards = []byte{0x01}
subaccRewardsBid = []byte{0x02}
subAccRewards = []byte{0x01}
)

// SubAccounts for auction Keeper
func SubAccounts() keeper.SubAccounts {
n := AppModuleBasic{}.Name()
return keeper.SubAccounts{
Rewards: address.Module(n, subaccRewards),
RewardsBid: address.Module(n, subaccRewardsBid),
RewardsCollect: address.Module(n, subAccRewards),
}
}

0 comments on commit 17a8fd0

Please sign in to comment.