Audit · firm’s term: audit report
QuillAudits reviewed Nex Labs Cross Chain (Nex Labs DeFi Indices) on 15 Jan 2025: 14 findings, 0 critical; all marked fixed.
Report hosted on quillaudits.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 | 6 |
| Low | 0 | 0 | 7 |
IndexFactory::swap takes in a _swapFee parameter which calls SwapHelpers::swap as poolFee. Now poolFee is checked to be greater than 0 to run the swapVersion3 code block and if it is 0 it will run the swapTokensv2 (else block) instead because as per the NATSPEC comment on the swap function, 2 or 3 is expected to signify v2 or v3 respectively. Only the if block will run in any scenario because poolFee is set to 2 or 3 which is always greater than 0
The failure to disable initializers at the constructor level of the proxy upgradeable contract raises<br>concern as it is susceptible to exploit. This oversight presents the potential of attackers initializing<br>the implementation contract itself.
These contracts implement the pausable functionality that prevents users from calling important en try points in time of emergency. In the IndexFactory, the internal functions (_pause and _unpause) of the Pausable contract were appropriately invoked and the external functions had onlyOwner modifier. However, the implementation is incomplete as the “whenNotPaused” modifier was not attached to any critical functions. This implies that in time of emergency when the admin calls the pause function, the activity of the contract does not exactly pause. Users will proceed with their activity
The mint function of the IndexToken contract has 5 require statements to check for address validity and the supply cap being less or equal to the supplyCeiling, however mintToFeeReceiver() function does not have a similar check for token supply minted. This would make the owner able to mint new tokens above the supplyCeiling set and also cause a DOS the next time an address with MINTER role calls mint() because totalSupply() + amount would already have exceeded the supplyCeiling. If the owner address gets hijacked at any point, the compromised account would be able to mint new tokens without any restrictions leading to economic loss for legitimate users of the protocol.
It was noticed that the minAmountOut is set to zero during interactions with the AMM router (Uniswap) for swaps. These parameters are intended to protect against slippage; setting them to zero exposes transactions to slippage, potentially resulting in receiving or adding smaller amounts than intended.
Identical to swapExactTokensForTokens, but succeeds for tokens that take a fee on transfer - <a href="https://docs.uniswap.org/contracts/v2/reference/smart-contracts/router-02#swapexacttokens" target="_blank">https://docs.uniswap.org/contracts/v2/reference/smart-contracts/router-02#swapexacttokens</a> fortokenssupportingfeeontransfertokens
The Index smart contract integrates Chainlink oracle for price derivation. However, when it fetches the price of a token, it fails to check that the price value is not stale as it is possible for an attacker to manipulate this
Users are allowed to pass in any amount of ETH via msg.value which could be much greater than the needed input amount, and when this happens there would be no way to process a refund.
The current arithmetic implementation for minting tokens to the fee receiver is heavily gas intensive because it performs the arithmetic for compounding with a loop. This would become considerably expensive when the number of days grows to a large number. With current tests, it costs ~500k gas units to call this function when 300 days have passed from the initial feeTimestamp value. Conversely, using a logarithmic approximation for compounding is just as precise with ~80% gas savings
The functionality of the pausable contract does not apply to the mintToFeeReceiver function and allows for the owner to continue token minting to the fee receiver while the contract is paused.
The in-line documentation of the IndexFactory states that users would not be able to pass in external funds via the receive() function but the code implementation in receive() allows for ETH to be sent into the contract without interacting with a payable function. Whereas, the IndexFactoryBalancer contract cannot receive ether which renders the withdraw func tion useless as no other function is marked payable to allow ETH deposits. The withdraw function cannot be called since no ether enters the contract.
The setFeeRate is conditioned to be called after 12 hours from the last time of update. After 12 hours<br>and 59 minutes, it’s impossible to reset the fee rate until 13 hours.
There are mock functions that appear to be used only for testing functionality within the contract because they fill storage variables with dummy data, and can be used as view/pure functions that do not directly affect any other functions
With the use of safeTransferLib, there is assurance of safety of transfer of tokens.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (20)
350 projects reviewed · 459 reports · latest Apr 2025
See QuillAudits’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