Particle

QuantstampFiles named in the report

Quantstamp reviewed Particle on 23 Aug 2023: 20 findings, 0 critical; 8 marked fixed, 12 acknowledged.

No open critical findings
Open the reportOpen Particle’s security record

Report hosted on certificate.quantstamp.com.

Trustblock does not review code.

Findings20

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical000
High001
Medium003
Low0124
Low`accruedInterest` Boundary Should Be Declared in DocumentationAcknowledged

There are several design assumptions in the system: 1. The interest is not bounded; The maximum APY is 1000%. 2. The market buy process and the auction process will revert if payback to borrower < 0. As a result, the lender will never receive interest higher than the margin. This is not clearly documented in the user-facing documentation. Also, there is no notification when the accrued interest is higher than the margin.

Low`Collection` Not WhitelistedAcknowledged

It is crucial to address the risks associated with the absence of whitelisting the NFT collection address in the `_supplyNf()` function. Failure to whitelist the collection can potentially render the contract vulnerable malicious user actions, especially if the collections contain exploits or have non-standard ERC721 implementations. This is particularly concerning because users have the freedom to select any collection address.

LowClone-and-OwnAcknowledged

The clone-and-own approach involves copying and adjusting open source code at one's own discretion. From the development perspective, it is initially beneficial as it reduces the amount of effort. However, from the security perspective, it involves some risks as the code may not follow the best practices, may contain a security vulnerability, or may include intentionally or unintentionally modified upstream libraries.

LowMissing Input ValidationAcknowledged

The following validation checks are missing from `ParticelExchange`: 1. `supplyNft() `: Validate that `price` is greater than zero. 2. `updateLoan() `: Validate that `price` is greater than zero. 3. `sellNftToMarketPull() `: Validate that `amount` is greater than zero. 4. `sellNftToMarketPush() `: Validate that `amount` is greater than zero. 5. `acceptBidSellNftToMarketPull() `: Validate that `amount` is greater than zero. 6. `acceptBidSellNftToMarketPush() `: Validate that `amount` is greater than zero. 7. `registerMarketplace()`: Ensure that `marketplace` is not the zero address. 8. `constructor` should validate the input address `wethAddress` is not 0.

LowMissing Return Value ValidationAcknowledged

The following value in the contract is returned without validation: - `weth.approve(spender, amount);` in function `_execBuyNftFromMarket()`

LowNot Using Upgradeable DependencyAcknowledged

The `ParticleExchange` contract is an upgradeable contract and should inherit from the upgradeable version of OpenZeppelin's contracts. However, `ParticleExchange` inherits from `ReentrancyGuard` instead of `ReentrancyGuardUpgradeable`. `ReentrancyGuardUpgradeable` has features that support upgradeability, such as a storage gap and a chained initialization function.

LowOwnership Can Be RenouncedAcknowledged

If the owner renounces their ownership, all ownable contracts will be left without an owner. Consequently, any function guarded by the `onlyOwner` modifier will no longer be able to be executed. The `ParticelExchange` contract currently relies on an owner for improtant administrative functionaltiy.

LowPrivileged Roles and OwnershipAcknowledged

The `ParticleExchange` contract features an owner who has exclusive permission to access the administrative functionality of the contract. It is important for project users to be aware of the privileged roles and their permissions so that they are aware of all potential risks. We have listed the privileged permissions of the contract owner below: 1. Register marketplaces that can be used to buy or sell NFTs through the protocol: `registerMarketplace()`. 2. Unregister a marketplace so that it can no longer be used to buy or sell NFTs through the protocol: `unregisterMarketplace()`. 3. Set the percentage of the interest fee to be paid to the protocol with a maximum of `10%`: `setTreasuryRate()`. 4. Withdraw funds from the treasury to an arbitrary address: `withdrawTreasury()`. 5. Allow the owner to upgrade the contract: `_authorizeUpgrade()`.

LowUnborrowed Nfts and Bids Have No Expiry TimeAcknowledged

A supplier may lend an NFT to the protocol, and it may stay unborrowed indefinitely. A worse scenario would be that the NFT does not get borrowed for a long time and then gets borrowed at market conditions that are unfavorable for the supplier. Since the protocol has no protection through oracles, it is important to implement an expiry time such that if a supplied NFT is not borrowed for a certain amount of time, it can not be borrowed anymore. The same scenario applies to bids.

LowUpgradeabilityAcknowledged

The `ParticleExchange` contract is upgradeable. While this is not a vulnerability, users should be aware that the behavior of the contracts could change if the contracts are upgraded. Furthermore, new vulnerabilities not present during the audit could be introduced in upgraded versions of the contract.

Show 2 more
LowUsers Are Responsible for MonitoringAcknowledged

The `ParticleExchange` contract does not rely on any oracles, so only suppliers can be relied on to activate liquidations in the form of auctions. The supplier must monitor the price of the NFT to ensure that the trader's margin has not been used up. Similarly, the trader must monitor when the supplier starts the auctions so that they can refinance if they don't want their position closed prematurely.

LowUsing `tokenId` in `lien` for Margin StorageAcknowledged

In function `updateBid` and `offerBid`, the new lien is created with: ```solidity Lien memory lien = Lien({ lender: address(0), borrower: msg.sender, collection: collection, tokenId: margin, /// @dev: use tokenId for margin storage price: price, rate: rate, loanStartTime: 0, auctionStartTime: 0 }); ``` While the code logic is correct, the mapping `liens` is a public mapping. It is unknown if such information will be displayed through other interfaces (such as web), as the users cannot identify the differences between `tokenId` and `margin`. Since `tokenId` and `margin` should be significantly different in number of digits, we consider this as a low risk issue.

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (6)

  • contracts/libraries/security/ReentrancyGuard.sol
  • contracts/libraries/math/MathUtils.sol
  • contracts/interfaces/IParticleExchange.sol
  • contracts/libraries/types/Errors.sol
  • contracts/libraries/types/Structs.sol
  • contracts/protocol/ParticleExchange.sol

Part of Particle’s security record

Particle
Audits1 audit by 1 firmLast audit Aug 2023, by Quantstamp.
Critical findingsNo open critical findingsIn 1 report.
Open Particle’s security record

Security firm

Quantstamp

236 projects reviewed · 332 reports · latest Oct 2026

See Quantstamp’s audits

Something 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