CertiK reviewed ChainPort Cross-Chain Bridge (ChainPort-Cardano Bridge) on 19 Dec 2022: 21 findings, 1 critical; 13 marked fixed, 8 open.
Report hosted on skynet.certik.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 1 |
| High | 1 | 0 | 0 |
| Medium | 0 | 0 | 3 |
| Low | 7 | 0 | 9 |
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
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`.
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.
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 ```
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.
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.
Many imported files are outside the scope of the audit. We treat 3rd party entities as black boxes and assume their functional correctness.
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.
The report names a repository or files. Open the report to see its scope.
1,044 projects reviewed · 1,375 reports · latest May 2025
See CertiK’s auditsSomething 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