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

Protorev: Post Handler + Proposal Handlers + Profit Sharing #3806

Merged
merged 18 commits into from
Jan 11, 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
3 changes: 1 addition & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,7 @@ func NewOsmosisApp(
app.IBCKeeper,
),
)
// Uncomment to enable postHandlers:
// app.SetPostHandler(NewTxPostHandler())
app.SetPostHandler(NewPostHandler(app.ProtoRevKeeper))
app.SetEndBlocker(app.EndBlocker)

// Register snapshot extensions to enable state-sync for wasm.
Expand Down
4 changes: 3 additions & 1 deletion app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
ibcratelimittypes "github.com/osmosis-labs/osmosis/v14/x/ibc-rate-limit/types"
"github.com/osmosis-labs/osmosis/v14/x/poolmanager"
poolmanagertypes "github.com/osmosis-labs/osmosis/v14/x/poolmanager/types"
"github.com/osmosis-labs/osmosis/v14/x/protorev"
ibchooks "github.com/osmosis-labs/osmosis/x/ibc-hooks"
ibchookskeeper "github.com/osmosis-labs/osmosis/x/ibc-hooks/keeper"
ibchookstypes "github.com/osmosis-labs/osmosis/x/ibc-hooks/types"
Expand Down Expand Up @@ -425,7 +426,8 @@ func (appKeepers *AppKeepers) InitNormalKeepers(
AddRoute(ibchost.RouterKey, ibcclient.NewClientProposalHandler(appKeepers.IBCKeeper.ClientKeeper)).
AddRoute(poolincentivestypes.RouterKey, poolincentives.NewPoolIncentivesProposalHandler(*appKeepers.PoolIncentivesKeeper)).
AddRoute(txfeestypes.RouterKey, txfees.NewUpdateFeeTokenProposalHandler(*appKeepers.TxFeesKeeper)).
AddRoute(superfluidtypes.RouterKey, superfluid.NewSuperfluidProposalHandler(*appKeepers.SuperfluidKeeper, *appKeepers.EpochsKeeper, *appKeepers.GAMMKeeper))
AddRoute(superfluidtypes.RouterKey, superfluid.NewSuperfluidProposalHandler(*appKeepers.SuperfluidKeeper, *appKeepers.EpochsKeeper, *appKeepers.GAMMKeeper)).
AddRoute(protorevtypes.RouterKey, protorev.NewProtoRevProposalHandler(*appKeepers.ProtoRevKeeper))

// The gov proposal types can be individually enabled
if len(wasmEnabledProposals) != 0 {
Expand Down
12 changes: 12 additions & 0 deletions app/posthandler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package app

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

protorevkeeper "github.com/osmosis-labs/osmosis/v14/x/protorev/keeper"
)

func NewPostHandler(protoRevKeeper *protorevkeeper.Keeper) sdk.AnteHandler {
protoRevDecorator := protorevkeeper.NewProtoRevDecorator(*protoRevKeeper)
return sdk.ChainAnteDecorators(protoRevDecorator)
}
9 changes: 0 additions & 9 deletions app/tx_post_handler.go

This file was deleted.

11 changes: 11 additions & 0 deletions proto/osmosis/protorev/v1beta1/protorev.proto
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,15 @@ message PoolStatistics {
];
// pool_id is the id of the pool
uint64 pool_id = 3;
}

// RouteWeights contains the weights of all of the different route types. Routes
// are broken up into different types based on the pool that is sandwiched in
// between the arbitrage route. This distinction is made and necessary because
// the execution time ranges fairly between the different route types.
message RouteWeights {
// The weight of a route that includes a stableswap pool
uint64 stable_weight = 1;
// The weight of a route that includes a balancer pool
uint64 balancer_weight = 2;
}
133 changes: 133 additions & 0 deletions x/protorev/client/cli/tx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package cli

import (
"fmt"
"strconv"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/gov/client/cli"
"github.com/spf13/cobra"

govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"

"github.com/osmosis-labs/osmosis/osmoutils/osmocli"
"github.com/osmosis-labs/osmosis/v14/x/protorev/types"

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

func NewCmdTx() *cobra.Command {
txCmd := osmocli.TxIndexCmd(types.ModuleName)
txCmd.AddCommand(
CmdSetProtoRevAdminAccountProposal(),
CmdSetProtoRevEnabledProposal(),
)
return txCmd
}

// CmdSetProtoRevAdminAccountProposal implements the command to submit a SetProtoRevAdminAccountProposal
func CmdSetProtoRevAdminAccountProposal() *cobra.Command {
davidterpay marked this conversation as resolved.
Show resolved Hide resolved
cmd := &cobra.Command{
Use: "set-protorev-admin-account-proposal [sdk.AccAddress]",
Args: cobra.ExactArgs(1),
Short: "submit a set protorev admin account proposal to set the admin account for x/protorev",
Example: fmt.Sprintf(`$ %s tx protorev set-protorev-admin-account osmo123... --from mykey`, version.AppName),
RunE: func(cmd *cobra.Command, args []string) error {
createContent := func(title string, description string, args ...string) (govtypes.Content, error) {
return types.NewSetProtoRevAdminAccountProposal(title, description, args[0]), nil
}

return ProposalExecute(cmd, args, createContent)
},
}

cmd.Flags().String(cli.FlagTitle, "", "title of proposal")
cmd.Flags().String(cli.FlagDescription, "", "description of proposal")
cmd.Flags().String(cli.FlagDeposit, "", "deposit of proposal")
flags.AddTxFlagsToCmd(cmd)
_ = cmd.MarkFlagRequired(cli.FlagTitle)
_ = cmd.MarkFlagRequired(cli.FlagDescription)

return cmd
}

// CmdSetProtoRevEnabledProposal implements the command to submit a SetProtoRevEnabledProposal
func CmdSetProtoRevEnabledProposal() *cobra.Command {
davidterpay marked this conversation as resolved.
Show resolved Hide resolved
cmd := &cobra.Command{
Use: "set-protorev-enabled-proposal [boolean]",
Args: cobra.ExactArgs(1),
Short: "submit a set protorev enabled proposal to enable or disable the protocol",
Example: fmt.Sprintf(`$ %s tx protorev set-protorev-enabled true --from mykey`, version.AppName),
RunE: func(cmd *cobra.Command, args []string) error {
createContent := func(title string, description string, args ...string) (govtypes.Content, error) {
res, err := strconv.ParseBool(args[0])
if err != nil {
return nil, err
}

content := types.NewSetProtoRevEnabledProposal(title, description, res)
return content, nil
}

return ProposalExecute(cmd, args, createContent)
},
}

cmd.Flags().String(cli.FlagTitle, "", "title of proposal")
cmd.Flags().String(cli.FlagDescription, "", "description of proposal")
cmd.Flags().String(cli.FlagDeposit, "", "deposit of proposal")
flags.AddTxFlagsToCmd(cmd)
_ = cmd.MarkFlagRequired(cli.FlagTitle)
_ = cmd.MarkFlagRequired(cli.FlagDescription)

return cmd
}

// ProposalExecute is a helper function to execute a proposal command. It takes in a function to create the proposal content.
func ProposalExecute(cmd *cobra.Command, args []string, createContent func(title string, description string, args ...string) (govtypes.Content, error)) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

title, err := cmd.Flags().GetString(cli.FlagTitle)
if err != nil {
return err
}

description, err := cmd.Flags().GetString(cli.FlagDescription)
if err != nil {
return err
}

depositStr, err := cmd.Flags().GetString(cli.FlagDeposit)
if err != nil {
return err
}

deposit, err := sdk.ParseCoinsNormalized(depositStr)
if err != nil {
return err
}

from := clientCtx.GetFromAddress()

content, err := createContent(title, description, args...)
if err != nil {
return err
}

msg, err := govtypes.NewMsgSubmitProposal(content, deposit, from)
if err != nil {
return err
}

if err = msg.ValidateBasic(); err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
}
28 changes: 27 additions & 1 deletion x/protorev/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,34 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState)
panic(err)
}

// Init module parameters
// Init module state
k.SetParams(ctx, genState.Params)
k.SetProtoRevEnabled(ctx, genState.Params.Enabled)
k.SetDaysSinceModuleGenesis(ctx, 0)
k.SetLatestBlockHeight(ctx, uint64(ctx.BlockHeight()))
k.SetRouteCountForBlock(ctx, 0)
davidterpay marked this conversation as resolved.
Show resolved Hide resolved

// Configure max routes per block. This roughly correlates to the ms of execution time protorev will
// take per block
if err := k.SetMaxRoutesPerBlock(ctx, 100); err != nil {
panic(err)
}

// Configure max routes per tx. This roughly correlates to the ms of execution time protorev will take
// per tx
if err := k.SetMaxRoutesPerTx(ctx, 6); err != nil {
panic(err)
}

// Configure the route weights for genesis. This roughly correlates to the ms of execution time
// by route type
routeWeights := types.RouteWeights{
StableWeight: 5, // it takes around 5 ms to execute a stable swap route
BalancerWeight: 2, // it takes around 2 ms to execute a balancer swap route
}
if err := k.SetRouteWeights(ctx, routeWeights); err != nil {
panic(err)
}

// Update the pools on genesis
if err := k.UpdatePools(ctx); err != nil {
Expand Down
61 changes: 61 additions & 0 deletions x/protorev/keeper/developer_fees.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package keeper

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

"github.com/osmosis-labs/osmosis/v14/x/protorev/types"
)

// SendDeveloperFeesToDeveloperAccount sends the developer fees from the module account to the developer account
func (k Keeper) SendDeveloperFeesToDeveloperAccount(ctx sdk.Context) error {
// Developer account must be set in order to be able to withdraw developer fees
developerAccount, err := k.GetDeveloperAccount(ctx)
if err != nil {
return err
}

coins := k.GetAllDeveloperFees(ctx)

for _, coin := range coins {
// Send the coins to the developer account
if err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, developerAccount, sdk.NewCoins(coin)); err != nil {
return err
}

// Reset the developer fees for the coin
k.DeleteDeveloperFees(ctx, coin.Denom)
}

return nil
}

// UpdateDeveloperFees updates the fees that developers can withdraw from the module account
func (k Keeper) UpdateDeveloperFees(ctx sdk.Context, denom string, profit sdk.Int) error {
daysSinceGenesis, err := k.GetDaysSinceModuleGenesis(ctx)
if err != nil {
return err
}

// Calculate the developer fee
if daysSinceGenesis < types.Phase1Length {
profit = profit.MulRaw(types.ProfitSplitPhase1).QuoRaw(100)
} else if daysSinceGenesis < types.Phase2Length {
profit = profit.MulRaw(types.ProfitSplitPhase2).QuoRaw(100)
} else {
profit = profit.MulRaw(types.ProfitSplitPhase3).QuoRaw(100)
}

// Get the developer fees for the denom, if not there then set it to 0 and initialize it
currentDeveloperFee, err := k.GetDeveloperFees(ctx, denom)
if err != nil {
currentDeveloperFee = sdk.NewCoin(denom, sdk.ZeroInt())
}
currentDeveloperFee.Amount = currentDeveloperFee.Amount.Add(profit)

// Set the developer fees for the denom
if err = k.SetDeveloperFees(ctx, currentDeveloperFee); err != nil {
return err
}

return nil
}
Loading