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

Audit name:

[SCA] Europeum | Track and Trace | Jul2026

Date:

Aug 13, 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.

Track and Trace is an EBSI document track-and-trace registry. Invited DID controllers create documents by hash through a commit–reveal flow, manage CREATE/DELEGATE/WRITE access, and append timestamped events under DID and policy checks.

Document

NameSmart Contract Code Review and Security Analysis Report for Europeum
Audited ByKhrystyna Tkachuk
Approved ByIvan Bondar
Websitehttps://europeum.eu/
Changelog07/08/2026 - Preliminary Report
12/08/2026 - Final Report
12/08/2026 - Updated Final Report
PlatformPrivate Chain
LanguageSolidity
TagsUpgradable
Methodologyhttps://docs.hacken.io/methodologies/smart-contracts

Review Scope

Repositoryhttps://gitlab.com/europeum/public/core-services/
Commitdb871ad
Final Commit85f94b2
Updated Final Commitd1535ba

Audit Summary

14Total Findings
12Resolved
1Accepted
1Mitigated

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 provided.

  • NatSpec is sufficient.

Code quality

  • The code leverages OpenZeppelin 5.6.1 and shared in-house primitives, and follows the established beacon-proxy upgradeable pattern.

  • The codebase is well-structured and clearly organized.

  • The development environment is configured.

Test coverage

Code coverage of the project is 97.56 % (statement coverage).

  • Deployment and basic user interactions are covered with 64 passing tests.

  • Negative cases coverage is present.

System Overview

TrackAndTrace is an OpenZeppelin upgradeable contract (AccessControlUpgradeable, ImplementationInitSelector) that stores documents keyed by bytes32 hash, with metadata, creator DID, timestamps (Source.Block or Source.External), per-subject access grants, an append-only event log, and a DocumentStatus lifecycle (None, Active, Deleted). Document creation uses a commit–reveal pattern: callers register a commitment via commitCreateDocument, wait CREATE_DOCUMENT_COMMITMENT_MATURITY blocks, then call createDocument with matching arguments and salt. Controllers of invited did:ebsi accounts may create documents; creators and delegated accounts call grantAccess / revokeAccess; creators and writers call writeEvent. Authorization uses external IDidRegistry.checkController for DID_EBSI and public-key-derived addresses for DID_KEY. Document-creation eligibility is gated by invitedDidEbsiAccounts, maintained via authoriseDid under the TNT:authoriseDid policy on IPolicyRegistry. removeDocument tombstones a document as DocumentStatus.Deleted after detaching subject indexes, permanently blocking hash reuse. DEFAULT_ADMIN_ROLE may update policiesRegistry and didRegistry through setPoliciesRegistry and setDidRegistry. Paginated getters expose documents, events, and access lists. Event string fields are bounded by MAX_METADATA_LENGTH.

TrackAndTraceLib supplies DID-key address derivation, assembly-based bytes equality, and EIP-712-style createDocument commitment hashing used by authorization, access revocation, and the commit–reveal path. No token or DeFi standards are implemented; the design is a permissioned on-chain registry for EBSI identity-bound document trails.

Files in Scope

  • TrackAndTrace.sol: Upgradeable registry for document lifecycle and access.

  • TrackAndTraceLib.sol: Shared helpers for DID-key handling and bytes comparison.

Privileged roles

TrackAndTracesol

  • DEFAULT_ADMIN_ROLE (inherited from AccessControlUpgradeable): Admin role for AccessControl role management and registry address updates.

    • Can call grantRole to grant roles.

    • Can call revokeRole to revoke roles.

    • Can call setRoleAdmin to change the admin role for a role.

    • Can call setPoliciesRegistry to replace policiesRegistry.

    • Can call setDidRegistry to replace didRegistry.

  • TNT:authoriseDid policy holder: Can whitelist or blacklist DID EBSI accounts for document creation (also requires DID controller of senderDid).

    • Can call authoriseDid to set invitedDidEbsiAccounts. Blacklisting blocks only new createDocument calls; existing documents, grants, and writeEvent rights remain.

  • Invited DID EBSI creator: Whitelisted DID EBSI account whose controller can create documents after a matured commitment.

    • Can call commitCreateDocument to register a create commitment.

    • Can call createDocument to create a document with a block or external timestamp once the matching commitment has matured.

  • Document creator: Controller of the document creator DID; manages document lifecycle and permissions.

    • Can call removeDocument to tombstone a document (DocumentStatus.Deleted), detach subject indexes, and remove the hash from documentsMapped.

    • Can call grantAccess to grant DELEGATE or WRITE permissions (CREATOR is not grantable).

    • Can call revokeAccess to revoke permissions previously granted by the creator.

    • Can call writeEvent to append events with a block or external timestamp.

  • Delegate: Account with DELEGATE permission whose controller can manage WRITE grants.

    • Can call grantAccess to grant WRITE permission.

    • Can call revokeAccess to revoke WRITE permissions previously granted by the delegate.

  • Writer: Account with WRITE permission whose controller can append document events.

    • Can call writeEvent to append events with a block or external timestamp.

Potential Risks

Dependency on External Registries and Bootstrap Logic: TrackAndTrace depends on out-of-scope IPolicyRegistry.checkPolicy for authoriseDid and migrationRemoveDocument, IDidRegistry.checkController for _authorize on DID_EBSI accounts, and ImplementationInitSelector plus Pagination from @ebsiint-sc/bootstrap for initialization and list queries. Core paths including _authorize, createDocument, grantAccess, revokeAccess, writeEvent, and authoriseDid treat live didRegistry and policiesRegistry addresses set in initialize (and policiesRegistry again in initializeV2) as authoritative. Misconfiguration, unavailability, or incorrect responses from those registries can halt legitimate operations or admit unauthorized document creation, access changes, or event writes.

Admin Control of Registry Addresses: Holders of DEFAULT_ADMIN_ROLE may call setPoliciesRegistry and setDidRegistry at any time, subject only to a non-zero address check. A substituted policy registry can redefine which addresses satisfy "TNT:authoriseDid". A substituted DID registry can redefine controller checks used by _authorize for creation, grants, revokes, and event writes across all documents.

Control Risks from Invited DID Whitelist: authoriseDid sets invitedDidEbsiAccounts after policiesRegistry.checkPolicy("TNT:authoriseDid", msg.sender) and _authorize of senderDid. _getAccountAccess grants SCOPE.TNT_CREATE from that mapping when documentHash is zero, which is the gate checked by both createDocument overloads. Holders of the "TNT:authoriseDid" policy therefore control which DID EBSI accounts may create documents, without on-chain bounds on how many accounts are whitelisted or how often the mapping is flipped. Blacklisting does not revoke existing documents, grants, or writeEvent rights.

Absence of Timelock Mechanisms for Critical Operations: Privilege-changing calls in TrackAndTrace take effect in the same transaction. No on-chain review window, cooling period, or multi-party approval gate exists inside this contract before those changes become enforceable.

Forced Execution Without Subject Consent: When ACCESS_ENUM.DELEGATE is revoked, _revokeAccess recursively revokes ACCESS_ENUM.WRITE for every account in the subject’s children array (bounded by MAX_DELEGATED_CHILDREN) without signatures from those children. Separately, a document creator’s controller may call removeDocument, which marks the document DocumentStatus.Deleted, clears subject index entries, and removes the hash from documentsMapped, ending Active access and further writes for all invitees without their consent while retaining nested storage as a permanent tombstone.

Flexibility and Risk in Contract Upgrades: The project's contracts are upgradable, allowing the administrator to update the contract logic at any time. While this provides flexibility in addressing issues and evolving the project, it also introduces risks if upgrade processes are not properly managed or secured, potentially allowing for unauthorized changes that could compromise the project's integrity and security.

Absence of Upgrade Window Constraints: The contract suite allows for immediate upgrades without a mandatory review or waiting period, increasing the risk of rapid deployment of malicious or flawed code, potentially compromising the system's integrity and user assets.

Upgrade Path Dependency: Initialization assumes a sequenced path where initialize sets DEFAULT_ADMIN_ROLE, policiesRegistry, and didRegistry, and initializeV2 uses reinitializer(2) only to replace policiesRegistry. didRegistry has no corresponding reinitializer. Incompatible storage layout changes relative to Document, Access_Struct, accessBySubject, and documentsMapped, or an incomplete upgrade sequence, can leave policy pointers or access indexes inconsistent with the new logic.

Unverified External Timestamp Proofs: Overloaded createDocument and writeEvent accept caller-supplied timestamp and timestampProof, persist them through _createDocument / _writeEvent with Source.External, and perform no on-chain validation of the proof against a signature, registry, or other verifier. Only timestamp != 0 and the usual DID-controller plus scope checks apply (plus a matured create commitment for document creation). Consumers that treat those fields as attested chronology may rely on values that TrackAndTrace does not cryptographically authenticate.

Unbounded Event Log Growth: _writeEvent appends to eventHashes without a per-document maximum count. String fields are capped at MAX_METADATA_LENGTH, but any account with WRITE access can still grow nested event storage indefinitely through many bounded writes. That growth increases gas costs for pagination over large event lists and leaves permanent storage on tombstoned documents.

Unbounded Invitee Iteration on Document Removal: removeDocument calls _detachDocumentSubjects, which iterates doc.allInvited with no upper bound. Subject count is otherwise uncapped by grantAccess (only DELEGATE children are limited by MAX_DELEGATED_CHILDREN). A document with a sufficiently large invitee list can push removeDocument past the block gas limit, preventing the creator from tombstoning the document and detaching subject indexes.

Ungated, Never-Cleared Create Commitments: commitCreateDocument accepts any non-zero commitment from any caller with no invite or role check, and writes permanently to createDocumentCommitments. Successful createDocument reveals validate maturity via _checkCreateDocumentCommitment but do not delete the commitment slot. Unused or spent commitments therefore accumulate indefinitely, enabling storage griefing by arbitrary accounts while invite eligibility is enforced only at reveal time.

Findings

Code
Title
Status
Severity
F-2026-1877Incomplete Mapping Cleanup in removeDocument Restores Document Permissions and Events on Hash Reuse
fixed

Critical
F-2026-1886Ungated initializeV2 Permanently Redirects policiesRegistry
fixed

High
F-2026-1877Missing accessBySubjectIndex Update in removeDocument Causes Permanent Removal DoS
fixed

High
F-2026-1887Sentinel Collision in _getAccountAccess Enables Whitelist Document Permission Takeover of Zero-Hash Documents
fixed

Medium
F-2026-1886Incorrect Unchecked subjectAccountType Permanently Locks writeEvent
fixed

Medium
F-2026-1886Ungated CREATOR Permission in grantAccess Enables Subject Type Poisoning
fixed

Medium
F-2026-1887Duplicate children Push Corrupts DELEGATE Cascade Indexes
fixed

Low
F-2026-1877Unbounded origin, externalHash, and eventHashes Enable Storage Griefing
mitigated

Low
F-2026-1887Dead and Unused Interface Surface
fixed

Observation
F-2026-1887AccessRevoked Event Omits Permission
fixed

Observation
1-10 of 14 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/
Commitdb871ad07ff4dd62e89dceeb08cacc4bbb50103f
Final Commit85f94b2c705dfde80d25c56f62ef54e39db84b27
Updated Final Commitd1535bacb0ee03fc987339c58324b34c3db14687
Whitepaper-
RequirementsREADME.md; NatSpec
Technical RequirementsREADME.md; NatSpec
  • Scope Details

    Commit
    db871ad07ff4dd62e89dceeb08cacc4bbb50103f
    Final Commit
    85f94b2c705dfde80d25c56f62ef54e39db84b27
    Updated Final Commit
    d1535bacb0ee03fc987339c58324b34c3db14687
    Whitepaper
    -
    Requirements
    README.md; NatSpec
    Technical Requirements
    README.md; NatSpec

Assets in Scope

contracts
track-and-trace
contracts
libraries
TrackAndTraceLib.sol - contracts › track-and-trace › contracts › libraries › TrackAndTraceLib.sol
TrackAndTrace.sol - contracts › track-and-trace › contracts › TrackAndTrace.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