Skip to content
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
1 change: 1 addition & 0 deletions app/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func NewAnteHandlerAndDepGenerator(options HandlerOptions) (sdk.AnteHandler, sdk
sdk.CustomDepWrappedAnteDecorator(ante.NewIncrementSequenceDecorator(options.AccountKeeper), depdecorators.SignerDepDecorator{ReadOnly: false}),
sdk.DefaultWrappedAnteDecorator(ibcante.NewAnteDecorator(options.IBCKeeper)),
sdk.DefaultWrappedAnteDecorator(dex.NewTickSizeMultipleDecorator(*options.DexKeeper)),
sdk.DefaultWrappedAnteDecorator(dex.NewCheckDexGasDecorator(*options.DexKeeper)),
}

anteHandler, anteDepGenerator := sdk.ChainAnteDecorators(anteDecorators...)
Expand Down
2 changes: 1 addition & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -718,14 +718,14 @@ func New(
vestingtypes.ModuleName,
crisistypes.ModuleName,
ibchost.ModuleName,
dexmoduletypes.ModuleName,
genutiltypes.ModuleName,
evidencetypes.ModuleName,
ibctransfertypes.ModuleName,
feegrant.ModuleName,
oracletypes.ModuleName,
tokenfactorytypes.ModuleName,
epochmoduletypes.ModuleName,
dexmoduletypes.ModuleName,
nitrotypes.ModuleName,
wasm.ModuleName,
acltypes.ModuleName,
Expand Down
8 changes: 8 additions & 0 deletions proto/dex/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,12 @@ message Params {
(gogoproto.jsontag) = "end_block_gas_limit",
(gogoproto.moretags) = "yaml:\"end_block_gas_limit\""
];
uint64 default_gas_per_order = 5 [
(gogoproto.jsontag) = "default_gas_per_order",
(gogoproto.moretags) = "yaml:\"default_gas_per_order\""
];
uint64 default_gas_per_cancel = 6 [
(gogoproto.jsontag) = "default_gas_per_cancel",
(gogoproto.moretags) = "yaml:\"default_gas_per_cancel\""
];
}
43 changes: 43 additions & 0 deletions x/dex/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,46 @@ func IsDecimalMultipleOf(a, b sdk.Dec) bool {
quotient := sdk.NewDecFromBigInt(a.Quo(b).RoundInt().BigInt())
return quotient.Mul(b).Equal(a)
}

const DexGasFeeUnit = "usei"

type CheckDexGasDecorator struct {
dexKeeper keeper.Keeper
}

func NewCheckDexGasDecorator(dexKeeper keeper.Keeper) CheckDexGasDecorator {
return CheckDexGasDecorator{
dexKeeper: dexKeeper,
}
}

// for a TX that contains dex gas-incurring messages, check if it provides enough gas based on dex params
func (d CheckDexGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: comment for the function

if ctx.IsReCheckTx() {
return next(ctx, tx, simulate)
}
params := d.dexKeeper.GetParams(ctx)
dexGasRequired := uint64(0)
for _, msg := range tx.GetMsgs() {
switch m := msg.(type) {
case *types.MsgPlaceOrders:
dexGasRequired += params.DefaultGasPerOrder * uint64(len(m.Orders))
case *types.MsgCancelOrders:
dexGasRequired += params.DefaultGasPerCancel * uint64(len(m.Cancellations))
}
}
if dexGasRequired == 0 {
return next(ctx, tx, simulate)
}
dexFeeRequired := sdk.NewDecWithPrec(int64(dexGasRequired), 0).Mul(params.SudoCallGasPrice).RoundInt()
feeTx, ok := tx.(sdk.FeeTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
}
for _, fee := range feeTx.GetFee() {
if fee.Denom == DexGasFeeUnit && fee.Amount.GTE(dexFeeRequired) {
return next(ctx, tx, simulate)
}
}
return ctx, sdkerrors.ErrInsufficientFee
}
71 changes: 71 additions & 0 deletions x/dex/ante_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,40 @@ import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
keepertest "github.com/sei-protocol/sei-chain/testutil/keeper"
"github.com/sei-protocol/sei-chain/x/dex"
"github.com/sei-protocol/sei-chain/x/dex/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type TestTx struct {
msgs []sdk.Msg
gas uint64
fee sdk.Coins
}

func (tx TestTx) GetMsgs() []sdk.Msg {
return tx.msgs
}

func (tx TestTx) ValidateBasic() error {
return nil
}

func (tx TestTx) GetGas() uint64 {
return tx.gas
}
func (tx TestTx) GetFee() sdk.Coins {
return tx.fee
}
func (tx TestTx) FeePayer() sdk.AccAddress {
return nil
}
func (tx TestTx) FeeGranter() sdk.AccAddress {
return nil
}

func TestIsDecimalMultipleOf(t *testing.T) {
v1, _ := sdk.NewDecFromStr("2.4")
v2, _ := sdk.NewDecFromStr("1.2")
Expand All @@ -32,3 +62,44 @@ func TestIsDecimalMultipleOf(t *testing.T) {
assert.True(t, dex.IsDecimalMultipleOf(v8, v6))
assert.True(t, dex.IsDecimalMultipleOf(v9, v10))
}

func TestCheckDexGasDecorator(t *testing.T) {
keeper, ctx := keepertest.DexKeeper(t)
decorator := dex.NewCheckDexGasDecorator(*keeper)
terminator := func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { return ctx, nil }
tx := TestTx{
msgs: []sdk.Msg{
types.NewMsgPlaceOrders("someone", []*types.Order{{}, {}}, keepertest.TestContract, sdk.NewCoins()),
types.NewMsgCancelOrders("someone", []*types.Cancellation{{}, {}, {}}, keepertest.TestContract),
},
fee: sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(3500))),
}
_, err := decorator.AnteHandle(ctx, tx, false, terminator)
require.Nil(t, err)
tx = TestTx{
msgs: []sdk.Msg{
types.NewMsgPlaceOrders("someone", []*types.Order{{}, {}}, keepertest.TestContract, sdk.NewCoins()),
types.NewMsgCancelOrders("someone", []*types.Cancellation{{}, {}, {}}, keepertest.TestContract),
},
fee: sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(3499))),
}
_, err = decorator.AnteHandle(ctx, tx, false, terminator)
require.NotNil(t, err)
tx = TestTx{
msgs: []sdk.Msg{
types.NewMsgPlaceOrders("someone", []*types.Order{{}}, keepertest.TestContract, sdk.NewCoins()),
},
}
_, err = decorator.AnteHandle(ctx, tx, false, terminator)
require.NotNil(t, err)
tx = TestTx{
msgs: []sdk.Msg{},
}
_, err = decorator.AnteHandle(ctx, tx, false, terminator)
require.Nil(t, err)
tx = TestTx{
msgs: []sdk.Msg{types.NewMsgContractDepositRent(keepertest.TestContract, 10, keepertest.TestAccount)},
}
_, err = decorator.AnteHandle(ctx, tx, false, terminator)
require.Nil(t, err)
}
2 changes: 1 addition & 1 deletion x/dex/contract/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func handleFinalizedBlocks(ctx context.Context, sdkCtx sdk.Context, env *environ
if !contractsNeedHook.Contains(contractAddr) {
return true
}
if _, err := dexkeeperutils.CallContractSudo(sdkCtx, keeper, contractAddr, finalizeBlockMsg); err != nil {
if _, err := dexkeeperutils.CallContractSudo(sdkCtx, keeper, contractAddr, finalizeBlockMsg, dexutils.ZeroUserProvidedGas); err != nil {
sdkCtx.Logger().Error(fmt.Sprintf("Error calling FinalizeBlock of %s", contractAddr))
env.failedContractAddresses.Add(contractAddr)
}
Expand Down
3 changes: 2 additions & 1 deletion x/dex/contract/settlement.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
dexkeeperutils "github.com/sei-protocol/sei-chain/x/dex/keeper/utils"
"github.com/sei-protocol/sei-chain/x/dex/types"
dextypeswasm "github.com/sei-protocol/sei-chain/x/dex/types/wasm"
dexutils "github.com/sei-protocol/sei-chain/x/dex/utils"
)

func HandleSettlements(
Expand All @@ -30,7 +31,7 @@ func callSettlementHook(
Entries: settlementEntries,
},
}
if _, err := dexkeeperutils.CallContractSudo(ctx, dexkeeper, contractAddr, nativeSettlementMsg); err != nil {
if _, err := dexkeeperutils.CallContractSudo(ctx, dexkeeper, contractAddr, nativeSettlementMsg, dexutils.ZeroUserProvidedGas); err != nil {
return err
}
return nil
Expand Down
3 changes: 2 additions & 1 deletion x/dex/keeper/abci/begin_block_new_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/sei-protocol/sei-chain/x/dex/keeper/utils"
"github.com/sei-protocol/sei-chain/x/dex/types/wasm"
dexutils "github.com/sei-protocol/sei-chain/x/dex/utils"
)

func (w KeeperWrapper) HandleBBNewBlock(sdkCtx sdk.Context, contractAddr string, epoch int64) error {
msg := wasm.SudoNewBlockMsg{
NewBlock: wasm.NewBlockRequest{Epoch: epoch},
}
_, err := utils.CallContractSudo(sdkCtx, w.Keeper, contractAddr, msg)
_, err := utils.CallContractSudo(sdkCtx, w.Keeper, contractAddr, msg, dexutils.ZeroUserProvidedGas)
return err
}
3 changes: 2 additions & 1 deletion x/dex/keeper/abci/end_block_cancel_orders.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ func (w KeeperWrapper) HandleEBCancelOrders(ctx context.Context, sdkCtx sdk.Cont

typedContractAddr := typesutils.ContractAddress(contractAddr)
msg := w.getCancelSudoMsg(sdkCtx, typedContractAddr, registeredPairs)
if _, err := utils.CallContractSudo(sdkCtx, w.Keeper, contractAddr, msg); err != nil {
userProvidedGas := w.GetParams(sdkCtx).DefaultGasPerCancel * uint64(len(msg.OrderCancellations.IdsToCancel))
if _, err := utils.CallContractSudo(sdkCtx, w.Keeper, contractAddr, msg, userProvidedGas); err != nil {
sdkCtx.Logger().Error(fmt.Sprintf("Error during cancellation: %s", err.Error()))
return err
}
Expand Down
2 changes: 1 addition & 1 deletion x/dex/keeper/abci/end_block_deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (w KeeperWrapper) HandleEBDeposit(ctx context.Context, sdkCtx sdk.Context,

typedContractAddr := typesutils.ContractAddress(contractAddr)
msg := w.GetDepositSudoMsg(sdkCtx, typedContractAddr)
_, err := utils.CallContractSudo(sdkCtx, w.Keeper, contractAddr, msg) // deposit
_, err := utils.CallContractSudo(sdkCtx, w.Keeper, contractAddr, msg, dexutils.ZeroUserProvidedGas) // deposit
if err != nil {
sdkCtx.Logger().Error(fmt.Sprintf("Error during deposit: %s", err.Error()))
return err
Expand Down
3 changes: 2 additions & 1 deletion x/dex/keeper/abci/end_block_place_orders.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ func (w KeeperWrapper) HandleEBPlaceOrders(ctx context.Context, sdkCtx sdk.Conte
responses := []wasm.SudoOrderPlacementResponse{}

for _, msg := range msgs {
data, err := utils.CallContractSudo(sdkCtx, w.Keeper, contractAddr, msg)
userProvidedGas := w.GetParams(sdkCtx).DefaultGasPerOrder * uint64(len(msg.OrderPlacements.Orders))
data, err := utils.CallContractSudo(sdkCtx, w.Keeper, contractAddr, msg, userProvidedGas)
if err != nil {
sdkCtx.Logger().Error(fmt.Sprintf("Error during order placement: %s", err.Error()))
return err
Expand Down
8 changes: 7 additions & 1 deletion x/dex/keeper/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,13 @@ func (k Keeper) GetAllContractInfo(ctx sdk.Context) []types.ContractInfoV2 {
return list
}

func (k Keeper) ChargeRentForGas(ctx sdk.Context, contractAddr string, gasUsed uint64) error {
// Reduce `RentBalance` of a contract if `userProvidedGas` cannot cover `gasUsed`
func (k Keeper) ChargeRentForGas(ctx sdk.Context, contractAddr string, gasUsed uint64, userProvidedGas uint64) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: can we add an updated comment for this function?

if gasUsed <= userProvidedGas {
// User provided can fully cover the consumed gas. Doing nothing
return nil
}
gasUsed -= userProvidedGas
contract, err := k.GetContract(ctx, contractAddr)
if err != nil {
return err
Expand Down
21 changes: 19 additions & 2 deletions x/dex/keeper/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,33 @@ func TestChargeRentForGas(t *testing.T) {
RentBalance: 1000000,
})
require.Nil(t, err)
err = keeper.ChargeRentForGas(ctx, keepertest.TestContract, 5000000)
err = keeper.ChargeRentForGas(ctx, keepertest.TestContract, 5000000, 0)
require.Nil(t, err)
contract, err := keeper.GetContract(ctx, keepertest.TestContract)
require.Nil(t, err)
require.Equal(t, uint64(500000), contract.RentBalance)
err = keeper.ChargeRentForGas(ctx, keepertest.TestContract, 6000000)
err = keeper.ChargeRentForGas(ctx, keepertest.TestContract, 6000000, 0)
require.NotNil(t, err)
contract, err = keeper.GetContract(ctx, keepertest.TestContract)
require.Nil(t, err)
require.Equal(t, uint64(0), contract.RentBalance)
err = keeper.SetContract(ctx, &types.ContractInfoV2{
Creator: keepertest.TestAccount,
ContractAddr: keepertest.TestContract,
CodeId: 1,
RentBalance: 1000000,
})
require.Nil(t, err)
err = keeper.ChargeRentForGas(ctx, keepertest.TestContract, 5000000, 4000000)
require.Nil(t, err)
contract, err = keeper.GetContract(ctx, keepertest.TestContract)
require.Nil(t, err)
require.Equal(t, uint64(900000), contract.RentBalance)
err = keeper.ChargeRentForGas(ctx, keepertest.TestContract, 5000000, 6000000)
require.Nil(t, err)
contract, err = keeper.GetContract(ctx, keepertest.TestContract)
require.Nil(t, err)
require.Equal(t, uint64(900000), contract.RentBalance)

// delete contract
keeper.DeleteContract(ctx, keepertest.TestContract)
Expand Down
4 changes: 2 additions & 2 deletions x/dex/keeper/utils/wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func hasErrInstantiatingWasmModuleDueToCPUFeature(err error) bool {
return strings.Contains(err.Error(), ErrWasmModuleInstCPUFeatureLiteral)
}

func CallContractSudo(sdkCtx sdk.Context, k *keeper.Keeper, contractAddr string, msg interface{}) ([]byte, error) {
func CallContractSudo(sdkCtx sdk.Context, k *keeper.Keeper, contractAddr string, msg interface{}, userProvidedGas uint64) ([]byte, error) {
contractAddress, err := sdk.AccAddressFromBech32(contractAddr)
if err != nil {
sdkCtx.Logger().Error(err.Error())
Expand All @@ -76,7 +76,7 @@ func CallContractSudo(sdkCtx sdk.Context, k *keeper.Keeper, contractAddr string,
sdkCtx.Logger().Error(err.Error())
return []byte{}, err
}
if err := k.ChargeRentForGas(sdkCtx, contractAddr, gasUsed); err != nil {
if err := k.ChargeRentForGas(sdkCtx, contractAddr, gasUsed, userProvidedGas); err != nil {
metrics.IncrementSudoFailCount(msgType)
sdkCtx.Logger().Error(err.Error())
return []byte{}, err
Expand Down
25 changes: 12 additions & 13 deletions x/dex/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@ var (
KeySudoCallGasPrice = []byte("KeySudoCallGasPrice") // gas price for sudo calls from endblock
KeyBeginBlockGasLimit = []byte("KeyBeginBlockGasLimit")
KeyEndBlockGasLimit = []byte("KeyEndBlockGasLimit")
KeyDefaultGasPerOrder = []byte("KeyDefaultGasPerOrder")
KeyDefaultGasPerCancel = []byte("KeyDefaultGasPerCancel")
)

const (
DefaultPriceSnapshotRetention = 24 * 3600 // default to one day
DefaultBeginBlockGasLimit = 200000000 // 200M
DefaultEndBlockGasLimit = 1000000000 // 1B
DefaultDefaultGasPerOrder = 10000
DefaultDefaultGasPerCancel = 5000
)

var DefaultSudoCallGasPrice = sdk.ZeroDec() // 0
var DefaultSudoCallGasPrice = sdk.NewDecWithPrec(1, 1) // 0.1

var _ paramtypes.ParamSet = (*Params)(nil)

Expand All @@ -42,6 +46,8 @@ func DefaultParams() Params {
SudoCallGasPrice: DefaultSudoCallGasPrice,
BeginBlockGasLimit: DefaultBeginBlockGasLimit,
EndBlockGasLimit: DefaultEndBlockGasLimit,
DefaultGasPerOrder: DefaultDefaultGasPerOrder,
DefaultGasPerCancel: DefaultDefaultGasPerCancel,
}
}

Expand All @@ -50,8 +56,10 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
return paramtypes.ParamSetPairs{
paramtypes.NewParamSetPair(KeyPriceSnapshotRetention, &p.PriceSnapshotRetention, validatePriceSnapshotRetention),
paramtypes.NewParamSetPair(KeySudoCallGasPrice, &p.SudoCallGasPrice, validateSudoCallGasPrice),
paramtypes.NewParamSetPair(KeyBeginBlockGasLimit, &p.BeginBlockGasLimit, validateBeginBlockGasLimit),
paramtypes.NewParamSetPair(KeyEndBlockGasLimit, &p.EndBlockGasLimit, validateEndBlockGasLimit),
paramtypes.NewParamSetPair(KeyBeginBlockGasLimit, &p.BeginBlockGasLimit, validateUint64Param),
paramtypes.NewParamSetPair(KeyEndBlockGasLimit, &p.EndBlockGasLimit, validateUint64Param),
paramtypes.NewParamSetPair(KeyDefaultGasPerOrder, &p.DefaultGasPerOrder, validateUint64Param),
paramtypes.NewParamSetPair(KeyDefaultGasPerCancel, &p.DefaultGasPerCancel, validateUint64Param),
}
}

Expand Down Expand Up @@ -83,16 +91,7 @@ func validateSudoCallGasPrice(i interface{}) error {
return nil
}

func validateBeginBlockGasLimit(i interface{}) error {
_, ok := i.(uint64)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}

return nil
}

func validateEndBlockGasLimit(i interface{}) error {
func validateUint64Param(i interface{}) error {
_, ok := i.(uint64)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
Expand Down
Loading