Skip to content

Commit

Permalink
fix(mint): fix pruning panic, add developer and community funding (#161)
Browse files Browse the repository at this point in the history
* fix(app): make sure to signal ica host and credential module addition

* feat(mint): add burning caps

* feat(mint): add migration to fix utsp param denom error

* chore(mint): don't fix the wrong stake tokens issue

This migration will just replace the mint denom

* chore(mint): make golangci-lint happy

* chore(mint): fix tests

* chore(mint): revert back to generic "stake" denom

We configure "utsp" via manual genesis.json editing. The migration
still writes "utsp" because it's fixing our bad behavior
(we should've edited the genesis).

* chore(mint): remove method impl for Burn interface

* feat(mint): distribute developer and community funds (#167)

* fix: disable CGO for node builds

* feat(devnet): adding script to spin up local devnet (#160)

* feat(mint): distribute developer and community funds

This commit enables distribution of 2*10% off the newly-minted tokens
to the x/distribution community pool, and the developer funding pool.
The developer funding pool is represented as a standard Cosmos address,
which should be determined at genesis time.

Co-authored-by: Andrea Giacobino <no.andrea@gmail.com>
Co-authored-by: PaddyMc <paddymchale@hotmail.com>

Co-authored-by: Andrea Giacobino <no.andrea@gmail.com>
Co-authored-by: PaddyMc <paddymchale@hotmail.com>
  • Loading branch information
3 people authored Jun 30, 2022
1 parent a303670 commit 7796175
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 25 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ build-linux:
GOOS=linux GOARCH=amd64 LEDGER_ENABLED=false $(MAKE) build

$(BUILD_TARGETS): go.sum $(BUILDDIR)/
CGO_ENABLED=0 go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./cmd/elestod
CGO_ENABLED=0 go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./...

$(BUILDDIR)/:
mkdir -p $(BUILDDIR)/
Expand Down
26 changes: 16 additions & 10 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ import (
const (
AccountAddressPrefix = "elesto"
Name = "elesto"
upgradeName = "testnet-upgrade-2022-06-21" // Latest upgrade to be applied for the chain
upgradeName = "testnetUpgrade20220706" // Latest upgrade to be applied for the chain
)

// this line is used by starport scaffolding # stargate/wasm/app/enabledProposals
Expand Down Expand Up @@ -351,14 +351,6 @@ func New(
)
app.StakingKeeper = &sk

app.MintKeeper = mintkeeper.NewKeeper(
appCodec,
keys[minttypes.StoreKey],
app.GetSubspace(minttypes.ModuleName),
app.AccountKeeper,
app.BankKeeper,
authtypes.FeeCollectorName,
)
app.DistrKeeper = distrkeeper.NewKeeper(
appCodec,
keys[distrtypes.StoreKey],
Expand All @@ -369,6 +361,15 @@ func New(
authtypes.FeeCollectorName,
app.ModuleAccountAddrs(),
)
app.MintKeeper = mintkeeper.NewKeeper(
appCodec,
keys[minttypes.StoreKey],
app.GetSubspace(minttypes.ModuleName),
app.AccountKeeper,
app.BankKeeper,
app.DistrKeeper,
authtypes.FeeCollectorName,
)
app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec,
keys[slashingtypes.StoreKey],
Expand Down Expand Up @@ -655,7 +656,12 @@ func New(
}

if upgradeInfo.Name == upgradeName && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
storeUpgrades := storetypes.StoreUpgrades{}
storeUpgrades := storetypes.StoreUpgrades{
Added: []string{
icahosttypes.StoreKey,
credential.StoreKey,
},
}

// configure store loader that checks if version == upgradeHeight and applies store upgrades
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades))
Expand Down
26 changes: 21 additions & 5 deletions x/mint/abci.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mint

import (
"fmt"
"math"
"time"

Expand Down Expand Up @@ -58,11 +59,26 @@ func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
panic(err)
}

// TODO: 80/10/10 splitted between
// - 80: default fee collector account
// - 10: team account
// - 10: community pool
// send the minted coins to the fee collector account
// calculate 10% off mintedCoins
// this is handled in sdk.Ints already, some rounding error might persist.
tenPercentRawAmt := mintedCoin.Amount.MulRaw(10).QuoRaw(100)
tenPercentAmt := sdk.NewCoins(sdk.NewCoin(params.MintDenom, tenPercentRawAmt))

// mintedCoins now has devFundAmt less coins, two times
// one for the dev fund, one for the community pool
mintedCoins = mintedCoins.Sub(tenPercentAmt).Sub(tenPercentAmt)

// send them from mint moduleAccount to the dev fund address
if err := k.CollectAmount(ctx, params.TeamAddress, tenPercentAmt); err != nil {
panic(fmt.Errorf("cannot send coins to team account, %w", err))
}

// fund the community pool
if err := k.FundCommunityPool(ctx, tenPercentAmt); err != nil {
panic(fmt.Errorf("cannot fund community pool, %w", err))
}

// send the remaining minted coins to the fee collector account
if err := k.AddInflationToFeeCollector(ctx, mintedCoins); err != nil {
panic(err)
}
Expand Down
55 changes: 50 additions & 5 deletions x/mint/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,21 @@ func (s *ModuleTestSuite) TestInflationRate() {

initialSupply := 200_000_000_000_000

params := s.app.MintKeeper.GetParams(s.ctx)

ctx := s.ctx.WithBlockHeight(int64(0))

err := s.keeper.MintCoins(ctx, sdk.NewCoins(sdk.NewInt64Coin("stake", int64(initialSupply))))
err := s.keeper.MintCoins(ctx, sdk.NewCoins(sdk.NewInt64Coin(params.MintDenom, int64(initialSupply))))
s.Require().NoError(err)
s.Require().EqualValues(s.keeper.GetSupply(
s.ctx.WithBlockHeight(1),
"stake",
params.MintDenom,
).Amount.Int64(), int64(initialSupply))

s.T().Log("circulating supply at block 0:", s.keeper.GetSupply(ctx, "stake").String())
s.T().Log("circulating supply at block 0:", s.keeper.GetSupply(ctx, params.MintDenom).String())

lastCommunityFundAmount := sdk.DecCoins{}
lastDevFundAmount := sdk.NewCoin(params.MintDenom, sdk.ZeroInt())

for year := 0; year <= simulationYears; year++ {
// Adding 1 here because we're running the simulation on the first day of the following year.
Expand All @@ -95,15 +100,55 @@ func (s *ModuleTestSuite) TestInflationRate() {

mint.BeginBlocker(ctx, s.keeper)

communityFundAmount := s.app.DistrKeeper.GetFeePoolCommunityCoins(s.ctx)
floatCommunityAmount, err := communityFundAmount.AmountOf(params.MintDenom).Float64()
s.NoError(err)

lastFloatCommunityAmount, err := lastCommunityFundAmount.AmountOf(params.MintDenom).Float64()
s.NoError(err)

taddr, err := sdk.AccAddressFromBech32(s.app.MintKeeper.GetParams(s.ctx).TeamAddress)
s.NoError(err)

teamBalance := s.app.BankKeeper.GetBalance(s.ctx, taddr, params.MintDenom)

s.T().Log("community pool amount", lastCommunityFundAmount.String())
s.T().Log("developer fund amount", lastDevFundAmount.String())

if year < 10 {
s.Greater(
floatCommunityAmount,
lastFloatCommunityAmount,
)

s.Greater(
teamBalance.Amount.Int64(),
lastDevFundAmount.Amount.Int64(),
)
} else {
s.EqualValues(
floatCommunityAmount,
lastFloatCommunityAmount,
)

s.EqualValues(
teamBalance.Amount.Int64(),
lastDevFundAmount.Amount.Int64(),
)
}

lastCommunityFundAmount = communityFundAmount
lastDevFundAmount = teamBalance

// Since running this simulation for each block would make this test take too much time,
// we mint the total amount of tokens minted in one year, minus 1 block since the `mint.BeginBlocker()`
// call already mints once for us.
blockInflationAmount := mint.BlockInflationAmount[year]
mintAmount := sdk.NewInt(int64(blockInflationAmount) * int64(blocksPerYear-1))
mintedCoin := sdk.NewCoin("stake", mintAmount)
mintedCoin := sdk.NewCoin(params.MintDenom, mintAmount)
mintedCoins := sdk.NewCoins(mintedCoin)
s.Require().NoError(s.keeper.MintCoins(ctx, mintedCoins))
supply := s.keeper.GetSupply(ctx, "stake")
supply := s.keeper.GetSupply(ctx, params.MintDenom)
s.T().Log("inflation for year", year, ":", "supply", supply)

supplyInTokens := supply.Amount.Quo(sdk.NewInt(1000000)).ToDec().RoundInt64()
Expand Down
22 changes: 21 additions & 1 deletion x/mint/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ type Keeper struct {
cdc codec.BinaryCodec
storeKey sdk.StoreKey
paramSpace paramtypes.Subspace
accountKeeper types.AccountKeeper
bankKeeper types.BankKeeper
distrKeeper types.DistributionKeeper
feeCollectorName string
}

// NewKeeper creates a new mint Keeper instance
func NewKeeper(
cdc codec.BinaryCodec, key sdk.StoreKey, paramSpace paramtypes.Subspace, ak types.AccountKeeper, bk types.BankKeeper, feeCollectorName string,
cdc codec.BinaryCodec, key sdk.StoreKey, paramSpace paramtypes.Subspace, ak types.AccountKeeper, bk types.BankKeeper, dk types.DistributionKeeper, feeCollectorName string,
) Keeper {
// ensure mint module account is set
if addr := ak.GetModuleAddress(types.ModuleName); addr == nil {
Expand All @@ -38,6 +40,8 @@ func NewKeeper(
storeKey: key,
paramSpace: paramSpace,
bankKeeper: bk,
distrKeeper: dk,
accountKeeper: ak,
feeCollectorName: feeCollectorName,
}
}
Expand Down Expand Up @@ -88,3 +92,19 @@ func (k Keeper) CollectAmount(ctx sdk.Context, address string, amount sdk.Coins)
func (k Keeper) GetSupply(ctx sdk.Context, denom string) sdk.Coin {
return k.bankKeeper.GetSupply(ctx, denom)
}

// FundCommunityPool funds the x/distribution community pool with amount coins, directly from
// this module's ModuleAccount.
func (k Keeper) FundCommunityPool(ctx sdk.Context, amount sdk.Coins) error {
if amount.Empty() {
// skip as no coins need to be minted
return nil
}

addr := k.accountKeeper.GetModuleAddress(types.ModuleName)
if addr == nil {
panic("the mint module account has not been set")
}

return k.distrKeeper.FundCommunityPool(ctx, amount, addr)
}
5 changes: 5 additions & 0 deletions x/mint/keeper/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/elesto-dao/elesto/v2/x/mint/migrations/testnetUpgrade20220621"
"github.com/elesto-dao/elesto/v2/x/mint/migrations/testnetUpgrade20220706"
)

// Migrator is a struct for handling in-place store migrations.
Expand All @@ -20,3 +21,7 @@ func NewMigrator(keeper Keeper) Migrator {
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
return testnetUpgrade20220621.MigrateParams(ctx, m.keeper)
}

func (m Migrator) Migrate2to3(ctx sdk.Context) error {
return testnetUpgrade20220706.Migrate(ctx, m.keeper)
}
22 changes: 22 additions & 0 deletions x/mint/migrations/testnetUpgrade20220706/store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package testnetUpgrade20220706

import (
sdk "github.com/cosmos/cosmos-sdk/types"

mintTypes "github.com/elesto-dao/elesto/v2/x/mint/types"
)

type ExpectedKeeper interface {
SetParams(ctx sdk.Context, params mintTypes.Params)
MintCoins(ctx sdk.Context, amt sdk.Coins) error
GetSupply(ctx sdk.Context, denom string) sdk.Coin
}

func Migrate(ctx sdk.Context, keeper ExpectedKeeper) error {
// reset params, and hardcode the mint denom as "utsp"
p := mintTypes.DefaultParams()
p.MintDenom = "utsp"
keeper.SetParams(ctx, p)

return nil
}
75 changes: 75 additions & 0 deletions x/mint/migrations/testnetUpgrade20220706/store_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package testnetUpgrade20220706_test

import (
"fmt"
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/elesto-dao/elesto/v2/app"
"github.com/elesto-dao/elesto/v2/x/mint/migrations/testnetUpgrade20220706"
mintTypes "github.com/elesto-dao/elesto/v2/x/mint/types"
"github.com/stretchr/testify/require"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)

func (b *bogusMigrationKeeper) SetParams(ctx sdk.Context, params mintTypes.Params) {
if b.failSetParams {
panic("cannot set params")
}
}

func (b *bogusMigrationKeeper) MintCoins(ctx sdk.Context, amt sdk.Coins) error {
if b.failMint {
return fmt.Errorf("cannot mint")
}

return nil
}

func (b *bogusMigrationKeeper) GetSupply(ctx sdk.Context, denom string) sdk.Coin {
if b.failGetSupply {
c := sdk.Coin{}
c.Denom = "a"

return c
}
for _, t := range b.supply {
if t.Denom == denom {
return t
}
}

return sdk.Coin{}
}

type bogusMigrationKeeper struct {
failSetParams bool
failMint bool
failBurn bool
failGetSupply bool
supply sdk.Coins
}

func TestMigrate(t *testing.T) {
app := app.Setup(false)
ctx := app.BaseApp.NewContext(false, tmproto.Header{})

testnetUpgrade20220706.Migrate(ctx, app.MintKeeper)

require.Equal(t, "utsp", app.MintKeeper.GetParams(ctx).MintDenom)
require.Equal(t, "stake", mintTypes.DefaultParams().MintDenom)
}


func TestFailSetParams(t *testing.T) {
app := app.Setup(false)
ctx := app.BaseApp.NewContext(false, tmproto.Header{})

keeper := &bogusMigrationKeeper{
failSetParams: true,
}

require.Panics(t, func() {
_ = testnetUpgrade20220706.Migrate(ctx, keeper)
})
}
6 changes: 5 additions & 1 deletion x/mint/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
if err := cfg.RegisterMigration(types.ModuleName, 1, migrator.Migrate1to2); err != nil {
panic(fmt.Errorf("cannot migrate x/mint store from version 1 to version 2, %w", err))
}

if err := cfg.RegisterMigration(types.ModuleName, 2, migrator.Migrate2to3); err != nil {
panic(fmt.Errorf("cannot migrate x/mint store from version 2 to version 3, %w", err))
}
}

// InitGenesis performs genesis initialization for the mint module. It returns
Expand All @@ -149,7 +153,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw
}

// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 2 }
func (AppModule) ConsensusVersion() uint64 { return 3 }

// BeginBlock returns the begin blocker for the mint module.
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
Expand Down
3 changes: 1 addition & 2 deletions x/mint/simulation/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"

Expand Down Expand Up @@ -42,7 +41,7 @@ func TestRandomizedGenState(t *testing.T) {
var genState types.GenesisState
simState.Cdc.MustUnmarshalJSON(simState.GenState[types.ModuleName], &genState)

require.Equal(t, sdk.DefaultBondDenom, genState.Params.MintDenom)
require.Equal(t, "stake", genState.Params.MintDenom)
require.Equal(t, types.DefaultParams().BlocksPerYear, genState.Params.BlocksPerYear)
require.Equal(t, types.DefaultParams().MaxSupply, genState.Params.MaxSupply)
}
Expand Down
5 changes: 5 additions & 0 deletions x/mint/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,8 @@ type BankKeeper interface {
MintCoins(ctx sdk.Context, name string, amt sdk.Coins) error
GetSupply(ctx sdk.Context, denom string) sdk.Coin
}

// DistributionKeeper defines the contract required for distribution APIs.
type DistributionKeeper interface {
FundCommunityPool(ctx sdk.Context, amount sdk.Coins, sender sdk.AccAddress) error
}

0 comments on commit 7796175

Please sign in to comment.