From 07e4ce1f97a222dc7434aa2619d50e41b0d84636 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Tue, 7 Feb 2023 12:56:33 +0100 Subject: [PATCH 1/5] fix: deprecated use of sdkerrors (#1788) ## Description Fixes golangci-lint complains about usage of deprecated function (cherry picked from commit 37909a363e71ff3ec068d6df846fe2dfa46ed25f) # Conflicts: # x/incentive/errors.go # x/leverage/keeper/oracle.go # x/oracle/types/errors.go # x/uibc/errors.go # x/uibc/msg.go # x/uibc/quota/ibc_module.go # x/uibc/quota/keeper/quota.go # x/uibc/quota/keeper/relay.go --- app/upgrades.go | 8 +- util/checkers/proposal.go | 8 + x/ibctransfer/keeper/keeper.go | 5 +- x/incentive/errors.go | 22 ++- x/incentive/msgs.go | 4 +- x/leverage/keeper/exchange_rate.go | 5 +- x/leverage/keeper/keeper.go | 3 +- x/leverage/keeper/oracle.go | 16 +- x/leverage/keeper/token.go | 3 +- x/leverage/types/errors.go | 72 ++++----- x/leverage/types/genesis.go | 3 +- x/leverage/types/msgs.go | 8 +- x/leverage/types/token.go | 6 +- x/oracle/keeper/historic_price.go | 22 ++- x/oracle/keeper/keeper.go | 11 +- x/oracle/keeper/msg_server.go | 9 +- x/oracle/types/errors.go | 27 +++- x/oracle/types/msgs.go | 24 +-- x/oracle/types/msgs_test.go | 2 +- x/uibc/errors.go | 10 ++ x/uibc/msg.go | 118 ++++++++++++++ x/uibc/quota/ibc_module.go | 103 ++++++++++++ x/uibc/quota/keeper/quota.go | 251 +++++++++++++++++++++++++++++ x/uibc/quota/keeper/relay.go | 36 +++++ 24 files changed, 666 insertions(+), 110 deletions(-) create mode 100644 x/uibc/errors.go create mode 100644 x/uibc/msg.go create mode 100644 x/uibc/quota/ibc_module.go create mode 100644 x/uibc/quota/keeper/quota.go create mode 100644 x/uibc/quota/keeper/relay.go diff --git a/app/upgrades.go b/app/upgrades.go index d503af34fb..88447d153a 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -1,9 +1,9 @@ package app import ( + "cosmossdk.io/errors" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/module" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" "github.com/cosmos/cosmos-sdk/x/group" @@ -143,7 +143,7 @@ func (app *UmeeApp) registerUpgrade3_0(upgradeInfo upgradetypes.Plan) { ctx.Logger().Info("Running setupBech32ibcKeeper") err := upgradev3.SetupBech32ibcKeeper(&app.bech32IbcKeeper, ctx) if err != nil { - return nil, sdkerrors.Wrapf( + return nil, errors.Wrapf( err, "%q Upgrade: Unable to upgrade, bech32ibc module not initialized", planName) } @@ -156,7 +156,7 @@ func (app *UmeeApp) registerUpgrade3_0(upgradeInfo upgradetypes.Plan) { ctx.Logger().Info("Updating validator minimum commission rate param of staking module") minCommissionRate, err := upgradev3.UpdateMinimumCommissionRateParam(ctx, app.StakingKeeper) if err != nil { - return vm, sdkerrors.Wrapf( + return vm, errors.Wrapf( err, "%q Upgrade: failed to update minimum commission rate param of staking module", planName) } @@ -165,7 +165,7 @@ func (app *UmeeApp) registerUpgrade3_0(upgradeInfo upgradetypes.Plan) { "name", planName) err = upgradev3.SetMinimumCommissionRateToValidators(ctx, app.StakingKeeper, minCommissionRate) if err != nil { - return vm, sdkerrors.Wrapf( + return vm, errors.Wrapf( err, "%q Upgrade: failed to update minimum commission rate for validators", planName) } diff --git a/util/checkers/proposal.go b/util/checkers/proposal.go index bde4a2740c..124516edb2 100644 --- a/util/checkers/proposal.go +++ b/util/checkers/proposal.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -56,3 +57,10 @@ func ValidateProposal(title, description, authority string) error { return nil } + +func ValidateAddr(addr, name string) error { + if _, err := sdk.AccAddressFromBech32(addr); err != nil { + return sdkerrors.ErrInvalidAddress.Wrapf("invalid %s address: %s", name, err) + } + return nil +} diff --git a/x/ibctransfer/keeper/keeper.go b/x/ibctransfer/keeper/keeper.go index c758e70c8e..7e82ec13f0 100644 --- a/x/ibctransfer/keeper/keeper.go +++ b/x/ibctransfer/keeper/keeper.go @@ -4,7 +4,6 @@ import ( "strings" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ibctransferkeeper "github.com/cosmos/ibc-go/v5/modules/apps/transfer/keeper" ibctransfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types" @@ -64,12 +63,12 @@ func (k Keeper) SendTransfer( hash, err := ibctransfertypes.ParseHexHash(hexHash) if err != nil { - return sdkerrors.Wrap(ibctransfertypes.ErrInvalidDenomForTransfer, err.Error()) + return ibctransfertypes.ErrInvalidDenomForTransfer.Wrap(err.Error()) } denomTrace, ok := k.GetDenomTrace(ctx, hash) if !ok { - return sdkerrors.Wrap(ibctransfertypes.ErrTraceNotFound, hexHash) + return ibctransfertypes.ErrTraceNotFound.Wrap(hexHash) } k.TrackDenomMetadata(ctx, denomTrace) diff --git a/x/incentive/errors.go b/x/incentive/errors.go index e298c5ae89..8297b064bd 100644 --- a/x/incentive/errors.go +++ b/x/incentive/errors.go @@ -3,24 +3,30 @@ package incentive // DONTCOVER import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "cosmossdk.io/errors" ) var ( // 0 = TODO - ErrNotImplemented = sdkerrors.Register(ModuleName, 0, "not implemented") + ErrNotImplemented = errors.Register(ModuleName, 0, "not implemented") // 1XX = General - ErrInvalidProgramID = sdkerrors.Register(ModuleName, 100, "invalid program ID") - ErrNilAsset = sdkerrors.Register(ModuleName, 101, "nil asset") - ErrInvalidTier = sdkerrors.Register(ModuleName, 102, "invalid unbonding tier") - ErrEmptyAddress = sdkerrors.Register(ModuleName, 103, "empty address") + ErrInvalidProgramID = errors.Register(ModuleName, 100, "invalid program ID") + ErrNilAsset = errors.Register(ModuleName, 101, "nil asset") + ErrInvalidTier = errors.Register(ModuleName, 102, "invalid unbonding tier") + ErrEmptyAddress = errors.Register(ModuleName, 103, "empty address") // 2XX = Params - ErrUnbondingTierOrder = sdkerrors.Register(ModuleName, 200, "unbonding tier lock durations out of order") - ErrUnbondingWeightOrder = sdkerrors.Register(ModuleName, 201, "unbonding tier weights out of order") + ErrUnbondingTierOrder = errors.Register(ModuleName, 200, "unbonding tier lock durations out of order") + ErrUnbondingWeightOrder = errors.Register(ModuleName, 201, "unbonding tier weights out of order") // 3XX = Gov Proposal +<<<<<<< HEAD ErrNonzeroRemainingRewards = sdkerrors.Register(ModuleName, 300, "remaining rewards must be zero in proposal") ErrNonzeroFundedRewards = sdkerrors.Register(ModuleName, 301, "funded rewards must be zero in proposal") +======= + ErrNonzeroRemainingRewards = errors.Register(ModuleName, 300, "remaining rewards must be zero in proposal") + ErrNonzeroFundedRewards = errors.Register(ModuleName, 301, "funded rewards must be zero in proposal") + ErrEmptyProposal = errors.Register(ModuleName, 302, "proposal contains no incentive programs") +>>>>>>> 37909a3 (fix: deprecated use of sdkerrors (#1788)) ) diff --git a/x/incentive/msgs.go b/x/incentive/msgs.go index 761da1ec0b..625c319872 100644 --- a/x/incentive/msgs.go +++ b/x/incentive/msgs.go @@ -1,8 +1,8 @@ package incentive import ( + "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/umee-network/umee/v4/util/checkers" leveragetypes "github.com/umee-network/umee/v4/x/leverage/types" @@ -241,7 +241,7 @@ func (ip IncentiveProgram) Validate() error { } if !leveragetypes.HasUTokenPrefix(ip.Denom) { // only allow uToken denoms - return sdkerrors.Wrap(leveragetypes.ErrNotUToken, ip.Denom) + return errors.Wrap(leveragetypes.ErrNotUToken, ip.Denom) } // TODO: Finish validate logic diff --git a/x/leverage/keeper/exchange_rate.go b/x/leverage/keeper/exchange_rate.go index 1eae32668d..717b1cdae9 100644 --- a/x/leverage/keeper/exchange_rate.go +++ b/x/leverage/keeper/exchange_rate.go @@ -2,7 +2,6 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/umee-network/umee/v4/x/leverage/types" ) @@ -16,7 +15,7 @@ func (k Keeper) ExchangeToken(ctx sdk.Context, token sdk.Coin) (sdk.Coin, error) uTokenDenom := types.ToUTokenDenom(token.Denom) if uTokenDenom == "" { - return sdk.Coin{}, sdkerrors.Wrap(types.ErrUToken, token.Denom) + return sdk.Coin{}, types.ErrUToken.Wrap(token.Denom) } exchangeRate := k.DeriveExchangeRate(ctx, token.Denom) @@ -34,7 +33,7 @@ func (k Keeper) ExchangeUToken(ctx sdk.Context, uToken sdk.Coin) (sdk.Coin, erro tokenDenom := types.ToTokenDenom(uToken.Denom) if tokenDenom == "" { - return sdk.Coin{}, sdkerrors.Wrap(types.ErrNotUToken, uToken.Denom) + return sdk.Coin{}, types.ErrNotUToken.Wrap(uToken.Denom) } exchangeRate := k.DeriveExchangeRate(ctx, tokenDenom) diff --git a/x/leverage/keeper/keeper.go b/x/leverage/keeper/keeper.go index bdbb33b733..2f743b6dba 100644 --- a/x/leverage/keeper/keeper.go +++ b/x/leverage/keeper/keeper.go @@ -6,7 +6,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/tendermint/tendermint/libs/log" @@ -126,7 +125,7 @@ func (k Keeper) Withdraw(ctx sdk.Context, supplierAddr sdk.AccAddress, uToken sd // Ensure module account has sufficient unreserved tokens to withdraw availableAmount := k.AvailableLiquidity(ctx, token.Denom) if token.Amount.GT(availableAmount) { - return sdk.Coin{}, sdkerrors.Wrap(types.ErrLendingPoolInsufficient, token.String()) + return sdk.Coin{}, types.ErrLendingPoolInsufficient.Wrap(token.String()) } // Withdraw will first attempt to use any uTokens in the supplier's wallet diff --git a/x/leverage/keeper/oracle.go b/x/leverage/keeper/oracle.go index 7576beb8cc..d04340cd72 100644 --- a/x/leverage/keeper/oracle.go +++ b/x/leverage/keeper/oracle.go @@ -1,14 +1,22 @@ package keeper import ( +<<<<<<< HEAD "strings" +======= + "cosmossdk.io/errors" +>>>>>>> 37909a3 (fix: deprecated use of sdkerrors (#1788)) sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +<<<<<<< HEAD oracletypes "github.com/umee-network/umee/v4/x/oracle/types" +======= + "github.com/umee-network/umee/v4/util/sdkutil" +>>>>>>> 37909a3 (fix: deprecated use of sdkerrors (#1788)) "github.com/umee-network/umee/v4/x/leverage/types" + oracletypes "github.com/umee-network/umee/v4/x/oracle/types" ) var ten = sdk.MustNewDecFromStr("10") @@ -35,7 +43,7 @@ func (k Keeper) TokenPrice(ctx sdk.Context, baseDenom string, mode types.PriceMo // spot price is required for modes other than historic spotPrice, err = k.oracleKeeper.GetExchangeRate(ctx, t.SymbolDenom) if err != nil { - return sdk.ZeroDec(), t.Exponent, sdkerrors.Wrap(err, "oracle") + return sdk.ZeroDec(), t.Exponent, errors.Wrap(err, "oracle") } } if mode != types.PriceModeSpot { @@ -44,7 +52,7 @@ func (k Keeper) TokenPrice(ctx sdk.Context, baseDenom string, mode types.PriceMo historicPrice, numStamps, err = k.oracleKeeper.MedianOfHistoricMedians( ctx, strings.ToUpper(t.SymbolDenom), uint64(t.HistoricMedians)) if err != nil { - return sdk.ZeroDec(), t.Exponent, sdkerrors.Wrap(err, "oracle") + return sdk.ZeroDec(), t.Exponent, errors.Wrap(err, "oracle") } if numStamps < t.HistoricMedians { return sdk.ZeroDec(), t.Exponent, types.ErrNoHistoricMedians.Wrapf( @@ -69,7 +77,7 @@ func (k Keeper) TokenPrice(ctx sdk.Context, baseDenom string, mode types.PriceMo } if price.IsNil() || !price.IsPositive() { - return sdk.ZeroDec(), t.Exponent, sdkerrors.Wrap(types.ErrInvalidOraclePrice, baseDenom) + return sdk.ZeroDec(), t.Exponent, types.ErrInvalidOraclePrice.Wrap(baseDenom) } return price, t.Exponent, nil diff --git a/x/leverage/keeper/token.go b/x/leverage/keeper/token.go index 105a938e2e..1b4a5c54dd 100644 --- a/x/leverage/keeper/token.go +++ b/x/leverage/keeper/token.go @@ -2,7 +2,6 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/umee-network/umee/v4/x/leverage/types" ) @@ -33,7 +32,7 @@ func (k Keeper) GetTokenSettings(ctx sdk.Context, denom string) (types.Token, er token := types.Token{} bz := store.Get(tokenKey) if len(bz) == 0 { - return token, sdkerrors.Wrap(types.ErrNotRegisteredToken, denom) + return token, types.ErrNotRegisteredToken.Wrap(denom) } err := k.cdc.Unmarshal(bz, &token) diff --git a/x/leverage/types/errors.go b/x/leverage/types/errors.go index 400bb7e1fc..97de2865bb 100644 --- a/x/leverage/types/errors.go +++ b/x/leverage/types/errors.go @@ -3,57 +3,57 @@ package types // DONTCOVER import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "cosmossdk.io/errors" ) var ( // 1XX = General Validation - ErrEmptyAddress = sdkerrors.Register(ModuleName, 100, "empty address") - ErrNilAsset = sdkerrors.Register(ModuleName, 101, "nil asset") - ErrGetAmount = sdkerrors.Register(ModuleName, 102, "retrieved invalid amount") - ErrSetAmount = sdkerrors.Register(ModuleName, 103, "cannot set invalid amount") - ErrInvalidPriceMode = sdkerrors.Register(ModuleName, 104, "invalid price mode") + ErrEmptyAddress = errors.Register(ModuleName, 100, "empty address") + ErrNilAsset = errors.Register(ModuleName, 101, "nil asset") + ErrGetAmount = errors.Register(ModuleName, 102, "retrieved invalid amount") + ErrSetAmount = errors.Register(ModuleName, 103, "cannot set invalid amount") + ErrInvalidPriceMode = errors.Register(ModuleName, 104, "invalid price mode") // 2XX = Token Registry - ErrNotRegisteredToken = sdkerrors.Register(ModuleName, 200, "not a registered Token") - ErrUToken = sdkerrors.Register(ModuleName, 201, "denom should not be a uToken") - ErrNotUToken = sdkerrors.Register(ModuleName, 202, "denom should be a uToken") - ErrSupplyNotAllowed = sdkerrors.Register(ModuleName, 203, "supplying of Token disabled") - ErrBorrowNotAllowed = sdkerrors.Register(ModuleName, 204, "borrowing of Token disabled") - ErrBlacklisted = sdkerrors.Register(ModuleName, 205, "blacklisted Token") - ErrDuplicateToken = sdkerrors.Register(ModuleName, 207, "duplicate token") - ErrCollateralWeightZero = sdkerrors.Register(ModuleName, 206, + ErrNotRegisteredToken = errors.Register(ModuleName, 200, "not a registered Token") + ErrUToken = errors.Register(ModuleName, 201, "denom should not be a uToken") + ErrNotUToken = errors.Register(ModuleName, 202, "denom should be a uToken") + ErrSupplyNotAllowed = errors.Register(ModuleName, 203, "supplying of Token disabled") + ErrBorrowNotAllowed = errors.Register(ModuleName, 204, "borrowing of Token disabled") + ErrBlacklisted = errors.Register(ModuleName, 205, "blacklisted Token") + ErrDuplicateToken = errors.Register(ModuleName, 207, "duplicate token") + ErrCollateralWeightZero = errors.Register(ModuleName, 206, "collateral weight of Token is zero: can't be used as a collateral") // 3XX = User Positions - ErrInsufficientBalance = sdkerrors.Register(ModuleName, 300, "insufficient balance") - ErrInsufficientCollateral = sdkerrors.Register(ModuleName, 301, "insufficient collateral") - ErrLiquidationRepayZero = sdkerrors.Register(ModuleName, 303, "liquidation would repay zero tokens") + ErrInsufficientBalance = errors.Register(ModuleName, 300, "insufficient balance") + ErrInsufficientCollateral = errors.Register(ModuleName, 301, "insufficient collateral") + ErrLiquidationRepayZero = errors.Register(ModuleName, 303, "liquidation would repay zero tokens") // 4XX = Price Sensitive - ErrBadValue = sdkerrors.Register(ModuleName, 400, "bad USD value") - ErrInvalidOraclePrice = sdkerrors.Register(ModuleName, 401, "invalid oracle price") - ErrUndercollaterized = sdkerrors.Register(ModuleName, 402, "borrow positions are undercollaterized") - ErrLiquidationIneligible = sdkerrors.Register(ModuleName, 403, "borrower not eligible for liquidation") - ErrNoHistoricMedians = sdkerrors.Register(ModuleName, 405, "insufficient historic medians available") + ErrBadValue = errors.Register(ModuleName, 400, "bad USD value") + ErrInvalidOraclePrice = errors.Register(ModuleName, 401, "invalid oracle price") + ErrUndercollaterized = errors.Register(ModuleName, 402, "borrow positions are undercollaterized") + ErrLiquidationIneligible = errors.Register(ModuleName, 403, "borrower not eligible for liquidation") + ErrNoHistoricMedians = errors.Register(ModuleName, 405, "insufficient historic medians available") // 5XX = Market Conditions - ErrLendingPoolInsufficient = sdkerrors.Register(ModuleName, 500, "lending pool insufficient") - ErrMaxSupplyUtilization = sdkerrors.Register(ModuleName, 501, "market would exceed MaxSupplyUtilization") - ErrMinCollateralLiquidity = sdkerrors.Register(ModuleName, 502, "market would fall below MinCollateralLiquidity") - ErrMaxCollateralShare = sdkerrors.Register(ModuleName, 503, "market would exceed MaxCollateralShare") - ErrMaxSupply = sdkerrors.Register(ModuleName, 504, "market would exceed MaxSupply") + ErrLendingPoolInsufficient = errors.Register(ModuleName, 500, "lending pool insufficient") + ErrMaxSupplyUtilization = errors.Register(ModuleName, 501, "market would exceed MaxSupplyUtilization") + ErrMinCollateralLiquidity = errors.Register(ModuleName, 502, "market would fall below MinCollateralLiquidity") + ErrMaxCollateralShare = errors.Register(ModuleName, 503, "market would exceed MaxCollateralShare") + ErrMaxSupply = errors.Register(ModuleName, 504, "market would exceed MaxSupply") // 6XX = Internal Failsafes - ErrInvalidUtilization = sdkerrors.Register(ModuleName, 600, "invalid token utilization") - ErrNegativeTotalBorrowed = sdkerrors.Register(ModuleName, 601, "total borrowed was negative") - ErrNegativeAPY = sdkerrors.Register(ModuleName, 602, "negative APY") - ErrNegativeTimeElapsed = sdkerrors.Register(ModuleName, 603, "negative time elapsed since last interest time") - ErrInvalidExchangeRate = sdkerrors.Register(ModuleName, 604, "exchange rate less than one") - ErrInconsistentTotalBorrow = sdkerrors.Register(ModuleName, 605, "total adjusted borrow inconsistency") - ErrExcessiveTimeElapsed = sdkerrors.Register(ModuleName, 606, "excessive time elapsed since last interest time") + ErrInvalidUtilization = errors.Register(ModuleName, 600, "invalid token utilization") + ErrNegativeTotalBorrowed = errors.Register(ModuleName, 601, "total borrowed was negative") + ErrNegativeAPY = errors.Register(ModuleName, 602, "negative APY") + ErrNegativeTimeElapsed = errors.Register(ModuleName, 603, "negative time elapsed since last interest time") + ErrInvalidExchangeRate = errors.Register(ModuleName, 604, "exchange rate less than one") + ErrInconsistentTotalBorrow = errors.Register(ModuleName, 605, "total adjusted borrow inconsistency") + ErrExcessiveTimeElapsed = errors.Register(ModuleName, 606, "excessive time elapsed since last interest time") // 7XX = Disabled Functionality - ErrNotLiquidatorNode = sdkerrors.Register(ModuleName, 700, "node has disabled liquidator queries") - ErrNotImplemented = sdkerrors.Register(ModuleName, 701, "not implemented") + ErrNotLiquidatorNode = errors.Register(ModuleName, 700, "node has disabled liquidator queries") + ErrNotImplemented = errors.Register(ModuleName, 701, "not implemented") ) diff --git a/x/leverage/types/genesis.go b/x/leverage/types/genesis.go index 67f407fff4..e884600ceb 100644 --- a/x/leverage/types/genesis.go +++ b/x/leverage/types/genesis.go @@ -5,7 +5,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // NewGenesisState creates a new GenesisState object @@ -95,7 +94,7 @@ func (gs GenesisState) Validate() error { } if rate.Scalar.LT(sdk.OneDec()) { - return sdkerrors.Wrap(ErrInvalidExchangeRate, rate.String()) + return ErrInvalidExchangeRate.Wrap(rate.String()) } } diff --git a/x/leverage/types/msgs.go b/x/leverage/types/msgs.go index ab731e6531..e3265db408 100644 --- a/x/leverage/types/msgs.go +++ b/x/leverage/types/msgs.go @@ -1,8 +1,8 @@ package types import ( + "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/umee-network/umee/v4/util/checkers" "gopkg.in/yaml.v3" @@ -42,7 +42,7 @@ func (msg MsgGovUpdateRegistry) ValidateBasic() error { for _, token := range msg.AddTokens { if err := token.Validate(); err != nil { - return sdkerrors.Wrap(err, "token") + return errors.Wrap(err, "token") } } @@ -52,7 +52,7 @@ func (msg MsgGovUpdateRegistry) ValidateBasic() error { for _, token := range msg.UpdateTokens { if err := token.Validate(); err != nil { - return sdkerrors.Wrap(err, "token") + return errors.Wrap(err, "token") } } @@ -75,7 +75,7 @@ func validateRegistryTokenDenoms(tokens []Token) error { tokenDenoms := map[string]bool{} for _, token := range tokens { if _, ok := tokenDenoms[token.BaseDenom]; ok { - return sdkerrors.Wrapf(ErrDuplicateToken, "duplicate token with baseDenom %s", token.BaseDenom) + return ErrDuplicateToken.Wrapf("duplicate token with baseDenom %s", token.BaseDenom) } tokenDenoms[token.BaseDenom] = true } diff --git a/x/leverage/types/token.go b/x/leverage/types/token.go index 7df2670ae6..9f0e364a5d 100644 --- a/x/leverage/types/token.go +++ b/x/leverage/types/token.go @@ -141,7 +141,7 @@ func (t Token) Validate() error { // AssertSupplyEnabled returns an error if a Token cannot be supplied. func (t Token) AssertSupplyEnabled() error { if !t.EnableMsgSupply { - return sdkerrors.Wrap(ErrSupplyNotAllowed, t.BaseDenom) + return ErrSupplyNotAllowed.Wrap(t.BaseDenom) } return nil } @@ -149,7 +149,7 @@ func (t Token) AssertSupplyEnabled() error { // AssertBorrowEnabled returns an error if a Token cannot be borrowed. func (t Token) AssertBorrowEnabled() error { if !t.EnableMsgBorrow { - return sdkerrors.Wrap(ErrBorrowNotAllowed, t.BaseDenom) + return ErrBorrowNotAllowed.Wrap(t.BaseDenom) } return nil } @@ -157,7 +157,7 @@ func (t Token) AssertBorrowEnabled() error { // AssertNotBlacklisted returns an error if a Token is blacklisted. func (t Token) AssertNotBlacklisted() error { if t.Blacklist { - return sdkerrors.Wrap(ErrBlacklisted, t.BaseDenom) + return ErrBlacklisted.Wrap(t.BaseDenom) } return nil } diff --git a/x/oracle/keeper/historic_price.go b/x/oracle/keeper/historic_price.go index 4ccf3a4b64..2358d9c076 100644 --- a/x/oracle/keeper/historic_price.go +++ b/x/oracle/keeper/historic_price.go @@ -1,10 +1,8 @@ package keeper import ( - "fmt" - + "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/umee-network/umee/v4/util" "github.com/umee-network/umee/v4/util/decmath" @@ -37,7 +35,7 @@ func (k Keeper) CalcAndSetHistoricMedian( historicPrices := k.historicPrices(ctx, denom, k.MaximumPriceStamps(ctx)) median, err := decmath.Median(historicPrices) if err != nil { - return sdkerrors.Wrap(err, fmt.Sprintf("denom: %s", denom)) + return errors.Wrap(err, "denom: "+denom) } block := uint64(ctx.BlockHeight()) @@ -67,7 +65,7 @@ func (k Keeper) HistoricMedianDeviation( blockNum := uint64(ctx.BlockHeight()) - blockDiff bz := store.Get(types.KeyMedianDeviation(denom, blockNum)) if bz == nil { - return &types.Price{}, sdkerrors.Wrap(types.ErrNoMedianDeviation, fmt.Sprintf("denom: %s", denom)) + return &types.Price{}, types.ErrNoMedianDeviation.Wrap("denom: " + denom) } decProto := sdk.DecProto{} @@ -87,14 +85,14 @@ func (k Keeper) WithinHistoricMedianDeviation( // get latest median medians := k.HistoricMedians(ctx, denom, 1) if len(medians) == 0 { - return false, sdkerrors.Wrap(types.ErrNoMedian, fmt.Sprintf("denom: %s", denom)) + return false, types.ErrNoMedian.Wrap("denom: " + denom) } median := medians[0].ExchangeRateTuple.ExchangeRate // get latest historic price prices := k.historicPrices(ctx, denom, 1) if len(prices) == 0 { - return false, sdkerrors.Wrap(types.ErrNoHistoricPrice, fmt.Sprintf("denom: %s", denom)) + return false, types.ErrNoHistoricPrice.Wrap("denom: " + denom) } price := prices[0] @@ -116,7 +114,7 @@ func (k Keeper) calcAndSetHistoricMedianDeviation( ) error { medianDeviation, err := decmath.MedianDeviation(median, prices) if err != nil { - return sdkerrors.Wrap(err, fmt.Sprintf("denom: %s", denom)) + return errors.Wrap(err, "denom: "+denom) } block := uint64(ctx.BlockHeight()) @@ -149,7 +147,7 @@ func (k Keeper) MedianOfHistoricMedians( } median, err := decmath.Median(medians.Decs()) if err != nil { - return sdk.ZeroDec(), 0, sdkerrors.Wrap(err, fmt.Sprintf("denom: %s", denom)) + return sdk.ZeroDec(), 0, errors.Wrap(err, "denom: "+denom) } return median, uint32(len(medians)), nil @@ -169,7 +167,7 @@ func (k Keeper) AverageOfHistoricMedians( } average, err := decmath.Average(medians.Decs()) if err != nil { - return sdk.ZeroDec(), 0, sdkerrors.Wrap(err, fmt.Sprintf("denom: %s", denom)) + return sdk.ZeroDec(), 0, errors.Wrap(err, "denom: "+denom) } return average, uint32(len(medians)), nil @@ -189,7 +187,7 @@ func (k Keeper) MaxOfHistoricMedians( } max, err := decmath.Max(medians.Decs()) if err != nil { - return sdk.ZeroDec(), 0, sdkerrors.Wrap(err, fmt.Sprintf("denom: %s", denom)) + return sdk.ZeroDec(), 0, errors.Wrap(err, "denom: "+denom) } return max, uint32(len(medians)), nil @@ -209,7 +207,7 @@ func (k Keeper) MinOfHistoricMedians( } min, err := decmath.Min(medians.Decs()) if err != nil { - return sdk.ZeroDec(), 0, sdkerrors.Wrap(err, fmt.Sprintf("denom: %s", denom)) + return sdk.ZeroDec(), 0, errors.Wrap(err, "denom: "+denom) } return min, uint32(len(medians)), nil diff --git a/x/oracle/keeper/keeper.go b/x/oracle/keeper/keeper.go index 575a952b25..9f23312b48 100644 --- a/x/oracle/keeper/keeper.go +++ b/x/oracle/keeper/keeper.go @@ -7,7 +7,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" gogotypes "github.com/gogo/protobuf/types" @@ -77,7 +76,7 @@ func (k Keeper) GetExchangeRate(ctx sdk.Context, symbol string) (sdk.Dec, error) symbol = strings.ToUpper(symbol) b := store.Get(types.KeyExchangeRate(symbol)) if b == nil { - return sdk.ZeroDec(), sdkerrors.Wrap(types.ErrUnknownDenom, symbol) + return sdk.ZeroDec(), types.ErrUnknownDenom.Wrap(symbol) } decProto := sdk.DecProto{} @@ -101,7 +100,7 @@ func (k Keeper) GetExchangeRateBase(ctx sdk.Context, denom string) (sdk.Dec, err } } if len(symbol) == 0 { - return sdk.ZeroDec(), sdkerrors.Wrap(types.ErrUnknownDenom, denom) + return sdk.ZeroDec(), types.ErrUnknownDenom.Wrap(denom) } exchangeRate, err := k.GetExchangeRate(ctx, symbol) @@ -263,7 +262,7 @@ func (k Keeper) GetAggregateExchangeRatePrevote( bz := store.Get(types.KeyAggregateExchangeRatePrevote(voter)) if bz == nil { - return types.AggregateExchangeRatePrevote{}, sdkerrors.Wrap(types.ErrNoAggregatePrevote, voter.String()) + return types.AggregateExchangeRatePrevote{}, types.ErrNoAggregatePrevote.Wrap(voter.String()) } var aggregatePrevote types.AggregateExchangeRatePrevote @@ -330,7 +329,7 @@ func (k Keeper) GetAggregateExchangeRateVote( bz := store.Get(types.KeyAggregateExchangeRateVote(voter)) if bz == nil { - return types.AggregateExchangeRateVote{}, sdkerrors.Wrap(types.ErrNoAggregateVote, voter.String()) + return types.AggregateExchangeRateVote{}, types.ErrNoAggregateVote.Wrap(voter.String()) } var aggregateVote types.AggregateExchangeRateVote @@ -391,7 +390,7 @@ func (k Keeper) ValidateFeeder(ctx sdk.Context, feederAddr sdk.AccAddress, valAd return err } if !delegate.Equals(feederAddr) { - return sdkerrors.Wrap(types.ErrNoVotingPermission, feederAddr.String()) + return types.ErrNoVotingPermission.Wrap(feederAddr.String()) } return nil diff --git a/x/oracle/keeper/msg_server.go b/x/oracle/keeper/msg_server.go index 26f47992b5..1d2a208dc6 100644 --- a/x/oracle/keeper/msg_server.go +++ b/x/oracle/keeper/msg_server.go @@ -4,7 +4,6 @@ import ( "context" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/umee-network/umee/v4/x/oracle/types" @@ -46,7 +45,7 @@ func (ms msgServer) AggregateExchangeRatePrevote( // Convert hex string to votehash voteHash, err := types.AggregateVoteHashFromHex(msg.Hash) if err != nil { - return nil, sdkerrors.Wrap(types.ErrInvalidHash, err.Error()) + return nil, types.ErrInvalidHash.Wrap(err.Error()) } aggregatePrevote := types.NewAggregateExchangeRatePrevote(voteHash, valAddr, uint64(ctx.BlockHeight())) @@ -75,7 +74,7 @@ func (ms msgServer) AggregateExchangeRateVote( params := ms.GetParams(ctx) aggregatePrevote, err := ms.GetAggregateExchangeRatePrevote(ctx, valAddr) if err != nil { - return nil, sdkerrors.Wrap(types.ErrNoAggregatePrevote, msg.Validator) + return nil, types.ErrNoAggregatePrevote.Wrap(msg.Validator) } // Check the vote is submitted in the `period == prevote.period+1` @@ -91,7 +90,7 @@ func (ms msgServer) AggregateExchangeRateVote( // Verify that the vote hash and prevote hash match hash := types.GetAggregateVoteHash(msg.Salt, msg.ExchangeRates, valAddr) if aggregatePrevote.Hash != hash.String() { - return nil, sdkerrors.Wrapf(types.ErrVerificationFailed, "must be given %s not %s", aggregatePrevote.Hash, hash) + return nil, types.ErrVerificationFailed.Wrapf("must be given %s not %s", aggregatePrevote.Hash, hash) } // Filter out rates which aren't included in the AcceptList @@ -129,7 +128,7 @@ func (ms msgServer) DelegateFeedConsent( val := ms.StakingKeeper.Validator(ctx, operatorAddr) if val == nil { - return nil, sdkerrors.Wrap(stakingtypes.ErrNoValidatorFound, msg.Operator) + return nil, stakingtypes.ErrNoValidatorFound.Wrap(msg.Operator) } ms.SetFeederDelegation(ctx, operatorAddr, delegateAddr) diff --git a/x/oracle/types/errors.go b/x/oracle/types/errors.go index 97c03a42de..9794dc23a9 100644 --- a/x/oracle/types/errors.go +++ b/x/oracle/types/errors.go @@ -3,12 +3,13 @@ package types import ( "fmt" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "cosmossdk.io/errors" "github.com/tendermint/tendermint/crypto/tmhash" ) // Oracle sentinel errors var ( +<<<<<<< HEAD ErrInvalidExchangeRate = sdkerrors.Register(ModuleName, 1, "invalid exchange rate") ErrNoPrevote = sdkerrors.Register(ModuleName, 2, "no prevote") ErrNoVote = sdkerrors.Register(ModuleName, 3, "no vote") @@ -29,4 +30,28 @@ var ( ErrNoHistoricPrice = sdkerrors.Register(ModuleName, 18, "no historic price for this denom at this block") ErrNoMedian = sdkerrors.Register(ModuleName, 19, "no median for this denom at this block") ErrNoMedianDeviation = sdkerrors.Register(ModuleName, 20, "no median deviation for this denom at this block") +======= + ErrInvalidExchangeRate = errors.Register(ModuleName, 1, "invalid exchange rate") + ErrNoPrevote = errors.Register(ModuleName, 2, "no prevote") + ErrNoVote = errors.Register(ModuleName, 3, "no vote") + ErrNoVotingPermission = errors.Register(ModuleName, 4, "unauthorized voter") + ErrInvalidHash = errors.Register(ModuleName, 5, "invalid hash") + ErrInvalidHashLength = errors.Register(ModuleName, 6, fmt.Sprintf("invalid hash length; should equal %d", tmhash.TruncatedSize)) //nolint: lll + ErrVerificationFailed = errors.Register(ModuleName, 7, "hash verification failed") + ErrRevealPeriodMissMatch = errors.Register(ModuleName, 8, "reveal period of submitted vote does not match with registered prevote") //nolint: lll + ErrInvalidSaltLength = errors.Register(ModuleName, 9, "invalid salt length; must be 64") + ErrInvalidSaltFormat = errors.Register(ModuleName, 10, "invalid salt format") + ErrNoAggregatePrevote = errors.Register(ModuleName, 11, "no aggregate prevote") + ErrNoAggregateVote = errors.Register(ModuleName, 12, "no aggregate vote") + ErrUnknownDenom = errors.Register(ModuleName, 13, "unknown denom") + ErrNegativeOrZeroRate = errors.Register(ModuleName, 14, "invalid exchange rate; should be positive") + ErrExistingPrevote = errors.Register(ModuleName, 15, "prevote already submitted for this voting period") + ErrBallotNotSorted = errors.Register(ModuleName, 16, "ballot must be sorted before this operation") + ErrNotImplemented = errors.Register(ModuleName, 17, "function not implemented") + ErrNoHistoricPrice = errors.Register(ModuleName, 18, "no historic price for this denom at this block") + ErrNoMedian = errors.Register(ModuleName, 19, "no median for this denom at this block") + ErrNoMedianDeviation = errors.Register(ModuleName, 20, "no median deviation for this denom at this block") + ErrMalformedLatestAvgPrice = errors.Register(ModuleName, 21, "malformed latest avg price, expecting one byte") + ErrNoLatestAvgPrice = errors.Register(ModuleName, 22, "no latest average price") +>>>>>>> 37909a3 (fix: deprecated use of sdkerrors (#1788)) ) diff --git a/x/oracle/types/msgs.go b/x/oracle/types/msgs.go index f8eb975fec..d663bcae5e 100644 --- a/x/oracle/types/msgs.go +++ b/x/oracle/types/msgs.go @@ -47,7 +47,7 @@ func (msg MsgAggregateExchangeRatePrevote) GetSigners() []sdk.AccAddress { func (msg MsgAggregateExchangeRatePrevote) ValidateBasic() error { _, err := AggregateVoteHashFromHex(msg.Hash) if err != nil { - return sdkerrors.Wrapf(ErrInvalidHash, "invalid vote hash (%s)", err) + return ErrInvalidHash.Wrapf("invalid vote hash (%s)", err) } // HEX encoding doubles the hash length @@ -57,12 +57,12 @@ func (msg MsgAggregateExchangeRatePrevote) ValidateBasic() error { _, err = sdk.AccAddressFromBech32(msg.Feeder) if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid feeder address (%s)", err) + return sdkerrors.ErrInvalidAddress.Wrapf("invalid feeder address (%s)", err) } _, err = sdk.ValAddressFromBech32(msg.Validator) if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid operator address (%s)", err) + return sdkerrors.ErrInvalidAddress.Wrapf("invalid operator address (%s)", err) } return nil @@ -102,29 +102,29 @@ func (msg MsgAggregateExchangeRateVote) GetSigners() []sdk.AccAddress { func (msg MsgAggregateExchangeRateVote) ValidateBasic() error { _, err := sdk.AccAddressFromBech32(msg.Feeder) if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid feeder address (%s)", err) + return sdkerrors.ErrInvalidAddress.Wrapf("invalid feeder address (%s)", err) } _, err = sdk.ValAddressFromBech32(msg.Validator) if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid operator address (%s)", err) + return sdkerrors.ErrInvalidAddress.Wrapf("invalid operator address (%s)", err) } if l := len(msg.ExchangeRates); l == 0 { - return sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "must provide at least one oracle exchange rate") + return sdkerrors.ErrInvalidRequest.Wrap("must provide at least one oracle exchange rate") } else if l > 4096 { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "exchange rates string can not exceed 4096 characters") + return sdkerrors.ErrInvalidRequest.Wrap("exchange rates string can not exceed 4096 characters") } exchangeRates, err := ParseExchangeRateTuples(msg.ExchangeRates) if err != nil { - return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "failed to parse exchange rates string cause: "+err.Error()) + return sdkerrors.ErrInvalidCoins.Wrap("failed to parse exchange rates string cause: " + err.Error()) } for _, exchangeRate := range exchangeRates { // check overflow bit length if exchangeRate.ExchangeRate.BigInt().BitLen() > 255+sdk.DecimalPrecisionBits { - return sdkerrors.Wrap(ErrInvalidExchangeRate, "overflow") + return ErrInvalidExchangeRate.Wrap("overflow") } } @@ -133,7 +133,7 @@ func (msg MsgAggregateExchangeRateVote) ValidateBasic() error { } _, err = AggregateVoteHashFromHex(msg.Salt) if err != nil { - return sdkerrors.Wrap(ErrInvalidSaltFormat, "salt must be a valid hex string") + return ErrInvalidSaltFormat.Wrap("salt must be a valid hex string") } return nil @@ -168,12 +168,12 @@ func (msg MsgDelegateFeedConsent) GetSigners() []sdk.AccAddress { func (msg MsgDelegateFeedConsent) ValidateBasic() error { _, err := sdk.ValAddressFromBech32(msg.Operator) if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid operator address (%s)", err) + return sdkerrors.ErrInvalidAddress.Wrapf("invalid operator address (%s)", err) } _, err = sdk.AccAddressFromBech32(msg.Delegate) if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid delegate address (%s)", err) + return sdkerrors.ErrInvalidAddress.Wrapf("invalid delegate address (%s)", err) } return nil diff --git a/x/oracle/types/msgs_test.go b/x/oracle/types/msgs_test.go index e071a2a211..1d91387fe2 100644 --- a/x/oracle/types/msgs_test.go +++ b/x/oracle/types/msgs_test.go @@ -91,7 +91,7 @@ func TestMsgAggregateExchangeRateVote(t *testing.T) { msgInvalidSalt := "invalid salt length; must be 64" msgInvalidOverflowValue := "out of range; bitLen:" msgInvalidHexString := "salt must be a valid hex string: invalid salt format" - msgInvalidUnknownRequest := "must provide at least one oracle exchange rate: unknown request" + msgInvalidUnknownRequest := "must provide at least one oracle exchange rate: invalid request" msgInvalidFeederAddr := "invalid feeder address (empty address string is not allowed): invalid address" msgInvalidOperatorAddr := "invalid operator address (empty address string is not allowed): invalid address" msgInvalidOraclePrice := "failed to parse exchange rates string cause: invalid oracle price: invalid coins" diff --git a/x/uibc/errors.go b/x/uibc/errors.go new file mode 100644 index 0000000000..70c6804005 --- /dev/null +++ b/x/uibc/errors.go @@ -0,0 +1,10 @@ +package uibc + +import ( + "cosmossdk.io/errors" +) + +var ( + ErrQuotaExceeded = errors.Register(ModuleName, 1, "quota transfer exceeded") + ErrNoQuotaForIBCDenom = errors.Register(ModuleName, 2, "no quota for ibc denom") +) diff --git a/x/uibc/msg.go b/x/uibc/msg.go new file mode 100644 index 0000000000..2156ad989c --- /dev/null +++ b/x/uibc/msg.go @@ -0,0 +1,118 @@ +package uibc + +import ( + "encoding/json" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/umee-network/umee/v4/util/checkers" +) + +var ( + _ sdk.Msg = &MsgGovUpdateQuota{} + _ sdk.Msg = &MsgGovSetIBCPause{} +) + +// GetTitle returns the title of the proposal. +func (msg *MsgGovUpdateQuota) GetTitle() string { return msg.Title } + +// GetDescription implements govv1b1.Content interface. +func (msg *MsgGovUpdateQuota) GetDescription() string { return msg.Description } + +// Route implements Msg +func (msg MsgGovUpdateQuota) Route() string { return RouterKey } + +// Type implements Msg +func (msg MsgGovUpdateQuota) Type() string { return sdk.MsgTypeURL(&msg) } + +// String implements the Stringer interface. +func (msg *MsgGovUpdateQuota) String() string { + out, _ := json.Marshal(msg) + return string(out) +} + +// ValidateBasic implements Msg +func (msg *MsgGovUpdateQuota) ValidateBasic() error { + if err := checkers.ValidateAddr(msg.Authority, "authority"); err != nil { + return err + } + + if msg.Total.IsNil() || !msg.Total.IsPositive() { + return sdkerrors.ErrInvalidRequest.Wrap("total quota must be positive") + } + + if msg.PerDenom.IsNil() || !msg.PerDenom.IsPositive() { + return sdkerrors.ErrInvalidRequest.Wrap("quota per denom must be positive") + } + + if msg.Total.LT(msg.PerDenom) { + return sdkerrors.ErrInvalidRequest.Wrap("total quota must be greater than or equal to per_denom quota") + } + + return checkers.ValidateProposal(msg.Title, msg.Description, msg.Authority) +} + +// GetSignBytes implements Msg +func (msg *MsgGovUpdateQuota) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) +} + +// GetSigners implements Msg +func (msg *MsgGovUpdateQuota) GetSigners() []sdk.AccAddress { + return checkers.Signers(msg.Authority) +} + +// GetTitle implements govv1b1.Content interface. +func (msg *MsgGovSetIBCPause) GetTitle() string { return msg.Title } + +// GetDescription implements govv1b1.Content interface. +func (msg *MsgGovSetIBCPause) GetDescription() string { return msg.Description } + +// Route implements Msg +func (msg MsgGovSetIBCPause) Route() string { return RouterKey } + +// Type implements Msg +func (msg MsgGovSetIBCPause) Type() string { return sdk.MsgTypeURL(&msg) } + +// String implements the Stringer interface. +func (msg *MsgGovSetIBCPause) String() string { + out, _ := json.Marshal(msg) + return string(out) +} + +// ValidateBasic implements Msg +func (msg *MsgGovSetIBCPause) ValidateBasic() error { + if err := checkers.ValidateAddr(msg.Authority, "authority"); err != nil { + return err + } + + if err := validateIBCTransferStatus(msg.IbcPauseStatus); err != nil { + return err + } + + return checkers.ValidateProposal(msg.Title, msg.Description, msg.Authority) +} + +// GetSignBytes implements Msg +func (msg *MsgGovSetIBCPause) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners implements Msg +func (msg *MsgGovSetIBCPause) GetSigners() []sdk.AccAddress { + return checkers.Signers(msg.Authority) +} + +func (q *Quota) Validate() error { + if len(q.IbcDenom) == 0 { + return sdkerrors.ErrInvalidRequest.Wrap("ibc denom shouldn't be empty") + } + + if q.OutflowSum.IsNil() || q.OutflowSum.IsNegative() { + return sdkerrors.ErrInvalidRequest.Wrap("ibc denom quota expires shouldn't be empty") + } + + return nil +} diff --git a/x/uibc/quota/ibc_module.go b/x/uibc/quota/ibc_module.go new file mode 100644 index 0000000000..6b111efaa9 --- /dev/null +++ b/x/uibc/quota/ibc_module.go @@ -0,0 +1,103 @@ +package quota + +import ( + "encoding/json" + + "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + transfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/v5/modules/core/05-port/types" + + "github.com/umee-network/umee/v4/util/sdkutil" + "github.com/umee-network/umee/v4/x/uibc" + "github.com/umee-network/umee/v4/x/uibc/quota/keeper" +) + +type IBCMiddleware struct { + porttypes.IBCModule + keeper keeper.Keeper + cdc codec.JSONCodec +} + +// NewIBCMiddleware creates a new IBCMiddlware given the keeper and underlying application +func NewIBCMiddleware(app porttypes.IBCModule, k keeper.Keeper, cdc codec.JSONCodec) IBCMiddleware { + return IBCMiddleware{ + IBCModule: app, + keeper: k, + cdc: cdc, + } +} + +// OnAcknowledgementPacket implements types.Middleware +func (im IBCMiddleware) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, + relayer sdk.AccAddress, +) error { + var ack channeltypes.Acknowledgement + if err := im.cdc.UnmarshalJSON(acknowledgement, &ack); err != nil { + return errors.Wrap(err, "cannot unmarshal ICS-20 transfer packet acknowledgement") + } + if _, ok := ack.Response.(*channeltypes.Acknowledgement_Error); ok { + err := im.RevertQuotaUpdate(ctx, packet.Data) + emitOnRevertQuota(&ctx, "acknowledgement", packet.Data, err) + } + + return im.IBCModule.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer) +} + +// OnTimeoutPacket implements types.Middleware +func (im IBCMiddleware) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) error { + err := im.RevertQuotaUpdate(ctx, packet.Data) + emitOnRevertQuota(&ctx, "timeout", packet.Data, err) + + return im.IBCModule.OnTimeoutPacket(ctx, packet, relayer) +} + +// RevertQuotaUpdate Notifies the contract that a sent packet wasn't properly received +func (im IBCMiddleware) RevertQuotaUpdate( + ctx sdk.Context, + packetData []byte, +) error { + var data transfertypes.FungibleTokenPacketData + if err := im.cdc.UnmarshalJSON(packetData, &data); err != nil { + return errors.Wrap(err, + "cannot unmarshal ICS-20 transfer packet data") + } + + amount, ok := sdkmath.NewIntFromString(data.Amount) + if !ok { + return sdkerrors.ErrInvalidRequest.Wrapf("invalid transfer amount %s", data.Amount) + } + + return im.keeper.UndoUpdateQuota(ctx, data.Denom, amount) +} + +func ValidateReceiverAddress(packet channeltypes.Packet) error { + var packetData transfertypes.FungibleTokenPacketData + if err := json.Unmarshal(packet.GetData(), &packetData); err != nil { + return err + } + if len(packetData.Receiver) >= 4096 { + return sdkerrors.ErrInvalidAddress.Wrapf( + "IBC Receiver address too long. Max supported length is %d", 4096, + ) + } + return nil +} + +// emitOnRevertQuota emits events related to quota update revert. +// packetData is ICS 20 packet data bytes. +func emitOnRevertQuota(ctx *sdk.Context, failureType string, packetData []byte, err error) { + if err == nil { + return + } + ctx.Logger().Error("revert quota update error", "err", err) + sdkutil.Emit(ctx, &uibc.EventBadRevert{ + Module: uibc.ModuleName, + FailureType: failureType, + Packet: string(packetData), + }) +} diff --git a/x/uibc/quota/keeper/quota.go b/x/uibc/quota/keeper/quota.go new file mode 100644 index 0000000000..7799cb841b --- /dev/null +++ b/x/uibc/quota/keeper/quota.go @@ -0,0 +1,251 @@ +package keeper + +import ( + "encoding/json" + "strings" + "time" + + sdkmath "cosmossdk.io/math" + prefixsore "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + transfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types" + "github.com/cosmos/ibc-go/v5/modules/core/exported" + + ltypes "github.com/umee-network/umee/v4/x/leverage/types" + "github.com/umee-network/umee/v4/x/uibc" +) + +// GetQuotaOfIBCDenoms returns quota of all tokens. +func (k Keeper) GetQuotaOfIBCDenoms(ctx sdk.Context) ([]uibc.Quota, error) { + var quotaOfIBCDenoms []uibc.Quota + + prefix := uibc.KeyPrefixDenomQuota + store := ctx.KVStore(k.storeKey) + + iter := sdk.KVStorePrefixIterator(store, prefix) + defer iter.Close() + + for ; iter.Valid(); iter.Next() { + var quotaOfIBCDenom uibc.Quota + if err := quotaOfIBCDenom.Unmarshal(iter.Value()); err != nil { + return nil, err + } + + quotaOfIBCDenoms = append(quotaOfIBCDenoms, quotaOfIBCDenom) + } + + return quotaOfIBCDenoms, nil +} + +// GetQuotaByDenom retunes the rate limits of ibc denom. +func (k Keeper) GetQuotaByDenom(ctx sdk.Context, ibcDenom string) (*uibc.Quota, error) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(uibc.KeyTotalOutflows(ibcDenom)) + if bz == nil { + return nil, uibc.ErrNoQuotaForIBCDenom + } + + var quotaOfIBCDenom uibc.Quota + if err := k.cdc.Unmarshal(bz, "aOfIBCDenom); err != nil { + return nil, err + } + + return "aOfIBCDenom, nil +} + +// SetDenomQuotas save the updated token quota. +func (k Keeper) SetDenomQuotas(ctx sdk.Context, quotas []uibc.Quota) { + for _, quotaOfIBCDenom := range quotas { + k.SetDenomQuota(ctx, quotaOfIBCDenom) + } +} + +// SetDenomQuota save the quota of denom into store. +func (k Keeper) SetDenomQuota(ctx sdk.Context, quotaOfIBCDenom uibc.Quota) { + store := ctx.KVStore(k.storeKey) + key := uibc.KeyTotalOutflows(quotaOfIBCDenom.IbcDenom) + store.Set(key, k.cdc.MustMarshal("aOfIBCDenom)) +} + +// GetTotalOutflowSum returns the total outflow of ibc-transfer amount. +func (k Keeper) GetTotalOutflowSum(ctx sdk.Context) sdk.Dec { + store := ctx.KVStore(k.storeKey) + bz := store.Get(uibc.KeyPrefixTotalOutflows) + return sdk.MustNewDecFromStr(string(bz)) +} + +// SetTotalOutflowSum save the total outflow of ibc-transfer amount. +func (k Keeper) SetTotalOutflowSum(ctx sdk.Context, amount sdk.Dec) { + store := ctx.KVStore(k.storeKey) + store.Set(uibc.KeyPrefixTotalOutflows, []byte(amount.String())) +} + +// SetExpire save the quota expires time of ibc denom into store. +func (k Keeper) SetExpire(ctx sdk.Context, expires time.Time) error { + store := ctx.KVStore(k.storeKey) + bz, err := expires.MarshalBinary() + if err != nil { + return err + } + store.Set(uibc.KeyPrefixQuotaExpires, bz) + + return nil +} + +// GetExpire returns ibc-transfer quota expires time. +func (k Keeper) GetExpire(ctx sdk.Context) (*time.Time, error) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(uibc.KeyPrefixQuotaExpires) + if bz == nil { + return nil, nil + } + quotaExpires := ctx.BlockTime() + if err := quotaExpires.UnmarshalBinary(bz); err != nil { + return "aExpires, err + } + return "aExpires, nil +} + +// ResetQuota will reset the ibc-transfer quotas +func (k Keeper) ResetQuota(ctx sdk.Context) error { + qd := k.GetParams(ctx).QuotaDuration + zero := sdk.NewDec(0) + newExpires := ctx.BlockTime().Add(qd) + if err := k.SetExpire(ctx, newExpires); err != nil { + return err + } + k.SetTotalOutflowSum(ctx, zero) + store := ctx.KVStore(k.storeKey) + store = prefixsore.NewStore(store, uibc.KeyPrefixDenomQuota) + iter := sdk.KVStorePrefixIterator(store, nil) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + ibcDenom := iter.Key() + q := uibc.Quota{IbcDenom: string(ibcDenom), OutflowSum: zero} + store.Set(ibcDenom, k.cdc.MustMarshal(&q)) + } + return nil +} + +// CheckAndUpdateQuota checks the quota of ibc-transfer of denom +func (k Keeper) CheckAndUpdateQuota(ctx sdk.Context, denom string, amount sdkmath.Int) error { + params := k.GetParams(ctx) + + quotaOfIBCDenom, err := k.GetQuotaByDenom(ctx, denom) + if err != nil { + return err + } + + if quotaOfIBCDenom == nil { + return nil + } + + exchangePrice, err := k.getExchangePrice(ctx, denom, amount) + if err != nil { + // Note: skip the ibc-transfer quota checking if `denom` is not support by leverage + // TODO: write test case for this + if ltypes.ErrNotRegisteredToken.Is(err) { + return nil + } else if err != nil { + return err + } + } + + // checking ibc-transfer token quota + quotaOfIBCDenom.OutflowSum = quotaOfIBCDenom.OutflowSum.Add(exchangePrice) + if quotaOfIBCDenom.OutflowSum.GT(params.TokenQuota) { + return uibc.ErrQuotaExceeded + } + + // checking total outflow quota + totalOutflowSum := k.GetTotalOutflowSum(ctx).Add(exchangePrice) + if totalOutflowSum.GT(params.TotalQuota) { + return uibc.ErrQuotaExceeded + } + + // update the per token outflow sum + k.SetDenomQuota(ctx, *quotaOfIBCDenom) + // updating the total outflow sum + k.SetTotalOutflowSum(ctx, totalOutflowSum) + return nil +} + +func (k Keeper) getExchangePrice(ctx sdk.Context, denom string, amount sdkmath.Int) (sdk.Dec, error) { + transferCoin := sdk.NewCoin(denom, amount) + var err error + + // convert to base asset if it is `uToken` + if ltypes.HasUTokenPrefix(denom) { + transferCoin, err = k.leverageKeeper.ExchangeUToken(ctx, transferCoin) + if err != nil { + return sdk.Dec{}, err + } + } + + // get the exchange price (eg: UMEE) in USD from oracle using base denom eg: `uumee` + return k.leverageKeeper.TokenValue(ctx, transferCoin, ltypes.PriceModeSpot) +} + +// UndoUpdateQuota undo the quota of ibc denom +func (k Keeper) UndoUpdateQuota(ctx sdk.Context, denom string, amount sdkmath.Int) error { + quotaOfIBCDenom, err := k.GetQuotaByDenom(ctx, denom) + if err != nil { + return err + } + + if quotaOfIBCDenom == nil { + return nil + } + + exchangePrice, err := k.getExchangePrice(ctx, denom, amount) + if err != nil { + // Note: skip the ibc-transfer quota checking if `denom` is not support by leverage + if ltypes.ErrNotRegisteredToken.Is(err) { + return nil + } else if err != nil { + return err + } + } + + // reset the outflow limit of token + quotaOfIBCDenom.OutflowSum = quotaOfIBCDenom.OutflowSum.Sub(exchangePrice) + k.SetDenomQuota(ctx, *quotaOfIBCDenom) + + // reset the total outflow sum + totalOutflowSum := k.GetTotalOutflowSum(ctx) + k.SetTotalOutflowSum(ctx, totalOutflowSum.Sub(exchangePrice)) + return nil +} + +// GetFundsFromPacket returns transfer amount and denom +func (k Keeper) GetFundsFromPacket(packet exported.PacketI) (sdkmath.Int, string, error) { + var packetData transfertypes.FungibleTokenPacketData + err := json.Unmarshal(packet.GetData(), &packetData) + if err != nil { + return sdkmath.Int{}, "", err + } + + amount, ok := sdkmath.NewIntFromString(packetData.Amount) + if !ok { + return sdkmath.Int{}, "", sdkerrors.ErrInvalidRequest.Wrapf("invalid transfer amount %s", packetData.Amount) + } + + return amount, k.GetLocalDenom(packetData.Denom), nil +} + +// GetLocalDenom retruns ibc denom +// Expected denoms in the following cases: +// +// send non-native: transfer/channel-0/denom -> ibc/xxx +// send native: denom -> denom +// recv (B)non-native: denom +// recv (B)native: transfer/channel-0/denom +func (k Keeper) GetLocalDenom(denom string) string { + if strings.HasPrefix(denom, "transfer/") { + denomTrace := transfertypes.ParseDenomTrace(denom) + return denomTrace.IBCDenom() + } + + return denom +} diff --git a/x/uibc/quota/keeper/relay.go b/x/uibc/quota/keeper/relay.go new file mode 100644 index 0000000000..64e432aa6a --- /dev/null +++ b/x/uibc/quota/keeper/relay.go @@ -0,0 +1,36 @@ +package keeper + +import ( + "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + ibcexported "github.com/cosmos/ibc-go/v5/modules/core/exported" +) + +// SendPacket wraps IBC ChannelKeeper's SendPacket function +func (k Keeper) SendPacket(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI) error { + funds, denom, err := k.GetFundsFromPacket(packet) + if err != nil { + return errors.Wrap(err, "bad packet in rate limit's SendPacket") + } + + if err := k.CheckAndUpdateQuota(ctx, denom, funds); err != nil { + return errors.Wrap(err, "bad packet in rate limit's SendPacket") + } + + return k.ics4Wrapper.SendPacket(ctx, chanCap, packet) +} + +// WriteAcknowledgement wraps IBC ChannelKeeper's WriteAcknowledgement function +// ICS29 WriteAcknowledgement is used for asynchronous acknowledgements +func (k Keeper) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, + acknowledgement ibcexported.Acknowledgement, +) error { + // ics4Wrapper may be core IBC or higher-level middleware + return k.ics4Wrapper.WriteAcknowledgement(ctx, chanCap, packet, acknowledgement) +} + +// GetAppVersion returns the underlying application version. +func (k Keeper) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { + return k.ics4Wrapper.GetAppVersion(ctx, portID, channelID) +} From 52690036da7ef04512d2277d445a6aa1e0b162b6 Mon Sep 17 00:00:00 2001 From: Adam Moser <63419657+toteki@users.noreply.github.com> Date: Mon, 13 Feb 2023 21:28:54 -0700 Subject: [PATCH 2/5] conflict-- --- x/incentive/errors.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/x/incentive/errors.go b/x/incentive/errors.go index 8297b064bd..4b27e3b9f0 100644 --- a/x/incentive/errors.go +++ b/x/incentive/errors.go @@ -21,12 +21,7 @@ var ( ErrUnbondingWeightOrder = errors.Register(ModuleName, 201, "unbonding tier weights out of order") // 3XX = Gov Proposal -<<<<<<< HEAD - ErrNonzeroRemainingRewards = sdkerrors.Register(ModuleName, 300, "remaining rewards must be zero in proposal") - ErrNonzeroFundedRewards = sdkerrors.Register(ModuleName, 301, "funded rewards must be zero in proposal") -======= ErrNonzeroRemainingRewards = errors.Register(ModuleName, 300, "remaining rewards must be zero in proposal") ErrNonzeroFundedRewards = errors.Register(ModuleName, 301, "funded rewards must be zero in proposal") ErrEmptyProposal = errors.Register(ModuleName, 302, "proposal contains no incentive programs") ->>>>>>> 37909a3 (fix: deprecated use of sdkerrors (#1788)) ) From 9ca47dc2193c9bd71a288cbb75b05db1fbddf6bd Mon Sep 17 00:00:00 2001 From: toteki <63419657+toteki@users.noreply.github.com> Date: Mon, 13 Feb 2023 21:31:24 -0700 Subject: [PATCH 3/5] conflict-- --- x/leverage/keeper/oracle.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/x/leverage/keeper/oracle.go b/x/leverage/keeper/oracle.go index d04340cd72..9646d9b558 100644 --- a/x/leverage/keeper/oracle.go +++ b/x/leverage/keeper/oracle.go @@ -1,20 +1,11 @@ package keeper import ( -<<<<<<< HEAD "strings" -======= "cosmossdk.io/errors" ->>>>>>> 37909a3 (fix: deprecated use of sdkerrors (#1788)) sdk "github.com/cosmos/cosmos-sdk/types" -<<<<<<< HEAD - oracletypes "github.com/umee-network/umee/v4/x/oracle/types" - -======= - "github.com/umee-network/umee/v4/util/sdkutil" ->>>>>>> 37909a3 (fix: deprecated use of sdkerrors (#1788)) "github.com/umee-network/umee/v4/x/leverage/types" oracletypes "github.com/umee-network/umee/v4/x/oracle/types" ) From 945944cc0c3d636f1b8b0b20a30b972fc4293166 Mon Sep 17 00:00:00 2001 From: toteki <63419657+toteki@users.noreply.github.com> Date: Mon, 13 Feb 2023 21:34:11 -0700 Subject: [PATCH 4/5] conflict-- --- x/oracle/types/errors.go | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/x/oracle/types/errors.go b/x/oracle/types/errors.go index 9794dc23a9..9a26ad6e93 100644 --- a/x/oracle/types/errors.go +++ b/x/oracle/types/errors.go @@ -9,28 +9,6 @@ import ( // Oracle sentinel errors var ( -<<<<<<< HEAD - ErrInvalidExchangeRate = sdkerrors.Register(ModuleName, 1, "invalid exchange rate") - ErrNoPrevote = sdkerrors.Register(ModuleName, 2, "no prevote") - ErrNoVote = sdkerrors.Register(ModuleName, 3, "no vote") - ErrNoVotingPermission = sdkerrors.Register(ModuleName, 4, "unauthorized voter") - ErrInvalidHash = sdkerrors.Register(ModuleName, 5, "invalid hash") - ErrInvalidHashLength = sdkerrors.Register(ModuleName, 6, fmt.Sprintf("invalid hash length; should equal %d", tmhash.TruncatedSize)) //nolint: lll - ErrVerificationFailed = sdkerrors.Register(ModuleName, 7, "hash verification failed") - ErrRevealPeriodMissMatch = sdkerrors.Register(ModuleName, 8, "reveal period of submitted vote does not match with registered prevote") //nolint: lll - ErrInvalidSaltLength = sdkerrors.Register(ModuleName, 9, "invalid salt length; must be 64") - ErrInvalidSaltFormat = sdkerrors.Register(ModuleName, 10, "invalid salt format") - ErrNoAggregatePrevote = sdkerrors.Register(ModuleName, 11, "no aggregate prevote") - ErrNoAggregateVote = sdkerrors.Register(ModuleName, 12, "no aggregate vote") - ErrUnknownDenom = sdkerrors.Register(ModuleName, 13, "unknown denom") - ErrNegativeOrZeroRate = sdkerrors.Register(ModuleName, 14, "invalid exchange rate; should be positive") - ErrExistingPrevote = sdkerrors.Register(ModuleName, 15, "prevote already submitted for this voting period") - ErrBallotNotSorted = sdkerrors.Register(ModuleName, 16, "ballot must be sorted before this operation") - ErrNotImplemented = sdkerrors.Register(ModuleName, 17, "functon not implemented") - ErrNoHistoricPrice = sdkerrors.Register(ModuleName, 18, "no historic price for this denom at this block") - ErrNoMedian = sdkerrors.Register(ModuleName, 19, "no median for this denom at this block") - ErrNoMedianDeviation = sdkerrors.Register(ModuleName, 20, "no median deviation for this denom at this block") -======= ErrInvalidExchangeRate = errors.Register(ModuleName, 1, "invalid exchange rate") ErrNoPrevote = errors.Register(ModuleName, 2, "no prevote") ErrNoVote = errors.Register(ModuleName, 3, "no vote") @@ -53,5 +31,4 @@ var ( ErrNoMedianDeviation = errors.Register(ModuleName, 20, "no median deviation for this denom at this block") ErrMalformedLatestAvgPrice = errors.Register(ModuleName, 21, "malformed latest avg price, expecting one byte") ErrNoLatestAvgPrice = errors.Register(ModuleName, 22, "no latest average price") ->>>>>>> 37909a3 (fix: deprecated use of sdkerrors (#1788)) ) From 9cf302406300bcf5af41cf80f20fc2d22baf0e50 Mon Sep 17 00:00:00 2001 From: toteki <63419657+toteki@users.noreply.github.com> Date: Mon, 13 Feb 2023 21:36:34 -0700 Subject: [PATCH 5/5] files-- --- x/uibc/errors.go | 10 -- x/uibc/msg.go | 118 ---------------- x/uibc/quota/ibc_module.go | 103 -------------- x/uibc/quota/keeper/quota.go | 251 ----------------------------------- x/uibc/quota/keeper/relay.go | 36 ----- 5 files changed, 518 deletions(-) delete mode 100644 x/uibc/errors.go delete mode 100644 x/uibc/msg.go delete mode 100644 x/uibc/quota/ibc_module.go delete mode 100644 x/uibc/quota/keeper/quota.go delete mode 100644 x/uibc/quota/keeper/relay.go diff --git a/x/uibc/errors.go b/x/uibc/errors.go deleted file mode 100644 index 70c6804005..0000000000 --- a/x/uibc/errors.go +++ /dev/null @@ -1,10 +0,0 @@ -package uibc - -import ( - "cosmossdk.io/errors" -) - -var ( - ErrQuotaExceeded = errors.Register(ModuleName, 1, "quota transfer exceeded") - ErrNoQuotaForIBCDenom = errors.Register(ModuleName, 2, "no quota for ibc denom") -) diff --git a/x/uibc/msg.go b/x/uibc/msg.go deleted file mode 100644 index 2156ad989c..0000000000 --- a/x/uibc/msg.go +++ /dev/null @@ -1,118 +0,0 @@ -package uibc - -import ( - "encoding/json" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - - "github.com/umee-network/umee/v4/util/checkers" -) - -var ( - _ sdk.Msg = &MsgGovUpdateQuota{} - _ sdk.Msg = &MsgGovSetIBCPause{} -) - -// GetTitle returns the title of the proposal. -func (msg *MsgGovUpdateQuota) GetTitle() string { return msg.Title } - -// GetDescription implements govv1b1.Content interface. -func (msg *MsgGovUpdateQuota) GetDescription() string { return msg.Description } - -// Route implements Msg -func (msg MsgGovUpdateQuota) Route() string { return RouterKey } - -// Type implements Msg -func (msg MsgGovUpdateQuota) Type() string { return sdk.MsgTypeURL(&msg) } - -// String implements the Stringer interface. -func (msg *MsgGovUpdateQuota) String() string { - out, _ := json.Marshal(msg) - return string(out) -} - -// ValidateBasic implements Msg -func (msg *MsgGovUpdateQuota) ValidateBasic() error { - if err := checkers.ValidateAddr(msg.Authority, "authority"); err != nil { - return err - } - - if msg.Total.IsNil() || !msg.Total.IsPositive() { - return sdkerrors.ErrInvalidRequest.Wrap("total quota must be positive") - } - - if msg.PerDenom.IsNil() || !msg.PerDenom.IsPositive() { - return sdkerrors.ErrInvalidRequest.Wrap("quota per denom must be positive") - } - - if msg.Total.LT(msg.PerDenom) { - return sdkerrors.ErrInvalidRequest.Wrap("total quota must be greater than or equal to per_denom quota") - } - - return checkers.ValidateProposal(msg.Title, msg.Description, msg.Authority) -} - -// GetSignBytes implements Msg -func (msg *MsgGovUpdateQuota) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) -} - -// GetSigners implements Msg -func (msg *MsgGovUpdateQuota) GetSigners() []sdk.AccAddress { - return checkers.Signers(msg.Authority) -} - -// GetTitle implements govv1b1.Content interface. -func (msg *MsgGovSetIBCPause) GetTitle() string { return msg.Title } - -// GetDescription implements govv1b1.Content interface. -func (msg *MsgGovSetIBCPause) GetDescription() string { return msg.Description } - -// Route implements Msg -func (msg MsgGovSetIBCPause) Route() string { return RouterKey } - -// Type implements Msg -func (msg MsgGovSetIBCPause) Type() string { return sdk.MsgTypeURL(&msg) } - -// String implements the Stringer interface. -func (msg *MsgGovSetIBCPause) String() string { - out, _ := json.Marshal(msg) - return string(out) -} - -// ValidateBasic implements Msg -func (msg *MsgGovSetIBCPause) ValidateBasic() error { - if err := checkers.ValidateAddr(msg.Authority, "authority"); err != nil { - return err - } - - if err := validateIBCTransferStatus(msg.IbcPauseStatus); err != nil { - return err - } - - return checkers.ValidateProposal(msg.Title, msg.Description, msg.Authority) -} - -// GetSignBytes implements Msg -func (msg *MsgGovSetIBCPause) GetSignBytes() []byte { - bz := ModuleCdc.MustMarshalJSON(msg) - return sdk.MustSortJSON(bz) -} - -// GetSigners implements Msg -func (msg *MsgGovSetIBCPause) GetSigners() []sdk.AccAddress { - return checkers.Signers(msg.Authority) -} - -func (q *Quota) Validate() error { - if len(q.IbcDenom) == 0 { - return sdkerrors.ErrInvalidRequest.Wrap("ibc denom shouldn't be empty") - } - - if q.OutflowSum.IsNil() || q.OutflowSum.IsNegative() { - return sdkerrors.ErrInvalidRequest.Wrap("ibc denom quota expires shouldn't be empty") - } - - return nil -} diff --git a/x/uibc/quota/ibc_module.go b/x/uibc/quota/ibc_module.go deleted file mode 100644 index 6b111efaa9..0000000000 --- a/x/uibc/quota/ibc_module.go +++ /dev/null @@ -1,103 +0,0 @@ -package quota - -import ( - "encoding/json" - - "cosmossdk.io/errors" - sdkmath "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - transfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types" - porttypes "github.com/cosmos/ibc-go/v5/modules/core/05-port/types" - - "github.com/umee-network/umee/v4/util/sdkutil" - "github.com/umee-network/umee/v4/x/uibc" - "github.com/umee-network/umee/v4/x/uibc/quota/keeper" -) - -type IBCMiddleware struct { - porttypes.IBCModule - keeper keeper.Keeper - cdc codec.JSONCodec -} - -// NewIBCMiddleware creates a new IBCMiddlware given the keeper and underlying application -func NewIBCMiddleware(app porttypes.IBCModule, k keeper.Keeper, cdc codec.JSONCodec) IBCMiddleware { - return IBCMiddleware{ - IBCModule: app, - keeper: k, - cdc: cdc, - } -} - -// OnAcknowledgementPacket implements types.Middleware -func (im IBCMiddleware) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, - relayer sdk.AccAddress, -) error { - var ack channeltypes.Acknowledgement - if err := im.cdc.UnmarshalJSON(acknowledgement, &ack); err != nil { - return errors.Wrap(err, "cannot unmarshal ICS-20 transfer packet acknowledgement") - } - if _, ok := ack.Response.(*channeltypes.Acknowledgement_Error); ok { - err := im.RevertQuotaUpdate(ctx, packet.Data) - emitOnRevertQuota(&ctx, "acknowledgement", packet.Data, err) - } - - return im.IBCModule.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer) -} - -// OnTimeoutPacket implements types.Middleware -func (im IBCMiddleware) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) error { - err := im.RevertQuotaUpdate(ctx, packet.Data) - emitOnRevertQuota(&ctx, "timeout", packet.Data, err) - - return im.IBCModule.OnTimeoutPacket(ctx, packet, relayer) -} - -// RevertQuotaUpdate Notifies the contract that a sent packet wasn't properly received -func (im IBCMiddleware) RevertQuotaUpdate( - ctx sdk.Context, - packetData []byte, -) error { - var data transfertypes.FungibleTokenPacketData - if err := im.cdc.UnmarshalJSON(packetData, &data); err != nil { - return errors.Wrap(err, - "cannot unmarshal ICS-20 transfer packet data") - } - - amount, ok := sdkmath.NewIntFromString(data.Amount) - if !ok { - return sdkerrors.ErrInvalidRequest.Wrapf("invalid transfer amount %s", data.Amount) - } - - return im.keeper.UndoUpdateQuota(ctx, data.Denom, amount) -} - -func ValidateReceiverAddress(packet channeltypes.Packet) error { - var packetData transfertypes.FungibleTokenPacketData - if err := json.Unmarshal(packet.GetData(), &packetData); err != nil { - return err - } - if len(packetData.Receiver) >= 4096 { - return sdkerrors.ErrInvalidAddress.Wrapf( - "IBC Receiver address too long. Max supported length is %d", 4096, - ) - } - return nil -} - -// emitOnRevertQuota emits events related to quota update revert. -// packetData is ICS 20 packet data bytes. -func emitOnRevertQuota(ctx *sdk.Context, failureType string, packetData []byte, err error) { - if err == nil { - return - } - ctx.Logger().Error("revert quota update error", "err", err) - sdkutil.Emit(ctx, &uibc.EventBadRevert{ - Module: uibc.ModuleName, - FailureType: failureType, - Packet: string(packetData), - }) -} diff --git a/x/uibc/quota/keeper/quota.go b/x/uibc/quota/keeper/quota.go deleted file mode 100644 index 7799cb841b..0000000000 --- a/x/uibc/quota/keeper/quota.go +++ /dev/null @@ -1,251 +0,0 @@ -package keeper - -import ( - "encoding/json" - "strings" - "time" - - sdkmath "cosmossdk.io/math" - prefixsore "github.com/cosmos/cosmos-sdk/store/prefix" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - transfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types" - "github.com/cosmos/ibc-go/v5/modules/core/exported" - - ltypes "github.com/umee-network/umee/v4/x/leverage/types" - "github.com/umee-network/umee/v4/x/uibc" -) - -// GetQuotaOfIBCDenoms returns quota of all tokens. -func (k Keeper) GetQuotaOfIBCDenoms(ctx sdk.Context) ([]uibc.Quota, error) { - var quotaOfIBCDenoms []uibc.Quota - - prefix := uibc.KeyPrefixDenomQuota - store := ctx.KVStore(k.storeKey) - - iter := sdk.KVStorePrefixIterator(store, prefix) - defer iter.Close() - - for ; iter.Valid(); iter.Next() { - var quotaOfIBCDenom uibc.Quota - if err := quotaOfIBCDenom.Unmarshal(iter.Value()); err != nil { - return nil, err - } - - quotaOfIBCDenoms = append(quotaOfIBCDenoms, quotaOfIBCDenom) - } - - return quotaOfIBCDenoms, nil -} - -// GetQuotaByDenom retunes the rate limits of ibc denom. -func (k Keeper) GetQuotaByDenom(ctx sdk.Context, ibcDenom string) (*uibc.Quota, error) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(uibc.KeyTotalOutflows(ibcDenom)) - if bz == nil { - return nil, uibc.ErrNoQuotaForIBCDenom - } - - var quotaOfIBCDenom uibc.Quota - if err := k.cdc.Unmarshal(bz, "aOfIBCDenom); err != nil { - return nil, err - } - - return "aOfIBCDenom, nil -} - -// SetDenomQuotas save the updated token quota. -func (k Keeper) SetDenomQuotas(ctx sdk.Context, quotas []uibc.Quota) { - for _, quotaOfIBCDenom := range quotas { - k.SetDenomQuota(ctx, quotaOfIBCDenom) - } -} - -// SetDenomQuota save the quota of denom into store. -func (k Keeper) SetDenomQuota(ctx sdk.Context, quotaOfIBCDenom uibc.Quota) { - store := ctx.KVStore(k.storeKey) - key := uibc.KeyTotalOutflows(quotaOfIBCDenom.IbcDenom) - store.Set(key, k.cdc.MustMarshal("aOfIBCDenom)) -} - -// GetTotalOutflowSum returns the total outflow of ibc-transfer amount. -func (k Keeper) GetTotalOutflowSum(ctx sdk.Context) sdk.Dec { - store := ctx.KVStore(k.storeKey) - bz := store.Get(uibc.KeyPrefixTotalOutflows) - return sdk.MustNewDecFromStr(string(bz)) -} - -// SetTotalOutflowSum save the total outflow of ibc-transfer amount. -func (k Keeper) SetTotalOutflowSum(ctx sdk.Context, amount sdk.Dec) { - store := ctx.KVStore(k.storeKey) - store.Set(uibc.KeyPrefixTotalOutflows, []byte(amount.String())) -} - -// SetExpire save the quota expires time of ibc denom into store. -func (k Keeper) SetExpire(ctx sdk.Context, expires time.Time) error { - store := ctx.KVStore(k.storeKey) - bz, err := expires.MarshalBinary() - if err != nil { - return err - } - store.Set(uibc.KeyPrefixQuotaExpires, bz) - - return nil -} - -// GetExpire returns ibc-transfer quota expires time. -func (k Keeper) GetExpire(ctx sdk.Context) (*time.Time, error) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(uibc.KeyPrefixQuotaExpires) - if bz == nil { - return nil, nil - } - quotaExpires := ctx.BlockTime() - if err := quotaExpires.UnmarshalBinary(bz); err != nil { - return "aExpires, err - } - return "aExpires, nil -} - -// ResetQuota will reset the ibc-transfer quotas -func (k Keeper) ResetQuota(ctx sdk.Context) error { - qd := k.GetParams(ctx).QuotaDuration - zero := sdk.NewDec(0) - newExpires := ctx.BlockTime().Add(qd) - if err := k.SetExpire(ctx, newExpires); err != nil { - return err - } - k.SetTotalOutflowSum(ctx, zero) - store := ctx.KVStore(k.storeKey) - store = prefixsore.NewStore(store, uibc.KeyPrefixDenomQuota) - iter := sdk.KVStorePrefixIterator(store, nil) - defer iter.Close() - for ; iter.Valid(); iter.Next() { - ibcDenom := iter.Key() - q := uibc.Quota{IbcDenom: string(ibcDenom), OutflowSum: zero} - store.Set(ibcDenom, k.cdc.MustMarshal(&q)) - } - return nil -} - -// CheckAndUpdateQuota checks the quota of ibc-transfer of denom -func (k Keeper) CheckAndUpdateQuota(ctx sdk.Context, denom string, amount sdkmath.Int) error { - params := k.GetParams(ctx) - - quotaOfIBCDenom, err := k.GetQuotaByDenom(ctx, denom) - if err != nil { - return err - } - - if quotaOfIBCDenom == nil { - return nil - } - - exchangePrice, err := k.getExchangePrice(ctx, denom, amount) - if err != nil { - // Note: skip the ibc-transfer quota checking if `denom` is not support by leverage - // TODO: write test case for this - if ltypes.ErrNotRegisteredToken.Is(err) { - return nil - } else if err != nil { - return err - } - } - - // checking ibc-transfer token quota - quotaOfIBCDenom.OutflowSum = quotaOfIBCDenom.OutflowSum.Add(exchangePrice) - if quotaOfIBCDenom.OutflowSum.GT(params.TokenQuota) { - return uibc.ErrQuotaExceeded - } - - // checking total outflow quota - totalOutflowSum := k.GetTotalOutflowSum(ctx).Add(exchangePrice) - if totalOutflowSum.GT(params.TotalQuota) { - return uibc.ErrQuotaExceeded - } - - // update the per token outflow sum - k.SetDenomQuota(ctx, *quotaOfIBCDenom) - // updating the total outflow sum - k.SetTotalOutflowSum(ctx, totalOutflowSum) - return nil -} - -func (k Keeper) getExchangePrice(ctx sdk.Context, denom string, amount sdkmath.Int) (sdk.Dec, error) { - transferCoin := sdk.NewCoin(denom, amount) - var err error - - // convert to base asset if it is `uToken` - if ltypes.HasUTokenPrefix(denom) { - transferCoin, err = k.leverageKeeper.ExchangeUToken(ctx, transferCoin) - if err != nil { - return sdk.Dec{}, err - } - } - - // get the exchange price (eg: UMEE) in USD from oracle using base denom eg: `uumee` - return k.leverageKeeper.TokenValue(ctx, transferCoin, ltypes.PriceModeSpot) -} - -// UndoUpdateQuota undo the quota of ibc denom -func (k Keeper) UndoUpdateQuota(ctx sdk.Context, denom string, amount sdkmath.Int) error { - quotaOfIBCDenom, err := k.GetQuotaByDenom(ctx, denom) - if err != nil { - return err - } - - if quotaOfIBCDenom == nil { - return nil - } - - exchangePrice, err := k.getExchangePrice(ctx, denom, amount) - if err != nil { - // Note: skip the ibc-transfer quota checking if `denom` is not support by leverage - if ltypes.ErrNotRegisteredToken.Is(err) { - return nil - } else if err != nil { - return err - } - } - - // reset the outflow limit of token - quotaOfIBCDenom.OutflowSum = quotaOfIBCDenom.OutflowSum.Sub(exchangePrice) - k.SetDenomQuota(ctx, *quotaOfIBCDenom) - - // reset the total outflow sum - totalOutflowSum := k.GetTotalOutflowSum(ctx) - k.SetTotalOutflowSum(ctx, totalOutflowSum.Sub(exchangePrice)) - return nil -} - -// GetFundsFromPacket returns transfer amount and denom -func (k Keeper) GetFundsFromPacket(packet exported.PacketI) (sdkmath.Int, string, error) { - var packetData transfertypes.FungibleTokenPacketData - err := json.Unmarshal(packet.GetData(), &packetData) - if err != nil { - return sdkmath.Int{}, "", err - } - - amount, ok := sdkmath.NewIntFromString(packetData.Amount) - if !ok { - return sdkmath.Int{}, "", sdkerrors.ErrInvalidRequest.Wrapf("invalid transfer amount %s", packetData.Amount) - } - - return amount, k.GetLocalDenom(packetData.Denom), nil -} - -// GetLocalDenom retruns ibc denom -// Expected denoms in the following cases: -// -// send non-native: transfer/channel-0/denom -> ibc/xxx -// send native: denom -> denom -// recv (B)non-native: denom -// recv (B)native: transfer/channel-0/denom -func (k Keeper) GetLocalDenom(denom string) string { - if strings.HasPrefix(denom, "transfer/") { - denomTrace := transfertypes.ParseDenomTrace(denom) - return denomTrace.IBCDenom() - } - - return denom -} diff --git a/x/uibc/quota/keeper/relay.go b/x/uibc/quota/keeper/relay.go deleted file mode 100644 index 64e432aa6a..0000000000 --- a/x/uibc/quota/keeper/relay.go +++ /dev/null @@ -1,36 +0,0 @@ -package keeper - -import ( - "cosmossdk.io/errors" - sdk "github.com/cosmos/cosmos-sdk/types" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - ibcexported "github.com/cosmos/ibc-go/v5/modules/core/exported" -) - -// SendPacket wraps IBC ChannelKeeper's SendPacket function -func (k Keeper) SendPacket(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI) error { - funds, denom, err := k.GetFundsFromPacket(packet) - if err != nil { - return errors.Wrap(err, "bad packet in rate limit's SendPacket") - } - - if err := k.CheckAndUpdateQuota(ctx, denom, funds); err != nil { - return errors.Wrap(err, "bad packet in rate limit's SendPacket") - } - - return k.ics4Wrapper.SendPacket(ctx, chanCap, packet) -} - -// WriteAcknowledgement wraps IBC ChannelKeeper's WriteAcknowledgement function -// ICS29 WriteAcknowledgement is used for asynchronous acknowledgements -func (k Keeper) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, - acknowledgement ibcexported.Acknowledgement, -) error { - // ics4Wrapper may be core IBC or higher-level middleware - return k.ics4Wrapper.WriteAcknowledgement(ctx, chanCap, packet, acknowledgement) -} - -// GetAppVersion returns the underlying application version. -func (k Keeper) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { - return k.ics4Wrapper.GetAppVersion(ctx, portID, channelID) -}