As of 14 Oct 2026, OpenSea has 2 audit reports by 1 security firm on Trustblock; the latest is by Quantstamp, dated 2 Sep 2022. Those reports list no open critical findings.
Record last updated . It holds audits and findings, contracts and incidents up to Oct 2026. Statuses are the security firms’ own. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| NFT Market (PresetHTC, Auction, Store) | Security firm: Quantstamp | Date: | Scope: Files named in the report | No open critical findings | Open · certificate.quantstamp.com |
| NFTMarket | Security firm: Quantstamp | Date: | Scope: Files named in the report | No open critical findings | Open · certificate.quantstamp.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 1 | 2 | 2 |
| Medium | 0 | 4 | 2 |
| Low | 3 | 8 | 6 |
The `auctions` mapping is first indexed by the `contractAddr` followed by the `tokenId`. However, in the case of ERC1155 tokens, there may be more than 1 supply of each `tokenId`. This is apparent in the `token.safeTransferFrom(_from, _to, _tokenID, 1, DEFAULT_MESSAGE)` call, where the 1 indicates the amount of `_tokenID` tokens to transfer. Suppose a `(contractAddr, tokenId)` pair has a supply larger than 1, and an auction is launched for one instance of this token. If a new auction is started for a different instance, the `auctionInfo[contractAddr][tokenId]` data will be overwritten, wiping previous auction data, and eventually locking 1 instance of the token in the contract forever.
Open the reportA reentrancy vulnerability is a scenario where an attacker can repeatedly call a function from itself, unexpectedly leading to potentially disastrous results. Here's a basic example representing the very attack which impacted The DAO in 2016: ``` function withdraw_with_reentrancy(uint256 _amount) public { msg.sender.call.value(_amount)(); // ATTACKER CAN CALL AGAIN BEFORE // FUNCTION TERMINATES because `call` // allows msg.sender to execute any code using fallback function balances[msg.sender] -= _amount; // Balance only updated AFTER funds withdrawn } ``` Specifically, re-entrancy is present in `launchAuction()`, `launchReservedAuction()` due to the use of `transferToken()`.
Open the reportFunctions `NFTAuction.vipBid()` and `NFTAuction.Bid()` only check if the bid is within the allowed time window of the auction, but does not take into account the status of the auction (Unsold), allowing one to bid on cancelled auctions so long as it falls in the allowed time frame.
Open the reportIn contract `NFTStore.sol` the native `.transfer()` function is used to transfer ETH, which only forwards `2300` gas and reverts on error. As during `vipBuy()` and `Buy()` funds are always forwared to all shares, a malicious `shareAddr` could prevent the sell operation, by consuming more than `2300` gas on ETH receival or otherwise err. The same applies for the `storeAddress` and `product.seller` address.
Open the reportIn order to validate the proper deployment and initialization of the contracts, it is a good practice to emit events. Also, any important state transition can be logged, which is beneficial for monitoring the contract, and also tracking eventual bugs, or hacks. Below we present a non-exhaustive list of events that could be emitted to improve the application management: 1. `ERC721PresetHTC.setContractUri()` does not emit an event reflecting changes made to the state variable `contractUri`. (**Update:** Fixed) 1. `ERC721PresetHTC.setBaseUri()` does not emit an event reflecting changes made to the state variable `_baseTokenURI`. (**Update:** Fixed) 1. `ERC721PresetHTC._setTokenURI()` does not emit an event reflecting changes made to the state variable `_tokenURIs[]`. (**Update:** Fixed) 1. `NFTAuction.setPriceLimit()` does not emit an event reflecting changes made to the state variables `priceThreshold` and `priceLimit`. (**Update:** Fixed) 1. `NFTAuction.setMerkleRoot()` does not emit an event reflecting changes made to the state variable `merkleRoots[]`. (**Update:** Fixed) 1. `NFTStore.setStoreData()` does not emit an event reflecting changes made to the state variables `storeAddress` and `storeDefaultProfit`. (**Update:** Fixed) 1. `NFTStore.setMerkleRoot()` does not emit an event reflecting changes made to the state variable `merkleRoots[]`. (**Update:** Fixed)
Open the reportIn the `finalizeAuction()` function, the caller is the `seller` of the auction and also has the `LAUNCH_ROLE`. The seller should not have access to launch new auctions, but should still be able to finalize their previous auctions. If before calling `finalizeAuction()` the admin revokes `LAUNCH_ROLE` for the `seller` the auction remains in open status and funds get locked in the contract. This is the result of mixing seller and launcher roles in one `LAUNCH_ROLE` role.
Open the reportAvoid leaving a contract uninitialized. An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation contract, which may impact the proxy.
Open the reportStorage variable `storeDefaultProfit` in contract `NFTStore.sol` is stored as an `uint256` variable, although, by business, it should not be able to exceed `10**4` (`BASE_PERCENT`). In L98 a primitive cast operation is performed `uint16(storeDefaultProfit)`, potentially leading to truncation, as the aforementioned bound is not enforced during `__NFTMarket_init()` and `storeDefaultProfit` could exceed `type(uint16).max`.
Open the reportThese two functions return 0 when the external call is not successful. This may lead to burned funds, particularly when `getAddrDataFromContract()` is used to transfer creator profit in the `acceptOffer()` function. Further, it is not clear why the functions `getUintDataFromContractI()` and `getAddrDataFromContract()` exist at all. It seems the relevant functionality could be represented through an interface that expects the function signatures `creatorOf(uint256)` and `creatorProfitOf(uint256)`.
Open the reportEvery Solidity file specifies in the header a version number of the format `pragma solidity (^)0.8.*`. The caret (`^`) before the version number implies an unlocked pragma, meaning that the compiler will use the specified version _and above_, hence the term "unlocked".
Open the reportThe reports name a repository or files. Open a report to see its scope.
Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.
Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.
<head><script src="https://widget.trustblock.run/project-widget.min.js" defer></script></head><body><divdata-tb-project-widgetdata-tb-project-slug="opensea"></div></body>
Paste the code where the label should appear. It uses no API credit and updates by itself.
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