Arkis security record

As of 21 Oct 2026, Arkis has 2 audit reports by 2 security firms on Trustblock; the latest is by Cantina, dated 8 May 2025. 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
arkis-smart-contractsSecurity firm: CantinaDate: Scope: Not recorded (see the report)No open critical findingsOpen · cantina.xyz
ArkisSecurity firm: QuantstampDate: Scope: Files named in the reportNo open critical findingsOpen · certificate.quantstamp.com

Findings25

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

SeverityOpenAcknowledgedFixed
Critical000
High001
Medium046
Low0311
HighMissing checkpoint on APY change will create unfair interest and rewardsarkis-smart-contracts · Cantina · 8 May 2025Fixed

The report gives no description here.

Open the report
MediumLenders will lose everything if they get removedarkis-smart-contracts · Cantina · 8 May 2025Fixed

The report gives no description here.

Open the report
MediumMissing executor/clipperExchange check could result in malicious commandarkis-smart-contracts · Cantina · 8 May 2025Fixed

The report gives no description here.

Open the report
MediumMissing slippage check on curve's remove liquidityarkis-smart-contracts · Cantina · 8 May 2025Fixed

The report gives no description here.

Open the report
MediumDebt Entries Can Be OverwrittenArkis · Quantstamp · 12 Jan 2024Fixed

Part of the execution flow of `Fund.forward()` involves calling `MoneyAccount.spendMoney(amount, reward, block.timestamp)`, where `block.timestamp` serves as a nonce. If `spendMoney()` is called more than once in the same block with identical parameters, any child calls to `createDebtIfNecessary()` will overwrite previous debt entries, and not all debt will be accounted for. This is in part because the `block.timestamp` acts as a salt rather than a true nonce.

Open the report
MediumFaulty Accounting when Claiming Rewards for Mutiple EpochsArkis · Quantstamp · 12 Jan 2024Fixed

Liquidity Providers accumulate rewards across epochs. Rewards are recalculated and distributed when they interact with the Pool. If it has been several epochs since the user last interacted with the pool, the function `calculateUserRewardsForTheWholeNumberOfEpochs()` calculates the rewards for elapsed epochs by applying the average TPS of the epochs across the elapsed time. However, the calculation assumes that each epoch is identical in length. Rewards should be distributed in proportion with the length of the epoch.

Open the report
MediumUsers Could Lose Rewards Due to Missing Check in `RewardsMath`Arkis · Quantstamp · 12 Jan 2024Fixed

The function `RewardsMath.increaseInterest()` updates the state `Staking.TPSS` by adding to it a factor based on the input `_rewardsAmount`, as seen in the following line: `self.TPSS += uint240((_rewardsAmount * TPSS_DENOMINATOR) / (self.tokenVolume))`. Afterwards, a new epoch is started and a few state variables are updated in the subsequent call to `startNewEpoch()` as seen below: ``` function startNewEpoch(Staking storage self, uint256 passingEpochTPSS) private { self.linkedListTPSS[passingEpochTPSS] = self.TPSS; self.tokenVolume = 0; self.epochStartTime[self.TPSS] = block.timestamp; self.numberOfEpochs++; } ``` If the value of `_rewardsAmount` is zero, then the “new” TPSS will be the same as the old one which leads to two errors: 1. The linked list will be pointing to itself `self.linkedListTPSS[passingEpochTPSS] = self.TPSS` since `passingEpochTPSS` is equal to `self.TPSS`. 2. The epoch start time of `self.TPSS` will be overwritten with a newer timestamp. **Impact** 1. **Users would get zero rewards from the incomplete first epoch**. The function `calculateUserRewardsForIncompleteFirstEpoch()` calculates the rewards based on the multiplicative factor `userFirstEpochTPSS = nextEpochTPSS - depositEpoch.TPSS`. Any user with `depositEpoch.TPSS` equal to the old `self.TPSS` would get a factor zero and therefore zero rewards. 2. **Users would get the wrong rewards from the complete epochs**. The function `calculateUserRewardsForTheWholeNumberOfEpochs()` calculates the rewards based on the multiplicative factor `tpsForTheRemainingEpochs = ((lastRewardTime - ufeEndTime) * (self.TPSS - nextTPSSFromUserDepositEpoch)) / numberOfWholeUserEpochs`. There are three members in this equation: `numberOfWholeUserEpochs` would be the correct since it was updated correctly in `startNewEpoch()`. However: * `A = (lastRewardTime - ufeEndTime)` where `ufeEndTime = self.epochStartTime[nextTPSSFromUserDepositEpoch]`. The timestamp in `ufeEndTime` would be newer (greater) than what it should be which leads to a difference lower that expected. * `B = (self.TPSS - nextTPSSFromUserDepositEpoch)`. If we assume the value of `self.TPSS` cannot be increased to compensate for that repeated update, then the current value of `self.TPSS` and `nextTPSSFromUserDepositEpoch` could more or less compensate each other resulting in the expected value of `B`. However, if the error of updating `TPSS` with the same old value happens multiple times, factor `B` would be lower than expected. On the other hand, if the value of `self.TPSS` can indeed by increased to compensate for that repeated updated, then the value of `B` could be greater than expected and this could compensate to some extent the lower value from `A`. However, it would still result in the wrong values. Any user with `depositEpoch.TPSS` equal to the old `self.TPSS` could get a different reward amount which could potentially reduce the amount of available tokens for other users.

Open the report
LowThe PendleValidatorMisc will revert if ETH is neededarkis-smart-contracts · Cantina · 8 May 2025Fixed

The report gives no description here.

Open the report
Low'Dead' CodeArkis · Quantstamp · 12 Jan 2024Fixed

Dead code should be avoided since it might consume more resources during development, testing, and compilation without contributing to the software's functionality. It makes the codebase harder to understand and may mislead developers, leading to potential bugs or wasted time. In the case of solidity, it might also increase the bytecode size increasing deployment costs. The following is a non-exhaustive list of dead or unused code instances: 1. The contract `ConvexFiImmutableState` is never imported or used anywhere in the codebase. 2. The variable `borrower` in the `AccountFactory` contract is private and is not used anywhere in the contract. 3. The abstract contract `InternalModifierDS` is never imported or used anywhere in the codebase.

Open the report
LowChecks-Effects-Interactions Pattern ViolationArkis · Quantstamp · 12 Jan 2024Fixed

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. The function `Pool.deposit()` updates the state through `staking.increasePosition()` after doing the external call `token.transferFrom()`.

Open the report
Show 8 more
LowCompliance May Be Bypassed for CurveArkis · Quantstamp · 12 Jan 2024Fixed

To add liquidity to Curve, it is required that the protocol is supported, but to withdraw or exchange it may be either supported or suspended. The curve function `Swaps.exchange_multiple` takes a `_swap_params` argument that determines the swap type. If the argument passed is `7, 8, 9, 10` or `11` then the swap will call `add_liquidity()` and add liquidity to the pool. The compliance check for `exchange_multiple()` on Arkis does not check the `_swap_params` so it may be used to add liquidity to Curve should it ever become suspended.

Open the report
LowFetch Once and Reuse to Improve Gas ConsumptionArkis · Quantstamp · 12 Jan 2024Fixed

The following are some opportunities for gas savings: 1. `ProtocolsRepository.updateProtocolSupport()` fetches the given protocol twice instead of once and reusing it. The condition in the `else if` branch can just call `prot.status` instead of `protocol(_protocol).status`. 2. `DebtManager.tryRepay()` calls `self.peek()` twice in stead of once and reuse it. The body of the `if` branch could just call `debt.partialRepay()` instead of using `self.peek().partialRepay()`. 3. `RewardsMath.calculateNewUserVolume()` fetches `depositEpoch.timeWhenUserVolumeWasLastUpdated` twice instead of once and reusing it.

Open the report
LowInconsistent Naming Hinders Code Comprehension & CollaborationArkis · Quantstamp · 12 Jan 2024Fixed

Having two classes or files with the same name should be avoided since it causes ambiguity, confusion, and potential naming conflicts. It also compromises code readability, comprehension, and collaboration. There are two structs called `Debt` in the codebase: the first struct is defined in `interfaces/liquidityManagement/insuranceFund/Debt.sol`, and the second is defined in `liquidityManagement/liquidityPool/libraries/DebtManager.sol`. Additionally, there are two files called `Debt.sol`: the one already mentioned and `liquidityManagement/insuranceFund/libraries/Debt.sol`.

Open the report
LowLiquidity Providers Can Lose Tokens Due to Unsafe CastingArkis · Quantstamp · 12 Jan 2024Fixed

The `DebtLibrary.createDebt()` function returns a new `Debt` object with the debt amount and rewards. However, these two values are cast from `uint256` to `uint128` without making sure that the values fit in 128 bits. This could potentially lead to the `Fund` forwarding less than it should to its corresponding `Pool` which means that users might end up with fewer tokens than deposited, and also fewer rewards.

Open the report
LowMissing Input ValidationArkis · Quantstamp · 12 Jan 2024Fixed

It is important to validate inputs, even if they only come from trusted addresses, to avoid human error. The following is a non-exhaustive list of inputs that should be validated: 1. `Account.constructor()`: Validate that the `_marginEngine` is not `address(0)` since it is an immutable variable and would need to be redeployed otherwise. 1. `CurveFiLiquidityPoolsRepository.initializePool()`: Validate that the pool has the specified `numberOfTokens`. 1. `CommandSafeExecutor.constructor()`: Validate that `compliance` is not `address(0)` since it is an immutable variable and would need to be redeployed otherwise. 1. `Fund.initialize()`: Validate that the `debtAdmin` is a non-zero address. 1. `ProtocolsRepository.updateProtocolSupport()`: Validate that `_protocol` is a non-empty string. 1. `ProtocolsRepository.updateOperatorSupport()`: Validate that `_protocol` is a non-empty string. 1. `PoolFactory.createPool()` and `Pool.initialize()`: Neither function validates the borrower and token address against `address(0)`. There is also no validation on `thresholdOnTotalDeposit_` making it possible for it to be zero. All three values are only set during the initialization of the pool and cannot be set later on. A wrong configuration would mean redeploying the pool.

Open the report
LowMissing Whitelist EnforcementsArkis · Quantstamp · 12 Jan 2024Fixed

We uncovered a few issues relating to whitelisting/permissions of different protocol interactions. 1. `UniswapV3Evaluator.evaluate(address, ExchangeRequest)` enforces that both the input token and output token are supported. Requiring that the input token be supported (rather than supported or suspended) may prevent favorable trades when liquidating margin accounts. Given that other dexes without this restriction are available, the issue has been marked as Informational severity. 2. The `CurveFiValidatorPlainPool.remove_liquidity()` checks that the pool coins are supported or suspended before creating the `Command` to remove liquidity. However, no token validation is done when adding liquidity. 3. The documentation states the following regarding whitelist enforcements for exchanges: > For exchange: `operator`, `pool` and `input token` MAY be either supported or suspended, but `output token` MUST be supported. However, `CurveFiEvaluator.evaluate(address, ExchangeRequest)` does not enforce that the output token is supported.

Open the report
LowTrapped Tokens in ConvexFiArkis · Quantstamp · 12 Jan 2024Fixed

If a user is liquidated, their Convex positions are assumed to be staked into the `RewardPool` or `Booster`. However, it is possible that the user has Deposit Tokens that have not been staked. Liquidating these tokens would require a tedious process as they will be omitted by the `DecreasePositionRequest`.

Open the report
LowUnlocked PragmaArkis · Quantstamp · 12 Jan 2024Fixed

Every Solidity file specifies in the header a version number of the format `pragma solidity (^)0.8.*`. The caret (`^`) before the version number implies an unlocked pragma, meaning that the compiler will use the specified version _and above_, hence the term "unlocked".

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="arkis"
></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