Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Large users can potentially prevent other smaller users to conduct omnipool trades in critical moments. #99

Open
c4-bot-3 opened this issue Feb 28, 2024 · 6 comments
Labels
bug Something isn't working downgraded by judge Judge downgraded the risk level of this issue edited-by-warden grade-a insufficient quality report This report is not of sufficient quality primary issue Highest quality submission among a set of duplicates Q-11 QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax

Comments

@c4-bot-3
Copy link
Contributor

c4-bot-3 commented Feb 28, 2024

Lines of code

https://github.com/code-423n4/2024-02-hydradx/blob/603187123a20e0cb8a7ea85c6a6d718429caad8d/HydraDX-node/pallets/circuit-breaker/src/lib.rs#L335-L354

Vulnerability details

Detailed Explanation

The protocol is imposing net trading volume limit based on percentage of current liquidity. However this limitation can cause issues during critical moments affecting small volume users. As you can see below, the function set_trade_volume_limit sets trading volume limit per asset.

The critical moments we are talking about here is during the times when users are eagerly trying to convert risky assets into more stable assets like BTC and ETH or stablecoins. When there is current set limit of 50% of an already small liquidity of risky asset pool, this can be easily filled by just one single large trade, preventing other succeeding small users to trade in critical moments, causes loss of funds to them due to quick degrading value of risky asset they want to trade.

If the large users want to intentionally DOS the trading activity of a particular asset, they can easily do it anytime specially during critical period, provided that the volume limit figure can be easily meet by them.

Although the trading volume limit is being reset per block, a large user with resources can still abuse this issue in several blocks, specially to those pools with very small liquidity.

#[pallet::call_index(0)]
		#[pallet::weight(<T as Config>::WeightInfo::set_trade_volume_limit())]
		pub fn set_trade_volume_limit(
			origin: OriginFor<T>,
			asset_id: T::AssetId,
			trade_volume_limit: (u32, u32),
		) -> DispatchResult {
			T::TechnicalOrigin::ensure_origin(origin)?;

			ensure!(asset_id != T::OmnipoolHubAsset::get(), Error::<T>::NotAllowed);

			Self::validate_limit(trade_volume_limit)?;

			<TradeVolumeLimitPerAsset<T>>::insert(asset_id, trade_volume_limit);

			Self::deposit_event(Event::TradeVolumeLimitChanged {
				asset_id,
				trade_volume_limit,
			});

			Ok(())
		}
pub struct TradeVolumeLimit<T: Config> {
	pub volume_in: T::Balance,
	pub volume_out: T::Balance,
	pub limit: T::Balance,
}

Impact

Small volume users can't trade in critical moments causing loss of funds to them.

Proof of Concept

Let's illustrate below a sample scenario wherein a large volume trader just filled in a single transaction the volume limit set by the protocol which is 200,00 units of HDX. Then, the subsequent small volume trader transaction failed in executing his transaction.

Please insert and run this test under file trade_volume.rs in circuit breaker folder.

#[test]
fn ensure_and_update_trade_volume_limit_should_fail_when_large_user_filled() {
	ExtBuilder::default().build().execute_with(|| {
		//Arrange
		assert_ok!(CircuitBreaker::initialize_trade_limit(HDX, INITIAL_LIQUIDITY));
		assert_ok!(CircuitBreaker::initialize_trade_limit(DOT, INITIAL_LIQUIDITY));
		
		assert_eq!(
			CircuitBreaker::allowed_trade_volume_limit_per_asset(HDX).unwrap(),
			TradeVolumeLimit {
				volume_in: 0,
				volume_out: 0,
				limit: 200_000,
			}
		);

		assert_ok!(CircuitBreaker::ensure_and_update_trade_volume_limit( // large user trade volume in
			HDX, 200_000, DOT, 0
		));

		assert_eq!(
			CircuitBreaker::allowed_trade_volume_limit_per_asset(HDX).unwrap(), // volume status after large user trade
			TradeVolumeLimit {
				volume_in: 200__000,
				volume_out: 0,
				limit: 200_000,
			}
		);
		
		// Act & Assert
		assert_noop!(
			CircuitBreaker::ensure_and_update_trade_volume_limit(HDX, 1_000, DOT, 0), // small user trade volume in fail
			Error::<Test>::TokenInfluxLimitReached
		);
	});
}

Tools Used

Manual Review

Recommended Mitigation Steps

Do not allow a single large user to grab the whole volume trade limit in single block transaction. Impose a trading limitation per asset per user account to avoid this abuse on small users.

Assessed type

DoS

@c4-bot-3 c4-bot-3 added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels Feb 28, 2024
c4-bot-10 added a commit that referenced this issue Feb 28, 2024
@0xRobocop
Copy link

Seems like a design decision

@c4-pre-sort c4-pre-sort added the insufficient quality report This report is not of sufficient quality label Mar 3, 2024
@c4-pre-sort
Copy link

0xRobocop marked the issue as insufficient quality report

@c4-pre-sort
Copy link

0xRobocop marked the issue as primary issue

@c4-pre-sort c4-pre-sort added the primary issue Highest quality submission among a set of duplicates label Mar 3, 2024
@OpenCoreCH
Copy link

Design decision, that's typically how circuit breakers work. Downgrading to QA

@c4-judge c4-judge added downgraded by judge Judge downgraded the risk level of this issue QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax and removed 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value labels Mar 8, 2024
@c4-judge
Copy link

c4-judge commented Mar 8, 2024

OpenCoreCH changed the severity to QA (Quality Assurance)

@c4-judge
Copy link

c4-judge commented Mar 9, 2024

OpenCoreCH marked the issue as grade-a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working downgraded by judge Judge downgraded the risk level of this issue edited-by-warden grade-a insufficient quality report This report is not of sufficient quality primary issue Highest quality submission among a set of duplicates Q-11 QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax
Projects
None yet
Development

No branches or pull requests

7 participants