In stableswap, Incorrect d value might be used in various trading and liquidity calculation, resulting in unfair reserve or share amount during trades #149
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
QA (Quality Assurance)
Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax
🤖_87_group
AI based duplicate group recommendation
Lines of code
https://github.com/code-423n4/2024-02-hydradx/blob/603187123a20e0cb8a7ea85c6a6d718429caad8d/HydraDX-node/pallets/omnipool/src/lib.rs#L1462-L1465
https://github.com/code-423n4/2024-02-hydradx/blob/603187123a20e0cb8a7ea85c6a6d718429caad8d/HydraDX-node/math/src/stableswap/math.rs#L560
Vulnerability details
Impact
In stableswap, Incorrect d value might be used in various trading and liquidity calculation, resulting in either pool's loss or users' loss.
Proof of Concept
Newton methods is used in converging the d-value from stableswap's invariant model, to determine the delta reserve amount in trading or liquidity management. See curve's stable swap whitepaper - page 4 for the invariant model.
The weakness of Newton method is if the initial guess is far from the actual root, or if the function has multiple roots in close proximity, it may fail to converge.
The problem is current implementation of Newton method in
calculate_d_internal()
reduces the number of iterations (compared to Curve's code) but doesn't have a safeguard against potential fail, and might allow any value to be used for delta reserve calculation.In
calculate_d_internal()
,D
is max iterations of Newton run and is 64. (pub const MAX_D_ITERATIONS: u8 = 64;
).(1) Success case: If convergence is reached (
d == d_prev
ord ==d_prev+1
),d
is a satisfied value and will be returned. This is fine.(2) failure case: If convergence is not reached within 64 iterations, no check on how close
d
value is fromhas_converged
criteria. Anyd
value will be passed and used.((https://github.com/code-423n4/2024-02-hydradx/blob/603187123a20e0cb8a7ea85c6a6d718429caad8d/HydraDX-node/math/src/stableswap/math.rs#L508))
Note: In comparison, Curve uses 255 iterations - much more than 64. A lower number of iterations means a higher risk of unsatisfied and incorrect values will be returned.
If this is the case,
calculate_d_internal()
should check thed
value after max 64 iterations to only allow acceptably closed
to be used, instead of anyd
value.In addition, same vulnerability also applies to
calculate_y_internal()
. See links to the affected code.Tools Used
Manual
Recommended Mitigation Steps
Either increase the number of iterations Or establish a wider range of allowable convergence to be checked at the end of max iterations. And revert when the returned d doesn't satisfy an acceptable wider range.
Assessed type
Math
The text was updated successfully, but these errors were encountered: