Skip to content

Commit

Permalink
Merge pull request #35 from provenance-io/bugfix/marker-module-begin-…
Browse files Browse the repository at this point in the history
…block

Wire in marker beginblocker method
  • Loading branch information
channa-figure authored Feb 3, 2021
2 parents 5db7ff7 + d530d54 commit 82724cb
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 109 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ profile.iws
tools-stamp
tmp-swagger-gen
proto-tools-stamp

#emacs tmp files
.#*
16 changes: 13 additions & 3 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,11 +460,21 @@ func New(
// CanWithdrawInvariant invariant.
// NOTE: staking module is required if HistoricalEntries param > 0
app.mm.SetOrderBeginBlockers(
upgradetypes.ModuleName, minttypes.ModuleName, distrtypes.ModuleName, slashingtypes.ModuleName,
evidencetypes.ModuleName, stakingtypes.ModuleName, ibchost.ModuleName,
upgradetypes.ModuleName,
minttypes.ModuleName,
distrtypes.ModuleName,
slashingtypes.ModuleName,
evidencetypes.ModuleName,
stakingtypes.ModuleName,
ibchost.ModuleName,
markertypes.ModuleName,
)

app.mm.SetOrderEndBlockers(crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName)
app.mm.SetOrderEndBlockers(
crisistypes.ModuleName,
govtypes.ModuleName,
stakingtypes.ModuleName,
)

// NOTE: The genutils module must occur after staking so that pools are
// properly initialized with tokens from genesis accounts.
Expand Down
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/CosmWasm/wasmd v0.14.0
github.com/armon/go-metrics v0.3.6
github.com/btcsuite/btcd v0.21.0-beta
github.com/cosmos/cosmos-sdk v0.40.1
github.com/cosmos/cosmos-sdk v0.41.0
github.com/cosmos/go-bip39 v1.0.0
github.com/gogo/protobuf v1.3.3
github.com/golang/protobuf v1.4.3
Expand All @@ -31,4 +31,6 @@ require (

)

replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.2-alpha.regen.4
replace google.golang.org/grpc => google.golang.org/grpc v1.33.2

replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
67 changes: 14 additions & 53 deletions go.sum

Large diffs are not rendered by default.

21 changes: 5 additions & 16 deletions x/marker/abci.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package marker

import (
"fmt"

abci "github.com/tendermint/tendermint/abci/types"

"github.com/provenance-io/provenance/x/marker/keeper"
Expand All @@ -17,23 +15,14 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper,
// Iterate through all marker accounts and check for supply above or below expected targets.
var err error
k.IterateMarkers(ctx, func(record types.MarkerAccountI) bool {
// Supply checks are only done against active markers of regular coin type.
// Supply checks are only done against active markers with a fixed supply.
if record.GetStatus() == types.StatusActive && record.HasFixedSupply() {
requiredSupply := record.GetSupply()
currentSupply := getCurrentSupply(ctx, requiredSupply.Denom, bk)
currentSupply := getCurrentSupply(ctx, record.GetDenom(), bk)

if requiredSupply.Amount.LT(currentSupply.Amount) {
offset := requiredSupply.Sub(currentSupply)
ctx.Logger().Error(
fmt.Sprintf("Current %s supply is NOT at the required amount, minting %d to required supply level",
requiredSupply.Denom, offset.Amount))
err = k.IncreaseSupply(ctx, record, offset)
} else if requiredSupply.Amount.GT(currentSupply.Amount) {
offset := currentSupply.Sub(requiredSupply)
ctx.Logger().Error(
fmt.Sprintf("Current %s supply is NOT at the required amount, burning %d to required supply level",
requiredSupply.Denom, offset.Amount))
err = k.DecreaseSupply(ctx, record, offset)
// If the current amount of marker coin in circulation doesn't match configured supply, make adjustments
if !requiredSupply.IsEqual(currentSupply) {
err = k.AdjustCirculation(ctx, record, requiredSupply)
}
// else supply is equal, nothing to do here.
}
Expand Down
6 changes: 3 additions & 3 deletions x/marker/client/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (s *IntegrationTestSuite) SetupSuite() {
Sequence: 0,
},
Status: markertypes.StatusActive,
SupplyFixed: true,
SupplyFixed: false,
MarkerType: markertypes.MarkerType_Coin,
AllowGovernanceControl: true,
Supply: cfg.BondedTokens.Mul(sdk.NewInt(int64(cfg.NumValidators))),
Expand Down Expand Up @@ -120,7 +120,7 @@ func (s *IntegrationTestSuite) TestMarkerQueryCommands() {
expectedOutput string
}{
{
"get testcoin marker",
"get testcoin marker json",
markercli.MarkerCmd(),
[]string{
"testcoin",
Expand All @@ -129,7 +129,7 @@ func (s *IntegrationTestSuite) TestMarkerQueryCommands() {
`{"marker":{"@type":"/provenance.marker.v1.MarkerAccount","base_account":{"address":"cosmos1p3sl9tll0ygj3flwt5r2w0n6fx9p5ngq2tu6mq","pub_key":null,"account_number":"100","sequence":"0"},"manager":"","access_control":[],"status":"MARKER_STATUS_ACTIVE","denom":"testcoin","supply":"1000","marker_type":"MARKER_TYPE_COIN","supply_fixed":true,"allow_governance_control":false}}`,
},
{
"get testcoin marker",
"get testcoin marker test",
markercli.MarkerCmd(),
[]string{
"testcoin",
Expand Down
2 changes: 1 addition & 1 deletion x/marker/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func AllHoldersCmd() *cobra.Command {
// MarkerCmd is the CLI command for querying marker module registrations.
func MarkerCmd() *cobra.Command {
cmd := &cobra.Command{
Use: " [address|denom]",
Use: "get [address|denom]",
Short: "Get marker details",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down
2 changes: 2 additions & 0 deletions x/marker/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import (
// InitGenesis creates the initial genesis state for the marker module. Typically these
// accounts would be listed with the rest of the accounts and not created here.
func (k Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) {
k.SetParams(ctx, data.Params)
if err := data.Validate(); err != nil {
panic(err)
}

// ensure our store contains references to any marker accounts in auth genesis
store := ctx.KVStore(k.storeKey)
acc := k.authKeeper.GetAllAccounts(ctx)
Expand Down
91 changes: 62 additions & 29 deletions x/marker/keeper/marker.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,34 +256,72 @@ func (k Keeper) BurnCoin(ctx sdk.Context, caller sdk.AccAddress, coin sdk.Coin)
return nil
}

// AdjustCirculation will mint/burn coin if required to ensure desired supply matches amount in circulation
func (k Keeper) AdjustCirculation(ctx sdk.Context, marker types.MarkerAccountI, desiredSupply sdk.Coin) error {
currentSupply := k.bankKeeper.GetSupply(ctx).GetTotal().AmountOf(marker.GetDenom())

if desiredSupply.Denom != marker.GetDenom() {
return fmt.Errorf("invalid denom for desired supply")
}

if desiredSupply.Amount.GT(currentSupply) { // not enough coin in circulation, mint more.
offset := sdk.NewCoin(marker.GetDenom(), desiredSupply.Amount.Sub(currentSupply))
ctx.Logger().Error(
fmt.Sprintf("Current %s supply is NOT at the required amount, minting %s to required supply level",
marker.GetDenom(), offset))
if err := k.bankKeeper.MintCoins(ctx, types.CoinPoolName, sdk.NewCoins(offset)); err != nil {
return err
}
if err := k.bankKeeper.SendCoinsFromModuleToAccount(
ctx, types.CoinPoolName, marker.GetAddress(), sdk.NewCoins(offset),
); err != nil {
return err
}
} else if desiredSupply.Amount.LT(currentSupply) { // too much coin in circulation, attempt to burn from marker account.
offset := sdk.NewCoin(marker.GetDenom(), currentSupply.Sub(desiredSupply.Amount))
ctx.Logger().Error(
fmt.Sprintf("Current %s supply is NOT at the required amount, burning %s to required supply level",
marker.GetDenom(), offset))
if err := k.bankKeeper.SendCoinsFromAccountToModule(
ctx, marker.GetAddress(), types.CoinPoolName, sdk.NewCoins(offset),
); err != nil {
return fmt.Errorf("could not send coin %v from marker account to module account: %w", offset, err)
}
// Perform controlled burn
if err := k.bankKeeper.BurnCoins(ctx, types.CoinPoolName, sdk.NewCoins(offset)); err != nil {
return fmt.Errorf("could not burn coin %v %w", offset, err)
}
}
return nil
}

// IncreaseSupply will mint coins to the marker module coin pool account, then send these to the marker account
func (k Keeper) IncreaseSupply(ctx sdk.Context, marker types.MarkerAccountI, coin sdk.Coin) error {
// using the marker, update the supply to ensure successful (save pending), abort on fail
total := marker.GetSupply().Add(coin)
inCirculation := sdk.NewCoin(marker.GetDenom(), k.bankKeeper.GetSupply(ctx).GetTotal().AmountOf(marker.GetDenom()))
total := inCirculation.Add(coin)
maxAllowed := k.GetParams(ctx).MaxTotalSupply
if total.Amount.Uint64() > maxAllowed {
return fmt.Errorf("requested supply %d exceeds maximum allowed value %d", total.Amount, maxAllowed)
}
if err := marker.SetSupply(total); err != nil {
return err
}

// Create the coins
if err := k.bankKeeper.MintCoins(ctx, types.CoinPoolName, sdk.NewCoins(coin)); err != nil {
return fmt.Errorf("could not increase coin supply in marker module: %v", err)
// If the marker has a fixed supply then adjust the supply to match the new total
if marker.HasFixedSupply() {
if err := marker.SetSupply(total); err != nil {
return err
}
// save the updated marker
k.SetMarker(ctx, marker)
}
// Create successful, save the updated marker
k.SetMarker(ctx, marker)

// dispense the coins from the marker module to the marker account.
return k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.CoinPoolName, marker.GetAddress(), sdk.NewCoins(coin))
return k.AdjustCirculation(ctx, marker, total)
}

// DecreaseSupply will move a given amount of coin from the marker to the markermodule coin pool account then burn it.
func (k Keeper) DecreaseSupply(ctx sdk.Context, marker types.MarkerAccountI, coin sdk.Coin) error {
total := marker.GetSupply()
inCirculation := sdk.NewCoin(marker.GetDenom(), k.bankKeeper.GetSupply(ctx).GetTotal().AmountOf(marker.GetDenom()))

// Ensure the request will not send the total supply below zero
if total.IsLT(coin) {
if inCirculation.IsLT(coin) {
return fmt.Errorf("cannot reduce marker total supply below zero %s, %v", coin.Denom, coin.Amount)
}
// ensure the current marker account is holding enough coin to cover burn request
Expand All @@ -292,23 +330,18 @@ func (k Keeper) DecreaseSupply(ctx sdk.Context, marker types.MarkerAccountI, coi
return fmt.Errorf("marker account contains insufficient funds to burn %s, %v", coin.Denom, coin.Amount)
}
// Update the supply (abort if this can not be done)
total = total.Sub(coin)
if err := marker.SetSupply(total); err != nil {
return err
inCirculation = inCirculation.Sub(coin)
if marker.HasFixedSupply() {
if err := marker.SetSupply(inCirculation); err != nil {
return err
}
// Finalize supply update in marker record
k.SetMarker(ctx, marker)
}

// Finalize supply update in marker record
k.SetMarker(ctx, marker)

// Move coins to markermodule coin pool in preparation for burn
if err := k.bankKeeper.SendCoinsFromAccountToModule(
ctx, marker.GetAddress(), types.CoinPoolName, sdk.NewCoins(coin),
); err != nil {
panic(fmt.Errorf("could not send coin %v from marker account to module account: %w", coin, err))
}
// Perform controlled burn
if err := k.bankKeeper.BurnCoins(ctx, types.CoinPoolName, sdk.NewCoins(coin)); err != nil {
panic(fmt.Errorf("could not burn coin %v %w", coin, err))
// Adjust circulation to match configured supply.
if err := k.AdjustCirculation(ctx, marker, inCirculation); err != nil {
panic(err)
}

return nil
Expand Down
4 changes: 3 additions & 1 deletion x/marker/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
}

// BeginBlock returns the begin blocker for the account module.
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {}
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
BeginBlocker(ctx, req, am.keeper, am.bankKeeper)
}

// EndBlock returns the end blocker for the account module. It returns no validator
// updates.
Expand Down
2 changes: 1 addition & 1 deletion x/marker/types/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (state GenesisState) Validate() error {

// DefaultGenesisState returns the initial module genesis state.
func DefaultGenesisState() *GenesisState {
return &GenesisState{}
return NewGenesisState(DefaultParams(), []MarkerAccount{})
}

// GetGenesisStateFromAppState returns x/auth GenesisState given raw application
Expand Down

0 comments on commit 82724cb

Please sign in to comment.