Cadabra security record

Arbitrum, BNB Chain, Ethereumcadabra.financeXGitHub

As of 21 Oct 2026, Cadabra has 2 audit reports by 2 security firms on Trustblock; the latest is by PeckShield, dated 22 Nov 2023. Those reports list no open critical findings.

Critical findings
No open critical findings
Across 2 reports.
Open the latest report
Your label, live
Get the label for your site

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

Audits2

Newest first

AuditSecurity firmDateScopeCritical findingsReport
Cadabra auditSecurity firm: PeckShieldDate: Scope: Not recorded (see the report)No open critical findingsOpen · GitHub
Cadabra FinanceSecurity firm: CertiKDate: Scope: Files named in the reportNo open critical findingsOpen · skynet.certik.com

Findings25

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

SeverityOpenAcknowledgedFixed
Critical000
High302
Medium103
Low4012
HighForced Investment Risk in BalancerUpgradeable and VelodromPoolAdapterCadabra audit · PeckShield · 22 Nov 2023Fixed

The report gives no description here.

Open the report
HighIncorrect Value Calculation in VelodromPoolAdapter_qStablePairCadabra audit · PeckShield · 22 Nov 2023Fixed

The report gives no description here.

Open the report
MediumIncorrect Redeem Slippage Control Enforcement in RouterCadabra audit · PeckShield · 22 Nov 2023Fixed

The report gives no description here.

Open the report
MediumIf `sqrtPriceX96` Is Greater Than Maximum `uint12Cadabra Finance · CertiK · 22 Aug 2023Fixed

If the `sqrtPriceX96` is greater than the maximum `uint128`, that is `2^128 - 1`, then when the following logic is reached it will revert due to overflow: ```solidity uint256 priceX192 = uint256(sqrtPriceX96) * uint256(sqrtPriceX96); ``` Thus in this scenario when the function `value()` is called on the `ThenaGammaToken0TWAPAdapter` it will revert, which will make it impossible for users to invest or redeem.

Open the report
MediumIssue With `ASSEST_OFFSET`Cadabra Finance · CertiK · 22 Aug 2023Fixed

The `SUPPLY_OFFSET` and `ASSEST_OFFSET` are set to be `1e18`, which creates `1e18` virtual shares and `1e18` virtual assets. As the amount of virtual assets is greater than 1, it allows for the possibility that a user will redeem for more assets than they should be entitled to, or it may revert as it may overestimate the actual amount of assets held by the contract. This is because when shares are redeemed for assets the following equation is used: $$ \frac{shares * (nav + 1e18)}{totalSupply() + 1e18} $$ rearranging this gives $$ \frac{shares}{totalSupply() + 1e18} * (nav + 1e18) $$ If the total supply is redeemed at once this equation becomes $$\frac{totalSupply}{totalSupply() + 1e18} * (nav + 1e18) < nav + 1e18$$ However as the fraction $\frac{totalSupply}{totalSupply() + 1e18}$ converges to 1 as the total supply increases, this value may exceed the value of `nav`. Thus allowing for some of the locked profit or fees to be given when redeeming or if the entire total supply is redeemed and there are no locked fees it will cause it to revert due to a lack of funds.

Open the report
Low`getSqrtTwapX96()` Does Not Alway Round Towards NCadabra Finance · CertiK · 22 Aug 2023Fixed

In the contract `TwapUtils`, the function `getSqrtTwapX96()` has the following logic: ```solidity sqrtPriceX96 = TickMath.getSqrtRatioAtTick( int24((tickCumulatives[1] - tickCumulatives[0]) / SafeCast.toInt56(SafeCast.toInt256(uint256(twapInterval)))) ); ``` However, if the difference `tickCumulatives[1] - tickCumulatives[0]` is negative, then when dividing by the `twapInterval` it will not round towards negative infinity. (For example -10/3 = -3 as opposed to -4) This means that the tick with the slightly higher price will be chosen in this scenario.

Open the report
LowImplement Prior To Deploying To A Layer 2Cadabra Finance · CertiK · 22 Aug 2023Fixed

In the contact `ChainLinkLib`, there a `TODO` comment as follows: ```solidity // TODO: L2 https://twitter.com/bytes032/status/1653943092427325448 // https://docs.chain.link/data-feeds/l2-sequencer-feeds ``` The first link addresses the potential problem of a sequencer going offline, while the second provides guidance on properly handling this issue for Arbitrum, Optimism, and Metis L2 chains.

Open the report
LowLocked Profit May Exceed Value Causing UnexpectedCadabra Finance · CertiK · 22 Aug 2023Fixed

The locked profits and fees are fixed and will not change in value as the invested tokens may. Thus if the invested tokens decrease dramatically in value, then the locked profits may exceed the total value of the adapters and cause calls to `_totalNAV()` to revert when the operation `value - lockedProfit` is performed.

Open the report
LowMissing Emit EventsCadabra Finance · CertiK · 22 Aug 2023Fixed

There should always be events emitted in the sensitive functions that update important states.

Open the report
LowNon-descriptive Revert If `feed.decimals()` Is GrCadabra Finance · CertiK · 22 Aug 2023Fixed

If a chainlink feed uses more than 18 decimals, when `scaleFactor` is computed it will revert due to underflow. While most chainlink feeds use 8 or 18 decimals, it is possible for a feed with more than 18 decimals to be created and used in the future.

Open the report
Show 7 more
LowPotential Division by ZeroCadabra Finance · CertiK · 22 Aug 2023Fixed

In the contract `LiquidityUtils` if the `reserve0` or `reserve1` is 0, then the function `ratio2` may unexpectedly revert due to a division by 0.

Open the report
LowPotential Locked TokensCadabra Finance · CertiK · 22 Aug 2023Fixed

There is no method to recover tokens other than the `depositTokens()` that are accidentally sent to an adapter, causing them to be lost forever. As the swaps are input manually, it is possible that an incorrect token will be swapped for and sent to the adapter or users may accidentally send the wrong token directly to the adapter. In addition, in the contract `BalancerUpgradeable` in the function `rebalance()`, when `redeem()` is called the redeemed tokens are sent to `address(this)` and when `invest()` is called the dust is sent to `address(this)`. This allows for tokens to potentially be left in the `BalancerUpgradeable` contract.

Open the report
LowPotential Rate ManipulationCadabra Finance · CertiK · 22 Aug 2023Fixed

The following comment is not correct in all possible cases ```solidity // shouldn't be susceptible to inflation attacks, since `valuePrior` can only increase through adding shares (???) ``` The `valuePrior` is determined by the `value()` returned by the adapter, which may depend on the value returned from an oracle, its balances stored in other contracts, or the balance of a certain token. These values may be able to be manipulated by an attacker. In general, the `value()` heavily depends on the adapter implementation.

Open the report
LowPotential To Run Out Of GasCadabra Finance · CertiK · 22 Aug 2023Fixed

Many of the for loops execute functions that take a significant amount of gas, if enough adapters, swaps, or transfers are used the transaction may exceed the block gas limit.

Open the report
LowTypos and InconsistenciesCadabra Finance · CertiK · 22 Aug 2023Fixed

In the contract `BalancerUpgradeable`: - The comment for the constant `REBALANCE_COOLDOWN` says "1 hour", when it is set to 6 hours. In the contract `ThenaGammaAdapter`: - The comment "// doesn't really mater what is `to` argument, shares are always issued to msg.sender" is not consistent with the functionality. The `to` argument indicates who the shares will be minted to and is not necessarily minted to the message sender.

Open the report
LowUnnecessary `receive()` FunctionCadabra Finance · CertiK · 22 Aug 2023Fixed

This contract does not contain any method to remove native tokens from the contract. This will cause any native token sent to the contract through the `receive()` function to be permanently lost.

Open the report
LowUnnecessary VariablesCadabra Finance · CertiK · 22 Aug 2023Fixed

In the contract `TwapUtils`, the function `getSqrtTwapX96` performs the following logic: ```solidity if (twapInterval == 0) { uint32[] memory secondsAgos = new uint32[](1); secondsAgos[0] = 0; (sqrtPriceX96,,,,,,) = IPool(uniswapV3Pool).globalState(); } ``` However, the array `secondsAgos` is defined and initialized, but never used. If the `twapInterval` is 0, then it should fetch the current price, which can be done by reading it from the global state without the need for the `secondsAgos` array.

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="cadabra-finance"
></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