Datachain - ELC For Bridge - BSC

QuantstampRepository at commit 78d1349

Quantstamp reviewed Datachain (Datachain - ELC For Bridge - BSC) on 6 Dec 2024: 6 findings, 0 critical; 5 marked fixed, 1 acknowledged.

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

Report hosted on certificate.quantstamp.com.

Trustblock does not review code.

Findings6

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

SeverityOpenAcknowledgedFixed
Critical000
High000
Medium001
Low014
MediumUntrusted Epochs Can Be Exploited by One Malicious Validator, Resulting in Finalization of Incorrect BlocksFixed

Suppose we want to finalize a target block `x` with reference to a trusted block `w`. In order to finalize `x`, it is required to provide a consecutive sequence of headers starting at `x` and ending in two adjacent headers (call them the "finalizing blocks" `y` and `z`) that contain BLS signatures from their corresponding active validator set. At the start of every epoch, a new validator set is elected. This validator set becomes active once an epoch-specific checkpoint is reached: before the checkpoint, headers must be signed by validators from the trusted epoch; starting from the checkpoint, headers are required to be signed by the new validator set; before the checkpoint, BLS signatures used to finalize blocks must come from validators of the trusted epoch; *after* the checkpoint, such BLS signatures must come from the new validator set. This process updates with every subsequent validator set election. Ordinarily, finalizing incorrect blocks is difficult because 14 out of 21 validators of an active validator set would need to sign BLS signatures for two consecutive blocks in order to finalize a block that comes prior. The light client also ensures that at least 8 validators in an untrusted epoch are from the previous trusted epoch. However, it appears to be possible for one malicious validator, Alice, to introduce 13 malicious validators into an untrusted validator set along with herself in the following scenarios. Along with (or inside) an incorrect target block, Alice transmits a fake new validator set and a sequence of fake headers that she signs herself in order to pass the `verify_seal()` check, up to and including the checkpoint. She will also submit finalizing headers post-checkpoint with BLS signatures coming from the malicious validator set, meeting quorum. See the "Exploit Scenario" section below for an example-based explanation of the issue. In the worst case, the finalization of incorrect blocks may impact components of the LCP project that rely on the light client for correct data: for example, if a bridge were to be fed incorrect data regarding the state of the `IBCStore`'s storage root, it could be assumed that messages were broadcast when they in fact weren't, resulting in, for example, the issuing of funds on a destination chain without the appropriate conditions.

LowClient Can Be Initialized with Zero HeightFixed

The current light client implementation is in violation of the [specification](https://github.com/datachainlab/parlia-elc/blob/main/SPEC.md#client-initialisation), which states that clients must be initialized only with heights greater than zero.

LowCorrespondence Between `chain_id.version` and `latest_height.revision_number` Is Not Enforced, Potentially Violating StateID UniquenessFixed

When a "State ID" is being generated from a client state and a consensus state, the client state is first simplified by calling `ClientState::canonicalize()`. This sets the `latest_height` to `{revision_number: self.chain_id.version, revision_height: 0}`. As such, there is an implicit correspondence between `chain_id.version` and `latest_height.revision_number`. However, no such correspondence is enforced when instantiating a `ClientState` (e.g. in `ClientState::try_from(value: RawClientState)`). Therefore, via data corruption, it is in principle possible for client states that are intended to refer to the same client state to be different via `chain_id.version`, and therefore result in different state IDs being generated for each.

LowRevision Number Is Not Validated When Decoding Client StateFixed

In communications with the client, it was determined that for any given `ClientState`, the `latest_height.revision_number` value should be equal to 0. However, when decoding a `RawClientState`, there is no validation indicating that a non-zero `revision_number` is forbidden. This may enable the use of invalid client states in the ELC.

LowUnexpected Client Behaviour if Pre-Bohr Fork Blocks Are UsedFixed

The current light client implementation is only compatible with blocks generated after the Bohr fork. In itself, this is merely an operational consideration as it represents the expectation of the developer. However, if a block height from before the Bohr fork is submitted, the client may behave unexpectedly because it lacks validation to prevent the submission of pre-Bohr fork blocks. The header parsing and BLS signature verification logic rely on the structure introduced in BEP-341 and BEP-402, which added fields like turn length data and modified signature verification processes. In BEP-341, the header's extra data field includes the turn length information, and the parsing logic accounts for this when extracting vote attestation data. Similarly, BEP-402 introduced changes to signature verification by adding new fields that must be verified. The parsing functions, such as `get_vote_attestation` and `get_validator_bytes_and_tern_term`, are designed to work with the modified header structure post-Bohr fork. When creating a client, it is assumed that the latest block height exceeds the Bohr fork height, but there is no explicit validation to enforce this. Submitting a block from before the Bohr fork can lead to parsing errors or unexpected client behaviour.

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 (44)

  • https://github.com/datachainlab/parlia-elc/light-client/src/errors.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto/src/prost/google.protobuf.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/build.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto-compiler/src/main.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto-compiler/src/cmd/clone.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto/definitions/ibc/lightclients/parlia/v1/parlia.proto at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/.gitignore at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto/src/prost/ibc.lightclients.parlia.v1.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/fixture/localnet.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/fixture/mod.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/header/eth_header.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/header/mod.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/message.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto/src/google.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto/Cargo.toml at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/misc.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto/src/IBC_GO_COMMIT at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto/src/prost/ibc.core.client.v1.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto/src/prost/cosmos.upgrade.v1beta1.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto-compiler/src/cmd.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/Cargo.lock at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/client.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto-compiler/src/cmd/compile.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto-compiler/Cargo.lock at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/misbehaviour.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/rust-toolchain at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/SPEC.md at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto-compiler/Cargo.toml at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/header/validator_set.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/commitment.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/client_state.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto-compiler/README.md at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/header/vote_attestation.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/lib.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/Cargo.toml at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/header/constant.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/header/epoch.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/Cargo.toml at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/LICENSE at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/consensus_state.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/.github/workflows/ci.yaml at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/proto/src/lib.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/README.md at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620
  • https://github.com/datachainlab/parlia-elc/light-client/src/header/eth_headers.rs at commit 78d134938e24b05b5faaee71c30e7eae2ca6c620

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