Skip to content

fix(open-market): minimum liquidity lock on pool creation (#1675) - #1786

Merged
Olowodarey merged 1 commit into
Arena1X:mainfrom
udeachudivine-spec:fix/min-liquidity-lock-1675
Aug 30, 2026
Merged

fix(open-market): minimum liquidity lock on pool creation (#1675)#1786
Olowodarey merged 1 commit into
Arena1X:mainfrom
udeachudivine-spec:fix/min-liquidity-lock-1675

Conversation

@udeachudivine-spec

@udeachudivine-spec udeachudivine-spec commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Closes #1675


Fixes the first-depositor share-inflation / full-drain vulnerability in add_liquidity's bootstrap branch.

Changes:

  • Add isqrt_i128() private helper (Babylonian method, i128 flavour of the existing isqrt_u128 used for IL math)
  • Bootstrap branch now computes:
    product = per_outcome_amount.checked_mul(per_outcome_amount)
    initial_liquidity = isqrt_i128(product)
    lp_tokens_to_mint = initial_liquidity - MIN_LIQUIDITY (1_000)
    total_supply is set to initial_liquidity so MIN_LIQUIDITY is
    permanently counted but never credited to any account
  • Dust deposits where isqrt(a*b) <= MIN_LIQUIDITY are rejected with
    StakeTooLow (error enum is at its 50-case XDR cap; no new variant
    can be added — StakeTooLow is semantically the closest fit)
  • All arithmetic uses checked_mul / checked_sub / checked_add only;
    no raw operators, no unwrap/expect

Tests:

  • test_first_deposit_locks_minimum_liquidity (new)
  • test_dust_deposit_rejected (new)
  • test_full_drain_prevented (new)
  • Updated 8 existing tests whose assertions assumed the old 1:1
    bootstrap behaviour; logic is correct, only expected values changed

Fixes the first-depositor share-inflation / full-drain vulnerability
in add_liquidity's bootstrap branch.

Changes:
- Add isqrt_i128() private helper (Babylonian method, i128 flavour of
  the existing isqrt_u128 used for IL math)
- Bootstrap branch now computes:
    product          = per_outcome_amount.checked_mul(per_outcome_amount)
    initial_liquidity = isqrt_i128(product)
    lp_tokens_to_mint = initial_liquidity - MIN_LIQUIDITY  (1_000)
  total_supply is set to initial_liquidity so MIN_LIQUIDITY is
  permanently counted but never credited to any account
- Dust deposits where isqrt(a*b) <= MIN_LIQUIDITY are rejected with
  StakeTooLow (error enum is at its 50-case XDR cap; no new variant
  can be added — StakeTooLow is semantically the closest fit)
- All arithmetic uses checked_mul / checked_sub / checked_add only;
  no raw operators, no unwrap/expect

Tests:
- test_first_deposit_locks_minimum_liquidity  (new)
- test_dust_deposit_rejected                  (new)
- test_full_drain_prevented                   (new)
- Updated 8 existing tests whose assertions assumed the old 1:1
  bootstrap behaviour; logic is correct, only expected values changed
@vercel

vercel Bot commented Aug 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
insight-arena-4rll Ready Ready Preview Aug 30, 2026 12:42pm

@drips-wave

drips-wave Bot commented Aug 30, 2026

Copy link
Copy Markdown

@udeachudivine-spec Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@udeachudivine-spec

Copy link
Copy Markdown
Contributor Author

close issue #1675

@Olowodarey
Olowodarey merged commit fe6c165 into Arena1X:main Aug 30, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Contracts] — open-market: Minimum Liquidity Lock on Pool Creation

2 participants