As of 30 Oct 2026, Datachain has 7 audit reports by 1 security firm on Trustblock; the latest is by Quantstamp, dated 25 Jul 2025. Those reports list no open critical findings.
Record last updated . It holds audits and findings, contracts and incidents up to Oct 2026. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| Datachain - ELC for Bridge (OptimismELC) | Security firm: Quantstamp | Date: | Scope: Not recorded (see the report) | No open critical findings | Open · certificate.quantstamp.com |
| Datachain LCP-zkDCAP | Security firm: Quantstamp | Date: | Scope: Files named in the report | No open critical findings | Open · certificate.quantstamp.com |
| Datachain - App for Liquidity | Security firm: Quantstamp | Date: | Scope: Repository at commit dcccb98 | No open critical findings | Open · certificate.quantstamp.com |
| Datachain - ELC for Bridge - Ethereum | Security firm: Quantstamp | Date: | Scope: Repository at commit 7a40e6a | No open critical findings | Open · certificate.quantstamp.com |
| Datachain - IBC | Security firm: Quantstamp | Date: | Scope: Repository at commit ca7a56c | No open critical findings | Open · certificate.quantstamp.com |
| Datachain - LCPs | Security firm: Quantstamp | Date: | Scope: Repository at commit 54d2bac | No open critical findings | Open · certificate.quantstamp.com |
| Datachain - ELC For Bridge - BSC | Security firm: Quantstamp | Date: | Scope: Repository at commit 78d1349 | No open critical findings | Open · certificate.quantstamp.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 1 | 7 |
| Medium | 1 | 1 | 7 |
| Low | 0 | 7 | 41 |
In order to send data (a packet) through IBC, a module needs to call the function `IBCChannelPacketSendRecv.sendPacket()`, and then the `IBCChannelPacketSendRecv.recvPacket()` function is called by a module in order to receive an IBC packet sent on the corresponding channel end on the counterparty chain. If a packet timeouts instead of being executed, on the originated chain the function `IBCChannelPacketTimeout.timeoutPacket()` is invoked, and the channel will be closed if it is of type `ORDERED`, thus not allowing following packets to be send. This feature can be leveraged in the context of EVM chains where you could find chains with significant gas limit differences per block (e.g, Ethereum with 30m gas limit vs Zircuit with 10m gas limit) to create a DoS by sending a large amount of data that could be processed by one chain but not by the other, therefore running into an `out of gas` error and making the packet timeout. The bigger the difference between the chains' gas limit per block, the easier it is to exploit the vulnerability.
Open the reportThe `eqFee` is a fee applied when the destination pool's balance is lower than its target balance. It is currently calculated on the source pool using the balances stored in `PeerPoolInfo`. However, the accuracy of `PeerPoolInfo` is dependent time since the last received packet from the destination chain. The `PeerPoolInfo.balance` on the source chain will always be less than or equal to `PeerPoolInfo.lastKnownBalance` on the destination chain. It is possible that the destination pool's balance has been replenished while users continue to be charged an `eqFee` for an incorrect Balance Deficit Zone.
Open the reportCurrent implementation only tracks transfers above `THRESHOLD`, allowing rate limit bypass through multiple smaller transfers. Allowing unlimited transfers below threshold. **Current Code**: ```solidity if (THRESHOLD < amount) { $._cancellableAmount = amount; $._currentPeriodAmount += amount; } else { $._cancellableAmount = 0; } ```
Open the reportThe `refuelAmount` is capped once received by the destination chain. The source chain validates that the `refuelAmount` is within bounds before sending out the message. However, the `refuelDstCap` can be updated at any time in `BridgeManager.setRefuelCap()`. If the chains fuel caps are ever desynchronized, a user may not have their full refuel amount transferred to them and the difference will be kept by the protocol.
Open the reportThe `_mintLPbyLD()` function in `Pool.sol` is responsible for minting LP tokens to users when they deposit liquidity into the pool. This function conditionally calls the `_deltaSourceUpdate()` function, which implements the Delta algorithm's rebalancing logic. The condition for calling `_deltaSourceUpdate()` depends on the `_batched` flag and the relationship between `_deltaCredit`, `_totalLiquidity`, and `_lpDeltaBP`. The `_deltaSourceUpdate()` function can be gas-intensive, as it involves iterating through all connected pools and potentially updating storage variables. Because the call to `_deltaSourceUpdate()` is conditional, some liquidity deposits will trigger it while others will not. This leads to unequal gas consumption for users performing the same operation (depositing liquidity). Users who happen to deposit liquidity when the conditions for triggering `_deltaSourceUpdate()` are met will incur significantly higher gas costs than those who deposit when the conditions are not met. This can be perceived as unfair and might discourage liquidity provision, especially when the pool is close to the threshold that triggers the update.
Open the reportThe function `is_valid_light_client_finalized_header()` is missing essential validation checks for finalized headers introduced in the Deneb (EIP-4844) and Capella upgrades. These checks ensure that: - For epochs earlier than `DENEB_FORK_EPOCH`, `execution.blob_gas_used` and `execution.excess_blob_gas` are both `0`. - For epochs earlier than `CAPELLA_FORK_EPOCH`, `execution` is an empty `ExecutionPayloadHeader`, and `execution_branch` is an empty `ExecutionBranch`. These validations are specified in the [Deneb upgrade to the Sync Protocol](https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/light-client/sync-protocol.md#modified-is_valid_light_client_header). Without these validations, the function may incorrectly validate headers that are non-compliant with the protocol rules for these upgrades.
Open the report[The specs](https://github.com/cosmos/ibc/blob/499818e9c4b136029717a436a04af15113f4424f/spec/core/ics-004-channel-and-packet-semantics/README.md?plain=1#L588) describe that in `channelCloseConfirm()` any upgrade stored at the channel upgrade path should be deleted during this process, however there is no deletion taking place.
Open the reportBelow, we include a non-exhaustive list of all deviations from the ICS-Specs in the ibc-solidity implementatio. These deviations are not standalone issues, however we list these deviations for transparency for all future users of ibc-solidity. Many of these deviations are a result of the limitations of the Solidity language and the EVM environment, such as gas costs or transaction gas limits and are intentional design decisions made by the Datachain team. The team has documented these changes in the files at `docs/adr`. Overall, we note that ibc-solidity does not support multi-hop connections or for the `ORDERED_ALLOW_TIMEOUT` channel ordering mechanism, as described in the ICS-Specs. Therefore, all logic associated with that is not present in the ibc-solidity implementation. Deviations: - `authenticateCapability()` does not exist in the ibc-solidity implementation as a single function, as described in the ICS specs. Instead, the owner of the `IBCHandler` contract will invoke `bindPort()` to assign module address to given ports in the provable store of the `IBCHandler`. Then, throughout conneciton and channel handshakes, capabilities are authenticated through functions such as `IBCModuleManager.lookupModuleByPort()` and `lookupModuleByChannel()`, which proves there is a non-zero address mapped at the port or channel, showing that the module has been bound by an IBC admin, and the channel has been written. During handshakes, module callback functions such as `onRecvPacket()` will only be invoked on the module addresses assigned by the Admin. - `clientConnectionsPath()` providing a reverse mapping from clients to a set of connections is not included in the implementation. - This means, there is no way that `queryClientConnections()` can be implemented and this data will have to be queried using other methods. - `ConnectionEnd` structural deviation: - `delayPeriodBlocks` is not defined to be a field within a Connection. Instead, when this field is needed for message passing, it is calculated during the transaction, as a function of the `delayPeriodTime` and the `expectedTimePerBlock` which is configurable by the IBCHandler admin. - Further, the `ConnectionEnd` doesn't have fields like `counterPartyPrefix` and instead, these fields are defined within a counterparty data structure which is a field within the ConnectionEnd itself - `channelOpenInit()` & `channelOpenTry()` do not confirm that the generated `channelId` is not already stored, as specified in the specs. We recognize that a clash is highly unlikely, as there are 2^64 possible ids. However, a check like this is done in `connectionOpenInit()` and we recommend verifying that there is nothing stored at the generated id for thoroughness. - `emit RecvPacket()` does not include the Order and Connection fields as [specified in ICS-specs](https://github.com/cosmos/ibc/blob/499818e9c4b136029717a436a04af15113f4424f/spec/core/ics-004-channel-and-packet-semantics/README.md?plain=1#L879) - the `_writeAcknowledgement()` function is emitting an event that is missing the following fields, that are otherwise specified in the specs: - `timeoutHeight` - `timeoutTimestamp` - `packet.data` - `sendPacket()` does not check that the connection exists. However, since the connection is stored within the `Channel.Data` itself, and the channel's existence is confirmed, we see no major issue here and include this to note the discrepancy. - Specs allow for a packet to received more than once, with just an identical event being emitted, however, in the implementation, we cannot receive a packet more than once, and the transaction will revert. the Datachain team has already acknowledged this to be a design choice however we note here for thoroughness and transparency. - `counterpartyUpgradePaths()` are not written to the provable store
Open the reportIn `verify_header_size()`, when there are headers that come at or after the checkpoint of an untrusted epoch, the function will attempt to validate the untrusted epoch by calling `UntrustedEpoch::try_borrow()`. This will check whether the untrusted epoch contains at least `x/3 + 1` validators from the trusted epoch, where `x` is the size of the trusted validator set. If the untrusted epoch does not contain this threshold number of trusted validators, an error will be returned. However, this does not account for cases that may appear where 1. A new validator set appears that does not contain `x/3 + 1` validators from the trusted epoch (this is possible because the procedure for selecting validators (on mainnet) involves [selecting the top stakers](https://docs.bnbchain.org/bnb-smart-chain/validator/overview/), which may change over time); 2. The only blocks after the new epoch's first block that contain BLS signatures are those that come after the new epoch's checkpoint. In such a case, the ELC may halt due to the aforementioned error.
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="datachain"></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