<!-- canonical: https://0xsimao.com/findings/singularity-dark-looping-join-split -->

# DarkPoolAssetManager can be drained by looping over join(), joinSplit() or swap() with only some initial amount

Crit/High · Three Sigma · Private DeFi access · 26th February, 2024

Finding 3S-SG-C05 of the Singularity security review.

- Protocol: https://www.thesingularity.network/
- Report: /reports/singularity
- Source: https://cdn.sanity.io/files/qoqld077/production/45b8aac56a2b8e3b557df4329ac9bf8220b64012.pdf

---

### Description

[DarkPoolAssetManager::join()](https://github.com/portalgateme/darkpool-v1-zk-contracts-fork/blob/master/contracts/core/DarkpoolAssetManager.sol#L397), [DarkPoolAssetManager::joinSplit()](https://github.com/portalgateme/darkpool-v1-zk-contracts-fork/blob/master/contracts/core/DarkpoolAssetManager.sol#L348) and
[DarkPoolAssetManager::swap()](https://github.com/portalgateme/darkpool-v1-zk-contracts-fork/blob/master/contracts/core/DarkpoolAssetManager.sol#L441) don't check if the 2 notes are the same. Thus, using only 1
note, it's possible to double the amount of funds available. When used in a loop, this enables
draining the whole asset manager.
[Here](https://github.com/portalgateme/darkpool-v1-zk-contracts-fork/commit/59dbe1b6625d180ec7a7c367169fd6386d1a077c) is the poc for join() and joinSplit and [here](https://github.com/portalgateme/darkpool-v1-zk-contracts-fork/blob/fuzzing/test/foundry/DarkpoolAssetManager.t.sol#L460) for swap().

### Recommendation

Check if the input notes are the same.

### Status

Addressed in [#8b300f0](https://github.com/portalgateme/darkpool-v1-zk-contracts-fork/commit/8b300f07a28f2c073154c8de3e9e90ba64ef1934).

---

Related findings:

- [Drained lender due to `LenderCommitmentGroup_Smart::acceptFundsForAcceptBid()` `_collateralAmount` by `STANDARD_EXPANSION_FACTOR` multiplication](https://0xsimao.com/findings/teller-finance-bid-collateral-factor-multiplication): Teller Finance
- [Users always pay fee on the full swapped amount in the `DeliHook`, even if the swap is smaller](https://0xsimao.com/findings/bmx-fee-full-swapped-hook): BMX
- [Swap amount can be 0 as it divides the balance by 2, DoSing ShadowStrategyGauge::collectGaugeRewards()](https://0xsimao.com/findings/yieldoor-i-divides-sing-shadow-rewards): Yieldoor Gauges
- [Allow lenders to set a minimum amount of asset they would take for their shares](https://0xsimao.com/findings/maple-finance-ii-lenders-minimum-they-shares): Maple Withdrawal Manager
