Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(x/auction): implement auction finalization #2498

Merged
merged 10 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"];
robert-zaremba marked this conversation as resolved.
Show resolved Hide resolved
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)
robert-zaremba marked this conversation as resolved.
Show resolved Hide resolved
robert-zaremba marked this conversation as resolved.
Show resolved Hide resolved
}

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 {
robert-zaremba marked this conversation as resolved.
Show resolved Hide resolved
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),
}
}
Loading