As of 3 Nov 2026, LIF3 has 3 audit reports by 2 security firms on Trustblock; the latest is by CertiK, dated 27 Feb 2024. Those reports list 1 critical acknowledged and not fixed. It also holds 1 deployed contract on 1 chain.
Record last updated . It holds audits, findings and contracts up to Nov 2026, and incidents up to Oct 2026. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| Lif3 L3USD | Security firm: CertiK | Date: | Scope: Not recorded (see the report) | 1 critical acknowledged, not fixed | Open · skynet.certik.com |
| Lif3 - vaults - SC | Security firm: CertiK | Date: | Scope: Files named in the report | No open critical findings | Open · skynet.certik.com |
| Lif3 / ERC20 | Security firm: Hacken | Date: | Scope: 1 address on Fantom | No open critical findings | Open · hacken.io |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 1 | 0 |
| High | 0 | 2 | 0 |
| Medium | 0 | 0 | 1 |
| Low | 6 | 0 | 5 |
In function `deposit()`, when calculating deposit share amount, the code calls function `_calculateShare()` with input `_amount` and `_lockTime`. The `_amount` it is using is the full amount of deposited token before fee deduction. If `depositFee` is larger than 0, then the actual deposited amount should be less than the full amount. The user share amount is calculated again during withdrawal, and this time the actual deposited amount is used. As a result, the withdrawn share amount would always be smaller than deposited. This may cause a leftover of rewards in the contract. ```solidity=352 if (depositFee > 0) { uint256 depositFeeAmount = (_amount * depositFee) / 10000; uint256 _amountMinusFee = _amount - depositFeeAmount; depositToken.safeTransferFrom(sender, feeCollector, depositFeeAmount); depositToken.safeTransferFrom(sender, address(this), _amountMinusFee); finalAmount = _amountMinusFee; } else { depositToken.safeTransferFrom(sender, address(this), _amount); finalAmount = _amount; } uint256 share = _calculateShare(_amount, _lockTime); ```
Open the reportA reentrancy attack can occur when the contract creates a function that makes an external call to another untrusted contract before resolving any effects. If the attacker can control the untrusted contract, they can make a recursive call back to the original function, repeating interactions that would have otherwise not run after the external call resolved the effects. 1. In function `deposit()`, the transfer-in of deposit token happens before updating state variables. 2. In function `withdraw()`, the transfer-out of deposit token and reward tokens happen before updating state variables. 3. In function `emergencyWithdraw()`, the transfer of reward tokens happen before updating state variables.
Open the reportPerforming integer division before multiplication truncates the low bits, losing the precision of calculation. ```solidity=218 return lock.amount * (lock.finalClaimEpochStartTime + epochLength - taxCalculationStart) / lock.lockTime * emergencyWithdrawTax / 10000; ``` --- ```solidity=338 PRBMath.UD60x18 memory exponent = PRBMath.UD60x18({value: _lockTime/epochLength*1e18}); ``` --- ```solidity=452 emergencyWithdrawTaxAmount = amount * (lock.finalClaimEpochStartTime + epochLength - currentEpochStart) / lock.lockTime * emergencyWithdrawTax / 10000; ```
Open the reportIn contract LockNFT, function `destroyLock()` and `_destroyLock()` can be called by any `DESTROYER_ROLE` to destroy any lock NFT token. This makes it possible for a user to make deposit in one reward pool, and call `withdraw()` or `emergencyWithdraw()` in another pool. As a result, the user's LockNFT would be burned, and he wouldn't be able to withdraw his deposited assets.
Open the reportThe linked variables assigned in the constructor can be declared as `immutable`. Immutable state variables can be assigned during contract creation but will remain constant throughout the lifetime of a deployed contract. A big advantage of immutable variables is that reading them is significantly cheaper than reading from regular state variables since they will not be stored in storage.
Open the reportThe report gives no description here.
Open the report| Address | Chain |
|---|---|
| 0xbf60…64da0xbf60e7414ef09026733c1e7de72e7393888c64da | Chain: Fantom |
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.
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.
<head><script src="https://widget.trustblock.run/project-widget.min.js" defer></script></head><body><divdata-tb-project-widgetdata-tb-project-slug="lif3"></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