Skip to content

fix(perps): enforce native equity health on withdrawals#141

Draft
rndrntwrk wants to merge 2 commits into
mainfrom
security/native-perps-equity-health
Draft

fix(perps): enforce native equity health on withdrawals#141
rndrntwrk wants to merge 2 commits into
mainfrom
security/native-perps-equity-health

Conversation

@rndrntwrk

Copy link
Copy Markdown
Collaborator

Summary

Fixes the native perps health-check issue found during the contract audit.

Before this patch, AgentPerpEngineNative checked leverage using raw margin only. After an adverse oracle move, a position could have negative equity while still passing the raw notional / margin check, and withdrawMargin() did not sync the oracle before evaluating the withdrawal.

This patch brings the native health gate in line with the ERC20 engine: health is evaluated against equity, where equity = margin + unrealizedPnl.

Security Impact

  • Native perps health checks now reject equity <= 0.
  • Max leverage is computed as notional / equity, not notional / raw margin.
  • withdrawMargin() now requires a live market, syncs the oracle, settles funding, subtracts the withdrawal, then checks equity before sending ETH.
  • modifyPosition() uses the same equity-aware health gate after position changes.

Verification

  • Red-path regression was confirmed before the fix: testNativeWithdrawMarginRejectsNegativeEquityAfterOracleMove failed because the withdrawal did not revert.
  • env FOUNDRY_LIBS='["../../node_modules","lib"]' forge test --match-path test/perps/AgentPerpEngine.t.sol --match-test testNativeWithdrawMarginRejectsNegativeEquityAfterOracleMove -> 1 passed, 0 failed
  • env FOUNDRY_LIBS='["../../node_modules","lib"]' forge test --match-path test/perps/AgentPerpEngine.t.sol -> 49 passed, 0 failed
  • env FOUNDRY_LIBS='["../../node_modules","lib"]' forge test --match-path test/perps/AgentPerpEngineFuzz.t.sol -> 2 passed, 0 failed
  • env FOUNDRY_LIBS='["../../node_modules","lib"]' forge test --match-path test/adversarial/PmPerpsAdversarial.t.sol -> 11 passed, 0 failed
  • git diff --check -> pass

Staging Policy

This PR targets main and is intentionally draft while review is pending. The same patch will be replayed into enoomian/staging for staging deployment and testing, but this effective PR remains open as the merge vehicle.

Follow-up

This PR fixes the withdrawal/health-gate portion. The separate native liquidation accounting finding remains open because it requires PnL realization, insurance draw, and bad-debt accounting changes in the liquidation path.

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.

1 participant