Q2 2026 Security & Compliance Report67 incidents, $764M in losses, 88% from operational failures.
Get the report →

Audit name:

[SCA] Europeum | TCR | Jul2026

Date:

Aug 11, 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 Europeum team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.

Europeum operates and scales Europe’s sovereign digital trust infrastructure, enabling secure, transparent, and interoperable services across the public and private sectors.

Document

NameSmart Contract Code Review and Security Analysis Report for Europeum
Audited BySeher Saylik
Approved ByIvan Bondar
Websitehttps://europeum.eu/
Changelog28/07/2026 - Preliminary Report
04/08/2026 - Retest V1
05/08/2026- Retest V2
14/08/2026 - Retest V3
17/08/2026 - Final Commit
PlatformPrivate Chain
LanguageSolidity
TagsProxy, Upgradable, Centralization
Methodologyhttps://docs.hacken.io/methodologies/smart-contracts
  • Document

    Name
    Smart Contract Code Review and Security Analysis Report for Europeum
    Audited By
    Seher Saylik
    Approved By
    Ivan Bondar
    Changelog
    28/07/2026 - Preliminary Report
    04/08/2026 - Retest V1
    05/08/2026- Retest V2
    14/08/2026 - Retest V3
    17/08/2026 - Final Commit
    Platform
    Private Chain
    Language
    Solidity
    Tags
    Proxy, Upgradable, Centralization

Review Scope

Repositoryhttps://gitlab.com/europeum/public/core-services/-/tree/main/contracts/contracts-registry/contracts
Commit89bb63b
Retest V1a64e313
Retest V2048a030
Retest V3d1535ba
Final Commit708ec7f

Audit Summary

20Total Findings
16Resolved
2Accepted
2Mitigated

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

Documentation quality

  • Functional requirements are partially documented.

  • A description is provided, but it is outdated and references missing components, roles, functions, and events.

Code quality

  • The contracts generally reuse OpenZeppelin and shared project libraries.

  • The development environment, compilation, and testing scripts are configured.

Test coverage

Code coverage of the project is 94.21% (state coverage).

  • Deployment and basic multi-user interactions are covered.

  • Negative cases are substantially covered.

  • However, adversarial beacon updates, malformed initialization data, constructor-time behavior, CREATE2 address drift, and pagination edge cases are not thoroughly covered.

System Overview

Europeum EBSI Contract Factory is a deployment system that enables authorized users and contracts to deploy upgradeable beacon proxies from governance-approved templates.

ProxyTemplateRegistry stores templates identified by name and version. Each template includes a beacon address, repository and audit references, integrity metadata, an initializer selector, and an active status. Templates can be registered, updated, or deprecated.

ProxyFactory deploys proxies from active templates using regular contract creation or CREATE2. It prepares initialization calldata, records each deployment, and groups deployed proxies by DID. Authorization depends on governance roles, external policies, DID ownership, or an existing active proxy record.

Pagination provides shared pagination logic for template and deployment queries.

Privileged Roles

  • DEFAULT_ADMIN_ROLE can grant and revoke roles, including EBSI_GOVERNOR.

  • EBSI_GOVERNOR in ProxyFactory can:

    • Change the DID and policy registries.

    • Deploy proxies without policy, DID-controller, or active-proxy checks.

    • Activate or deactivate registered deployments via setDeploymentActive.

  • EBSI_GOVERNOR in ProxyTemplateRegistry can:

    • Change the policy registry.

    • Add, update, and deprecate templates without policy authorization.

  • Holders of the TCR:manageTemplates policy can manage templates.

  • Holders of the TCR:deployProxy policy can deploy proxies when they control the supplied DID or are registered as an active proxy.

Potential Risks

Contracts calling deployProxy() become the proxy’s beacon-level upgrade owner and must implement properly authorized functions to call upgradeProxyToVersion() and transferProxyOwnership() on the beacon; otherwise, the proxy’s upgrade and ownership-transfer rights will be inaccessible.

Because EBSI_GOVERNOR bypasses didRegistry.checkController, it can deploy a proxy using any supplied DID without proving control, after which the factory stores, indexes, and emits that DID as the proxy’s deployment attribution.

EBSI_GOVERNOR can immediately replace the factory’s DID and policy registries with any non-zero address, potentially changing authorization behavior or preventing legitimate deployments if the role is compromised.

ProxyFactory and ProxyTemplateRegistry are deployed behind upgradeable beacon proxies, allowing the relevant beacon owner to replace their logic for all instances; if this authority is compromised or misused, authorization rules, template records, and deployment behavior could be changed without protection from any timelock or approval mechanism in the scoped contracts.

Because deprecation only blocks one template name and version, the same beacon can be registered again with a different name or version and used for new proxy deployments.

Implementation initializers execute with msg.sender set to the factory, in both deployment paths — via delegatecall from the proxy in deployProxy and via functionCall in deployProxyWithSalt. Any implementation that derives privileges from msg.sender inside initialize (granting an admin role, setting an owner) will assign them to ProxyFactory rather than to the deployer. Privileged addresses must be passed explicitly in initData.

Pagination helpers used by getDeployedContracts and getContractsByTemplate can return prev = 0 for an empty list when page >= 2, and a very large out-of-range page can overflow the cursor calculation and revert with panic 0x11 instead of returning an empty page.

A registered proxy can deploy with an empty deployerDID and reuse its parent’s stored DID without a new didRegistry.checkController check. If that DID’s controller is later revoked or the parent proxy is compromised, the factory still allows further deployments under the old DID until an EBSI_GOVERNOR calls setDeploymentActive. Until then, unauthorized or obsolete callers can keep creating proxies attributed to a DID they no longer control. The team stated that this is intentional.

functionCall is a call from the factory into the proxy. Any implementation that treats msg.sender as owner/admin during initialize assigns that role to ProxyFactory, not the deployer. Privileged addresses must come from initData / the separate owner arg.

Every factory deployment creates a VersionedBeaconProxy, which calls registerProxy on template.beaconAddress in its constructor. addTemplate only checks standard IBeacon.implementation(), so a plain OpenZeppelin UpgradeableBeacon can be registered even though it has no registerProxy. Any later deployProxy / deployProxyWithSalt for that template then reverts in the proxy constructor, so the template appears active but no proxy can be deployed from it. Therefore, Normal OZ UpgradeableBeacon is not supported in this code.

Findings

Code
Title
Status
Severity
F-2026-1824Template Integrity Metadata Is Never Enforced and Deployments Follow the Beacon's Live Implementation
mitigated

Medium
F-2026-1896Deactivation Does Not Cascade to Child Proxies
mitigated

Medium
F-2026-1871Deployed Proxies Cannot Be Deactivated
fixed

Low
F-2026-1871Hardcoded Proxy Ownership Can Assign Upgrade Authority to the Calling Contract
fixed

Low
F-2026-1825Stale Template Initializer Selector Can Break Proxy Deployment
accepted

Low
F-2026-1824deployProxy Executes initialize() Before Proxy Code Is Deployed
fixed

Low
F-2026-1896CREATE2 Address Prediction Is Bound to msg.sender Instead of an Explicit Deployer
fixed

Low
F-2026-1871Pagination Helper Returns prev and next in Reversed Order
fixed

Observation
F-2026-1870Non-Deterministic CREATE2 Address Due to Live Beacon State in Salt Derivation
fixed

Observation
F-2026-1868IProxyFactory Does Not Fully Represent the Factory’s External API
fixed

Observation
1-10 of 20 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://gitlab.com/europeum/public/core-services/-/tree/main/contracts/contracts-registry/contracts
Commit89bb63b74e88c7e3b1602f4801d682e634b6a521
Retest V1a64e3139c3a139da5bc3ff81c4d25fb35212c7f2
Retest V2048a0308e34fa43f19402a7efd69064475fa2310
Retest V3d1535bacb0ee03fc987339c58324b34c3db14687
Final Commit708ec7f98d45e3709024e950c6ac83b48fc5a9d2
WhitepaperN/A
RequirementsNatSpec
Technical RequirementsN/A

Assets in Scope

contracts
contracts-registry
contracts
libraries
Pagination.sol - contracts › contracts-registry › contracts › libraries › Pagination.sol
ProxyFactory.sol - contracts › contracts-registry › contracts › ProxyFactory.sol
ProxyTemplateRegistry.sol - contracts › contracts-registry › contracts › ProxyTemplateRegistry.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