Reproduced Exploit
Persistence: empty funds list locks 100 of Alice's LST
The amount check runs only when funds contains the denom. An empty list skips it, then the lock balance still increases. joinPool pays that credit from the tokens Alice deposited.
Chain
Other
Category
logic
Date
Jan 2024
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: 53505-prst-5-user-can-lock-and-stake-arbitrary-amount-of-tokens-wi. Standalone Foundry PoC and full write-up: 53505-prst-5-user-can-lock-and-stake-arbitrary-amount-of-tokens-wi_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/logic/missing-check
Key info#
| Protocol | Persistence |
| Finding | Hexens PRST-5, AuditVault 53505 |
| Vulnerable code | Locker.lockLstAsset |
| Harm | Bob locks 100 with an empty funds list and joinPool pays him Alice's 100 LST. The fixed locker reverts and her 100 stays. |
| Chain | local synthetic |
TL;DR#
The amount check runs only when funds contains the denom. An empty list skips it, then the lock balance still increases. joinPool pays that credit from the tokens Alice deposited.
The vulnerable code#
// @> VULN: lock credit increases even when funds contained no matching coin
locked_amount = locked_amount + asset.amount;
Root cause#
Nothing requires that the funds loop actually matched the denom before the credit is stored.
Preconditions#
Alice has locked 100 ux and the contract holds those tokens. Bob can call lock with an empty coin list.
Attack walkthrough#
- Alice locks 100 and pays 100 LST. See output.txt.
- The credit line runs for her paying call.
- Bob locks 100 with an empty funds array. No tokens move.
- Bob's lock record is 100.
joinPooltransfers 100 to Bob.- The locker balance is 0 and Alice's credit is still 100. The fixed path reverts the unpaid lock.
Diagrams#
Impact#
Alice loses 100 LST. Bob paid nothing. The fixed locker reverts unless a matching coin was pulled.
Remediation#
Require that a coin of the locked denom was received for the full amount before increasing the lock balance.
How to reproduce#
cd 53505-prst-5-user-can-lock-and-stake-arbitrary-amount-of-tokens-wi_exp
forge test -vv
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 53505-prst-5-user-can-lock-and-stake-arbitrary-amount-of-tokens-wi_exp (evm-hack-registry mirror).
- AuditVault finding: 53505-prst-5-user-can-lock-and-stake-arbitrary-amount-of-tokens-wi.
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.