Reproduced Exploit
Buffer `closeAnytime` never ties the user's close signature to the pricing timestamp
Chain
Other
Category
untagged
Date
Jul 2023
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: 55637-h-05-closeanytime-timestamp-is-never-validated-against-prici. Standalone Foundry PoC and full write-up: 55637-h-05-closeanytime-timestamp-is-never-validated-against-prici_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/wrong-condition · vuln/timestamp-dependence · impact/loss-of-funds/direct-drain
Reproduction: the test deploys the REAL audited Buffer v2.5
BufferRouter+BufferBinaryOptions+BufferBinaryPooland drives the realcloseAnytimepath. A user's valid close signature is paired by a malicious keeper with publisher pricing from a completely different time, settling the user's winning option at a stale, worthless price.
Root cause#
closeAnytime verifies three independent signatures whose timestamps are never required to
agree:
Validator.verifyCloseAnytimebinds only(assetPair, userSignInfo.timestamp, optionId)— not the price.Validator.verifyPublisherbinds(assetPair, publisherSignInfo.timestamp, closingPrice).unlock(...)then settles usingpublisherSignInfo.timestampandclosingPrice.
Nothing ties userSignInfo.timestamp to publisherSignInfo.timestamp. A user signs a close
authorization for their option at a moment when the price is favorable, but their signature does
not constrain which price the settlement uses. With private keeper mode disabled, a malicious
keeper (or a front-runner) can pair the user's valid close signature with publisher pricing from
an entirely different, unfavorable time.
Exploit walkthrough (numbers from the test)#
- A user owns an ETH/USD call, strike
1000, locking 100 USDC. They sign a close authorization atT_user = 5000, when the price was1500(deep ITM) — expecting the full 100 USDC payout. - Control: an identical option closed correctly — publisher price
1500atT_user— pays the full 100 USDC, proving the option is a winner. - Exploit: the keeper reuses the user's
T_userclose signature but pairs it with a genuine publisher signature for price900at a different timestamp9000. Because900 < strikeandclosingTime (9000) >= expiration (4600), the option expires worthless. - The user receives 0 instead of the 100 USDC they signed to collect — a total loss of their in-the-money payout, purely because the pricing timestamp was decoupled from their signature.
Fix#
Require the pricing-data timestamp and the closeAnytime (user) timestamp to match. Buffer's
remediation (PR #4) removes
the ability to disable private keeper mode — but, as the auditor notes, a malicious or
compromised keeper can still exploit this.
Reproduction#
- Registry PoC:
_shared/run-poc/run_poc.sh 55637-h-05-closeanytime-timestamp-is-never-validated-against-prici_exp -vvvvv - Real audited source under
src/at commit84b6060b4447b2550de595202e8820c7f515988b.
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 55637-h-05-closeanytime-timestamp-is-never-validated-against-prici_exp (evm-hack-registry mirror).
- AuditVault finding: 55637-h-05-closeanytime-timestamp-is-never-validated-against-prici.
- Upstream DeFiHackLabs PoC directory: src/test.
Alerts & third-party analyses
- DeFiHackLabs incident explorer: search "Buffer
closeAnytimenever ties the user's close signature to the pricing timestamp". - Web3Sec X hacked database: search.
- Rekt leaderboard: search.
- Solodit incident search: search.
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.