Platform: Code4rena
Start Date: 02/02/2024
Pot Size: $100,000 USDC
Total HM: 11
Participants: 27
Period: 28 days
Judge: Lambda
Total Solo HM: 4
Id: 327
League:
Rank: 10/27
Findings: 1
Award: $1,291.82
🌟 Selected for report: 1
🚀 Solo Findings: 0
🌟 Selected for report: hunter_w3b
Also found by: 0xSmartContract, Franfran, TheSchnilch, ZanyBonzy, carrotsmuggler, castle_chain, fouzantanveer, kaveyjoe, popeye, yongskiws
1291.8215 USDC - $1,291.82
HydraDX is a cutting-edge DeFi protocol designed to enhance liquidity within the Polkadot
ecosystem. At its core, HydraDX operates as a cross-chain liquidity protocol built on Substrate, offering an open and permissionless platform for users. The protocol functions as a parachain within the Polkadot
network, enabling native asset swaps within the ecosystem while also facilitating interoperability with other blockchain networks such as Ethereum.
One of the key innovations of HydraDX
is its Omnipool, which serves as an AMM. Unlike traditional order book-based exchanges, where buyers and sellers create orders that are matched against each other, an AMM like the Omnipool provides liquidity through a single pool where assets are traded against the protocol itself. Liquidity providers contribute assets to the pool and earn rewards in return, helping to maintain liquidity for various trading pairs.
HydraDX addresses several challenges faced by existing DEX
protocols, such as slippage, impermanent loss, and front-running. To overcome these challenges, HydraDX
implements several innovative features. The Omnipool consolidates liquidity for all assets into a single pool, reducing slippage and improving trading efficiency. Additionally, the protocol employs an order matching engine connected to the AMM pool via an oracle, allowing for more efficient trade execution. Transaction fees can be paid in any currency, enhancing flexibility for users, and the protocol supports dollar-cost averaging, automating asset purchases at regular intervals regardless of price fluctuations. Looking ahead, HydraDX is exploring additional features such as zkRollups for transaction scalability, resistance mechanisms against front-running, and the introduction of new financial instruments like lending, derivatives, and synthetics. The protocol also utilizes a LBP model to distribute tokens and bootstrap liquidity, ensuring a fair and sustainable ecosystem for users and the community.
lib.rs: This contract implements a DEX using an AMM model on the Substrate framework. It allows users to trade assets without intermediaries by pooling liquidity from providers and using on-chain math functions to calculate state changes during operations like adding/removing
liquidity or executing swaps. Key functions allow managing the assets, positions represented as NFTs, and trades, while adhering to parameters like price barriers and dynamic fees. Precise updates to the pool reserves and hub asset imbalance are performed through hooks and events provide transparency. The non-custodial and low fee nature of the omnipool model enables greater decentralization and accessibility for traders compared to order-book based HydraDX
alternatives.
Here's a breakdown of the key functions:
Protocol Account:
protocol_account()
: Returns the protocol account address, which is used for managing the omnipool's assets.Asset Management:
load_asset_state(asset_id)
: Retrieves the state of an asset, including its reserve and tradability.set_asset_state(asset_id, new_state)
: Sets the new state of an asset.add_asset(asset_id, state)
: Adds a new asset to the omnipool.update_asset_state(asset_id, delta)
: Updates the state of an asset with the given delta changes.remove_asset(asset_id)
: Removes an asset from the omnipool.allow_assets(asset_in, asset_out)
: Checks if the given assets can be traded based on their tradability.sell_hub_asset(origin, who, asset_out, amount, limit)
: Swaps hub asset for asset_out.buy_asset_for_hub_asset(origin, who, asset_out, amount, limit)
: Swaps asset for hub asset.buy_hub_asset(who, asset_in, amount, limit)
: Buys hub asset from the pool.sell_asset_for_hub_asset(who, asset_in, amount, limit)
: Sells asset for hub asset.Position Management:
create_and_mint_position_instance(owner)
: Generates an NFT instance ID and mints an NFT for the position.set_position(position_id, position)
: Inserts or updates a position with the given data.load_position(position_id, owner)
: Loads a position and checks its owner.Other Functions:
get_hub_asset_balance_of_protocol_account()
: Returns the hub asset balance of the protocol account.is_hub_asset_allowed(operation)
: Checks if the given operation is allowed for the hub asset.exists(asset)
: Checks if an asset exists in the omnipool.process_trade_fee(trader, asset, amount)
: Calls the on_trade_fee
hook and ensures that no more than the fee amount is transferred.process_hub_amount(amount, dest)
: Processes the given hub amount by transferring it to the specified destination or burning it if the transfer fails.types.rs: The codebase defines types and structures used in an Omnipool.
Here's a breakdown of the key functions:
Types:
Balance
: This type represents the balance of an asset and is implemented as a u128
.Price
: This type represents the price of an asset and is implemented as a FixedU128
.Tradability
: This bitflag type indicates whether an asset can be bought, sold, or have liquidity added or removed.AssetState
: This type stores the state of an asset in the Omnipool, including its hub reserve, LP shares, protocol shares, weight cap, and tradability.Position
: This type represents a liquidity position in the Omnipool, including the asset ID, amount added, LP shares owned, and the price at which liquidity was provided.SimpleImbalance
: This type represents an imbalance, which can be positive or negative.AssetReserveState
: This type stores the state of an asset reserve, including its reserve, hub reserve, LP shares, protocol shares, weight cap, and tradability.Functions:
impl From<AssetReserveState<Balance>> for AssetState<Balance>
: Converts an AssetReserveState
to an AssetState
.
impl From<(MathReserveState<Balance>, Permill, Tradability)> for AssetState<Balance>
: Converts a tuple of MathReserveState
, Permill
, and Tradability
to an AssetState
.
impl From<&Position<Balance, AssetId>> for hydra_dx_math::omnipool::types::Position<Balance>
: Converts a Position
to a Position
in the hydra_dx_math::omnipool::types
module.
impl Position<Balance, AssetId>
: Provides methods to update the position state with delta changes.
impl Add<Balance> for SimpleImbalance<Balance>
: Adds a Balance
to a SimpleImbalance
.
impl Sub<Balance> for SimpleImbalance<Balance>
: Subtracts a Balance
from a SimpleImbalance
.
impl From<&AssetReserveState<Balance>> for MathReserveState<Balance>
: Converts an AssetReserveState
to a MathReserveState
.
impl From<AssetReserveState<Balance>> for MathReserveState<Balance>
: Converts an AssetReserveState
to a MathReserveState
.
impl From<(&AssetState<Balance>, Balance)> for AssetReserveState<Balance>
: Converts a tuple of AssetState
and Balance
to an AssetReserveState
.
impl From<(AssetState<Balance>, Balance)> for AssetReserveState<Balance>
: Converts a tuple of AssetState
and Balance
to an AssetReserveState
.
impl AssetReserveState<Balance>
: Provides methods to calculate the price and weight cap of an asset, and update the asset state with delta changes.
Key Features:
The Tradability
bitflag provides a convenient way to represent the tradability of an asset.
The SimpleImbalance
type provides a simple way to represent imbalances, which can be positive or negative.
The AssetReserveState
type provides a comprehensive representation of an asset reserve's state in the Omnipool.
The Position
type provides a complete representation of a liquidity position in the Omnipool.
The functions provided allow for the conversion between different representations of assets, liquidity positions, and imbalances.
traits.rs: This contract defines traits
, structs
, and implementations facilitating the management of an Omnipool, including hooks for liquidity changes and trades, external price fetching, and enforcing price constraints.
Here's a breakdown of the key functions:
Traits:
OmnipoolHooks
: This trait defines hooks that can be implemented to perform custom actions when liquidity is changed or a trade occurs in the Omnipool.ExternalPriceProvider
: This trait defines an interface for an external price provider that can be used to get the price of an asset pair.ShouldAllow
: This trait defines a way to validate whether a price change is allowed.Types:
AssetInfo
: This type stores information about an asset before and after a liquidity change or trade.EnsurePriceWithin
: This type implements the ShouldAllow
trait and ensures that the price of an asset is within a certain range of the current spot price and the external oracle price.Key Features:
OmnipoolHooks
trait provides a way to hook into the Omnipool protocol and perform custom actions when liquidity is changed or a trade occurs.ExternalPriceProvider
trait provides a way to get the price of an asset pair from an external source.ShouldAllow
trait provides a way to validate whether a price change is allowed.EnsurePriceWithin
type implements the ShouldAllow
trait and ensures that the price of an asset is within a certain range of the current spot price and the external oracle price.math.rs: This codebase implements a set of functions for calculating the delta changes in the state of an asset pool when various liquidity-related operations are performed, such as selling, buying, adding liquidity, removing liquidity, and calculating the total value locked (TVL) and cap difference.
Here's a breakdown of the key functionality of the contract:
Selling an asset:
calculate_sell_state_changes
calculates the delta changes in the state of the asset pool when an asset is sold. It takes the current state of the asset in and out, the amount being sold, and the asset and protocol fees as input. It calculates the delta changes in the hub and reserve balances of both assets, the delta change in the imbalance, and the fee amounts.calculate_sell_hub_state_changes
calculates the delta changes in the state of the asset pool when the asset being sold is the Hub asset. It takes the current state of the asset out, the amount of Hub asset being sold, the asset fee, the current imbalance, and the total hub reserve as input. It calculates the delta changes in the reserve and hub reserve balances of the asset out, the delta change in the imbalance, and the fee amount.Buying an asset:
calculate_buy_for_hub_asset_state_changes
calculates the delta changes in the state of the asset pool when the asset being bought is the Hub asset. It takes the current state of the asset out, the amount of asset out being bought, the asset fee, the current imbalance, and the total hub reserve as input. It calculates the delta changes in the reserve and hub reserve balances of the asset out, the delta change in the imbalance, and the fee amount.calculate_buy_state_changes
calculates the delta changes in the state of the asset pool when an asset is bought. It takes the current state of the asset in and out, the amount being bought, the asset and protocol fees, and the current imbalance as input. It calculates the delta changes in the hub and reserve balances of both assets, the delta change in the imbalance, and the fee amounts.Adding liquidity:
calculate_add_liquidity_state_changes
calculates the delta changes in the state of the asset pool when liquidity is added. It takes the current state of the asset, the amount being added, the current imbalance, and the total hub reserve as input. It calculates the delta changes in the hub and reserve balances of the asset, the delta change in the shares, and the delta change in the imbalance.Removing liquidity:
calculate_remove_liquidity_state_changes
calculates the delta changes in the state of the asset pool when liquidity is removed. It takes the current state of the asset, the shares being removed, the position from which liquidity should be removed, the current imbalance, the total hub reserve, and the withdrawal fee as input. It calculates the delta changes in the hub and reserve balances of the asset, the delta change in the shares, the delta change in the imbalance, the amount of Hub asset transferred to the LP, and the delta changes in the position's reserve and shares.Calculating TVL and cap difference:
calculate_tvl
calculates the total value locked (TVL) in the asset pool. It takes the hub reserve and the stable asset reserve as input. It calculates the TVL by multiplying the hub reserve by the stable asset reserve and dividing by the stable asset's hub reserve.calculate_cap_difference
calculates the difference between the current weight of an asset in the pool and its weight cap. It takes the current state of the asset, the asset cap, and the total hub reserve as input. It calculates the weight cap, the maximum allowed hub reserve, the price of the asset, and the cap difference.calculate_tvl_cap_difference
calculates the difference between the current TVL of the asset pool and its TVL cap. It takes the current state of the asset, the current state of the stable asset, the TVL cap, and the total hub reserve as input. It calculates the TVL cap, the maximum allowed hub reserve, the price of the asset, and the TVL cap difference.verify_asset_cap
verifies if the weight of an asset in the pool exceeds its weight cap. It takes the current state of the asset, the asset cap, the hub amount being added, and the total hub reserve as input. It calculates the weight of the asset and compares it to the weight cap.types.rs: This contract defines structs and implementations related to asset reserves, liquidity pools, and trading mechanics, including functions for updating asset states, calculating prices, and handling balance updates.
Here's a breakdown of the key functions:
lib.rs: It implements a Curve-style stablecoin AMM with up to 5 assets in a pool. Pools are created by an authority and have a pricing formula based on amplification. Also implements a stableswap pallet for the HydraDX runtime.The stableswap pallet allows for the creation of liquidity pools for stablecoins, which are asset that are pegged to a usd. Stablecoins are designed to be less volatile than other assets, making them more suitable for use in everyday transactions. The stableswap pallet uses a constant product formula to calculate the price of assets in a pool. This formula ensures that the price of an asset in a pool is always proportional to the amount of that asset in the pool.
Here's a breakdown of the key functionality:
AuthorityOrigin
role. When a pool is created, the creator must specify the following information:
LiquidityProviderOrigin
role. When liquidity is added to a pool, the provider must specify the following information:
LiquidityProviderOrigin
role. When liquidity is removed from a pool, the provider must specify the following information:
TraderOrigin
role. When a trade is executed, the trader must specify the following information:
types.rs: This codebase defines data structures and traits related to the management of stable pools . It includes representations of pool properties, asset amounts, tradability flags, and interfaces for interacting with the oracle and calculating weights.
Here's a breakdown of the key functionality:
PoolInfo
PoolInfo
struct defines the properties of a stable pool.assets
: List of asset IDs in the pool.initial_amplification
: Initial amplification parameter.final_amplification
: Final amplification parameter.initial_block
: Block number at which the pool was created.final_block
: Block number at which the amplification parameter will reach its final value.fee
: Trade fee to be withdrawn on sell/buy operations.AssetAmount
AssetAmount
struct represents the amount of an asset with a specified asset ID.u128
balance value.Tradability
Tradability
flag indicates whether an asset can be bought, sold, or have liquidity added or removed.FROZEN
: Asset is frozen and no operations are allowed.SELL
: Asset can be sold into the stable pool.BUY
: Asset can be bought from the stable pool.ADD_LIQUIDITY
: Liquidity of the asset can be added.REMOVE_LIQUIDITY
: Liquidity of the asset can be removed.PoolState
PoolState
struct tracks the state of a stable pool before and after an operation.assets
: List of asset IDs in the pool.before
: Balances of assets before the operation.after
: Balances of assets after the operation.delta
: Difference in balances between before and after.issuance_before
: Total issuance before the operation.issuance_after
: Total issuance after the operation.share_prices
: Share prices of the assets in the pool.StableswapHooks
The StableswapHooks
trait defines an interface for interacting with the oracle and calculating weights.
It includes the following methods:
on_liquidity_changed
: Called when liquidity is added or removed from a pool.on_trade
: Called when a trade occurs in a pool.on_liquidity_changed_weight
: Calculates the weight for liquidity changed operations.on_trade_weight
: Calculates the weight for trade operations.The default implementation of this trait does nothing and returns zero weight.
math.rs: The contract implementing functions for a stableswap pool, used for AMM with multiple assets, incorporating features such as calculating asset amounts for liquidity provision, trading between assets with fees, and determining the number of shares to be distributed to liquidity providers based on their contribution. The contract implements formulas for calculating the D invariant, representing the product of reserves to maintain stable trading ratios between assets, and the Y reserve value, used in trading calculations within the pool. These calculations are performed using mathematical operations and iterative algorithms to ensure accuracy and stability within the automated market making system.
Here's a breakdown of the key function:
D
invarianttypes.rs: This contract an implementation of the StableSwap for calculating the amount of tokens to be received or sent to a liquidity pool given the amount of tokens to be sent or received from the pool, respectively. That is use a mathematical formula that ensures that the ratio of the reserves of the different assets in the pool remains constant, even as tokens are added or removed from the pool.
Here's a breakdown of the key functionality:
lib.rs: The code is implementation of an EMA
oracle for the protocol. The EMA oracle is used to track the price, volume, and liquidity of assets traded on the HydraDX
over time. The oracle is implemented as a pallet in the Substrate framework.
Here's a breakdown of the key functionality:
HydraDX
.
It updates the EMA oracle with the new trade data.HydraDX
.
It updates the EMA oracle with the new liquidity data.types.rs: The types.rs
contract using the exponential moving average (EMA). It maintains a set of EMA oracles for each asset pair and period, and updates them whenever a trade or liquidity change occurs on the HydraDX
.
Here's a breakdown of the key functionality:
calculate_new_by_integrating_incoming
.calculate_current_from_outdated
.math.rs: The contract defines functions for calculating exponential moving averages (EMAs) and performing weighted averages for oracle values in a HydraDX
.
Here's a breakdown of the key functiona:
calculate_new_by_integrating_incoming
: Calculates new oracle values by integrating incoming values with previous values, using a specified smoothing factor.update_outdated_to_current
: Updates outdated oracle values to current values, using a smoothing factor and the number of iterations since the outdated values were calculated.iterated_price_ema
: Calculates the iterated EMA for prices.iterated_balance_ema
: Calculates the iterated EMA for balances.iterated_volume_ema
: Calculates the iterated EMA for volumes.iterated_liquidity_ema
: Calculates the iterated EMA for liquidity values.exp_smoothing
: Calculates the smoothing factor for a given period.smoothing_from_period
: Calculates the smoothing factor based on a specified period.price_weighted_average
: Calculates a weighted average for prices, giving more weight to the incoming value.balance_weighted_average
: Calculates a weighted average for balances, giving more weight to the incoming value.volume_weighted_average
: Calculates a weighted average for volumes, giving more weight to the incoming value.liquidity_weighted_average
: Calculates a weighted average for liquidity values, giving more weight to the incoming value.lib.rs: This contract is pallet for the Substrate framework. It defines a pallet named pallet
that manages circuit breakers for trade volume and liquidity limits in a HydraDX
.
Here's a breakdown of the key functiona:
Config Trait: The Config
trait defines the requirements that the pallet has on the runtime environment. It includes:
RuntimeEvent
: The type of events that the pallet can emit.AssetId
: The type representing the identifier of an asset.Balance
: The type representing the balance of an asset.TechnicalOrigin
: The origin that is allowed to change trade volume limits.WhitelistedAccounts
: The list of accounts that bypass liquidity limit checks.DefaultMaxNetTradeVolumeLimitPerBlock
: The default maximum percentage of a pool's liquidity that can be traded in a block.DefaultMaxAddLiquidityLimitPerBlock
: The default maximum percentage of a pool's liquidity that can be added in a block.DefaultMaxRemoveLiquidityLimitPerBlock
: The default maximum percentage of a pool's liquidity that can be removed in a block.OmnipoolHubAsset
: The asset ID of the Omnipool's hub asset.WeightInfo
: The weight information for the pallet's extrinsics.Pallet Implementation: The implementation of the pallet includes various functions and methods:
initialize_trade_limit
: Initializes the trade volume limit for an asset if it doesn't exist.calculate_and_store_liquidity_limits
: Calculates and stores the liquidity limits for an asset if they don't exist.ensure_and_update_trade_volume_limit
: Ensures that the trade volume limit for an asset is not exceeded and updates the allowed trade volume limit for the current block.ensure_and_update_add_liquidity_limit
: Ensures that the add liquidity limit for an asset is not exceeded and updates the allowed add liquidity amount for the current block.ensure_and_update_remove_liquidity_limit
: Ensures that the remove liquidity limit for an asset is not exceeded and updates the allowed remove liquidity amount for the current block.validate_limit
: Validates a limit value.calculate_limit
: Calculates the limit value based on the provided liquidity and limit ratio.ensure_pool_state_change_limit
: Ensures that the trade volume limit is not exceeded when performing a pool state change.ensure_add_liquidity_limit
: Ensures that the add liquidity limit is not exceeded.ensure_remove_liquidity_limit
: Ensures that the remove liquidity limit is not exceeded.is_origin_whitelisted_or_root
: Checks if the provided origin is whitelisted or is the root account.lib.rs:
types.rs
Tradability:
Tradability
enum and its associated methods.AssetState:
AssetState
struct and its associated methods for conversion and updating state.Position:
Position
struct and its associated methods.SimpleImbalance:
SimpleImbalance
struct and its associated methods for addition and subtraction.AssetReserveState:
AssetReserveState
struct and its associated methods for conversion, calculating price, and updating state.traits.rs
AssetInfo:
AssetInfo
struct and its associated methods.OmnipoolHooks:
OmnipoolHooks
trait and its associated methods.ExternalPriceProvider:
ExternalPriceProvider
trait and its associated method.ShouldAllow:
ShouldAllow
trait and its associated method.EnsurePriceWithin:
ShouldAllow
trait to ensure that the price change is within certain bounds.EnsurePriceWithin
struct and its implementation of the ShouldAllow
trait.math.rs:
Trade Calculations:
calculate_sell_state_changes
, calculate_sell_hub_state_changes
, calculate_buy_for_hub_asset_state_changes
, calculate_buy_state_changes
Liquidity Operations:
calculate_add_liquidity_state_changes
, calculate_remove_liquidity_state_changes
Fee Calculations:
calculate_fee_amount_for_buy
, calculate_withdrawal_fee
Imbalance Handling:
calculate_imbalance_in_hub_swap
, calculate_delta_imbalance
Price Calculations:
calculate_spot_sprice
, calculate_lrna_spot_sprice
Capacity and Cap Management:
calculate_cap_difference
, calculate_tvl_cap_difference
, verify_asset_cap
types.rs
AssetReserveState: Represents the state of an asset within the system. Roles associated with this struct include:
AssetStateChange: Represents the delta changes of asset state. Roles associated with this struct include:
TradeFee: Contains information about trade fee amounts. Roles associated with this struct include:
TradeStateChange: Represents the delta changes after a trade is executed. Roles associated with this struct include:
HubTradeStateChange: Represents delta changes after a trade with hub asset is executed. Roles associated with this struct include:
LiquidityStateChange: Represents delta changes after adding or removing liquidity. Roles associated with this struct include:
Position: Represents a position with regards to liquidity provision. Roles associated with this struct include:
I129: Represents a signed integer. Roles associated with this struct include:
lib.rs:
Authority Origin: This role is designated to the origin that has the authority to create a new pool. It is specified in the Config
trait as type AuthorityOrigin
.
Liquidity Provider (LP): Liquidity providers are users who add liquidity to the pool by providing assets. They are the origin of functions like add_liquidity
and remove_liquidity
.
Pool Manager: The pool manager is responsible for managing and updating pool parameters such as fees and amplification. The pool manager's role is typically associated with the Authority Origin
.
System Account: The system account, represented by frame_system::Config::AccountId
, may have implicit roles in the contract, such as executing transactions and maintaining system-level operations.
Share Token Holder: Share token holders are users who receive shares in exchange for providing liquidity to the pool. These shares represent the LP's ownership stake in the pool.
types.rs
PoolInfo: Represents the properties of a liquidity pool. Roles associated with this struct include:
AssetAmount: Represents the amount of an asset. Roles associated with this struct include:
Tradability: Represents the tradability flags for assets. Roles associated with this struct include:
BenchmarkHelper: Trait for benchmarking purposes. Roles associated with this trait include:
PoolState: Represents the state of a liquidity pool. Roles associated with this struct include:
StableswapHooks: Trait for interacting with the stableswap module. Roles associated with this trait include:
Default implementations (impl
blocks): Provide default behavior for certain structs and traits. Roles associated with these blocks include:
The roles represented in the provided Rust code are primarily related to managing and interacting with a stableswap pool, which is a type of automated market maker (AMM) commonly used in decentralized finance (DeFi) platforms. Here's a breakdown of the roles associated with the functions in the code:
Liquidity Providers (LPs):
calculate_shares
and calculate_shares_for_amount
functions calculate the amount of shares to be given to LPs based on the assets they provide and the fees involved.Traders:
calculate_out_given_in
, calculate_in_given_out
, calculate_out_given_in_with_fee
, and calculate_in_given_out_with_fee
are used by traders to determine the amounts they will receive or need to send for a given trade, taking into account fees.Stableswap Pool:
calculate_d
, calculate_ann
, calculate_amplification
, normalize_reserves
, and normalize_value
are involved in managing the stableswap pool's internal state and performing calculations related to trading and liquidity provision.Governance:
calculate_amplification
function calculates the current amplification value based on specified parameters and the current block number, which could be set by governance.Developers:
Overall, these roles work together to ensure the efficient operation of the stableswap pool, providing liquidity to traders while incentivizing LPs with fees and share ownership in the pool. 2. types.rs:
The roles represented in the provided Rust code are related to managing asset reserves within a system. Here's an overview:
Asset Reserves Manager:
AssetReserve
struct represents each asset reserve, containing information about the reserve amount and the number of decimals.Asset Reserves Users:
AssetReserve
struct provides methods like new
and is_zero
for users to create new asset reserves and check if a reserve is empty.Integration Developers:
AssetReserve
struct.Overall, the AssetReserve
struct and associated functionality serve to manage asset reserves efficiently within a system, providing a foundational component for various financial operations and calculations.
lib.rs:
types.rs:
math.rs:
EMA Calculation Functions:
iterated_price_ema
, iterated_balance_ema
, iterated_volume_ema
, and iterated_liquidity_ema
calculate EMAs based on previous values, incoming values, and smoothing factors.Weighted Average Calculation Functions:
price_weighted_average
, balance_weighted_average
, volume_weighted_average
, and liquidity_weighted_average
compute weighted averages for prices, balances, volumes, and liquidity.Utility Functions:
saturating_sub
, multiply
, round
, round_to_rational
, rounding_add
, and rounding_sub
are utility functions used in precision handling, arithmetic operations, and rounding during EMA calculations.Constants and Types:
EmaPrice
, EmaVolume
, and EmaLiquidity
are provided.Fraction::ONE
and Fraction::ZERO
are used in calculations.lib.rs:
Technical Origin: This role has permission to change the trade volume limit of an asset. It is specified in the Config
trait as type TechnicalOrigin: EnsureOrigin<Self::RuntimeOrigin>;
. Functions that require this role include:
set_trade_volume_limit
Whitelisted Accounts: These accounts bypass checks for adding/removing liquidity. The root account is always whitelisted. Functions that check for whitelisted accounts include:
ensure_add_liquidity_limit
ensure_remove_liquidity_limit
Omnipool
Notation
Variable | Description |
---|---|
$R_i$ | Omnipool reserves of asset $i$ |
$Q_i$ | LRNA in subpool for asset $i$ |
$S_i$ | Shares in asset $i$ subpool |
$\omega_i$ | Weight cap for asset $i$ in Omnipool |
For a given state variable $X$, we will generally denote the value of $X$ after the operation by $X^+$.
Function-level Invariants
Swap
For all assets $i$ in Omnipool, the invariant $R_i Q_i$ should not decrease due to a swap. This means that after a swap for all assets $i$ in Omnipool:
Add liquidity
Add liquidity should respect price $\frac{Q_i}{R_i}$. This means $\frac{Q_i}{R_i} = \frac{Q_i^+}{R_i^+}$, or $Q_i R_i^+ = Q_i^+ R_i$. What is most important here is not which direction we round but the accuracy. So we must test that
Withdraw liquidity
Withdraw liquidity should respect price $\frac{Q_i}{R_i}$. This means $\frac{Q_i}{R_i} = \frac{Q_i^+}{R_i^+}$, or $Q_i R_i^+ = Q_i^+ R_i$. Allowing for rounding error, we must check
Stableswap
Variable | Description |
---|---|
$R_i$ | Stableswap reserve of asset $i$ |
$S$ | Shares in stableswap pool |
$D$ | Stableswap invariant |
For a given state variable $X$, we will generally denote the value of $X$ after the operation by $X^+$.
Operation-specific
Swap
After a swap, we should have
Add Liquidity (arbitrary assets)
After adding liquidity, we should have
Withdraw Liquidity (one asset)
After removing liquidity, we should have
Variable | Description |
---|---|
$Q$ | Total LRNA in Omnipool |
$Q_i$ | LRNA in subpool for asset $i$ |
$S_i$ | Shares in asset $i$ subpool |
$B_i$ | Protocol shares in asset $i$ |
$s_i^\alpha$ | Shares in asset $i$ held by LP $\alpha$ |
For a given state variable $X$, we will generally denote the value of $X$ after the operation by $X^+$.
Accordingly, I analyzed and audited the subject in the following steps;
Core Protocol Contract Overview:
I focused on thoroughly understanding the codebase and providing recommendations to improve its functionality.
The main goal was to take a close look at the important contracts and how they work together in the HydraDX
.
I start with the following contracts, which play crucial roles in the HydraDX
:
Main Contracts I Looked At
I start with the following contracts, which play crucial roles in the HydraDX:
omnipool/src/lib.rs omnipool/src/types.rs omnipool/src/traits.rs src/omnipool/math.rs src/omnipool/types.rs stableswap/src/lib.rs stableswap/src/types.rs src/stableswap/math.rs src/stableswap/types.rs ema-oracle/src/lib.rs ema-oracle/src/types.rs src/ema/math.rs circuit-breaker/src/lib.rs
I started my analysis by examining the intricate structure and functionalities of the hydrax protocol, particularly focusing on its various modules such as Omnipool, Omnipool Math, and Stableswap. These modules offer a comprehensive suite of features for managing liquidity, trading assets, and maintaining stablecoin pools within the ecosystem.In Omnipool, the protocol enables decentralized trading through an Automated Market Maker (AMM) model, facilitating asset swaps without intermediaries. Key functions such as asset management, position management, and trade processing are provided to ensure efficient operation of the liquidity pool. Additionally, the protocol defines types and traits to facilitate the management and interaction with the Omnipool. The Omnipool Math module offers essential mathematical functions for calculating changes in asset states during various liquidity-related operations. Functions for selling, buying, adding liquidity, removing liquidity, as well as calculating total value locked (TVL) and cap differences, are meticulously implemented to ensure accurate state transitions within the pool.On the other hand, the Stableswap module introduces a Curve-style stablecoin AMM, allowing the creation and management of liquidity pools for stablecoins. With features like pool creation, liquidity addition, removal, and trading, the Stableswap module provides a robust framework for maintaining stablecoin liquidity pools with adjustable parameters such as amplification and trade fees.
Documentation Review:
Then went to Review this docs for a more detailed and technical explanation of the HydraDX project.
Compiling code and running provided tests:
Manuel Code Review In this phase, I initially conducted a line-by-line analysis, following that, I engaged in a comparison mode.
Line by Line Analysis: Pay close attention to the contract's intended functionality and compare it with its actual behavior on a line-by-line basis.
Comparison Mode: Compare the implementation of each function with established standards or existing implementations, focusing on the function names to identify any deviations.
Overall, I consider the quality of the HydraDX protocol codebase to be Good. The code appears to be mature and well-developed. We have noticed the implementation of various standards adhere to appropriately. Details are explained below:
Codebase Quality Categories | Comments |
---|---|
Architecture & Design | The protocol features a modular design, segregating functionality into distinct contracts (e.g., Omnipool, Stableswap, Oracle) for clarity and ease of maintenance. The use of libraries like Stableswap Math for mathematical operations also indicates thoughtful design choices aimed at optimizing contract performance and gas efficiency. |
Upgradeability & Flexibility | The project does not explicitly implement upgradeability patterns (e.g., proxy contracts), which might impact long-term maintainability. Considering an upgrade path or versioning strategy could enhance the project's flexibility in addressing future requirements.. |
Community Governance & Participation | The protocol incorporates mechanisms for community governance, enabling token holders to influence decisions. This fosters a decentralized and participatory ecosystem, aligning with the broader ethos of blockchain development. |
Error Handling & Input Validation | Functions check for conditions and validate inputs to prevent invalid operations, though the depth of validation (e.g., for edge cases transactions) would benefit from closer examination. |
Code Maintainability and Reliability | The provided contracts are well-structured, exhibiting a solid foundation for maintainability and reliability. Each contract serves a specific purpose within the ecosystem, following established patterns and standards. This adherence to best practices and standards ensures that the code is not only secure but also future-proof. The usage of contracts for implementing token and security features like access control further underscores the commitment to code quality and reliability. However, the centralized control present in the form of admin and owner privileges could pose risks to decentralization and trust in the long term. Implementing decentralized governance or considering upgradeability through proxy contracts could mitigate these risks and enhance overall reliability. |
Code Comments | The contracts are accompanied by comprehensive comments, facilitating an understanding of the functional logic and critical operations within the code. Functions are described purposefully, and complex sections are elucidated with comments to guide readers through the logic. Despite this, certain areas, particularly those involving intricate mechanics or tokenomics, could benefit from even more detailed commentary to ensure clarity and ease of understanding for developers new to the project or those auditing the code. |
Testing | The contracts exhibit a commendable level of test coverage, approaching nearly 100%, which is indicative of a robust testing regime. This coverage ensures that a wide array of functionalities and edge cases are tested, contributing to the reliability and security of the code. However, to further enhance the testing framework, the incorporation of fuzz testing and invariant testing is recommended. These testing methodologies can uncover deeper, systemic issues by simulating extreme conditions and verifying the invariants of the contract logic, thereby fortifying the codebase against unforeseen vulnerabilities. |
Code Structure and Formatting | The codebase benefits from a consistent structure and formatting, adhering to the stylistic conventions and best practices of Solidity programming. Logical grouping of functions and adherence to naming conventions contribute significantly to the readability and navigability of the code. While the current structure supports clarity, further modularization and separation of concerns could be achieved by breaking down complex contracts into smaller, more focused components. This approach would not only simplify individual contract logic but also facilitate easier updates and maintenance. |
Strengths | Among the notable strengths of the codebase are its adherence to innovative integration of blockchain technology with dex's and stableswaps. The utilization of stableswap libraries for security and standard compliance emphasizes a commitment to code safety and interoperability. The creative use of circuit-breaker/src/lib.rs and src/ema/math.rs in the Dex's mechanics demonstrates. |
Documentation | The contracts themselves contain comments and some descriptions of functionality, which aids in understanding the immediate logic. It was learned that the project also provides external documentation. However, it has been mentioned that this documentation is somewhat outdated. For a project of this complexity and scope, keeping the documentation up-to-date is crucial for developer onboarding, security audits, and community engagement. Addressing the discrepancies between the current codebase and the documentation will be essential for ensuring that all stakeholders have a clear and accurate understanding of the system's architecture and functionalities. |
Omnipool
Asset Management:
Position Management:
Trade Execution:
Stableswap
Pool Creation:
Liquidity Management:
Trading:
EMA Oracle
Price Tracking:
Exponential Moving Average (EMA):
Circuit Breaker
Trade Volume and Liquidity Limits:
Limit Enforcement:
Overall Workflow
The HydraDX protocol combines these components to provide a comprehensive and flexible trading platform for digital assets. Users can trade assets, provide liquidity, and access accurate price information through the EMA oracle. The circuit breaker mechanism helps ensure the stability and liquidity of the markets, while the Omnipool and Stableswap modules provide efficient and scalable trading mechanisms for both volatile and stable assets.
File Name | Core Functionality | Technical Characteristics | Importance and Management |
---|---|---|---|
omnipool/src/lib.rs | The core functionality of this contract is to provide a decentralized exchange (DEX) using an Automated Market Maker (AMM) model, allowing users to trade assets without intermediaries by pooling liquidity and utilizing on-chain math functions for state calculations. | Technical characteristics include asset management functionalities, position management represented as NFTs, and trade execution with parameters like price barriers and dynamic fees, all implemented through precise updates to pool reserves and asset imbalances using hooks and events. | Importance and management in this contract involve enabling non-custodial trading with low fees, thereby promoting greater decentralization and accessibility compared to order-book based alternatives like HydraDX. |
omnipool/src/types.rs | The core functionality of this contract is to define types and structures essential for managing an Omnipool, including representations of asset balances, prices, tradability, positions, imbalances, and asset reserve states. | Technical characteristics encompass features like using bitflags for asset tradability, providing types for representing imbalances and asset reserve states, and offering functions for converting between different representations of assets and positions. | Importance and management in this contract involve facilitating precise tracking and management of asset states and positions within the Omnipool, thereby enabling efficient liquidity provision and trading operations while ensuring consistency and accuracy in state transitions. |
omnipool/src/traits.rs | The core functionality of this contract is to define traits, structs, and implementations facilitating the management of an Omnipool, including hooks for liquidity changes and trades, external price fetching, and enforcing price constraints. | Technical characteristics include the definition of traits such as OmnipoolHooks, ExternalPriceProvider, and ShouldAllow, along with types like AssetInfo and EnsurePriceWithin, which collectively enable extensibility, external integration, and validation mechanisms within the Omnipool ecosystem. | Importance and management in this contract involve providing a flexible framework for customizing Omnipool behavior, integrating external price data, and enforcing price constraints, thus ensuring the integrity and efficiency of liquidity management and trading operations within the ecosystem. |
src/omnipool/math.rs | The core functionality of this contract is to implement mathematical functions for calculating delta changes in the state of an asset pool during liquidity-related operations like selling, buying, adding liquidity, removing liquidity, and determining metrics such as total value locked (TVL) and cap differences. | Technical characteristics include the provision of precise mathematical calculations for various liquidity operations, including selling, buying, adding, and removing liquidity, along with functionalities for determining TVL and cap differences, ensuring accuracy and efficiency in managing asset pools. | Importance and management in this contract involve enabling accurate and efficient management of liquidity operations within the asset pool, facilitating informed decision-making regarding TVL and cap differences, thereby enhancing the stability and functionality of the liquidity system. |
src/omnipool/types.rs | The core functionality of this contract involves defining structures and implementations for managing asset reserves, liquidity pools, and trading mechanisms, facilitating operations such as updating asset states, calculating prices, and handling balance adjustments. | Technical characteristics include the provision of structured data types and functions to efficiently represent and manipulate asset states, balance updates, trade fees, and liquidity changes within the Omnipool, ensuring accuracy and reliability in managing liquidity operations. | Importance and management in this contract entail enabling precise tracking and management of asset reserves, liquidity states, and trading activities, thereby enhancing the stability, efficiency, and functionality of the Omnipool ecosystem. |
stableswap/src/lib.rs | The core functionality of this contract is to enable the creation and management of Curve-style stablecoin automated market maker (AMM) pools with up to 5 assets, featuring a pricing formula based on amplification and facilitating liquidity provision, removal, and asset trading. | Technical characteristics include the implementation of a stableswap pallet within the HydraDX runtime, utilizing a constant product formula for price calculation and providing roles such as AuthorityOrigin, LiquidityProviderOrigin, and TraderOrigin for managing pool creation, liquidity addition/removal, and trading operations. | Importance and management in this contract involve facilitating stablecoin trading with minimized volatility, enabling efficient liquidity provision and removal, and ensuring fair and transparent trading mechanisms, ultimately enhancing the stability and usability of the ecosystem for everyday transactions. |
stableswap/src/types.rs | The core functionality of this contract is to define data structures and traits for managing stable pools, including pool properties, asset amounts, tradability flags, and interfaces for oracle interaction and weight calculation. | Technical characteristics include the representation of pool information through the PoolInfo struct, asset amounts with the AssetAmount struct, tradability flags with the Tradability bitmask, and pool state tracking with the PoolState struct, alongside the StableswapHooks trait for oracle interaction and weight calculation. | Importance and management in this contract revolve around enabling the creation and management of stable pools, ensuring efficient tracking of pool state and asset tradability, and providing extensible interfaces for oracle integration and weight calculation to support stable trading operations effectively. |
src/stableswap/math.rs | The core functionality of this contract involves implementing mathematical functions for a stableswap pool, facilitating automated market making with multiple assets, including liquidity provision, asset trading with fees, and share distribution to liquidity providers, ensuring stable trading ratios between assets. | Technical characteristics include formulas for calculating the D invariant and reserve values (Y), alongside functions for handling share minting, precision normalization, and trade execution using mathematical operations and iterative algorithms. | Importance and management in this contract revolve around maintaining accurate and stable trading within the automated market making system, enabling efficient liquidity provision, asset trading, and fair share distribution among liquidity providers, crucial for the effective operation of the stableswap pool. |
src/stableswap/types.rs | The core functionality of this contract involves implementing the StableSwap algorithm for calculating token amounts in liquidity pools, maintaining constant reserve ratios, and facilitating token swaps. | Technical characteristics include mathematical functions like calculate_out_given_in, calculate_in_given_out, calculate_shares, and others, ensuring accurate calculation of token amounts, shares, and reserves in liquidity pools. | Importance and management in this contract lie in providing efficient and stable token swaps within liquidity pools, crucial for decentralized exchanges and other DeFi applications, enabling effective liquidity provision, trading, and asset management. |
ema-oracle/src/lib.rs | The core functionality of this contract involves implementing an Exponential Moving Average (EMA) oracle for tracking asset price, volume, and liquidity over time in the HydraDX protocol. | Technical characteristics include functions such as on_trade and on_liquidity_changed for updating the oracle with trade and liquidity data, as well as methods like get_entry and get_price for retrieving EMA values and asset prices. | Importance and management in this contract revolve around providing accurate and up-to-date data on asset metrics, crucial for efficient price discovery, liquidity provision, and trading strategies within the HydraDX protocol, managed by the oracle's functionalities. |
ema-oracle/src/types.rs | The core functionality of this contract involves managing Exponential Moving Average (EMA) oracles for each asset pair and period in the HydraDX protocol, updating them with trade and liquidity changes. | Technical characteristics include OracleEntry struct for storing oracle data, and functions like calculate_new_by_integrating_incoming and update_to_new_by_integrating_incoming for calculating and updating oracle entries. | Importance and management lie in providing accurate EMA data for asset pairs and periods, crucial for price tracking, liquidity monitoring, and informed decision-making within the HydraDX protocol, managed through oracle updates and calculations. |
src/ema/math.rs | The core functionality of this contract lies in providing functions for calculating exponential moving averages (EMAs) and performing weighted averages for oracle values in the HydraDX protocol. | Technical characteristics include the calculation of EMAs and weighted averages using specified smoothing factors, as well as functions for updating outdated values and determining smoothing factors based on periods. | Importance and management revolve around accurately tracking oracle values, particularly prices, balances, volumes, and liquidity, which are crucial for informed decision-making within the HydraDX protocol, managed through the calculation and updating of EMAs and weighted averages. |
circuit-breaker/src/lib.rs | The core functionality of this contract lies in managing circuit breakers for trade volume and liquidity limits in the HydraDX protocol. | Technical characteristics include the definition of a Config trait specifying runtime requirements and the implementation of functions to initialize and enforce trade and liquidity limits, as well as account whitelisting. | Importance and management revolve around maintaining the stability and security of the HydraDX protocol by preventing excessive trading and liquidity operations through circuit breakers, which are configurable and enforceable via the pallet's functions and methods. |
Here's an analysis of potential systemic, centralization, Technical and Integration risks in the contracts:
lib.rs:
types.rs
Systemic Risks:
Centralization Risks:
Technical Risks:
Integration Risks:
traits.rs
Systemic Risks:
Centralization Risks:
Technical Risks:
Integration Risks:
math.rs:
Systemic Risks:
Centralization Risks:
Technical Risks:
Integration Risks:
types.rs:
Systemic Risks:
BalanceUpdate
) if the balances exceed their maximum representable value. This can lead to unexpected behavior or loss of funds if not handled properly.Centralization Risks:
protocol_shares
in AssetReserveState
indicates a degree of control exerted by the protocol over the LP shares for an asset. Depending on how these shares are managed and utilized, there could be centralization risks if the protocol wields disproportionate power.Technical Risks:
CheckedAdd
, CheckedSub
) in the implementation of balance updates (BalanceUpdate
) introduces technical risks. While these operations aim to prevent arithmetic overflow or underflow, there is still a risk of unexpected behavior if the checks fail or if the checks are not comprehensive.Integration Risks:
lib.rs:
Systemic Risks:
MAX_ASSETS_IN_POOL
). Exceeding this limit could potentially cause systemic issues or unexpected behavior in the pool management logic.Centralization Risks:
create_pool
function requires an origin that must be T::AuthorityOrigin
, indicating a centralized authority responsible for creating pools. This centralization could lead to dependency risks if the authority is compromised or misuses its power.Technical Risks:
AmplificationRange
), and the update_amplification
function allows modifying the pool's amplification within this range. However, incorrect manipulation of amplification could introduce technical risks such as impermanent loss or instability in the pool's behavior.Integration Risks:
T::AssetInspection
) to check if assets are correctly registered and retrieve asset decimals. Integration with this external registry introduces the risk of data inconsistency or reliance on external systems, which could impact the contract's functionality if the registry is unavailable or inaccurate.types.rs:
Systemic Risks:
MAX_ASSETS_IN_POOL
). Exceeding this limit could lead to systemic issues or unexpected behavior in the pool management logic.Centralization Risks:
Technical Risks:
has_unique_elements
to check for unique elements in a collection of assets. However, this function relies on the correct implementation of iterators and could introduce technical risks if not implemented correctly, potentially leading to incorrect pool configurations or unexpected behavior.Integration Risks:
Pallet::<T>::retrieve_decimals
) to retrieve asset decimals. Integration with this external registry introduces the risk of data inconsistency or reliance on external systems, which could impact the contract's functionality if the registry is unavailable or inaccurate.math.rs:
Systemic Risks:
D
and Y
) is insufficient. This lack of convergence can lead to incorrect calculations and potential loss of funds.Centralization Risks:
calculate_amplification
function adjusts the amplification parameter based on block numbers. Depending on how this adjustment is governed, it could introduce centralization risks if controlled by a small number of entities or subject to manipulation.Technical Risks:
MAX_Y_ITERATIONS
and MAX_D_ITERATIONS
). If these limits are set too low, it may lead to premature termination of calculations, potentially resulting in inaccurate results or failed transactions.checked_add
, checked_sub
, etc.) aimed at preventing overflow or underflow. However, if these checks are inadequate or incorrectly implemented, they could introduce vulnerabilities to arithmetic errors.calculate_out_given_in
, calculate_in_given_out
, etc. Insufficient input validation could lead to unexpected behavior or vulnerabilities such as denial-of-service attacks or manipulation of calculations.Integration Risks:
num_traits
, primitive_types
, sp_arithmetic
, sp_std
, etc.). Any vulnerabilities or changes in these dependencies could impact the security and functionality of the contract.types.rs:
Systemic Risks:
is_zero
function to check if the reserve amount is zero, there are no measures in place to prevent or handle data loss or corruption. If reserve amounts are inadvertently set to zero or corrupted, it could lead to unexpected behavior or loss of funds.Centralization Risks:
Technical Risks:
From
) to convert AssetReserve
instances into u128
values. However, there are no checks or safeguards to ensure the validity of these conversions, potentially leading to unexpected behavior or errors if used improperly.is_zero
function checks if the reserve amount is zero, there are no explicit error-handling mechanisms if zero balance assets are encountered in calculations. This lack of error handling could lead to unexpected behavior or vulnerabilities in downstream processes or calculations.Integration Risks:
num_traits
. Any vulnerabilities or changes in these dependencies could impact the security and functionality of the contract.lib.rs:
Systemic Risks:
Centralization Risks:
Technical Risks:
frame_support
and sp_runtime
. Any vulnerabilities or changes in these dependencies could impact the security and functionality of the pallet.Integration Risks:
types.rs:
Systemic Risks:
hydra_dx_math
and hydradx_traits
for mathematical operations and trait implementations. Any failure or vulnerability in these dependencies could impact the contract's functionality.Centralization Risks:
hydra_dx_math
and hydradx_traits
) could create a centralization risk if these libraries are controlled by a single entity or if there are limited alternatives available.Technical Risks:
Price
, Volume
, Liquidity
) that may require careful handling to ensure type safety and prevent overflow or underflow vulnerabilities.Integration Risks:
math.rs: Here's an analysis of the provided contract for systemic risks, centralization risks, technical risks, and integration risks:
Systemic Risks:
EmaPrice
, EmaVolume
, EmaLiquidity
) with limited precision. Precision loss during calculations could lead to inaccuracies in the oracle values, especially over multiple iterations or when dealing with large numbers.iterated_price_ema
and iterated_balance_ema
, rely on the number of iterations (u32
) to calculate exponential moving averages. Dependency on iteration count introduces risks if iterations are miscounted or inconsistent, leading to incorrect results.Centralization Risks:
crate::fraction
, crate::support
, crate::transcendental
) for arithmetic operations and utility functions. Centralization risks arise if these libraries are controlled by a single entity or if there are limited alternatives available.Integration Risks:
U512
) and may be susceptible to arithmetic overflow or underflow vulnerabilities if not handled properly. Saturating operations are used to mitigate this risk, but thorough testing is required to ensure correctness.Integration Risks:
lib.rs:
Systemic Risks:
T::Balance
). Errors like overflow, underflow, and division by zero can lead to systemic risks if not handled properly, potentially disrupting the functioning of the entire system.Centralization Risks:
type WhitelistedAccounts
bypass checks for adding/removing liquidity. Centralizing control over these accounts poses centralization risks as they can influence liquidity operations without standard checks, potentially favoring specific entities and impacting the fairness of the system.Integration Risks:
TechnicalOrigin
to ensure the origin of certain calls. Technical permissions are crucial for maintaining the integrity of the system, but incorrect or insufficient origin checks can lead to technical risks such as unauthorized access or manipulation of critical parameters.Integration Risks:
Integration of Stableswap and Omnipool:
Dynamic Fee Adjustment Mechanism:
Advanced Risk Management Strategies:
Enhanced Oracle Integration:
Security Audits and Formal Verification:
withdraw_asset_amount
(buy / add liquidity), missing in Curve implementationadd_liquidity_shares
(buy / add liquidity), missing in Curve implementation90 hours
#0 - c4-pre-sort
2024-03-03T18:14:07Z
0xRobocop marked the issue as sufficient quality report
#1 - c4-judge
2024-03-08T19:02:00Z
OpenCoreCH marked the issue as grade-a
#2 - c4-judge
2024-03-08T19:19:45Z
OpenCoreCH marked the issue as selected for report
#3 - Frankcastleauditor
2024-03-15T00:01:51Z
Hi @OpenCoreCH
I think that this report has a lot of generics about any protocol of the same type .
such as
Asset Price Calculation: Incorrect calculation of asset prices may lead to systemic risks, affecting the accuracy of trade executions and liquidity provision within the system.
which is applied to all the protocols in the ecosystem , there a lot of examples of this is the report such as
Inaccurate calculation of withdrawal fees based on spot prices and oracle prices may introduce systemic risks, impacting the fairness and efficiency of liquidity withdrawals. Centralization risks arise from the calculation of imbalances in liquidity provision, as discrepancies in determining the appropriate imbalance may impact the stability and fairness of the system.
and some of the risks are not true such as this , so the balance BalanceUpdate uses checked math of the arithmetic operation
Unchecked Arithmetic Operations: The use of unchecked arithmetic operations (CheckedAdd, CheckedSub) in the implementation of balance updates (BalanceUpdate) introduces technical risks. While these operations aim to prevent arithmetic overflow or underflow, there is still a risk of unexpected behavior if the checks fail or if the checks are not comprehensive.
the function add
which is applied for the type BalanceUpdate
uses the checkedAdd function as shown here , so this recommendation is invalid .
impl<Balance: Into<<FixedU128 as FixedPointNumber>::Inner> + CheckedAdd + CheckedSub + Copy + Default> Add<Balance> for BalanceUpdate<Balance> { type Output = Option<Balance>; fn add(self, rhs: Balance) -> Self::Output { match &self { BalanceUpdate::Increase(amount) => rhs.checked_add(amount), BalanceUpdate::Decrease(amount) => rhs.checked_sub(amount), } } }
the report has also this generic in the technical risks
Numerical Precision: The contract involves numerous calculations with fixed-point arithmetic and conversions between different numeric representations. Any miscalculations or inaccuracies in these operations could result in incorrect financial outcomes or vulnerabilities to attacks.
I need also to mention that the warden only submit an analysis without finding any high , medium , or QA issues , which indicates that the risks mentioned in the report are just generics which can be applied on all the protocol of this type .
I am asking to reconsider the validation of this report and choosing it to be selected for the final report .
#4 - albahaca0000
2024-03-15T01:50:11Z
Hi everyone, I often read analyses of protocols and quickly learn a lot about the protocol. Although I'm not participating in this contest, I found this analysis to be the best in explaining everything clearly compared to others, understand a lot about the HydraDX protocol.
#5 - OpenCoreCH
2024-03-15T09:58:46Z
While the report contains some generic recommendations and errors (like most other reports), there are various good recommendations (many of which have been reported as separate issues), for instance checking the convergence of Newton's method, centralization issues because of the amplification parameter changes, valid improvement suggestions, and good attack ideas.