ChainPort Cross-Chain Bridge security record

Arbitrum, BNB Chain, Ethereum, Fantom, Polygon (POS)chainport.ioX

As of 3 Nov 2026, ChainPort Cross-Chain Bridge has 5 audit reports by 2 security firms on Trustblock; the latest is by Zokyo, dated 3 Jan 2024. Those reports list no open critical findings.

Critical findings
No open critical findings
Across the 5 reports, 1 critical finding was reported. It is marked fixed by the firm that reported it. See the findings
Open the latest report
Your label, live
Get the label for your site

Record last updated . It holds audits, findings and contracts up to Nov 2026, and incidents up to Oct 2026. Trustblock does not review code.

Audits5

Newest first

AuditSecurity firmDateScopeCritical findingsReport
ChainportSecurity firm: ZokyoDate: Scope: Not recorded (see the report)No open critical findingsOpen · IPFS
Chainport2023Security firm: CertiKDate: Scope: Not recorded (see the report)No open critical findingsOpen · skynet.certik.com
Chainport (PORT)Security firm: CertiKDate: Scope: Not recorded (see the report)No open critical findingsOpen · skynet.certik.com
Chainport (Sol part)Security firm: CertiKDate: Scope: Files named in the reportNo open critical findingsOpen · skynet.certik.com
ChainPort-Cardano BridgeSecurity firm: CertiKDate: Scope: Not recorded (see the report)1 critical finding, fixedOpen · skynet.certik.com

Findings63

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

SeverityOpenAcknowledgedFixed
Critical000
High061
Medium804
Low20024
HighMissing Token Address Whitelist CheckChainport2023 · CertiK · 20 Jul 2023Fixed

The function `handle_non_evm_token_transfer_event()` does not check whether the token's address being used belongs to the whitelist defined on the same file. Without this check, the whitelist is useless and users can interact with any token they desire, including malicious contracts.

Open the report
MediumInhomogeneous addresses form in whitelist check.Chainport2023 · CertiK · 20 Jul 2023Fixed

In the function `is_valid_deposit_utxo` the `target_web3_address_whitelist_check` is extracted from `transaction_metadata` to verify its presence in the `whitelisted_addresses` list. The enforced check verifies if the `.lower()` case version of the `target_web3_address_whitelist_check` is present in the `whitelisted_address` list. The problem resides in the fact that addresses from the `whitelisted_address` list are not guaranteed to be lower case. Considering that it is common practice in the EVM ecosystem to provide addresses in their checksummed form, i.e. with the case of the `abcdf` values being different and deterministic, the pointed check, in the current form, would very likely result in false negatives. In fact, the hardcoded list already contains checksummed addresses.

Open the report
MediumTransaction With "ERROR" Status Would Be Saved AsChainport2023 · CertiK · 20 Jul 2023Fixed

On the function `cardano_bridge_utxo_monitor()` the transactions are processed and saved in the database. In case a transaction is valid and had no errors while processing, it is saved with the `transaction_status` property set to 0. However, when a transaction is valid but an Exception occurred while processing it, the transaction would still be saved with the `transaction_status` property set to 0. This issue arises given that the line that changes the status to the value "2" is an equality check "==" rather than an assignment "=".

Open the report
MediumWrong function name pointed in loggerChainport2023 · CertiK · 20 Jul 2023Fixed

The pointed line of code configure the function name as a prefix in the log message, but the wrong function name is used. Reporting `event_by_burn_tx` event as `bridge_event_by_id` can have dangerous implications, as others systems may consume logs and infer from them that bridge event happened instead of burn event, that may have potential harmful implications to a system.

Open the report
MediumPotential Fake Deposit EventChainport (Sol part) · CertiK · 26 Jan 2023Fixed

The deposit and release functions only check if the token to be deposited is frozen. An attacker can call the deposit or release function with a malicious contract as input of the `token` parameter, emit an event "TokensDeposited(address(usdt), attacker, 1000 ether, 56)" in the `balanceOf()`/`safeTransfer()` function of the malicious contract. It is possible that this event will be accepted by the Chainport cross-chain system. If this happens, the attacker can withdraw tokens without depositing any token and drain the pool.

Open the report
LowDict access mismatch in log messageChainport2023 · CertiK · 20 Jul 2023Fixed

The `transaction_metadata` parameter is accessed as a dictionary using the key `type` as a string. If such value does not match the hardcoded one, a log entry is generated with the current value. However when the log entry is generated the current content is accessed again, but using `type` as a Python keyword, not as a string. This very likely results in a `None` value.

Open the report
LowDouble Variable DeclarationChainport2023 · CertiK · 20 Jul 2023Fixed

The function `mint_bridge_tokens()` declares twice the variable `port_obj`. Given that there is no reason to re-instantiate the variable, the second declaration could be removed.

Open the report
LowEmpty String Assigned to `issuer_address`Chainport2023 · CertiK · 20 Jul 2023Fixed

In the function `evm_to_cardano`, every time a new Cardano transaction is created an empty string is assigned to the variable `issuer_address`.

Open the report
LowEnum Index value Used like magic number Instead OChainport2023 · CertiK · 20 Jul 2023Fixed

The function `create_new_cardano_policy()` from `cardano_policy.py` defines the `policy_type` with a value of `1`, like a magic number. Using the index of the `PolicyType` enum instead of using its name, in this case, `one_time_minter` makes the code harder to read.

Open the report
LowImproper `None` Comparison CheckChainport2023 · CertiK · 20 Jul 2023Fixed

The pointed statements compare if the object is distinct from the `None` value. This check is done with the distinct operator `!=` but could be replaced with a more appropriate, readable check. A similar issue occurs with the statement `if object == None` which could be replaced with `if object is None`. Of course behaviour can be overwritten and custom defined for `==` operator, but rule of thumb is to use `is None`. Therefore, it may cause misalignment between different developers working on same codebase , and behavior beyond expectation.

Open the report
Show 10 more
LowImproper type hint for JSON objectsChainport2023 · CertiK · 20 Jul 2023Fixed

Starting from the 3.5 version, Python allows to specify type hints for parameters in functions. Such hints, simply suggest the developer on the expected type and do not enforce any static or dynamic check. This does not imply any word can be used as a type and either Python types should be used or custom ones should be defined. Code at the pointed location uses the `json` word as a type hint but it represents a module. Given the context in which it is used, logic expects a JSON data object to use instead of the `json` module.

Open the report
LowInconsistency In Function's Return ValueChainport2023 · CertiK · 20 Jul 2023Fixed

The linked functions present an inconsistency in the return value they produce. They sometimes return a value and sometimes do not. Indeed, the function assumes that self.api.block_latest() will always return a non-empty value. If this assumption is incorrect, the function will return None, while the return type is set to `int` and it could lead to unexpected behavior.

Open the report
LowInconsistency in Query Result ManagementChainport2023 · CertiK · 20 Jul 2023Fixed

In the functions `session_get_cardano_bridge_event_by_deposit_tx_id` and `session_get_cardano_bridge_event_by_burn_tx_id` the `one_or_none()` method is used to manage the result of the `outer_session.query`, while in function `session_get_cardano_bridge_event_by_id` the `one` getter is used to accomplish the same operation. The [sqlalchemy](https://docs.sqlalchemy.org/en/14/orm/query.html#sqlalchemy.orm.Query.one) documentation suggests that `one_or_none()` returns at most one result or raises an exception and returns `None` if the query selects no rows, while `one()` returns exactly one result or raise an exception. Thus `one()` never returns `None`. Having different strategies to manage the returns value of the session queries generates inconsistency in the codebase error recovery mechanisms.

Open the report
LowInconsistent Check And Error MessageChainport2023 · CertiK · 20 Jul 2023Fixed

The function `is_valid_deposit_utxo` enforces a check verifying if the `transaction_metadata.type` is equal to `deposit_v2` string. However the error message raised when the check is false prints a different string `deposit`.

Open the report
LowInconsistent Comment and CodeChainport2023 · CertiK · 20 Jul 2023Fixed

The comment on the function `generate_unsigned_transaction_with_metadata_v2()` from `cardano.py` is inconsistent with the code. The comment states that the transaction is invalid after `100` blocks, but the code checks if it's invalid after `1000` blocks. The same issue occurs on the function `generate_unsigned_transaction_with_metadata()` from the same file. Behavior is incorrect if comment considered being a specification.

Open the report
LowMisleading key type or variable nameChainport2023 · CertiK · 20 Jul 2023Fixed

The `get_address_from_vkey` function takes a `VerificationKey` for the `vkey` parameter. Instead, the variable name `hot_bridge_skey` initialized with data from the `fetch_keys` parameter suggests a key of type `SigningKey`.

Open the report
LowMissing check on body correctness in transactionChainport2023 · CertiK · 20 Jul 2023Fixed

The `submit_transaction` method in the `Cardano` class is responsible to send a signed transaction to the blockchain through the BlockFrostApi. Such function takes as input the signed transaction as a `Transaction` object and the `TransactionBody`. The body is used to return the transaction hash after the transaction submission. However, there is not any validation that the passed body corresponds to the signed transaction, so that if the caller passed two parameters which do not match, then a `Transaction` is sent but a wrong hash is returned. Such situation should be prevented, so, if buggy software calls the `submit_transaction` with such inconsistency, it is detected through an error.

Open the report
LowMissing check on issuer addressChainport2023 · CertiK · 20 Jul 2023Fixed

The `mint_bridge_tokens` function accepts `issuer_web3_addess` as an optional parameter. In the case in which `None` is passed, then the issuer address is retrieved from the persistent storage. However, code at line 47 always fetches such information from the storage, independently from the provided parameter, so such data is anyway present in the database. In this case, if the `issuer_web3_addess` is provided by the function caller, there is not any check that the supplied value conforms to the fetched one. Moreover, the `issuer_obj` is not used in any part of the `mint_bridge_tokens` function other than line 58

Open the report
LowToo Many DigitsChainport2023 · CertiK · 20 Jul 2023Fixed

Literals with many digits are difficult to read and review.

Open the report
LowUngrouped ImportsChainport2023 · CertiK · 20 Jul 2023Fixed

The linked import statements import different modules from the same package. They could be grouped to improve the code's readability.

Open the report
Show 9 more
LowUnnecessary assignmentChainport2023 · CertiK · 20 Jul 2023Fixed

Code at the pointed lines assigns a value to a variable that is already set to the same value. This is an error prone approach since if during subsequent development iterations such value need to be changed, developer needs to remember or notice to do it twice. Moreover by saving an assignment, compute units are saved.

Open the report
LowUnnecessary Call To `__len__()`Chainport2023 · CertiK · 20 Jul 2023Fixed

The linked statements make use of the `__len__()` method which returns the length of the object. The same result can be obtained by using the `len()` function directly, which is more readable.

Open the report
LowUnresolved `TODO` in production codebaseChainport2023 · CertiK · 20 Jul 2023Fixed

The linked statements are `TODO` comments. Such comments are used to identify unimplemented code logic.

Open the report
LowUnused ArgumentsChainport2023 · CertiK · 20 Jul 2023Fixed

The linked arguments are declared but are not used inside the function's body.

Open the report
Lowunused id parameter in `get_policy_id`Chainport2023 · CertiK · 20 Jul 2023Fixed

`id` parameter in `get_policy_id` is unused.

Open the report
LowUsage Of `print()` In ProductionChainport2023 · CertiK · 20 Jul 2023Fixed

The linked statements are from a `print()` call. Such a function will print to the standard output and is usually meant for testing purposes. Thus, if the value has to be persisted, it is advised to use a more robust logging solution.

Open the report
LowUsing Integers To Represent StatesChainport2023 · CertiK · 20 Jul 2023Fixed

The linked statements use plain integers to represent different states. This technique makes the code more difficult to read as one can not know what that value represents.

Open the report
LowInefficient Conditional StatementChainport (Sol part) · CertiK · 26 Jan 2023Fixed

Comparison `taxPercent >= 0` that is always true may be unnecessary. ```solidity=311 require(taxPercent >= 0 && taxPercent <= precision, "Tax override value"); ```

Open the report
LowMissing Input ValidationChainport (Sol part) · CertiK · 26 Jan 2023Fixed

The given input is missing the check to ensure the `originNetworkId` is not the `officialNetworkId`.

Open the report

Contracts

No deployed address is recorded for these audits.

The reports name a repository or files. Open a report to see its scope.

The repositories and files the reports name

Show this on your site

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.

Content

Facts

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.

Fixed as
Language

Style

Layout
Theme
Accent
Corners

Format

Size
Date
Embed as
HTML
<head>
<script src="https://widget.trustblock.run/project-widget.min.js" defer></script>
</head>
<body>
<div
data-tb-project-widget
data-tb-project-slug="chainport-cross"
></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