Skip to content

Commit

Permalink
Initial cellarfees v2 migration code
Browse files Browse the repository at this point in the history
  • Loading branch information
cbrit committed Oct 8, 2024
1 parent aa61ae1 commit 97d5a9a
Show file tree
Hide file tree
Showing 27 changed files with 4,704 additions and 3 deletions.
15 changes: 13 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ import (
gravitykeeper "github.com/peggyjv/gravity-bridge/module/v4/x/gravity/keeper"
gravitytypes "github.com/peggyjv/gravity-bridge/module/v4/x/gravity/types"
appParams "github.com/peggyjv/sommelier/v7/app/params"
v8 "github.com/peggyjv/sommelier/v7/app/upgrades/v8"
"github.com/peggyjv/sommelier/v7/x/auction"
auctionclient "github.com/peggyjv/sommelier/v7/x/auction/client"
auctionkeeper "github.com/peggyjv/sommelier/v7/x/auction/keeper"
Expand Down Expand Up @@ -1008,13 +1009,23 @@ func (app *SommelierApp) setupUpgradeStoreLoaders() {

var storeUpgrades *storetypes.StoreUpgrades = nil

// TODO: Add v8 store loader when writing upgrade handler
if upgradeInfo.Name == v8.UpgradeName {
// Is this correct?
storeUpgrades = &storetypes.StoreUpgrades{}
}

if storeUpgrades != nil {
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, storeUpgrades))
}
}

func (app *SommelierApp) setupUpgradeHandlers() {
// TODO: Add v8 upgrade handler
// TODO: Add v8 upgrade handle
app.UpgradeKeeper.SetUpgradeHandler(
v8.UpgradeName,
v8.CreateUpgradeHandler(
app.mm,
app.configurator,
),
)
}
8 changes: 8 additions & 0 deletions app/upgrades/v8/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# v8 upgrade

This upgrade moves Sommelier to major version 8.

## Summary of changes

* Update the cellarfees module to start fee auctions based on the accrued USD value of a particular denom
* Update the auction module to allow a portion of SOMM proceeds earned by auctions to be burned
5 changes: 5 additions & 0 deletions app/upgrades/v8/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package v8

const (
UpgradeName = "v8"
)
23 changes: 23 additions & 0 deletions app/upgrades/v8/upgrades.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package v8

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
)

func CreateUpgradeHandler(
mm *module.Manager,
configurator module.Configurator,
) upgradetypes.UpgradeHandler {
return func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
ctx.Logger().Info("v2 upgrade: entering handler and running migrations")

fromVM := make(map[string]uint64)
for moduleName, m := range mm.Modules {
fromVM[moduleName] = m.(module.HasConsensusVersion).ConsensusVersion()
}

return mm.RunMigrations(ctx, configurator, fromVM)
}
}
21 changes: 21 additions & 0 deletions x/cellarfees/keeper/migrations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package keeper

import (
sdk "github.com/cosmos/cosmos-sdk/types"
v1 "github.com/peggyjv/sommelier/v7/x/cellarfees/migrations/v1"
)

// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
keeper Keeper
}

// NewMigrator returns a new Migrator.
func NewMigrator(keeper Keeper) Migrator {
return Migrator{keeper: keeper}
}

// Migrate1to2 migrates from consensus version 1 to 2.
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
return v1.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc, m.keeper.paramSpace)
}
52 changes: 52 additions & 0 deletions x/cellarfees/migrations/v1/keeper/abci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package keeper

import (
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/peggyjv/sommelier/v7/app/params"
)

// BeginBlocker emits rewards each block they are available by sending them to the distribution module's fee collector
// account. Emissions are a constant value based on the last peak supply of distributable fees so that the reward supply
// will decrease linearly until exhausted.
func (k Keeper) BeginBlocker(ctx sdk.Context) {

// Handle fee auctions
cellarfeesParams := k.GetParams(ctx)

counters := k.GetFeeAccrualCounters(ctx)

modulus := ctx.BlockHeader().Height % int64(cellarfeesParams.AuctionInterval)

for _, counter := range counters.Counters {

if counter.Count >= cellarfeesParams.FeeAccrualAuctionThreshold && modulus == 0 {
started := k.beginAuction(ctx, counter.Denom)
if started {
counters.ResetCounter(counter.Denom)
}
}

}
k.SetFeeAccrualCounters(ctx, counters)

// Handle reward emissions
moduleAccount := k.GetFeesAccount(ctx)
remainingRewardsSupply := k.bankKeeper.GetBalance(ctx, moduleAccount.GetAddress(), params.BaseCoinUnit).Amount

if remainingRewardsSupply.IsZero() {
return
}

emission := k.GetEmission(ctx, remainingRewardsSupply)

// Send to fee collector for distribution
err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, moduleAccount.GetName(), authtypes.FeeCollectorName, emission)
if err != nil {
panic(err)
}

}

// EndBlocker is called at the end of every block
func (k Keeper) EndBlocker(ctx sdk.Context) {}
50 changes: 50 additions & 0 deletions x/cellarfees/migrations/v1/keeper/auction.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package keeper

import (
sdk "github.com/cosmos/cosmos-sdk/types"
auctiontypes "github.com/peggyjv/sommelier/v7/x/auction/types"
"github.com/peggyjv/sommelier/v7/x/cellarfees/types"
)

// Attempts to start an auction for the provided denom
func (k Keeper) beginAuction(ctx sdk.Context, denom string) (started bool) {
activeAuctions := k.auctionKeeper.GetActiveAuctions(ctx)

// Don't start an auction if the denom has an active one
for _, auction := range activeAuctions {
if denom == auction.StartingTokensForSale.Denom {
return false
}
}

// We auction the entire balance in the cellarfees module account
cellarfeesParams := k.GetParams(ctx)
balance := k.bankKeeper.GetBalance(ctx, k.GetFeesAccount(ctx).GetAddress(), denom)
if balance.IsZero() {
k.Logger(ctx).Error("Attempted to begin auction for denom %s with a zero balance.", denom)
return false
}

err := k.auctionKeeper.BeginAuction(
ctx,
balance,
cellarfeesParams.InitialPriceDecreaseRate,
cellarfeesParams.PriceDecreaseBlockInterval,
types.ModuleName,
types.ModuleName,
)
if err != nil {
switch err {
case auctiontypes.ErrUnauthorizedFundingModule:
panic("Attempted to start an auction with an unauthorized funding module")
case auctiontypes.ErrUnauthorizedProceedsModule:
panic("Attempted to start an auction with an unauthorized proceeds module")
default:
k.Logger(ctx).Error(err.Error())
}

return false
}

return true
}
40 changes: 40 additions & 0 deletions x/cellarfees/migrations/v1/keeper/cellarfees.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package keeper

import (
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/peggyjv/sommelier/v7/app/params"
"github.com/peggyjv/sommelier/v7/x/cellarfees/types"
)

// Getter for module account that holds the fee pool funds
func (k Keeper) GetFeesAccount(ctx sdk.Context) authtypes.ModuleAccountI {
return k.accountKeeper.GetModuleAccount(ctx, types.ModuleName)
}

func (k Keeper) GetEmission(ctx sdk.Context, remainingRewardsSupply math.Int) sdk.Coins {
previousSupplyPeak := k.GetLastRewardSupplyPeak(ctx)
cellarfeesParams := k.GetParams(ctx)

var emissionAmount math.Int
if remainingRewardsSupply.GT(previousSupplyPeak) {
k.SetLastRewardSupplyPeak(ctx, remainingRewardsSupply)
emissionAmount = remainingRewardsSupply.Quo(sdk.NewInt(int64(cellarfeesParams.RewardEmissionPeriod)))
} else {
emissionAmount = previousSupplyPeak.Quo(sdk.NewInt(int64(cellarfeesParams.RewardEmissionPeriod)))
}

// Emission should be at least 1usomm and at most the remaining reward supply
if emissionAmount.IsZero() {
emissionAmount = sdk.OneInt()
} else if emissionAmount.GTE(remainingRewardsSupply) {
// We zero out the previous peak value here to avoid doing it every block. We set the final emission
// to the remaining supply here even though it's potentially redundant because it's less code than
// having another check where we would also have to zero out the prevoius peak supply.
k.SetLastRewardSupplyPeak(ctx, sdk.ZeroInt())
emissionAmount = remainingRewardsSupply
}

return sdk.NewCoins(sdk.NewCoin(params.BaseCoinUnit, emissionAmount))
}
31 changes: 31 additions & 0 deletions x/cellarfees/migrations/v1/keeper/genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package keeper

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
v1types "github.com/peggyjv/sommelier/v7/x/cellarfees/migrations/v1/types"
"github.com/peggyjv/sommelier/v7/x/cellarfees/types"
)

// InitGenesis initializes the module's state from a provided genesis
// state.
func (k Keeper) InitGenesis(ctx sdk.Context, gs v1types.GenesisState) {
k.SetParams(ctx, gs.Params)
k.SetFeeAccrualCounters(ctx, gs.FeeAccrualCounters)
k.SetLastRewardSupplyPeak(ctx, gs.LastRewardSupplyPeak)

feesAccount := k.GetFeesAccount(ctx)
if feesAccount == nil {
panic(fmt.Sprintf("%s module account has not been set", types.ModuleName))
}
}

// ExportGenesis returns the module's exported genesis.
func (k Keeper) ExportGenesis(ctx sdk.Context) v1types.GenesisState {
return v1types.GenesisState{
Params: k.GetParams(ctx),
FeeAccrualCounters: k.GetFeeAccrualCounters(ctx),
LastRewardSupplyPeak: k.GetLastRewardSupplyPeak(ctx),
}
}
76 changes: 76 additions & 0 deletions x/cellarfees/migrations/v1/keeper/hooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package keeper

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
gravitytypes "github.com/peggyjv/gravity-bridge/module/v4/x/gravity/types"
"github.com/peggyjv/sommelier/v7/app/params"
"github.com/peggyjv/sommelier/v7/x/cellarfees/types"
)

type Hooks struct {
k Keeper
}

var _ gravitytypes.GravityHooks = Hooks{}

// Hooks Return the wrapper struct
func (k Keeper) Hooks() Hooks {
return Hooks{k}
}

func (h Hooks) AfterContractCallExecutedEvent(ctx sdk.Context, event gravitytypes.ContractCallExecutedEvent) {
}

func (h Hooks) AfterERC20DeployedEvent(ctx sdk.Context, event gravitytypes.ERC20DeployedEvent) {}

func (h Hooks) AfterSignerSetExecutedEvent(ctx sdk.Context, event gravitytypes.SignerSetTxExecutedEvent) {
}

func (h Hooks) AfterBatchExecutedEvent(ctx sdk.Context, event gravitytypes.BatchExecutedEvent) {}

// Each time we receive a fee accrual from a cellar, we increment a counter for the respective denom. If a counter
// reaches a threshold defined in the cellarfees params, we attempt to start an auction. If the auction is started
// successfully we reset the count for that denom.
func (h Hooks) AfterSendToCosmosEvent(ctx sdk.Context, event gravitytypes.SendToCosmosEvent) {
// Check if recipient is the cellarfees module account
moduleAccountAddress := h.k.GetFeesAccount(ctx).GetAddress()
if event.CosmosReceiver != moduleAccountAddress.String() {
return
}

if event.Amount.IsZero() {
return
}

// Check if the sender is an approved Cellar contract. We don't want to count coins sent from any address
// as fee accruals.
if !h.k.corkKeeper.HasCellarID(ctx, common.HexToAddress(event.EthereumSender)) {
return
}

// Denom cannot be SOMM
_, denom := h.k.gravityKeeper.ERC20ToDenomLookup(ctx, common.HexToAddress(event.TokenContract))
if denom == params.BaseCoinUnit {
return
}

counters := h.k.GetFeeAccrualCounters(ctx)
count := counters.IncrementCounter(denom)
h.k.SetFeeAccrualCounters(ctx, counters)

ctx.EventManager().EmitEvents(
sdk.Events{
sdk.NewEvent(
types.EventTypeFeeAccrual,
sdk.NewAttribute(types.AttributeKeyCellar, event.EthereumSender),
sdk.NewAttribute(types.AttributeKeyTokenContract, event.TokenContract),
sdk.NewAttribute(types.AttributeKeyDenom, denom),
sdk.NewAttribute(types.AttributeKeyAmount, event.Amount.String()),
sdk.NewAttribute(types.AttributeKeyCount, fmt.Sprint(count)),
),
},
)
}
Loading

0 comments on commit 97d5a9a

Please sign in to comment.