UnibotX security record

Ethereumunibot.appX

As of 3 Nov 2026, UnibotX has 1 audit report on Trustblock, by Quantstamp, dated 13 Nov 2022. That report lists no open critical findings.

Critical findings
No open critical findings
In 1 report.
Open the latest report
Your label, live
Get the label for your site

Record last updated . It holds audits, findings and contracts up to Nov 2026, and incidents up to Oct 2026. Trustblock does not review code.

Audits1

Newest first

AuditSecurity firmDateScopeCritical findingsReport
UniBot (Diamond Protocol)Security firm: QuantstampDate: Scope: Files named in the reportNo open critical findingsOpen · certificate.quantstamp.com

Findings34

Statuses are the security firm’s own, from each report.

SeverityOpenAcknowledgedFixed
Critical000
High002
Medium108
Low1715
HighInappropriate Validation of Liquidation Fees Can Possibly Lead the Liquidity Pool to Be DrainedUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

`DiamondFactoryV3._closePosition()` Liquidation fees are applied to the amounts returned by `DiamondFactoryV3._removeUniLiquidity()` which are equivalent to the initial want token deposit minus the reserve and the amount borrowed with leverage. For example, assuming a liquidation fee of 5% and a 4x leverage with zero reserve ratio, the final fees applied on the original deposited amount turn out to be close to 20%, which is a high value. The issue described can lead users if liquidation is allowed for non-keeper addresses (owners of the position e.g) or keepers to get back a value even higher than the initial deposit (worst case scenario).

Open the report
HighThe Estimated `amountInWithSlippage` Can Lead `DiamondFactoryV3._trySwapExactOutput()` to Revert when Closing a PositionUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

`DiamondFactoryV3._trySwapExactOutput()` uses the average price tick (`oracleTimeWeightedSec = 900`) to estimate the maximum `quoteAmount` and can be the reason why the swap will possibly throw leading `DiamondFactoryV3._trySwapExactOutput()` to revert due to the requirement stated below: ``` require(_amountIn < amountInWithSlippage, "Slippage protect"); ``` This will cause healthy positions to revert when closing them and possibly turn to unhealthy or even to bad positions. Please note that this issue depends on a random factor (the price volatility during the last `oracleTimeWeightedSec`), and it is hard to predict when a user will be able to claim his position again.

Open the report
MediumAutomatic Max Approval when `lendingPool` Is Set and UpdatedUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

The lending pool used by the contract can be set and updated with the function `setLendingPoolAddress()`. Only the owner of the contract has the right to execute that function. However, if the lending pool is malicious or if it gets exploited, it gets the right to drain all the `borrowToken` owned by the contract.

Open the report
MediumFactory Can Be Prevented From Repaying Borrowed LoansUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

`LendingPoolV3.repayBorrow()` checks if the caller (which should be factory) is in the whitelist. However, if a factory borrows from a lending pool, and then is removed from the whitelist, it will not be able to call `LendinPool.repayBorrow()`.

Open the report
MediumFunctions `init()` Vulnerable to Front-RunningUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

The contracts `DiamondFactoryV3` and `BalanceVaultV3` have no constructor but have a function `init()`. As a result, once the contracts are deployed, everyone can call the function `init()` and become the owner of these contracts.

Open the report
MediumInfinite Loop if a User Has Too Many PositionsUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

The function `_findPositionIndex()` checks with a for loop if a user owns a given position based on its `_positionId`. However, the loop does not use the library `SafeMath` and uses an `uint8` variable which can store a maximum of 256 values. As a result, an overflow can happen on the variable `i`, which would lead to an infinite loop. Such a situation can be mitigated with the state variable `maxPositionNumber` of the contract `DiamondFactoryController`, but there is no upper limit for its value. If `maxPositionNumber` is not set properly, closing a position that has an id higher than 255 will cause the transaction to throw.

Open the report
MediumKeeper Requirement Can Be Bypassed when Liquidating a Position or Executing a Stop LossUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

If a particular position reaches a `healthFactor < 1` it can be liquidated through a call to `DiamondFactoryV3.liquidate()`. This function checks that a caller is registered as a keeper in `DiamondFactoryController` when `requireKeeper` flag is set. However, a user can call `DiamondFactoryV3.closePosition()` on an unhealthy position he owns and bypass the keeper requirement imposed in `liquidate()`.

Open the report
MediumNo Use of Re-Entrancy Guard or Respect of CEI PatternUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

A reentrancy vulnerability is a scenario where an attacker can repeatedly call a function from itself, unexpectedly leading to potentially disastrous results. This is done through a function that does not respect Checks-Effects-Interactions. The [Checks-Effects-Interactions](https://solidity.readthedocs.io/en/latest/security-considerations.html#use-the-checks-effects-interactions-pattern) coding pattern is meant to mitigate any chance of other contracts manipulating the state of the blockchain in unexpected and possibly malicious ways before control is returned to the original contract. As the name implied, only after checking whether appropriate conditions are met and acting internally on those conditions should any external calls to, or interactions with, other contracts be done. All the functions listed below need to have a re-entrancy guard set: - `DiamondFactoryV3.liquidate()` - `DiamondFactoryV3.stopLoss()` - `DiamondFactoryV3.openPosition()` - `DiamondFactoryV3.closePosition()` - `DiamondFactoryV3.addCollateral()` - `DiamondFactoryV3.decreaseCollateral()` - `DiamondFactoryV3.collectFee()` - `DiamondFactoryV3.updateStopLossPrice()` - `BalanceVaultV3.deposit()` - `BalanceVaultV3.withdraw()` - `BalanceVaultV3.transferBalanceFromVault()` - `LendingPoolV3.deposit()` - `LendingPoolV3.withdraw()` Even if a function seems re-entrancy safe due to its interaction with a trusted third-party contract (known token contract, e.g.), it should not be trusted.

Open the report
MediumPossible Sandwich Attack when Opening or Closing a PositionUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

A common attack in DeFi is the sandwich attack. Upon observing a position opening or closing, an attacker can front-run the victim transaction by buying one of the assets, letting the victim execute the transaction, and then executing another trade after the victim by trading back the amount gained in the first trade. In both `DiamondFactoryV3._provideUniLiquidity()` and `DiamondFactoryV3._removeUniLiquidity()` the following parameters are not set: - When minting liquidity: - `MintParams.amount0Min` - `MintParams.amount1Min` - When decreasing liquidity (burning): - `DecreaseLiquidityParams.amount0Min` - `DecreaseLiquidityParams.amount1Min` As a slippage prevention mechanism, the official documentation of Uniswap V3 recommends that non-zero values should be used for the parameters `amount0Min` and `amount1Min` when using in production the functions: - `NonfungiblePositionManager.mint()` https://docs.uniswap.org/protocol/guides/providing-liquidity/mint-a-position#calling-mint ; - `NonfungiblePositionManager.decreaseLiquiditymint()` https://docs.uniswap.org/protocol/guides/providing-liquidity/decrease-liquidity#decrease-liquidity ; This best practice is not respected when the functions are called by the functions `_provideUniLiquidity()` and `_removeUniLiquidity()`.

Open the report
MediumProtocol Solvency Depends on the Availability and Reactivity of the KeepersUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

Keepers play an essential role in the protocol when enabled. They liquidate insolvent positions and activate stop losses when a price tick goes below or above stop loss limits defined by the owners of positions. It implies that the protocol solvency highly depends on a limited set of addresses which could easily become single points of failure. On top of that, the function `removeKeeper()` is used to remove a keeper. However, the fact that the last allowed keeper can be removed is not checked. As a result, the protocol can remain without any keeper.

Open the report
Show 10 more
Low`openPositionMinimumAmount` Cannot Be Updated Once SetUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

The state variable `openPositionMinimumAmount` acts as a lower limit for the number of tokens for a position. It is set in the function `init()`. However, there is no function to update it.

Open the report
Low`Oracle.consult()` Can Revert for some Values of `oracleTimeWeightedSec`UniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

The function `Oracle.consult()` is used to fetch time-weighted average ticks using Uniswap V3 oracle. It uses the state variable `oracleTimeWeightedSec` as a parameter. However, the call will revert if `oracleTimeWeightedSec` is equal to `0` or if it goes beyond the oldest observation recorded in the pool.

Open the report
LowAllowance RemovalUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

`DiamondFactoryV3.setLendingPoolAddress()` approves the borrow token to be spent by the new pool but does not remove the allowance for the previous address. This represents a risk since a compromised pool will still be able to access possible funds on `DiamondFactoryV3` contract address even after removing them.

Open the report
LowAllowing Changing Pool Address Represent a RiskUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

`DiamondFactoryV3.setLendingPoolAddress()` allows changing the lending pool address while the contract is deployed. This seems to introduce unnecessary risk since the new address state might not be the same as the previous one. As a consequence, users will likely not be able to withdraw their assets.

Open the report
LowCollection of Performance Fees by the Protocol Not LoggedUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

Performance fees are collected in the function `collectFee()`. No event is emitted with the number of performance fees that have been collected, which could negatively impact the off-chain monitoring of the protocol.

Open the report
LowConfusing Names of Local Variables in `openPosition()`UniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

The names used for the local variables in the function `openPosition()` are close and also mix expected and actual amounts of both tokens. For example, the variables `_strategyParams.wantTokenAmount` and `wantTokenAmount` are very similar. Also, the variables `usdcLiquidityAmount` and `wethLiquidityAmount` have token names in their names, which is not recommended if the contract is meant to be used for other tokens than USDC and WETH. The impact is that it is hard to check that the function behaves as expected.

Open the report
LowDocumentation Mismatch Between Interface and Implementation ContractsUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

For several functions, there are differences between the documentation in the interface contract and the implementation contract. The description is sometimes more detailed in the interface and sometimes it is the inverse. The impact is that some integrity constraints could be added or ignored, which could ultimately break the interoperability expected from different contracts implementing the same interface. Also, there is no documentation in the interface `IInterestModel`.

Open the report
LowFee Recipient Cannot Be Updated in `LendingPool`UniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

The state variable `feeReceipt` stores the address that will get the fees generated by the contract. Its value is set in the constructor. However, there is no function to update its value. As a result, if the address `feeReceipt` is compromised or blacklisted for the token want, the only way to react would be to set the variable `performanceFee` to 0.

Open the report
LowFunctions `find()` and `get()` with Complex LogicUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

1. The function `find()` of the library `Positions`: - returns `true` if a position exists; - reverts if a position doesn't exist; As a result, it never returns `false` and reverts instead. 2. The function `get()` of the library `Positions` includes an optional check of ownership. However, it does not check if the position does exist. As a result, if the position does not exist, it is possible to: - return an empty position, if `checkOwner == false`; - revert with the incorrect reason `"Invalid position owner"`, if `checkOwner == true`; In both cases, a developer could be misled by the name of these functions if the library is reused in future versions.

Open the report
LowMismatch Between Documentation and Code for Whitelisted FactoriesUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

In the contract `BalanceVaultV3`, it is possible to manage whitelisted addresses with the functions `addWhiteFactory()` and `removeWhiteFactory()`. However, the documentation of these functions states that an address is whitelisted for a given token and the function expects a parameter `_token`, which is not used in the code. Also, the state variable `whiteFactories` does not record which token should be whitelisted for a given factory.

Open the report
Show 5 more
LowMissleading Comments in `DiamondFactoryV3._removeUniLiquidity()`UniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

The following comments in `DiamondFactoryV3._removeUniLiquidity()` seems incorrect: ``` // We charge performance fee based on uniswap fee, but when you removed liquidity // uniswap will not tell you how much fee do you earned. So we have to calculate // how much uniswap fee should we have first. ``` The whole ` IDiamondFactoryHelper(_helper()).getPositionTokenAmount()` is executed to get the fees when only a single call to the line stated below will return the accumulated fees values: ``` (uint256 fee0, uint256 fee1) = PositionValue.fees( INonfungiblePositionManager(UNI_POSITION_MANAGER), _positionId ); ``` The comments are misleading since no real calculations are done to get the fee values.

Open the report
LowTokens Can Get Frozen in ContractsUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

The contracts do not have specific functions to pull tokens or ETH sent on purpose or by mistake.

Open the report
LowUse of Unchecked Arithmitic OperationsUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

`InterestModal` execute multiple arithmetic operations without the use of any safe math library or a solidity version greater than `0.8.0`. Unchecked arithmetic operations can lead to overflows and possible exploits.

Open the report
LowUsing Non-Standard ERC20 Can Disrupt Internal AccountingUniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

In the contract `BalanceVaultV3`, four functions are used by the contract to receive or transfer funds: `deposit()`, `withdraw()`, `transferBalanceFromVault()`, `transferBalanceToVault()`. Tokens received are owned by the contract and the internal accounting of which address owns which amount of token is stored in the state variable `balances`. However, that state variable is updated based on the amount that is expected to be transferred, instead of based on what has been received. As a result, if the contract used an ERC20 where the amount to transfer is different than the amount received (greater or lower), the internal accounting of the contract would be broken and users could claim more or less than the actual amount of tokens owned by the contract.

Open the report
LowVariable `tokenDecimalDiff` Not Used in `DiamondFactoryV3`UniBot (Diamond Protocol) · Quantstamp · 13 Nov 2022Fixed

The state variable `tokenDecimalDiff` is set in the function `init()`. However, it is not used in the contract.

Open the report

Contracts

No deployed address is recorded for these audits.

The reports name a repository or files. Open a report to see its scope.

The repositories and files the reports name

Show this on your site

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.

Content

Facts

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.

Fixed as
Language

Style

Layout
Theme
Accent
Corners

Format

Size
Date
Embed as
HTML
<head>
<script src="https://widget.trustblock.run/project-widget.min.js" defer></script>
</head>
<body>
<div
data-tb-project-widget
data-tb-project-slug="unibot"
></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