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 | |
|---|---|
| Name | Smart Contract Code Review and Security Analysis Report for Verasity |
| Audited By | Khrystyna Tkachuk |
| Approved By | Kornel Światłowski |
| Website | https://verasity.io→ |
| Changelog | 03/04/2026 - Preliminary Report |
| 10/04/2026 - Final Report | |
| Platform | Base |
| Language | Solidity |
| Tags | Fungible Token; ERC20; Centralization; Vesting |
| Methodology | https://docs.hacken.io/methodologies/smart-contracts→ |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for Verasity
- Audited By
- Khrystyna Tkachuk
- Approved By
- Kornel Światłowski
- Website
- https://verasity.io→
- Changelog
- 03/04/2026 - Preliminary Report
- 10/04/2026 - Final Report
- Platform
- Base
- Language
- Solidity
- Tags
- Fungible Token; ERC20; Centralization; Vesting
Review Scope | |
|---|---|
| File Name | contracts.zip |
| File Hash (SHA256) | 8a64bdd |
| Final File Name | Archive.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
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
transferWithDatafunction that performs a standard transfer and emits an additional event containing caller-supplieddata.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 forMINTER_ROLE,PAUSER_ROLE, andBLOCK_ROLE. Assigned to the deployer at construction.MINTER_ROLE: Can mint an arbitrary amount of tokens to any address viamint()(no supply cap enforced). Can permanently and irreversibly disable all future minting viafinishMinting(). Assigned to the deployer at construction.PAUSER_ROLE: Can pause and unpause all token transfers globally viapause()/unpause(). Pausing also prevents minting and burning. Assigned to the deployer at construction.BLOCK_ROLE: Can add or remove individual addresses from the blocklist viablockAccount()/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 viaaddLock(). Can release any matured lock on behalf of the beneficiary viarelease(). Can withdraw all unallocated tokens (contract balance minus total locked) to any address viarecoverUnallocated(). Can transfer ownership to another address in a single step viatransferOwnership()(inherited from Ownable). Set toinitialOwnerat construction.beneficiary(per-lock, non-privileged): Can callrelease()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
Code ― | Title | Status | Severity | |
|---|---|---|---|---|
| F-2026-1572 | Redundant Public Getter Alongside Public State Variable | fixed | Observation | |
| F-2026-1572 | Redundant Zero-Address Check in mint() Function | fixed | Observation | |
| F-2026-1572 | Misleading NatSpec References Non-Existent revoke() Function | fixed | Observation | |
| F-2026-1571 | Missing Lock Existence Validation in release() Function | fixed | Observation | |
| F-2026-1571 | Use Ownable2Step instead of Ownable | accepted | Observation | |
| F-2026-1571 | Redundant Import | fixed | Observation | |
| F-2026-1569 | Floating Pragma | accepted | Observation |
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 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 |
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
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.