mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-23 23:05:18 +00:00
feat: add pricefeed spec
This commit is contained in:
parent
8ef03e4181
commit
c6d287a5b3
@ -9,15 +9,15 @@ import (
|
||||
// EndBlocker updates the current pricefeed
|
||||
func EndBlocker(ctx sdk.Context, k Keeper) {
|
||||
// Update the current price of each asset.
|
||||
for _, a := range k.GetMarkets(ctx) {
|
||||
if a.Active {
|
||||
err := k.SetCurrentPrices(ctx, a.MarketID)
|
||||
for _, market := range k.GetMarkets(ctx) {
|
||||
if market.Active {
|
||||
err := k.SetCurrentPrices(ctx, market.MarketID)
|
||||
if err != nil {
|
||||
// In the event of failure, emit an event.
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
EventTypeNoValidPrices,
|
||||
sdk.NewAttribute(AttributeKeyPriceUpdateFailed, fmt.Sprintf("%s", a.MarketID)),
|
||||
sdk.NewAttribute(AttributeMarketID, fmt.Sprintf("%s", market.MarketID)),
|
||||
),
|
||||
)
|
||||
continue
|
||||
|
@ -12,26 +12,25 @@ import (
|
||||
|
||||
// nolint
|
||||
const (
|
||||
EventTypeMarketPriceUpdated = types.EventTypeMarketPriceUpdated
|
||||
EventTypeOracleUpdatedPrice = types.EventTypeOracleUpdatedPrice
|
||||
EventTypeNoValidPrices = types.EventTypeNoValidPrices
|
||||
AttributeValueCategory = types.AttributeValueCategory
|
||||
AttributeMarketID = types.AttributeMarketID
|
||||
AttributeMarketPrice = types.AttributeMarketPrice
|
||||
AttributeOracle = types.AttributeOracle
|
||||
AttributeExpiry = types.AttributeExpiry
|
||||
AttributeKeyPriceUpdateFailed = types.AttributeKeyPriceUpdateFailed
|
||||
ModuleName = types.ModuleName
|
||||
StoreKey = types.StoreKey
|
||||
RouterKey = types.RouterKey
|
||||
QuerierRoute = types.QuerierRoute
|
||||
DefaultParamspace = types.DefaultParamspace
|
||||
TypeMsgPostPrice = types.TypeMsgPostPrice
|
||||
QueryGetParams = types.QueryGetParams
|
||||
QueryMarkets = types.QueryMarkets
|
||||
QueryOracles = types.QueryOracles
|
||||
QueryRawPrices = types.QueryRawPrices
|
||||
QueryPrice = types.QueryPrice
|
||||
EventTypeMarketPriceUpdated = types.EventTypeMarketPriceUpdated
|
||||
EventTypeOracleUpdatedPrice = types.EventTypeOracleUpdatedPrice
|
||||
EventTypeNoValidPrices = types.EventTypeNoValidPrices
|
||||
AttributeValueCategory = types.AttributeValueCategory
|
||||
AttributeMarketID = types.AttributeMarketID
|
||||
AttributeMarketPrice = types.AttributeMarketPrice
|
||||
AttributeOracle = types.AttributeOracle
|
||||
AttributeExpiry = types.AttributeExpiry
|
||||
ModuleName = types.ModuleName
|
||||
StoreKey = types.StoreKey
|
||||
RouterKey = types.RouterKey
|
||||
QuerierRoute = types.QuerierRoute
|
||||
DefaultParamspace = types.DefaultParamspace
|
||||
TypeMsgPostPrice = types.TypeMsgPostPrice
|
||||
QueryGetParams = types.QueryGetParams
|
||||
QueryMarkets = types.QueryMarkets
|
||||
QueryOracles = types.QueryOracles
|
||||
QueryRawPrices = types.QueryRawPrices
|
||||
QueryPrice = types.QueryPrice
|
||||
)
|
||||
|
||||
// nolint
|
||||
|
3
x/pricefeed/spec/01_concepts.md
Normal file
3
x/pricefeed/spec/01_concepts.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Concepts
|
||||
|
||||
Prices can be posted by any account which is added as an oracle. Oracles are specific to each market and can be updated via param change proposals. When an oracle posts a price, they submit a message to the blockchain that contains the current price for that market and a time when that price should be considered expired. If an oracle posts a new price, that price becomes the current price for that oracle, regardless of the previous price's expiry. A group of prices posted by a set of oracles for a particular market are referred to as 'raw prices' and the current median price of all valid oracle prices is referred to as the 'current price'. Each block, the current price for each market is determined by calculating the median of the raw prices.
|
44
x/pricefeed/spec/02_state.md
Normal file
44
x/pricefeed/spec/02_state.md
Normal file
@ -0,0 +1,44 @@
|
||||
# State
|
||||
|
||||
## Parameters and genesis state
|
||||
|
||||
`Paramaters` determine which markets are tracked by the pricefeed and which oracles are authorized to post prices for a given market. There is only one active parameter set at any given time. Updates to parameters can be made via on-chain parameter update proposals.
|
||||
|
||||
```go
|
||||
// Params params for pricefeed. Can be altered via governance
|
||||
type Params struct {
|
||||
Markets Markets `json:"markets" yaml:"markets"` // Array containing the markets supported by the pricefeed
|
||||
}
|
||||
|
||||
// Market an asset in the pricefeed
|
||||
type Market struct {
|
||||
MarketID string `json:"market_id" yaml:"market_id"`
|
||||
BaseAsset string `json:"base_asset" yaml:"base_asset"`
|
||||
QuoteAsset string `json:"quote_asset" yaml:"quote_asset"`
|
||||
Oracles []sdk.AccAddress `json:"oracles" yaml:"oracles"`
|
||||
Active bool `json:"active" yaml:"active"`
|
||||
}
|
||||
|
||||
type Markets []Market
|
||||
```
|
||||
|
||||
`GenesisState` defines the state that must be persisted when the blockchain stops/stars in order for the normal function of the pricefeed to resume.
|
||||
|
||||
```go
|
||||
// GenesisState - pricefeed state that must be provided at genesis
|
||||
type GenesisState struct {
|
||||
Params Params `json:"params" yaml:"params"`
|
||||
PostedPrices []PostedPrice `json:"posted_prices" yaml:"posted_prices"`
|
||||
}
|
||||
|
||||
// PostedPrice price for market posted by a specific oracle
|
||||
type PostedPrice struct {
|
||||
MarketID string `json:"market_id" yaml:"market_id"`
|
||||
OracleAddress sdk.AccAddress `json:"oracle_address" yaml:"oracle_address"`
|
||||
Price sdk.Dec `json:"price" yaml:"price"`
|
||||
Expiry time.Time `json:"expiry" yaml:"expiry"`
|
||||
}
|
||||
|
||||
type PostedPrices []PostedPrice
|
||||
```
|
||||
|
20
x/pricefeed/spec/03_messages.md
Normal file
20
x/pricefeed/spec/03_messages.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Messages
|
||||
|
||||
## Posting Prices
|
||||
|
||||
An authorized oraclef for a particular market can post the current price for that market using the `MsgPostPrice` type.
|
||||
|
||||
```go
|
||||
// MsgPostPrice struct representing a posted price message.
|
||||
// Used by oracles to input prices to the pricefeed
|
||||
type MsgPostPrice struct {
|
||||
From sdk.AccAddress `json:"from" yaml:"from"` // client that sent in this address
|
||||
MarketID string `json:"market_id" yaml:"market_id"` // asset code used by exchanges/api
|
||||
Price sdk.Dec `json:"price" yaml:"price"` // price in decimal (max precision 18)
|
||||
Expiry time.Time `json:"expiry" yaml:"expiry"` // expiry time
|
||||
}
|
||||
```
|
||||
|
||||
### State Modifications
|
||||
|
||||
* Update the raw price for the oracle for this market. This replaces any previous price for that oracle.
|
22
x/pricefeed/spec/04_events.md
Normal file
22
x/pricefeed/spec/04_events.md
Normal file
@ -0,0 +1,22 @@
|
||||
# Events
|
||||
|
||||
The `x/pricefeed` module emits the following events:
|
||||
|
||||
## MsgPostPrice
|
||||
|
||||
| Type | Attribute Key | Attribute Value |
|
||||
|----------------------|---------------|------------------|
|
||||
| oracle_updated_price | market_id | {market ID} |
|
||||
| oracle_updated_price | oracle | {oracle} |
|
||||
| oracle_updated_price | market_price | {price} |
|
||||
| oracle_updated_price | expiry | {expiry} |
|
||||
| message | module | pricefeed |
|
||||
| message | sender | {sender address} |
|
||||
|
||||
## BeginBlock
|
||||
|
||||
| Type | Attribute Key | Attribute Value |
|
||||
|----------------------|-----------------|-----------------|
|
||||
| market_price_updated | market_id | {market ID} |
|
||||
| market_price_updated | market_price | {price} |
|
||||
| no_valid_prices | market_id | {market ID} |
|
17
x/pricefeed/spec/05_params.md
Normal file
17
x/pricefeed/spec/05_params.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Parameters
|
||||
|
||||
The pricefeed module has the following parameters:
|
||||
|
||||
| Key | Type | Example | Description |
|
||||
|------------|----------------|---------------|--------------------------------------------------|
|
||||
| Markets | array (Market) | [{see below}] | array of params for each market in the pricefeed |
|
||||
|
||||
Each `Market` has the following parameters
|
||||
|
||||
| Key | Type | Example | Description |
|
||||
|------------|--------------------|--------------------------|----------------------------------------------------------------|
|
||||
| MarketID | string | "bnb:usd" | identifier for the market -- **must** be unique across markets |
|
||||
| BaseAsset | string | "bnb" | the base asset for the market pair |
|
||||
| QuoteAsset | string | "usd" | the quote asset for the market pair |
|
||||
| Oracles | array (AccAddress) | ["kava1...", "kava1..."] | addresses which can post prices for the market |
|
||||
| Active | bool | true | flag to disable oracle interactions with the module |
|
26
x/pricefeed/spec/06_begin_block.md
Normal file
26
x/pricefeed/spec/06_begin_block.md
Normal file
@ -0,0 +1,26 @@
|
||||
# Begin Block
|
||||
|
||||
At the start of each block, the current price is calculated as the median of all raw prices for each market. The logic is as follows:
|
||||
|
||||
```go
|
||||
// EndBlocker updates the current pricefeed
|
||||
func EndBlocker(ctx sdk.Context, k Keeper) {
|
||||
// Update the current price of each asset.
|
||||
for _, market := range k.GetMarkets(ctx) {
|
||||
if market.Active {
|
||||
err := k.SetCurrentPrices(ctx, market.MarketID)
|
||||
if err != nil {
|
||||
// In the event of failure, emit an event.
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
EventTypeNoValidPrices,
|
||||
sdk.NewAttribute(AttributeMarketID, fmt.Sprintf("%s", market.MarketID)),
|
||||
),
|
||||
)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
```
|
13
x/pricefeed/spec/README.md
Normal file
13
x/pricefeed/spec/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# `pricefeed`
|
||||
|
||||
<!-- 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/pricefeed` is an implementation of a Cosmos SDK Module that handles the posting of prices for various markets by a group of whitelisted oracles. At the beginning of each block, the median price of all oracle posted prices is determined for each market and stored.
|
@ -6,10 +6,9 @@ const (
|
||||
EventTypeOracleUpdatedPrice = "oracle_updated_price"
|
||||
EventTypeNoValidPrices = "no_valid_prices"
|
||||
|
||||
AttributeValueCategory = ModuleName
|
||||
AttributeMarketID = "market_id"
|
||||
AttributeMarketPrice = "market_price"
|
||||
AttributeOracle = "oracle"
|
||||
AttributeExpiry = "expiry"
|
||||
AttributeKeyPriceUpdateFailed = "price_update_failed"
|
||||
AttributeValueCategory = ModuleName
|
||||
AttributeMarketID = "market_id"
|
||||
AttributeMarketPrice = "market_price"
|
||||
AttributeOracle = "oracle"
|
||||
AttributeExpiry = "expiry"
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user