All audits

Web3 · Smart contract audit

DMD Diamond

softstack completed a smart contract audit of DMD Diamond's Core in November 2025, reporting 48 findings (2 high, 14 medium, 17 low and 15 informational), of which 40 were resolved or mitigated before the final report. The full report is published in the softstack public audit archive.

Key facts

Client
DMD Diamond
Completed
Type
Smart contract audit
Commit
a121c2f26403
Market cap
$4M as of 2026-10-13

About the project

DMD Diamond is a proof-of-stake layer-1 blockchain founded in 2013 and steered by a community association rather than a company. The v4 network pairs the Honey Badger BFT consensus algorithm with POSDAO validator election, giving instant finality and full EVM compatibility. Supply is capped at 4.38 million DMD issued at genesis, with on-chain DAO governance over upgrades and funding.

Scope

Source repositorygithub.com/DMDcoin/diamond-contracts-dao

Components reviewed

1 module
  1. See the published report for the file list

Findings

0Critical
2High
14Medium
17Low
15Informational

40 of 48 findings resolved before the final report.

IDTitleSeverityStatus
6.2.1Denial of Service (DoS) Attack on ClaimContract's Fill Function

The ClaimContract contains a critical vulnerability in its fill function that allows a malicious actor to permanently prevent the contract from being initialized.

Highfixed
6.2.2Missing Access Control in AtomicSequencerImplementation

The claim function in the ClaimContract is vulnerable to signature replay attacks. The function uses a _postfix parameter in the signature verification process, but there's no mechanism to ensure this postfix is unique for each claim.

Highacknowledged
6.2.3Over-permissive Certification Logic in 'certified' Function

The 'certified' function in the CertifierHbbft contract contains a vulnerability in its logic for determining whether an address is certified.

Mediumacknowledged
6.2.4Uninitialized Counters in KeyGenHistory Contract

The KeyGenHistory contract has an initialization vulnerability where the counters numberOfPartsWritten and numberOfAcksWritten are not properly initialized during the contract's initialization process.

Mediumfixed
6.2.5Inconsistent Health Tracking in RandomHbbft Contract

The RandomHbbft contract has an inconsistency in how it tracks the health status of the validator set. The contract sets an unhealthiness flag for a block when setCurrentSeed is called and the validator set is not at full health.

Mediumfixed
6.2.6Array Out of Bounds Vulnerability in getSliceUInt256 Function

The getSliceUInt256 function in the TxPermissionHbbft contract contains a critical vulnerability that allows for out-of-bounds array access.

Mediumfixed
6.2.7Staking and Withdrawal Time Restrictions Disabled

The areStakeAndWithdrawAllowed() function in the StakingHbbft contract is currently hardcoded to always return true, effectively disabling any time-based restrictions on staking and withdrawal operations.

Mediumfixed
6.2.8Missing Input Validation in setPoolInfo Function

The setPoolInfo function in the StakingHbbft contract lacks crucial input validation for its parameters. This function allows users to set their pool's public key, IP address, and port number.

Mediumfixed
6.2.9Potential Signature Malleability and Replay Attack Vulnerability in Claim Verification

The claimMessageMatchesSignature function in the ClaimContract uses the Solidity ecrecover function directly to verify signatures.

Mediumacknowledged
6.2.10Incomplete Bitcoin-Style Address Generation in publicKeyToDMDAddress Function

The publicKeyToDMDAddress function in the ClaimContract attempts to generate a Bitcoin-style address from ECDSA public key coordinates.

Mediumacknowledged
6.2.11Insufficient Timestamp Validation in Dilution Events

The ClaimContract contains two significant issues related to the validation of dilution event timestamps: 1.

Mediumfixed
6.2.12Lack of Public Key Validation in claimMessageMatchesSignature Function

The claimMessageMatchesSignature function in the ClaimContract lacks crucial validation for the ECDSA public key coordinates (_pubKeyX and _pubKeyY) provided as input parameters.

Mediumfixed
6.2.13ECDSA Signature Malleability in claimMessageMatchesSignature Function

The claimMessageMatchesSignature function in the ClaimContract is vulnerable to signature malleability attacks. The function verifies ECDSA signatures without implementing protection against the malleability property of ECDSA signatures.

Mediumfixed
6.2.14Phase Duration Will Be Shortened Each Time switchPhase Is Delayed

When switchPhase is called, the new phase's start and end timestamps are derived from the previous phase's end timestamp: uint64 newPhaseStart = daoPhase.end + 1; daoPhase.start = newPhaseStart; daoPhase.end = newPhaseStart +…

Mediumfixed
6.2.15Finalization Uses Vote Snapshot But Dynamically Recalculates Quorum with Current Total Stake

During the finalize step of a proposal, votes are counted from a fixed user stakeAmount snapshot taken at the end of the Voting phase: function _snapshotStakes(uint64 daoEpoch) private { address[] memory daoEpochVoters =…

Mediumfixed
6.2.16Proposal Type Determination Ignores Intermediate Calldatas

When a proposal contains multiple calldatas, the _checkProposalType function determines the proposal type based on the last processed calldata that successfully identifies a range or defaults to a ContractUpgrade if any of the calldatas is…

Mediumfixed
6.2.17Misspelled Parameter Name in Claim Function

In the claim function of the ClaimContract, there is a misspelling in the parameter name _targetAdress. The correct spelling should be _targetAddress.

Lowfixed
6.2.18Inaccurate Comment for Public Key Y Coordinate

In the claim function of the ClaimContract, there is an incorrect comment for the _pubKeyY parameter. The comment incorrectly states "ECDSA public key X coordinate" instead of "Y coordinate".

Lowfixed
6.2.19Typographical Error in Dilution Error Message

In the ClaimContract, specifically within the dilution functions (dilute1, dilute2, and dilute3), there is a typographical error in the error message used when reverting due to an already executed dilution.

Lowfixed
6.2.20Mismatch Between Documented and Actual Return Type in createClaimMessage Function

In the ClaimContract, the createClaimMessage function has a discrepancy between its documented return type and its actual return type.

Lowfixed
6.2.21Use of RIPEMD-160 Precompile in publicKeyToDMDAddress Function May Not Be Universally Compatible

The publicKeyToDMDAddress function in the ClaimContract uses the ripemd160 hash function, which is implemented as a precompile contract in Ethereum at address(2).

Lowacknowledged
6.2.22Misspelling in Variable Name for Reinsert Pot Transfer Amount

In the _sendDilutedAmounts function of the ClaimContract, there is a typographical error in the variable name used for calculating the transfer amount to the Reinsert Pot.

Lowfixed
6.2.23Potential Reentrancy Vulnerability in _distributeRewards

The _distributeRewards function in the BlockRewardHbbft contract performs external calls before completing all state updates.

Lowfixed
6.2.24Redundant Check in 'certified' Function

The certified function in the CertifierHbbft contract performs a redundant check against the validator set.

Lowfixed
6.2.25Revocation State Inconsistency After Key Generation

In the KeyGenHistory contract, when the clearPrevKeyGenState function is called at the start of a new key generation round, it clears all pending validators' states and revocations from the previous epoch.

Lowfixed
6.2.26Insufficient Validation in Pool Removal Functions

The ValidatorSetHbbft contract's pool removal functions (_removePool and _removePoolUnordered) lack comprehensive validation checks before removing a pool from the active validator set.

Lowfixed
6.2.27Missing Reentrancy Protection in Critical Functions

The DiamondDao contract initializes the ReentrancyGuard in its initialize function but fails to apply the nonReentrant modifier to several critical functions that handle funds or make significant state changes.

Lowfixed
6.2.28Lack of Bounds Checking in _getCurrentValWithSelector Function

The _getCurrentValWithSelector function in the DiamondDao contract performs a staticcall to an external contract and attempts to read a 32-byte value from the returned data without verifying the data length.

Lowfixed
6.2.29Implicit Double-Voting Prevention in DAO Voting System

The DiamondDao contract implements a voting system for proposals using an EnumerableSet to track voters and a mapping to store vote records.

Lowfixed
6.2.30Owner Initialization Failure Making onlyOwner Functions Unusable

The DAO contract inherits Ownable functionality but never invokes __Ownable_init or otherwise sets the owner during initialization. As a result, the owner() is permanently address(0).

Lowfixed
6.2.31Zero or Negligible Total Stake Allows Proposals to Always Pass

In extreme scenarios where the total staking amount is zero or extremely small, the quorum calculation will allow proposals to almost always pass.

Lowfixed
6.2.32ProxyAdmin Ownership Not Transferred to DAO, Blocking Proposal Type Upgrades

The DAO uses a transparent proxy pattern controlled by a ProxyAdmin contract. For on-chain governance proposals to perform contract upgrades, the DAO must own the ProxyAdmin.

Lowfixed
6.2.33Proposals Can Be Finalized at Any Time But Execution Is Restricted to Specific Window

According to the DiamondDAO documentation, historical proposals can be finalized and executed at any time.

Lowfixed
6.2.34Inefficient Gas Usage Due to Non-Immutable Critical Variables

The ClaimContract contains several critical state variables that are set in the constructor and are not intended to be changed after contract deployment. These variables include beneficiary addresses and dilution timestamps.

Informationalfixed
6.2.35Unit Test Gaps

The diamond-contracts-core repository has achieved 95% test coverage, but there are specific test gaps that should be addressed to ensure comprehensive coverage of all contract functionalities and edge cases.

Informationalfixed
6.2.36Limited Flexibility in Proposal Fee Configuration

The DiamondDAO contract's initialize function sets up a fixed array of allowed proposal fee values (createProposalFeeAllowedParams). This array is hardcoded with nine specific values ranging from 10 to 90 ether.

Informationalfixed
6.2.37Potential for Proposal ID Collisions in hashProposal Function

The DiamondDao contract uses a hashProposal function to generate unique identifiers for proposals.

Informationalacknowledged
6.2.38Mismatch in Proposal Fee and Mention of Nonexistent Network Fees

The documentation states that the proposal fee is fixed at 20 DMD and can be changed via an ecosystem parameter proposal: The proposal fee is fixed at 20 DMD for all proposal types.

Informationalacknowledged
6.2.39Race Condition in _executeOperations Due to Limited governancePot

When multiple Open proposals execute in quick succession, they may drain the governancePot. Subsequent proposals attempting to execute transfers could fail if insufficient funds remain.

Informationalfixed
6.2.40Abstain Votes Are Ineffective

Currently, the contract calculates proposal acceptance based on exceeding yes/no percentages. Since participation thresholds is the same as the acceptance, abstain votes have no meaningful impact on the final outcome, despite being…

Informationalfixed
6.2.41Define and Use Constant Variables Instead of Using Literals

Rather than using constant literal values, create a constant state variable and reference it throughout the contract.

Informationalfixed
6.2.42Event Is Missing Indexed Fields

Index event fields make the field more quickly accessible to off-chain tools that parse events. Each event should use three indexed fields if there are three or more fields, and gas usage is not particularly of concern for the events in…

Informationalfixed
6.2.43Unused Custom Error

It is recommended that the definition be removed when custom error is unused. Found 2 instances: • Line 55: error FunctionUpgradeNotAllowed(bytes4 funcSelector, address targetContract); • Line 56: error InvalidUpgradeValue(uint256…

Informationalfixed
6.2.44Repeated Access to currentPhaseProposals.length in Loop Condition

In the loop condition (i < currentPhaseProposals.length) of the switchPhase function, the contract repeatedly reads the length property of a storage array. Each read from storage is more expensive than reading from memory.

Informationalfixed
6.2.45Hardcoded Governance Pot Address in Contract Logic

The BlockRewardHbbft contract uses a hardcoded governance pot address (0x2000000000000000000000000000000000000002 or similar) throughout its distribution logic.

Informationalacknowledged
6.2.46Commented Out Code in 'certified' Function

The certified function in the CertifierHbbft contract contains commented-out code that references a staking contract check.

Informationalfixed
6.2.47Typo in Parameter Name '_upcommingEpoch'

The KeyGenHistory contract contains a consistent spelling error in multiple locations where the parameter name _upcommingEpoch is used instead of the correct spelling _upcomingEpoch (with one 'm' instead of two). This typo appears in: 1.

Informationalfixed
6.2.48Unused '_txPermission' Parameter in Initialize Function

The DiamondDao contract's initialize function accepts an _txPermission parameter but never uses it anywhere in the contract.

Informationalfixed

Methodology

Review process

  1. Scoping and threat modelling

    The commit hash is frozen and the attack surface is mapped: asset flows, trust assumptions, privileged roles and the external systems the code depends on.

  2. Automated analysis

    Static analysers sweep the full codebase to surface known weakness patterns, unreachable states and deviations from established conventions.

  3. Manual code review

    Independent engineers read the code line by line, concentrating on business logic, access control, arithmetic and the handling of external calls.

  4. Adversarial testing

    Property-based fuzzing and invariant tests attack the assumptions the protocol relies on, targeting states that ordinary unit tests never reach.

  5. Reporting

    Every finding is documented with a severity rating, its impact, the steps to reproduce it and a concrete remediation the team can act on.

  6. Remediation verification

    Submitted fixes are re-reviewed against the original finding, and the final report records the resolved state of each one.

FAQ

The review reported 48 findings: 2 high, 14 medium, 17 low and 15 informational. 40 of 48 were resolved or mitigated before the final report.

The review covered the code in github.com/DMDcoin/diamond-contracts-dao at commit a121c2f. The published report lists every file covered.

This report covers the code as reviewed in November 2025 at commit a121c2f. Any code changed after that point is outside the reviewed scope.