<!-- canonical: https://0xsimao.com/reports/vertex -->

# Vertex audit

Three Sigma · Hybrid orderbook DEX · 3rd April 2024

A private security review of Vertex (hybrid orderbook DEX), conducted with Three Sigma and completed on 3rd April 2024 over 40 days. 0xSimao disclosed 24 findings: 4 high severity, 1 medium, 16 low and 3 informational.

## What Vertex is

Vertex is a decentralised exchange built on a hybrid orderbook and AMM model: spot and perpetual markets, lending and borrowing inside one cross-margined clearinghouse, chasing the speed of a centralised venue with on-chain settlement.

## Scope

A fourteen person-week Three Sigma engagement across the core exchange: the clearinghouse, its spot and perpetual engines, the endpoint sequencing layer, margin and liquidation logic, and the ArbAirdrop distribution contract.

## Findings

### High

- [ClearingHouseLiq::_assertLiquidationAmount() may increase basis points due to negative quoteBalance.amount + insurance](https://0xsimao.com/findings/vertex-liquidation-increase-points-insurance)
- [state.cumulativeDepositsMultiplierX18 may become 0 or negative, leading to loss of funds](https://0xsimao.com/findings/vertex-cumulative-deposits-multiplier-become)
- [OffchainExchange::swapAmm() does not validate that txn.priceX18 > 0, allowing donation attacks](https://0xsimao.com/findings/vertex-offchain-validate-price-donation)
- [ClearingHouseLiq::_finalizeSubaccount() does not check if the subaccount has lps](https://0xsimao.com/findings/vertex-liq-finalize-subaccount-lps)

### Medium

- [Missing disableInitializers() call in the constructor](https://0xsimao.com/findings/vertex-disable-initializers-call-constructor)

### Low

- [Verifier::checkQuorum() returns false with more than 3 signers](https://0xsimao.com/findings/vertex-verifier-quorum-false-signers)
- [Downcasting Leads to Silent Overflow](https://0xsimao.com/findings/vertex-downcasting-silent-overflow)
- [isHealthy() Function Always Returns True](https://0xsimao.com/findings/vertex-healthy-function-returns-true)
- [Precision loss due to engines not using .muldiv() when calculating lp ratios](https://0xsimao.com/findings/vertex-precision-engines-muldiv-calculating)
- [Unused argument in Endpoint::registerTransferableWallet()](https://0xsimao.com/findings/vertex-endpoint-register-transferable-wallet)
- [Risk parameters should include additional checks to prevent mistakes](https://0xsimao.com/findings/vertex-parameters-include-additional-mistakes)
- [PerpEngineLp::burnLp() and SpotEngineLp::burnLp() are missing slippage checks](https://0xsimao.com/findings/vertex-perp-burn-spot-slippage)
- [ClearingHouse::addEngine() initializes productEngine, so it may be frontrunned and someone initializes productEngine instead](https://0xsimao.com/findings/vertex-initializes-product-frontrunned-someone)
- [Any user may enforce the referral code of other new users](https://0xsimao.com/findings/vertex-user-enforce-referral-new)
- [txType == TransactionType.ExecuteSlowMode may cause batch of transactions to fail due to _slowModeConfig.txUpTo < _slowModeConfig.txCount](https://0xsimao.com/findings/vertex-transaction-execute-transactions-config)
- [User deposits are exposed to protocol risk before being able to do anything](https://0xsimao.com/findings/vertex-deposits-exposed-protocol-anything)
- [Ratios in PerpEngineLp or SpotEngineLp may be manipulated when the liquidity is low](https://0xsimao.com/findings/vertex-ratios-manipulated-liquidity-low)
- [Reevaluate the Need for renounceOwnership()](https://0xsimao.com/findings/vertex-reevaluate-need-renounce-ownership)
- [Missing pagination for some functions that iterate](https://0xsimao.com/findings/vertex-missing-pagination-functions-iterate)
- [Ownable2Step is preferred over Ownable](https://0xsimao.com/findings/vertex-ownable2-step-preferred-ownable)
- [Missing events](https://0xsimao.com/findings/vertex-missing-events)

### Informational

- [IERC20Base Noncompliant With ERC20 Standard](https://0xsimao.com/findings/vertex-ierc20-noncompliant-erc20-standard)
- [Use of abi.encodePacked() with Dynamic Types](https://0xsimao.com/findings/vertex-encode-packed-dynamic-types)
- [RiskHelper::isoGroup() returns 0, regardless of the passed subaccount](https://0xsimao.com/findings/vertex-helper-iso-group-subaccount)

## The report

[Download the report (PDF)](https://0xsimao.com/reports/2024-04-03-vertex.pdf)
