<!-- canonical: https://0xsimao.com/findings/singularity-curve-withdraw-paying-fees -->

# Curve multi exchange can be used to withdraw assets without paying fees

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

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

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

---

### Description

CurveMultiExchangeAssetManager::exchange() allows sending any route, which is of
type Array of [initial token, pool or zap, token, pool or zap, token, ...].
The pool or zap chosen indexes are not validated, which means any contract can be
specified. Thus, users can create a contract with the same interface as pool or zap and
receive the amountIn there. Then, only send back a very small amount of token out to
bypass the fee manager check in calculateFee() of the amount being bigger than
serviceCharge + relayerRefund. The service fees will be very small and the user will get
the funds right away.
The [poc](https://github.com/portalgateme/darkpool-v1-zk-contracts-fork/commit/15579b3292a2ba64e6366359eab22a5774c44edd#diff-2ca8b97729682cb38022f50764c9ff79acfcb1b4520988d573457c6b91cb7d3dR14) for issue #13 contains an example of a malicious swap contract.

### Recommendation

Apply the fees when releasing assetIn instead, this way it can not be gamed.

### Status

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

---

Related findings:

- [Users can exploit the batch minting feature to avoid paying minting fees for tokens](https://0xsimao.com/findings/titles-publishing-protocol-exploit-feature-avoid-fees): TITLES Publishing Protocol
- [ERC4626YieldBackend.withdrawSurplus() uses convertToAssets() which doesn't account for fees](https://0xsimao.com/findings/superfluid-erc4626-yield-withdraw-fees): Superfluid Yield Backends
- [MapleSkyStrategy::assetsUnderManagement() uses maxWithdraw(), which may return 0](https://0xsimao.com/findings/maple-finance-iv-sky-management-withdraw-return): Maple Cash Strategies
- [`totalCdsDepositedAmountWithOptionFees` is incorrectly reduced in `CDSLib::withdrawUser()`, leading to stuck option fees](https://0xsimao.com/findings/autonomint-fees-reduced-withdraw-stuck): Autonomint
