Illuvium security record

As of 21 Oct 2026, Illuvium has 6 audit reports by 4 security firms on Trustblock; the latest is by Cyfrin, dated 21 Oct 2025. Those reports list no open critical findings.

Critical findings
No open critical findings
Across 6 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.

Audits6

Newest first

AuditSecurity firmDateScopeCritical findingsReport
Illuvium Staking V3 Audit ReportSecurity firm: CyfrinDate: Scope: Not recorded (see the report)No open critical findingsOpen · GitHub
Illuvium Land Sale ProtocolSecurity firm: CertiKDate: Scope: Files named in the reportNo open critical findingsOpen · skynet.certik.com
Illuvium auditSecurity firm: PeckShieldDate: Scope: Not recorded (see the report)No open critical findingsOpen · GitHub
Illuvium (Part 4 - Staking V2)Security firm: QuantstampDate: Scope: Files named in the reportNo open critical findingsOpen · certificate.quantstamp.com
Illuvium Yield Farming RewardsSecurity firm: QuantstampDate: Scope: Files named in the reportNo open critical findingsOpen · certificate.quantstamp.com
Illuvium ERC20Security firm: QuantstampDate: Scope: Files named in the reportNo open critical findingsOpen · certificate.quantstamp.com

Findings60

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

SeverityOpenAcknowledgedFixed
Critical000
High022
Medium205
Low21037
HighMissing function callIlluvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

The comment on the following line is not implemented; only one value (`subVaultRewards `) is updated. ``` // subYieldRewards and subVaultRewards needs to be updated on every `_processRewards` call user.subVaultRewards = uint256(user.totalWeight).weightToReward(vaultRewardsPerWeight); ```

Open the report
HighUniswap Call Susceptible To Price Manipulation AttacksIlluvium Yield Farming Rewards · Quantstamp · 14 Aug 2021Fixed

The function `swapEthForIlv` uses Uniswap to exchange ETH for ILV tokens. The function is declared public with no access control. If the contract holds a large amount of ETH, attackers can manipulate (likely using flash loans) the Uniswap ETH/ILV price such that the `IlluviumVault` will receive an unfavorable amount of ILV. Further, computing `ilvOut` in the function leaves it susceptible to [sandwich attacks](https://medium.com/coinmonks/demystify-the-dark-forest-on-ethereum-sandwich-attacks-5a3aec9fa33e).

Open the report
MediumProper Migration in CorePool::moveFundsFromWallet()Illuvium audit · PeckShield · 19 Mar 2022Fixed

The report gives no description here.

Open the report
MediumUnchecked Return ValuesIlluvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

The function `stake` calls `transferFrom` but ignores the return value; function `unstake` calls `transfer` and also ignores the return value.

Open the report
MediumUnlimited ApprovalsIlluvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

In `sendILVRewards`, there are approvals with `type(uint256).max` which is dangerous if something goes wrong.

Open the report
MediumPotentially Lost RewardsIlluvium Yield Farming Rewards · Quantstamp · 14 Aug 2021Fixed

The `_processVaultRewards` function inside `IlluviumCorePool` and in `IlluviumLockedPool` will not give users the full amount of the reward they are entitled to, when `pendingVaultClaim > poolTokenReserve`. Moreover, the function will also stop the users from requesting for the missing amount afterward. Hence the users will lose rewards.

Open the report
MediumPotentially Uncounted RewardsIlluvium Yield Farming Rewards · Quantstamp · 14 Aug 2021Fixed

The `IlluviumPoolBase._updateStakeLock` function does not flush rewards before changing the value of `user.totalWeight`. This may lead to incorrect reward amounts subsequently.

Open the report
LowCalling StakingVault::notifyRewardAmount on empty vault leaves ILV stuckIlluvium Staking V3 Audit Report · Cyfrin · 21 Oct 2025Fixed

The report gives no description here.

Open the report
LowDeployment script requires unencrypted private keyIlluvium Staking V3 Audit Report · Cyfrin · 21 Oct 2025Fixed

The report gives no description here.

Open the report
LowDistributor can over-allocate claimables, causing temporary claim DoSIlluvium Staking V3 Audit Report · Cyfrin · 21 Oct 2025Fixed

The report gives no description here.

Open the report
Show 10 more
LowDust amounts of rewards get stuck in the VaultIlluvium Staking V3 Audit Report · Cyfrin · 21 Oct 2025Fixed

The report gives no description here.

Open the report
LowDust rewards can become permanently lockedIlluvium Staking V3 Audit Report · Cyfrin · 21 Oct 2025Fixed

The report gives no description here.

Open the report
LowEqual distribution fallback logic errorIlluvium Staking V3 Audit Report · Cyfrin · 21 Oct 2025Fixed

The report gives no description here.

Open the report
Low`_pauseDuration` Incorrectly EmittedIlluvium Land Sale Protocol · CertiK · 18 May 2022Fixed

In the function `initialize()`, when the sale is in paused state, the value of `_pauseDuration` will be incorrectly emitted in the `Resumed` event.

Open the report
LowHardcoded Oracle Answer Update TimeframeIlluvium Land Sale Protocol · CertiK · 18 May 2022Fixed

The oracle update timeframe is hardcoded as 30 days, which lacks of readability and maintenance

Open the report
LowLack of Input ValidationIlluvium Land Sale Protocol · CertiK · 18 May 2022Fixed

in `setMetadata()`, there are no input validations on `Site Type` and `Landmark Type ID`, where - `Site Type` must be in the range of [1, 6] - `Landmark Type ID` must be in the range of [0, 7]

Open the report
LowMissing Emit EventsIlluvium Land Sale Protocol · CertiK · 18 May 2022Fixed

There should always be events emitted in the sensitive functions that are controlled by centralization roles.

Open the report
LowMissing Error MessagesIlluvium Land Sale Protocol · CertiK · 18 May 2022Fixed

The **require** can be used to check for conditions and throw an exception if the condition is not met. It is better to provide a string message containing details about the error that will be passed back to the caller.

Open the report
LowRequisite Value of ERC-20 `transferFrom()` / `traIlluvium Land Sale Protocol · CertiK · 18 May 2022Fixed

While the ERC-20 implementation does necessitate that the `transferFrom()` / `transfer()` function returns a `bool` variable yielding `true`, many token implementations do not return anything i.e. Tether (USDT) leading to unexpected halts in code execution.

Open the report
LowProper Stake Weight Calculation in CorePool::stake()Illuvium audit · PeckShield · 19 Mar 2022Fixed

The report gives no description here.

Open the report
Show 10 more
LowTimely Pool Update Upon Weight Change in CorePool/FlashPoolIlluvium audit · PeckShield · 19 Mar 2022Fixed

The report gives no description here.

Open the report
LowEvent `LogMigrateUser` Could Present More InformationIlluvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

The function `migrateUser(...)` contains the following: `emit LogMigrateUser(msg.sender, _to)`. Perhaps adding more information to this log would help in future investigations.

Open the report
LowExternal Functions of `ILVPool.sol` can be Called by AnyoneIlluvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

The functions from this file can be called by anyone. However, the code comment states that “External `MigrateLockedStakes` call, [is] used in Sushi LP pool”.

Open the report
LowIncorrect `paramIndex`Illuvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

In `CorePool.sol`, lines 274 and 275 `paramIndex` for `_initTime` and `_weight` are off-by-one. Similarly, line 40 in `VaultRecipient.sol` has an incorrect `paramIndex`.

Open the report
LowIncorrect and Unclear `Keccak256`Illuvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

In `ILVPool.sol`, the hash comment `bytes4(keccak256("_migrateYieldWeights(bytes32[],uint256,uint256")))` in function `_migrateYieldWeights` does not have the closing bracket for `_migrateYieldWeights` inside the quote. In `CorePool.sol`, the hash `0x867a0347` is not explained when it should be.

Open the report
LowIndistinguishable Return ValueIlluvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

In `getV1StakePosition`, the value zero is returned if the stake id provided is not found. However, this value is also returned if the stake is the first entry.

Open the report
LowOwnership can be RenouncedIlluvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

All files that inherit from the `Ownable` contract could be left with no owner if the latter renounces his ownership. As one potential consequence, that could prevents update to the deployed contracts, requiring re-deploys and potential downtime.

Open the report
LowPoorly Named Function: `CorePool.migrateUser(…)`Illuvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

The function `migrateUser(...)` is related to migrations of wallets of the same user, and not migrating users from V1 to V2. Thus, we encourage the team to provide a better name for this function.

Open the report
LowReview the Visibility of State VariablesIlluvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

The proper declaration of the visibility of state variables is a good programming practice and it also reduces the final contract size. Public variables increase the contract size:for each public variable, the solidity compiler automatically generates the `getter` and `setter`[functions](https://docs.soliditylang.org/en/v0.6.10/contracts.html#visibility-and-getters). For instance, we do not see a reason for declaring the following state variables as `public` in `Vault.sol`: - `Pools public pools;` - `IUniswapV2Router02 public sushiRouter` and - `IERC20 public ilv`.

Open the report
LowState Variables can Change when the Contract is PausedIlluvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

The functions `migrateUser(...)`, `sync()`, `receiveVaultRewards(...)`, `setWeight(...)`, and `pendingRewards(...)`can be called when the contract is paused. This can be dangerous since they change state variables.

Open the report
Show 10 more
LowSuboptimal CodeIlluvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

The contract size can be optimized by turning `modifiers` into `functions`, as shown in the example below: ``` modifier checkStuff() {} function doSomething() checkStuff {} ``` The `function doSomething()` can rewritten without modifiers as: ``` function checkStuff() private {} function doSomething() { checkStuff(); } ```

Open the report
LowUnrestricted `endTime`Illuvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

In `setEndTime`, there is no sanity checks for the new value. It could be before the current time, or interact with existing pools in unexpected ways.

Open the report
LowUnsafe CastIlluvium (Part 4 - Staking V2) · Quantstamp · 17 Mar 2022Fixed

The function `unstake` in `FlashPool.sol` converts a `uint256` to a `unit128` without checking that the cast is safe. Similar issues - with as small a bit width as 64 - exist elsewhere in the contract. These issues are found in `CorePool.sol` as well.

Open the report
Low`swapEthForIlv` Reverts On Zero ETH BalanceIlluvium Yield Farming Rewards · Quantstamp · 14 Aug 2021Fixed

If the ETH balance of `IlluviumVault` is zero (possibly due to a previous call to either `swapEthForIlv` or `sendIlvRewards`), the function will revert due to the check `balance > 0` on L159. However, since `swapEthForIlv` is public, a legitimate call to `sendIlvRewards` could be griefed by any user if they front-run with a call to `swapEthForIlv`.

Open the report
LowInconsistent Initialization StepsIlluvium Yield Farming Rewards · Quantstamp · 14 Aug 2021Fixed

According to the inline documentation, step 2 should invoke `setPool`, and step 3 sets balances (through potentially multiple calls to `setBalances`). However, the function `setBalances` requires on L164 that `address(pool) == address(0)`, so step 3 cannot occur after step 2. The steps on L17-20 appear correct, but L126 and L149 do not align with this summary.

Open the report
LowMisaligned Code And CommentsIlluvium Yield Farming Rewards · Quantstamp · 14 Aug 2021Fixed

In the `IlluviumCorePool.stakeAsPool` function on L155 code comment says that the `_useSILV` should be `false`, however it's not in the case on L165 where the 2nd parameter passed to the `_processRewards` function, which represents the value of `_useSILV` is hardcoded to `true`.

Open the report
LowMissing invariant checksIlluvium Yield Farming Rewards · Quantstamp · 14 Aug 2021Fixed

Assumptions about intermediate values during function processing should be explicitly checked, especially if these values depend on outputs returned by external contract calls. For example, we assume that the value of `stakeWeight` on L420 inside of `IlluviumPoolBase._stake()` should be greater than zero. Otherwise, it doesn't make sense to create a deposit with `stakeWeight == 0`. <br><br> Note that this is one example of what we assume to be an implicit assumption, however, all implicit assumptions should be checked in a similar way.

Open the report
LowMissing Or Insufficient Input ValidationIlluvium Yield Farming Rewards · Quantstamp · 14 Aug 2021Fixed

The following instances of missing or insufficient input validation have been encountered: 1. The `_pool` parameter of the of the `TokenLocking.setPool()` function is not checked to conform to the `ILockedPool` interface and could be any address. 2. The `_rewardsAmount` parameter of the `IlluviumLockedPool.receiveVaultRewards()` function is not checked to be greater than zero. The same applies to the function with the same name in other contracts. 3. The `_from` and `_to` parameters of `IlluviumLockedPool.changeLockedHolder()` are not checked to be different. This could lead to deleting a holder. 4. The `_vault` parameter of `IlluviumCorePool.setVault()` is not checked to be different from `address(0)`. 5. The `_weight` parameter of `IlluviumPoolBase.setWeight()` is not checked to be greater than zero. Note that this is not an exhaustive list. User inputs should always be validated.

Open the report
LowTotal Balances Set Larger Than IntendedIlluvium Yield Farming Rewards · Quantstamp · 14 Aug 2021Fixed

The `TokenLocking.setBalances()` function may be called multiple times in order to "allow setting balance to zero in case of accidental addition of the holder". However, due to missing checks/assertions there exists a possibility for human error which could lead to unlocking a total balance larger than intended.

Open the report
LowUnclear ILV Token Bookkeeping For ILV/ETH Pair PoolIlluvium Yield Farming Rewards · Quantstamp · 14 Aug 2021Fixed

In `IlluviumCorePool.sol` on L30, the comment states that `poolTokenReserve` is the "Total value of ILV tokens available in the pool". However, while functions such as `IlluviumCorePool.receiveVaultRewards` only increase `poolTokenReserve` when `poolToken == ilv`, this is not the case for functions such as `IlluviumCorePool._stake`. For example, if the `poolToken` is `ILV/ETH Pair`, the `poolTokenReserve` is still increased on L205, even though pair tokens are staked (not ILV). This makes the computation in `IlluviumVault.sendIlvRewards` of `ilvInPairPool` unclear: ``` uint256 ilvInPairPool = (pairPoolReserve.mul(ilv.balanceOf(address(ilvEthPair))).div(ilvEthPair.totalSupply())).add( pairPoolIlvBalance ); ``` In particular, the expression `(pairPoolReserve.mul(ilv.balanceOf(address(ilvEthPair))).div(ilvEthPair.totalSupply()))` seems to suggest that `pairPoolReserve` should store the amount of `ILV/ETH Pair` tokens in the `ILV/ETH Pair` pool, *NOT* the ILV balance itself. With the current setup, it appears that the `ilvInPairPool` computation above will double-count some tokens, since `pairPoolReserve` is increased for both `ILV` and `ILV/ETH Pair` deposits. This will inflate the weight associated with the `ILV/ETH Pair` pool.

Open the report
Show 4 more
LowUnused FunctionsIlluvium Yield Farming Rewards · Quantstamp · 14 Aug 2021Fixed

The `now256()` and `blockNumber()` functions declared on L235 and L224 in `IlluviumLockedPool.sol` are never used.

Open the report
Low`FeaturesUpdated` event is never usedIlluvium ERC20 · Quantstamp · 19 Mar 2021Fixed

`FeaturesUpdated` event defined in `AccessControl.sol` contract is never used. Instead, the `RoleUpdated` event is emitted when features are updated.

Open the report
LowOff-by-one errorIlluvium ERC20 · Quantstamp · 19 Mar 2021Fixed

Signature expiration should occur at the block with timestamp specified by the `_exp` input parameter of the `delegateWithSig()` function. This means that at `block.timestamp == _exp` the signature should already be expired. However, the `require` statement on L1014 only throws if `block.timestamp > _exp`.

Open the report
LowWrong underflow checkIlluvium ERC20 · Quantstamp · 19 Mar 2021Fixed

In L742-745, the checks are wrong. The check in L742 tests for overflow (instead of underflow), whereas the check in L745 allows to decrease by 0 (which contradicts the documentation).

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