Reproduced Exploit
[H-01] Buffer Finance v2.5 — payments for coupons to the Booster are irretrievable
Chain
Other
Category
logic
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: 55633-h-01-payments-for-coupons-to-booster-are-irretrievable-0x52. Standalone Foundry PoC and full write-up: 55633-h-01-payments-for-coupons-to-booster-are-irretrievable-0x52_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/logic/locked-funds · vuln/accounting/fee-sink · frozen-funds
Reproduction: the test deploys the historical Buffer
Boostercontract and calls its realbuyentry point. The coupon payment issafeTransferFrom'd into the Booster, and the contract exposes no function that can ever move that ERC20 back out — the money is locked forever.
Root cause#
The audited Booster at commit
84b6060
collects coupon payments into itself:
function buy(address tokenAddress, uint256 traderNFTId) external {
...
uint256 price = couponPrice - discount;
require(token.balanceOf(user) >= price, "Not enough balance");
token.safeTransferFrom(user, address(this), couponPrice); // <-- payment lands in the Booster
userBoostTrades[tokenAddress][user].totalBoostTrades += MAX_TRADES_PER_BOOST;
emit BuyCoupon(tokenAddress, user, couponPrice);
}
The full Booster surface is: setConfigure, getUserBoostData, updateUserBoost,
getBoostPercentage, setPrice, setBoostPercentage, buy, plus the inherited
Ownable / AccessControl role helpers. None of them transfer an ERC20 out of the
contract, and there is no fallback/receive. Every unit paid for a coupon is
therefore permanently frozen — neither the payer, the owner, nor the admin can recover it.
The remediation (PR #8) routes the fee to the admin instead of the Booster, confirming the destination address is the bug.
The exact historical contract is vendored at
src/core/Booster.sol; its interfaces at
src/interfaces/Interfaces.sol. OpenZeppelin 4.9.3
(Ownable/AccessControl/SafeERC20/ERC20) is vendored under src/oz.
Reproduction#
The fixture deploys the real Booster, a minimal real ERC20 as the opaque coupon-payment
token, and a minimal trader-NFT stub (an out-of-scope external boundary whose owner never
matches the buyer, so the full couponPrice flows in). A user funds, approves, and buys
one coupon.
cd 55633-h-01-payments-for-coupons-to-booster-are-irretrievable-0x52_exp
forge test -vvv
Expected result: 1 passed. The assertions in
test/55633-h-01-payments-for-coupons-to-booster-are-irretrievable-0x52_exp.sol
verify that:
- the buyer pays the full
couponPrice(5,000 PAY) and the Booster holds it; - the boost credit is granted (the payment was a legitimate, expected one); and
- every plausible retrieval selector (
withdraw,sweep,recoverERC20,rescueTokens,emergencyWithdraw,transferToken,claimFees, …) reverts with "unrecognized function selector … no fallback" — so no egress path exists and the 5,000 PAY remains locked in the Booster after all attempts. Harm:profit == 0attacker-side; the concrete loss is the permanently frozen coupon revenue.
Sources#
- AuditVault finding #55633
- Buffer v2.5
Booster.sol@84b6060 - 0x52 report — 2023-07-26 Buffer v2.5
- Fix PR #8 (fees to admin)
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 55633-h-01-payments-for-coupons-to-booster-are-irretrievable-0x52_exp (evm-hack-registry mirror).
- AuditVault finding: 55633-h-01-payments-for-coupons-to-booster-are-irretrievable-0x52.
- Upstream DeFiHackLabs PoC directory: src/test.
Alerts & third-party analyses
- DeFiHackLabs incident explorer: search "[H-01] Buffer Finance v2.5".
- 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.