Quantstamp reviewed Particle on 23 Aug 2023: 20 findings, 0 critical; 8 marked fixed, 12 acknowledged.
Report hosted on certificate.quantstamp.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 0 | 1 |
| Medium | 0 | 0 | 3 |
| Low | 0 | 12 | 4 |
The `_execBuyNftMarket()` keeps track of the balance of ETH before and after the market trade in order to ensure the correct amount of ETH or WETH is used in the trade. Whether or not WETH is used as payment for the trade, the contract's entire balance of WETH will be converted to ETH after the trade. Therefore, if the contract holds any WETH before the trade, it will be converted back to ETH and invalidate the strict inequality check and trigger `Errors.InvalidNFTBuy()`.
The `onERC721Received()` function allows users to take various actions on the protocol without the additional step of approving an NFT transfer. The action taken depends on the contents of the `data` parameter. However, for some values of invalid values of `data` no protocol action will be taken on the NFT, and it will simply be swallowed up by the contract and locked forever. This would happen for values of data such that: `data.length != 64 && data.length != 288 data.length < 384`.
The `onERC721Received()` function can be called by externally owned accounts and smart contracts alike. If an NFT contract is able to call `onERC721Received()` without actually transferring the NFT, the Lien will still be considered repaid.
The following functions are missing non-reentrant modifiers: - `acceptBidSellNftToMarketPull()` - `acceptBidSellNftToMarketPush()` - `onERC721Received() ` It is unclear why the project team committed to using a re-entrancy guard on those functions.
The CEI (Check-Effect-Interact) pattern is not respected in the following functions: 1. `sellNftToMarketPush()` 2. `buyNftFromMarket()` 3. `swapWithEth()` 4. `repayWithNft()` 5. `acceptBidSellNftToMarketPull()` 6. `acceptBidSellNftToMarketPush()` 7. `auctionBuyNft()` 8. `onERC721Received()` The state is updated after the execution of external calls to third-party addresses. If any hook allows a chain of calls to execute any logic in a contract that relies on the `ParticleExchange` contract state, it might be exploited since the state in `ParticleExchange` is not yet finalized. Please note that non-reentrant modifiers only protect the local state of the called contract from being re-entered. However, multiple contracts can share a single state through static calls and return values that create a broader global state that can be exploited with more complex mechanisms.
The `onERC721Recieved()` function can be called by externally owned accounts and smart contracts alike. If an EOA calls the function, a new Lien will be created without supplying a new NFT to the contract. Similarly, a smart contract could do the same. These Lien creations will emit the `SupplyNFT` event and could cause issues on the front end.
A supplier may withdraw their NFT if it has not been borrowed by a trader using the `withdrawNft()` function. However, the `withdrawNFT()` function makes uses the `ERC721.safeTransferFrom()` function, which would fail if the lender was a contract that did not implement `onERC721Received()`. In this case, the `withdrawNft()` function would revert. The supplier may use a workaround of using a different address to call `swapWithEth()` and then use that other address to call `withdrawNft()`.
IParticleExchange is using an unlocked solc version.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (6)
236 projects reviewed · 332 reports · latest Oct 2026
See Quantstamp’s auditsSomething wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.
Tell us