MeldDAO

CertiKFiles named in the report

CertiK reviewed MELD (MeldDAO) on 9 Jun 2023: 15 findings, 0 critical; 9 marked fixed, 2 acknowledged, 4 open.

No open critical findings
Open the reportOpen MELD’s security record

Report hosted on skynet.certik.com.

Trustblock does not review code.

Findings15

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical000
High010
Medium012
Low407
MediumDelegated Token Can be RedeemedFixed

The function `redeem()` in the contract `MeldDaoERC721` only ensures that it has voted in an ongoing proposal, but does not check whether it is delegated to another NFT. As a result, the delegator cannot call the function `submitVote()` to submit the vote once the NFT which is delegated to it has been redeemed, because the transaction will be reverted by the owner check in the function `updateRedeemableTimestamp()`. To solve the issue, the delegator has to identify the redeemed NFT and call the function `removeDelegatedNft()` to remove the delegation.

MediumFunction `rescueERC721()` Should Filter Out `addrFixed

The function `rescueERC721()` allows the role `DEFAULT_ADMIN_ROLE` to transfer all types of the `ERC721` tokens including the current `MeldDaoERC721` tokens to an arbitrary address. The function does not check whether the `_token` address equals `address(this)`.

Low`delegatedIndexes` Not Updated In Function `removFixed

The function `removeAllDelegatedNfts()` does not clear the `delegatedIndexes` as the function `removeDelegatedNft()`. The behaviors should be consistent for both functions, the only difference should be execution to all delegations. ```solidity nft.delegatedIndexes[delegatedNftId] = 0; ``` As a result, the mapping `nft.delegatedIndexes` will contain obsolete data which contradicts the mapping `nft.delegatedNfts`.

Low`delegatedIndexes` Starts From 0Fixed

The mapping `delegatedIndexes` is the index of a given NFT in the `delegatedNfts` array. We can see that the index starts from 0 in the below code snippet in the function `delegateMyNft()`. However, this mechanism cannot distinguish the actual zero index from the null value, because the default value of the type `uint256` is also 0. If the `delegatedNfts` only has one element whose token id is 1, the value of `nft.delegatedIndexes[userNftId]` is still 0 which equals the default value. ```solidity nft.delegatedNfts.push(userNftId); nft.delegatedIndexes[userNftId] = nft.delegatedNfts.length - 1; ```

LowCheck-effects pattern not usedFixed

A reentrancy attack can occur when the contract creates a function that makes an external call to another untrusted contract before resolving any effects. If the attacker can control the untrusted contract, they can make a recursive call back to the original function, repeating interactions that would have otherwise not run after the external call resolved the effects. *This finding is considered informational because the meldToken is a known contract. Also, the effect of out-of-order increments may be unobservable after the transaction and the `require` statement may prevent the attack. However, the reentrancy vulnerability may still cause other issues in the middle of the transaction.* --- In the function `mint()`: ### External call(s) ```solidity=73 meldToken.safeTransferFrom(msg.sender, address(this), nftPrice); ``` ### State variables written after the call(s) ```solidity=78 lockedMeldTokens += nftPrice; ``` ```solidity=77 pricePaidPerNft[tokenId] = nftPrice; ``` ```solidity=76 _mint(msg.sender, tokenId); ``` * This function call executes the following assignment(s). * In `ERC721._mint`, * `_owners[tokenId] = to` *Note: Only a sample of 3 assignments (out of 5) are shown above.* --- In the function `redeem()`: ### External call(s) ```solidity=93 meldToken.safeTransfer(msg.sender, pricePaid - fee); ``` ```solidity=94 meldToken.safeTransfer(feeAddress, fee); ``` ### State variables written after the call(s) ```solidity=95 redeemedNfts++; ```

LowIncorrect Variable NamingFixed

The variable names `index` and `nftId` in the mapping `delegatedIndexes` are reversed. The key should be `nftId` and the value should be `index`. ```solidity=24 struct Nft { bool delegateable; uint256[] delegatedNfts; mapping(uint256 index => uint256 nftId) delegatedIndexes; } ```

LowMissing Emit EventsFixed

Functions that update state variables should emit relevant events as notifications. For example: `MeldVotingContract.startNewVotingForProposal()`.

LowNo Function To Cancel The VoteFixed

If the wrong proposals are made, there is no cancellation function in the contracts `MeldVotingContract` and `DaoRegistry`, although the `DaoRegistry` contract mentioned the `flags` can be `canceled`(code comment L90).

LowUnused parameter with no nameFixed

The function `startNewVotingForProposal()` in the contract `MeldVotingContract` receives a parameter in `bytes` type with no name and does not use it. It might be used for recording the proposal content.

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (12)

  • contracts/guards/AdapterGuard.sol
  • contracts/meld/adapters/interfaces/IMeldVoting.sol
  • contracts/core/CloneFactory.sol
  • contracts/meld/nft/MeldDaoERC721.sol
  • contracts/core/DaoRegistry.sol
  • contracts/helpers/DaoHelper.sol
  • contracts/meld/utils/RescueTokens.sol
  • contracts/meld/adapters/MeldProposalInitializer.sol
  • contracts/meld/adapters/interfaces/IMeldProposalInitializer.sol
  • contracts/meld/adapters/voting/MeldVoting.sol
  • contracts/guards/MemberGuard.sol
  • contracts/core/DaoFactory.sol

Part of MELD’s security record

MELD
Audits2 audits by 1 firmLast audit Jun 2023, by CertiK.
Critical findingsNo open critical findingsAcross 2 reports.
Open MELD’s security record

Security firm

CertiK

1,044 projects reviewed · 1,375 reports · latest May 2025

See CertiK’s audits

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us