Reproduced Exploit

P2P Yield Proxy: the deposit fee residual stays in the proxy with no withdraw path

_deposit pulls amount and forwards amount * s_clientBasisPointsOfDeposit / 10_000. With the client share at 8000 bps, a 10000 YLD deposit forwards 8000 and leaves 2000 sitting on the proxy. deposits[user] is 8000. withdrawAll returns 8000. The 2000 is not tracked and has no transfer. The fixed depo…

May 2025•Other•dos•2 min read

Chain

Other

Category

dos

Date

May 2025

Source

AuditVault

EVM Playground

Source-level debugger — step opcodes and Solidity in sync

evm-hack-analyzer

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.

Loading fork state…

Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 56810-locked-residual-token-amounts-on-deposit-mixbytes-none-p2por. Standalone Foundry PoC and full write-up: 56810-locked-residual-token-amounts-on-deposit-mixbytes-none-p2por_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/dos/frozen-funds · vuln/logic/state-update

Reproduction: cheatcode-free local synthetic. _deposit uses the audited formula. Full trace: output.txt. PoC: test/56810-locked-residual-token-amounts-on-deposit-mixbytes-none-p2por_exp.sol.

AuditVault taxonomy: lang/solidity · sector/staking · severity/high · MixBytes P2P.org Staking Lending Proxy, May 2025

Key info#

ProtocolP2P.org Staking Lending Proxy
FindingMixBytes, AuditVault 56810, high
Vulnerable codeP2pYieldProxy._deposit
Harm2000 of 10000 YLD stays in the proxy after the user withdraws everything the books will pay
Chainlocal synthetic

TL;DR#

_deposit pulls amount and forwards amount * s_clientBasisPointsOfDeposit / 10_000. With the client share at 8000 bps, a 10000 YLD deposit forwards 8000 and leaves 2000 sitting on the proxy. deposits[user] is 8000. withdrawAll returns 8000. The 2000 is not tracked and has no transfer. The fixed deposit sends that residual to the treasury, and the proxy balance after withdraw is 0.

The vulnerable code#

SOLIDITY
uint256 amountToDepositAfterFee = amount * s_clientBasisPointsOfDeposit / 10_000;
token.approve(address(underlying), amountToDepositAfterFee);
// @> VULN: amount - amountToDepositAfterFee stays in this proxy with no withdrawal path
underlying.deposit(amountToDepositAfterFee);
deposits[msg.sender] += amountToDepositAfterFee;

Diagrams#

flowchart TD A["User deposits 10000 YLD"] --> B["Client bps is 8000"] B --> C["8000 is forwarded to the underlying"] C --> D["2000 stays on the proxy"] D --> E["deposits records 8000 only"] E --> F["withdrawAll pays 8000"] F --> G["Proxy still holds 2000 YLD"]

Sources & further analysis#

Reproductions & code

Alerts & third-party analyses

  • 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.