Prepared by:
HALBORN
Last Updated 03/06/2025
Date of Engagement: February 26th, 2025 - February 27th, 2025
100% of all REPORTED Findings have been addressed
All findings
7
Critical
0
High
0
Medium
1
Low
0
Informational
6
Mintify
engaged Halborn
to conduct a security assessment on their Mintify SPL Token with Wormhole integration beginning on February 26th, 2025 and ending on February 27th, 2025. The security assessment was scoped to the smart contracts provided in the mintify-wormhole-token GitHub repository, commit hashes, and further details can be found in the Scope section of this report.
The team at Halborn assigned one full-time security engineer to check the security of the smart contracts. The security engineer is a blockchain and smart-contract security expert with advanced penetration testing and smart-contract hacking skills, and deep knowledge of multiple blockchain protocols.
The purpose of this assessment is to:
Ensure that smart contract functionality operates as intended
Identify potential security issues with the smart contracts
In summary, Halborn identified some improvements to reduce the likelihood and impact of risks, which have been partially addressed by the Mintify team
. The main ones were the following:
Add a strict check during minting to ensure that no more tokens than intended can ever be minted.
Implement OpenZeppelin's Pausable module to provide a flexible and secure mechanism for temporarily suspending contract functionality in case of emergency.
Use a fixed Solidity version in the pragma to ensure the contract is always compiled with a known version.
Halborn
performed a combination of manual review of the code and automated security testing to balance efficiency, timeliness, practicality, and accuracy in regard to the scope of the smart contract assessment. While manual testing is recommended to uncover flaws in logic, process, and implementation; automated testing techniques help enhance coverage of smart contracts and can quickly identify items that do not follow security best practices. The following phases and associated tools were used throughout the term of the assessment:
Research into the architecture, purpose, and use of the platform.
Smart contract manual code review and walkthrough to identify any logic issue.
Thorough assessment of safety and usage of critical Solidity variables and functions in scope that could lead to arithmetic related vulnerabilities.
Manual testing by custom scripts.
Graphing out functionality and contract logic/connectivity/functions (solgraph
).
Static Analysis of security for scoped contract, and imported functions. (Slither
).
EXPLOITABILITY METRIC () | METRIC VALUE | NUMERICAL VALUE |
---|---|---|
Attack Origin (AO) | Arbitrary (AO:A) Specific (AO:S) | 1 0.2 |
Attack Cost (AC) | Low (AC:L) Medium (AC:M) High (AC:H) | 1 0.67 0.33 |
Attack Complexity (AX) | Low (AX:L) Medium (AX:M) High (AX:H) | 1 0.67 0.33 |
IMPACT METRIC () | METRIC VALUE | NUMERICAL VALUE |
---|---|---|
Confidentiality (C) | None (I:N) Low (I:L) Medium (I:M) High (I:H) Critical (I:C) | 0 0.25 0.5 0.75 1 |
Integrity (I) | None (I:N) Low (I:L) Medium (I:M) High (I:H) Critical (I:C) | 0 0.25 0.5 0.75 1 |
Availability (A) | None (A:N) Low (A:L) Medium (A:M) High (A:H) Critical (A:C) | 0 0.25 0.5 0.75 1 |
Deposit (D) | None (D:N) Low (D:L) Medium (D:M) High (D:H) Critical (D:C) | 0 0.25 0.5 0.75 1 |
Yield (Y) | None (Y:N) Low (Y:L) Medium (Y:M) High (Y:H) Critical (Y:C) | 0 0.25 0.5 0.75 1 |
SEVERITY COEFFICIENT () | COEFFICIENT VALUE | NUMERICAL VALUE |
---|---|---|
Reversibility () | None (R:N) Partial (R:P) Full (R:F) | 1 0.5 0.25 |
Scope () | Changed (S:C) Unchanged (S:U) | 1.25 1 |
Severity | Score Value Range |
---|---|
Critical | 9 - 10 |
High | 7 - 8.9 |
Medium | 4.5 - 6.9 |
Low | 2 - 4.4 |
Informational | 0 - 1.9 |
Critical
0
High
0
Medium
1
Low
0
Informational
6
Security analysis | Risk level | Remediation Date |
---|---|---|
Missing MAX_SUPPLY Enforcement | Medium | Solved - 02/28/2025 |
Centralized Minter Role | Informational | Acknowledged - 03/03/2025 |
Absence of Pausable Mechanism for Emergency Control | Informational | Acknowledged - 03/03/2025 |
Floating Pragma | Informational | Acknowledged - 03/03/2025 |
Use of Hardcoded Decimal Value Instead of Constant or Function | Informational | Acknowledged - 03/03/2025 |
Missing Validation for Non-Zero Mint Amount | Informational | Acknowledged - 03/03/2025 |
Lack of Dedicated Mint Event for Transparency | Informational | Acknowledged - 03/03/2025 |
//
Although a MAX_SUPPLY
constant is declared in the contract, there is no validation against it in the mint
function.
This allows for unlimited token creation, potentially causing severe inflation, undermining the token’s value, and resulting in behavior that is clearly not intended.
Snippet of code from Mintify contract:
contract Mintify is ERC20, ERC20Permit, ERC20Burnable, Ownable2Step {
uint256 public constant MAX_SUPPLY = 10_000_000_000 * 10 ** 18;
address public minter;
Code of mint
function:
function mint(address account, uint256 amount) external onlyMinter {
_mint(account, amount);
}
It is recommended to add a strict check in mint
:
require(totalSupply() + amount <= MAX_SUPPLY, "Exceeds max supply");
This ensures that no more tokens than intended can ever be minted.
SOLVED: The Mintify team has solved this issue by implementing the recommended validation.
//
The contract designates a single address as the minter
, with the power to mint new tokens at will, creating a significant centralization risk. If the minter
address is compromised, lost, or behaves maliciously, the following risks arise:
Unlimited Token Creation: A compromised minter
could mint an infinite number of tokens, causing severe inflation and undermining the token’s value and integrity.
Single Point of Failure: If the minter
private key is lost, the contract loses its minting capability, potentially halting crucial operations.
It is recommended to decentralize the minting authority by:
Implementing a Multisig Wallet: Use a multisignature wallet (e.g., Gnosis Safe) as the minter
, requiring multiple approvals for each minting action. This approach minimizes the impact of a compromised private key, as no single entity can unilaterally mint tokens.
Adopting Governance Mechanisms: Incorporate a decentralized governance model (e.g., DAO voting) to control the minter
role, ensuring community involvement and reducing the risk of centralized abuse.
ACKNOWLEDGED: The Mintify team has acknowledged this finding.
//
The contract lacks a Pausable
implementation, which means it cannot be temporarily halted in case of emergencies, such as security breaches, exploits, or unexpected behavior.
Without this safeguard, the contract remains fully operational even if a critical vulnerability is discovered, increasing the risk of further damage, unauthorized minting, or fund loss
It is recommended to implement OpenZeppelin's Pausable
module to provide a flexible and secure mechanism for temporarily suspending contract functionality in case of emergency.
ACKNOWLEDGED: The Mintify team has acknowledged this finding.
//
The Mintify
contract uses a floating pragma version, which allows compilation with multiple versions of the Solidity compiler.
This approach can introduce unexpected behaviors if new compiler versions are released, potentially introducing changes or bugs that impact the contract.
Snippet of code from Mintify contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
It is recommended to use a fixed Solidity version in the pragma, such as pragma solidity 0.8.20
, to ensure the contract is always compiled with a known version. This minimizes the risk of unexpected behaviors due to compiler changes.
ACKNOWLEDGED: The Mintify team has acknowledged this finding.
//
The contract uses the 10**18
value directly as a magic number to represent the token’s decimals, which can lead to higher gas costs and decrease readability.
Additionally, using hardcoded values can make it difficult to adjust the decimal precision if necessary.
Snippet of code from StarOFToken contract:
contract Mintify is ERC20, ERC20Permit, ERC20Burnable, Ownable2Step {
uint256 public constant MAX_SUPPLY = 10_000_000_000 * 10 ** 18;
address public minter;
It is recommended to replace the hardcoded decimal value with decimals()
or define a constant, such as DECIMALS
to optimize gas usage and improve the contract’s readability. This will make the code more adaptable to future changes.
ACKNOWLEDGED: The Mintify team has acknowledged this finding.
//
The contract fails to verify that the amount to be minted is strictly greater than zero.
Even though _mint
ensures a non-zero recipient address, zero-token minting remains possible, creating unnecessary transactions with no meaningful effect.
Code of mint
function:
function mint(address account, uint256 amount) external onlyMinter {
_mint(account, amount);
}
It is recommended to include a check within the mint
function:
require(amount > 0, "Mint zero tokens");
This ensures all mint operations involve a positive token amount, improving clarity and saving gas.
ACKNOWLEDGED: The Mintify team has acknowledged this finding.
//
The contract relies solely on the standard Transfer
event emitted by _mint
.
Although this indicates the creation of new tokens, it lacks explicit clarity. Off-chain services, explorers, and auditors may find it challenging to differentiate between minting and regular transfers from the zero address.
It is recommended to create and emit a custom Mint
event, for example:
event Mint(address indexed to, uint256 amount);
function mint(address account, uint256 amount) external onlyMinter {
_mint(account, amount);
emit Mint(account, amount);
}
This ensures clear tracking of newly minted tokens.
ACKNOWLEDGED: The Mintify team has acknowledged this finding.
Halborn used automated testing techniques to enhance the coverage of certain areas of the smart contracts in scope. Among the tools used was Slither, a Solidity static analysis framework. After Halborn verified the smart contracts in the repository and was able to compile them correctly into their abis and binary format, Slither was run against the contracts. This tool can statically verify mathematical relationships between Solidity variables to detect invalid or inconsistent usage of the contracts' APIs across the entire code-base.
The security team assessed all findings identified by the Slither software, however, findings with related to external dependencies are not included in the below results for the sake of report readability.
The findings from the Slither scan have not been included in the report, as they were all related to third-party dependencies.
Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.
// Download the full report
* Use Google Chrome for best results
** Check "Background Graphics" in the print settings if needed