As of 3 Nov 2026, FNCY has 1 audit report on Trustblock, by CertiK, dated 22 Mar 2024. That report lists no open critical findings.
Record last updated . It holds audits, findings and contracts up to Nov 2026, and incidents up to Oct 2026. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| FNCY Chain | Security firm: CertiK | Date: | Scope: Files named in the report | No open critical findings | Open · skynet.certik.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 3 | 2 |
| Medium | 0 | 3 | 4 |
| Low | 7 | 0 | 24 |
When transferring standard ERC20 deflationary tokens, the input amount may not be equal to the received amount due to the charged transaction fee. As a result, an inconsistency in the amount will occur. For example, if a user locks 100 deflationary tokens (with a 10% transaction fee) to the bridge contract, only 90 tokens actually arrive to the bridge. ```solidity if (paymentAmount > 0) { if (paymentToken != address(0)) { ... TransferHelper.safeTransferFrom(paymentToken, msg.sender, launchpadFeeInterceptor, paymentAmount); } else if (paymentToken == address(0)) { ... } ILaunchpadFeeInterceptor(launchpadFeeInterceptor).executeFundsTransfer(projectId, paymentAmount, paymentToken); } ```
Open the reportFor the functions `addProject()` and `updateProject()`, there is a lack of sufficient checks around the input parameters. - For address variables like `settlement` and `paymentTokens`, there are no checks that the addresses are zero addresses. - For timestamp variables like `startTimestamp` and `endTimestamp` there are no checks in relation to the current time `block.timestamp`, therefore they could be set to times in the past. - For numeric values like `price` or `total` it might be helpful to include checks on the lower and/or upper values. - Specifically for the `updateProject()` function, there are no checks on the updated values in comparison to their original values. Changes to values like `total` and `endTimestamp` during the course of the project could lead to unexpected behavior. ```solidity function updateProject( uint256 projectId, INFT nft, uint8 limitPerWallet, uint112 total, uint256 price, uint256 startTimestamp, uint256 endTimestamp, address payable settlement, address[] memory paymentTokens ) public onlyAdmin { Project storage project = projects[projectId]; project.nft = nft; project.limitPerWallet = limitPerWallet; project.total = total; project.price = price; project.startTimestamp = startTimestamp; project.endTimestamp = endTimestamp; project.settlement = settlement; ... ```
Open the reportThere is a potential issue that occurs if a user provides an array `nftIds` with duplicate `nftId` values to a function (such as the `bulkMint()` function) that uses the `_checkHasMinted(address collection, uint256[] memory nftIds)` method, which could bypass the "Already Minted" check for duplicates since all checks are completed before any NFTs are minted in bulk. It is also uncertain the relationship between `nftId` (which is a server generated value) and the parameter input `tokenId` which is used to identify the minted tokens. In the current implementation there could hypothetically be the case where duplicate NFTs that are processed in bulk and have passed the `_checkHasMinted` verification are assigned different tokenIds. This would mean that they will be identified as unique NFTs in the contract even though they were initially duplicates.
Open the reportWithin function `_transferFee()`, transfers to `fee.recipients` in ETH could potentially fail especially if there are any recipients that are smart contract that do not contain an appropriate fallback function. ```solidity=122 require(_transferTo(fee.recipient, payout), "Transfer Fail"); ``` This failure would cause all the transfers to the set fee recipients to fail. If one of the `fee.recipient` addresses is controlled by a malicious actor, they can craft their smart contract's `fallback` function in a way that will always cause it to revert. This would effectively cause the `_transferFee()` function to revert every time, leading to a Denial of Service (DoS) for the functionality of transferring fees.
Open the reportWithin function `_bulkMint,` NFT transfers to `recipients` could potentially fail, especially if any recipients are contracts that do not contain an appropriate `onERC721Received` function. ```solidity=122 if (CallType.MINT == callType) { for (uint256 i = 0; i < _size; i++) { (uint256 rTokenId) = _callMint(collectionConfig.collection, recipients[i], tokenIds[i], uris[i]); rTokenIds[i]=rTokenId; } } else if (CallType.SAFE_TRANSFER_FROM == callType) { for (uint256 i = 0; i < _size; i++) { _callSafeTransferFrom(collectionConfig.collection, collectionConfig.merchant, recipients[i], tokenIds[i]); // Error handling exists in ERC721 } } ``` This failure would cause all the transfers to the recipients to fail. If one of the `recipients` addresses is controlled by a malicious actor, they can craft their smart contract's `onERC721Received` function in a way that will always cause it to revert. This would effectively cause the `_bulkMint` function to revert every time, leading to a Denial of Service (DoS) for the functionality of distributing NFTs.
Open the reportIn function `_transferFee()` the `payout` could potentially be zero due to the division truncation of integers, if the value of `_price.mul(fee.feeRate)` is less than the `FEE_BASIS_POINT`. ```solidity=124 uint256 payout = _price.mul(fee.feeRate).div(FEE_BASIS_POINT); ``` Especially, if the token has a small number of decimals, like 6, then the _price value will tend to be smaller, and it will exacerbate this truncation issue.
Open the reportThe contract is serving as the underlying entity to interact with one or more third-party protocols. The scope of the audit treats third-party entities as black boxes and assumes their functional correctness. However, in the real world, third parties can be compromised and this may lead to lost or stolen assets. In addition, upgrades of third parties can possibly create severe impacts, such as increasing fees of third parties, migrating to new LP pools, etc. ```solidity=38 mapping(address => address) public interceptors; ``` - The contract `NFTExchange` interacts with third-party contracts with `IExchangeFeeInterceptor` interface via `interceptors`. --- ```solidity=27 address public launchpadFeeInterceptor; ``` - The contract `NFTLaunchpad` interacts with third-party contracts with `ILaunchpadFeeInterceptor` interface via `launchpadFeeInterceptor`. --- ```solidity interface INFT { function safeMint(address to, uint256 tokenId, string memory uri) external returns(uint256); } ``` ```solidity struct Project { INFT nft; uint8 limitPerWallet; uint112 total; uint256 price; uint256 startTimestamp; uint256 endTimestamp; uint256 soldCount; address payable settlement; bool fundraising; } ``` - The `NFTLaunchpad` contract interacts with third-party contracts with `INFT` interface via `Project.nft` --- ```solidity function buyFromAnotherChain(address user, uint256 projectId, uint8 count, string memory receipt, uint256 chainId) public onlySpecial onlyAvailable(projectId) ``` - The `NFTLaunchpad` contract may interact with the off-chain bridge server to perform the purchase from another chain. --- ```solidity interface IBaseNFT { function safeMint(address to, uint256 tokenId, string memory uri) external returns(uint256); } ``` ```solidity struct CollectionConfig { address collection; address merchant; bool enabled; CallType callType; } ``` - The `TransferManagement` contract interacts with third-party contracts with `IBaseNFT` interface via `CollectionConfig.collection`. --- ```solidity function sell(address _nftAddress, uint256 _tokenId, uint256 _price, uint256 _deadline) public nonReentrant whenNotPaused ``` - The `NFTExchange` contract interacts with third-party contracts with `IERC721Upgradeable` interface via `_nftAddress`.
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="fncy"></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