TrustNet Score
The TrustNet Score evaluates crypto projects based on audit results, security, KYC verification, and social media presence. This score offers a quick, transparent view of a project's credibility, helping users make informed decisions in the Web3 space.
Real-Time Threat Detection
Real-time threat detection, powered by Cyvers.io,
is currently not
activated
for this project.
This advanced feature provides continuous monitoring and instant alerts to safeguard your assets from potential security threats. Real-time detection enhances your project's security by proactively identifying and mitigating risks.
For more information, click here.
Security Assessments
Summary and Final Words
No crucial issues found
The contract does not contain issues of high or medium criticality. This means that no known vulnerabilities were found in the source code.
Contract owner cannot mint
It is not possible to mint new tokens.
Contract owner cannot blacklist addresses.
It is not possible to lock user funds by blacklisting addresses.
Contract owner cannot set high fees
The fees, if applicable, can be a maximum of 25% or lower. The contract can therefore not be locked. Please take a look in the comment section for more details.
Contract cannot be locked
Owner cannot lock any user funds.
Token cannot be burned
There is no burning within the contract without any allowances
Ownership is renounced
The contract does not include owner functions that allow post-deployment modifications.
Contract is not upgradeable
The contract does not use proxy patterns or other mechanisms to allow future upgrades. Its behavior is locked in its current state.
Scope of Work
This audit encompasses the evaluation of the files listed below, each verified with a SHA-1 Hash. The team referenced above has provided the necessary files for assessment.
The auditing process consists of the following systematic steps:
- Specification Review: Analyze the provided specifications, source code, and instructions to fully understand the smart contract's size, scope, and functionality.
- Manual Code Examination: Conduct a thorough line-by-line review of the source code to identify potential vulnerabilities and areas for improvement.
- Specification Alignment: Ensure that the code accurately implements the provided specifications and intended functionalities.
- Test Coverage Assessment: Evaluate the extent and effectiveness of test cases in covering the codebase, identifying any gaps in testing.
- Symbolic Execution: Analyze the smart contract to determine how various inputs affect execution paths, identifying potential edge cases and vulnerabilities.
- Best Practices Evaluation: Assess the smart contracts against established industry and academic best practices to enhance efficiency, maintainability, and security.
- Actionable Recommendations: Provide detailed, specific, and actionable steps to secure and optimize the smart contracts.
A file with a different Hash has been intentionally or otherwise modified after the security review. A different Hash may indicate a changed condition or potential vulnerability that was not within the scope of this review.
Final Words
The following provides a concise summary of the audit report, accompanied by insightful comments from the auditor. This overview captures the key findings and observations, offering valuable context and clarity.
Ownership Privileges
- The governor can pause or unpause the entire bridge.
- The governor can initiate an upgrade of the Solana token bridge contract.
- The governor can initiate an upgrade of the Solana core bridge contract.
- The governor can change the guardian set for the entire bridge.
- The governor can change the per-transaction value limit on the entire bridge.
- The governor can change the 24-hour value limit on the entire bridge.
- The governor can trigger an emergency reset of the rate limits on the entire bridge.
- The update_key holder can update the bridge_gov contract.
- The update_key holder can update the bridge contract.
- The update_key holder can update the update_key.
- The send_all_key holder can update the send_all_key.
- The send_all_key holder can emergency transfer funds to the recipient address.
- The guardians can mint tokens for the user, with the help of the lock transaction hash.
- The guardians can authorize the creation of a new wrapped token contract and the initial minting of tokens for a user, based on the validated VAA from a first-time cross-chain deposit.
- The governor can reset the rate limit.
- The governor can update the rate limit.
The project maintains ownership of wrapped token mints via the Bridge Program PDA to ensure upgradability and emergency response capabilities. This architecture mirrors industry standards (e.g., Wormhole) and is strictly governed by the decentralized Guardian multi-sig via Verified Action Approvals (VAAs). No single entity possesses unilateral control; ownership retention is a deliberate security feature to allow for critical vulnerability patching.
Note - This audit report consists of a security analysis of the Bridge contract. This analysis did not include functional testing (or unit testing) of the token’s logic. Furthermore, we only audited the mentioned contract associated with this project. Other contracts related to this project were not audited by our team. We recommend investors conduct their own research before engaging with the token.
Files and details
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Functions
public
/
State variables
public
/
Total lines
of code
/
Capabilities
Hover on items
/
Findings and Audit result
high Issues | 1 findings
Resolved
#1 high Issue
Centralization Risk of Unilateral Fund Withdrawal ("Rug Pull")
The send_all function constitutes the most severe centralized risk within the entire bridge architecture. It acts as a privileged backdoor or "master key," granting the holder of the send_all_key the unilateral and absolute power to withdraw all user funds held in custody by the proxy contract in a single transaction. This function bypasses all normal bridge logic, including security measures like pause states and rate limits. While intended as a final emergency measure to rescue funds in the event of a critical exploit, its current implementation represents a classic "rug pull" vector. If the send_all_key is compromised or its holder acts maliciously, they can drain the entire bridge of its assets, leading to a total and irreversible loss of funds for all users. The security of every asset locked in the bridge is therefore entirely dependent on the trust and operational security of this single key holder.
medium Issues | 12 findings
Resolved
#1 medium Issue
Centralization of Administrative Control via Hardcoded Single Key
The init function assigns the two most powerful roles in the contract, the update_key and the send_all_key, to the same hardcoded address (gov_$BRIDGEGUARDIAN+0000). The update_key grants the authority to replace the core logic and governance contracts of the bridge, while the send_all_key provides an emergency function to withdraw all funds held by the proxy. This design creates a single point of failure for the entire administrative security of the proxy contract. If the private key corresponding to this single address is compromised, a malicious actor can gain complete and unilateral control over the bridge, allowing them to redirect logic to a malicious contract and steal all locked assets.
Resolved
#2 medium Issue
Fund Loss Due to Recipient Address Being a Non-Owned Account
The end-to-end bridge protocol allows a user to burn tokens on Zera while specifying a destination solana_address that is a validly formatted address but does not belong to a user-owned wallet (e.g., it is the address of another smart contract or program). While the burn_sol function on Zera will succeed, the corresponding release_spl/release_sol transaction on Solana will fail because program addresses cannot own token accounts. This discrepancy between a successful irreversible burn on the source chain and a failed release on the destination chain constitutes a fund loss vector. The vulnerability is the lack of a check within the system to ensure the final recipient can legally own the assets being sent.
Resolved
#3 medium Issue
Centralization of Power in a Single, Unverifiable Governor Address
All administrative functions within this contract are secured by a single authorization check that delegates ultimate authority to one hardcoded address, GOV_CONTRACT. The security of critical operations—such as pausing the bridge, upgrading its core components, and managing the Guardian set—is therefore entirely dependent on the security of this single address. Within the provided codebase, it is not possible to verify the nature of this address. Following the principle of assuming the worst case for any unverified assumption, we must treat this as a single-signature wallet. This represents a critical single point of failure. If the private key for this address were ever compromised, an attacker could unilaterally execute any governance action, posing a catastrophic risk to the bridge's operation and integrity. If the key were lost, all governance functionality would be permanently frozen.
Resolved
#4 medium Issue
State Desynchronization Vulnerability in Two-Step Governance Protocol
The governance model for updating parameters that must be synchronized across both Zera and Solana is fundamentally flawed. It relies on two separate, uncorrelated transactions: (1) a call to the bridge_gov contract to emit a "command" event, and (2) a subsequent call to the bridge_logic contract to apply the state change on the Zera side. The state-changing functions in bridge_logic do not and cannot verify that the parameters they are given match the parameters that were broadcast in the official governance event. This creates a critical vulnerability where a simple human error or a malicious governor can provide different parameters to the two transactions, leading to a state of desynchronization. If the security parameters (e.g., rate limits, guardian sets) on the Zera side do not match the parameters on the Solana side, it will inevitably lead to valid transactions being started on one chain but failing on the other, resulting in the permanent and irreversible loss of user funds.
Resolved
#5 medium Issue
Missing Proper Validation for Parameters
This governance contract is responsible for initiating critical, security-sensitive changes on the Solana side of the bridge by emitting public events. It is therefore of the utmost importance that the parameters emitted in these events are correct and syntactically valid. Several functions in this contract fail to perform any, or perform only partial, validation on their input parameters before broadcasting them. Specifically, update_token_bridge and update_core_bridge do not validate that their account inputs are valid Solana addresses. The update_guardian_keys function fails to validate both the guardian key addresses and the numerical threshold. The pause function has inconsistent and incomplete validation. This systemic lack of input validation means that a simple human error (a typo) by the governor can result in the contract issuing a fundamentally malformed command. This introduces significant operational risk, as a malformed command would cause the cross-chain governance action to fail on Solana, potentially delaying a time-sensitive security upgrade or administrative change.
Resolved
#6 medium Issue
Unvalidated New Contract Address When Upgrading Governance
The proxy contract's upgrade mechanism, handled by the update_gov and update functions, is critically flawed due to a complete lack of input validation. Both functions accept the new target smart_contract name and instance as raw strings and write them directly into the contract's state without any verification. This design blindly trusts that the authorized update_key holder will provide a perfect, valid, and existing contract address. A simple human error, such as a typo, would cause the proxy to permanently save a malformed or incorrect address. If this happens in update_gov, it would brick the entire governance mechanism. If it happens in update, the consequences are catastrophic: all primary user functions would cease, and all funds held by the proxy would become frozen and inaccessible, as the logic contract containing the release functions would become unreachable.
Resolved
#7 medium Issue
Risk of Fund Loss from Unvalidated Emergency Withdrawal Address
The send_all function is a "nuclear option" designed to rescue all funds from the proxy in a catastrophic emergency. This function is critically flawed because it fails to validate its single most important parameter: the destination wallet address. It accepts this address as a raw string and passes it directly to the powerful, native smart_contracts::send_all blockchain function without any checks. In a high-pressure emergency scenario, the administrator could easily make a typo or copy-paste error. If an invalid, null, or malformed address is provided, the contract would command the blockchain to transfer all of its funds to an uncontrollable or non-existent address. This would result in the permanent and irreversible loss of all user funds held by the bridge, turning a rescue attempt into a total disaster.
Resolved
#8 medium Issue
Pause Logic Contradicts "IncomingOnly" Specification
There is a direct and systemic contradiction between the documented behavior of the bridge's pause functionality and its implementation in the code for all incoming transactions. The README specifies that a Level 1 pause is "IncomingOnly," a state designed to halt new outgoing transfers while allowing in-flight "incoming" transfers to complete, thus enabling a safe "draining" of the bridge's pending transaction pipeline. However, the code for all three incoming functions (release_zera, mint_sol, and create_sol) contains a check_pause(1, ...) call. This check causes the functions to revert if the bridge's pause level is 1 or greater. Consequently, when operators activate a Level 1 pause, they will unexpectedly block all traffic in both directions on the Zera side, not just the intended outgoing traffic. This operational confusion during a high-pressure security incident is a significant risk, as it prevents the intended safe clearing of pending transactions and can lead to user funds being trapped in transit for longer than necessary.
Resolved
#9 medium Issue
Complete Absence of Rate-Limiting Check in create_sol Function
The create_sol function, which handles the initial bridging of a new asset from Solana, critically fails to implement any rate-limiting checks. This function operates under the flawed security assumption that if a VAA (Verifiable Action Approval) is validly signed by the Guardians, then the transaction's value must also adhere to the bridge's economic policies (e.g., the per-transaction and 24-hour limits). This assumption is incorrect. The Guardians' role is to attest to the factual validity of an event on the source chain (i.e., that a lock occurred), not to enforce the destination chain's economic rules. Therefore, if an oversized lock transaction were to occur on Solana (for instance, through a bug or exploit on the Solana-side contract), the honest Guardians would be obligated to sign a valid VAA for that large amount. The create_sol function, in its current state, would then receive this valid VAA, check the signatures, and—because it is missing its own rate-limit check—it would proceed to mint an amount of tokens that violates the bridge's fundamental security policy.
Resolved
#10 medium Issue
Complete Lack of Input Validation on Pause Parameters
The update_pause_config function is a privileged administrative function that directly modifies the bridge's emergency pause state. It is critically flawed as it performs zero validation on its pause_level and pause_expiry inputs. The function blindly trusts that the authorized governor will provide valid and logical values. This allows for several failure scenarios due to human error. For example, the governor could accidentally set the pause_level to an undefined value (e.g., 5), putting the contract into an unpredictable state. More critically, they could set the pause_expiry to a timestamp in the past, which would cause the check_pause logic to immediately treat any newly set pause as expired, effectively neutralizing the bridge's primary safety mechanism. A function that controls a critical safety feature must be defensively programmed and must never blindly trust its inputs, even from an authorized administrator.
Resolved
#11 medium Issue
Failure to Validate New Guardian Set and Threshold
The update_guardian_state function, which manages the bridge's root of trust on the Zera side, is critically flawed due to a complete lack of input validation. It blindly accepts and saves a string of new guardian keys and a numerical threshold from the governor. This allows a simple human error to place the bridge into a catastrophic state. For example, a governor could accidentally set the guardian_threshold to a value greater than the number of guardians, which would make it impossible to ever approve another transaction, permanently freezing all incoming bridge transfers. Conversely, setting the threshold to 0 would completely disable the multi-signature security, allowing anyone to forge a VAA and steal funds. A function that controls a security mechanism this critical must be defensively programmed to make entering an insecure or irrecoverable state impossible.
Resolved
#12 medium Issue
Centralized Control over Economic Limits Allows for Complete Bypass of Safety Mechanisms
The reset_rate_limit and update_rate_limit functions grant a single, centralized entity (the GOV_CONTRACT) complete and unilateral control over the bridge's economic rate limits. The update_rate_limit function allows the governor to set the limits to arbitrarily high values, effectively disabling them, while the reset_rate_limit function allows the governor to instantly erase the 24-hour usage history, enabling them to bypass a limit that has been hit. A malicious governor, or an attacker who has compromised the governor's key, can abuse these functions to nullify the bridge's primary defense against rapid fund drainage. This allows for a catastrophic attack where the security limits can be disabled and the bridge can be drained in a small number of transactions, completely defeating the purpose of having a rate-limiting system. This places the trust for the bridge's entire economic defense model onto the security and honesty of a single, centralized key.
low Issues | 3 findings
Resolved
#1 low Issue
Missing Input Validation on Recipient solana_address Leading to Potential Fund Loss
The function accepts the solana_address as a raw String input and proceeds to use it in the final event emission without any form of validation. A smart contract must not blindly trust user-controlled input for critical parameters. This creates a significant risk of user error, such as a typo or pasting an address from a different blockchain. If an invalid solana_address is provided, the function will still succeed: the user's funds will be permanently locked on the Zera side, and an event will be emitted with the malformed address. The Guardians will be unable to process this event on the Solana side, as the destination address is invalid. Because the contract has no mechanism to reverse a successful lock, this scenario would result in the permanent and irreversible loss of the user's funds.
Resolved
#2 low Issue
Missing Input Validation on Recipient solana_address
The function accepts the solana_address parameter as a raw string and does not perform any validation to ensure it conforms to the standard format of a Solana address. A user can provide a syntactically invalid address (e.g., due to a typo, or by pasting an address from a different blockchain). The function will proceed to successfully burn the user's wrapped tokens on the Zera network, but the cross-chain transaction will be impossible for the Guardians to complete on the Solana side. As the burn action is irreversible, this results in a permanent loss of the user's funds.
Resolved
#3 low Issue
Permanent Loss of Administrative Power via Unvalidated Ownership Transfer
The functions for transferring ownership of the contract's two most powerful administrative roles—update_update_key (for the master upgrade key) and update_send_all_key (for the emergency fund-withdrawal key)—are incorrect. Both functions accept the new owner's address as a raw, unvalidated string. This input is then written directly to the contract's state without any checks to ensure it is a syntactically valid, non-null, and controllable address. This creates a risk scenario where the current administrator, through a simple human error such as a typo or a copy-paste mistake, could transfer a critical administrative power to a malformed or non-existent address. Such an action would be irreversible and would permanently "burn" that administrative capability. Losing the update_key would make all future contract upgrades impossible, while losing the send_all_key would neutralize the single most important safety mechanism for rescuing funds in a crisis.
informational Issues | 7 findings
Resolved
#1 informational Issue
Unchecked Return Value from External Price Oracle Contract
During initialization, the contract calls an external price oracle, smart_contracts::get_ace_data, to determine the correct amount of ZRA tokens equivalent to the $100 USD deployment fee. This external call returns a tuple containing a boolean authorized and the numerical rate. The authorized boolean is intended to signal whether the returned rate is valid and up-to-date. The current implementation proceeds to use the rate variable in a critical fee calculation without first checking if the authorized flag is true. This creates a scenario where the contract could be operating on stale, incorrect, or even zero-value price data. While the direct impact in the init function is limited to a failed deployment (e.g., via a division-by-zero panic), it represents a flawed security practice of implicitly trusting external contract return values.
Resolved
#2 informational Issue
Implicit Trust in External Price Oracle Return Value
The function calculates the bridge fee by calling an external price oracle, smart_contracts::get_ace_data, which returns both a rate and an authorized boolean flag. The code currently uses the rate in its calculation without first verifying the authorized flag. While this is unlikely to cause a critical failure, as the most probable outcome of an oracle error is a harmless transaction revert, it deviates from the security best practice of "explicit verification over implicit trust." This pattern creates a dependency on the assumed fail-safe behavior of the external oracle. In edge-case scenarios, such as the oracle returning a stale price with authorized=false, the current code would proceed with the stale data, leading to a minor economic bug in the fee calculation.
Resolved
#3 informational Issue
Useless Transactions and Event Spam from Zero-Amount Burns
The function does not prevent a user from calling it with an amount of zero. The transaction will proceed, zero tokens will be successfully "burned," and a valid cross-chain event (EVENT:SEND_WRAPPED_SOLANA_TO_SOLANA) will be emitted for a zero-value transfer. This has no legitimate economic purpose but still requires network resources on Zera to process and, more importantly, generates a useless event that the off-chain Guardian infrastructure is obligated to process. This creates a potential Denial of Service (DoS) vector where an attacker could spam the bridge with these useless events, increasing operational costs for Guardians and potentially delaying the processing of legitimate transactions.
Resolved
#4 informational Issue
Inconsistent Error Handling on Invalid Input
The function handles invalid inputs inconsistently. When an invalid pause_level is provided, the validation on line 50 fails, and the function terminates silently by returning on line 52. This is inconsistent with the validation for the pause_duration parameter, which correctly emits a descriptive on-chain error event if the input is invalid (line 59). While this does not pose a direct security risk, this inconsistent behavior makes it more difficult for operators to debug failed governance transactions. A silent failure provides no on-chain record of why the call did not succeed, potentially causing confusion. All input validation failures should be accompanied by a corresponding error event for clarity and easier debugging.
Resolved
#5 informational Issue
Inconsistent Error Handling on Authorization Failure
The administrative functions in this contract, such as update_gov, correctly perform an authorization check to ensure the caller is the update_key holder. However, if this check fails, the function terminates silently by executing a return statement. This behavior is inconsistent with the error handling in other contracts within the bridge system (e.g., bridge_gov), which emit a descriptive, on-chain error event when an authorization check fails. A silent failure provides no on-chain record or context as to why a critical administrative transaction did not succeed, which can complicate and delay debugging efforts by the operators.
Resolved
#6 informational Issue
System Allows Useless Zero-Amount Token Transfers Across All Core Functions
Every function in the contract responsible for moving tokens (lock_zera, burn_sol, mint_sol, create_sol, release_zera) shares a common validation flaw. While they all check that the amount parameter is a valid number, none of them enforce that this amount must be greater than zero. This allows for the successful execution of transactions that transfer, lock, burn, or mint zero tokens. Such transactions have no legitimate economic purpose but still consume network resources, generate on-chain events, and, in the case of Guardian-gated functions, consume a unique, one-time transaction signature (VAA). This represents a protocol hygiene issue and a minor Denial of Service (DoS) vector, as it allows for the creation of useless state transitions and events that the entire bridge infrastructure is obligated to process.
Resolved
#7 informational Issue
Missing Logical Validation on Rate Limit Parameters
The update_rate_limit function, which allows the governor to set the bridge's economic limits, fails to perform a logical validation check on its inputs. It correctly accepts the single_limit and rate_limit as numerical types but applies them directly to the state without ensuring their relationship is logical. This allows the governor, through a potential human error, to set the per-transaction limit (single_limit) to a value that is greater than the total 24-hour rate_limit. While this does not cause a direct vulnerability that would lead to a loss of funds, it puts the bridge's rate-limiting policy into an illogical and likely unintended state. A function responsible for configuring security parameters should be defensively programmed to reject illogical configurations.