ChainPort-Cardano Bridge

CertiKCode version: not recorded (see the report)

CertiK reviewed ChainPort Cross-Chain Bridge (ChainPort-Cardano Bridge) on 19 Dec 2022: 21 findings, 1 critical; 13 marked fixed, 8 open.

1 critical finding, fixed
Open the reportOpen ChainPort Cross-Chain Bridge’s security record

Report hosted on skynet.certik.com.

Trustblock does not review code.

Findings21

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

SeverityOpenAcknowledgedFixed
Critical001
High100
Medium003
Low709
HighPotential Vulnerability To Deep RollbackOpen

A **rollback** refers to the chain of events that occur when a node discovers that its local version of the blockchain is different from the canonical one that the other nodes agree on. In order to prevent a contradiction of state, the differing node must discard the last couple of blocks that are different from the target blockchain. This `discarding of blocks` is what is known as the **rollback**, and can ultimately call for a loss of transaction outputs and changes of state that occurred within the blocks that were discarded. Therefore, if a blockchain of length `n` has a rollback of length `k`, then the state of the blockchain after the rollback will be at block `n-k`. Please see the attached link for further information regarding [Rollbacks on Cardano](https://playground.plutus.iohkdev.io/doc/plutus/explanations/rollback.html) ---- In the aforementioned lines of code, the block threshold check will prevent the effects of shallow rollbacks; however, deep rollbacks can allow the following exploits to occur: 1. Loss of EVM/Sidechain Tokens With No Return * A user deposits tokens on the EVM/Sidechain to get to Cardano * A rollback happens and the UTxO gets deleted * The user now has no tokens on Cardano, nor the EVM/Sidechain 2. Double spending UTxO on Mainchain * A user sends `UTxO A` to the burn address * `Signature A` is created to redeem tokens from the Mainchain * EVM Tokens are recovered using `Signature A` * A rollback occurs which reverts the state of the chain and the user gets back `UTxO A` * The user deposits `UTxO A` again to create `Signature B` * EVM Tokens are recovered using `Signature B` and, as a result, the user has double the amount of tokens on EVM 3. Double spending UTxO on Sidechain * A user sends `UTxO A` to the burn address * `Token X` is minted on the Sidechain * The user receives `X Tokens` * A rollback occurs which reverts the state of the chain and the user gets back `UTxO A` * The user deposits `UTxO A` again to mint more `Token X` * The user receives more `X Tokens` and, as a result, the user has double the amount of `X Tokens` on the Sidechain

LowDifferent Variables With Same NameOpen

In the file `create_bridge_token.py`, the method `create_new_bridge_token()` calls two functions: `init_contract()` and `init_contract_with_default_address()`, and then stores the returned values in the same local variable: `target_network_bridge_contract`. ---- In the file `mint_tokens.py`, the method `mint_bridge_tokens()` calls two functions: `init_contract()` and `init_contract_with_default_address()`, and then stores the returned values in the same local variable: `target_network_bridge`.

LowIncorrect Checking of `Policy ID`Open

The `policy_asset_hash` is the concatenation of a `policy_id` and hex-encoded `asset_name`. Thus, checking that a given `policy_id` is a substring of `policy_asset_hash` is too permissive. Although it is very unlikely, there could be a `policy_asset_hash` containing `policy_id` in the middle instead of at the beginning.

LowLoops Used Instead of List ComprehensionsOpen

Instead of constructing a new list by iterating over an existing one, a list comprehension can be used. This is more clear and concise. For example: ```python return [get_mdy_date_string(port.created_at) for port in ports] ``` ```python port_list = [] for port in ports: created_at_mdy = get_mdy_date_string(port.created_at) port_list.append(created_at_mdy) return port_list ```

LowMissing Checks on `metadata`Open

In the `cardano_monitor.py` file, the `cardano_to_evm_transaction()` method extracts the metadata from the deposited UTxO to get the `target_network_id` and the `target_web3_address`, however no checks are performed on these values to prevent unexpected errors. \ Regarding `target_network_id`: this value will be used in the case of a transfer from Cardano to an EVM sidechain to obtain the `target_token_obj` using the method `session_get_target_token_by_base_token_id_and_network_id()`. This function is outside the scope of this audit, but we suppose it could return `None`. \ The lack of check on the metadata could lead to calling `cardano_to_mint_transaction()` with `None` as an important parameter making the whole execution of the function fail. \ Moreover, a failure here will imply that the `cardano_burn_monitor()` will not be executed completely, and prevent the future execution of this function because the problematic transaction would have not been removed.

LowThird Party DependenciesOpen

The program interacts with the third-party `PyCardano` and `BlockFrost` APIs. The scope of the audit treats 3rd party entities as black boxes and assumes their functional correctness. However, in the real world, 3rd parties can be compromised and this may lead to lost or stolen assets.

LowUnknown ImplementationsOpen

Many imported files are outside the scope of the audit. We treat 3rd party entities as black boxes and assume their functional correctness.

LowUTxO Buildup At the Burn AddressOpen

Anyone can send any UTxO to the burn address, and every UTxO at the burn address is collected for inspection each time. When the `cardano_utxo_monitor` runs, it will collect these (possibly "invalid") UTxOs to attempt to process them. As more UTxOs at the burn address pile up, this can slow down the `cardano_utxo_monitor` process. Furthermore, when tokens are burned at the burn address as expected, newly produced `change UTxOs` left at the burn address will not be cleaned up either. ---- UTxO buildup can also happen if multiple kinds of tokens are mistakenly sent in one transaction. In the function `get_transaction_output_multi_asset()`, all the multi asset tokens associated to a given `TransactionOutput` are extracted and the `policy_hash` and `value` of only the first token are returned.

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.

Part of ChainPort Cross-Chain Bridge’s security record

ChainPort Cross-Chain Bridge
Audits5 audits by 2 firmsLast audit Jan 2024, by Zokyo.
Critical findingsNo open critical findingsAcross the 5 reports, 1 critical finding was reported. It is marked fixed by the firm that reported it.
Open ChainPort Cross-Chain Bridge’s security record

Security firm

CertiK

1,044 projects reviewed · 1,375 reports · latest May 2025

See CertiK’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