As of 3 Nov 2026, Aconomy Marketplace has 1 audit report on Trustblock, by QuillAudits, dated 24 Jun 2024. That report lists no open critical findings.
Record last updated . It holds audits and findings, contracts and incidents up to Nov 2026. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| Aconomy | Security firm: QuillAudits | Date: | Scope: Files named in the report | No open critical findings | Open · quillaudits.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 0 | 0 |
| Medium | 4 | 0 | 3 |
| Low | 13 | 0 | 17 |
A nuanced action from the borrower may be seen when NFT deposits happen, they take loans and then do not pay back the ERC20 token loaned. There is no guarantee that users will pay back the loans they take by returning the ERC20 token along with the interest accrued over time. When enough time passes, retrieving the NFT by repaying the debt would be more expensive than the user could want to bear.
Open the reportWhile calling BuyNFT()/executeBidOrder() the user has the ability to set _fromCollection as true/false to choose less (or even more for other users to whom the remaining amount would be sent) fees/royalties amount.This happens because depending on the if{} or else{} execution , the different royalties are used. Instead of allowing the user to toggle _fromCollection bool value in BuyNFT() and in executeBidOrder(), another variable can be added to the TokenMeta struct , where the bool value can be set while creating the sale itself. The contract will make a call on the _contractAddress address entered by the user while creating the sale and will check if it is a collection or not. The ERC-165 standard interface detection can be used for the same. In both BuyNFT() and in executeBidOrder() this boolean value can be used from the stored TokenMeta and depending on this bool value the royalties would be fetched in if or else. The implemented functionality should be checked practically as it may break the functionality for contracts that are not supporting the ERC-165 standard interface detection. Additionally the assumption is made that the piMarket is only supporting valid collections/contract implementations supported by the marketplace as discussed internally.
Open the reportThere is no restriction on who can pay back the loan bidded for by the lender. Any user can repay the loan to receive the NFT that the original lender added as collateral. As it is, there is no time delta between when the user is 'safe' to redeem their tokens and when an arbitrageur/liquidator could swoop in to pick up the user's collateral. This means that users who put up their NFT for sale run the risk of losing their NFT immediately another user repays the amount + interest accrued.
Open the reportsetAconomyPoolFee(), setAconomyPiMarketFee(), setAconomyNFTLendBorrowFee() functions are setting fees. Currently, there’s no maximum limit for fees, the maximum limit for fees can be added to increase the trust among users.
Open the reportAdd amount 0 restriction check in withdraw() as allowing 0 amount can create a problem where for the first time the NFT will get transferred and then on L504 the 0 amount will get added to the withdrawnAmount mapping. While calling withdraw() again, on L476 it will check that the msg.sender is owner and it will revert as the NFT is already transferred to the contract while withdrawing the ERC20 first time, even though 0 tokens were withdrawn.If this type of condition happens then the user again needs to repay 0 amount so the user will get his NFT back. There are certain situations where this issue can be triggered e.g while making a call on the front end the amount for withdraw ends up to be 0 because of some issues or some unhandled inputs, While this issue can be rare, it’s still good practice to add the require check to avoid panic at a critical moment.
Open the reportOn L330 it checks that require(erc20Balance >= _value); The revert message can be added.
Open the reportIn listNFTforBorrowing() and setExpectedAmount(), _expectedAmount entered is getting checked to be greater than or equal to 10000000 (1e7) on L174, L238 respectively. Additionally on L264 in Bid(), it checks for require(_bidAmount >= 10000000, "bid amount too low"); which is also 1e7.
Open the reportWhen the user stakes the amount, on L63 the amount is getting added in validatorStakes[_validator].stakedAmount. Any ERC20 token can be used by a user while staking.When a user uses different ERC20 tokens the same mapping is used to add/store the staked amount. This mapping is then used while subtracting an amount while refunding the stake. This can create misrepresentation for the staked amount, as it’s not possible to understand how much amount of different ERC20 tokens was added by that validator.
Open the reportThe __Pausable_init() calls __Pausable_init_unchained() which sets the _paused to false. Although the default uninitialized value is false as well, it is good practice to call the __Pausable_init within the initialize() call.The same happens with __ReentrancyGuard_init() which is empty but remains uncalled.
Open the reportThe interfaces within CollectionMethods and PiNFT are similar for validator royalties. In PiMarket.sol, getCollectionValidatorRoyalty() and retrieveValidatorRoyalty() call the getValidatorRoyalties() method on the contract address passed in to obtain the LibShare.Share[] array details.
Open the reportThe contract owner is allowed to perform a refund of the validator’s stake at any time deemed necessary (except when the contract is paused). The validator’s staked tokens could be an arbitrary token, say DAI for example, but the owner is not constrained to refund DAI tokens. They can refund any amount of any ERC20 tokens, which could be worth nothing at all. This way, a malicious/compromised owner account could deny validators access to their staked amounts and keep the staked value stuck in the contract still as there is no central withdraw / sweep function in validatorStake.sol
Open the reportAconomyPoolFee(), AconomyPiMarketFee(), AconomyNFTLendBorrowFee() are public view methods used to return the values of _AconomyPoolFee,_AconomyPiMarketFee,_AconomyNFTLendBorrowFee variables respectively.Solidity creates getter methods for every public variable. the contract currently has these above-mentioned functions defined for returning the values, which makes it redundant to have other public methods created by solidity for _AconomyPoolFee,_AconomyPiMarketFee,_AconomyNFTLendBorrowFee.
Open the reportERC20Address address type variable from StakeDetail struct is not getting used. The AttestationRegistryAddress variable is not used in any of the contracts.
Open the report• In validatorStake.sol, Counters.sol is getting imported on L8 and L10, and using directive is getting used for it on L19. No functionality from Counters.sol is getting used hence it's redundant. Consider removing the import on L8,L10 and its usage on L19. • Same in PoolRegistry.sol, Counters.sol is getting imported on L4 and it’s using directive is on L21. It is also redundant.In piNFT.sol, IERC20 and IERC721Receiver are redundant imports. Consider removing the unused imports. • IERC20Upgradeable, IERC721ReceiverUpgradeable, Ownable are unused imports in ValidatedNFT.sol and can be removed. • IERC20, ERC721, LibCollection are unused imports in CollectionMethods.sol and can be removed. • Solidity pragma versions greater than 0.8.0 have internal underflow and overflow protection. Arithmetic operations that would result in underflow and overflow would result in an internal panic. The SafeMath library helps to protect from such issues in earlier Solidity versions but now becomes redundant as used here. • In NFTLendingBorrowing.sol, Counters.sol is getting imported on L10 and using directive is getting used for it on L23. No functionality from Counters.sol is getting used hence it's redundant. Consider removing the import on L10 and its usage on L23. • ERC721, Ownable are unused imports in PiMarket.sol and can be removed. ERC721 is imported on L5 and Ownable is imported on L6 but they are unused throughout the codebase and can be removed. • In piNFTMethods the import "./CollectionMethods.sol"; on L12 is unused hence can be removed. In poolAddress.sol , the Counters.sol is imported but never used hence can be removed.
Open the reportIn CollectionMethods.sol, the modifier that checks if a caller is the NFT owner is unused. Although CollectionMethods is imported in the piMarket contract, piMarket.sol defines onlyOwnerOfToken separately, not using the existing function modifier in CollectionMethods.sol.
Open the reportOn L203, L204 addERC20() function has require checks, The first statement checks that approvedValidator[_collectionAddress][_tokenId] should not be address(0) and the second one checks that msg.sender should be equal to approvedValidator[_collectionAddress][_tokenId].Instead of checking for both the conditions only one condition can be checked that is require(msg.sender == approvedValidator[_collectionAddress][_tokenId]);. So if msg.sender == approvedValidator[_collectionAddress][_tokenId] is true then approvedValidator[_collectionAddress][_tokenId] can't be a zero address.
Open the reportWhile adding the validator with addValidator() and lazyAddValidator(), No check is added in the piNFTMethods for checking if the validator has staked or not. There's the possibility that the validators that haven’t been staked can be also added by users in piNFTMethods.
Open the reportThe variable bidStartTime in the TokenMeta struct is declared but never used. It currently takes up an extra portion of storage in every instance of the TokenMeta struct created and will never be filled.
Open the reportIn Fundingpool.sol, InstallmentRepaid() is unused hence can be removed.In poolAddress.sol, repaidAmounts() event is unused hence can be removed.
Open the reportThe initialize() function in the ValidatedNFT contract does not initialize ERC721Upgradeable by calling __ERC721_init(). The ERC721Upgradeable is inherited in ERC721URIStorageUpgradeable. The __ERC721_init() sets the contract name and symbol in __ERC721_init(). Not calling the initializer function leaves the NFT without a name and symbol which could affect metadata parsing for each ValidatedNFT minted, even though they will have all other information intact.
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="aconomy-marketplace"></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