Reproduced Exploit
Ostium scaleVariables settles PnL at 20 instead of 10
scaleVariables scales accPnlPerToken only when it is negative. A vault with 100 tokens, 100 shares and trader profit of 10 has accPnlPerToken of 0.1. A 90-token deposit mints 100 shares and leaves the accumulator at 0.1. Implied PnL becomes 200 * 0.1 = 20 instead of 10. Settlement pays the trader 2…
Chain
Other
Category
arithmetic
Date
Sep 2025
Source
AuditVault
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.
Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 65202-h-04-code-does-not-scale-accpnlpertoken-in-scalevariables-al. Standalone Foundry PoC and full write-up: 65202-h-04-code-does-not-scale-accpnlpertoken-in-scalevariables-al_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/arithmetic/decimal-mismatch · vuln/logic/price-calculation
Key info#
| Protocol | Ostium |
| Finding | Pashov H-04, AuditVault 65202 |
| Vulnerable code | Vault.scaleVariables |
| Harm | Settlement pays 20 tokens; the fair PnL is 10; off by 10 |
| Chain | local synthetic |
TL;DR#
scaleVariables scales accPnlPerToken only when it is negative. A vault with 100 tokens, 100 shares and trader profit of 10 has accPnlPerToken of 0.1. A 90-token deposit mints 100 shares and leaves the accumulator at 0.1. Implied PnL becomes 200 * 0.1 = 20 instead of 10. Settlement pays the trader 20. Scaling the positive accumulator pays 10.
The vulnerable code#
uint256 supply = totalSupply();
// @> VULN: a positive accPnlPerToken is left unchanged, so implied PnL grows with the new shares
if (accPnlPerToken < 0) {
accPnlPerToken = accPnlPerToken * supply.toInt256()
/ (isDeposit ? (supply + shares).toInt256() : (supply - shares).toInt256());
}
The control applies that same ratio when the accumulator is positive: 0.1e18 * 100 / 200 = 0.05e18, and 0.05 * 200 = 10.
Root cause#
The sign check treats a positive per-token PnL as "already correct". It is correct only for the old supply. New shares inherit the old per-token value, so the implied total doubles when the share supply doubles.
Preconditions#
accPnlPerToken is positive. A deposit increases the share supply. The numbers are the report's example, scaled by 1e18: 100 tokens, 100 shares, profit 10, deposit 90.
Attack walkthrough#
- The depositor adds 90 tokens and receives 100 shares.
scaleVariablessees a positive accumulator and writes nothing.- Supply is 200 and
accPnlPerTokenis still 0.1e18. settlepays20e18to the trader.- The fair payment is
10e18. The difference is10e18.
Diagrams#
Impact#
Traders are settled 20 tokens of PnL when the open profit is 10. The extra 10 comes out of depositor equity. The control pays 10.
Remediation#
Scale accPnlPerToken by supply / (supply + shares) on deposits, and by supply / (supply - shares) on withdrawals, for both signs.
How to reproduce#
cd 65202-h-04-code-does-not-scale-accpnlpertoken-in-scalevariables-al_exp
forge test -vv
Sources#
- AuditVault finding: https://github.com/Auditware/AuditVault/blob/main/findings/65202-h-04-code-does-not-scale-accpnlpertoken-in-scalevariables-al.md
- Pashov report: https://github.com/pashov/audits/blob/master/team/md/Ostium-security-review_2025-09-14.md
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 65202-h-04-code-does-not-scale-accpnlpertoken-in-scalevariables-al_exp (evm-hack-registry mirror).
- AuditVault finding: 65202-h-04-code-does-not-scale-accpnlpertoken-in-scalevariables-al.
Alerts & third-party analyses
These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.