feat: add spec, update redundant type names

This commit is contained in:
Kevin Davis 2020-01-07 12:17:27 -05:00
parent b2fa8d81ee
commit de4f55ea20
14 changed files with 241 additions and 39 deletions

View File

@ -25,21 +25,29 @@ var (
NewForwardAuction = types.NewForwardAuction
NewReverseAuction = types.NewReverseAuction
NewForwardReverseAuction = types.NewForwardReverseAuction
NewWeightedAddresses = types.NewWeightedAddresses
RegisterCodec = types.RegisterCodec
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
ValidateGenesis = types.ValidateGenesis
GetAuctionKey = types.GetAuctionKey
GetAuctionByTimeKey = types.GetAuctionByTimeKey
Uint64FromBytes = types.Uint64FromBytes
Uint64ToBytes = types.Uint64ToBytes
NewMsgPlaceBid = types.NewMsgPlaceBid
NewAuctionParams = types.NewAuctionParams
DefaultAuctionParams = types.DefaultAuctionParams
NewParams = types.NewParams
DefaultParams = types.DefaultParams
ParamKeyTable = types.ParamKeyTable
NewKeeper = keeper.NewKeeper
NewQuerier = keeper.NewQuerier
// variable aliases
ModuleCdc = types.ModuleCdc
KeyAuctionBidDuration = types.KeyAuctionBidDuration
KeyAuctionDuration = types.KeyAuctionDuration
ModuleCdc = types.ModuleCdc
AuctionKeyPrefix = types.AuctionKeyPrefix
AuctionByTimeKeyPrefix = types.AuctionByTimeKeyPrefix
NextAuctionIDKey = types.NextAuctionIDKey
KeyAuctionBidDuration = types.KeyAuctionBidDuration
KeyAuctionDuration = types.KeyAuctionDuration
)
type (
@ -48,10 +56,12 @@ type (
ForwardAuction = types.ForwardAuction
ReverseAuction = types.ReverseAuction
ForwardReverseAuction = types.ForwardReverseAuction
GenesisAuctions = types.GenesisAuctions
WeightedAddresses = types.WeightedAddresses
SupplyKeeper = types.SupplyKeeper
Auctions = types.Auctions
GenesisState = types.GenesisState
MsgPlaceBid = types.MsgPlaceBid
AuctionParams = types.AuctionParams
Params = types.Params
QueryResAuctions = types.QueryResAuctions
Keeper = keeper.Keeper
)

View File

@ -8,7 +8,7 @@ import (
func InitGenesis(ctx sdk.Context, keeper Keeper, data GenesisState) {
keeper.SetNextAuctionID(ctx, data.NextAuctionID)
keeper.SetParams(ctx, data.AuctionParams)
keeper.SetParams(ctx, data.Params)
for _, a := range data.Auctions {
keeper.SetAuction(ctx, a)
@ -24,7 +24,7 @@ func ExportGenesis(ctx sdk.Context, keeper Keeper) GenesisState {
params := keeper.GetParams(ctx)
var genAuctions GenesisAuctions
var genAuctions Auctions
keeper.IterateAuctions(ctx, func(a Auction) bool {
genAuctions = append(genAuctions, a)
return false

View File

@ -49,11 +49,15 @@ func TestForwardAuctionBasic(t *testing.T) {
// Check seller's coins have not increased (because proceeds are burned)
tApp.CheckBalance(t, ctx, sellerAddr, cs(c("token1", 80), c("token2", 100)))
// increment bid same bidder
err = keeper.PlaceBid(ctx, auctionID, buyer, c("token2", 20), c("token1", 20))
require.NoError(t, err)
// Close auction at just at auction expiry time
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(types.DefaultBidDuration))
require.NoError(t, keeper.CloseAuction(ctx, auctionID))
// Check buyer's coins increased
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 120), c("token2", 90)))
tApp.CheckBalance(t, ctx, buyer, cs(c("token1", 120), c("token2", 80)))
}
func TestReverseAuctionBasic(t *testing.T) {

View File

@ -6,12 +6,12 @@ import (
)
// SetParams sets the auth module's parameters.
func (k Keeper) SetParams(ctx sdk.Context, params types.AuctionParams) {
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
k.paramSubspace.SetParamSet(ctx, &params)
}
// GetParams gets the auth module's parameters.
func (k Keeper) GetParams(ctx sdk.Context) (params types.AuctionParams) {
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
k.paramSubspace.GetParamSet(ctx, &params)
return
}
}

View File

@ -0,0 +1,13 @@
<!--
order: 1
-->
# Concepts
Auctions are broken down into three distinct types, which correspond to three specific functionalities within the CDP system.
* **Forward Auction:** An auction in which a fixed lot of coins (c1) is sold for increasing amounts of other coins (c2). Bidders increment the amount of c2 they are willing to pay for the lot of c1. After the completion of a forward auction, the winning bid of c2 is burned, and the bidder receives the lot of c1. As a concrete example, forward auction are used to sell a fixed amount of USDX stable coins in exchange for increasing bids of KAVA governance tokens. The governance tokens are then burned and the winner receives USDX.
* **Reverse Auction:** An auction in which a fixed amount of coins (c1) is bid for a decreasing lot of other coins (c2). Bidders decrement the lot of c2 they are willing to receive for the fixed amount of c1. As a concrete example, reverse auctions are used to raise a certain amount of USDX stable coins in exchange for decreasing lots of KAVA governance tokens. The USDX tokens are used to recapitalize the cdp system and the winner receives KAVA.
* **Forward Reverse Auction:** An two phase auction is which a fixed lot of coins (c1) is sold for increasing amounts of other coins (c2). Bidders increment the amount of c2 until a specific `maxBid` is reached. Once `maxBid` is reached, a fixed amount of c2 is bid for a decreasing lot of c1. In the second phase, bidders decrement the lot of c1 they are willing to receive for a fixed amount of c2. As a concrete example. forward reverse auctions are used to sell collateral (ATOM, for example) for up to a `maxBid` amount of USDX. The USDX tokens are used to recapitalize the cdp system and the winner receives the specified lot of ATOM. In the event that the winning lot is smaller than the total lot, the excess ATOM is ratably returned to the original owners of the liquidated CDPs that were collateralized with that ATOM.
Auctions are always initiated by another module, and not directly by users. Auctions start with an expiry, the time at which the auction is guaranteed to end, even if there have been no bidders. After each bid, the auction is extended by a specific amount of time, `BidDuration`. In the case that increasing the auction time by `BidDuration` would cause the auction to go past its expiry, the expiry is chosen as the ending time.

View File

@ -0,0 +1,76 @@
<!--
order: 2
-->
# State
## Parameters and genesis state
`Paramaters` define the rules according to which auctions are run. There is only one active parameter set at any given time. Updates to the parameter set can be made via on-chain parameter update proposals.
```go
// Params governance parameters for auction module
type Params struct {
MaxAuctionDuration time.Duration `json:"max_auction_duration" yaml:"max_auction_duration"` // max length of auction
MaxBidDuration time.Duration `json:"max_bid_duration" yaml:"max_bid_duration"` // additional time added to the auction end time after each bid, capped by the expiry.
}
```
`GenesisState` defines the state that must be persisted when the blockchain stops/restarts in order for normal function of the auction module to resume.
```go
// GenesisState - auction state that must be provided at genesis
type GenesisState struct {
NextAuctionID uint64 `json:"next_auction_id" yaml:"next_auction_id"` // auctionID that will be used for the next created auction
Params Params `json:"auction_params" yaml:"auction_params"` // auction params
Auctions Auctions `json:"genesis_auctions" yaml:"genesis_auctions"` // auctions currently in the store
}
```
## Base types
```go
// Auction is an interface to several types of auction.
type Auction interface {
GetID() uint64
WithID(uint64) Auction
GetBidder() sdk.AccAddress
GetBid() sdk.Coin
GetLot() sdk.Coin
GetEndTime() time.Time
}
// BaseAuction type shared by all Auctions
type BaseAuction struct {
ID uint64
Initiator string // Module that starts the auction. Giving away Lot (aka seller in a forward auction). Restricted to being a module account name rather than any account.
Lot sdk.Coin // Amount of coins up being given by initiator (FA - amount for sale by seller, RA - cost of good by buyer (bid))
Bidder sdk.AccAddress // Person who bids in the auction. Receiver of Lot. (aka buyer in forward auction, seller in RA)
Bid sdk.Coin // Amount of coins being given by the bidder (FA - bid, RA - amount being sold)
EndTime time.Time // Auction closing time. Triggers at the end of the block with time ≥ endTime (bids placed in that block are valid) // TODO ensure everything is consistent with this
MaxEndTime time.Time // Maximum closing time. Auctions can close before this but never after.
}
// ForwardAuction type for forward auctions
type ForwardAuction struct {
BaseAuction
}
// ReverseAuction type for reverse auctions
type ReverseAuction struct {
BaseAuction
}
// WeightedAddresses type for storing an address and its associated weight
type WeightedAddresses struct {
Addresses []sdk.AccAddress
Weights []sdk.Int
}
// ForwardReverseAuction type for forward reverse auction
type ForwardReverseAuction struct {
BaseAuction
MaxBid sdk.Coin
LotReturns WeightedAddresses // return addresses to pay out reductions in the lot amount to. Lot is bid down during reverse phase.
}
```

View File

@ -0,0 +1,37 @@
<!--
order: 3
-->
# Messages
## Bidding
Users can bid on auctions using the `MsgPlaceBid` message type. All auction types can be bid on using the same message type.
```go
// MsgPlaceBid is the message type used to place a bid on any type of auction.
type MsgPlaceBid struct {
AuctionID uint64
Bidder sdk.AccAddress
Bid sdk.Coin
Lot sdk.Coin
}
```
**State Modifications:**
* Update bidder if different than previous bidder
* For forward auctions:
* Update Bid Amount
* Return bid coins to previous bidder
* Burn coins equal to the increment in the bid (CurrentBid - PreviousBid)
* For Reverse auctions:
* Update lot amount
* Return bid coins to previous bidder
* For Forward Reverse auctions:
* Return bid coins to previous bidder
* If in forward phase:
* Update bid amount
* If in reverse phase:
* Update lot amount
* Extend auction by `BidDuration`, or `MaxEndTime`

View File

@ -0,0 +1,9 @@
<!--
order: 4
-->
# Events
<!--
TODO: Add events for auction_start, auction_end, auction_bid
-->

View File

@ -0,0 +1,12 @@
<!--
order: 5
-->
# Parameters
The auction module contains the following parameters:
| Key | Type | Example |
| ------------------ | ---------------------- | -----------|
| MaxAuctionDuration | string (time.Duration) | "48h0m0s" |
| MaxBidDuration | string (time.Duration) | "3h0m0s" |

View File

@ -0,0 +1,20 @@
<!--
order: 6
-->
At the beginning of each block, auctions that have reached `EndTime` are closed. The logic to close auctions is as follows:
```go
var expiredAuctions []uint64
k.IterateAuctionsByTime(ctx, ctx.BlockTime(), func(id uint64) bool {
expiredAuctions = append(expiredAuctions, id)
return false
})
for _, id := range expiredAuctions {
err := k.CloseAuction(ctx, id)
if err != nil {
panic(err)
}
}
```

20
x/auction/spec/README.md Normal file
View File

@ -0,0 +1,20 @@
<!--
order: 0
title: Auction Overview
parent:
title: "auction"
-->
# `auction`
<!-- TOC -->
1. **[Concepts](01_concepts.md)**
2. **[State](02_state.md)**
3. **[Messages](03_messages.md)**
4. **[Events](04_events.md)**
5. **[Params](05_params.md)**
6. **[BeginBlock](06_begin_block.md)**
## Abstract
`x/auction` is an implementation of a Cosmos SDK Module that handles the creation, bidding, and payout of 3 distinct auction types. All auction types implement the `Auction` interface. Each auction type is used at different points during the normal functioning of the CDP system.

View File

@ -149,6 +149,7 @@ func NewForwardReverseAuction(seller string, lot sdk.Coin, EndTime time.Time, ma
return auction
}
// WeightedAddresses type for storing an address and its associated weight
type WeightedAddresses struct {
Addresses []sdk.AccAddress
Weights []sdk.Int

View File

@ -4,28 +4,28 @@ import (
"bytes"
)
// GenesisAuctions type for an array of auctions
type GenesisAuctions []Auction
// Auctions type for an array of auctions
type Auctions []Auction
// GenesisState - auction state that must be provided at genesis
type GenesisState struct {
NextAuctionID uint64 `json:"next_auction_id" yaml:"next_auction_id"`
AuctionParams AuctionParams `json:"auction_params" yaml:"auction_params"`
Auctions GenesisAuctions `json:"genesis_auctions" yaml:"genesis_auctions"`
Params Params `json:"auction_params" yaml:"auction_params"`
Auctions Auctions `json:"genesis_auctions" yaml:"genesis_auctions"`
}
// NewGenesisState returns a new genesis state object for auctions module
func NewGenesisState(nextID uint64, ap AuctionParams, ga GenesisAuctions) GenesisState {
func NewGenesisState(nextID uint64, ap Params, ga Auctions) GenesisState {
return GenesisState{
NextAuctionID: nextID,
AuctionParams: ap,
Params: ap,
Auctions: ga,
}
}
// DefaultGenesisState defines default genesis state for auction module
func DefaultGenesisState() GenesisState {
return NewGenesisState(0, DefaultAuctionParams(), GenesisAuctions{})
return NewGenesisState(0, DefaultParams(), Auctions{})
}
// Equal checks whether two GenesisState structs are equivalent
@ -42,7 +42,7 @@ func (data GenesisState) IsEmpty() bool {
// ValidateGenesis validates genesis inputs. Returns error if validation of any input fails.
func ValidateGenesis(data GenesisState) error {
if err := data.AuctionParams.Validate(); err != nil {
if err := data.Params.Validate(); err != nil {
return err
}
return nil

View File

@ -18,30 +18,30 @@ const (
// Parameter keys
var (
// ParamStoreKeyAuctionParams Param store key for auction params
// ParamStoreKeyParams Param store key for auction params
KeyAuctionBidDuration = []byte("MaxBidDuration")
KeyAuctionDuration = []byte("MaxAuctionDuration")
)
var _ subspace.ParamSet = &AuctionParams{}
var _ subspace.ParamSet = &Params{}
// AuctionParams governance parameters for auction module
type AuctionParams struct {
MaxAuctionDuration time.Duration `json:"max_auction_duration" yaml:"max_auction_duration"` // max length of auction, in blocks
MaxBidDuration time.Duration `json:"max_bid_duration" yaml:"max_bid_duration"`
// Params governance parameters for auction module
type Params struct {
MaxAuctionDuration time.Duration `json:"max_auction_duration" yaml:"max_auction_duration"` // max length of auction
MaxBidDuration time.Duration `json:"max_bid_duration" yaml:"max_bid_duration"` // additional time added to the auction end time after each bid, capped by the expiry.
}
// NewAuctionParams creates a new AuctionParams object
func NewAuctionParams(maxAuctionDuration time.Duration, bidDuration time.Duration) AuctionParams {
return AuctionParams{
// NewParams creates a new Params object
func NewParams(maxAuctionDuration time.Duration, bidDuration time.Duration) Params {
return Params{
MaxAuctionDuration: maxAuctionDuration,
MaxBidDuration: bidDuration,
}
}
// DefaultAuctionParams default parameters for auctions
func DefaultAuctionParams() AuctionParams {
return NewAuctionParams(
// DefaultParams default parameters for auctions
func DefaultParams() Params {
return NewParams(
DefaultMaxAuctionDuration,
DefaultBidDuration,
)
@ -49,35 +49,35 @@ func DefaultAuctionParams() AuctionParams {
// ParamKeyTable Key declaration for parameters
func ParamKeyTable() subspace.KeyTable {
return subspace.NewKeyTable().RegisterParamSet(&AuctionParams{})
return subspace.NewKeyTable().RegisterParamSet(&Params{})
}
// ParamSetPairs implements the ParamSet interface and returns all the key/value pairs
// pairs of auth module's parameters.
// nolint
func (ap *AuctionParams) ParamSetPairs() subspace.ParamSetPairs {
func (ap *Params) ParamSetPairs() subspace.ParamSetPairs {
return subspace.ParamSetPairs{
{KeyAuctionBidDuration, &ap.MaxBidDuration},
{KeyAuctionDuration, &ap.MaxAuctionDuration},
}
}
// Equal returns a boolean determining if two AuctionParams types are identical.
func (ap AuctionParams) Equal(ap2 AuctionParams) bool {
// Equal returns a boolean determining if two Params types are identical.
func (ap Params) Equal(ap2 Params) bool {
bz1 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&ap)
bz2 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&ap2)
return bytes.Equal(bz1, bz2)
}
// String implements stringer interface
func (ap AuctionParams) String() string {
func (ap Params) String() string {
return fmt.Sprintf(`Auction Params:
Max Auction Duration: %s
Max Bid Duration: %s`, ap.MaxAuctionDuration, ap.MaxBidDuration)
}
// Validate checks that the parameters have valid values.
func (ap AuctionParams) Validate() error {
func (ap Params) Validate() error {
// TODO check durations are within acceptable limits, if needed
return nil
}