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

Audit name:

[SCA] Verasity | Multitoken | Apr2026

Date:

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

Verasity is an open ledger ecosystem bringing trust and transparency to digital advertising and payments.

Document

NameSmart Contract Code Review and Security Analysis Report for Verasity
Audited ByKhrystyna Tkachuk
Approved ByKornel Światłowski
Websitehttps://verasity.io→
Changelog03/04/2026 - Preliminary Report
10/04/2026 - Final Report
PlatformBase
LanguageSolidity
TagsFungible Token; ERC20; Centralization; Vesting
Methodologyhttps://docs.hacken.io/methodologies/smart-contracts→

Review Scope

File Namecontracts.zip
File Hash (SHA256)8a64bdd
Final File NameArchive.zip
Final File Hash (SHA256)191b142
  • Review Scope

    File Name
    contracts.zip
    File Hash (SHA256)
    8a64bdd
    Final File Name
    Archive.zip
    Final File Hash (SHA256)
    191b142

Audit Summary

7Total Findings
5Resolved
2Accepted
0Mitigated

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

Documentation quality

  • Functional requirements are provided.

  • Technical description is provided.

    • Run instructions are provided.

    • Technical specification is provided.

  • The NatSpec documentation is sufficient.

Code quality

  • The code leverages OpenZeppelin contracts and follows established patterns.

  • The development environment is configured.

Test coverage

Code coverage of the project is 0%.

  • The project does not include any test cases.

System Overview

Verasity is an ERC-20 token ecosystem consisting of a feature-rich token contract and an accompanying multi-beneficiary timelock. Together they provide the infrastructure for issuing the PLRL token with centralized compliance controls (minting, pausing, blocklisting) and for distributing tokens to beneficiaries under time-locked distribution.

The token layer is implemented as an abstract base contract ERC20MintablePausableBlocklistable that composes OpenZeppelin AccessControl, ERC20Burnable, and Pausable. It adds role-gated minting with a one-way finishMinting() switch, a per-account blocklist enforced at the _update() level (blocking both sends and receives), and a transferWithData() helper that attaches arbitrary calldata to standard transfers via an event. The concrete PluralToken contract inherits the base ERC20MintablePausableBlocklistable and has the following attributes:

  • Name: PLRL

  • Symbol: PLRL

  • Decimals: 18

  • Total supply: 10 000 000 000 tokens.

The distribution layer is handled by MultiTokenTimelock, a deposit-model timelock. The admin first sends tokens to the contract via a plain ERC-20 transfer, then calls addLock() to allocate deposited tokens to a beneficiary with a specified lock duration. After the lock period elapses, either the beneficiary or the contract owner can call release() to transfer the tokens out. Unallocated tokens (deposits that have not been assigned to any lock) can be swept back to any address by the owner via recoverUnallocated(). The contract tracks allocations through an auto-incrementing lock ID counter and a totalAllocated accumulator that is checked against the contract's actual token balance to derive the unallocated surplus.

Both contracts are non-upgradeable. PluralToken uses OpenZeppelin's AccessControl for role-based permissioning, while MultiTokenTimelock uses OpenZeppelin's Ownable for single-owner administration.

Files in scope

  • PluralToken.sol: ERC-20 token with compliance controls. Defines the abstract ERC20MintablePausableBlocklistable base, which layers role-gated minting, global pause/unpause, per-account blocklisting, burning, and a transferWithData function that performs a standard transfer and emits an additional event containing caller-supplied data.

  • MultiTokenTimelock.sol: Multi-beneficiary deposit-model token timelock. Accepts a single immutable ERC-20 token address and an initial owner at construction.

Privileged roles

PluralToken.sol (inherits ERC20MintablePausableBlocklistable):

  • DEFAULT_ADMIN_ROLE: Can grant and revoke all roles (including itself). Serves as the admin role for MINTER_ROLE, PAUSER_ROLE, and BLOCK_ROLE. Assigned to the deployer at construction.

  • MINTER_ROLE: Can mint an arbitrary amount of tokens to any address via mint() (no supply cap enforced). Can permanently and irreversibly disable all future minting via finishMinting(). Assigned to the deployer at construction.

  • PAUSER_ROLE: Can pause and unpause all token transfers globally via pause() / unpause(). Pausing also prevents minting and burning. Assigned to the deployer at construction.

  • BLOCK_ROLE: Can add or remove individual addresses from the blocklist via blockAccount() / unblockAccount(). Blocked addresses cannot send or receive tokens. Assigned to the deployer at construction.

MultiTokenTimelock.sol:

  • owner: Can create new time-locked token allocations for any beneficiary via addLock(). Can release any matured lock on behalf of the beneficiary via release(). Can withdraw all unallocated tokens (contract balance minus total locked) to any address via recoverUnallocated(). Can transfer ownership to another address in a single step via transferOwnership() (inherited from Ownable). Set to initialOwner at construction.

  • beneficiary (per-lock, non-privileged): Can call release() on their own lock IDs after the lock period has expired. Has no other administrative capabilities.

Potential Risks

Centralized Minting to a Single Address: The PluralToken contract concentrates minting tokens in a single address at the deployment, raising the risk of fund mismanagement or theft, especially if key storage security is compromised.

Centralized Control of Minting Process: The PluralToken token contract grants the holder of the MINTER_ROLE unlimited minting privileges, posing a risk of unauthorized token issuance, potentially diluting the token value and undermining trust in the project's economic governance.

Absence of Minting Cap: The mint() function has no supply cap. Any address with MINTER_ROLE can mint an arbitrary amount of tokens at any time (until finishMinting() is called). If the minter key is compromised, the attacker can inflate the supply indefinitely, destroying token value.

Single Points of Failure and Control: The project is fully or partially centralized, introducing single points of failure and control. This centralization can lead to vulnerabilities in decision-making and operational processes, making the system more susceptible to targeted attacks or manipulation.

Findings

F-2026-1572Redundant Public Getter Alongside Public State Variable
Status
fixed
Severity

Observation
F-2026-1572Redundant Zero-Address Check in mint() Function
Status
fixed
Severity

Observation
F-2026-1572Misleading NatSpec References Non-Existent revoke() Function
Status
fixed
Severity

Observation
F-2026-1571Missing Lock Existence Validation in release() Function
Status
fixed
Severity

Observation
F-2026-1571Use Ownable2Step instead of Ownable
Status
accepted
Severity

Observation
F-2026-1571Redundant Import
Status
fixed
Severity

Observation
F-2026-1569Floating Pragma
Status
accepted
Severity

Observation
Code
―
Title
Status
Severity
F-2026-1572Redundant Public Getter Alongside Public State Variable
fixed

Observation
F-2026-1572Redundant Zero-Address Check in mint() Function
fixed

Observation
F-2026-1572Misleading NatSpec References Non-Existent revoke() Function
fixed

Observation
F-2026-1571Missing Lock Existence Validation in release() Function
fixed

Observation
F-2026-1571Use Ownable2Step instead of Ownable
accepted

Observation
F-2026-1571Redundant Import
fixed

Observation
F-2026-1569Floating Pragma
accepted

Observation
1-7 of 7 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

File Namecontracts.zip
File Hash (SHA256)8a64bddc94ce781c233ba068c4ba5f1d58c26bc00d1b98772f74e06039d8f716
Final File NameArchive.zip
Final File Hash (SHA256)191b14253e95206195f91198feac3aefbdf6bc58d7192c2ab553f3d606d505d8
WhitepaperN/A
RequirementsReadme.md
Technical RequirementsReadme.md
  • Scope Details

    File Name
    contracts.zip
    File Hash (SHA256)
    8a64bddc94ce781c233ba068c4ba5f1d58c26bc00d1b98772f74e06039d8f716
    Final File Name
    Archive.zip
    Final File Hash (SHA256)
    191b14253e95206195f91198feac3aefbdf6bc58d7192c2ab553f3d606d505d8
    Whitepaper
    N/A
    Requirements
    Readme.md
    Technical Requirements
    Readme.md

Assets in Scope

MultiTokenTimelock.sol - MultiTokenTimelock.sol
PluralToken.sol - PluralToken.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