Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: track and query protocol rev across all modules #6804

Merged
merged 21 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Features

* [#6804](https://github.com/osmosis-labs/osmosis/pull/6804) feat: track and query protocol rev across all modules

### Fix Localosmosis docker-compose with state.

* Updated the docker-compose for localosmosis with state to be inline with Operations updated process.
Expand Down
42 changes: 42 additions & 0 deletions app/apptesting/test_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,31 @@ func (s *KeeperTestHelper) Setup() {
}
}

func (s *KeeperTestHelper) SetupWithCustomChainId(chainId string) {
dir, err := os.MkdirTemp("", "osmosisd-test-home")
if err != nil {
panic(fmt.Sprintf("failed creating temporary directory: %v", err))
}
s.T().Cleanup(func() { os.RemoveAll(dir); s.withCaching = false })
s.App = app.SetupWithCustomHomeAndChainId(false, dir, chainId)
s.setupGeneralCustomChainId(chainId)

// Manually set validator signing info, otherwise we panic
vals := s.App.StakingKeeper.GetAllValidators(s.Ctx)
for _, val := range vals {
consAddr, _ := val.GetConsAddr()
signingInfo := slashingtypes.NewValidatorSigningInfo(
consAddr,
s.Ctx.BlockHeight(),
0,
time.Unix(0, 0),
false,
0,
)
s.App.SlashingKeeper.SetValidatorSigningInfo(s.Ctx, consAddr, signingInfo)
}
}

// PrepareAllSupportedPools creates all supported pools and returns their IDs.
// Additionally, attaches an internal gauge ID for each pool.
func (s *KeeperTestHelper) PrepareAllSupportedPools() SupportedPoolAndGaugeInfo {
Expand Down Expand Up @@ -192,6 +217,23 @@ func (s *KeeperTestHelper) setupGeneral() {
s.hasUsedAbci = false
}

func (s *KeeperTestHelper) setupGeneralCustomChainId(chainId string) {
s.Ctx = s.App.BaseApp.NewContext(false, tmtypes.Header{Height: 1, ChainID: chainId, Time: defaultTestStartTime})
if s.withCaching {
s.Ctx, _ = s.Ctx.CacheContext()
}
s.QueryHelper = &baseapp.QueryServiceTestHelper{
GRPCQueryRouter: s.App.GRPCQueryRouter(),
Ctx: s.Ctx,
}

s.SetEpochStartTime()
s.TestAccs = []sdk.AccAddress{}
s.TestAccs = append(s.TestAccs, baseTestAccts...)
s.SetupConcentratedLiquidityDenomsAndPoolCreation()
s.hasUsedAbci = false
}

func (s *KeeperTestHelper) SetupTestForInitGenesis() {
// Setting to True, leads to init genesis not running
s.App = app.Setup(true)
Expand Down
85 changes: 85 additions & 0 deletions app/apptesting/txfees.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package apptesting
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The methods in the file are extracted from previously existing txfees helpers because they need to be used in other module tests, and I wanted to prevent code duplication.


import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/bank/testutil"

"github.com/cosmos/cosmos-sdk/client"

clienttx "github.com/cosmos/cosmos-sdk/client/tx"

"github.com/osmosis-labs/osmosis/osmomath"
"github.com/osmosis-labs/osmosis/v20/x/txfees/keeper"
"github.com/osmosis-labs/osmosis/v20/x/txfees/types"
)

var baseGas = uint64(10000)

func (s *KeeperTestHelper) ExecuteUpgradeFeeTokenProposal(feeToken string, poolId uint64) error {
upgradeProp := types.NewUpdateFeeTokenProposal(
"Test Proposal",
"test",
[]types.FeeToken{
{
Denom: feeToken,
PoolID: poolId,
},
},
)
return s.App.TxFeesKeeper.HandleUpdateFeeTokenProposal(s.Ctx, &upgradeProp)
}

func (s *KeeperTestHelper) SetupTxFeeAnteHandlerAndChargeFee(clientCtx client.Context, minGasPrices sdk.DecCoins, gasRequested uint64, isCheckTx, isSimulate bool, txFee sdk.Coins) error {
mempoolFeeOpts := types.NewDefaultMempoolFeeOptions()
mempoolFeeOpts.MinGasPriceForHighGasTx = osmomath.MustNewDecFromStr("0.0025")

uionPoolId := s.PrepareBalancerPoolWithCoins(
sdk.NewInt64Coin(sdk.DefaultBondDenom, 500),
sdk.NewInt64Coin("uion", 500),
)
err := s.ExecuteUpgradeFeeTokenProposal("uion", uionPoolId)
s.Require().NoError(err)

if gasRequested == 0 {
gasRequested = baseGas
}
s.Ctx = s.Ctx.WithIsCheckTx(isCheckTx).WithMinGasPrices(minGasPrices)

// TODO: Cleanup this code.
// TxBuilder components reset for every test case
txBuilder := clientCtx.TxConfig.NewTxBuilder()
priv0, _, addr0 := testdata.KeyTestPubAddr()
acc1 := s.App.AccountKeeper.NewAccountWithAddress(s.Ctx, addr0)
s.App.AccountKeeper.SetAccount(s.Ctx, acc1)
msgs := []sdk.Msg{testdata.NewTestMsg(addr0)}
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv0}, []uint64{0}, []uint64{0}
signerData := authsigning.SignerData{
ChainID: s.Ctx.ChainID(),
AccountNumber: accNums[0],
Sequence: accSeqs[0],
}

gasLimit := gasRequested
sigV2, _ := clienttx.SignWithPrivKey(
1,
signerData,
txBuilder,
privs[0],
clientCtx.TxConfig,
accSeqs[0],
)

err = testutil.FundAccount(s.App.BankKeeper, s.Ctx, addr0, txFee)
s.Require().NoError(err)

tx := s.BuildTx(txBuilder, msgs, sigV2, "", txFee, gasLimit)

mfd := keeper.NewMempoolFeeDecorator(*s.App.TxFeesKeeper, mempoolFeeOpts)
dfd := keeper.NewDeductFeeDecorator(*s.App.TxFeesKeeper, *s.App.AccountKeeper, s.App.BankKeeper, nil)
antehandlerMFD := sdk.ChainAnteDecorators(mfd, dfd)
_, err = antehandlerMFD(s.Ctx, tx, isSimulate)
return err
}
2 changes: 2 additions & 0 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers(
appKeepers.EpochsKeeper,
appKeepers.PoolManagerKeeper,
appKeepers.ConcentratedLiquidityKeeper,
appKeepers.TxFeesKeeper,
)
appKeepers.ProtoRevKeeper = &protorevKeeper
appKeepers.PoolManagerKeeper.SetProtorevKeeper(appKeepers.ProtoRevKeeper)
Expand All @@ -403,6 +404,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers(
appKeepers.DistrKeeper,
)
appKeepers.TxFeesKeeper = &txFeesKeeper
appKeepers.ProtoRevKeeper.SetTxFeesKeeper(appKeepers.TxFeesKeeper)

appKeepers.IncentivesKeeper = incentiveskeeper.NewKeeper(
appKeepers.keys[incentivestypes.StoreKey],
Expand Down
23 changes: 23 additions & 0 deletions app/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,29 @@ func SetupWithCustomHome(isCheckTx bool, dir string) *OsmosisApp {
return app
}

func SetupWithCustomHomeAndChainId(isCheckTx bool, dir, chainId string) *OsmosisApp {
db := cometbftdb.NewMemDB()
app := NewOsmosisApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, dir, 0, sims.EmptyAppOptions{}, EmptyWasmOpts, baseapp.SetChainID(chainId))
if !isCheckTx {
genesisState := GenesisStateWithValSet(app)
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
if err != nil {
panic(err)
}

app.InitChain(
abci.RequestInitChain{
Validators: []abci.ValidatorUpdate{},
ConsensusParams: sims.DefaultConsensusParams,
AppStateBytes: stateBytes,
ChainId: chainId,
},
)
}

return app
}

// Setup initializes a new OsmosisApp.
func Setup(isCheckTx bool) *OsmosisApp {
return SetupWithCustomHome(isCheckTx, DefaultNodeHome)
Expand Down
5 changes: 4 additions & 1 deletion app/upgrades/v21/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import (
)

// UpgradeName defines the on-chain upgrade name for the Osmosis v21 upgrade.
const UpgradeName = "v21"
const (
UpgradeName = "v21"
TestingChainId = "testing-chain-id"
)

var Upgrade = upgrades.Upgrade{
UpgradeName: UpgradeName,
Expand Down
30 changes: 26 additions & 4 deletions app/upgrades/v21/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
icahosttypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/host/types"
ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"

"github.com/osmosis-labs/osmosis/osmoutils"
"github.com/osmosis-labs/osmosis/v20/app/keepers"
"github.com/osmosis-labs/osmosis/v20/app/upgrades"
concentratedliquiditytypes "github.com/osmosis-labs/osmosis/v20/x/concentrated-liquidity/types"
Expand Down Expand Up @@ -48,8 +49,17 @@ func CreateUpgradeHandler(
keepers *keepers.AppKeepers,
) upgradetypes.UpgradeHandler {
return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
// UNFORKINGNOTE: If we don't manually set this to 2, the gov modules doesn't go through its necessary migrations to version 4
fromVM[govtypes.ModuleName] = 2
// I spent a very long time trying to figure out how to test this in a non hacky way.
// TL;DR, on mainnet, we run a fork of v0.43, so we should be starting at version 2.
// Without this change, since we unfork to the primary repo, we start at version 5, which
// wouldn't allow us to run each migration.
//
// Now, starting from 2 only works on mainnet because the legacysubspace is set.
// Because the legacysubspace is not set in the gotest, we cant simply run these migrations without setting the legacysubspace.
// This legacysubspace can only be set at the initChain level, so it isn't clear to me how to directly set this in the test.
if ctx.ChainID() != TestingChainId {
fromVM[govtypes.ModuleName] = 2
}
baseAppLegacySS := keepers.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramstypes.ConsensusParamsKeyTable())

// https://github.com/cosmos/cosmos-sdk/pull/12363/files
Expand Down Expand Up @@ -140,22 +150,34 @@ func CreateUpgradeHandler(
return nil, err
}

// set POB params
// Set POB Params:
err = setAuctionParams(ctx, keepers)
if err != nil {
return nil, err
}

// set expedited proposal param
// Set expedited proposal param:
govParams := keepers.GovKeeper.GetParams(ctx)
govParams.ExpeditedMinDeposit = sdk.NewCoins(sdk.NewCoin("uosmo", sdk.NewInt(5000000000)))
err = keepers.GovKeeper.SetParams(ctx, govParams)
if err != nil {
return nil, err
}

// Set CL param:
keepers.ConcentratedLiquidityKeeper.SetParam(ctx, concentratedliquiditytypes.KeyHookGasLimit, concentratedliquiditytypes.DefaultContractHookGasLimit)

// Since we are now tracking all protocol rev, we set the accounting height to the current block height for each module
// that generates protocol rev.
keepers.PoolManagerKeeper.SetTakerFeeTrackerStartHeight(ctx, ctx.BlockHeight())
keepers.TxFeesKeeper.SetTxFeesTrackerStartHeight(ctx, ctx.BlockHeight())
// We start the cyclic arb tracker from the value it currently is at since it has been tracking since inception (without a start height).
// This will allow us to display the amount of cyclic arb profits that have been generated from a certain block height.
allCyclicArbProfits := keepers.ProtoRevKeeper.GetAllProfits(ctx)
allCyclicArbProfitsCoins := osmoutils.ConvertCoinArrayToCoins(allCyclicArbProfits)
keepers.ProtoRevKeeper.SetCyclicArbProfitTrackerValue(ctx, allCyclicArbProfitsCoins)
keepers.ProtoRevKeeper.SetCyclicArbProfitTrackerStartHeight(ctx, ctx.BlockHeight())

return migrations, nil
}
}
Expand Down
71 changes: 71 additions & 0 deletions app/upgrades/v21/upgrades_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package v21_test

import (
"testing"

"github.com/stretchr/testify/suite"

upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"

v21 "github.com/osmosis-labs/osmosis/v20/app/upgrades/v21"

abci "github.com/cometbft/cometbft/abci/types"

"github.com/osmosis-labs/osmosis/osmomath"
"github.com/osmosis-labs/osmosis/v20/app/apptesting"
"github.com/osmosis-labs/osmosis/v20/x/protorev/types"

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

poolmanagertypes "github.com/osmosis-labs/osmosis/v20/x/poolmanager/types"
)

const (
v21UpgradeHeight = int64(10)
)

type UpgradeTestSuite struct {
apptesting.KeeperTestHelper
}

func TestUpgradeTestSuite(t *testing.T) {
suite.Run(t, new(UpgradeTestSuite))
}

func (s *UpgradeTestSuite) TestUpgrade() {
s.SetupWithCustomChainId(v21.TestingChainId)
dummyUpgrade(s)
s.Require().NotPanics(func() {
s.App.BeginBlocker(s.Ctx, abci.RequestBeginBlock{})
})

// Psuedo collect cyclic arb profits
cyclicArbProfits := sdk.NewCoins(sdk.NewCoin(types.OsmosisDenomination, osmomath.NewInt(9000)), sdk.NewCoin("Atom", osmomath.NewInt(3000)))
err := s.App.AppKeepers.ProtoRevKeeper.UpdateStatistics(s.Ctx, poolmanagertypes.SwapAmountInRoutes{}, cyclicArbProfits[0].Denom, cyclicArbProfits[0].Amount)
s.Require().NoError(err)
err = s.App.AppKeepers.ProtoRevKeeper.UpdateStatistics(s.Ctx, poolmanagertypes.SwapAmountInRoutes{}, cyclicArbProfits[1].Denom, cyclicArbProfits[1].Amount)
s.Require().NoError(err)

allProtocolRevenue := s.App.ProtoRevKeeper.GetAllProtocolRevenue(s.Ctx)
// Check all accounting start heights should be the same height as the upgrade
s.Require().Equal(v21UpgradeHeight, allProtocolRevenue.CyclicArbTracker.HeightAccountingStartsFrom)
s.Require().Equal(v21UpgradeHeight, allProtocolRevenue.TakerFeesTracker.HeightAccountingStartsFrom)
s.Require().Equal(v21UpgradeHeight, allProtocolRevenue.TxFeesTracker.HeightAccountingStartsFrom)
// All values should be nill except for the cyclic arb profits, which should start at the value it was at time of upgrade
s.Require().Equal(sdk.Coins(nil), allProtocolRevenue.TakerFeesTracker.TakerFeesToCommunityPool)
s.Require().Equal(sdk.Coins(nil), allProtocolRevenue.TakerFeesTracker.TakerFeesToStakers)
s.Require().Equal(sdk.Coins(nil), allProtocolRevenue.TxFeesTracker.TxFees)
s.Require().Equal(cyclicArbProfits, allProtocolRevenue.CyclicArbTracker.CyclicArb)

}

func dummyUpgrade(s *UpgradeTestSuite) {
s.Ctx = s.Ctx.WithBlockHeight(v21UpgradeHeight - 1)
plan := upgradetypes.Plan{Name: "v21", Height: v21UpgradeHeight}
err := s.App.UpgradeKeeper.ScheduleUpgrade(s.Ctx, plan)
s.Require().NoError(err)
_, exists := s.App.UpgradeKeeper.GetUpgradePlan(s.Ctx)
s.Require().True(exists)

s.Ctx = s.Ctx.WithBlockHeight(v21UpgradeHeight)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ require (
github.com/ory/dockertest/v3 v3.10.0
github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20231108202153-af031b1367bb
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231108202153-af031b1367bb
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231110043608-da030c5b18ac
github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20231108202153-af031b1367bb
github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.9-0.20231108202153-af031b1367bb
github.com/pkg/errors v0.9.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1458,8 +1458,8 @@ github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 h1:Ylmch
github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3/go.mod h1:lV6KnqXYD/ayTe7310MHtM3I2q8Z6bBfMAi+bhwPYtI=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20231108202153-af031b1367bb h1:d4JXafqN5tqmM5gQ56nMGsOccLI9M+zp3KgI3vFU8vk=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20231108202153-af031b1367bb/go.mod h1:I8CSvdOyPJREATq1Kb4mFPiDVrl2jxCRd4W3NVQFom8=
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231108202153-af031b1367bb h1:Xt1HqDuWA4ix+B+wEJIqoFHTrcE6hxoK26Nk/6uC4qo=
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231108202153-af031b1367bb/go.mod h1:5vLzE4XFr/qa5bXq6zSFncM3jUwTMOW9hMjVRSlTQAc=
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231110043608-da030c5b18ac h1:60A8/hLeNPpEJ4QPoJbpN0BgJEjMzcAy+0lByxGIlaE=
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231110043608-da030c5b18ac/go.mod h1:5vLzE4XFr/qa5bXq6zSFncM3jUwTMOW9hMjVRSlTQAc=
github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20231108202153-af031b1367bb h1:Gz4FoT0QgrqbYUt+fj+pl7kpcmv/Jd4VAKWOq3Bjpow=
github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20231108202153-af031b1367bb/go.mod h1:mno+X8PKNJZ+zKX+nG0R2Z0tEc+IM5RSvIRWKjhY+UA=
github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.9-0.20231108202153-af031b1367bb h1:GsepaIGS+uWEZT0K7cQ9hxjIVN5U6x+jzOr/7qNz7cc=
Expand Down
8 changes: 8 additions & 0 deletions osmoutils/coin_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,11 @@ func MergeCoinMaps[T comparable](currentEpochExpectedDistributionsOne map[T]sdk.
}
return newMap
}

func ConvertCoinArrayToCoins(coinArray []sdk.Coin) sdk.Coins {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While coin arrays can be used in place of a coins object and still be valid, coin array do not posses the same sub methods (ex. Sub, Add, etc), so this method is useful imo.

coins := sdk.Coins{}
for _, coin := range coinArray {
coins = append(coins, coin)
}
return coins
}
Loading