Prepared by:
HALBORN
Last Updated 07/15/2025
Date of Engagement: May 26th, 2025 - June 2nd, 2025
100% of all REPORTED Findings have been addressed
All findings
3
Critical
0
High
0
Medium
1
Low
0
Informational
2
Caldera
engaged Halborn
to conduct a security assessment on their smart contracts beginning on May 26th, 2025 and ending on June 2nd, 2025. The security assessment was scoped to the smart contracts provided to Halborn. Commit hashes and further details can be found in the Scope section of this report.
The Caldera
codebase in scope consists of the MetaERC20
smart contracts, a cross-chain token bridge built on top of the Metalayer/Hyperlane messaging protocol. It enables seamless transfer of ERC20 tokens between different blockchain networks while maintaining token supply integrity and providing security controls for high-value transfers.
Halborn
was provided 7 days for the engagement and assigned a full-time security engineer to review the security of the smart contracts in scope.
The purpose of the assessment is to:
Identify potential security issues within the smart contracts.
Ensure that smart contract functionality operates as intended.
In summary, Halborn identified some improvements to reduce the likelihood and impact of risks, which were completely addressed by Caldera
. The main one was the following:
Implement a functionality to disallow transfers marked as executed during emergency to be executed again
Halborn
performed a manual review of the code. Manual testing is great to uncover flaws in logic, process, and implementation.
The following phases and associated tools were used throughout the term of the assessment:
Research into architecture, purpose and use of the platform.
Smart contract manual code review and walkthrough to identify any logic issue.
Thorough assessment of safety and usage of critical Solidity variables and functions in scope that could led to arithmetic related vulnerabilities.
EXPLOITABILITY METRIC () | METRIC VALUE | NUMERICAL VALUE |
---|---|---|
Attack Origin (AO) | Arbitrary (AO:A) Specific (AO:S) | 1 0.2 |
Attack Cost (AC) | Low (AC:L) Medium (AC:M) High (AC:H) | 1 0.67 0.33 |
Attack Complexity (AX) | Low (AX:L) Medium (AX:M) High (AX:H) | 1 0.67 0.33 |
IMPACT METRIC () | METRIC VALUE | NUMERICAL VALUE |
---|---|---|
Confidentiality (C) | None (I:N) Low (I:L) Medium (I:M) High (I:H) Critical (I:C) | 0 0.25 0.5 0.75 1 |
Integrity (I) | None (I:N) Low (I:L) Medium (I:M) High (I:H) Critical (I:C) | 0 0.25 0.5 0.75 1 |
Availability (A) | None (A:N) Low (A:L) Medium (A:M) High (A:H) Critical (A:C) | 0 0.25 0.5 0.75 1 |
Deposit (D) | None (D:N) Low (D:L) Medium (D:M) High (D:H) Critical (D:C) | 0 0.25 0.5 0.75 1 |
Yield (Y) | None (Y:N) Low (Y:L) Medium (Y:M) High (Y:H) Critical (Y:C) | 0 0.25 0.5 0.75 1 |
SEVERITY COEFFICIENT () | COEFFICIENT VALUE | NUMERICAL VALUE |
---|---|---|
Reversibility () | None (R:N) Partial (R:P) Full (R:F) | 1 0.5 0.25 |
Scope () | Changed (S:C) Unchanged (S:U) | 1.25 1 |
Severity | Score Value Range |
---|---|
Critical | 9 - 10 |
High | 7 - 8.9 |
Medium | 4.5 - 6.9 |
Low | 2 - 4.4 |
Informational | 0 - 1.9 |
Critical
0
High
0
Medium
1
Low
0
Informational
2
Security analysis | Risk level | Remediation Date |
---|---|---|
Emergency functions do not consider a possible message arrival in the future | Medium | Solved - 05/28/2025 |
Floating pragma version | Informational | Solved - 07/08/2025 |
Redundant checks in token recovery functions | Informational | Solved - 07/08/2025 |
//
MetaERC20Hub
and MetaERC20Spoke
have emergency functions to handle stuck messages. For example, EMERGENCY_UNLOCK()
:
function EMERGENCY_UNLOCK(bytes32 _transferId, address _recipientAddress) external onlyRole(ADMIN_ROLE) {
// ...
}
However, it fails to consider that the message can actually potentially arrive in the future, resulting in inconsistent state. This will result in inconsistent state, effectively a double-spending scenario.
Consider implementing a functionality to toggle the message as executed, which will then revert upon handling it here:
if (executedTransfers[message.transferId]) revert AlreadyExecuted();
SOLVED
: The Caldera
team has solved the issue in 7e4c282
by following the recommendation.
//
The contracts in scope have a non-fixed pragma version:
pragma solidity >=0.8.20 <0.9.0;
Not using a fixed pragma version is considered a bad practice and instead it is recommended to use a fixed one.
Consider using a fixed pragma version
SOLVED
: The Caldera
team has fixed the issue in PR #53 based on the recommendation.
//
The base MetaERC20Base
has the following code when recovering tokens accidentally sent to the contract where _amount
is the function input:
if (_amount > token.balanceOf(address(this))) revert("Insufficient token balance");
This check is redundant as upon conducting the transfer, the code would revert anyway if the balance is insufficient. A similar check is also in recoverETH()
where it is also redundant.
Consider removing the checks as they serve no purpose
SOLVED
: The Caldera
team have solved the issue in PR #55 based on the recommendation.
Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.
// Download the full report
Metalayer-Fetcher: Smart Contract Assessment
* Use Google Chrome for best results
** Check "Background Graphics" in the print settings if needed