No reviewers
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic!1002
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "qa/464-465-amm-256bit-widening"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes the two AMM launch-blockers from the security sweep. Same root cause (native-width reserve arithmetic), same file, so patched together.
#464 — constant-product overflow
Every reserve product in the pair ran in native
Uint128with no 256-bit widening, soreserve_a * reserve_boverflows at ~1.85e19 raw per side (~18 whole tokens for an 18-dec asset), reverting swaps and quotes. Widened all the product sites toUint256, narrowing results back toUint128(they're always bounded by a reserve/supply):k+ k-invariant recheck (contract.rs), and the swap simulationisqrtnow overUint256) + subsequent mint + slippageexpected_lpspot_linear_spread_over_grossscale_hybrid_templatebook splithybrid_reverse.rspool-net + reverse-seed productsBehaviour is identical for every existing (small-reserve) case — 256-bit is a superset, same division/rounding, same
ceil_divguarantee.#465 — oracle panic → brick + fund lock
oracle_updateused the panickingDecimal::from_ratio; an extreme reserve ratio (reserve_b/reserve_a > Decimal::MAX) panicked, and sinceoracle_updateruns on the swap AND withdraw paths that permanently bricked the pair and locked LP funds. Switched toDecimal::checked_from_ratioand skip the observation on overflow (graceful degrade, no state committed) instead of aborting.Tests
pool_net_output_survives_18dec_scale_reserves— pool math at 2e19/side reserves (pre-fix overflowed here).oracle_overflow_tests::extreme_ratio_degrades_gracefully_instead_of_panicking+normal_ratio_still_records_observation.Note: an end-to-end 18-dec pool integration test (custom whitelisted large-token pair) is a good follow-up; the pool-math regression + the fully-green existing suite (which exercises swap/mint/withdraw/hybrid/oracle on the widened math) cover the core here.
@PlasticDigits — these are the two launch-blockers, ready for review.
mentioned in issue #464
mentioned in issue #465
Security review — MR !1002
Commit reviewed:
4811caf939f0661a6574f32b2431fa6ab8e45164Base:
21381a0e19412a96c6e34487f657e62e7d2b8e85Scope
smartcontracts/contracts/pair/src/contract.rs— Uint256 widening for constant-product reserve math (isqrt_u256,ceil_div_u256,narrow_u128);oracle_updateswitched toDecimal::checked_from_ratiowith graceful skip (#465)smartcontracts/contracts/pair/src/hybrid_reverse.rs— matching 256-bit reserve math for reverse-quote seedingMethod
Traced attacker-controlled inputs (swap amounts, liquidity deposits/withdrawals, reserve imbalance) through widened product/division sites and the oracle update path. Checked whether
narrow_u128can mint or pay out beyondUint128bounds, whether rounding diverges from pre-fix semantics, and whether oracle skip re-opens the #465 fund-lock class.Outcome: FINDINGS: 0 (no medium+)
Uint256 widening (#464): All narrowed outputs are bounded by an existing
Uint128reserve, LP supply, or withdraw pro-rata share.ceil_div_u256preserves the same pool-favourable rounding as the removedceil_div;k-invariant checks are unchanged in intent. Widening also correctly allows provide-liquidity paths whose intermediateamount × supplyproduct exceedsu128but whose floored LP result still fits — a false rejection fix, not a mint inflation vector.Oracle (#465): Replacing the panicking
Decimal::from_ratioon the swap/withdraw/provide execute path withchecked_from_ratio+ skip removes the launch-blocker fund-lock. Skipped observations do not commit oracle state; swaps and withdrawals proceed. The remainingDecimal::from_ratioinoracle_observe_singleis query-only (Observe) — a failed query does not mutate state or block execute; out of scope for the execute-path brick this MR targets. A secondaryprice_times_dtoverflow returningContractError::Oracleon very high (but sub-Decimal::MAX) ratios with multi-seconddtis pre-existing behaviour (pre-fix code reachedprice_times_dtafter successfulfrom_ratio); this MR does not widen that failure mode and actually un-bricks the above-Decimal::MAXregime via skip.Inline threads: none (no medium+ findings).
Automated security review — no
block:securitylabel applied.mentioned in commit
fcdcbd87f2