Chainport2023

CertiKCode version: not recorded (see the report)

CertiK reviewed ChainPort Cross-Chain Bridge (Chainport2023) on 20 Jul 2023: 45 findings, 0 critical; 26 marked fixed, 1 acknowledged, 18 open.

No open critical findings
Open the reportOpen ChainPort Cross-Chain Bridge’s security record

Report hosted on skynet.certik.com.

Trustblock does not review code.

Findings45

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

SeverityOpenAcknowledgedFixed
Critical000
High011
Medium603
Low12022
MediumImproper verification of transaction replayOpen

Code at the pointed lines searches on the persistent storage for transaction with the given `data_passed` on the provided `network_id`. Then, if such transaction is found the `mint_bridge_tokens` returns with no-operations. The data passed in the `data_passed` parameter includes the transaction signature computed in line 94. The signature algorithm of Ethereum accounts is ECDSA which is based on random one-time-use numbers for signature generation. This means that distinct signatures of the same data by the same account are different. So, querying a transaction by including the signature as a parameter is always going to fail since each transaction, even if containing the same data, will produce different signatures. As a result, the logic to exit the `mint_bridge_tokens` function if `prev_tx_obj` is found is not able to detect already created transactions.

MediumMissing replay protection for minting handlerOpen

The `cardano_one_time_minter` function mints Cardano tokens and tracks them by saving the new token information on the database. However, no data about the on-chain transaction that caused such mint is contextually stored with the minting operation. As a result, if the `cardano_one_time_minter` handler is called twice (e.g. because of bugs in the calling logic, misconfiguration of cloud resources, ...) in reference to the same on-chain event, then two distinct mint actions are executed, and proportion between locked tokens and minted ones is altered.

MediumPotential asset_name Collision AttackOpen

Variable with string (`asset_name`) and (`token_name`) is salted with postfix and truncated to first 32 bytes without checking it's length. This may result in collision attack or bugs of wrong parameters in the case of 0 length strings or names which differ only for characters after the 31st.

MediumPotential state misalignment with chain stateOpen

The function `cardano_one_time_minter()` calls the function `mint_one_time_token()` on the Cardano object in order to mint a new token. Subsequently, code at the pointed locations, updates the off-chain persistent storage. However, such storage updates may fail (e.g. for a database connection issue), trigger an Exception and leave the off-chain logic in an outdated state in respect to what happened on-chain. Considering the the off-chain logic drives the bridge business logic, this condition must be avoided.

MediumTransaction Hash Can Be Lost Due To Slack ErrorOpen

The function `burn_utxo()` from `cardano.py` performs three operations on a `try` statement. If any of those operations fail to throw an error, the `except` block will execute. Two of those operations are network related and are prone to fail due to connection errors. But, an issue might arise if one operation was performed successfully and the other one is not (for example, if the slack bot is down). The transaction submission was successful but the slack message threw an exception, the function will return `None` as the transaction hash, losing the correct hash that corresponds to the transaction. A similar issue occurs on the functions `release_tokens()`, `mint_one_time_token()` and `mint_token()` from the same file.

MediumUnhandled error on minting transaction submissionOpen

The code at the pointed lines submits a transaction to the network and saves such information on the persistent storage. However, if the transaction submission fails for any reason, there is no error handling to either recover from the failure or investigate the reason of the failure. Moreover, if the error on the transaction submission happens while decoding the answer from the service through which the transaction was submitted, the system could be exposed to a replay of the minting transaction in reference to the same deposit. In fact, if the transaction gets included in the chain but the code fails before saving such information, then the system is in the state in which a new minting operation is issued, which causes a loss of funds.

LowCode DuplicationOpen

The functions `session_get_pending_cardano_burn_transactions()`, `session_get_pending_cardano_deposit_transactions()` and `session_get_pending_cardano_mint_transactions()` from `cardano_transaction.py` are almost identical. The shared functionality could be extracted into a separate function from which the linked functions could use with their needed `transaction_type`.

LowConfiguration Inside The CodeOpen

The linked statements are meant to configure the environment on which the script will run. On the platform chosen by the client to deploy the scripts (AWS), the configuration is done outside the code, either via the console or via another script (like terraform). Moreover, lambdas should get their environment variables and context from the `context` parameter. Additionally, the linked whitelists could be defined externally. The reason is that if a change needs to be made into one, there is no need to redeploy the lambdas.

LowCounter Could Start From 0Open

In the function `session_get_latest_cardano_event_counter_by_name` the function returns `1` if a `CardanoBridgeEvent` is not matching with any `name` and `res.counter + 1` if the `name` matches an existing `CardanoBrdigeEvent`. Starting the counter from `0` can avoid the necessity of adding `1` to `res.counter` when the condition is met.

LowDuplicated Fields in DBOpen

In the function `get_or_create_cardano_deposit_transaction_and_bridge_event` the `deposit_transaction_obj.id` is assigned to two different variables, respectively `bridge_event_obj.deposit_tx` and `bridge_event_obj.burn_tx`, that are stored in DB resulting in a duplicated field.

Show 8 more
LowInput sanitation and asserting typesOpen

Most functions in the codebase are missing types and input values sanitation. Since parameter types in python are suggestions not enforced, it can lead to processing other types as inputs that were anticipated. Additionally, the above functions should document ranges of expected inputs and proper sanitation of input parameters ensured.

LowMisleading `Burn` Address NameOpen

The name `burn` of the address used for recording and monitoring deposits on the Cardano blockchain is misleading. In web3 world, a burn address is a digital wallet that can't be accessed because it doesn't have a private key attached to it, however, as shown in the commented out of code function `move_utxos_from_burn_address` seems the team has a different idea behind the `burn` address. Indeed the burn address is used in the codebase as a `deposit` address. Misleading naming may lead users to use system in a way they did not intent do - e.g. they may expect certain guarantees from `burn` address, and otherwise they may have decided on different strategy of moving their funds.

LowToo Long Function `handle_non_evm_deposit_tx()`Open

The linked function has almost 300 Lines of Code. This amount reduces the code's readability and maintainability.

LowTyposOpen

The linked statements contain typos: - "addess" should be "address" - "maintaner_addresss" should be "maintainer_address" - "benficiary" should be "beneficiary" - "carando" should be "cardano" - "cardaon" should be "cardano" - "policys" should be "policies" - "recieved_sum" should be "received_sum" - "reciever_address" should be "receiver_address" - "fee_reciever_web3_identity_id" should be "fee_receiver_web3_identity_id" - "cardano_reciever_web3_identity_obj" should be "cardano_receiver_web3_identity_obj" - "returuns" should be "returns" - "submiting" should be "submitting" - "transaciton" should be "transaction" - "useable" should be "usable" - "verifcation_key" should be "verification_key" - "verificaiton" should be "verification" - "issuer_web3_addess" should be "issuer_web3_address"

LowUnnecessary Parameter CastingOpen

The function `is_multi_asset_utxco_useable()` defines the parameter `asset_value` as a string. Then, when using the variable, it is cast into an integer. Moreover, the function's caller casts the `asset_value` parameter into a string. These casts are redundant because the parameter could be used directly on its `int` representation. If it was intended to take `asset_value` as string, then should be considered logic that handles if provided data does not adhere expected format , leading to incorrect conversion to integer. Otherwise, ensure proper integer was provided as input.

LowUnnecessary VariablesOpen

The linked local variables are not necessary and their value can be used directly. This would improve the code's readability.

LowUnused VariablesOpen

The pointed variables are declared but never used in the codebase. E.g. in function `is_valid_deposit_utxo` the variable `_` is filled with the `target_network_id` taken from `transaction_metadata`, however, it is never used inside the function.

LowUsage of Magic NumbersOpen

Different magic numbers are used as-is in code.

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