Open c4-bot-2 opened 8 months ago
0xRobocop marked the issue as insufficient quality report
Is not clear how the attacker will profit by donating tokens to the pool.
0xRobocop marked the issue as primary issue
@enthusiastmartin This was not shown to you in the sponsor review and I would like to hear your opinion here. Do you consider this to be an issue or is it fine that HDX can be transferred to the protocol account?
@enthusiastmartin This was not shown to you in the sponsor review and I would like to hear your opinion here. Do you consider this to be an issue or is it fine that HDX can be transferred to the protocol account?
Although there is no obvious problem when HDX is donated to omnipool, we have all transfers to omnipool account explicitly filtered. So adding this too makes sense, but i disagree with severity. It might be considered low/QA
Downgrading to QA because the demonstrated impact here is very small: An attacker would have to actively spend funds to (temporarily) manipulate the withdrawal fee or the price difference checks. While it is possible that the manipulation of these parts have other implications, this was not demonstrated here.
OpenCoreCH changed the severity to QA (Quality Assurance)
OpenCoreCH marked the issue as grade-a
Lines of code
https://github.com/code-423n4/2024-02-hydradx/blob/603187123a20e0cb8a7ea85c6a6d718429caad8d/HydraDX-node/pallets/omnipool/src/lib.rs#L597-L603 https://github.com/code-423n4/2024-02-hydradx/blob/603187123a20e0cb8a7ea85c6a6d718429caad8d/HydraDX-node/pallets/omnipool/src/lib.rs#L746-L752 https://github.com/code-423n4/2024-02-hydradx/blob/603187123a20e0cb8a7ea85c6a6d718429caad8d/HydraDX-node/pallets/omnipool/src/lib.rs#L759-L764
Vulnerability details
Impact
A medium risk finding
[A1] Oracle is not updated by directly sending assets to an Omnipool
in the previous EMA Oracle audit still exists in the HDX sub-pool, the previous audit outlines the impact of this vulnerability to the EMA Oracle including misleading exchange rate and influence to the honest user's operation, which still apply to the current implementation of the Omnipool.Moreover, in the
add_liquidity
andremove_liquidity
there is a check to ensure the price difference between the spot price and the oracle price can't be greater than 1% otherwise theadd_liquidity/remove_liquidity
will fail. The oracle price is hard to manipulate but the attacker can directly send HDX to the protocol account to manipulate the spot price of HDX thus manipulating the price difference and further the result of the check.When the check is supposed to pass, by manipulating the spot price of HDX to make the check fail, the attacker can prevent any liquidity change in the HDX sub-pool. The LPs of the HDX sub-pool are incentivized to launch such an attack because by preventing other LPs join the HDX sub-pool, they can earn more fees proportionate to the volume of the HDX sub-pool without worrying about other LPs joining and splitting the fee.
When the check is supposed to fail, by manipulating the spot price of HDX to make the check pass, the attacker can break the first mitigation step of a known/mitigated critical vulnerability. Also, the withdrawal fee in the second mitigation step is determined by the price difference between the spot price and the
Short
period oracle price, so (even without flipping the check result) by manipulating the price difference the attacker can pay less withdrawal fee thus cause loss to the pool.The cost of the attack is low for a large LP of the HDX sub-pool, because he owns a large proportion of the share of the pool, and a corresponding large proportion of HDX that is directly sent to the protocol account still belongs to him.
Proof of Concept
The CallFilter is intended to fix
[A1] Oracle is not updated by directly sending assets to an Omnipool
but it doesn't filter the pallet_balances::Call::transfer_allow_death call, which can be utilized by the attacker to directly send HDX to the protocol account. This can be reproduced inpolkadot.js
by:HydraDX
and clickFork Locally
to create a local fork ofHydraDX
with Chopsticksbalances.transferAllowDeath
In the Omnipool, the spot price of an asset is a combination of the free balance of the asset that is directly queried from the protocol account and the
hub_reserve
tracking in the asset state, by sending HDX to the protocol account the spot price of HDX can be manipulated.In both the
add_liquidity
andremove_liquidity
, the spot price is used directly to perform the price difference check against the EMA Oracle [1][2], and inremove_liquidity
the price difference between the spot price and theShort
period oracle price is used to calculate the withdrawal fee.The oracle prices used in the price difference check are the
Short
period oracle price and theLastBlock
period oracle price (the check only passes if the difference with both oracle prices is within the limit), and the limit is set to 1%. TheLastBlock
period oracle price is used for the withdrawal fee calculation.Tools Used
Manual inspection
Recommended Mitigation Steps
Add the
pallet_balances::Call::transfer_allow_death
to theCallFilter
to avoid directly sending assets to the protocol account completely.Assessed type
Invalid Validation