Merge branch 'develop' into cwgoes/check-supply-in-simulation
This commit is contained in:
commit
22cb6983b7
|
@ -83,6 +83,8 @@ BREAKING CHANGES
|
|||
* [x/stake] \#2500 Block conflicting redelegations until we add an index
|
||||
* [x/params] Global Paramstore refactored
|
||||
* [x/stake] \#2508 Utilize Tendermint power for validator power key
|
||||
* [x/stake] \#2531 Remove all inflation logic
|
||||
* [x/mint] \#2531 Add minting module and inflation logic
|
||||
|
||||
* Tendermint
|
||||
* Update tendermint version from v0.23.0 to v0.25.0, notable changes
|
||||
|
|
|
@ -480,11 +480,7 @@ func TestPoolParamsQuery(t *testing.T) {
|
|||
var pool stake.Pool
|
||||
err = cdc.UnmarshalJSON([]byte(body), &pool)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, initialPool.DateLastCommissionReset, pool.DateLastCommissionReset)
|
||||
require.Equal(t, initialPool.PrevBondedShares, pool.PrevBondedShares)
|
||||
require.Equal(t, initialPool.BondedTokens, pool.BondedTokens)
|
||||
require.Equal(t, initialPool.NextInflation(params), pool.Inflation)
|
||||
initialPool = initialPool.ProcessProvisions(params) // provisions are added to the pool every hour
|
||||
require.Equal(t, initialPool.LooseTokens, pool.LooseTokens)
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
distr "github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
|
@ -46,6 +47,7 @@ type GaiaApp struct {
|
|||
keyStake *sdk.KVStoreKey
|
||||
tkeyStake *sdk.TransientStoreKey
|
||||
keySlashing *sdk.KVStoreKey
|
||||
keyMint *sdk.KVStoreKey
|
||||
keyDistr *sdk.KVStoreKey
|
||||
tkeyDistr *sdk.TransientStoreKey
|
||||
keyGov *sdk.KVStoreKey
|
||||
|
@ -59,6 +61,7 @@ type GaiaApp struct {
|
|||
bankKeeper bank.Keeper
|
||||
stakeKeeper stake.Keeper
|
||||
slashingKeeper slashing.Keeper
|
||||
mintKeeper mint.Keeper
|
||||
distrKeeper distr.Keeper
|
||||
govKeeper gov.Keeper
|
||||
paramsKeeper params.Keeper
|
||||
|
@ -78,6 +81,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
|||
keyAccount: sdk.NewKVStoreKey("acc"),
|
||||
keyStake: sdk.NewKVStoreKey("stake"),
|
||||
tkeyStake: sdk.NewTransientStoreKey("transient_stake"),
|
||||
keyMint: sdk.NewKVStoreKey("mint"),
|
||||
keyDistr: sdk.NewKVStoreKey("distr"),
|
||||
tkeyDistr: sdk.NewTransientStoreKey("transient_distr"),
|
||||
keySlashing: sdk.NewKVStoreKey("slashing"),
|
||||
|
@ -110,6 +114,10 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
|||
app.bankKeeper, app.paramsKeeper.Subspace(stake.DefaultParamspace),
|
||||
app.RegisterCodespace(stake.DefaultCodespace),
|
||||
)
|
||||
app.mintKeeper = mint.NewKeeper(app.cdc, app.keyMint,
|
||||
app.paramsKeeper.Subspace(mint.DefaultParamspace),
|
||||
app.stakeKeeper, app.feeCollectionKeeper,
|
||||
)
|
||||
app.distrKeeper = distr.NewKeeper(
|
||||
app.cdc,
|
||||
app.keyDistr,
|
||||
|
@ -147,11 +155,11 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
|||
AddRoute("stake", stake.NewQuerier(app.stakeKeeper, app.cdc))
|
||||
|
||||
// initialize BaseApp
|
||||
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyStake, app.keyMint, app.keyDistr,
|
||||
app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams)
|
||||
app.SetInitChainer(app.initChainer)
|
||||
app.SetBeginBlocker(app.BeginBlocker)
|
||||
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
|
||||
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyStake, app.keyDistr,
|
||||
app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams)
|
||||
app.MountStoresTransient(app.tkeyParams, app.tkeyStake, app.tkeyDistr)
|
||||
app.SetEndBlocker(app.EndBlocker)
|
||||
|
||||
|
@ -184,6 +192,9 @@ func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) ab
|
|||
// distribute rewards from previous block
|
||||
distr.BeginBlocker(ctx, req, app.distrKeeper)
|
||||
|
||||
// mint new tokens for this new block
|
||||
mint.BeginBlocker(ctx, app.mintKeeper)
|
||||
|
||||
return abci.ResponseBeginBlock{
|
||||
Tags: tags.ToKVPairs(),
|
||||
}
|
||||
|
@ -232,8 +243,8 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
|
|||
|
||||
// load the address to pubkey map
|
||||
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakeData)
|
||||
|
||||
gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData)
|
||||
mint.InitGenesis(ctx, app.mintKeeper, genesisState.MintData)
|
||||
distr.InitGenesis(ctx, app.distrKeeper, genesisState.DistrData)
|
||||
err = GaiaValidateGenesisState(genesisState)
|
||||
if err != nil {
|
||||
|
@ -289,13 +300,14 @@ func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, val
|
|||
return false
|
||||
}
|
||||
app.accountMapper.IterateAccounts(ctx, appendAccount)
|
||||
|
||||
genState := GenesisState{
|
||||
Accounts: accounts,
|
||||
StakeData: stake.WriteGenesis(ctx, app.stakeKeeper),
|
||||
DistrData: distr.WriteGenesis(ctx, app.distrKeeper),
|
||||
GovData: gov.WriteGenesis(ctx, app.govKeeper),
|
||||
}
|
||||
genState := NewGenesisState(
|
||||
accounts,
|
||||
stake.WriteGenesis(ctx, app.stakeKeeper),
|
||||
mint.WriteGenesis(ctx, app.mintKeeper),
|
||||
distr.WriteGenesis(ctx, app.distrKeeper),
|
||||
gov.WriteGenesis(ctx, app.govKeeper),
|
||||
slashing.GenesisState{}, // TODO create write methods
|
||||
)
|
||||
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
distr "github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
@ -31,12 +32,26 @@ var (
|
|||
type GenesisState struct {
|
||||
Accounts []GenesisAccount `json:"accounts"`
|
||||
StakeData stake.GenesisState `json:"stake"`
|
||||
MintData mint.GenesisState `json:"mint"`
|
||||
DistrData distr.GenesisState `json:"distr"`
|
||||
GovData gov.GenesisState `json:"gov"`
|
||||
SlashingData slashing.GenesisState `json:"slashing"`
|
||||
GenTxs []json.RawMessage `json:"gentxs"`
|
||||
}
|
||||
|
||||
func NewGenesisState(accounts []GenesisAccount, stakeData stake.GenesisState, mintData mint.GenesisState,
|
||||
distrData distr.GenesisState, govData gov.GenesisState, slashingData slashing.GenesisState) GenesisState {
|
||||
|
||||
return GenesisState{
|
||||
Accounts: accounts,
|
||||
StakeData: stakeData,
|
||||
MintData: mintData,
|
||||
DistrData: distrData,
|
||||
GovData: govData,
|
||||
SlashingData: slashingData,
|
||||
}
|
||||
}
|
||||
|
||||
// GenesisAccount doesn't need pubkey or sequence
|
||||
type GenesisAccount struct {
|
||||
Address sdk.AccAddress `json:"address"`
|
||||
|
@ -110,6 +125,7 @@ func GaiaAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (genesisStat
|
|||
genesisState = GenesisState{
|
||||
Accounts: genaccs,
|
||||
StakeData: stakeData,
|
||||
MintData: mint.DefaultGenesisState(),
|
||||
DistrData: distr.DefaultGenesisState(),
|
||||
GovData: gov.DefaultGenesisState(),
|
||||
SlashingData: slashingData,
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
distributionsim "github.com/cosmos/cosmos-sdk/x/distribution/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint"
|
||||
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation"
|
||||
|
@ -81,13 +82,16 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
|||
stakeGenesis.Pool.LooseTokens = sdk.NewDec(int64(100*250) + (numInitiallyBonded * 100))
|
||||
stakeGenesis.Validators = validators
|
||||
stakeGenesis.Bonds = delegations
|
||||
|
||||
// No inflation, for now
|
||||
stakeGenesis.Params.InflationMax = sdk.NewDec(0)
|
||||
stakeGenesis.Params.InflationMin = sdk.NewDec(0)
|
||||
mintGenesis := mint.DefaultGenesisState()
|
||||
mintGenesis.Params.InflationMax = sdk.NewDec(0)
|
||||
mintGenesis.Params.InflationMin = sdk.NewDec(0)
|
||||
|
||||
genesis := GenesisState{
|
||||
Accounts: genesisAccounts,
|
||||
StakeData: stakeGenesis,
|
||||
MintData: mintGenesis,
|
||||
DistrData: distr.DefaultGenesisWithValidators(valAddrs),
|
||||
SlashingData: slashingGenesis,
|
||||
GovData: govGenesis,
|
||||
|
|
|
@ -231,7 +231,6 @@ func TestGaiaCLICreateValidator(t *testing.T) {
|
|||
defaultParams := stake.DefaultParams()
|
||||
initialPool := stake.InitialPool()
|
||||
initialPool.BondedTokens = initialPool.BondedTokens.Add(sdk.NewDec(100)) // Delegate tx on GaiaAppGenState
|
||||
initialPool = initialPool.ProcessProvisions(defaultParams) // provisions are added to the pool every hour
|
||||
|
||||
// create validator
|
||||
cvStr := fmt.Sprintf("gaiacli tx create-validator %v", flags)
|
||||
|
@ -290,8 +289,6 @@ func TestGaiaCLICreateValidator(t *testing.T) {
|
|||
require.True(t, defaultParams.Equal(params))
|
||||
|
||||
pool := executeGetPool(t, fmt.Sprintf("gaiacli query pool --output=json %v", flags))
|
||||
require.Equal(t, initialPool.DateLastCommissionReset, pool.DateLastCommissionReset)
|
||||
require.Equal(t, initialPool.PrevBondedShares, pool.PrevBondedShares)
|
||||
require.Equal(t, initialPool.BondedTokens, pool.BondedTokens)
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ pool which validator holds individually
|
|||
(`ValidatorDistribution.ProvisionsRewardPool`).
|
||||
|
||||
```
|
||||
func AllocateFees(feesCollected sdk.Coins, feePool FeePool, proposer ValidatorDistribution,
|
||||
func AllocateTokens(feesCollected sdk.Coins, feePool FeePool, proposer ValidatorDistribution,
|
||||
sumPowerPrecommitValidators, totalBondedTokens, communityTax,
|
||||
proposerCommissionRate sdk.Dec)
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# Begin-Block
|
||||
|
||||
## Inflation
|
||||
|
||||
Inflation occurs at the beginning of each block.
|
||||
|
||||
### NextInflation
|
||||
|
||||
The target annual inflation rate is recalculated for each provisions cycle. The
|
||||
inflation is also subject to a rate change (positive or negative) depending on
|
||||
the distance from the desired ratio (67%). The maximum rate change possible is
|
||||
defined to be 13% per year, however the annual inflation is capped as between
|
||||
7% and 20%.
|
||||
|
||||
NextInflation(params Params, bondedRatio sdk.Dec) (inflation sdk.Dec) {
|
||||
inflationRateChangePerYear = (1 - bondedRatio/params.GoalBonded) * params.InflationRateChange
|
||||
inflationRateChange = inflationRateChangePerYear/hrsPerYr
|
||||
|
||||
// increase the new annual inflation for this next cycle
|
||||
inflation += inflationRateChange
|
||||
if inflation > params.InflationMax {
|
||||
inflation = params.InflationMax
|
||||
}
|
||||
if inflation < params.InflationMin {
|
||||
inflation = params.InflationMin
|
||||
}
|
||||
|
||||
return inflation
|
|
@ -0,0 +1,31 @@
|
|||
## State
|
||||
|
||||
### Minter
|
||||
|
||||
The minter is a space for holding current inflation information.
|
||||
|
||||
- Minter: `0x00 -> amino(minter)`
|
||||
|
||||
```golang
|
||||
type Minter struct {
|
||||
InflationLastTime time.Time // block time which the last inflation was processed
|
||||
Inflation sdk.Dec // current annual inflation rate
|
||||
}
|
||||
```
|
||||
|
||||
### Params
|
||||
|
||||
Minting params are held in the global params store.
|
||||
|
||||
- Params: `mint/params -> amino(params)`
|
||||
|
||||
```golang
|
||||
type Params struct {
|
||||
MintDenom string // type of coin to mint
|
||||
InflationRateChange sdk.Dec // maximum annual change in inflation rate
|
||||
InflationMax sdk.Dec // maximum inflation rate
|
||||
InflationMin sdk.Dec // minimum inflation rate
|
||||
GoalBonded sdk.Dec // goal of percent bonded atoms
|
||||
}
|
||||
```
|
||||
|
|
@ -12,10 +12,6 @@ inflation information, etc.
|
|||
type Pool struct {
|
||||
LooseTokens int64 // tokens not associated with any bonded validator
|
||||
BondedTokens int64 // reserve of bonded tokens
|
||||
InflationLastTime int64 // block which the last inflation was processed // TODO make time
|
||||
Inflation sdk.Dec // current annual inflation rate
|
||||
|
||||
DateLastCommissionReset int64 // unix timestamp for last commission accounting reset (daily)
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -28,11 +24,6 @@ overall functioning of the stake module.
|
|||
|
||||
```golang
|
||||
type Params struct {
|
||||
InflationRateChange sdk.Dec // maximum annual change in inflation rate
|
||||
InflationMax sdk.Dec // maximum inflation rate
|
||||
InflationMin sdk.Dec // minimum inflation rate
|
||||
GoalBonded sdk.Dec // Goal of percent bonded atoms
|
||||
|
||||
MaxValidators uint16 // maximum number of validators
|
||||
BondDenom string // bondable coin denomination
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ func (fck FeeCollectionKeeper) setCollectedFees(ctx sdk.Context, coins sdk.Coins
|
|||
store.Set(collectedFeesKey, bz)
|
||||
}
|
||||
|
||||
// add collected fees (mostly exposed for simulation...)
|
||||
// add to the fee pool
|
||||
func (fck FeeCollectionKeeper) AddCollectedFees(ctx sdk.Context, coins sdk.Coins) sdk.Coins {
|
||||
newCoins := fck.GetCollectedFees(ctx).Plus(coins)
|
||||
fck.setCollectedFees(ctx, newCoins)
|
||||
|
|
|
@ -13,7 +13,7 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper)
|
|||
if ctx.BlockHeight() > 1 {
|
||||
previousPercentPrecommitVotes := getPreviousPercentPrecommitVotes(req)
|
||||
previousProposer := k.GetPreviousProposerConsAddr(ctx)
|
||||
k.AllocateFees(ctx, previousPercentPrecommitVotes, previousProposer)
|
||||
k.AllocateTokens(ctx, previousPercentPrecommitVotes, previousProposer)
|
||||
}
|
||||
|
||||
consAddr := sdk.ConsAddress(req.Header.ProposerAddress)
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
)
|
||||
|
||||
// Allocate fees handles distribution of the collected fees
|
||||
func (k Keeper) AllocateFees(ctx sdk.Context, percentVotes sdk.Dec, proposer sdk.ConsAddress) {
|
||||
func (k Keeper) AllocateTokens(ctx sdk.Context, percentVotes sdk.Dec, proposer sdk.ConsAddress) {
|
||||
ctx.Logger().With("module", "x/distribution").Error(fmt.Sprintf("allocation height: %v", ctx.BlockHeight()))
|
||||
|
||||
// get the proposer of this block
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAllocateFeesBasic(t *testing.T) {
|
||||
func TestAllocateTokensBasic(t *testing.T) {
|
||||
|
||||
// no community tax on inputs
|
||||
ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
|
||||
|
@ -41,7 +41,7 @@ func TestAllocateFeesBasic(t *testing.T) {
|
|||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// verify that these fees have been received by the feePool
|
||||
percentProposer := sdk.NewDecWithPrec(5, 2)
|
||||
|
@ -52,7 +52,7 @@ func TestAllocateFeesBasic(t *testing.T) {
|
|||
require.True(sdk.DecEq(t, expRes, feePool.Pool[0].Amount))
|
||||
}
|
||||
|
||||
func TestAllocateFeesWithCommunityTax(t *testing.T) {
|
||||
func TestAllocateTokensWithCommunityTax(t *testing.T) {
|
||||
communityTax := sdk.NewDecWithPrec(1, 2) //1%
|
||||
ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, communityTax)
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
|
@ -68,7 +68,7 @@ func TestAllocateFeesWithCommunityTax(t *testing.T) {
|
|||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// verify that these fees have been received by the feePool
|
||||
feePool := keeper.GetFeePool(ctx)
|
||||
|
@ -80,7 +80,7 @@ func TestAllocateFeesWithCommunityTax(t *testing.T) {
|
|||
require.True(sdk.DecEq(t, expRes, feePool.Pool[0].Amount))
|
||||
}
|
||||
|
||||
func TestAllocateFeesWithPartialPrecommitPower(t *testing.T) {
|
||||
func TestAllocateTokensWithPartialPrecommitPower(t *testing.T) {
|
||||
communityTax := sdk.NewDecWithPrec(1, 2)
|
||||
ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, communityTax)
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
|
@ -97,7 +97,7 @@ func TestAllocateFeesWithPartialPrecommitPower(t *testing.T) {
|
|||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
percentPrecommitVotes := sdk.NewDecWithPrec(25, 2)
|
||||
keeper.AllocateFees(ctx, percentPrecommitVotes, valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, percentPrecommitVotes, valConsAddr1)
|
||||
|
||||
// verify that these fees have been received by the feePool
|
||||
feePool := keeper.GetFeePool(ctx)
|
||||
|
|
|
@ -30,7 +30,7 @@ func TestWithdrawDelegationRewardBasic(t *testing.T) {
|
|||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw delegation
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
|
@ -64,7 +64,7 @@ func TestWithdrawDelegationRewardWithCommission(t *testing.T) {
|
|||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw delegation
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
|
@ -104,7 +104,7 @@ func TestWithdrawDelegationRewardTwoDelegators(t *testing.T) {
|
|||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// delegator 1 withdraw delegation
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
|
@ -146,7 +146,7 @@ func TestWithdrawDelegationRewardTwoDelegatorsUneven(t *testing.T) {
|
|||
feeInputs := sdk.NewInt(90)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
|
||||
// delegator 1 withdraw delegation early, delegator 2 just keeps it's accum
|
||||
|
@ -160,7 +160,7 @@ func TestWithdrawDelegationRewardTwoDelegatorsUneven(t *testing.T) {
|
|||
feeInputs = sdk.NewInt(180)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
ctx = ctx.WithBlockHeight(2)
|
||||
|
||||
// delegator 2 now withdraws everything it's entitled to
|
||||
|
@ -228,7 +228,7 @@ func TestWithdrawDelegationRewardsAll(t *testing.T) {
|
|||
feeInputs := sdk.NewInt(1000)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw delegation
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
|
|
|
@ -23,7 +23,7 @@ func TestWithdrawValidatorRewardsAllNoDelegator(t *testing.T) {
|
|||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw self-delegation reward
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
|
@ -55,7 +55,7 @@ func TestWithdrawValidatorRewardsAllDelegatorNoCommission(t *testing.T) {
|
|||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw self-delegation reward
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
|
@ -89,7 +89,7 @@ func TestWithdrawValidatorRewardsAllDelegatorWithCommission(t *testing.T) {
|
|||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw validator reward
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
|
@ -129,7 +129,7 @@ func TestWithdrawValidatorRewardsAllMultipleValidator(t *testing.T) {
|
|||
feeInputs := sdk.NewInt(1000)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw validator reward
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
|
@ -175,7 +175,7 @@ func TestWithdrawValidatorRewardsAllMultipleDelegator(t *testing.T) {
|
|||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
keeper.AllocateTokens(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw validator reward
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package mint
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// Called every block, process inflation on the first block of every hour
|
||||
func BeginBlocker(ctx sdk.Context, k Keeper) {
|
||||
|
||||
blockTime := ctx.BlockHeader().Time
|
||||
minter := k.GetMinter(ctx)
|
||||
if blockTime.Sub(minter.InflationLastTime) < time.Hour { // only mint on the hour!
|
||||
return
|
||||
}
|
||||
|
||||
params := k.GetParams(ctx)
|
||||
totalSupply := k.sk.TotalPower(ctx)
|
||||
bondedRatio := k.sk.BondedRatio(ctx)
|
||||
minter.InflationLastTime = blockTime
|
||||
minter, mintedCoin := minter.ProcessProvisions(params, totalSupply, bondedRatio)
|
||||
k.fck.AddCollectedFees(ctx, sdk.Coins{mintedCoin})
|
||||
k.SetMinter(ctx, minter)
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package mint
|
||||
|
||||
import sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
// expected stake keeper
|
||||
type StakeKeeper interface {
|
||||
TotalPower(ctx sdk.Context) sdk.Dec
|
||||
BondedRatio(ctx sdk.Context) sdk.Dec
|
||||
InflateSupply(ctx sdk.Context, newTokens sdk.Dec)
|
||||
}
|
||||
|
||||
// expected fee collection keeper interface
|
||||
type FeeCollectionKeeper interface {
|
||||
AddCollectedFees(sdk.Context, sdk.Coins) sdk.Coins
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package mint
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// GenesisState - all distribution state that must be provided at genesis
|
||||
type GenesisState struct {
|
||||
Minter Minter `json:"Minter"` // minter object
|
||||
Params Params `json:"params"` // inflation params
|
||||
}
|
||||
|
||||
func NewGenesisState(minter Minter, params Params) GenesisState {
|
||||
return GenesisState{
|
||||
Minter: minter,
|
||||
Params: params,
|
||||
}
|
||||
}
|
||||
|
||||
// get raw genesis raw message for testing
|
||||
func DefaultGenesisState() GenesisState {
|
||||
return GenesisState{
|
||||
Minter: InitialMinter(),
|
||||
Params: DefaultParams(),
|
||||
}
|
||||
}
|
||||
|
||||
// new mint genesis
|
||||
func InitGenesis(ctx sdk.Context, keeper Keeper, data GenesisState) {
|
||||
keeper.SetMinter(ctx, data.Minter)
|
||||
keeper.SetParams(ctx, data.Params)
|
||||
}
|
||||
|
||||
// WriteGenesis returns a GenesisState for a given context and keeper. The
|
||||
// GenesisState will contain the pool, and validator/delegator distribution info's
|
||||
func WriteGenesis(ctx sdk.Context, keeper Keeper) GenesisState {
|
||||
|
||||
minter := keeper.GetMinter(ctx)
|
||||
params := keeper.GetParams(ctx)
|
||||
return NewGenesisState(minter, params)
|
||||
}
|
||||
|
||||
// ValidateGenesis validates the provided staking genesis state to ensure the
|
||||
// expected invariants holds. (i.e. params in correct bounds, no duplicate validators)
|
||||
func ValidateGenesis(data GenesisState) error {
|
||||
err := validateParams(data.Params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = validateMinter(data.Minter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package mint
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
)
|
||||
|
||||
// keeper of the stake store
|
||||
type Keeper struct {
|
||||
storeKey sdk.StoreKey
|
||||
cdc *codec.Codec
|
||||
paramSpace params.Subspace
|
||||
sk StakeKeeper
|
||||
fck FeeCollectionKeeper
|
||||
}
|
||||
|
||||
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey,
|
||||
paramSpace params.Subspace, sk StakeKeeper, fck FeeCollectionKeeper) Keeper {
|
||||
|
||||
keeper := Keeper{
|
||||
storeKey: key,
|
||||
cdc: cdc,
|
||||
paramSpace: paramSpace.WithTypeTable(ParamTypeTable()),
|
||||
sk: sk,
|
||||
fck: fck,
|
||||
}
|
||||
return keeper
|
||||
}
|
||||
|
||||
//____________________________________________________________________
|
||||
// Keys
|
||||
|
||||
var (
|
||||
minterKey = []byte{0x00} // the one key to use for the keeper store
|
||||
|
||||
// params store for inflation params
|
||||
ParamStoreKeyParams = []byte("params")
|
||||
)
|
||||
|
||||
// ParamTable for stake module
|
||||
func ParamTypeTable() params.TypeTable {
|
||||
return params.NewTypeTable(
|
||||
ParamStoreKeyParams, Params{},
|
||||
)
|
||||
}
|
||||
|
||||
const (
|
||||
// default paramspace for params keeper
|
||||
DefaultParamspace = "mint"
|
||||
)
|
||||
|
||||
//______________________________________________________________________
|
||||
|
||||
// get the minter
|
||||
func (k Keeper) GetMinter(ctx sdk.Context) (minter Minter) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
b := store.Get(minterKey)
|
||||
if b == nil {
|
||||
panic("Stored fee pool should not have been nil")
|
||||
}
|
||||
k.cdc.MustUnmarshalBinary(b, &minter)
|
||||
return
|
||||
}
|
||||
|
||||
// set the minter
|
||||
func (k Keeper) SetMinter(ctx sdk.Context, minter Minter) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
b := k.cdc.MustMarshalBinary(minter)
|
||||
store.Set(minterKey, b)
|
||||
}
|
||||
|
||||
//______________________________________________________________________
|
||||
|
||||
// get inflation params from the global param store
|
||||
func (k Keeper) GetParams(ctx sdk.Context) Params {
|
||||
var params Params
|
||||
k.paramSpace.Get(ctx, ParamStoreKeyParams, ¶ms)
|
||||
return params
|
||||
}
|
||||
|
||||
// set inflation params from the global param store
|
||||
func (k Keeper) SetParams(ctx sdk.Context, params Params) {
|
||||
k.paramSpace.Set(ctx, ParamStoreKeyParams, ¶ms)
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package mint
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// current inflation state
|
||||
type Minter struct {
|
||||
InflationLastTime time.Time `json:"inflation_last_time"` // block time which the last inflation was processed
|
||||
Inflation sdk.Dec `json:"inflation"` // current annual inflation rate
|
||||
}
|
||||
|
||||
// minter object for a new minter
|
||||
func InitialMinter() Minter {
|
||||
return Minter{
|
||||
InflationLastTime: time.Unix(0, 0),
|
||||
Inflation: sdk.NewDecWithPrec(13, 2),
|
||||
}
|
||||
}
|
||||
|
||||
func validateMinter(minter Minter) error {
|
||||
if minter.Inflation.LT(sdk.ZeroDec()) {
|
||||
return fmt.Errorf("mint parameter Inflation should be positive, is %s ", minter.Inflation.String())
|
||||
}
|
||||
if minter.Inflation.GT(sdk.OneDec()) {
|
||||
return fmt.Errorf("mint parameter Inflation must be <= 1, is %s", minter.Inflation.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var hrsPerYr = sdk.NewDec(8766) // as defined by a julian year of 365.25 days
|
||||
|
||||
// process provisions for an hour period
|
||||
func (m Minter) ProcessProvisions(params Params, totalSupply, bondedRatio sdk.Dec) (
|
||||
minter Minter, provisions sdk.Coin) {
|
||||
|
||||
m.Inflation = m.NextInflation(params, bondedRatio)
|
||||
provisionsDec := m.Inflation.Mul(totalSupply).Quo(hrsPerYr)
|
||||
provisions = sdk.NewCoin(params.MintDenom, provisionsDec.TruncateInt())
|
||||
return m, provisions
|
||||
}
|
||||
|
||||
// get the next inflation rate for the hour
|
||||
func (m Minter) NextInflation(params Params, bondedRatio sdk.Dec) (inflation sdk.Dec) {
|
||||
|
||||
// The target annual inflation rate is recalculated for each previsions cycle. The
|
||||
// inflation is also subject to a rate change (positive or negative) depending on
|
||||
// the distance from the desired ratio (67%). The maximum rate change possible is
|
||||
// defined to be 13% per year, however the annual inflation is capped as between
|
||||
// 7% and 20%.
|
||||
|
||||
// (1 - bondedRatio/GoalBonded) * InflationRateChange
|
||||
inflationRateChangePerYear := sdk.OneDec().
|
||||
Sub(bondedRatio.Quo(params.GoalBonded)).
|
||||
Mul(params.InflationRateChange)
|
||||
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYr)
|
||||
|
||||
// increase the new annual inflation for this next cycle
|
||||
inflation = m.Inflation.Add(inflationRateChange)
|
||||
if inflation.GT(params.InflationMax) {
|
||||
inflation = params.InflationMax
|
||||
}
|
||||
if inflation.LT(params.InflationMin) {
|
||||
inflation = params.InflationMin
|
||||
}
|
||||
|
||||
return inflation
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package mint
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func TestNextInflation(t *testing.T) {
|
||||
minter := InitialMinter()
|
||||
params := DefaultParams()
|
||||
|
||||
// Governing Mechanism:
|
||||
// inflationRateChangePerYear = (1- BondedRatio/ GoalBonded) * MaxInflationRateChange
|
||||
|
||||
tests := []struct {
|
||||
bondedRatio, setInflation, expChange sdk.Dec
|
||||
}{
|
||||
// with 0% bonded atom supply the inflation should increase by InflationRateChange
|
||||
{sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), params.InflationRateChange.Quo(hrsPerYr)},
|
||||
|
||||
// 100% bonded, starting at 20% inflation and being reduced
|
||||
// (1 - (1/0.67))*(0.13/8667)
|
||||
{sdk.OneDec(), sdk.NewDecWithPrec(20, 2),
|
||||
sdk.OneDec().Sub(sdk.OneDec().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYr)},
|
||||
|
||||
// 50% bonded, starting at 10% inflation and being increased
|
||||
{sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(10, 2),
|
||||
sdk.OneDec().Sub(sdk.NewDecWithPrec(5, 1).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYr)},
|
||||
|
||||
// test 7% minimum stop (testing with 100% bonded)
|
||||
{sdk.OneDec(), sdk.NewDecWithPrec(7, 2), sdk.ZeroDec()},
|
||||
{sdk.OneDec(), sdk.NewDecWithPrec(70001, 6), sdk.NewDecWithPrec(-1, 6)},
|
||||
|
||||
// test 20% maximum stop (testing with 0% bonded)
|
||||
{sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2), sdk.ZeroDec()},
|
||||
{sdk.ZeroDec(), sdk.NewDecWithPrec(199999, 6), sdk.NewDecWithPrec(1, 6)},
|
||||
|
||||
// perfect balance shouldn't change inflation
|
||||
{sdk.NewDecWithPrec(67, 2), sdk.NewDecWithPrec(15, 2), sdk.ZeroDec()},
|
||||
}
|
||||
for i, tc := range tests {
|
||||
minter.Inflation = tc.setInflation
|
||||
|
||||
inflation := minter.NextInflation(params, tc.bondedRatio)
|
||||
diffInflation := inflation.Sub(tc.setInflation)
|
||||
|
||||
require.True(t, diffInflation.Equal(tc.expChange),
|
||||
"Test Index: %v\nDiff: %v\nExpected: %v\n", i, diffInflation, tc.expChange)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package mint
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// mint parameters
|
||||
type Params struct {
|
||||
MintDenom string `json:"mint_denom"` // type of coin to mint
|
||||
InflationRateChange sdk.Dec `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||
InflationMax sdk.Dec `json:"inflation_max"` // maximum inflation rate
|
||||
InflationMin sdk.Dec `json:"inflation_min"` // minimum inflation rate
|
||||
GoalBonded sdk.Dec `json:"goal_bonded"` // goal of percent bonded atoms
|
||||
}
|
||||
|
||||
// default minting module parameters
|
||||
func DefaultParams() Params {
|
||||
return Params{
|
||||
MintDenom: "steak",
|
||||
InflationRateChange: sdk.NewDecWithPrec(13, 2),
|
||||
InflationMax: sdk.NewDecWithPrec(20, 2),
|
||||
InflationMin: sdk.NewDecWithPrec(7, 2),
|
||||
GoalBonded: sdk.NewDecWithPrec(67, 2),
|
||||
}
|
||||
}
|
||||
|
||||
func validateParams(params Params) error {
|
||||
if params.GoalBonded.LT(sdk.ZeroDec()) {
|
||||
return fmt.Errorf("mint parameter GoalBonded should be positive, is %s ", params.GoalBonded.String())
|
||||
}
|
||||
if params.GoalBonded.GT(sdk.OneDec()) {
|
||||
return fmt.Errorf("mint parameter GoalBonded must be <= 1, is %s", params.GoalBonded.String())
|
||||
}
|
||||
if params.InflationMax.LT(params.InflationMin) {
|
||||
return fmt.Errorf("mint parameter Max inflation must be greater than or equal to min inflation")
|
||||
}
|
||||
if params.MintDenom == "" {
|
||||
return fmt.Errorf("mint parameter MintDenom can't be an empty string")
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -103,20 +103,9 @@ func ValidateGenesis(data types.GenesisState) error {
|
|||
}
|
||||
|
||||
func validateParams(params types.Params) error {
|
||||
if params.GoalBonded.LTE(sdk.ZeroDec()) {
|
||||
bondedPercent := params.GoalBonded.MulInt(sdk.NewInt(100)).String()
|
||||
return fmt.Errorf("staking parameter GoalBonded should be positive, instead got %s percent", bondedPercent)
|
||||
}
|
||||
if params.GoalBonded.GT(sdk.OneDec()) {
|
||||
bondedPercent := params.GoalBonded.MulInt(sdk.NewInt(100)).String()
|
||||
return fmt.Errorf("staking parameter GoalBonded should be less than 100 percent, instead got %s percent", bondedPercent)
|
||||
}
|
||||
if params.BondDenom == "" {
|
||||
return fmt.Errorf("staking parameter BondDenom can't be an empty string")
|
||||
}
|
||||
if params.InflationMax.LT(params.InflationMin) {
|
||||
return fmt.Errorf("staking parameter Max inflation must be greater than or equal to min inflation")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -121,16 +121,6 @@ func TestValidateGenesis(t *testing.T) {
|
|||
wantErr bool
|
||||
}{
|
||||
{"default", func(*types.GenesisState) {}, false},
|
||||
// validate params
|
||||
{"200% goalbonded", func(data *types.GenesisState) { (*data).Params.GoalBonded = sdk.OneDec().Add(sdk.OneDec()) }, true},
|
||||
{"-67% goalbonded", func(data *types.GenesisState) { (*data).Params.GoalBonded = sdk.OneDec().Neg() }, true},
|
||||
{"no bond denom", func(data *types.GenesisState) { (*data).Params.BondDenom = "" }, true},
|
||||
{"min inflation > max inflation", func(data *types.GenesisState) {
|
||||
(*data).Params.InflationMin = (*data).Params.InflationMax.Add(sdk.OneDec())
|
||||
}, true},
|
||||
{"min inflation = max inflation", func(data *types.GenesisState) {
|
||||
(*data).Params.InflationMax = (*data).Params.InflationMin
|
||||
}, false},
|
||||
// validate genesis validators
|
||||
{"duplicate validator", func(data *types.GenesisState) {
|
||||
(*data).Validators = genValidators1
|
||||
|
|
|
@ -2,7 +2,6 @@ package stake
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/keeper"
|
||||
|
@ -31,7 +30,7 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
|
|||
}
|
||||
}
|
||||
|
||||
// Called every block, process inflation, update validator set
|
||||
// Called every block, update validator set
|
||||
func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.ValidatorUpdate) {
|
||||
endBlockerTags := sdk.EmptyTags()
|
||||
|
||||
|
@ -64,17 +63,6 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Valid
|
|||
))
|
||||
}
|
||||
|
||||
pool := k.GetPool(ctx)
|
||||
|
||||
// Process provision inflation
|
||||
blockTime := ctx.BlockHeader().Time
|
||||
if blockTime.Sub(pool.InflationLastTime) >= time.Hour {
|
||||
params := k.GetParams(ctx)
|
||||
pool.InflationLastTime = blockTime
|
||||
pool = pool.ProcessProvisions(params)
|
||||
k.SetPool(ctx, pool)
|
||||
}
|
||||
|
||||
// reset the intra-transaction counter
|
||||
k.SetIntraTxCounter(ctx, 0)
|
||||
|
||||
|
|
|
@ -85,13 +85,6 @@ func TestValidatorByPowerIndex(t *testing.T) {
|
|||
power2 := GetValidatorsByPowerIndexKey(validator, pool)
|
||||
require.True(t, keep.ValidatorByPowerIndexExists(ctx, keeper, power2))
|
||||
|
||||
// inflate a bunch
|
||||
params := keeper.GetParams(ctx)
|
||||
for i := 0; i < 200; i++ {
|
||||
pool = pool.ProcessProvisions(params)
|
||||
keeper.SetPool(ctx, pool)
|
||||
}
|
||||
|
||||
// now the new record power index should be the same as the original record
|
||||
power3 := GetValidatorsByPowerIndexKey(validator, pool)
|
||||
require.Equal(t, power2, power3)
|
||||
|
|
|
@ -18,30 +18,6 @@ func ParamTypeTable() params.TypeTable {
|
|||
return params.NewTypeTable().RegisterParamSet(&types.Params{})
|
||||
}
|
||||
|
||||
// InflationRateChange - Maximum annual change in inflation rate
|
||||
func (k Keeper) InflationRateChange(ctx sdk.Context) (res sdk.Dec) {
|
||||
k.paramstore.Get(ctx, types.KeyInflationRateChange, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// InflationMax - Maximum inflation rate
|
||||
func (k Keeper) InflationMax(ctx sdk.Context) (res sdk.Dec) {
|
||||
k.paramstore.Get(ctx, types.KeyInflationMax, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// InflationMin - Minimum inflation rate
|
||||
func (k Keeper) InflationMin(ctx sdk.Context) (res sdk.Dec) {
|
||||
k.paramstore.Get(ctx, types.KeyInflationMin, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// GoalBonded - Goal of percent bonded atoms
|
||||
func (k Keeper) GoalBonded(ctx sdk.Context) (res sdk.Dec) {
|
||||
k.paramstore.Get(ctx, types.KeyGoalBonded, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// UnbondingTime
|
||||
func (k Keeper) UnbondingTime(ctx sdk.Context) (res time.Duration) {
|
||||
k.paramstore.Get(ctx, types.KeyUnbondingTime, &res)
|
||||
|
@ -62,10 +38,6 @@ func (k Keeper) BondDenom(ctx sdk.Context) (res string) {
|
|||
|
||||
// Get all parameteras as types.Params
|
||||
func (k Keeper) GetParams(ctx sdk.Context) (res types.Params) {
|
||||
res.InflationRateChange = k.InflationRateChange(ctx)
|
||||
res.InflationMax = k.InflationMax(ctx)
|
||||
res.InflationMin = k.InflationMin(ctx)
|
||||
res.GoalBonded = k.GoalBonded(ctx)
|
||||
res.UnbondingTime = k.UnbondingTime(ctx)
|
||||
res.MaxValidators = k.MaxValidators(ctx)
|
||||
res.BondDenom = k.BondDenom(ctx)
|
||||
|
|
|
@ -72,6 +72,19 @@ func (k Keeper) TotalPower(ctx sdk.Context) sdk.Dec {
|
|||
return pool.BondedTokens
|
||||
}
|
||||
|
||||
// total power from the bond
|
||||
func (k Keeper) BondedRatio(ctx sdk.Context) sdk.Dec {
|
||||
pool := k.GetPool(ctx)
|
||||
return pool.BondedRatio()
|
||||
}
|
||||
|
||||
// when minting new tokens
|
||||
func (k Keeper) InflateSupply(ctx sdk.Context, newTokens sdk.Dec) {
|
||||
pool := k.GetPool(ctx)
|
||||
pool.LooseTokens = pool.LooseTokens.Add(newTokens)
|
||||
k.SetPool(ctx, pool)
|
||||
}
|
||||
|
||||
//__________________________________________________________________________
|
||||
|
||||
// Implements DelegationSet
|
||||
|
|
|
@ -73,18 +73,6 @@ func MakeTestCodec() *codec.Codec {
|
|||
return cdc
|
||||
}
|
||||
|
||||
// default params without inflation
|
||||
func ParamsNoInflation() types.Params {
|
||||
return types.Params{
|
||||
InflationRateChange: sdk.ZeroDec(),
|
||||
InflationMax: sdk.ZeroDec(),
|
||||
InflationMin: sdk.ZeroDec(),
|
||||
GoalBonded: sdk.NewDecWithPrec(67, 2),
|
||||
MaxValidators: 100,
|
||||
BondDenom: "steak",
|
||||
}
|
||||
}
|
||||
|
||||
// hogpodge of all sorts of input required for testing
|
||||
func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context, auth.AccountMapper, Keeper) {
|
||||
|
||||
|
|
|
@ -234,8 +234,6 @@ func Setup(mapp *mock.App, k stake.Keeper) simulation.RandSetup {
|
|||
return func(r *rand.Rand, accs []simulation.Account) {
|
||||
ctx := mapp.NewContext(false, abci.Header{})
|
||||
gen := stake.DefaultGenesisState()
|
||||
gen.Params.InflationMax = sdk.NewDec(0)
|
||||
gen.Params.InflationMin = sdk.NewDec(0)
|
||||
stake.InitGenesis(ctx, k, gen)
|
||||
params := k.GetParams(ctx)
|
||||
denom := params.BondDenom
|
||||
|
|
|
@ -58,13 +58,10 @@ var (
|
|||
GetREDsByDelToValDstIndexKey = keeper.GetREDsByDelToValDstIndexKey
|
||||
TestingUpdateValidator = keeper.TestingUpdateValidator
|
||||
|
||||
DefaultParamspace = keeper.DefaultParamspace
|
||||
KeyInflationRateChange = types.KeyInflationRateChange
|
||||
KeyInflationMax = types.KeyInflationMax
|
||||
KeyGoalBonded = types.KeyGoalBonded
|
||||
KeyUnbondingTime = types.KeyUnbondingTime
|
||||
KeyMaxValidators = types.KeyMaxValidators
|
||||
KeyBondDenom = types.KeyBondDenom
|
||||
DefaultParamspace = keeper.DefaultParamspace
|
||||
KeyUnbondingTime = types.KeyUnbondingTime
|
||||
KeyMaxValidators = types.KeyMaxValidators
|
||||
KeyBondDenom = types.KeyBondDenom
|
||||
|
||||
DefaultParams = types.DefaultParams
|
||||
InitialPool = types.InitialPool
|
||||
|
|
|
@ -1,145 +0,0 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
//changing the int in NewSource will allow you to test different, deterministic, sets of operations
|
||||
var r = rand.New(rand.NewSource(6595))
|
||||
|
||||
func TestGetInflation(t *testing.T) {
|
||||
pool := InitialPool()
|
||||
params := DefaultParams()
|
||||
|
||||
// Governing Mechanism:
|
||||
// BondedRatio = BondedTokens / TotalSupply
|
||||
// inflationRateChangePerYear = (1- BondedRatio/ GoalBonded) * MaxInflationRateChange
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
setBondedTokens, setLooseTokens,
|
||||
setInflation, expectedChange sdk.Dec
|
||||
}{
|
||||
// with 0% bonded atom supply the inflation should increase by InflationRateChange
|
||||
{"test 1", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), params.InflationRateChange.Quo(hrsPerYrDec)},
|
||||
|
||||
// 100% bonded, starting at 20% inflation and being reduced
|
||||
// (1 - (1/0.67))*(0.13/8667)
|
||||
{"test 2", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2),
|
||||
sdk.OneDec().Sub(sdk.OneDec().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrDec)},
|
||||
|
||||
// 50% bonded, starting at 10% inflation and being increased
|
||||
{"test 3", sdk.OneDec(), sdk.OneDec(), sdk.NewDecWithPrec(10, 2),
|
||||
sdk.OneDec().Sub(sdk.NewDecWithPrec(5, 1).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrDec)},
|
||||
|
||||
// test 7% minimum stop (testing with 100% bonded)
|
||||
{"test 4", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), sdk.ZeroDec()},
|
||||
{"test 5", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(70001, 6), sdk.NewDecWithPrec(-1, 6)},
|
||||
|
||||
// test 20% maximum stop (testing with 0% bonded)
|
||||
{"test 6", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2), sdk.ZeroDec()},
|
||||
{"test 7", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(199999, 6), sdk.NewDecWithPrec(1, 6)},
|
||||
|
||||
// perfect balance shouldn't change inflation
|
||||
{"test 8", sdk.NewDec(67), sdk.NewDec(33), sdk.NewDecWithPrec(15, 2), sdk.ZeroDec()},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
pool.BondedTokens, pool.LooseTokens = tc.setBondedTokens, tc.setLooseTokens
|
||||
pool.Inflation = tc.setInflation
|
||||
|
||||
inflation := pool.NextInflation(params)
|
||||
diffInflation := inflation.Sub(tc.setInflation)
|
||||
|
||||
require.True(t, diffInflation.Equal(tc.expectedChange),
|
||||
"Name: %v\nDiff: %v\nExpected: %v\n", tc.name, diffInflation, tc.expectedChange)
|
||||
}
|
||||
}
|
||||
|
||||
// Test that provisions are correctly added to the pool and validators each hour for 1 year
|
||||
func TestProcessProvisions(t *testing.T) {
|
||||
pool := InitialPool()
|
||||
params := DefaultParams()
|
||||
|
||||
var (
|
||||
initialTotalTokens int64 = 550000000
|
||||
cumulativeExpProvs = sdk.ZeroDec()
|
||||
)
|
||||
pool.LooseTokens = sdk.NewDec(initialTotalTokens)
|
||||
|
||||
// process the provisions for a year
|
||||
for hr := 0; hr < 100; hr++ {
|
||||
var expProvisions sdk.Dec
|
||||
_, expProvisions, pool = updateProvisions(t, pool, params, hr)
|
||||
cumulativeExpProvs = cumulativeExpProvs.Add(expProvisions)
|
||||
}
|
||||
|
||||
//get the pool and do the final value checks from checkFinalPoolValues
|
||||
checkFinalPoolValues(t, pool, sdk.NewDec(initialTotalTokens), cumulativeExpProvs)
|
||||
}
|
||||
|
||||
//_________________________________________________________________________________________
|
||||
////////////////////////////////HELPER FUNCTIONS BELOW/////////////////////////////////////
|
||||
|
||||
// Final check on the global pool values for what the total tokens accumulated from each hour of provisions
|
||||
func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, cumulativeExpProvs sdk.Dec) {
|
||||
calculatedTotalTokens := initialTotalTokens.Add(cumulativeExpProvs)
|
||||
require.True(sdk.DecEq(t, calculatedTotalTokens, pool.TokenSupply()))
|
||||
}
|
||||
|
||||
// Processes provisions are added to the pool correctly every hour
|
||||
// Returns expected Provisions, expected Inflation, and pool, to help with cumulative calculations back in main Tests
|
||||
func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Dec, sdk.Dec, Pool) {
|
||||
|
||||
expInflation := pool.NextInflation(params)
|
||||
expProvisions := expInflation.Mul(pool.TokenSupply()).Quo(hrsPerYrDec)
|
||||
startTotalSupply := pool.TokenSupply()
|
||||
pool = pool.ProcessProvisions(params)
|
||||
|
||||
//check provisions were added to pool
|
||||
require.True(sdk.DecEq(t, startTotalSupply.Add(expProvisions), pool.TokenSupply()))
|
||||
|
||||
return expInflation, expProvisions, pool
|
||||
}
|
||||
|
||||
// Checks that The inflation will correctly increase or decrease after an update to the pool
|
||||
func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation sdk.Dec, msg string) {
|
||||
inflationChange := updatedInflation.Sub(previousInflation)
|
||||
|
||||
switch {
|
||||
//BELOW 67% - Rate of change positive and increasing, while we are between 7% <= and < 20% inflation
|
||||
case pool.BondedRatio().LT(sdk.NewDecWithPrec(67, 2)) && updatedInflation.LT(sdk.NewDecWithPrec(20, 2)):
|
||||
require.Equal(t, true, inflationChange.GT(sdk.ZeroDec()), msg)
|
||||
|
||||
//BELOW 67% - Rate of change should be 0 while inflation continually stays at 20% until we reach 67% bonded ratio
|
||||
case pool.BondedRatio().LT(sdk.NewDecWithPrec(67, 2)) && updatedInflation.Equal(sdk.NewDecWithPrec(20, 2)):
|
||||
if previousInflation.Equal(sdk.NewDecWithPrec(20, 2)) {
|
||||
require.Equal(t, true, inflationChange.IsZero(), msg)
|
||||
|
||||
//This else statement covers the one off case where we first hit 20%, but we still needed a positive ROC to get to 67% bonded ratio (i.e. we went from 19.99999% to 20%)
|
||||
} else {
|
||||
require.Equal(t, true, inflationChange.GT(sdk.ZeroDec()), msg)
|
||||
}
|
||||
|
||||
//ABOVE 67% - Rate of change should be negative while the bond is above 67, and should stay negative until we reach inflation of 7%
|
||||
case pool.BondedRatio().GT(sdk.NewDecWithPrec(67, 2)) &&
|
||||
updatedInflation.LT(sdk.NewDecWithPrec(20, 2)) && updatedInflation.GT(sdk.NewDecWithPrec(7, 2)):
|
||||
require.Equal(t, true, inflationChange.LT(sdk.ZeroDec()), msg)
|
||||
|
||||
//ABOVE 67% - Rate of change should be 0 while inflation continually stays at 7%.
|
||||
case pool.BondedRatio().GT(sdk.NewDecWithPrec(67, 2)) &&
|
||||
updatedInflation.Equal(sdk.NewDecWithPrec(7, 2)):
|
||||
|
||||
if previousInflation.Equal(sdk.NewDecWithPrec(7, 2)) {
|
||||
require.Equal(t, true, inflationChange.IsZero(), msg)
|
||||
|
||||
//This else statement covers the one off case where we first hit 7%, but we still needed a negative ROC to continue to get down to 67%. (i.e. we went from 7.00001% to 7%)
|
||||
} else {
|
||||
require.Equal(t, true, inflationChange.LT(sdk.ZeroDec()), msg)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
)
|
||||
|
||||
|
@ -24,24 +23,15 @@ const (
|
|||
|
||||
// nolint - Keys for parameter access
|
||||
var (
|
||||
KeyInflationRateChange = []byte("InflationRateChange")
|
||||
KeyInflationMax = []byte("InflationMax")
|
||||
KeyInflationMin = []byte("InflationMin")
|
||||
KeyGoalBonded = []byte("GoalBonded")
|
||||
KeyUnbondingTime = []byte("UnbondingTime")
|
||||
KeyMaxValidators = []byte("MaxValidators")
|
||||
KeyBondDenom = []byte("BondDenom")
|
||||
KeyUnbondingTime = []byte("UnbondingTime")
|
||||
KeyMaxValidators = []byte("MaxValidators")
|
||||
KeyBondDenom = []byte("BondDenom")
|
||||
)
|
||||
|
||||
var _ params.ParamSet = (*Params)(nil)
|
||||
|
||||
// Params defines the high level settings for staking
|
||||
type Params struct {
|
||||
InflationRateChange sdk.Dec `json:"inflation_rate_change"` // maximum annual change in inflation rate
|
||||
InflationMax sdk.Dec `json:"inflation_max"` // maximum inflation rate
|
||||
InflationMin sdk.Dec `json:"inflation_min"` // minimum inflation rate
|
||||
GoalBonded sdk.Dec `json:"goal_bonded"` // Goal of percent bonded atoms
|
||||
|
||||
UnbondingTime time.Duration `json:"unbonding_time"`
|
||||
|
||||
MaxValidators uint16 `json:"max_validators"` // maximum number of validators
|
||||
|
@ -51,10 +41,6 @@ type Params struct {
|
|||
// Implements params.ParamSet
|
||||
func (p *Params) KeyValuePairs() params.KeyValuePairs {
|
||||
return params.KeyValuePairs{
|
||||
{KeyInflationRateChange, &p.InflationRateChange},
|
||||
{KeyInflationMax, &p.InflationMax},
|
||||
{KeyInflationMin, &p.InflationMin},
|
||||
{KeyGoalBonded, &p.GoalBonded},
|
||||
{KeyUnbondingTime, &p.UnbondingTime},
|
||||
{KeyMaxValidators, &p.MaxValidators},
|
||||
{KeyBondDenom, &p.BondDenom},
|
||||
|
@ -71,13 +57,9 @@ func (p Params) Equal(p2 Params) bool {
|
|||
// DefaultParams returns a default set of parameters.
|
||||
func DefaultParams() Params {
|
||||
return Params{
|
||||
InflationRateChange: sdk.NewDecWithPrec(13, 2),
|
||||
InflationMax: sdk.NewDecWithPrec(20, 2),
|
||||
InflationMin: sdk.NewDecWithPrec(7, 2),
|
||||
GoalBonded: sdk.NewDecWithPrec(67, 2),
|
||||
UnbondingTime: defaultUnbondingTime,
|
||||
MaxValidators: 100,
|
||||
BondDenom: "steak",
|
||||
UnbondingTime: defaultUnbondingTime,
|
||||
MaxValidators: 100,
|
||||
BondDenom: "steak",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,11 +67,7 @@ func DefaultParams() Params {
|
|||
// parameters.
|
||||
func (p Params) HumanReadableString() string {
|
||||
|
||||
resp := "Pool \n"
|
||||
resp += fmt.Sprintf("Maximum Annual Inflation Rate Change: %s\n", p.InflationRateChange)
|
||||
resp += fmt.Sprintf("Max Inflation Rate: %s\n", p.InflationMax)
|
||||
resp += fmt.Sprintf("Min Inflation Tate: %s\n", p.InflationMin)
|
||||
resp += fmt.Sprintf("Bonded Token Goal (%s): %s\n", "s", p.GoalBonded)
|
||||
resp := "Params \n"
|
||||
resp += fmt.Sprintf("Unbonding Time: %s\n", p.UnbondingTime)
|
||||
resp += fmt.Sprintf("Max Validators: %d: \n", p.MaxValidators)
|
||||
resp += fmt.Sprintf("Bonded Coin Denomination: %s\n", p.BondDenom)
|
||||
|
|
|
@ -3,7 +3,6 @@ package types
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -11,15 +10,8 @@ import (
|
|||
|
||||
// Pool - dynamic parameters of the current state
|
||||
type Pool struct {
|
||||
LooseTokens sdk.Dec `json:"loose_tokens"` // tokens which are not bonded in a validator
|
||||
BondedTokens sdk.Dec `json:"bonded_tokens"` // reserve of bonded tokens
|
||||
InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed
|
||||
Inflation sdk.Dec `json:"inflation"` // current annual inflation rate
|
||||
|
||||
DateLastCommissionReset int64 `json:"date_last_commission_reset"` // unix timestamp for last commission accounting reset (daily)
|
||||
|
||||
// Fee Related
|
||||
PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // last recorded bonded shares - for fee calculations
|
||||
LooseTokens sdk.Dec `json:"loose_tokens"` // tokens which are not bonded in a validator
|
||||
BondedTokens sdk.Dec `json:"bonded_tokens"` // reserve of bonded tokens
|
||||
}
|
||||
|
||||
// nolint
|
||||
|
@ -32,12 +24,8 @@ func (p Pool) Equal(p2 Pool) bool {
|
|||
// initial pool for testing
|
||||
func InitialPool() Pool {
|
||||
return Pool{
|
||||
LooseTokens: sdk.ZeroDec(),
|
||||
BondedTokens: sdk.ZeroDec(),
|
||||
InflationLastTime: time.Unix(0, 0),
|
||||
Inflation: sdk.NewDecWithPrec(7, 2),
|
||||
DateLastCommissionReset: 0,
|
||||
PrevBondedShares: sdk.ZeroDec(),
|
||||
LooseTokens: sdk.ZeroDec(),
|
||||
BondedTokens: sdk.ZeroDec(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,52 +67,6 @@ func (p Pool) bondedTokensToLoose(bondedTokens sdk.Dec) Pool {
|
|||
return p
|
||||
}
|
||||
|
||||
//_______________________________________________________________________
|
||||
// Inflation
|
||||
|
||||
const precision = 10000 // increased to this precision for accuracy
|
||||
var hrsPerYrDec = sdk.NewDec(8766) // as defined by a julian year of 365.25 days
|
||||
|
||||
// process provisions for an hour period
|
||||
func (p Pool) ProcessProvisions(params Params) Pool {
|
||||
p.Inflation = p.NextInflation(params)
|
||||
provisions := p.Inflation.
|
||||
Mul(p.TokenSupply()).
|
||||
Quo(hrsPerYrDec)
|
||||
|
||||
// TODO add to the fees provisions
|
||||
p.LooseTokens = p.LooseTokens.Add(provisions)
|
||||
return p
|
||||
}
|
||||
|
||||
// get the next inflation rate for the hour
|
||||
func (p Pool) NextInflation(params Params) (inflation sdk.Dec) {
|
||||
|
||||
// The target annual inflation rate is recalculated for each previsions cycle. The
|
||||
// inflation is also subject to a rate change (positive or negative) depending on
|
||||
// the distance from the desired ratio (67%). The maximum rate change possible is
|
||||
// defined to be 13% per year, however the annual inflation is capped as between
|
||||
// 7% and 20%.
|
||||
|
||||
// (1 - bondedRatio/GoalBonded) * InflationRateChange
|
||||
inflationRateChangePerYear := sdk.OneDec().
|
||||
Sub(p.BondedRatio().
|
||||
Quo(params.GoalBonded)).
|
||||
Mul(params.InflationRateChange)
|
||||
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrDec)
|
||||
|
||||
// increase the new annual inflation for this next cycle
|
||||
inflation = p.Inflation.Add(inflationRateChange)
|
||||
if inflation.GT(params.InflationMax) {
|
||||
inflation = params.InflationMax
|
||||
}
|
||||
if inflation.LT(params.InflationMin) {
|
||||
inflation = params.InflationMin
|
||||
}
|
||||
|
||||
return inflation
|
||||
}
|
||||
|
||||
// HumanReadableString returns a human readable string representation of a
|
||||
// pool.
|
||||
func (p Pool) HumanReadableString() string {
|
||||
|
@ -134,10 +76,6 @@ func (p Pool) HumanReadableString() string {
|
|||
resp += fmt.Sprintf("Bonded Tokens: %s\n", p.BondedTokens)
|
||||
resp += fmt.Sprintf("Token Supply: %s\n", p.TokenSupply())
|
||||
resp += fmt.Sprintf("Bonded Ratio: %v\n", p.BondedRatio())
|
||||
resp += fmt.Sprintf("Previous Inflation Block: %s\n", p.InflationLastTime)
|
||||
resp += fmt.Sprintf("Inflation: %v\n", p.Inflation)
|
||||
resp += fmt.Sprintf("Date of Last Commission Reset: %d\n", p.DateLastCommissionReset)
|
||||
resp += fmt.Sprintf("Previous Bonded Shares: %v\n", p.PrevBondedShares)
|
||||
return resp
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package types
|
|||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -185,10 +184,8 @@ func TestRemoveDelShares(t *testing.T) {
|
|||
DelegatorShares: delShares,
|
||||
}
|
||||
pool := Pool{
|
||||
BondedTokens: sdk.NewDec(248305),
|
||||
LooseTokens: sdk.NewDec(232147),
|
||||
InflationLastTime: time.Unix(0, 0),
|
||||
Inflation: sdk.NewDecWithPrec(7, 2),
|
||||
BondedTokens: sdk.NewDec(248305),
|
||||
LooseTokens: sdk.NewDec(232147),
|
||||
}
|
||||
shares := sdk.NewDec(29)
|
||||
_, newPool, tokens := validator.RemoveDelShares(pool, shares)
|
||||
|
@ -238,10 +235,8 @@ func TestPossibleOverflow(t *testing.T) {
|
|||
DelegatorShares: delShares,
|
||||
}
|
||||
pool := Pool{
|
||||
LooseTokens: sdk.NewDec(100),
|
||||
BondedTokens: poolTokens,
|
||||
InflationLastTime: time.Unix(0, 0),
|
||||
Inflation: sdk.NewDecWithPrec(7, 2),
|
||||
LooseTokens: sdk.NewDec(100),
|
||||
BondedTokens: poolTokens,
|
||||
}
|
||||
tokens := int64(71)
|
||||
msg := fmt.Sprintf("validator %#v", validator)
|
||||
|
|
Loading…
Reference in New Issue