Impossible Finance security record

Arbitrum, Avalanche, BNB Chainimpossible.financeXGitHub

As of 3 Nov 2026, Impossible Finance has 1 audit report on Trustblock, by Quantstamp, dated 7 Mar 2024. That report lists no open critical findings. It also holds 1 incident (latest 20 Jun 2021).

Critical findings
No open critical findings
In 1 report.
Incident
Incident 20 Jun 2021
Source: De.Fi incident database. 1 audit has been published since. See the incident
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
Impossible FinanceSecurity firm: QuantstampDate: Scope: Files named in the reportNo open critical findingsOpen · certificate.quantstamp.com

Findings13

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

SeverityOpenAcknowledgedFixed
Critical000
High001
Medium001
Low056
HighUsers Can Obtain Unlimited Giveaway AmountsImpossible Finance · Quantstamp · 7 Mar 2024Fixed

In the `IFFixedSale` contract, both the `withdrawGiveaway()` and `withdrawGiveawayVested()` functions accept an `allocation` input that can be specified by the user. In situations where the giveaway is not whitelisted, users can enter any `allocation` value without restrictions.

Open the report
MediumRisk of Incorrect Vesting AmountImpossible Finance · Quantstamp · 7 Mar 2024Fixed

The `IFSale.setWithdrawDelay()` function allows the owner to set the withdrawal delay, and it calls `setWithdrawTime(endTime - withdrawDelay + _withdrawDelay)` to set the withdrawal time. The formula `endTime - withdrawDelay + _withdrawDelay` would be adequate for its initial setting, as the default value for `withdrawDelay` is zero. However, if the function is called a second time to adjust the withdrawal delay, the formula will incorrectly set the withdrawal time. In the worst case, the withdrawal time could be set earlier than the end time. The incorrect withdrawal time will impact the accuracy of the `IFVestable.getUnlockedToken()` function. This function depends on the `withdrawTime`, which may be incorrectly set. Therefore, if the withdrawal time ends up being earlier than it should be, it could result in more tokens vested than expected.

Open the report
LowConsolidation of Best PracticesImpossible Finance · Quantstamp · 7 Mar 2024Fixed

This is a consolidation of all the best practices we think could help improve the code quality. **Input Validation**: 1. `IFWhitelistable.setWhitelistSetter()`should have validation against zero-address as the parameter. Redundant code: 1. In `IFPurchasable._purchaseWithCode()`, the logic `if (paymentReceivedWithEachCode[_msgSender()][code] == 0 && paymentAmount > 0)` can be simplified to `if (paymentReceivedWithEachCode[_msgSender()][code] == 0)` because `paymentAmount > 0` is already checked for in the call to `_purchase()` few lines above. 2. The check `if (bytes(code).length > 0)` in `IFPurchasable._purchaseWithCode()#L178` is unnecessary, as the same check is performed in `L158` too. <br> **Gas optimization**: 1. In `IFSale.withdraw()` and `IFSale.withdrawGiveaway()`, the statement `require(tokenOwed != 0, 'withdraw giveaway amount 0');` can be moved earlier to save on gas if the execution reverts. 2. For loops can be gas-optimized by cashing the `array.length` in a `memory` variable and incrementing the iterator via `unchecked {++i;}` <br> **Code documentation**: 1. In `IFFixedSale.purchase(uint256)`, the revert statement is `revert("Use purchase(uint256 paymentAmount, bytes32[] calldata merkleProof, uint256 allocation)");`. However, `purchase(uint256 paymentAmount, bytes32[] calldata merkleProof, uint256 allocation)` does not exist. This is likely referring to `whitelistedPurchase(uint256 paymentAmount, bytes32[] calldata merkleProof, uint256 _allocation)` instead. A similar issue exists for `whitelistedPurchase(uint256, bytes32[] calldata)`. <br> **Code maintenance**: 1. Can replace `require(endTime + withdrawDelay < block.timestamp, 'cannot withdraw yet');` with the `onlyAfterSale` modifier for `IFFundable.cash()`. 2. Can use `EnumerableSet` to simplify the logic of having both `hasWithdrawn` and `withdrawerCount`. 3. In `IFFundable`, the `ONE_YEAR` and `FIVE_YEAR` values are leap year adjusted, while the `TEN_YEAR` value is not. Consider aligning it.

Open the report
LowOwnership Can Be RenouncedImpossible Finance · Quantstamp · 7 Mar 2024Fixed

If the owner renounces their ownership, all ownable contracts will be left without an owner. Consequently, any function guarded by the `onlyOwner` modifier will no longer be able to be executed.

Open the report
LowProject Team Unable to Retrieve Remaining Giveaway TokensImpossible Finance · Quantstamp · 7 Mar 2024Fixed

The `IFundable.cash()` function is designed to enable the project team to withdraw the payment tokens and any unsold sale tokens. However, in the context of a giveaway, where the `salePrice` is set to zero, this results in a failure due to the `IFSale.getSaleTokensSold()` function attempting to divide by `salePrice`, causing the `cash()` function to revert in giveaway scenarios. While payment tokens can still be withdrawn using `cashPaymentToken()` or `emergencyTokenRetrieve()`, any remaining sale tokens will be locked post-giveaway. It should be noted that the project team can utilize the `setWhitelist()` function to modify the whitelist, facilitating a "withdrawal" through the standard giveaway process by updating the Merkel root. However such manual intervention can introduce unnecessary risk due to human errors.

Open the report
LowPurchase Can Be Called Even when the Sale Price Is ZeroImpossible Finance · Quantstamp · 7 Mar 2024Fixed

When `salePrice` is zero, a user should claim its token from `withdrawGiveaway()` (or related functions) instead of calling `purchase()`. There is no explicit check that when a user calls purchase, say in `IFSale` and `IFFixedSale`, the `salePrice` is non-zero. It is noted that the execution will revert implicitly due to a division by zero error in ` uint256 tokenPurchased = (paymentReceived[_msgSender()] * SALE_PRICE_DECIMALS) / salePrice;`, but this non-zero price check should be the responsibility of `IFPurchasable` rather than `IFSale`.

Open the report
LowUnlocked PragmaImpossible Finance · Quantstamp · 7 Mar 2024Fixed

Every Solidity file specifies in the header a version number of the format `pragma solidity (^)0.8.9`. 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". Furthermore, the current version used is `0.8.9` (as defined in `hardhat.config.ts`. It is recommended to use a newer version of the solidity compiler as mentioned [here](https://github.com/crytic/slither/wiki/Detector-Documentation#recommendation-80).

Open the report
LowUser Can Potentially Get More than Whitelisted AllocationsImpossible Finance · Quantstamp · 7 Mar 2024Fixed

In the `IFFixedSale` contract, both `whitelistedPurchaseWithCode()` and `whitelistedPurchase()` functions determine whether the allocation should use the `publicAllocation` or the whitelisted allocation, depending on whether the `merkleProof` is provided. However, if a user's whitelisted amount is lower than the `publicAllocation`, the user can opt for the public allocation instead and receive more than what is allocated for whitelisted users. We consider the risk low, as we believe the project team is likely to grant larger allocations to whitelisted users. Nonetheless, we want to highlight this potential risk.

Open the report

Incidents1

Attached through a shared contract address. Our incident data ends in Oct 2026.

Incident

Incident,

com/token/0x9892dd7a51a09c970e2a925e3baf2107bc8dac74 - created LP with the fake token and IF token - swapped 32,570 IF into 221,898 BUSD and another 32,570 IF into 221,898 BUSD using IF router through the FAKE token LP - repeated the steps from 3 to 5 - sold 556,384 BUSD for 1,731 BNB, repaid the flash loan.

Source: De.Fi incident database.

Audits before it
0.
Audits since
1, the latest dated 7 Mar 2024.

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="impossible-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