Q3 2026 Security & Compliance$1.18B stolen across 107 incidents. Main drivers: supply chain, smart contracts, keys.
Get the report →

Audit name:

[SCA] Bullbit | Bridge Governance | Aug2026

Date:

Sep 14, 2026

Table of Content

→Introduction
→Audit Summary
→System Overview
→Potential Risks
→Findings
→Appendix 1. Definitions
→Appendix 2. Scope
→Appendix 3. Additional Valuables
→Disclaimer

Want a comprehensive audit report like this?

Introduction

We express our gratitude to the Bullbit team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.

BridgeGovernance is a typed function-route whitelist UUPS governance router for an EVM token bridge. A documented external Safe (per spec) is the intended owner that executes typed administrative actions on the sibling DepositFactory and Vault proxies, and Foundry deploy documentation targets Base and Base Sepolia on otherwise EVM-generic contracts (per spec).

Document

NameSmart Contract Code Review and Security Analysis Report for Bullbit
Audited ByIvan Bondar
Approved ByKornel Światłowski
Websitehttps://bullbit.ai/→
Changelog08/09/2026 - Preliminary Report
14/09/2026 - Final Report
PlatformBase
LanguageSolidity
TagsGovernance; Bridge; Proxy; Upgradable;
Methodologyhttps://docs.hacken.io/methodologies/smart-contracts→

Review Scope

Repositoryhttps://github.com/bullbit/Bridge-Governance-Smart-Contract→
Initial Commit1dc6a2e
Final Commitd60b6c1

Audit Summary

2Total Findings
2Resolved
0Accepted
0Mitigated

The system users should acknowledge all the risks summed up in the risks section of the report

Documentation quality

  • Functional requirements are partially missed.

  • Technical description is not provided. No architecture note, event catalog, or per-route NatSpec.

Code quality

  • Owner routes follow one template: onlyOwner, optional zero check, _callTarget, event.

  • The development environment is configured (Foundry 0.8.30, Makefile, remappings, fmt, coverage filter, deploy scripts).

Test coverage

Code coverage of the project is 100% (branch coverage).

  • Deployment and basic owner routes are covered.

  • Negative cases are present.

  • Multi-user flows are tested.

System Overview

BridgeGovernance is deployed behind a UUPS ERC-1967 proxy. initialize assigns initialOwner and is gated only by the initializer modifier, so any address may call it once on an uninitialized proxy. Initializable, Ownable2StepUpgradeable, and UUPSUpgradeable are inherited. The contract is not a voting Governor. A single owner address is stored in OpenZeppelin Ownable ERC-7201 storage. An external Safe and its signing threshold are deployment intent only (per spec). Typed routes and events are defined on this contract. renounceOwnership is overridden to revert with RenounceDisabled. Replacement of this proxy's implementation is performed through the inherited upgradeToAndCall entry, which is public, onlyProxy, and invokes the internal _authorizeUpgrade hook. That hook is onlyOwner and requires the new implementation to contain code.

BridgeGovernance is intended to become the owner of the sibling EVM bridge DepositFactory and Vault proxies after an Ownable2Step transfer (per spec). Those sibling contracts live outside this repository. Owner-restricted functions encode calldata against IDepositFactoryGovernanceTarget, IVaultGovernanceTarget, IOwnable2StepTarget, and IUUPSUpgradeableTarget, then forward it through _callTarget. No generic execute entry is present. upgradeTarget encodes the target's upgradeToAndCall with empty setup calldata. Post-upgrade configuration uses the typed factory and vault routes. Inherited upgradeToAndCall accepts setup calldata for this proxy. A target must be a nonzero address other than this contract and must contain code. An implementation must be nonzero and must contain code. _validateTarget does not read a stored factory or vault address and does not compare target, factory, or vault arguments to any allowlist. The whitelist is the set of typed function routes. BridgeGovernance declares no storage variables and no __gap. Inherited OpenZeppelin bases use ERC-7201 namespaced storage. Target ownership is accepted or started through acceptTargetOwnership and transferTargetOwnership. transferTargetOwnership rejects a zero newOwner. Target UUPS upgrades are performed through upgradeTarget.

Factory administration covers setFactoryVault, setFactorySupportedToken, setFactoryOperator, pauseFactory, unpauseFactory, and rescueUnsupportedForwarderToken. Vault administration covers setVaultValset, setVaultReleaseRelayer, setVaultOperator, setVaultColdVault, consolidateVault, pauseVault, and unpauseVault. DepositFactory.deployWallet has no route on this contract and remains callable on the factory proxy (per spec). Routine Factory and Vault actions are handled by operators (per spec). Releases through Vault.releaseWithAttestation are performed by a release relayer outside this contract (per spec).

Files in Scope

  • BridgeGovernance.sol — UUPS Ownable2Step governance router. Owner-restricted typed routes are forwarded through _callTarget to caller-supplied addresses intended to be DepositFactory and Vault proxies, covering configuration, pause control, token rescue, valset and relayer updates, consolidation, ownership handover, and upgrades. renounceOwnership is disabled. No factory or vault address is stored. Inherited upgradeToAndCall is the self-upgrade entry. upgradeTarget upgrades a target with empty setup calldata.

  • IDepositFactoryGovernanceTarget.sol — Interface consumed by BridgeGovernance to type setVault, setSupportedToken, updateOperator, pause, unpause, and rescue on a factory target. IOwnable2StepTarget is extended so factory ownership handover uses the same typed surface. The interface declares no access control.

  • IOwnable2StepTarget.sol — Interface consumed by BridgeGovernance for Ownable2Step views and mutations: owner, pendingOwner, transferOwnership, and acceptOwnership. Handover routes encode transferOwnership and acceptOwnership against this surface. The interface declares no access control.

  • IUUPSUpgradeableTarget.sol — Interface consumed by BridgeGovernance to type upgradeToAndCall on a UUPS target. upgradeTarget encodes this function with empty data. The interface declares no access control.

  • IVaultGovernanceTarget.sol — Interface consumed by BridgeGovernance to type setValset, setReleaseRelayer, updateOperator, setColdVault, consolidate, pause, and unpause on a vault target. A Member struct with attestor and power is defined for valset updates. IOwnable2StepTarget is extended. The interface declares no access control.

Privileged roles

BridgeGovernance.sol

  • owner (inherited from Ownable2StepUpgradeable): Every onlyOwner function is reserved to this role. The owner is a single address in Ownable ERC-7201 storage. An external Safe is documented as the intended owner (per spec) and is not enforced by this contract. Target ownership handover, target upgrades, DepositFactory and Vault governance, ownership transfer of BridgeGovernance, and UUPS upgrades of this proxy are included.

    • Can call acceptTargetOwnership to accept pending ownership of an external Ownable2Step target.

    • Can call transferTargetOwnership to start ownership transfer of an external Ownable2Step target to a nonzero new owner.

    • Can call upgradeTarget to upgrade an external UUPS target to a new implementation with empty calldata.

    • Can call setFactoryVault to set the vault address on a DepositFactory.

    • Can call setFactorySupportedToken to enable or disable a supported token on a DepositFactory.

    • Can call setFactoryOperator to set the operator on a DepositFactory.

    • Can call pauseFactory to pause a DepositFactory.

    • Can call unpauseFactory to unpause a DepositFactory.

    • Can call rescueUnsupportedForwarderToken to rescue a token from a forwarder through a DepositFactory to a recipient.

    • Can call setVaultValset to set validator members and the power threshold on a Vault.

    • Can call setVaultReleaseRelayer to enable or disable a release relayer on a Vault.

    • Can call setVaultOperator to set the operator on a Vault.

    • Can call setVaultColdVault to set the cold vault address on a Vault.

    • Can call consolidateVault to consolidate a token amount on a Vault.

    • Can call pauseVault to pause a Vault.

    • Can call unpauseVault to unpause a Vault.

    • Can call renounceOwnership, which is overridden to revert with RenounceDisabled.

    • Can call transferOwnership to set or replace the pending owner of BridgeGovernance, including the zero address to cancel a pending transfer.

    • Can call upgradeToAndCall to replace this proxy's implementation and optionally execute setup calldata. Authorization is enforced by the internal _authorizeUpgrade hook, which is onlyOwner and requires the implementation to contain code.

  • pendingOwner (inherited from Ownable2StepUpgradeable): Ownership of BridgeGovernance is completed by this role after a transfer is started.

    • Can call acceptOwnership to become the owner of BridgeGovernance and clear the pending owner.

Potential Risks

Unrestricted State Modification by Owner: Owner routes forward parameter payloads without local range, membership, or operator-nonzero checks. setVaultValset passes members and powerThreshold unchanged, setFactorySupportedToken accepts any nonzero token and supported flag, and setFactoryVault and setVaultColdVault accept any nonzero address. setFactoryOperator and setVaultOperator forward operator without a zero-address check. A single owner transaction can replace the vault attestor set, retarget the factory vault pointer, or write a zero operator if the target allows it.

Absence of Timelock Mechanisms for Critical Operations: BridgeGovernance implements no enqueue, delay, or veto window. Owner invocations of upgradeTarget, setVaultValset, setVaultColdVault, rescueUnsupportedForwarderToken, consolidateVault, pauseVault, and unpauseFactory execute _callTarget immediately. Once the owner transaction is mined, the in-scope contract provides no function that can undo a valset replacement, implementation swap, or rescue except by a later owner call to the same targets.

Treasury or Rescue Authority: rescueUnsupportedForwarderToken requires nonzero forwarder, token, and to, then calls IDepositFactoryGovernanceTarget.rescue with those arguments. consolidateVault requires a nonzero token and forwards IVaultGovernanceTarget.consolidate with the owner-chosen amount. Neither route imposes an amount cap or a fixed recipient. Tokens held in a targeted forwarder or vault can be moved in one owner transaction when the out-of-repository target accepts the call.

Single Owner Control Path: The owner of BridgeGovernance is the only persistent privileged role that can upgrade this proxy, upgrade or reown factory and vault targets, replace the vault valset and release relayer, assign operators, move assets through rescueUnsupportedForwarderToken and consolidateVault, and pause or unpause both target types. A single onlyOwner gate covers that entire surface. The stored owner is one address in Ownable ERC-7201 storage. The bytecode does not require that address to be a Safe, a governor, or any other multi-signature module; the Safe owner described in project documentation is an off-chain deployment assumption (per spec).

Flexibility and Risk in Contract Upgrades: BridgeGovernance inherits UUPSUpgradeable, calls _disableInitializers in the constructor, and authorizes replacement logic in _authorizeUpgrade after _validateImplementation. Inherited upgradeToAndCall accepts caller data for this proxy. Separately, upgradeTarget passes empty bytes into IUUPSUpgradeableTarget.upgradeToAndCall on a caller-chosen target. A successful owner transaction can replace governance logic or the logic of any UUPS target that still recognizes BridgeGovernance as owner, including logic that later changes access control or asset handling.

Absence of Upgrade Window Constraints: Neither _authorizeUpgrade nor upgradeTarget records a future implementation or waits a mandatory period. _validateImplementation rejects only the zero address and empty code. The owner can replace the BridgeGovernance implementation or a factory or vault implementation in a single transaction.

Caller-Chosen Targets Without a Registry: _validateTarget on BridgeGovernance rejects the zero address, address(this), and accounts with no code. It does not load a stored DepositFactory or Vault and does not compare target, factory, or vault parameters to any allowlist. acceptTargetOwnership, setFactoryVault, setVaultValset, upgradeTarget, and the other owner routes therefore act on whichever contract the owner supplies. Events such as FactoryVaultSet and TargetUpgraded still fire after a non-reverting _callTarget, even when the address is not the intended bridge proxy.

Findings

F-2026-1922Documented Permissionless Forwarder Deployment Contradicts Operator-Gated Factory
Status
fixed
Severity

Observation
F-2026-1922Unrestricted Calldata In Target Upgrade Hook Bypasses The Typed Route Whitelist
Status
fixed
Severity

Observation
Code
―
Title
Status
Severity
F-2026-1922Documented Permissionless Forwarder Deployment Contradicts Operator-Gated Factory
fixed

Observation
F-2026-1922Unrestricted Calldata In Target Upgrade Hook Bypasses The Typed Route Whitelist
fixed

Observation
1-2 of 2 findings

Identify vulnerabilities in your smart contracts.

Appendix 1. Definitions

Severities

When auditing smart contracts, Hacken is using a risk-based approach that considers Likelihood, Impact, Exploitability and Complexity metrics to evaluate findings and score severities.

Reference on how risk scoring is done is available through the repository in our Github organization:

Severity

Description

Critical
Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.

High
High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.

Medium
Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.

Low
Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution.
  • Severity

    Critical

    Description

    Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.

    Severity

    High

    Description

    High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.

    Severity

    Medium

    Description

    Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.

    Severity

    Low

    Description

    Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution.

Potential Risks

The "Potential Risks" section identifies issues that are not direct security vulnerabilities but could still affect the project’s performance, reliability, or user trust. These risks arise from design choices, architectural decisions, or operational practices that, while not immediately exploitable, may lead to problems under certain conditions. Additionally, potential risks can impact the quality of the audit itself, as they may involve external factors or components beyond the scope of the audit, leading to incomplete assessments or oversight of key areas. This section aims to provide a broader perspective on factors that could affect the project's long-term security, functionality, and the comprehensiveness of the audit findings.

Appendix 2. Scope

The scope of the project includes the following smart contracts from the provided repository:

Scope Details

Repositoryhttps://github.com/bullbit/Bridge-Governance-Smart-Contract→
Initial Commit1dc6a2e2fc53cbbbd3bff54818c00761dcf596be
Final Commitd60b6c1a8d78d004a36e5ea48e227eca59afbb13
WhitepaperN/A
RequirementsREADME.md; NatSpec
Technical RequirementsREADME.md; NatSpec

Assets in Scope

src
interfaces
IDepositFactoryGovernanceTarget.sol - src › interfaces › IDepositFactoryGovernanceTarget.sol
IOwnable2StepTarget.sol - src › interfaces › IOwnable2StepTarget.sol
IUUPSUpgradeableTarget.sol - src › interfaces › IUUPSUpgradeableTarget.sol
IVaultGovernanceTarget.sol - src › interfaces › IVaultGovernanceTarget.sol

Appendix 3. Additional Valuables

Additional Recommendations

The smart contracts in the scope of this audit could benefit from the introduction of automatic emergency actions for critical activities, such as unauthorized operations like ownership changes or proxy upgrades, as well as unexpected fund manipulations, including large withdrawals or minting events. Adding such mechanisms would enable the protocol to react automatically to unusual activity, ensuring that the contract remains secure and functions as intended.

To improve functionality, these emergency actions could be designed to trigger under specific conditions, such as:

  • Detecting changes to ownership or critical permissions.

  • Monitoring large or unexpected transactions and minting events.

  • Pausing operations when irregularities are identified.

These enhancements would provide an added layer of security, making the contract more robust and better equipped to handle unexpected situations while maintaining smooth operations.

Frameworks and Methodologies

This security assessment was conducted in alignment with recognised penetration testing standards, methodologies and guidelines, including the NIST SP 800-115 – Technical Guide to Information Security Testing and Assessment →, and the Penetration Testing Execution Standard (PTES) →, These assets provide a structured foundation for planning, executing, and documenting technical evaluations such as vulnerability assessments, exploitation activities, and security code reviews. Hacken’s internal penetration testing methodology extends these principles to Web2 and Web3 environments to ensure consistency, repeatability, and verifiable outcomes.

Disclaimer