As of 3 Nov 2026, Iskra has 4 audit reports by 1 security firm on Trustblock; the latest is by CertiK, dated 22 Apr 2024. Those reports list no open critical findings.
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 |
|---|---|---|---|---|---|
| Iskra - Audit 5 | Security firm: CertiK | Date: | Scope: Files named in the report | No open critical findings | Open · skynet.certik.com |
| Iskra - ItemNFTSnapshot | Security firm: CertiK | Date: | Scope: Files named in the report | No open critical findings | Open · skynet.certik.com |
| Iskra - Launchpad | Security firm: CertiK | Date: | Scope: Files named in the report | No open critical findings | Open · skynet.certik.com |
| Iskra - Audit for Token (Part 1) | Security firm: CertiK | Date: | Scope: Files named in the report | No open critical findings | Open · skynet.certik.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 8 | 2 | 0 |
| Medium | 0 | 0 | 2 |
| Low | 8 | 0 | 25 |
The contract `LaunchpadInitializer` does not protect its initializer. An attacker can call the initializer and assume ownership of the logic contract, whereby she can perform privileged operations that either indirectly break the proxy by destroying the logic contract or trick unsuspecting users into believing that she is the owner of the upgradeable contract. Since the `LaunchpadInitializer` is meant to update important state variables before using the `Launchpad` implementation, a lack of security in this contract could have unexpected effects on the protocol.
Open the reportIn `StructuredSignVerifier`, the state variable `_TYPE_HASH` is shadowing another component defined in `EIP712`. \ This variable is used to perform sensitive tasks related to the cryptographic protocol, therefore it is not recommended to shadow any variable or interfere with the underlying mechanism.
Open the reportThe `OFTPermit` smart contract inherits from both `OFT` and `ERC20Permit`. During the construction phase of the `OFTPermit` contract, the constructor initializes the parent contracts with the provided parameters but does not mint any initial tokens. This oversight means that while the contract is capable of receiving tokens from other chains, it lacks the capability to send tokens to other chains initially due to the absence of a token supply.
Open the reportThere should always be events emitted in the sensitive functions that are controlled by centralization roles.
Open the reportIn the contract `Launchpad`, the function `_deployIGO()` has the following *for* loop: ```solidity=119 for (uint256 i = 0; i < saleAmounts.length; ++i) { totalAmounts += saleAmounts[i]; require(saleAmounts[i] % amountPerTicket == 0, "invalid amountPerTicket."); } ``` The **require** statement could be placed before the update of `totalAmounts`, so in case of an invalid `amountPerTicket` the execution reverts before updating a variable.
Open the reportA reentrancy attack can occur when the contract includes 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.
Open the reportBoolean constants can be used directly and do not need to be compared to true or false. ```solidity=249 require(_isPaymentToken[token] == false, "already registered payment token."); ``` --- ```solidity=257 require(_isPaymentToken[token] == true, "not registered payment token."); ```
Open the reportThere is no storage gap preserved in the logic contract. Any logic contract that acts as a base contract that needs to be inherited by other upgradeable child should have a reasonable size of storage gap preserved for any new state variables introduced by future upgrades. This finding is for informational purposes only because from context it is understood that likely all new state variables would be added to `LaunchpadBase`, which holds all state variables related to `Launchpad`.
Open the reportIn `InitialGameOffering.sol`, the function `initialize()` sets the values of `_saleInfo[SaleKind.PIONEER].saleAmount` and `_saleInfo[SaleKind.EXPLORER].saleAmount`. There is a missing requirement that these values are not set as 0.
Open the reportIn `StructuredSignVerifier`, the function `changeSignLifespan()` allows modifying the validity period of a signature. However, there is no upper bound on the value it is set to.
Open the reportIn `InitialGameOffering.sol`, many functions are depending on the `status()` of the contract to execute correctly. The `status()` depends heavily on the time marks and periods defined using the function `_changeSaleTimeline()`. This function allows the time intervals to have arbitrarily large values. This can cause the state of the contract to be stuck for a crucial amount of time. Since `refund()` and `claim()` functions are also dependent on the status of the contract, this could lead to a loss of assets for users.
Open the reportAddresses should be checked before assignment or external call to make sure they are not zero addresses. ```solidity=66 token = token_; ``` - `token_` is not zero-checked before being used. --- ```solidity=112 operator = operator_; ``` - `operator_` is not zero-checked before being used.
Open the reportIn `InitialGameOffering.sol`, the function `initialize()` does not perform an upper bound check when setting `sellerFeePerMille` and `buyerFeePerMille` although those values cannot be set higher than 1000 in any other functions.
Open the reportThe function `_verifySignature()` does not perform enough checks to prevent someone from reusing the same parameter more than once. \ This could potentially be used to perform a replay attack. In the scope of this audit, the signature mechanism seems to be used only to ensure a user participating in an `InitialGameOffering` is authorized to do so. In this case, the replay allowed by the signature verification seems to be fine since it will only allow a specific user to participate.
Open the reportA local variable is shadowing another component defined elsewhere. ```solidity=72 string memory symbol = abi.decode(queriedSymbol, (string)); ``` - Local variable `symbol` in `IGOVesting.initialize` shadows: - Function `symbol` in `ERC20Upgradeable` - Function `symbol` in `IERC20MetadataUpgradeable` --- ```solidity=16 constructor(address signer) StructuredSignVerifier("LaunchpadQualificationChecker", signer, 5 minutes) {} ``` - Local variable `signer` in `LaunchpadQualificationChecker.constructor` shadows the variable `signer` in `StructuredSignVerifier`.
Open the reportIn the linked locations, a function is creating a local variable `prev` whose only purpose is to be used in an event.
Open the reportOne or more logic contracts do not protect their initializers. An attacker can call the initializer and assume ownership of the logic contract, whereby she can perform privileged operations that trick unsuspecting users into believing that she is the owner of the upgradeable contract. ```solidity=15 contract IGOVesting is OwnableUpgradeable, IIGOVesting, ERC20Upgradeable, ERC165 { ``` - `IGOVesting` is an upgradeable contract that does not protect its initializer. ```solidity=53 function initialize( ``` - `initialize` is an unprotected initializer function. --- ```solidity=16 contract InitialGameOffering is OwnableUpgradeable, IInitialGameOffering { ``` - `InitialGameOffering` is an upgradeable contract that does not protect its initializer. ```solidity=90 function initialize( ``` - `initialize` is an unprotected initializer function.
Open the reportThe return value of an external call is not stored in a local or state variable. ```solidity=433 IERC20Upgradeable(_vesting.token()).approve(address(_vesting), amount); ```
Open the reportThe contract `GameToken` is importing and inheriting the `Ownable2Step` contract, however, the `onlyOwner` modifier is never used in the contract.
Open the reportThe contract `Vesting.sol` is using a solidity version greater than 0.8.0; this version has built-in checks in the compiler preventing overflow/underflow of arithmetic operators. In the function `prepare()`, the varaible `_totalLocked` is computed as follow: ```solidity=88 initialVestingAmount = _amount; initialUnlockedAmount = _initialUnlocked; uint256 _totalLocked = initialVestingAmount - initialUnlockedAmount; ``` meaning that `_totalLocked = _amount - _initialUnlocked`, hence any underflow is prevented by the following check: ```solidity=74 require( _amount >= _initialUnlocked, "Vesting: `_initialUnlocked` is greater than `_amount`" ); ```
Open the reportWhen transferring standard ERC20 deflationary tokens, the input amount may not be equal to the received amount due to the charged transaction fee. For example, if a user stakes 100 deflationary tokens (with a 10% transaction fee) in the `Vesting` contract, only 90 tokens actually arrive in the contract. However, the user can still withdraw 100 tokens from the contract, which causes the contract to lose 10 tokens in such a transaction.
Open the reportOne or more parameters with `memory` data location are never modified in their functions and those functions are never called internally within the contract. Thus, their data location can be changed to `calldata` to avoid the gas consumption copying from calldata to memory. ```solidity=14 function setURI(string memory newuri) public { ``` `setURI` has memory location parameters: `newuri`. --- ```solidity=18 function mint( ``` `mint` has memory location parameters: `data`. --- ```solidity=27 function mintBatch( ``` `mintBatch` has memory location parameters: `ids`, `values`, `data`. --- ```solidity=44 function burnBatch( ``` `burnBatch` has memory location parameters: `ids`, `values`. --- ```solidity=60 function setURI(uint256 tokenId, string memory tokenURI_) public onlyOwner { ``` `setURI` has memory location parameters: `tokenURI_`. --- ```solidity=64 function setBaseURI(string memory baseURI) public onlyOwner { ``` `setBaseURI` has memory location parameters: `baseURI`. --- ```solidity=121 function mint( ``` `mint` has memory location parameters: `data`. --- ```solidity=130 function mintBatch( ``` `mintBatch` has memory location parameters: `ids`, `amounts`, `data`. --- ```solidity=115 function setTokenURI(uint256 tokenId, string memory _tokenURI) ``` `setTokenURI` has memory location parameters: `_tokenURI`.
Open the reportIn the contract `Vesting.sol`, the function `revoke()` should have a check preventing `_reclaimer == address(this)`. \ If the `_reclaimer` parameter is mistakenly set as the address of the contract, all tokens will stay in `Vesting`, and since after the transfer the `VestingStatus` is set as `REVOKED` it will be impossible to retrieve the tokens.
Open the reportAddresses should be checked before assignment or external call to make sure they are not zero addresses. ```solidity=187 beneficiary = _newBeneficiary; ``` - `_newBeneficiary` is not zero-checked before being used.
Open the reportThe return value of the transfer()/transferFrom() call is not checked. ```solidity=93 token.transferFrom( _distributor, address(this), initialVestingAmount * 10**18 ); ``` --- ```solidity=146 token.transfer(_reclaimer, _amount); ``` --- ```solidity=169 token.transfer(beneficiary, _amount * 10**18); ```
Open the reportIn the contract `Vesting.sol`, the function `prepare()` performs the following checks: ```solidity=71 require(_duration > 0, "Vesting: `_duration` is 0"); // otherwise, claimer can claim all amount after first unlock period require(_amount > 0, "Vesting: `_amount` is 0"); ``` ```solidity=79 require( _amount >= _duration, "Vesting: _amount must be greater than _duration" ); ``` Since `_duration > 0` is enforced by the first **require** statement and `_amount >= _duration` is enforced by the third one, the `_amount > 0` is implied and: ```solidity=74 require(_amount > 0, "Vesting: `_amount` is 0"); ``` is redundant.
Open the reportOne or more logic contracts do not protect their initializers. An attacker can call the initializer and assume ownership of the logic contract, whereby she can perform privileged operations that trick unsuspecting users into believing that she is the owner of the upgradeable contract. ```solidity=10 contract Vesting is OwnableUpgradeable { ``` - `Vesting` is an upgradeable contract that does not protect its initializer. ```solidity=47 function initialize() public initializer { ``` - `initialize` is an unprotected initializer function.
Open the reportThe reports name a repository or files. Open a report to see its scope.
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="iskra"></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