Datachain - App for Liquidity

QuantstampRepository at commit dcccb98

Quantstamp reviewed Datachain (Datachain - App for Liquidity) on 27 Jan 2025: 20 findings, 0 critical; 15 marked fixed, 4 acknowledged, 1 open.

No open critical findings
Open the reportOpen Datachain’s security record

Report hosted on certificate.quantstamp.com.

Trustblock does not review code.

Findings20

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

SeverityOpenAcknowledgedFixed
Critical000
High002
Medium113
Low0310
HighPools are not always replenishedFixed

`_deltaSourceUpdate()` is designed to apply the `deltaCredit` to replenish the soft partitions of the liquidity pool. The `diff` between the target total balance and current balance (the deficit) is calculated for each pool. `deltaCredit` is then applied to replenish each pool according to their weights. However, if `fullMode == true` and `totalDiff <= deltaCredit`, the `diff[i]` is never applied to `amtToCredit`. In this scenario, only the `excessCredit` is distributed to the pools. The inline and NatSpec comments further validate that this is a missing requirement.

HighThe Drift protocol fee is prohibitively expensiveFixed

The expected value of arbitraging a price drift between two pegged assets is equal to: ```js expectedValue = (dstPrice - srcPrice) * amountGD ``` The protocol drift fee is equal to: ```js (amountGd * srcPrice) / dstPrice ``` The current calculation far overcharges the protocol drift fee.

MediumFailed transactions cause a drift in target balanceFixed

When a failed transaction can no longer be retried, a permanent difference between the last known balance on the destination chain and the balance on the source chain grows by the value of the failed transaction, such that: ```js chainA.peerPoolInfo[chainB].lastKnownBalance >= chainB.peerPoolInfo[chainA].balance + totalFailedTransfers ``` The last known balance is used to determine how much a pool needs to be replenished in the delta algorithm. When the last known balance is greater than the actual balance available, the pool is underestimating how much liquidity is needed to replenish the pool. This gap will grow larger as the number of locked funds due to failed crosschain transactions increase over time. While pools can be rebalanced to accomodate for bandwidth requirements, many of the fees depend on accurately assessing pool health. A pool that seems to be closer to its target balance than it is in actuality cannot accurately manage incentives through fees.

MediumFunction in `BridgeFallback` Reverts During Retry Due to `onlySelf` ModifierFixed

The `BridgeFallback` contract uses the `onlySelf` modifier to restrict access to its `addRevert*()` functions, intending for these functions to be called only internally within the `BridgeFallback` contract itself. However, the `retryOnReceive` function, designed to retry failed cross-chain operations, attempts to call these `addRevert*()` functions when a retry fails, using a `try-catch` block. In that case, the `msg.sender` will be the external caller of `retryOnReceive`, not the `BridgeFallback` contract itself. This causes a revert, because the `onlySelf` modifier evaluates as false.

MediumLack of Price Feed Staleness ValidationFixed

The `TokenPriceOracle` contract retrieves price data from `Chainlink` price feeds but lacks validation checks for stale or outdated price data. This could lead to the usage of outdated prices in critical operations if the price feed experiences delays or issues.

LowArbitrage Is Only Prohibited For Negative Price DriftFixed

The `getDriftProtocolFee()` is intended to eliminate any profits that might be made from token arbitrage. If `srcPrice < dstPrice`, it will charge the user any profits made from the arbitrage as a fee. Otherwise it will return a fee of zero. However, if the `srcStatus == IStableTokenPriceOracle.PriceDeviationStatus.Normal`, then a fee of zero is returned regardless of whether an arbitrage opportunity exists. If the `dstPrice` has an upwards depeg such that it is worth more than the pegged `srcPrice` (such as $1.01), then an arbitraged trade is possible. While price depegs in the upwards direction tend to repeg quickly, it is important to consider how rapid fluctuations in liquidity affect the protocol.

LowEmpty `fallback()` Function in `BridgeFallback` Masks ErrorsFixed

The `BridgeFallback` contract currently has an empty `fallback()` function. This implementation creates a security concern in the context of upgradeable contracts. When users interact with the `Bridge` contract using an outdated ABI after an upgrade, calls to functions that no longer exist or have changed signatures will be routed to the `fallback()` function. Because the `fallback()` function is empty, these calls will appear to succeed (they won't revert and will return no data).

LowInaccurate balance checkFixed

As described by the delta algorithm, the `Pool.transfer()` function will check that there is sufficient balance in the destination pool before executing a transfer. However, the balance check does not match the balance decremented on receival: ``` // Pool.transfer() feeInfo.lastKnownBalance = amountGD - feeInfo.lpFee + feeInfo.eqReward; if (peerPoolInfo.balance < amountGD) { revert TokiInsufficientPoolLiquidity( peerPoolInfo.balance, amountGD ); } // Pool.recv() peerPoolInfo.lastKnownBalance = peerPoolInfo.lastKnownBalance - feeInfo.lastKnownBalance; ``` If `feeInfo.lpFee > feeInfo.eqReward`, it is possible that the transfer will overdraft and revert due to underflow on the receiving side, thereby breaking the guarantee of finality.

LowLocked EtherFixed

Empty `receive()` function can lead to permanently locked ETH in contract if users accidentally send ETH directly to the contract without using the intended functions.

LowPrice Unit Inconsistency Risk in Token Price Oracle ImplementationFixed

The current token price oracle implementation lacks validation for price units and decimals between different chains' native tokens. This could lead to incorrect fee calculations if the price feeds use inconsistent units or decimal places. ```solidity function _calcSrcNativeAmount( uint256 dstGas, uint256 dstTokenAmount, uint256 srcTokenPrice, // No unit validation uint256 dstTokenPrice, // No unit validation uint256 dstGasPrice, uint256 riskBPS ) internal pure returns (uint256) ``` This could result in incorrect fee calculations leading to under/over charging users and potential economic losses for users or relayers.

Show 5 more
LowUnable to Transfer ETH to PoolFixed

The `Bridge.deposit()` contract is `payable`. However, the `IBCUtils.safeTransferFrom()` function does not support sending ETH. This prevents users from depositing ETH into the pool when calling `Bridge.deposit()` directly.

LowUnbounded Loop in `_deltaSourceUpdate` Leads to Potential Denial-of-Service (Dos) AttackFixed

The `_deltaSourceUpdate()` function in `Pool.sol` contains a loop that iterates over all entries in the `_peerPoolInfos` array. The number of iterations of this loop is not bounded by any constant or configuration parameter. If the number of peer pools grows large, this loop could consume excessive gas, potentially leading to out-of-gas errors and a denial-of-service (DoS) condition. **Specifically, the following loops are affected:** ```solidity for (uint256 i = 0; i < peerPoolInfosLength; ++i) { ... } ```

LowUndisabled initializers within upgradeable contract implementationFixed

The constructors of implementation contracts fail to call the `_disableInitializers()` function, leaving the contracts vulnerable to unexpected initialization outside the proxy.

LowUnprotected `reinitializer` functionFixed

The `RecoveredLCPClientUpgradeable.upgrade()` is an unprotected `reinitializer` function that can be exploited in protocol takeover scenarios.

LowUsage of the transfer function can lead to unexpected future behaviorFixed

Relying on `address.transfer()` in Solidity for a reentrancy-free transfer of funds can lead to unexpected failed calls. The gas cost of different opcodes has been adjusted before and can be adjusted again, which may create unforeseen side effects.

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (47)

  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/Bridge.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IDecimalConvertible.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IBridgeQuerier.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IETHVault.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/library/MessageType.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/BridgeQuerier.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/BridgeFallback.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IRelayerFeeCalculator.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/handler/OwnableIBCHandlerUpgradeable.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/IBCChannelUpgradableModuleBase.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/library/IBCUtils.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/ITransferPoolFeeCalculator.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/BridgeBase.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/ITokiErrors.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/yui.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/StaticFlowRateLimiter.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IETHBridge.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IStaticFlowRateLimiter.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IBridgeRouter.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/DecimalConvertibleUpgradeable.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IBridgeManager.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IAppVersion.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/BridgeChannelUpgradeFallback.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IPoolRepository.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IStableTokenPriceOracle.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/BridgeManager.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/GasPriceOracle.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IChainlinkPriceFeed.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IGasPriceOracle.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/clients/LCPClientUpgradeable.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/clients/RecoveredLCPClientUpgradeable.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/Pool.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/ETHBridge.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/ITokiOuterServiceReceiver.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/StableTokenPriceOracle.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/PoolRepository.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/TokenPriceOracle.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/VersionStringValidator.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IReceiveRetryable.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/replaceable/RelayerFeeCalculator.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/ITokenPriceOracle.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/replaceable/TransferPoolFeeCalculator.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IBridge.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IReceiveRetryableSelf.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/interfaces/IPool.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/ETHVault.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257
  • https://github.com/datachainlab/toki-bridge-evm-contracts/src/BridgeStore.sol at commit dcccb98ee4edf58a7956cc9c7cc804969b407257

Part of Datachain’s security record

Datachain
Audits7 audits by 1 firmLast audit Jul 2025, by Quantstamp.
Critical findingsNo open critical findingsAcross 7 reports.
Open Datachain’s security record

Security firm

Quantstamp

236 projects reviewed · 332 reports · latest Oct 2026

See Quantstamp’s audits

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