Kinetiq

Kinetiq: kntq

Cantina Security Report

Organization

@kinetiq

Engagement Type

Cantina Reviews

Period

-

Researchers


Findings


Informational6 findings

  1. DeploySKNTQ: batched initialization calldata is not directly observable from script output

    State

    New

    Severity

    Severity: Informational

    Submitted by

    Optimum


    Description

    When batchCalls execution is skipped in forge script (e.g. due to precompile revert), the script logs each individual target, calldata, and value in a loop.

    This does not reflect the actual on-chain execution, which is a single call to CallBatcher.batchCalls, and requires manual reconstruction of calldata, which is error-prone.

    As a result, the exact transaction that must be sent on-chain is not directly observable from the script output.

    Recommendation

    Log the fully encoded calldata for CallBatcher.batchCalls(targets, data, values) so it can be submitted directly via cast send.

  2. Using CREATE2 in forge scripts can be front-run causing unexpected reverts

    State

    New

    Severity

    Severity: Informational

    Submitted by

    Optimum


    Description

    Foundry deployment scripts rely under the hood on the CREATE2 deployer at
    0x4e59b44847b379578588920cA78FbF26c0B4956C, whose fallback function performs CREATE2 deployments.

    Because this is a public contract, a third party can front-run a deployment transaction and deploy a contract with the same salt and bytecode first. When the script’s transaction executes afterward, the CREATE2 call reverts, causing the deployment script to fail.

    Foundry does not currently detect or gracefully handle this case, so the revert can be unexpected and hard to diagnose.

    Impact

    Deployment scripts using new {salt: ...} may revert non-deterministically under adversarial or congested conditions, even when the script logic itself is correct.

    Note

    While this can be worked around by avoiding new and using a low-level call that tolerates pre-existing deployments, this is heavy-handed. At minimum, this behavior should be documented to raise awareness for users encountering unexplained deployment reverts.

  3. Avoid hardcoded CREATE2 deployer address magic constant

    State

    New

    Severity

    Severity: Informational

    Submitted by

    Optimum


    Description

    Some deployment scripts rely on the CREATE2 deployer at the fixed address
    0x4e59b44847b379578588920cA78FbF26c0B4956C, embedding it directly as a literal in the code.

    Using this address as a magic constant is brittle and obscures where the value comes from, making scripts harder to reason about, audit, and maintain. It also tightly couples user code to Foundry internals without an explicit abstraction or reference.

    Recommendation

    Avoid hardcoding the CREATE2 deployer address as a literal in deployment scripts. Prefer a named constant, helper, or documented reference provided by Foundry.

    See Foundry’s documentation on deterministic deployments for context:
    https://getfoundry.sh/guides/deterministic-deployments-using-create2

  4. ERC4626AsynchronousUpgradeable: unused _transferIn function should be removed

    State

    New

    Severity

    Severity: Informational

    Submitted by

    Optimum


    Description

    The function _transferIn(address from, uint256 assets) is defined in ERC4626AsynchronousUpgradeable but is never used by the contract.

    Deposits rely on the inherited ERC4626 implementation, and this override is not referenced anywhere in the codebase, making it dead code.

    Recommendation

    Remove _transferIn if it is not intended to be used, or explicitly document and integrate it into the deposit flow if customization is planned.

  5. ERC4626 inflation mitigation: isolate initial shares from vault-held assets

    State

    New

    Severity

    Severity: Informational

    Submitted by

    Optimum


    Description

    The initial shares minted for ERC4626 inflation-attack mitigation are currently sent to the skntq contract itself.
    This is functionally correct because the vault already holds the corresponding token balance, and the accounting remains consistent.

    However, this design couples the “burned” shares with a contract that actively participates in vault accounting. While correct by construction, this reduces isolation between live vault state and permanently inaccessible shares.

    Recommendation

    Consider sending the initial shares to a burn address
    0x000000000000000000000000000000000000dEaD
    to fully isolate unspendable shares from the vault’s operational balance. This improves conceptual clarity and reduces the chance of confusion during audits or future changes.

    Note

    This is a best-practice suggestion for clarity and isolation, not a correctness issue.

  6. Storage layout inconsistency: SKNTQ uses linear storage while base contracts use ERC7201

    State

    New

    Severity

    Severity: Informational

    Submitted by

    Optimum


    Description

    The base contracts follow the ERC7201 namespaced storage pattern, while SKNTQ uses a traditional linear storage layout.

    While not incorrect, this inconsistency increases cognitive overhead and raises the risk of storage collisions or upgrade fragility in a system composed of multiple upgradeable components.

    Recommendation

    Consider migrating SKNTQ to the ERC7201 storage pattern to align with the base contracts and ensure consistent, collision-resistant storage layouts across the codebase.