mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 02:07:52 +00:00 
			
		
		
		
	[R4R] Fix pricefeed sims so does not always go to zero (#434)
* Generate pricefeed prices using a random walk at the beginning of sims Co-authored-by: rhuairahrighairigh <ruaridh.odonnell@gmail.com> Co-authored-by: John Maheswaran <john@kava.io> Co-authored-by: Ruaridh <rhuairahrighairidh@users.noreply.github.com> Co-authored-by: John Maheswaran <john@noreply> Co-authored-by: Kevin Davis <karzak@users.noreply.github.com> Co-authored-by: Kevin Davis <kjydavis3@gmail.com> Co-authored-by: Denali Marsh <denali@kava.io>
This commit is contained in:
		
							parent
							
								
									5ae0b76e0c
								
							
						
					
					
						commit
						55747ed0b8
					
				@ -304,7 +304,7 @@ func testAndRunTxs(app *App, config simulation.Config) []simulation.WeightedOper
 | 
				
			|||||||
					})
 | 
										})
 | 
				
			||||||
				return v
 | 
									return v
 | 
				
			||||||
			}(nil),
 | 
								}(nil),
 | 
				
			||||||
			pricefeedsimops.SimulateMsgUpdatePrices(app.pricefeedKeeper),
 | 
								pricefeedsimops.SimulateMsgUpdatePrices(app.pricefeedKeeper, config.NumBlocks),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			func(_ *rand.Rand) int {
 | 
								func(_ *rand.Rand) int {
 | 
				
			||||||
 | 
				
			|||||||
@ -156,7 +156,7 @@ func SimulateMsgCdp(ak auth.AccountKeeper, k cdp.Keeper, pfk pricefeed.Keeper) s
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		// repay debt 25% of the time
 | 
							// repay debt 25% of the time
 | 
				
			||||||
		if hasCoins(acc, randDebtParam.Denom) {
 | 
							if hasCoins(acc, randDebtParam.Denom) {
 | 
				
			||||||
			debt := (existingCDP.Principal.Add(existingCDP.AccumulatedFees)).AmountOf(randDebtParam.Denom)
 | 
								debt := existingCDP.Principal.AmountOf(randDebtParam.Denom)
 | 
				
			||||||
			maxRepay := acc.GetCoins().AmountOf(randDebtParam.Denom)
 | 
								maxRepay := acc.GetCoins().AmountOf(randDebtParam.Denom)
 | 
				
			||||||
			payableDebt := debt.Sub(randDebtParam.DebtFloor)
 | 
								payableDebt := debt.Sub(randDebtParam.DebtFloor)
 | 
				
			||||||
			if maxRepay.GT(payableDebt) {
 | 
								if maxRepay.GT(payableDebt) {
 | 
				
			||||||
 | 
				
			|||||||
@ -12,51 +12,61 @@ import (
 | 
				
			|||||||
	pricefeed "github.com/kava-labs/kava/x/pricefeed/types"
 | 
						pricefeed "github.com/kava-labs/kava/x/pricefeed/types"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						// BaseAssets is a list of collateral asset denoms
 | 
				
			||||||
 | 
						BaseAssets = [3]string{"bnb", "xrp", "btc"}
 | 
				
			||||||
 | 
						QuoteAsset = "usd"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RandomizedGenState generates a random GenesisState for pricefeed
 | 
					// RandomizedGenState generates a random GenesisState for pricefeed
 | 
				
			||||||
func RandomizedGenState(simState *module.SimulationState) {
 | 
					func RandomizedGenState(simState *module.SimulationState) {
 | 
				
			||||||
	// get the params with xrp, btc and bnb to usd
 | 
						pricefeedGenesis := loadPricefeedGenState(simState)
 | 
				
			||||||
	// getPricefeedSimulationParams is defined to return params with xrp:usd, btc:usd, bnb:usd
 | 
					 | 
				
			||||||
	params := getPricefeedSimulationParams()
 | 
					 | 
				
			||||||
	markets := []types.Market{}
 | 
					 | 
				
			||||||
	genPrices := []types.PostedPrice{}
 | 
					 | 
				
			||||||
	// chose one account to be the oracle
 | 
					 | 
				
			||||||
	oracle := simState.Accounts[simulation.RandIntBetween(simState.Rand, 0, len(simState.Accounts))]
 | 
					 | 
				
			||||||
	for _, market := range params.Markets {
 | 
					 | 
				
			||||||
		updatedMarket := types.Market{market.MarketID, market.BaseAsset, market.QuoteAsset, []sdk.AccAddress{oracle.Address}, true}
 | 
					 | 
				
			||||||
		markets = append(markets, updatedMarket)
 | 
					 | 
				
			||||||
		genPrice := types.PostedPrice{market.MarketID, oracle.Address, getInitialPrice(market.MarketID), simState.GenTimestamp.Add(time.Hour * 24)}
 | 
					 | 
				
			||||||
		genPrices = append(genPrices, genPrice)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	params = types.NewParams(markets)
 | 
					 | 
				
			||||||
	pricefeedGenesis := types.NewGenesisState(params, genPrices)
 | 
					 | 
				
			||||||
	fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, codec.MustMarshalJSONIndent(simState.Cdc, pricefeedGenesis))
 | 
						fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, codec.MustMarshalJSONIndent(simState.Cdc, pricefeedGenesis))
 | 
				
			||||||
	simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(pricefeedGenesis)
 | 
						simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(pricefeedGenesis)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getPricefeedSimulationParams returns the params with xrp:usd, btc:usd, bnb:usd
 | 
					// loadPricefeedGenState loads a valid pricefeed gen state
 | 
				
			||||||
func getPricefeedSimulationParams() types.Params {
 | 
					func loadPricefeedGenState(simState *module.SimulationState) pricefeed.GenesisState {
 | 
				
			||||||
	// SET UP THE PRICEFEED GENESIS STATE
 | 
						var markets []pricefeed.Market
 | 
				
			||||||
	pricefeedGenesis := pricefeed.GenesisState{
 | 
						var postedPrices []pricefeed.PostedPrice
 | 
				
			||||||
		Params: pricefeed.Params{
 | 
						for _, denom := range BaseAssets {
 | 
				
			||||||
			Markets: []pricefeed.Market{
 | 
							// Select an account to be the oracle
 | 
				
			||||||
				pricefeed.Market{MarketID: "btc:usd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true},
 | 
							oracle := simState.Accounts[simulation.RandIntBetween(simState.Rand, 0, len(simState.Accounts))]
 | 
				
			||||||
				pricefeed.Market{MarketID: "xrp:usd", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true},
 | 
					
 | 
				
			||||||
				pricefeed.Market{MarketID: "bnb:usd", BaseAsset: "bnb", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true},
 | 
							marketID := fmt.Sprintf("%s:%s", denom, QuoteAsset)
 | 
				
			||||||
			},
 | 
							// Construct market for asset
 | 
				
			||||||
		},
 | 
							market := pricefeed.Market{
 | 
				
			||||||
 | 
								MarketID:   marketID,
 | 
				
			||||||
 | 
								BaseAsset:  denom,
 | 
				
			||||||
 | 
								QuoteAsset: QuoteAsset,
 | 
				
			||||||
 | 
								Oracles:    []sdk.AccAddress{oracle.Address},
 | 
				
			||||||
 | 
								Active:     true,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Construct posted price for asset
 | 
				
			||||||
 | 
							postedPrice := pricefeed.PostedPrice{
 | 
				
			||||||
 | 
								MarketID:      market.MarketID,
 | 
				
			||||||
 | 
								OracleAddress: oracle.Address,
 | 
				
			||||||
 | 
								Price:         getInitialPrice(marketID),
 | 
				
			||||||
 | 
								Expiry:        simState.GenTimestamp.Add(time.Hour * 24),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							markets = append(markets, market)
 | 
				
			||||||
 | 
							postedPrices = append(postedPrices, postedPrice)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return pricefeedGenesis.Params
 | 
						params := pricefeed.NewParams(markets)
 | 
				
			||||||
 | 
						return pricefeed.NewGenesisState(params, postedPrices)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getInitialPrice gets the starting price for each of the base assets
 | 
					// getInitialPrice gets the starting price for each of the base assets
 | 
				
			||||||
func getInitialPrice(marketId string) (price sdk.Dec) {
 | 
					func getInitialPrice(marketID string) (price sdk.Dec) {
 | 
				
			||||||
	switch marketId {
 | 
						switch marketID {
 | 
				
			||||||
	case "btc:usd":
 | 
						case "btc:usd":
 | 
				
			||||||
		return sdk.MustNewDecFromStr("7000")
 | 
							return sdk.MustNewDecFromStr("7000")
 | 
				
			||||||
	case "bnb:usd":
 | 
						case "bnb:usd":
 | 
				
			||||||
		return sdk.MustNewDecFromStr("14")
 | 
							return sdk.MustNewDecFromStr("14")
 | 
				
			||||||
	case "xrp:usd":
 | 
						case "xrp:usd":
 | 
				
			||||||
		return sdk.MustNewDecFromStr("0.2")
 | 
							return sdk.MustNewDecFromStr("0.2")
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return sdk.MustNewDecFromStr("20") // Catch future additional assets
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	panic(fmt.Sprintf("Invalid marketId in getInitialPrice: %s\n", marketId))
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@ package operations
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"math/rand"
 | 
						"math/rand"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/cosmos/cosmos-sdk/baseapp"
 | 
						"github.com/cosmos/cosmos-sdk/baseapp"
 | 
				
			||||||
@ -15,44 +16,54 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	noOpMsg = simulation.NoOpMsg(pricefeed.ModuleName)
 | 
						noOpMsg   = simulation.NoOpMsg(pricefeed.ModuleName)
 | 
				
			||||||
 | 
						btcPrices = []sdk.Dec{}
 | 
				
			||||||
 | 
						bnbPrices = []sdk.Dec{}
 | 
				
			||||||
 | 
						xrpPrices = []sdk.Dec{}
 | 
				
			||||||
 | 
						genPrices sync.Once
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SimulateMsgUpdatePrices updates the prices of various assets by randomly varying them based on current price
 | 
					// SimulateMsgUpdatePrices updates the prices of various assets by randomly varying them based on current price
 | 
				
			||||||
func SimulateMsgUpdatePrices(keeper keeper.Keeper) simulation.Operation {
 | 
					func SimulateMsgUpdatePrices(keeper keeper.Keeper, blocks int) simulation.Operation {
 | 
				
			||||||
	// get a pricefeed handler
 | 
						// get a pricefeed handler
 | 
				
			||||||
	handler := pricefeed.NewHandler(keeper)
 | 
						handler := pricefeed.NewHandler(keeper)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account) (
 | 
						return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account) (
 | 
				
			||||||
		simulation.OperationMsg, []simulation.FutureOperation, error) {
 | 
							simulation.OperationMsg, []simulation.FutureOperation, error) {
 | 
				
			||||||
 | 
							genPrices.Do(func() {
 | 
				
			||||||
 | 
								// generate a random walk for each asset exactly once, with observations equal to the number of blocks in the sim
 | 
				
			||||||
 | 
								for _, m := range keeper.GetMarkets(ctx) {
 | 
				
			||||||
 | 
									startPrice := getStartPrice(m.MarketID)
 | 
				
			||||||
 | 
									// allow prices to fluctuate from 10x GAINZ to 100x REKT
 | 
				
			||||||
 | 
									maxPrice := sdk.MustNewDecFromStr("10.0").Mul(startPrice)
 | 
				
			||||||
 | 
									minPrice := sdk.MustNewDecFromStr("0.01").Mul(startPrice)
 | 
				
			||||||
 | 
									previousPrice := startPrice
 | 
				
			||||||
 | 
									for i := 0; i < blocks; i++ {
 | 
				
			||||||
 | 
										increment := getIncrement(m.MarketID)
 | 
				
			||||||
 | 
										// note calling r instead of rand here breaks determinism
 | 
				
			||||||
 | 
										upDown := rand.Intn(2)
 | 
				
			||||||
 | 
										if upDown == 0 {
 | 
				
			||||||
 | 
											if previousPrice.Add(increment).GT(maxPrice) {
 | 
				
			||||||
 | 
												previousPrice = maxPrice
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												previousPrice = previousPrice.Add(increment)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											if previousPrice.Sub(increment).LT(minPrice) {
 | 
				
			||||||
 | 
												previousPrice = minPrice
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												previousPrice = previousPrice.Sub(increment)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										setPrice(m.MarketID, previousPrice)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// OVERALL LOGIC:
 | 
					 | 
				
			||||||
		// (1) RANDOMLY PICK AN ASSET OUT OF BNB AN BTC [TODO QUESTION - USDX IS EXCLUDED AS IT IS A STABLE DENOM
 | 
					 | 
				
			||||||
		// (2) GET THE CURRENT PRICE OF THAT ASSET IN USD
 | 
					 | 
				
			||||||
		// (3) GENERATE A RANDOM NUMBER IN THE RANGE 0.8-1.2 (UNIFORM DISTRIBUTION)
 | 
					 | 
				
			||||||
		// (4) MULTIPLY THE CURRENT PRICE BY THE RANDOM NUMBER
 | 
					 | 
				
			||||||
		// (5) POST THE NEW PRICE TO THE KEEPER
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// pick a random asset out of BNB and BTC
 | 
					 | 
				
			||||||
		randomMarket := pickRandomAsset(ctx, keeper, r)
 | 
							randomMarket := pickRandomAsset(ctx, keeper, r)
 | 
				
			||||||
 | 
					 | 
				
			||||||
		marketID := randomMarket.MarketID
 | 
							marketID := randomMarket.MarketID
 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Get the current price of the asset
 | 
					 | 
				
			||||||
		currentPrice, err := keeper.GetCurrentPrice(ctx, marketID) //  Note this is marketID AND **NOT** just the base asset
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return noOpMsg, nil, fmt.Errorf("Error getting current price")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// get the address for the account
 | 
					 | 
				
			||||||
		// this address needs to be an oracle and also exist. genesis should add all the accounts as oracles.
 | 
					 | 
				
			||||||
		address := getRandomOracle(r, randomMarket)
 | 
							address := getRandomOracle(r, randomMarket)
 | 
				
			||||||
 | 
							price := pickNewRandomPrice(marketID, int(ctx.BlockHeight()))
 | 
				
			||||||
		// generate a new random price based off the current price
 | 
					 | 
				
			||||||
		price, err := pickNewRandomPrice(r, currentPrice.Price)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return noOpMsg, nil, fmt.Errorf("Error picking random price")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// get the expiry time based off the current time
 | 
							// get the expiry time based off the current time
 | 
				
			||||||
		expiry := getExpiryTime(ctx)
 | 
							expiry := getExpiryTime(ctx)
 | 
				
			||||||
@ -73,6 +84,51 @@ func SimulateMsgUpdatePrices(keeper keeper.Keeper) simulation.Operation {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getStartPrice(marketID string) (startPrice sdk.Dec) {
 | 
				
			||||||
 | 
						switch marketID {
 | 
				
			||||||
 | 
						case "btc:usd":
 | 
				
			||||||
 | 
							return sdk.MustNewDecFromStr("7000")
 | 
				
			||||||
 | 
						case "bnb:usd":
 | 
				
			||||||
 | 
							return sdk.MustNewDecFromStr("15")
 | 
				
			||||||
 | 
						case "xrp:usd":
 | 
				
			||||||
 | 
							return sdk.MustNewDecFromStr("0.25")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return sdk.MustNewDecFromStr("100")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getIncrement(marketID string) (increment sdk.Dec) {
 | 
				
			||||||
 | 
						startPrice := getStartPrice(marketID)
 | 
				
			||||||
 | 
						divisor := sdk.MustNewDecFromStr("20")
 | 
				
			||||||
 | 
						increment = startPrice.Quo(divisor)
 | 
				
			||||||
 | 
						return increment
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func setPrice(marketID string, price sdk.Dec) {
 | 
				
			||||||
 | 
						switch marketID {
 | 
				
			||||||
 | 
						case "btc:usd":
 | 
				
			||||||
 | 
							btcPrices = append(btcPrices, price)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						case "bnb:usd":
 | 
				
			||||||
 | 
							bnbPrices = append(bnbPrices, price)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						case "xrp:usd":
 | 
				
			||||||
 | 
							xrpPrices = append(xrpPrices, price)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func pickNewRandomPrice(marketID string, blockHeight int) (newPrice sdk.Dec) {
 | 
				
			||||||
 | 
						switch marketID {
 | 
				
			||||||
 | 
						case "btc:usd":
 | 
				
			||||||
 | 
							return btcPrices[blockHeight-1]
 | 
				
			||||||
 | 
						case "bnb:usd":
 | 
				
			||||||
 | 
							return bnbPrices[blockHeight-1]
 | 
				
			||||||
 | 
						case "xrp:usd":
 | 
				
			||||||
 | 
							return xrpPrices[blockHeight-1]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						panic("invalid price request")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getRandomOracle picks a random oracle from the list of oracles
 | 
					// getRandomOracle picks a random oracle from the list of oracles
 | 
				
			||||||
func getRandomOracle(r *rand.Rand, market pricefeed.Market) sdk.AccAddress {
 | 
					func getRandomOracle(r *rand.Rand, market pricefeed.Market) sdk.AccAddress {
 | 
				
			||||||
	randomIndex := simulation.RandIntBetween(r, 0, len(market.Oracles))
 | 
						randomIndex := simulation.RandIntBetween(r, 0, len(market.Oracles))
 | 
				
			||||||
@ -98,31 +154,6 @@ func getExpiryTime(ctx sdk.Context) (t time.Time) {
 | 
				
			|||||||
	return t
 | 
						return t
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// pickNewRandomPrice picks a new random price given the current price
 | 
					 | 
				
			||||||
// It takes the current price then generates a random number to multiply it by to create variation while
 | 
					 | 
				
			||||||
// still being in the similar range. Random walk style.
 | 
					 | 
				
			||||||
func pickNewRandomPrice(r *rand.Rand, currentPrice sdk.Dec) (price sdk.Dec, err sdk.Error) {
 | 
					 | 
				
			||||||
	// Pick random price
 | 
					 | 
				
			||||||
	// this is in the range [0-0.4) because when added to 0.8 it gives a multiplier in the range 0.8-1.2
 | 
					 | 
				
			||||||
	got := sdk.MustNewDecFromStr("0.4")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	randomPriceMultiplier := simulation.RandomDecAmount(r, got) // get a random number
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Errorf("Error generating random price multiplier\n")
 | 
					 | 
				
			||||||
		return sdk.ZeroDec(), err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// 0.8 offset corresponds to 80% of the the current price
 | 
					 | 
				
			||||||
	offset := sdk.MustNewDecFromStr("0.8")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// gives a result in range 0.8-1.2 inclusive, so the price can fluctuate from 80% to 120% of its current value
 | 
					 | 
				
			||||||
	randomPriceMultiplier = randomPriceMultiplier.Add(offset)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// multiply the current price by the price multiplier
 | 
					 | 
				
			||||||
	price = randomPriceMultiplier.Mul(currentPrice)
 | 
					 | 
				
			||||||
	// return the price
 | 
					 | 
				
			||||||
	return price, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// submitMsg submits a message to the current instance of the keeper and returns a boolean whether the operation completed successfully or not
 | 
					// submitMsg submits a message to the current instance of the keeper and returns a boolean whether the operation completed successfully or not
 | 
				
			||||||
func submitMsg(ctx sdk.Context, handler sdk.Handler, msg sdk.Msg) (ok bool) {
 | 
					func submitMsg(ctx sdk.Context, handler sdk.Handler, msg sdk.Msg) (ok bool) {
 | 
				
			||||||
	ctx, write := ctx.CacheContext()
 | 
						ctx, write := ctx.CacheContext()
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user