Prepared by:
HALBORN
Last Updated 04/09/2024
Date of Engagement by: February 2nd, 2024 - March 15th, 2024
100% of all REPORTED Findings have been addressed
All findings
22
Critical
2
High
2
Medium
3
Low
8
Informational
7
The Elys Network Team
engaged Halborn to conduct a security assessment on their cosmos appchain modules, beginning on 02/02/2024 and ending on 03/15/2024. The security assessment was scoped to the sections of code that pertain to the modules of app chain. Commit hashes and further details can be found in the Scope section of this report.
Halborn was provided 12 weeks for the engagement and assigned 1 full-time security engineer to review the security of the modules in scope. The engineer is a blockchain and smart contract security expert with advanced penetration testing and smart contract hacking skills, and deep knowledge of multiple blockchain protocols.
The purpose of the assessment is to:
- Ensure that the AppChain Modules operate as intended.
- Identify potential security issues with the custom modules used in the Elys Chain.
In summary, Halborn identified some security issues that were mostly addressed by the Elys Network team
.
Halborn performed a combination of manual and automated security testing to balance efficiency, timeliness, practicality, and accuracy in regard to the scope of the custom modules. While manual testing is recommended to uncover flaws in logic, process, and implementation; automated testing techniques help enhance coverage of structures and can quickly identify items that do not follow security best practices. The following phases and associated tools were used throughout the term of the assessment:
- Research into architecture and purpose.
- Static Analysis of security for scoped repository, and imported functions. (e.g., staticcheck
, gosec
, unconvert
, codeql
, ineffassign
and semgrep
)
- Manual Assessment for discovering security vulnerabilities on the codebase.
- Ensuring the correctness of the codebase.
- Dynamic Analysis of files and modules related to the Elys Network Modules.
External libraries and financial-related attacks.
New features/implementations after/with the remediation commit IDs
Changes that occur outside of the scope of PRs.
EXPLOITABILITY METRIC () | METRIC VALUE | NUMERICAL VALUE |
---|---|---|
Attack Origin (AO) | Arbitrary (AO:A) Specific (AO:S) | 1 0.2 |
Attack Cost (AC) | Low (AC:L) Medium (AC:M) High (AC:H) | 1 0.67 0.33 |
Attack Complexity (AX) | Low (AX:L) Medium (AX:M) High (AX:H) | 1 0.67 0.33 |
IMPACT METRIC () | METRIC VALUE | NUMERICAL VALUE |
---|---|---|
Confidentiality (C) | None (I:N) Low (I:L) Medium (I:M) High (I:H) Critical (I:C) | 0 0.25 0.5 0.75 1 |
Integrity (I) | None (I:N) Low (I:L) Medium (I:M) High (I:H) Critical (I:C) | 0 0.25 0.5 0.75 1 |
Availability (A) | None (A:N) Low (A:L) Medium (A:M) High (A:H) Critical (A:C) | 0 0.25 0.5 0.75 1 |
Deposit (D) | None (D:N) Low (D:L) Medium (D:M) High (D:H) Critical (D:C) | 0 0.25 0.5 0.75 1 |
Yield (Y) | None (Y:N) Low (Y:L) Medium (Y:M) High (Y:H) Critical (Y:C) | 0 0.25 0.5 0.75 1 |
SEVERITY COEFFICIENT () | COEFFICIENT VALUE | NUMERICAL VALUE |
---|---|---|
Reversibility () | None (R:N) Partial (R:P) Full (R:F) | 1 0.5 0.25 |
Scope () | Changed (S:C) Unchanged (S:U) | 1.25 1 |
Severity | Score Value Range |
---|---|
Critical | 9 - 10 |
High | 7 - 8.9 |
Medium | 4.5 - 6.9 |
Low | 2 - 4.4 |
Informational | 0 - 1.9 |
Critical
2
High
2
Medium
3
Low
8
Informational
7
Security analysis | Risk level | Remediation Date |
---|---|---|
Lack of Access Control in RequestBandPrice Function | Critical | Solved - 03/12/2024 |
Incorrect Calculation of Minimum Collateral Due to Ignored Decimal Precision | Critical | Solved - 03/12/2024 |
Absence of Creation Fee in CreatePool Method Leading to Spamming Attacks | High | Solved - 04/05/2024 |
Inadequate Handling Of Large Webassembly (Wasm) Files On The System Leads To Dos | High | Solved - 03/12/2024 |
Absence of IBC Channel Verification in UpdateEntry Function | Medium | Solved - 03/12/2024 |
Lack of Broker Address Validation in MsgUpdateBrokerAddress's ValidateBasic Function | Medium | Solved - 03/12/2024 |
Implement TWAP for More Accurate Price Retrieval in Keeper Methods | Medium | Risk Accepted |
JoinPoolNoSwap Exhibits Discrepancy Between Expected and Actual Calculated Share Outputs | Low | Risk Accepted |
Bulk Coin Sends | Low | Risk Accepted |
Lack of spec on the modules | Low | Risk Accepted |
Missing Asset Whitelisting/Denom Check in FeedPrice Method | Low | Risk Accepted |
Insufficient Validation in MsgCreateEntry, MsgUpdateEntry, and MsgDeleteEntry | Low | Risk Accepted |
Vulnerabilities in Cosmos SDK v0.47.4 Affecting Elys Network | Low | Risk Accepted |
Utilize Block Height in Price Feeding | Low | Solved - 04/08/2024 |
Potential Denial of Service (DoS) Vulnerability in PowApprox Function | Low | Risk Accepted |
Increase Precision of Initial Pool Shares to Match Industry Standards | Informational | Solved - 04/08/2024 |
Missing Usage Description For All Transaction Commands Cli | Informational | Acknowledged |
Implement Fee Market Integrated into Consensus Layer | Informational | Acknowledged |
Lack OF IBC Rate-Limitting Implementation | Informational | Acknowledged |
Arbitrary Token Transfer Leads to Chain Halt | Informational | Acknowledged |
Keep Slippage Expiration Date as a Governance Parameter | Informational | Solved - 04/08/2024 |
Silent Error in RecordWithdrawValidatorCommission Function | Informational | Acknowledged |
// Critical
This function is intended to request price data from the Band Oracle, but it appears to lack sufficient access control measures. This oversight could potentially allow unauthorized entities to manipulate oracle requests, leading to inaccurate or compromised data being fed into the system. The function RequestBandPrice does not implement checks to ensure that the caller or the message sender has the necessary permissions to request data from the Band Oracle. In its current state, any entity can potentially trigger the oracle request, which could lead to a range of issues, including but not limited to: Data manipulation Spamming the oracle with unnecessary requests Triggering unintended oracle responses.
func (k msgServer) RequestBandPrice(goCtx context.Context, msg *types.MsgRequestBandPrice) (*types.MsgRequestBandPriceResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
sourcePort := types.PortID
channelCap, ok := k.scopedKeeper.GetCapability(ctx, host.ChannelCapabilityPath(sourcePort, msg.SourceChannel))
if !ok {
return nil, errorsmod.Wrap(channeltypes.ErrChannelCapabilityNotFound,
"module does not own channel capability")
}
encodedCalldata := obi.MustEncode(*msg.Calldata)
packetData := packet.NewOracleRequestPacketData(
msg.ClientID,
msg.OracleScriptID,
encodedCalldata,
msg.AskCount,
msg.MinCount,
msg.FeeLimit,
msg.PrepareGas,
msg.ExecuteGas,
)
_, err := k.channelKeeper.SendPacket(ctx, channelCap, sourcePort, msg.SourceChannel, clienttypes.NewHeight(0, 0), uint64(ctx.BlockTime().UnixNano()+int64(10*time.Minute)), packetData.GetBytes())
if err != nil {
return nil, err
}
return &types.MsgRequestBandPriceResponse{}, nil
}
func CmdRequestBandPrice() *cobra.Command {
cmd := &cobra.Command{
Use: "request-band-price [oracle-script-id] [requested-validator-count] [sufficient-validator-count]",
Short: "Make a new BandPrice query request via an existing BandChain oracle script",
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
// retrieve the oracle script id.
uint64OracleScriptID, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
return err
}
oracleScriptID := types.OracleScriptID(uint64OracleScriptID)
// retrieve the requested validator count.
askCount, err := strconv.ParseUint(args[1], 10, 64)
if err != nil {
return err
}
// retrieve the sufficient(minimum) validator count.
minCount, err := strconv.ParseUint(args[2], 10, 64)
if err != nil {
return err
}
channel, err := cmd.Flags().GetString(flagChannel)
if err != nil {
return err
}
// retrieve the list of symbols for the requested oracle script.
symbols, err := cmd.Flags().GetStringSlice(flagSymbols)
if err != nil {
return err
}
// retrieve the multiplier for the symbols' price.
multiplier, err := cmd.Flags().GetUint64(flagMultiplier)
if err != nil {
return err
}
calldata := &types.BandPriceCallData{
Symbols: symbols,
Multiplier: multiplier,
}
// retrieve the amount of coins allowed to be paid for oracle request fee from the pool account.
coinStr, err := cmd.Flags().GetString(flagFeeLimit)
if err != nil {
return err
}
feeLimit, err := sdk.ParseCoinsNormalized(coinStr)
if err != nil {
return err
}
// retrieve the amount of gas allowed for the prepare step of the oracle script.
prepareGas, err := cmd.Flags().GetUint64(flagPrepareGas)
if err != nil {
return err
}
// retrieve the amount of gas allowed for the execute step of the oracle script.
executeGas, err := cmd.Flags().GetUint64(flagExecuteGas)
if err != nil {
return err
}
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
msg := types.NewMsgRequestBandPrice(
clientCtx.GetFromAddress().String(),
oracleScriptID,
channel,
calldata,
askCount,
minCount,
feeLimit,
prepareGas,
executeGas,
)
if err := msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
cmd.Flags().String(flagChannel, "", "The channel id")
cmd.MarkFlagRequired(flagChannel)
cmd.Flags().StringSlice(flagSymbols, nil, "Symbols used in calling the oracle script")
cmd.Flags().Uint64(flagMultiplier, 1000000, "Multiplier used in calling the oracle script")
cmd.Flags().String(flagFeeLimit, "", "the maximum tokens that will be paid to all data source providers")
cmd.Flags().Uint64(flagPrepareGas, 200000, "Prepare gas used in fee counting for prepare request")
cmd.Flags().Uint64(flagExecuteGas, 200000, "Execute gas used in fee counting for execute request")
flags.AddTxFlagsToCmd(cmd)
return cmd
}
Introduce checks at the beginning of the RequestBandPrice function to ensure that only authorized entities can make requests to the Band Oracle.
SOLVED: The Elys Network team solved this issue by deleting the implementation.
// Critical
The function CalcMinCollateral in the keeper package is designed to calculate the minimum collateral required to open a position based on the provided leverage. However, the current implementation does not correctly account for the decimal precision of the collateral amount. The calculation returns the result without considering the collateral_decimals, leading to potential inaccuracies in the minimum collateral required, especially in systems where collateral assets have significant decimal precision.
// CalcMinCollateral calculates the minimum collateral required to open a position
func (k Keeper) CalcMinCollateral(ctx sdk.Context, leverage sdk.Dec) (math.Int, error) {
// leverage must be greater than 1
if leverage.LTE(sdk.NewDec(1)) {
return sdk.ZeroInt(), errorsmod.Wrapf(types.ErrInvalidLeverage, "leverage must be greater than 1")
}
// get min borrow rate
borrowInterestRateMin := k.GetBorrowInterestRateMin(ctx)
// min_collateral = ( 1 / (( leverage - 1 ) * borrow_interest_rate_min )) / 10 ^ collateral_decimals
minCollateral := sdk.NewDec(1).Quo(
leverage.Sub(sdk.NewDec(1)).Mul(borrowInterestRateMin),
)
return minCollateral.TruncateInt(), nil
}
Users may be required to provide more or less collateral than accurately needed due to decimal precision not being considered. This can lead to inefficiencies, where users either over-collateralize (locking up more funds than necessary) or under-collateralize (posing a risk to the system's financial stability). Modify the CalcMinCollateral function to account for collateral_decimals. This involves adjusting the final collateral amount by the decimal precision of the collateral asset, ensuring the calculation reflects the actual minimum required collateral in terms of the asset's smallest unit.
SOLVED: The Elys Network team solved this issue by adjusting decimals.
// High
Upon review of the CreatePool method within the Keeper module, a notable gap has been identified: the method does not implement a creation fee for new pools. This absence can potentially lead to spamming attacks, as malicious actors may exploit it to create numerous pools with minimal cost, cluttering the system and possibly degrading its performance. The lack of a creation fee for pools could lead to an influx of low-quality or spam pools being created on the platform.
func (k Keeper) CreatePool(ctx sdk.Context, msg *types.MsgCreatePool) (uint64, error) {
sender := msg.GetSigners()[0]
entry, found := k.assetProfileKeeper.GetEntry(ctx, ptypes.BaseCurrency)
if !found {
return 0, errorsmod.Wrapf(assetprofiletypes.ErrAssetProfileNotFound, "asset %s not found", ptypes.BaseCurrency)
}
baseCurrency := entry.Denom
// If the fee denom is empty, set it to the base currency
if msg.PoolParams.FeeDenom == "" {
msg.PoolParams.FeeDenom = baseCurrency
}
// Get the next pool ID and increment the pool ID counter
// Create the pool with the given pool ID
poolId := k.GetNextPoolId(ctx)
pool, err := types.NewBalancerPool(poolId, *msg.PoolParams, msg.PoolAssets, ctx.BlockTime())
if err != nil {
return 0, err
}
if err := pool.Validate(poolId); err != nil {
return 0, err
}
address, err := sdk.AccAddressFromBech32(pool.GetAddress())
if err != nil {
return 0, fmt.Errorf("invalid pool address %s", pool.GetAddress())
}
// create and save the pool's module account to the account keeper
if err := utils.CreateModuleAccount(ctx, k.accountKeeper, address); err != nil {
return 0, fmt.Errorf("creating pool module account for id %d: %w", poolId, err)
}
// Run the initialization logic.
if err := k.InitializePool(ctx, &pool, sender); err != nil {
return 0, err
}
// Send initial liquidity to the pool's address.
initialPoolLiquidity := msg.InitialLiquidity()
err = k.bankKeeper.SendCoins(ctx, sender, address, initialPoolLiquidity)
if err != nil {
return 0, err
}
// Increase liquidty amount
for _, asset := range msg.PoolAssets {
k.RecordTotalLiquidityIncrease(ctx, sdk.Coins{asset.Token})
}
// emitCreatePoolEvents(ctx, poolId, msg)
return pool.GetPoolId(), nil
}
func (suite *KeeperTestSuite) TestMsgServerCreatePool() {
for _, tc := range []struct {
desc string
senderInitBalance sdk.Coins
poolParams types.PoolParams
poolAssets []types.PoolAsset
expSenderBalance sdk.Coins
expTotalLiquidity sdk.Coins
expLpCommitment sdk.Coin
expPass bool
}{
{
desc: "zero tvl pool creation",
senderInitBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Eden, 1000000), sdk.NewInt64Coin(ptypes.Elys, 1000000)},
poolParams: types.PoolParams{
SwapFee: sdk.ZeroDec(),
ExitFee: sdk.ZeroDec(),
UseOracle: false,
WeightBreakingFeeMultiplier: sdk.ZeroDec(),
WeightBreakingFeeExponent: sdk.NewDecWithPrec(25, 1), // 2.5
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
FeeDenom: ptypes.BaseCurrency,
},
poolAssets: []types.PoolAsset{
{
Token: sdk.NewInt64Coin(ptypes.Eden, 1000000),
Weight: sdk.OneInt(),
},
{
Token: sdk.NewInt64Coin(ptypes.Elys, 1000000),
Weight: sdk.OneInt(),
},
},
expSenderBalance: sdk.Coins{},
expLpCommitment: sdk.NewCoin("amm/pool/1", sdk.NewInt(100).Mul(types.OneShare)),
expPass: true,
},
{
desc: "positive tvl pool creation",
senderInitBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Eden, 1000000), sdk.NewInt64Coin(ptypes.BaseCurrency, 1000000)},
poolParams: types.PoolParams{
SwapFee: sdk.ZeroDec(),
ExitFee: sdk.ZeroDec(),
UseOracle: false,
WeightBreakingFeeMultiplier: sdk.ZeroDec(),
WeightBreakingFeeExponent: sdk.NewDecWithPrec(25, 1), // 2.5
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
FeeDenom: ptypes.BaseCurrency,
},
poolAssets: []types.PoolAsset{
{
Token: sdk.NewInt64Coin(ptypes.Eden, 1000000),
Weight: sdk.OneInt(),
},
{
Token: sdk.NewInt64Coin(ptypes.BaseCurrency, 1000000),
Weight: sdk.OneInt(),
},
},
expSenderBalance: sdk.Coins{},
expLpCommitment: sdk.NewCoin("amm/pool/1", sdk.NewInt(2).Mul(types.OneShare)),
expPass: true,
},
{
desc: "not enough balance to create pool",
senderInitBalance: sdk.Coins{sdk.NewInt64Coin(ptypes.Eden, 1000000)},
poolParams: types.PoolParams{
SwapFee: sdk.ZeroDec(),
ExitFee: sdk.ZeroDec(),
UseOracle: false,
WeightBreakingFeeMultiplier: sdk.ZeroDec(),
WeightBreakingFeeExponent: sdk.NewDecWithPrec(25, 1), // 2.5
ExternalLiquidityRatio: sdk.NewDec(1),
WeightRecoveryFeePortion: sdk.NewDecWithPrec(10, 2), // 10%
ThresholdWeightDifference: sdk.ZeroDec(),
FeeDenom: ptypes.BaseCurrency,
},
poolAssets: []types.PoolAsset{
{
Token: sdk.NewInt64Coin(ptypes.Eden, 1000000),
Weight: sdk.OneInt(),
},
{
Token: sdk.NewInt64Coin(ptypes.BaseCurrency, 1000000),
Weight: sdk.OneInt(),
},
},
expSenderBalance: sdk.Coins{},
expLpCommitment: sdk.Coin{},
expPass: false,
},
} {
suite.Run(tc.desc, func() {
suite.SetupTest()
suite.SetupStableCoinPrices()
// bootstrap accounts
sender := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address())
// bootstrap balances
err := suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, tc.senderInitBalance)
suite.Require().NoError(err)
err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, sender, tc.senderInitBalance)
suite.Require().NoError(err)
// execute function
msgServer := keeper.NewMsgServerImpl(suite.app.AmmKeeper)
resp, err := msgServer.CreatePool(
sdk.WrapSDKContext(suite.ctx),
&types.MsgCreatePool{
Sender: sender.String(),
PoolParams: &tc.poolParams,
PoolAssets: tc.poolAssets,
})
if !tc.expPass {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
suite.Require().Equal(resp.PoolID, uint64(1))
pools := suite.app.AmmKeeper.GetAllPool(suite.ctx)
suite.Require().Len(pools, 1)
suite.Require().Equal(pools[0].PoolId, uint64(1))
suite.Require().Equal(pools[0].PoolParams, tc.poolParams)
suite.Require().Equal(pools[0].TotalShares.Amount.String(), tc.expLpCommitment.Amount.String())
totalWeight := sdk.ZeroInt()
for _, poolAsset := range tc.poolAssets {
totalWeight = totalWeight.Add(poolAsset.Weight)
}
suite.Require().Equal(pools[0].TotalWeight.String(), totalWeight.MulRaw(types.GuaranteedWeightPrecision).String())
// check balance change on sender
balances := suite.app.BankKeeper.GetAllBalances(suite.ctx, sender)
suite.Require().Equal(balances.String(), tc.expSenderBalance.String())
// check lp token commitment
commitments := suite.app.CommitmentKeeper.GetCommitments(suite.ctx, sender.String())
suite.Require().Len(commitments.CommittedTokens, 1)
suite.Require().Equal(commitments.CommittedTokens[0].Denom, tc.expLpCommitment.Denom)
suite.Require().Equal(commitments.CommittedTokens[0].Amount.String(), tc.expLpCommitment.Amount.String())
}
})
}
}
Introduce a fee for creating new pools. This fee should be set at a level that discourages spamming while remaining reasonable for legitimate users.
SOLVED: The Elys Network team solved this issue by adding a pool creation fee.
// High
Inadequate handling of large WebAssembly (WASM) files on the chain can lead to performance issues, slow startup times, and potentially cause system failure. It can cause to DOS.
echo "Running store code"
RES=$(client tx wasm store artifacts/larger_wasm_file.wasm --from alice -y --output json -b block $TXFLAG)
CODE_ID=$(echo $RES | jq -r '.logs[0].events[-1].attributes[0].value')
echo "Got CODE_ID = $CODE_ID"
echo "Deploying contract"
# swallow output
OUT=$(client tx wasm instantiate $CODE_ID "$INIT" --from alice --label "my first contract" --gas-prices 10$FEE_DENOM --gas auto --gas-adjustment 1.3 -b block -y --no-admin $NODE --chain-id $CHAIN_ID)
ADDR=$(client query wasm list-contract-by-code $CODE_ID --output json $NODE | jq -r '.contracts[0]')
echo "Could not deploy larger wasm file"
To prevent issues related to inadequate handling of large WASM files, increase or override the default max file size limit to allow the system to handle larger WASM files. (https://github.com/osmosis-labs/osmosis/blob/574233334f7b69fe1a58d2f79ef189dd68d32eee/app/app.go#L183)
SOLVED: The Elys Network team solved the issue.
// Medium
In the provided UpdateEntry function, part of a system managing entries in IBC. The function updates an entry with various fields, including IbcChannelId and IbcCounterpartyChannelId. However, it lacks verification for the correctness and validity of these Inter-Blockchain Communication (IBC) channel identifiers.
func (k msgServer) UpdateEntry(goCtx context.Context, msg *types.MsgUpdateEntry) (*types.MsgUpdateEntryResponse, error) {
if k.authority != msg.Authority {
return nil, errors.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, msg.Authority)
}
ctx := sdk.UnwrapSDKContext(goCtx)
// Check if the value exists
entry, isFound := k.GetEntry(ctx, msg.BaseDenom)
if !isFound {
return nil, errorsmod.Wrap(sdkerrors.ErrKeyNotFound, "entry not set")
}
// Checks if the the msg authority is the same as the current owner
if msg.Authority != entry.Authority {
return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner")
}
entry = types.Entry{
Authority: msg.Authority,
BaseDenom: msg.BaseDenom,
Decimals: msg.Decimals,
Denom: msg.Denom,
Path: msg.Path,
IbcChannelId: msg.IbcChannelId,
IbcCounterpartyChannelId: msg.IbcCounterpartyChannelId,
DisplayName: msg.DisplayName,
DisplaySymbol: msg.DisplaySymbol,
Network: msg.Network,
Address: msg.Address,
ExternalSymbol: msg.ExternalSymbol,
TransferLimit: msg.TransferLimit,
Permissions: msg.Permissions,
UnitDenom: msg.UnitDenom,
IbcCounterpartyDenom: msg.IbcCounterpartyDenom,
IbcCounterpartyChainId: msg.IbcCounterpartyChainId,
CommitEnabled: msg.CommitEnabled,
WithdrawEnabled: msg.WithdrawEnabled,
}
k.SetEntry(ctx, entry)
return &types.MsgUpdateEntryResponse{}, nil
}
Consider validating IBC channel.
SOLVED: The Elys Network team solved the issue.
// Medium
The MsgUpdateBrokerAddress function in the given code is designed to update the broker address in app chain. This function creates an instance of MsgUpdateBrokerAddress with a specified creator and broker address. However, a crucial issue is identified in the associated ValidateBasic method: it does not validate the BrokerAddress. Currently, the ValidateBasic method only validates the Creator field, overlooking the validation of BrokerAddress. For instance, some swap operations can fail.
Enhance the ValidateBasic function to include validation for the BrokerAddress. This validation should ensure that the BrokerAddress is correctly formatted and adheres to the expected address standards.
SOLVED: The Elys Network team solved the issue.
// Medium
The current implementation of Elys Network Keeper methods (GetLatestPriceFromAssetAndSource and GetLatestPriceFromAnySource) retrieves the latest price of an asset, either from a specific source or any source. While this provides the most recent price data, it may not accurately reflect the market price due to short-term price fluctuations or potential manipulation. To enhance the reliability of the pricing mechanism, we propose the implementation of Time-Weighted Average Price (TWAP).
func (k msgServer) FeedPrice(goCtx context.Context, msg *types.MsgFeedPrice) (*types.MsgFeedPriceResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
feeder, found := k.Keeper.GetPriceFeeder(ctx, msg.Provider)
if !found {
return nil, types.ErrNotAPriceFeeder
}
if !feeder.IsActive {
return nil, types.ErrPriceFeederNotActive
}
price := types.Price{
Provider: msg.Provider,
Asset: msg.Asset,
Price: msg.Price,
Source: msg.Source,
Timestamp: uint64(ctx.BlockTime().Unix()),
}
k.SetPrice(ctx, price)
return &types.MsgFeedPriceResponse{}, nil
}
Modify the existing GetPrice function to calculate the TWAP. This might involve fetching multiple price points within a defined time window and computing their average.
RISK ACCEPTED: The Elys Network team accepted the risk of the issue.
// Low
In the current implementation of JoinPoolNoSwap, the implementation does not consider with diff in the calculations of the expected shares out and calculated shares out. The diff in calculations is at most 1 denom-coin - rounding error. There will be dust.
func (k Keeper) JoinPoolNoSwap(
ctx sdk.Context,
sender sdk.AccAddress,
poolId uint64,
shareOutAmount sdk.Int,
tokenInMaxs sdk.Coins,
) (tokenIn sdk.Coins, sharesOut sdk.Int, err error) {
// defer to catch panics, in case something internal overflows.
defer func() {
if r := recover(); r != nil {
tokenIn = sdk.Coins{}
sharesOut = sdk.Int{}
err = fmt.Errorf("function JoinPoolNoSwap failed due to internal reason: %v", r)
}
}()
// all pools handled within this method are pointer references, `JoinPool` directly updates the pools
pool, poolExists := k.GetPool(ctx, poolId)
if !poolExists {
return nil, sdk.ZeroInt(), types.ErrInvalidPoolId
}
if !pool.PoolParams.UseOracle {
tokensIn := tokenInMaxs
if len(tokensIn) != 1 {
// we do an abstract calculation on the lp liquidity coins needed to have
// the designated amount of given shares of the pool without performing swap
neededLpLiquidity, err := pool.GetMaximalNoSwapLPAmount(shareOutAmount)
if err != nil {
return nil, sdk.ZeroInt(), err
}
// check that needed lp liquidity does not exceed the given `tokenInMaxs` parameter. Return error if so.
// if tokenInMaxs == 0, don't do this check.
if tokenInMaxs.Len() != 0 {
if !(neededLpLiquidity.DenomsSubsetOf(tokenInMaxs)) {
return nil, sdk.ZeroInt(), errorsmod.Wrapf(types.ErrLimitMaxAmount, "TokenInMaxs does not include all the tokens that are part of the target pool,"+
" upperbound: %v, needed %v", tokenInMaxs, neededLpLiquidity)
} else if !(tokenInMaxs.DenomsSubsetOf(neededLpLiquidity)) {
return nil, sdk.ZeroInt(), errorsmod.Wrapf(types.ErrDenomNotFoundInPool, "TokenInMaxs includes tokens that are not part of the target pool,"+
" input tokens: %v, pool tokens %v", tokenInMaxs, neededLpLiquidity)
}
if !(tokenInMaxs.IsAllGTE(neededLpLiquidity)) {
return nil, sdk.ZeroInt(), errorsmod.Wrapf(types.ErrLimitMaxAmount, "TokenInMaxs is less than the needed LP liquidity to this JoinPoolNoSwap,"+
" upperbound: %v, needed %v", tokenInMaxs, neededLpLiquidity)
}
}
tokensIn = neededLpLiquidity
}
sharesOut, err = pool.JoinPool(ctx, k.oracleKeeper, k.accountedPoolKeeper, tokensIn)
if err != nil {
return nil, sdk.ZeroInt(), err
}
// sanity check, don't return error as not worth halting the LP. We know its not too much.
if sharesOut.LT(shareOutAmount) {
ctx.Logger().Error(fmt.Sprintf("Expected to JoinPoolNoSwap >= %s shares, actually did %s shares",
shareOutAmount, sharesOut))
}
err = k.applyJoinPoolStateChange(ctx, pool, sender, sharesOut, tokensIn)
// Increase liquidty amount
k.RecordTotalLiquidityIncrease(ctx, tokensIn)
return tokensIn, sharesOut, err
}
// on oracle pool, full tokenInMaxs are used regardless shareOutAmount
sharesOut, err = pool.JoinPool(ctx, k.oracleKeeper, k.accountedPoolKeeper, tokenInMaxs)
if err != nil {
return nil, sdk.ZeroInt(), err
}
// sanity check, don't return error as not worth halting the LP. We know its not too much.
if sharesOut.LT(shareOutAmount) {
ctx.Logger().Error(fmt.Sprintf("Expected to JoinPoolNoSwap >= %s shares, actually did %s shares",
shareOutAmount, sharesOut))
}
err = k.applyJoinPoolStateChange(ctx, pool, sender, sharesOut, tokenInMaxs)
// Increase liquidty amount
k.RecordTotalLiquidityIncrease(ctx, tokenInMaxs)
return tokenInMaxs, sharesOut, err
}
Consider adding a difference check with the bounds.
RISK ACCEPTED: The Elys Network team accepted the risk of the issue.
// Low
For blockchains that support custom token transfer logic, such as blacklists for specific tokens like USDC, it is crucial to ensure that all token transfers in the Begin/EndBlock stages properly handle and catch potential panics. While this is generally a straightforward task, it is commonly overlooked in one specific context: bulk coin sends.
The Cosmos SDK allows for multiple coins to be transferred in a single function call through its SendCoins function. This function acts as a black box, which means it does not provide the ability to validate each individual token transfer. As a result, developers often overlook the necessity to handle panics within this function.
If a single panic is triggered during a call to SendCoins in the Begin/EndBlock stages, it can lead to a complete halt of the blockchain. This highlights the importance of properly handling panics in bulk coin send operations, as failing to do so can have severe consequences on the chain's availability and functionality.
Therefore, when implementing custom token transfer logic or working with bulk coin sends, it is essential to thoroughly review the code and ensure that all potential panic scenarios are properly caught and handled. This proactive approach can help prevent unexpected chain halts and maintain the stability and reliability of the blockchain.
Example Code Location : https://github.com/elys-network/elys/blob/6a6ec2162613ba8bf7d683162698516e7c6eb7ba/x/perpetual/keeper/handle_funding_fee_distribution.go#L80-L81
While one can catch the panic on the entire SendCoins call, this would mean that an attacker can DoS all transfers in the batch. Thus, the solution for these situations is to transfer coins one by one with SendCoin and verify each transfer so that problematic ones can be skipped.
RISK ACCEPTED: The Elys Network team accepted the risk of the issue.
// Low
The spec file intends to outline the common structure for specifications within this directory. The assetprofile
- parameter
- commitment
- stablestake
- oracle
- accountedpool
- amm
modules are missing spec. This documentation is segmented into developer-focused messages and end-user-facing messages. These messages may be shown to the end user (the human) at the time that they will interact with the module.
It is recommended that modules are fully annotated using spec for all available functionalities.
RISK ACCEPTED: The Elys Network team accepted the risk of the issue.
// Low
The current implementation of the FeedPrice method in the msgServer struct lacks an essential security feature: asset whitelisting for the price feeder. This function is designed to update the price of an asset provided by a price feeder, but it does not verify whether the asset being updated is recognized or authorized by the system.
func (k msgServer) FeedPrice(goCtx context.Context, msg *types.MsgFeedPrice) (*types.MsgFeedPriceResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
feeder, found := k.Keeper.GetPriceFeeder(ctx, msg.Provider)
if !found {
return nil, types.ErrNotAPriceFeeder
}
if !feeder.IsActive {
return nil, types.ErrPriceFeederNotActive
}
price := types.Price{
Provider: msg.Provider,
Asset: msg.Asset,
Price: msg.Price,
Source: msg.Source,
Timestamp: uint64(ctx.BlockTime().Unix()),
}
k.SetPrice(ctx, price)
return &types.MsgFeedPriceResponse{}, nil
}
Introduce a mechanism to maintain a whitelist of approved assets. The FeedPrice method should include a check to ensure that the asset provided in msg.Asset is part of this whitelist.
RISK ACCEPTED: The Elys Network team accepted the risk of the issue.
// Low
The functions NewMsgCreateEntry, NewMsgUpdateEntry, and NewMsgDeleteEntry are part of a system that manages entries. However, an issue arises in their ValidateBasic methods: there is a lack of comprehensive validation for all the fields in these messages. Currently, the validation only checks the Authority field's format, neglecting other crucial fields like BaseDenom, Denom, Path, IbcChannelId, and others. This insufficient validation can lead to potential operational failures or vulnerabilities, as malformed or invalid data might be processed by the system.
func NewMsgUpdateEntry(
authority string,
baseDenom string,
decimals uint64,
denom string,
path string,
ibcChannelId string,
ibcCounterpartyChannelId string,
displayName string,
displaySymbol string,
network string,
address string,
externalSymbol string,
transferLimit string,
permissions []string,
unitDenom string,
ibcCounterpartyDenom string,
ibcCounterpartyChainId string,
) *MsgUpdateEntry {
return &MsgUpdateEntry{
Authority: authority,
BaseDenom: baseDenom,
Decimals: decimals,
Denom: denom,
Path: path,
IbcChannelId: ibcChannelId,
IbcCounterpartyChannelId: ibcCounterpartyChannelId,
DisplayName: displayName,
DisplaySymbol: displaySymbol,
Network: network,
Address: address,
ExternalSymbol: externalSymbol,
TransferLimit: transferLimit,
Permissions: permissions,
UnitDenom: unitDenom,
IbcCounterpartyDenom: ibcCounterpartyDenom,
IbcCounterpartyChainId: ibcCounterpartyChainId,
}
}
Extend the ValidateBasic method in each message type to include validation checks for all relevant fields. These checks should ensure that the fields are correctly formatted and meet the expected standards.
RISK ACCEPTED: The Elys Network team accepted the risk of the issue.
// Low
Elys Network, which utilizes the Cosmos SDK version 0.47.4, is exposed to multiple vulnerabilities identified within the specified version of the SDK. The issues encompass a range of security flaws that could potentially impact the stability, security, and integrity of the Elys Network. The vulnerabilities are documented in the following GitHub advisories:
GHSA-4j93-fm92-rp4m: Describes a critical flaw that could allow for unintended behavior or access.
GHSA-2557-x9mg-76w8: Details vulnerabilities that may lead to denial of service (DoS) attacks or affect the network's operational integrity.
GHSA-95rx-m9m5-m94v: Outlines issues that could potentially be exploited to compromise the confidentiality, integrity, or availability of the network.
GHSA-86h5-xcpx-cfqc: Highlights flaws that might allow malicious actors to impact the network adversely.
Promptly upgrade to the latest version of the Cosmos SDK that addresses these vulnerabilities. Ensure thorough testing of the upgraded version in a test environment before deploying it to the mainnet to confirm compatibility and stability.
RISK ACCEPTED: The Elys Network team accepted the risk of the issue.
// Low
In the current implementation of the FeedPrice
function, the timestamp for the price feed is derived from the block time by converting it to Unix time. However, relying solely on the block time may not be sufficient in certain scenarios, as it can potentially lead to issues such as:
Time Manipulation Attacks: If an attacker can manipulate the block time, they may be able to feed incorrect prices by adjusting the timestamp.
Timestamp Collisions: If multiple price feeds are submitted within the same Unix timestamp, there could be potential collisions or overwriting of prices, leading to data loss or inconsistencies.
Lack of Determinism: Using only the block time introduces a non-deterministic element, as the block time can vary slightly between nodes due to network latency or other factors.
To address these potential issues and improve the security and reliability of the price feeding mechanism, it is recommended to utilize both the block time and the block height in the price feed message.
func (k msgServer) FeedPrice(goCtx context.Context, msg *types.MsgFeedPrice) (*types.MsgFeedPriceResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
feeder, found := k.Keeper.GetPriceFeeder(ctx, msg.Provider)
if !found {
return nil, types.ErrNotAPriceFeeder
}
if !feeder.IsActive {
return nil, types.ErrPriceFeederNotActive
}
price := types.Price{
Provider: msg.Provider,
Asset: msg.Asset,
Price: msg.Price,
Source: msg.Source,
Timestamp: uint64(ctx.BlockTime().Unix()),
}
k.SetPrice(ctx, price)
return &types.MsgFeedPriceResponse{}, nil
}
Modify the MsgFeedPrice
message to include the block height in addition to the timestamp.
SOLVED: The Elys Network team solved the issue by implementing the suggested recommendation.
// Low
The Elys project uses a function called PowApprox
to calculate approximate values for the exponentiation operation (a^b
). This function is implemented using a Taylor series approximation, and it uses a while loop to iterate until the terms being added are sufficiently small. However, the implementation does not have a bound on the maximum number of iterations, which can potentially lead to a Denial of Service (DoS) vulnerability.
The issue arises when specific values of a
and b
are chosen, such as a = 1.999999999999999
and b = 0.1
. In these cases, the PowApprox
function can take an excessive number of iterations (over two million iterations on an M1 processor) to converge, resulting in a prolonged computation time of over 800 milliseconds.
This long runtime is not accounted for in the gas costs of transactions that use the PowApprox
function. As a result, an attacker can craft a transaction that calls PowApprox
with carefully chosen values, causing the Elys nodes to spend an inordinate amount of time computing this function without having to pay a proportional gas cost.
// Contract: 0 < base <= 2
// 0 <= exp < 1.
func PowApprox(base sdk.Dec, exp sdk.Dec, precision sdk.Dec) sdk.Dec {
if !base.IsPositive() {
panic(fmt.Errorf("base must be greater than 0"))
}
if exp.IsZero() {
return sdk.OneDec()
}
// Common case optimization
// Optimize for it being equal to one-half
if exp.Equal(one_half) {
output, err := base.ApproxSqrt()
if err != nil {
panic(err)
}
return output
}
// TODO: Make an approx-equal function, and then check if exp * 3 = 1, and do a check accordingly
// We compute this via taking the maclaurin series of (1 + x)^a
// where x = base - 1.
// The maclaurin series of (1 + x)^a = sum_{k=0}^{infty} binom(a, k) x^k
// Binom(a, k) takes the natural continuation on the first parameter, namely that
// Binom(a, k) = N/D, where D = k!, and N = a(a-1)(a-2)...(a-k+1)
// Next we show that the absolute value of each term is less than the last term.
// Note that the change in term n's value vs term n + 1 is a multiplicative factor of
// v_n = x(a - n) / (n+1)
// So if |v_n| < 1, we know that each term has a lesser impact on the result than the last.
// For our bounds on |x| < 1, |a| < 1,
// it suffices to see for what n is |v_n| < 1,
// in the worst parameterization of x = 1, a = -1.
// v_n = |(-1 + epsilon - n) / (n+1)|
// So |v_n| is always less than 1, as n ranges over the integers.
//
// Note that term_n of the expansion is 1 * prod_{i=0}^{n-1} v_i
// The error if we stop the expansion at term_n is:
// error_n = sum_{k=n+1}^{infty} term_k
// At this point we further restrict a >= 0, so 0 <= a < 1.
// Now we take the _INCORRECT_ assumption that if term_n < p, then
// error_n < p.
// This assumption is obviously wrong.
// However our usages of this function don't use the full domain.
// With a > 0, |x| << 1, and p sufficiently low, perhaps this actually is true.
// TODO: Check with our parameterization
// TODO: If theres a bug, balancer is also wrong here :thonk:
base = base.Clone()
x, xneg := AbsDifferenceWithSign(base, one)
term := sdk.OneDec()
sum := sdk.OneDec()
negative := false
a := exp.Clone()
bigK := sdk.NewDec(0)
// TODO: Document this computation via taylor expansion
for i := int64(1); term.GTE(precision); i++ {
// At each iteration, we need two values, i and i-1.
// To avoid expensive big.Int allocation, we reuse bigK variable.
// On this line, bigK == i-1.
c, cneg := AbsDifferenceWithSign(a, bigK)
// On this line, bigK == i.
bigK.Set(sdk.NewDec(i)) // TODO: O(n) bigint allocation happens
term.MulMut(c).MulMut(x).QuoMut(bigK)
// a is mutated on absDifferenceWithSign, reset
a.Set(exp)
if term.IsZero() {
break
}
if xneg {
negative = !negative
}
if cneg {
negative = !negative
}
if negative {
sum.SubMut(term)
} else {
sum.AddMut(term)
}
}
return sum
}
// calculate a^b
// assumption: a is between 0 and 2, b is between 0 and 1
fn PowApprox(a,b) {
total <- 1
i <- 0
term <- 1
const precision = 0.00000001
// (the real implementation took precision as a function parameter rather than a constant)
while abs(term) >= precision {
i <- i + 1
term <- term * ((b-(i-1)) / i) * (a-1)
total <- total + term
}
return total
}
Implement a maximum iteration limit or a timeout mechanism in the PowApprox
function to prevent excessive computation times.
RISK ACCEPTED: The Elys Network team accepted the risk of the issue.
// Informational
We've identified a potential issue with the precision of the initial shares allocated to the first liquidity provider (LP) of a pool. Currently, the protocol initializes a pool with 10^18 shares. However, this might not offer enough precision, especially in scenarios where the initial liquidity provider is a significant entity (like the project team) and contributes a substantial amount of liquidity. For context, Balancer, a well-known protocol in the DeFi space, initializes its pools with a higher precision, specifically 100 * 10^18 shares (reference: Balancer's BConst.sol). This higher level of precision allows for more granular control and accuracy in the distribution of pool shares, which is particularly important in the DeFi ecosystem where large and fractional values are common.
Increase the precision of initial pool shares from 10^18 to 100 * 10^18.
SOLVED: The Elys Network team solved the issue by adjusting the share amount.
// Informational
All the transaction and query commands for all the modules are missing a long message to provide description about their usage, which will be helpful for users and external developers.
It is recommended to specify a long message for all transaction commands. Each command should provide a description of how to use the command correctly.
ACKNOWLEDGED: The Elys Network team acknowledged the issue.
// Informational
During periods of high network activity, maintaining liveness and usability becomes challenging without a robust fee market mechanism in place. While there are various approaches, the Ethereum Improvement Proposal (EIP-1559) has proven to be an effective default solution. However, implementing it directly in the mempool, as some blockchains have done, is suboptimal compared to integrating the fee market directly into the consensus layer.
The superior long-term solution is to leverage the ABCI 2.0
protocol and integrate the fee market into the consensus layer. This approach offers several advantages, including improved reliability, scalability, and adaptability to changing network conditions. By leveraging ABCI 2.0
, blockchains can seamlessly adopt the fee market mechanism without the need for extensive modifications or hard forks.
Conduct thorough testing and simulations to ensure the fee market mechanism operates as intended under various network conditions, including periods of high usage and congestion.
ACKNOWLEDGED: The Elys Network team acknowledged the issue.
// Informational
Rate limits are safety controls that disable certain functionality of a system when a pre-defined threshold is surpassed. In this context, we categorize rate limit mechanisms that don’t require external trigger invocation, as the tripping conditions are defined in the protocol. As such, rate limit thresholds tend to be simpler and numeric. (Osmosis Implementation : https://commonwealth.im/osmosis/discussion/8543-set-ibc-rate-limits)
Implement rate-limiting on the IBC like an Osmosis.
ACKNOWLEDGED: The Elys Network team acknowledged the issue.
// Informational
In blockchains that allow for arbitrary token transfer hooks and execute them during the Begin/EndBlock stages, a potential vulnerability exists where an attacker can create a token that triggers an infinitely looping CosmWasm contract. When this malicious token is transferred during the next block's BeginBlock, it can cause the entire chain to halt due to the unintended infinite loop.
This issue highlights the importance of properly handling and limiting the execution of arbitrary code during critical phases of the blockchain's operation, such as the BeginBlocker and EndBlocker operations. Failing to impose appropriate constraints can lead to Denial of Service (DoS) attacks and severe disruptions to the chain's availability and functionality.
The root cause of this vulnerability lies in the lack of proper gas metering or execution time limits for the arbitrary code executed during token transfers. An attacker can exploit this by crafting a token that triggers an infinite loop or resource-intensive computation, effectively locking up the node's resources and preventing further block processing.
Implement gas metering or execution time limits for all arbitrary code executed during token transfers or other critical blockchain operations. This can be achieved by leveraging the existing gas metering mechanisms in the Cosmos SDK or implementing custom time-based limits.
ACKNOWLEDGED: The Elys Network team acknowledged the issue.
// Informational
In the provided code snippet, the ClearOutdatedSlippageTrack
function is responsible for deleting expired slippage tracks. However, the expiration date is currently hardcoded as a constant value of 7 days (86400 * 7 seconds). This hardcoded value limits the flexibility of the system and may not be suitable for all scenarios or deployment environments.
Having a fixed expiration date for slippage tracks can lead to potential issues, such as:
Lack of Adaptability: Different projects or use cases may require different retention periods for slippage tracks, depending on their specific requirements or analysis needs.
Limited Governance: The expiration date is hardcoded in the system, preventing the community or governance mechanisms from adjusting or fine-tuning this parameter based on changing circumstances or feedback.
Maintenance Challenges: If the desired expiration period needs to be changed in the future, it would require modifying the codebase and potentially deploying a new version of the software, which can be a time-consuming and error-prone process.
Code Location : https://github.com/elys-network/elys/blob/6a6ec2162613ba8bf7d683162698516e7c6eb7ba/x/amm/keeper/abci.go#L174-L175
Create a new governance parameter that represents the slippage expiration date (e.g., SlippageTrackExpirationDays
). This parameter should be stored in the module's parameter store and initialized with a sensible default value (e.g., 7 days).
SOLVED: The Elys Network team solved the issue by adding suggested recommendations.
// Informational
In the RecordWithdrawValidatorCommission
function within the keeper, there is a potential issue where the function does not return an error in case of failure.
// Eden
unclaimed := commitments.GetRewardUnclaimedForDenom(ptypes.Eden)
if !unclaimed.IsZero() {
err = k.cmk.RecordWithdrawValidatorCommission(ctx, delegator, validator, ptypes.Eden, unclaimed)
}
// EdenB
unclaimed = commitments.GetRewardUnclaimedForDenom(ptypes.EdenB)
if !unclaimed.IsZero() {
err = k.cmk.RecordWithdrawValidatorCommission(ctx, delegator, validator, ptypes.EdenB, unclaimed)
}
Modify the RecordWithdrawValidatorCommission
function to handle errors gracefully and return them consistently.
ACKNOWLEDGED: The Elys Network team acknowledged the issue.
Halborn used automated testing techniques to enhance coverage of certain areas of the scoped component. Among the tools used were staticcheck, gosec, semgrep, unconvert, codeql and nancy. After Halborn verified all the code and scoped structures in the repository and was able to compile them correctly, these tools were leveraged on scoped structures. With these tools, Halborn can statically verify security related issues across the entire codebase.
Gosec
[/elys-0.29.2/x/tokenomics/module.go:75] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
74: func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
> 75: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
76: }
[/elys-0.29.2/x/stablestake/module.go:73] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
72: func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
> 73: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
74: }
[/elys-0.29.2/x/perpetual/module.go:75] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
74: func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
> 75: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
76: }
[/elys-0.29.2/x/perpetual/migrations/v5_migration.go:18] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
17: for _, mtp := range m.keeper.GetAllMTPs(ctx) {
> 18: m.keeper.DestroyMTP(ctx, mtp.Address, mtp.Id)
19: }
[/elys-0.29.2/x/perpetual/migrations/v5_migration.go:14] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
13: params := types.NewParams()
> 14: m.keeper.SetParams(ctx, ¶ms)
15:
[/elys-0.29.2/x/perpetual/migrations/v5_migration.go:10] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
9: // reset store
> 10: m.keeper.ResetStore(ctx)
11:
[/elys-0.29.2/x/perpetual/migrations/v4_migration.go:18] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
17: for _, mtp := range m.keeper.GetAllMTPs(ctx) {
> 18: m.keeper.DestroyMTP(ctx, mtp.Address, mtp.Id)
19: }
[/elys-0.29.2/x/perpetual/migrations/v4_migration.go:14] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
13: params := types.NewParams()
> 14: m.keeper.SetParams(ctx, ¶ms)
15:
[/elys-0.29.2/x/perpetual/migrations/v4_migration.go:10] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
9: // reset store
> 10: m.keeper.ResetStore(ctx)
11:
[/elys-0.29.2/x/perpetual/migrations/v3_migration.go:10] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
9: params := types.NewParams()
> 10: m.keeper.SetParams(ctx, ¶ms)
11: return nil
[/elys-0.29.2/x/perpetual/migrations/v2_migration.go:10] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
9: params := types.NewParams()
> 10: m.keeper.SetParams(ctx, ¶ms)
11: return nil
[/elys-0.29.2/x/perpetual/keeper/open_short_process.go:83] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
82: // Set MTP
> 83: k.OpenShortChecker.SetMTP(ctx, mtp)
84:
[/elys-0.29.2/x/perpetual/keeper/open_short_process.go:77] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
76: // Update consolidated collateral amount
> 77: k.OpenShortChecker.CalcMTPConsolidateCollateral(ctx, mtp, baseCurrency)
78:
[/elys-0.29.2/x/perpetual/keeper/open_long_process.go:103] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
102: // Set MTP
> 103: k.OpenLongChecker.SetMTP(ctx, mtp)
104:
[/elys-0.29.2/x/perpetual/keeper/open_long_process.go:97] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
96: // Update consolidated collateral amount
> 97: k.OpenLongChecker.CalcMTPConsolidateCollateral(ctx, mtp, baseCurrency)
98:
[/elys-0.29.2/x/perpetual/genesis.go:35] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
34: // this line is used by starport scaffolding # genesis/module/init
> 35: k.SetParams(ctx, &genState.Params)
36: }
[/elys-0.29.2/x/parameter/module.go:75] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
74: func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
> 75: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
76: }
[/elys-0.29.2/x/oracle/module.go:76] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
75: func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
> 76: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
77: }
[/elys-0.29.2/x/leveragelp/module.go:75] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
74: func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
> 75: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
76: }
[/elys-0.29.2/x/leveragelp/migrations/v2_migration.go:10] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
9: params := types.NewParams()
> 10: m.keeper.SetParams(ctx, ¶ms)
11: return nil
[/elys-0.29.2/x/leveragelp/genesis.go:32] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
31: // this line is used by starport scaffolding # genesis/module/init
> 32: k.SetParams(ctx, &genState.Params)
33: }
[/elys-0.29.2/x/incentive/module.go:75] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
74: func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
> 75: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
76: }
[/elys-0.29.2/x/incentive/keeper/hooks_staking.go:16] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
15: // Create an entity in commitment module
> 16: k.cmk.BeforeDelegationCreated(ctx, delAddr.String(), valAddr.String())
17:
[/elys-0.29.2/x/incentive/keeper/hooks_commitment.go:14] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
13: func (k Keeper) EdenUncommitted(ctx sdk.Context, creator string, amount sdk.Coin) {
> 14: k.BurnEdenBFromEdenUncommitted(ctx, creator, amount.Amount)
15: }
[/elys-0.29.2/x/commitment/module.go:74] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
73: func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
> 74: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
75: }
[/elys-0.29.2/x/burner/module.go:74] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
73: func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
> 74: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
75: }
[/elys-0.29.2/x/assetprofile/module.go:74] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
73: func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
> 74: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
75: }
[/elys-0.29.2/x/amm/module.go:75] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
74: func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
> 75: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
76: }
[/elys-0.29.2/x/amm/keeper/update_pool_for_swap.go:98] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
97: if k.hooks != nil {
> 98: k.hooks.AfterSwap(ctx, sender, pool, tokensIn, tokensOut)
99: }
[/elys-0.29.2/x/amm/keeper/msg_server_update_pool_params.go:33] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
32: pool.PoolParams = poolParams
> 33: k.SetPool(ctx, pool)
34:
[/elys-0.29.2/x/amm/keeper/msg_server_feed_multiple_external_liquidity.go:92] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
91: pool.PoolParams.ExternalLiquidityRatio = elRatio
> 92: k.SetPool(ctx, pool)
93: }
[/elys-0.29.2/x/amm/keeper/denom_liquidity.go:89] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
88:
> 89: k.IncreaseDenomLiquidity(ctx, coin.Denom, coin.Amount)
90: }
[/elys-0.29.2/x/amm/genesis.go:13] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
12: for _, elem := range genState.PoolList {
> 13: k.SetPool(ctx, elem)
14: }
[/elys-0.29.2/x/accountedpool/module.go:74] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
73: func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
> 74: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
75: }
[/elys-0.29.2/x/accountedpool/keeper/hooks_perpetual.go:38] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
37: func (k Keeper) AfterAmmSwap(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool) {
> 38: k.UpdateAccountedPool(ctx, ammPool, perpetualPool)
39: }
[/elys-0.29.2/x/accountedpool/keeper/hooks_perpetual.go:33] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
32: func (k Keeper) AfterAmmExitPool(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool) {
> 33: k.UpdateAccountedPool(ctx, ammPool, perpetualPool)
34: }
[/elys-0.29.2/x/accountedpool/keeper/hooks_perpetual.go:28] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
27: func (k Keeper) AfterAmmJoinPool(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool) {
> 28: k.UpdateAccountedPool(ctx, ammPool, perpetualPool)
29: }
[/elys-0.29.2/x/accountedpool/keeper/hooks_perpetual.go:23] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
22: func (k Keeper) AfterAmmPoolCreated(ctx sdk.Context, ammPool ammtypes.Pool) {
> 23: k.InitiateAccountedPool(ctx, ammPool)
24: }
[/elys-0.29.2/x/accountedpool/keeper/hooks_perpetual.go:18] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
17: func (k Keeper) AfterPerpetualPositionClosed(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool) {
> 18: k.UpdateAccountedPool(ctx, ammPool, perpetualPool)
19: }
[/elys-0.29.2/x/accountedpool/keeper/hooks_perpetual.go:14] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
13: func (k Keeper) AfterPerpetualPositionModified(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool) {
> 14: k.UpdateAccountedPool(ctx, ammPool, perpetualPool)
15: }
[/elys-0.29.2/x/accountedpool/keeper/hooks_perpetual.go:10] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
9: func (k Keeper) AfterPerpetualPositionOpen(ctx sdk.Context, ammPool ammtypes.Pool, perpetualPool perpetualtypes.Pool) {
> 10: k.UpdateAccountedPool(ctx, ammPool, perpetualPool)
11: }
Staticcheck
accountedpool/keeper/accounted_pool_initiate.go:25:2: should replace loop with accountedPool.PoolAssets = append(accountedPool.PoolAssets, ammPool.PoolAssets...) (S1011)
accountedpool/keeper/accounted_pool_update_test.go:47:2: should replace loop with accountedPool.PoolAssets = append(accountedPool.PoolAssets, ammPool.PoolAssets...) (S1011)
accountedpool/keeper/keeper.go:42:83: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
accountedpool/module_simulation.go:45:63: simtypes.WeightedProposalContent is deprecated: Use WeightedProposalMsg instead. (SA1019)
accountedpool/types/accounted_pool.pb.go:34:14: github_com_cosmos_cosmos_sdk_types.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
accountedpool/types/errors.go:11:33: sdkerrors.Register is deprecated: functionality of this package has been moved to it's own module: (SA1019)
accountedpool/types/errors.go:12:33: sdkerrors.Register is deprecated: functionality of this package has been moved to it's own module: (SA1019)
accountedpool/types/pool_asset.pb.go:30:9: github_com_cosmos_cosmos_sdk_types.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
accountedpool/types/query.pb.gw.go:16:2: "github.com/golang/protobuf/descriptor" is deprecated: See the "google.golang.org/protobuf/reflect/protoreflect" package for how to obtain an EnumDescriptor or MessageDescriptor in order to programatically interact with the protobuf type system. (SA1019)
accountedpool/types/query.pb.gw.go:17:2: "github.com/golang/protobuf/proto" is deprecated: Use the "google.golang.org/protobuf/proto" package instead. (SA1019)
accountedpool/types/query.pb.gw.go:32:9: descriptor.ForMessage is deprecated: Not all concrete message types satisfy the Message interface. Use MessageDescriptorProto instead. If possible, the calling code should be rewritten to use protobuf reflection instead. See package "google.golang.org/protobuf/reflect/protoreflect" for details. (SA1019)
amm/client/wasm/query_balance_of_denom.go:12:20: func (*Querier).queryBalanceOfDenom is unused (U1000)
amm/keeper/apply_exit_pool_state_change.go:10:109: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/apply_exit_pool_state_change_test.go:8:2: package "github.com/elys-network/elys/x/amm/types" is being imported more than once (ST1019)
amm/keeper/apply_exit_pool_state_change_test.go:9:2: other import of "github.com/elys-network/elys/x/amm/types"
amm/keeper/apply_join_pool_state_change.go:8:109: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/calc_in_route_spot_price.go:10:5: should omit nil check; len() for []*github.com/elys-network/elys/x/amm/types.SwapAmountInRoute is defined as zero (S1009)
amm/keeper/calc_out_route_spot_price.go:10:5: should omit nil check; len() for []*github.com/elys-network/elys/x/amm/types.SwapAmountOutRoute is defined as zero (S1009)
amm/keeper/create_elys_multihop_expected_swap_outs.go:14:6: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/create_elys_multihop_expected_swap_outs.go:15:24: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/elys_routed_multihop.go:41:2: should use 'return poolIds[0] != poolIds[1]' instead of 'if poolIds[0] == poolIds[1] { return false }; return true' (S1008)
amm/keeper/keeper_exit_pool.go:13:16: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/keeper_join_pool_no_swap.go:22:17: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/keeper_join_pool_no_swap.go:24:33: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/keeper_join_pool_no_swap.go:29:16: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/keeper_swap_exact_amount_in_test.go:20:23: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/keeper_swap_exact_amount_out_test.go:19:23: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/msg_server_exit_pool_test.go:19:21: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/msg_server_join_pool_test.go:18:21: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/msg_server_swap_by_denom_test.go:19:21: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/msg_server_swap_exact_amount_in_test.go:20:21: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/msg_server_swap_exact_amount_out_test.go:18:21: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/msg_server_test.go:13:6: func setupMsgServer is unused (U1000)
amm/keeper/pool.go:146:2: redundant return statement (S1023)
amm/keeper/pool_share.go:38:2: this value of entry is never used (SA4006)
amm/keeper/pool_share.go:92:104: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/pool_share_test.go:11:2: package "github.com/elys-network/elys/x/amm/types" is being imported more than once (ST1019)
amm/keeper/pool_share_test.go:12:2: other import of "github.com/elys-network/elys/x/amm/types"
amm/keeper/route_exact_amount_in_test.go:20:23: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/route_exact_amount_out_test.go:20:23: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/keeper/update_pool_for_swap.go:21:4: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/module_simulation.go:70:63: simtypes.WeightedProposalContent is deprecated: Use WeightedProposalMsg instead. (SA1019)
amm/types/calc_exit_pool.go:11:139: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/calc_exit_pool.go:18:2: should merge variable declaration with assignment on next line (S1021)
amm/types/calc_exit_pool.go:82:129: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/calc_exit_pool.go:90:2: should merge variable declaration with assignment on next line (S1021)
amm/types/calc_in_amt_given_out.go:25:3: this value of err is never used (SA4006)
amm/types/calc_out_amt_given_in.go:44:3: this value of err is never used (SA4006)
amm/types/denom_liquidity.pb.go:30:12: github_com_cosmos_cosmos_sdk_types.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/expected_keepers.go:55:51: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/hooks.go:10:104: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/hooks.go:13:81: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/hooks.go:35:126: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/hooks.go:41:103: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/keys.go:102:30: variable in loop condition never changes (SA4008)
amm/types/message_exit_pool.go:13:90: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/message_join_pool.go:13:90: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/pool.go:142:35: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/pool.go:146:44: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/pool.go:235:58: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/pool.pb.go:35:20: github_com_cosmos_cosmos_sdk_types.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/pool_asset.pb.go:30:9: github_com_cosmos_cosmos_sdk_types.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/pool_calc_join_pool_no_swap_shares.go:21:68: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/pool_calc_join_pool_no_swap_shares.go:82:72: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/pool_calc_join_pool_shares.go:10:116: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/pool_calc_join_pool_shares.go:10:136: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/pool_calc_join_pool_shares.go:36:77: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/pool_exit_pool.go:7:124: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
amm/types/pool_exit_pool.go:22:87: sdk.Int is deprecated: Functionality of this package has been moved to it's own module: cosmossdk.io/math (SA1019)
Errcheck
accountedpool/keeper/accounted_pool.go:40:22: defer iterator.Close()
accountedpool/keeper/accounted_pool_update_test.go:93:25: apk.UpdateAccountedPool(ctx, ammPool, perpetualPool)
accountedpool/keeper/hooks_perpetual.go:10:23: k.UpdateAccountedPool(ctx, ammPool, perpetualPool)
accountedpool/keeper/hooks_perpetual.go:14:23: k.UpdateAccountedPool(ctx, ammPool, perpetualPool)
accountedpool/keeper/hooks_perpetual.go:18:23: k.UpdateAccountedPool(ctx, ammPool, perpetualPool)
accountedpool/keeper/hooks_perpetual.go:23:25: k.InitiateAccountedPool(ctx, ammPool)
accountedpool/keeper/hooks_perpetual.go:28:23: k.UpdateAccountedPool(ctx, ammPool, perpetualPool)
accountedpool/keeper/hooks_perpetual.go:33:23: k.UpdateAccountedPool(ctx, ammPool, perpetualPool)
accountedpool/keeper/hooks_perpetual.go:38:23: k.UpdateAccountedPool(ctx, ammPool, perpetualPool)
accountedpool/module.go:74:34: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
amm/genesis.go:13:12: k.SetPool(ctx, elem)
amm/keeper/abci_test.go:288:31: suite.app.AmmKeeper.SetPool(suite.ctx, pool)
amm/keeper/abci_test.go:289:31: suite.app.AmmKeeper.SetPool(suite.ctx, pool2)
amm/keeper/batch_processing.go:41:22: defer iterator.Close()
amm/keeper/batch_processing.go:56:22: defer iterator.Close()
amm/keeper/batch_processing.go:84:22: defer iterator.Close()
amm/keeper/batch_processing.go:99:22: defer iterator.Close()
amm/keeper/calc_in_route_spot_price_test.go:91:29: suite.app.AmmKeeper.SetPool(suite.ctx, pool)
amm/keeper/calc_in_route_spot_price_test.go:92:29: suite.app.AmmKeeper.SetPool(suite.ctx, pool2)
amm/keeper/calc_out_route_spot_price_test.go:91:29: suite.app.AmmKeeper.SetPool(suite.ctx, pool)
amm/keeper/calc_out_route_spot_price_test.go:92:29: suite.app.AmmKeeper.SetPool(suite.ctx, pool2)
amm/keeper/calc_swap_estimation_by_denom_test.go:91:29: suite.app.AmmKeeper.SetPool(suite.ctx, pool)
amm/keeper/calc_swap_estimation_by_denom_test.go:92:29: suite.app.AmmKeeper.SetPool(suite.ctx, pool2)
amm/keeper/denom_liquidity.go:40:22: defer iterator.Close()
amm/keeper/denom_liquidity.go:89:27: k.IncreaseDenomLiquidity(ctx, coin.Denom, coin.Amount)
amm/keeper/keeper_test.go:122:12: k.SetPool(ctx, pool)
amm/keeper/msg_server_feed_multiple_external_liquidity.go:92:12: k.SetPool(ctx, pool)
amm/keeper/msg_server_join_pool_test.go:174:31: suite.app.AmmKeeper.SetPool(suite.ctx, pool)
amm/keeper/msg_server_swap_by_denom_test.go:144:31: suite.app.AmmKeeper.SetPool(suite.ctx, pool)
amm/keeper/msg_server_swap_by_denom_test.go:145:31: suite.app.AmmKeeper.SetPool(suite.ctx, pool2)
amm/keeper/msg_server_swap_exact_amount_in_test.go:177:31: suite.app.AmmKeeper.SetPool(suite.ctx, pool)
amm/keeper/msg_server_swap_exact_amount_in_test.go:178:31: suite.app.AmmKeeper.SetPool(suite.ctx, pool2)
amm/keeper/msg_server_swap_exact_amount_in_test.go:271:29: suite.app.AmmKeeper.SetPool(suite.ctx, pool)
amm/keeper/msg_server_swap_exact_amount_out_test.go:174:31: suite.app.AmmKeeper.SetPool(suite.ctx, pool)
amm/keeper/msg_server_swap_exact_amount_out_test.go:175:31: suite.app.AmmKeeper.SetPool(suite.ctx, pool2)
amm/keeper/msg_server_update_pool_params.go:33:11: k.SetPool(ctx, pool)
amm/keeper/oracle_pool_slippage_track.go:40:22: defer iterator.Close()
amm/keeper/oracle_pool_slippage_track.go:56:22: defer iterator.Close()
amm/keeper/oracle_pool_slippage_track.go:75:22: defer iterator.Close()
amm/keeper/pool.go:41:22: defer iterator.Close()
amm/keeper/pool.go:56:22: defer iterator.Close()
amm/keeper/pool.go:135:22: defer iterator.Close()
amm/keeper/pool_test.go:35:17: keeper.SetPool(ctx, items[i])
amm/keeper/pool_test.go:96:17: keeper.SetPool(ctx, item)
amm/keeper/route_exact_amount_in_test.go:176:31: suite.app.AmmKeeper.SetPool(suite.ctx, pool)
amm/keeper/route_exact_amount_out_test.go:174:31: suite.app.AmmKeeper.SetPool(suite.ctx, pool)
amm/keeper/update_pool_for_swap.go:98:20: k.hooks.AfterSwap(ctx, sender, pool, tokensIn, tokensOut)
amm/module.go:75:34: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
assetprofile/keeper/entry.go:33:22: defer iterator.Close()
assetprofile/keeper/entry.go:57:22: defer iterator.Close()
assetprofile/module.go:74:34: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
burner/keeper/history.go:57:22: defer iterator.Close()
burner/module.go:74:34: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
commitment/keeper/commitments.go:25:22: defer iterator.Close()
commitment/keeper/commitments.go:72:22: defer iterator.Close()
commitment/keeper/deposit_liquid_tokens_test.go:53:35: keeper.DepositLiquidTokensClaimed(ctx, ptypes.Eden, sdk.NewInt(100), creator.String())
commitment/module.go:74:34: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
epochs/keeper/epoch_infos.go:41:22: defer iterator.Close()
incentive/keeper/elys_staked.go:40:22: defer iterator.Close()
incentive/keeper/hooks_commitment.go:14:32: k.BurnEdenBFromEdenUncommitted(ctx, creator, amount.Amount)
incentive/keeper/hooks_staking.go:16:31: k.cmk.BeforeDelegationCreated(ctx, delAddr.String(), valAddr.String())
incentive/keeper/keeper_apr_per_pool_test.go:92:29: ik.UpdateLPRewardsUnclaimed(ctx, lpIncentive)
incentive/keeper/keeper_apr_per_pool_test.go:114:29: ik.UpdateLPRewardsUnclaimed(ctx, lpIncentive)
incentive/keeper/keeper_withdraw_test.go:126:46: app.CommitmentKeeper.BeforeDelegationCreated(ctx, delegator, valAddress.String())
incentive/module.go:75:34: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
leveragelp/genesis.go:32:13: k.SetParams(ctx, &genState.Params)
leveragelp/keeper/begin_blocker_test.go:30:13: k.SetParams(suite.ctx, ¶ms)
leveragelp/keeper/begin_blocker_test.go:56:13: k.SetParams(suite.ctx, ¶ms)
leveragelp/keeper/params_test.go:15:13: k.SetParams(ctx, ¶ms)
leveragelp/keeper/pool.go:20:22: defer iterator.Close()
leveragelp/keeper/position_close_test.go:36:29: suite.app.AmmKeeper.SetPool(suite.ctx, ammtypes.Pool{
leveragelp/keeper/position_open_test.go:31:29: suite.app.AmmKeeper.SetPool(suite.ctx, ammtypes.Pool{
leveragelp/keeper/query_params_test.go:16:18: keeper.SetParams(ctx, ¶ms)
leveragelp/keeper/utils_test.go:19:13: k.SetParams(suite.ctx, ¶ms)
leveragelp/keeper/utils_test.go:29:13: k.SetParams(suite.ctx, ¶ms)
leveragelp/keeper/utils_test.go:95:13: k.SetParams(suite.ctx, ¶ms)
leveragelp/keeper/utils_test.go:123:29: suite.app.AmmKeeper.SetPool(suite.ctx, ammtypes.Pool{
leveragelp/migrations/v2_migration.go:10:20: m.keeper.SetParams(ctx, ¶ms)
leveragelp/module.go:75:34: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
oracle/keeper/asset_info.go:39:22: defer iterator.Close()
oracle/keeper/price.go:32:22: defer iterator.Close()
oracle/keeper/price.go:46:22: defer iterator.Close()
oracle/keeper/price.go:68:22: defer iterator.Close()
oracle/keeper/price_feeder.go:40:22: defer iterator.Close()
oracle/module.go:76:34: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
parameter/module.go:75:34: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
perpetual/genesis.go:35:13: k.SetParams(ctx, &genState.Params)
perpetual/keeper/get_amm_pool_test.go:66:23: app.AmmKeeper.SetPool(ctx, expectedPool)
perpetual/keeper/get_best_pool_test.go:66:23: app.AmmKeeper.SetPool(ctx, pool)
perpetual/keeper/open_long_process.go:97:48: k.OpenLongChecker.CalcMTPConsolidateCollateral(ctx, mtp, baseCurrency)
perpetual/keeper/open_long_process.go:103:26: k.OpenLongChecker.SetMTP(ctx, mtp)
perpetual/keeper/open_short_process.go:77:49: k.OpenShortChecker.CalcMTPConsolidateCollateral(ctx, mtp, baseCurrency)
perpetual/keeper/open_short_process.go:83:27: k.OpenShortChecker.SetMTP(ctx, mtp)
perpetual/keeper/params_test.go:15:13: k.SetParams(ctx, ¶ms)
perpetual/keeper/pool.go:20:22: defer iterator.Close()
perpetual/keeper/query_params_test.go:16:18: keeper.SetParams(ctx, ¶ms)
perpetual/keeper/reset_store.go:22:19: defer iter.Close()
perpetual/migrations/v2_migration.go:10:20: m.keeper.SetParams(ctx, ¶ms)
perpetual/migrations/v3_migration.go:10:20: m.keeper.SetParams(ctx, ¶ms)
perpetual/migrations/v4_migration.go:10:21: m.keeper.ResetStore(ctx)
perpetual/migrations/v4_migration.go:14:20: m.keeper.SetParams(ctx, ¶ms)
perpetual/migrations/v4_migration.go:18:22: m.keeper.DestroyMTP(ctx, mtp.Address, mtp.Id)
perpetual/migrations/v5_migration.go:10:21: m.keeper.ResetStore(ctx)
perpetual/migrations/v5_migration.go:14:20: m.keeper.SetParams(ctx, ¶ms)
perpetual/migrations/v5_migration.go:18:22: m.keeper.DestroyMTP(ctx, mtp.Address, mtp.Id)
perpetual/module.go:75:34: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
stablestake/keeper/debt.go:50:22: defer iterator.Close()
stablestake/module.go:73:34: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
tokenomics/keeper/airdrop.go:40:22: defer iterator.Close()
tokenomics/keeper/time_based_inflation.go:51:22: defer iterator.Close()
tokenomics/module.go:75:34: types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
transferhook/keeper/swap_test.go:243:31: suite.app.AmmKeeper.SetPool(suite.ctx, pool)
Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.
// Download the full report
* Use Google Chrome for best results
** Check "Background Graphics" in the print settings if needed