Introduction
We express our gratitude to the Haycen team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
The FiatTokenV3
contract is an upgradable ERC-20 token built for fiat-backed stablecoins, with compliance features like blacklisting, pausability, and meta-transaction support. Minting and burning are tightly controlled: only approved minters with assigned allowances can mint, and they can burn tokens from their own balance to reduce supply.
Document | |
---|---|
Name | Smart Contract Code Review and Security Analysis Report for Haycen |
Audited By | David Camps Novi, Kornel Światłowski |
Approved By | Ataberk Yavuzer |
Website | https://www.haycen.com/→ |
Changelog | 29/04/2025 - Preliminary Report |
19/05/2025 - Final Report | |
Platform | Ethereum, Arbitrum, Optimism, Polygon |
Language | Solidity |
Tags | Permit Token, Signatures, Upgradable, ERC-20 |
Methodology | https://hackenio.cc/sc_methodology→ |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for Haycen
- Audited By
- David Camps Novi, Kornel Światłowski
- Approved By
- Ataberk Yavuzer
- Website
- https://www.haycen.com/→
- Changelog
- 29/04/2025 - Preliminary Report
- 19/05/2025 - Final Report
- Platform
- Ethereum, Arbitrum, Optimism, Polygon
- Language
- Solidity
- Tags
- Permit Token, Signatures, Upgradable, ERC-20
- Methodology
- https://hackenio.cc/sc_methodology→
Review Scope | |
---|---|
Repository | https://github.com/Haycen/haycen-smart-contract→ |
Commit | 5157b7cc8f2198de381a4aaf45a2d7280ebbe5a7 |
Remediation Commit | 07eae8b101aaef34fe8dbf285a82674cb5ec1bc2 |
Review Scope
- Commit
- 5157b7cc8f2198de381a4aaf45a2d7280ebbe5a7
- Remediation Commit
- 07eae8b101aaef34fe8dbf285a82674cb5ec1bc2
Audit Summary
The system users should acknowledge all the risks summed up in the risks section of the report
Documentation quality
Functional requirements are detailed.
Project overview is detailed.
All roles in the system are described.
All interactions are described.
For each contract all futures are described.
Technical description is robust.
Run instructions are provided.
Technical specification is provided.
NatSpec covers the code and is excellent.
Code quality
Development environment is configured.
Test coverage
Code coverage of the project is 95.26% (branch coverage).
Deployment and basic user interactions are covered with tests.
System Overview
The FiatTokenV3
contract is an upgradable ERC-20 token built for fiat-backed stablecoins, with compliance features like blacklisting, pausability, and meta-transaction support. Minting and burning are tightly controlled: only approved minters with assigned allowances can mint, and they can burn tokens from their own balance to reduce supply. Roles such as pauser, blacklister, and master minter enable centralized governance and emergency controls. This design ensures secure, permissioned issuance and transfer of stablecoins within regulatory frameworks.
This Ownable
contract implements a basic ownership access control mechanism, allowing a single address to be designated as the owner with exclusive permission to perform restricted operations. Ownership can be transferred to another address through an externally accessible function, with safeguards against assigning ownership to the zero address. The initial owner is set during deployment, and ownership changes are recorded via emitted events.
This Pausable
contract implements an emergency stop mechanism, allowing designated addresses to pause and unpause contract operations through controlled state transitions. A distinct pauser role is assigned and can be updated by the owner, with checks preventing assignment to the zero address. Functions guarded by the whenNotPaused
modifier enforce conditional execution based on the contract’s paused state.
The Controller
contract implements an owner-controller-worker access model, where the owner assigns a unique worker to each controller address. Controller-to-worker relationships are maintained in a mapping and can be configured or disabled by the owner. Execution of certain functions is restricted to controllers with active worker assignments.
The MintController
contract extends the Controller
contract to manage minting permissions through a controller-minter model. Controllers, once configured by the owner, are permitted to manage a single associated minter by configuring, removing, or adjusting its minting allowance via interactions with a MinterManagementInterface
implementation. The minter address must be active to permit allowance changes, and each controller's permissions are limited to a single minter, while the same minter can be shared across multiple controllers.
The Rescuable
contract allows controlled recovery of ERC20 tokens from the contract by a designated rescuer address. The rescuer can be updated by the contract owner and is the only address authorized to trigger token transfers using the rescueERC20
function. This mechanism is intended to prevent loss of assets due to incorrect or stuck transfers.
The EIP2612V3
abstract contract provides an internal implementation of EIP-2612, enabling gas-abstracted token approvals via off-chain signatures. It uses typed structured data in accordance with EIP-712 and integrates nonce tracking to prevent replay attacks. Signature validity is verified at execution using a utility function, and upon successful verification, the allowance is updated through an internal approval method.
The EIP3009V3
abstract contract implements EIP-3009, enabling off-chain authorized transfers and cancellations through gas-abstracted mechanisms. Authorization data includes validity windows and unique nonces, which are checked to prevent replay and front-running attacks. Signature verification is performed using EIP-712 structured data hashing, and authorization state is tracked to ensure single-use enforcement.
This Proxy
contract defines a proxy pattern enabling delegation of all calls to a designated implementation address determined at runtime. The fallback function captures all unmatched calls and forwards them via low-level delegatecall
.
Privileged roles
The FiatTokenV3
contract uses the custom implementation of Ownable
contract and custom access control roles to restrict access to important functions.
The contract
owner
can:Updates the
pauser
address.Update the
masterMinter
address.Updates the
rescuer
address.Updates the
blacklister
address.Transfer control of the contract to a new owner.
The address stored in
masterMinter
can:Add or update minters with specific minting allowances.
Remove existing minters.
The address marked as
minter
can:Mint new tokens within their configured allowances.
Burn their own token balances.
The address stored in
blacklister
can:Blacklist and unblacklist accounts, preventing them from interacting with the token.
The address stored in
pauser
can:Pause and unpause contract operations.
The address stored in
rescuer
can:Rescue ERC20 tokens locked up in this contract.
The MintController
contract extends the Controller
contract that uses a custom implementation of Ownable
contract that restrict access to important functions.
The contract
owner
can:Set a new
minterManager
address viasetMinterManager()
.Assign a controller to a specific worker using
configureController()
.Remove a controller by setting its associated worker to the zero address via
removeController()
.
Addresses defined as controllers in the internal
controllers
mapping can:Enable and set an allowance for their associated minter using
configureMinter()
.Remove their associated minter using
removeMinter()
.Increment the allowance for their associated minter using
incrementMinterAllowance()
.Decrement the allowance for their associated minter using
decrementMinterAllowance()
.
Potential Risks
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.
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, and potentially compromising the system's integrity and user assets.
The FiatTokenV3
contract does not enforce a maximum token supply. Minting is restricted to addresses with the minter role
, and each minter must have a configured allowance. Both roles and allowances are managed by the controller
. However, if the controller's private key is compromised, an attacker could grant unlimited allowances and mint unbounded tokens. This would result in severe inflation, loss of token value, erosion of user trust, and potential collapse of the protocol’s economic model and utility.
The FiatTokenV3
contract includes a blacklist mechanism that prevents blacklisted addresses from sending and receiving tokens. This mechanism is controlled by the blacklister
role, and the contract owner
has the authority to assign new blacklisters. If either the blacklister’s or owner’s private key is compromised, an attacker could arbitrarily blacklist any address, potentially disrupting user access, freezing assets, and undermining trust in the protocol.
The ability to pause contract operations introduces a risk by centralizing control in the hands of an administrator. If this control is compromised or misused, it could result in halting critical functions, leading to service disruptions or financial losses. This centralization increases the potential attack surface and undermines the principles of decentralization, making it a vulnerability. To mitigate this risk, it is recommended to implement additional safeguards, such as multi-signatures or decentralized control mechanisms.
In the library SignatureChecker
, the method isContract()
uses extcodesize(address)
to distinguish EOAs from smart contracts. However, during a contract’s constructor execution, extcodesize
returns 0
since the contract’s code is not yet stored on-chain. This means a contract under construction appears indistinguishable from an EOA, potentially allowing it to bypass this protection.
The FiatTokenV3
contract introduces _blacklist(address(this))
in its constructor to prevent the token contract from receiving tokens, by adding it to a blacklist. However, this restriction can be removed by using the unBlacklist()
function, as it allows the blacklisting to be reversed, enabling the contract to receive tokens again. This could lead to unintended consequences, such as the contract receiving tokens when it was originally intended to be restricted from doing so.
The MinterController
contract allows multiple controller addresses to be linked to the same minter without restrictions. Although each controller maps to only one minter, there's no constraint preventing many controllers from configuring the same minter's allowance independently. Given that controllers appear to be external actors, this creates a risk of miscommunication or conflicting configuration changes. This design may lead to unclear ownership, overlapping responsibilities, and potentially uncoordinated minting allowance updates. Therefore it introduces governance complexity that could affect operational clarity and scalability.
Findings
Code ― | Title | Status | Severity | |
---|---|---|---|---|
F-2025-1008 | Lack of disableInitializers Allow Direct Implementation Initialization | fixed | Observation | |
F-2025-1006 | Lack of Zero-Amount Checks | fixed | Observation | |
F-2025-1006 | Unused State Variable | accepted | Observation | |
F-2025-1004 | Gas Inefficiency Due to Missing Usage of Solidity Custom Errors | accepted | Observation | |
F-2025-1004 | Missing Zero Address Validation | fixed | Observation | |
F-2025-1007 | Missing Storage Gaps in Base Contracts | accepted | Observation | |
F-2025-1004 | Use Ownable2Step instead of Ownable | accepted | Observation | |
F-2025-1007 | Missing Allowance Checks May Result in Silent Failure | fixed | Observation |
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 | |
---|---|
Repository | https://github.com/Haycen/haycen-smart-contract→ |
Commit | 5157b7cc8f2198de381a4aaf45a2d7280ebbe5a7 |
Remediation Commit | 07eae8b101aaef34fe8dbf285a82674cb5ec1bc2 |
Whitepaper | N/A |
Requirements | https://github.com/Haycen/haycen-smart-contract/doc→ |
Technical Requirements | https://github.com/Haycen/haycen-smart-contract/doc→ |
Scope Details
- Commit
- 5157b7cc8f2198de381a4aaf45a2d7280ebbe5a7
- Remediation Commit
- 07eae8b101aaef34fe8dbf285a82674cb5ec1bc2
- Whitepaper
- N/A
- Technical Requirements
- https://github.com/Haycen/haycen-smart-contract/doc→
Assets in Scope
File: minting/Controller.sol
File: minting/MasterMinter.sol
File: minting/MintController.sol
File: upgradeability/Proxy.sol
File: util/MessageHashUtils.sol
File: util/SignatureChecker.sol
File: v1.1/Rescuable.sol
File: v1/AbstractFiatTokenV1.sol
File: v1/Blacklistable.sol
File: v1/Ownable.sol
File: v1/Pausable.sol
File: v2/EIP712Domain.sol
File: v3/AbstractFiatTokenV3.sol
File: v3/EIP2612V3.sol
File: v3/EIP3009V3.sol
Appendix 3. Additional Valuables
Verification of System Invariants
During the audit of Haycen, Hacken followed its methodology by performing fuzz-testing on the project's main functions. Foundry, a tool used for fuzz-testing, was employed to check how the protocol behaves under various inputs. Due to the complex and dynamic interactions within the protocol, unexpected edge cases might arise. Therefore, it was important to use fuzz-testing to ensure that several system invariants hold true in all situations.
Fuzz-testing allows the input of many random data points into the system, helping to identify issues that regular testing might miss. A specific Echidna fuzzing suite was prepared for this task, and throughout the assessment, 7 invariants were tested over 70,000 runs. This thorough testing ensured that the system works correctly even with unexpected or unusual inputs.
Invariant | Test Result | Run Count |
---|---|---|
ownership transfer | Passed | 10k |
mint controller and worker | Passed | 10k |
decrement allowance amount | Passed | 10k |
burn amount and minter address | Passed | 10k |
transfer addresses and amount | Passed | 10k |
transferFrom addresses and amount | Passed | 10k |
signature | Passed | 10k |
Invariant
- ownership transfer
Test Result
- Passed
Run Count
- 10k
Invariant
- mint controller and worker
Test Result
- Passed
Run Count
- 10k
Invariant
- decrement allowance amount
Test Result
- Passed
Run Count
- 10k
Invariant
- burn amount and minter address
Test Result
- Passed
Run Count
- 10k
Invariant
- transfer addresses and amount
Test Result
- Passed
Run Count
- 10k
Invariant
- transferFrom addresses and amount
Test Result
- Passed
Run Count
- 10k
Invariant
- signature
Test Result
- Passed
Run Count
- 10k
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.