fix(positions): floor live withdrawable at 10% of open notional - #297
claude[bot] wants to merge 3 commits into
Conversation
The live position recompute deducted only the summed initial margin from equity when computing withdrawable cash. The protocol floors the margin deduction at 10% of total open notional, so the withdrawable amount was overstated whenever that floor is the binding constraint (higher-leverage positions, where summed IM is below 10% of notional). Accumulate total open notional in the perp loop and deduct max(summed IM, open_notional / 10) instead of summed IM. Withdrawable is still forced to 0 below maintenance margin. Adds unit tests covering both the floor-binding case and the IM-binding case. Co-Authored-By: Claude <noreply@anthropic.com>
Resolve add/add conflict in positions-live.test.ts: keep both the withdrawable-floor suite and the maintenanceMargin suite over one unified set of test helpers. positions-live.ts auto-merged cleanly (10% open-notional floor and the added maintenanceMargin return field are independent changes). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The Also: node rounds this term up ( |
The 10%-of-open-notional term of the withdrawable margin floor rounds up, not truncates: it is a requirement against the holder, so a fractional wei is met rather than forgiven. Truncating over-reported withdrawable by up to 1 wei, so a max-withdraw at the boundary was rejected. Use ceil division ((openNotional + 9) / 10) and cover the not-divisible-by-10 case. Co-Authored-By: Claude <noreply@anthropic.com>
|
Fixed the rounding in On the ratio being a per-network config value rather than a constant — agreed, and the SDK can't read the tuned value until it's exposed. Two ways to close that, and it's the team's call:
Left it hardcoded at the 0.1 default for now so this PR still lands as a strict improvement. Happy to do either follow-up once the team decides. Generated by Claude Code |
Summary
The live position recompute (
ts-sdk/src/sync/positions-live.ts) computes withdrawable cash by deducting a margin requirement from perp equity. The protocol floors that margin deduction at 10% of total open notional, but the recompute deducted only the summed initial margin — so the reported withdrawable amount was too high whenever the 10% floor is the binding constraint.Before
The deduction was always the summed initial margin. For higher-leverage positions, where
Σ initial_marginfalls below 10% of open notional, this understates the deduction and overstates withdrawable cash relative to the protocol.After
Total open notional (
Σ |size|·mark) is accumulated in the existing perp loop, and the deduction is floored at 10% of it, matching the protocol. Division by 10 gives 10% on the WAD-scaled integers, keeping the integer-faithful semantics of the surrounding math. When summed initial margin already exceeds 10% of notional, behavior is unchanged.Tests
Added
ts-sdk/src/sync/positions-live.test.tswith two cases:Typecheck, full test suite (171 tests), and build all pass.