You are on page 1of 15

SECURITY AUDIT OF

DGG MARKETPLACE

Public Report
Apr 04, 2023

Verichains Lab
info@verichains.io
https://www.verichains.io
Driving Technology > Forward
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

ABBREVIATIONS
Name Description

Ethereum An open source platform based on blockchain technology to create and


distribute smart contracts and decentralized applications.

Ether A cryptocurrency whose blockchain is generated by the Ethereum platform.


(ETH) Ether is used for payment of transactions and computing services in the
Ethereum network.

Smart A computer protocol intended to digitally facilitate, verify or enforce the


contract negotiation or performance of a contract.

Solidity A contract-oriented, high-level language for implementing smart contracts for


the Ethereum platform.

Solc A compiler for Solidity.

ERC721 The ERC-721 introduces a standard for NFT, in other words, this type of
Token is unique and can have different value than another Token from the
same Smart Contract, maybe due to its age, rarity or even something else like
its visual

Page 2
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

EXECUTIVE SUMMARY
This Security Audit Report was prepared by Verichains Lab on Apr 04, 2023. We would
like to thank the DGG Network for trusting Verichains Lab in auditing smart contracts.
Delivering high-quality audits is always our top priority.
This audit focused on identifying security flaws in code and the design of the DGG
Marketplace. The scope of the audit is limited to the source code files provided to Verichains.
Verichains Lab completed the assessment using manual, static, and dynamic analysis
techniques.
During the audit process, the audit team had identified some vulnerable issues in the smart
contracts code.

Page 3
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

TABLE OF CONTENTS
1. MANAGEMENT SUMMARY ................................................................................................................. 5
1.1. About DGG Marketplace .................................................................................................................. 5
1.2. Audit scope .......................................................................................................................................... 5
1.3. Audit methodology ............................................................................................................................. 5
1.4. Disclaimer ........................................................................................................................................... 6
2. AUDIT RESULT ........................................................................................................................................ 7
2.1. Overview ............................................................................................................................................. 7
2.1.1. Market.sol ..................................................................................................................................... 7
2.1.2. MintingStation.sol ........................................................................................................................ 7
2.2. Findings ............................................................................................................................................... 7
2.2.1. [ ] Market.sol - Remove collection address when remove a collection ID ................. 7
2.2.2. [ ] Market.sol - Modify ask order with arbitrary tokenBuy ...................................... 8
2.2.3. [ ] Market.sol - Front-Running: seller can change tokenBuy before buyer buy ....... 9
2.2.4. [ ] Market.sol - owner can transfer any ERC20 tokens in contract, including creator and
trading fee .................................................................................................................................................... 10
2.2.5. [ ] Market.sol - Wrong execution with comment of recoverNonFungibleToken()
function ........................................................................................................................................................ 11
2.2.6. [ ] Market.sol - Inconsistency in creating and modify collection ...................................... 11
2.2.7. [ ] Market.sol - Inconsistency in _collectionAddressSet and _collections
variables ....................................................................................................................................................... 12
2.2.8. [ ] Market.sol - Creator can change trading fee after seller ask to sell ............................... 13
2.2.9. [ ] Market.sol - TYPO reciver in batchTransfer() function ................. 14
2.2.10. [ ] Market.sol - Missing emit event at buyToken() function ...................... 14
3. VERSION HISTORY .............................................................................................................................. 15

Page 4
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

1. MANAGEMENT SUMMARY
1.1. About DGG Marketplace
DGG Marketplace is an NFT marketplace that facilitates the buying and selling of Non-
Fungible Tokens (ERC721) using Fungible Tokens (ERC20). Users are required to pay a small
trading fee and the creator also receives compensation through this platform.

1.2. Audit scope


This audit focused on identifying security flaws in code and the design of the DGG
Marketplace.
The following files were made available in the course of the review:

SHA256 Sum File

4d3a545aa58420f786368c05158d4748e12c491a Market.sol

dec0ddf860846e1368f7e0fc9106bdf67b9e30cc MintingStation.sol

1.3. Audit methodology


Our security audit process for smart contract includes two steps:
• Smart contract codes are scanned/tested for commonly known and more specific
vulnerabilities using public and RK87, our in-house smart contract security analysis
tool.
• Manual audit of the codes for security issues. The contracts are manually analyzed to
look for any potential problems.
Following is the list of commonly known vulnerabilities that were considered during the
audit of the smart contract:
• Integer Overflow and Underflow
• Timestamp Dependence
• Race Conditions
• Transaction-Ordering Dependence
• DoS with (Unexpected) revert
• DoS with Block Gas Limit
• Gas Usage, Gas Limit and Loops
• Redundant fallback function
• Unsafe type Inference
• Reentrancy

Page 5
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

• Explicit visibility of functions state variables (external, internal, private and public)
• Logic Flaws
For vulnerabilities, we categorize the findings into categories as listed in table below,
depending on their severity level:

SEVERITY DESCRIPTION
LEVEL

A vulnerability that can disrupt the contract functioning; creates a critical


risk to the contract; required to be fixed immediately.

A vulnerability that could affect the desired outcome of executing the


contract with high impact; needs to be fixed with high priority.

A vulnerability that could affect the desired outcome of executing the


contract with medium impact in a specific scenario; needs to be fixed.

An issue that does not have a significant impact, can be considered as less
important.

Table 1. Severity levels

1.4. Disclaimer
Please note that security auditing cannot uncover all existing vulnerabilities, and even an
audit in which no vulnerabilities are found is not a guarantee for a 100% secure smart contract.
However, auditing allows discovering vulnerabilities that were unobserved, overlooked during
development and areas where additional security measures are necessary.

Page 6
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

2. AUDIT RESULT
2.1. Overview
This table lists some properties of the audited DGG Marketplace (as of the report writing
time).

2.1.1. Market.sol
This smart contract inherits from Ownable, ReentrancyGuard and ERC721Holder. The Market
feature enables the admin to create collections that include ERC721 addresses, which allows
users to list their assets and set ask orders for selling. Moreover, users have the option to
purchase NFT assets using ERC20 tokens that have been pre-defined by either the admin or
the collection creator.
Specifically, the admin can recover fungible tokens if the balance of an address surpasses
the pending revenue required to pay either the creator or the treasury. Furthermore, they can
recover non-fungible tokens that are not listed in the ask orders.

2.1.2. MintingStation.sol
The contract inherits from the AccessControl contract from the OpenZeppelin library, which
provides a role-based access control mechanism.
The MintingStation contract enables the contract owner to recover ERC20/ERC721 tokens,
set a whitelist of signers, and transfer contract ownership. The smart contract only allows
signers who are in the whitelist to call the mintCollectible() function to mint new ERC721
tokens. The function uses the ecrecover() function to verify that the message was signed by a
signer who is in the whitelist.

2.2. Findings
During the audit process, the audit team found some vulnerability issues in the given
sources of DGG Marketplace.

2.2.1. [ ] Market.sol - Remove collection address when remove a collection ID


2.2.1.1. Description
When an admin uses the closeCollectionForTradingAndListing() function to close a
collection for trading and listing, the function unintentionally removes the entire _collection
instead of just deleting the collection ID. Consequently, this leads to the loss of all other
collection IDs that have the same address.
function closeCollectionForTradingAndListing(address _collection,uint256 _collectionId)
external onlyAdmin {

Page 7
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

require(_collectionAddressSet.contains(_collection), "Operations: Collection not


listed");

_collections[_collection][_collectionId].status = CollectionStatus.Close;
_collectionAddressSet.remove(_collection); // ISSUE AT THIS LINE

emit CollectionClose(_collection, _collectionId);


}

RECOMMENDATION

The code can be fixed as below:


function closeCollectionForTradingAndListing(address _collection,uint256 _collectionId)
external onlyAdmin {
require(_collections[_collection][_collectionId].status == CollectionStatus.Open,
"Operations: Collection not listed"); // FIXED

_collections[_collection][_collectionId].status = CollectionStatus.Close;
// _collectionAddressSet.remove(_collection); <-- REMOVE THIS

emit CollectionClose(_collection, _collectionId);


}

UPDATES

• Apr 4, 2023: This issue has been acknowledged and fixed by the DGG Network team

2.2.2. [ ] Market.sol - Modify ask order with arbitrary tokenBuy


2.2.2.1. Description
After creating an ask order, the token owner can modify it using the modifyAskOrder()
function. This function accepts both the _newTokenBuy and _tokenBuy parameters. However, a
flaw in the code causes the function to first check if the buy token is allowed using the _tokenBuy
parameter, and then it assigns the new buy token using _newTokenBuy. This mistake can enable
the owner to modify an ask order with an arbitrary tokenBuy.
Scenario impact:
• Owner list a NFT on market that token buy is BNB (allowed) and price is 1 BNB.
• Owner edit token buy to ETH.
• Front-end display 1 unknown token and user click buy then approve quickly.
• NFT was sold with 1 ETH.

RECOMMENDATION

The code can be fixed as below:

Page 8
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

function modifyAskOrder(
address _collection,
uint256 _tokenId,
uint256 _newPrice,
address _newTokenBuy,
//address _tokenBuy, <-- REMOVE THIS LINE
uint256 _collectionId
) external nonReentrant {
// Verify new price is not too low/high
require(_newPrice >= minimumAskPrice && _newPrice <= maximumAskPrice, "Order: Price not
within range");

// Verify collection is accepted


require(_collections[_collection][_collectionId].status == CollectionStatus.Open,
"Collection: Not for listing");

// Verify the sender has listed it


require(_tokenIdsOfSellerForCollection[msg.sender][_collection].contains(_tokenId),
"Order: Token not listed");

// require(allowBuyTokens[_tokenBuy] == true, "Order: token buy not allow"); // REMOVE


THIS LINE
require(allowBuyTokens[_newTokenBuy] == true, "Order: token buy not allow"); //FIXED

require(askHistory[_collection][_tokenId].collectionId == _collectionId, "wrong


collection");

// Adjust the information


_askDetails[_collection][_tokenId].price = _newPrice;
_askDetails[_collection][_tokenId].tokenBuy = _newTokenBuy;

// Emit event
emit AskUpdate(_collection, msg.sender, _tokenId, _newPrice, _newTokenBuy,
_collectionId);
}

UPDATES

• Apr 4, 2023: This issue has been acknowledged and fixed by the DGG Network team

2.2.3. [ ] Market.sol - Front-Running: seller can change tokenBuy before buyer


buy
2.2.3.1. Description
If someone buys an attacker's NFT and then initiates a transaction to purchase a token, the
attacker may be able to execute a front-running transaction. This could involve modifying the

Page 9
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

token purchase to a different token that was previously approved by the user, and that has a
higher price than the original token being purchased.
Example: Front-running change 1 BNB to 1 ETH.

RECOMMENDATION

The code can be fixed as below:


function buyToken(
address _collection,
uint256 _tokenId,
uint256 _price,
address _tokenBuy, // ADD THIS
uint256 _collectionId
) public nonReentrant {
Ask memory askOrder = _askDetails[_collection][_tokenId];

require(_tokenBuy == askOrder.tokenBuy, "Buy: Incorrect Token"); // FIXED

IERC20(askOrder.tokenBuy).safeTransferFrom(address(msg.sender), address(this), _price);

_buyToken(_collection, _tokenId, _price, _collectionId);


}

UPDATES

• Apr 4, 2023: This issue has been acknowledged and fixed by the DGG Network team

2.2.4. [ ] Market.sol - owner can transfer any ERC20 tokens in contract, including
creator and trading fee
2.2.4.1. Description
If the owner of a contract calls the recoverFungibleTokens() function, they should be able to
withdraw all the ERC20 tokens balance in the contract, including those that were originally
sent as creator and trading fees.

RECOMMENDATION

Calculate carefully before transfer. We suggest have a global mapping to store total pending
revenue (totalPendingRevenue) for each token. And then, the code can be fixed as below:
function recoverFungibleTokens(address _token) external onlyOwner {
uint256 amountToRecover = IERC20(_token).balanceOf(address(this)) -
totalPendingRevenue[_token]; // FIXED
require(amountToRecover != 0, "Operations: No token to recover");

Page 10
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

IERC20(_token).safeTransfer(address(msg.sender), amountToRecover);

emit TokenRecovery(_token, amountToRecover);


}

UPDATES

• Apr 4, 2023: This issue has been acknowledged


• Apr 6, 2023: This issue has been fixed by the DGG Network team

2.2.5. [ ] Market.sol - Wrong execution with comment of recoverNonFungibleToken()


function
2.2.5.1. Description
The recoverNonFungibleToken() function is expected to transfer a non-fungible token from
the contract address to the msg.sender. However, it is not doing so in its current implementation.
It is important to note that the administrator has the ability to transfer any non-fungible token
by providing an incorrect collection ID.

RECOMMENDATION

The contract must have a mapping to store all NFT listed on market (ex: tokenListed) and
then the code can be fixed as below:
function recoverNonFungibleToken(address _token, uint256 _tokenId) external onlyOwner
nonReentrant {
require(!tokenListed[_token].contains(_tokenId), "Operations: NFT not recoverable");
// FIXED
IERC721(_token).safeTransferFrom(address(this), msg.sender, _tokenId);
// FIXED

emit NonFungibleTokenRecovery(_token, _tokenId, _collectionId);


}

UPDATES

• Apr 4, 2023: This issue has been acknowledged


• Apr 6, 2023: This issue has been fixed by the DGG Network team

2.2.6. [ ] Market.sol - Inconsistency in creating and modify collection


2.2.6.1. Description
If the admin sets the creator's address to zero while creating a collection, the
modifyCollection() function will be dissatisfied with the first requirement. Consequently, the
admin will be unable to modify the collection.

Page 11
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

In a similar way, the admin can create collection exits again.

RECOMMENDATION

require(_collections[_collection][_collectionId].creatorAddress != address(0),"Operations:
Collection not listed");

Replace above code with this fixed code:


require(_collections[_collection][_collectionId].collectionId != 0,"Operations: Collection
not listed");

UPDATES

• Apr 4, 2023: This issue has been acknowledged and fixed by the DGG Network team

2.2.7. [ ] Market.sol - Inconsistency in _collectionAddressSet and _collections


variables
2.2.7.1. Description
After remove collection, the collection address stored in _collectionAddressSet is deleted.
But admin still can modify that collection because modifyCollection() does not check collection
in _collectionAddressSet.
Example:
• admin create a collection A => _collectionAddressSet has A and status A in
_collections is OPEN
• admin remove collection A => _collectionAddressSet removed A and status A in
_collections is CLOSED
• admin modify collection A => _collectionAddressSet does not have A and status A in
_collections is OPEN

RECOMMENDATION

The code can be fixed like the first issue:


function closeCollectionForTradingAndListing(address _collection,uint256 _collectionId)
external onlyAdmin {
require(_collections[_collection][_collectionId].status == CollectionStatus.Open,
"Operations: Collection not listed"); // FIXED

_collections[_collection][_collectionId].status = CollectionStatus.Close;
// _collectionAddressSet.remove(_collection); <-- REMOVE THIS

emit CollectionClose(_collection, _collectionId);


}

Page 12
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

UPDATES

• Apr 4, 2023: This issue has been acknowledged and fixed by the DGG Network team

2.2.8. [ ] Market.sol - Creator can change trading fee after seller ask to sell
2.2.8.1. Description
It is not transparent when the creator or admin modifies the collection's creator or trading
fee after the seller has requested to list the NFT on the market.

RECOMMENDATION

The code need check before modify collection as below:


function modifyCollection(
address _collection,
address _creator,
address _whitelistChecker,
uint256 _tradingFee,
uint256 _creatorFee,
uint256 _collectionId
) external {
//require(_collectionAddressSet.contains(_collection), "Operations: Collection not
listed");
require(_collections[_collection][_collectionId].creatorAddress !=
address(0),"Operations: Collection not listed");

require(
(_creatorFee == 0 && _creator == address(0)) || (_creatorFee != 0 && _creator !=
address(0)),
"Operations: Creator parameters incorrect"
);

Collection storage collection = _collections[_collection][_collectionId];

require(msg.sender == collection.creatorAddress || msg.sender == adminAddress, "not


creator or admin");

if(_askTokenIds[_collection][_collectionId].length() == 0) {
require(_tradingFee + _creatorFee <= TOTAL_MAX_FEE, "Operations: Sum of fee must
inferior to TOTAL_MAX_FEE");

collection = Collection({
status: CollectionStatus.Open,
creatorAddress: _creator,
whitelistChecker: _whitelistChecker,
tradingFee: _tradingFee,
creatorFee: _creatorFee,

Page 13
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

collectionId: _collectionId
});
} else {
collection = Collection({
status: CollectionStatus.Open,
creatorAddress: _creator,
whitelistChecker: _whitelistChecker,
tradingFee: collection.tradingFee,
creatorFee: collection.creatorFee,
collectionId: _collectionId
});
}

emit CollectionUpdate(_collection, _creator, _whitelistChecker, _tradingFee,


_creatorFee,_collectionId);
}

UPDATES

• Apr 4, 2023: This issue has been acknowledged and fixed by the DGG Network team

2.2.9. [ ] Market.sol - TYPO reciver in batchTransfer() function

RECOMMENDATION

Replace reciver with receiver.

UPDATES

• Apr 4, 2023: This issue has been acknowledged and fixed by the DGG Network team

2.2.10. [ ] Market.sol - Missing emit event at buyToken() function

RECOMMENDATION

Add emit at the end of buyToken() function

UPDATES

• Apr 4, 2023: This issue has been acknowledged and fixed by the DGG Network team

Page 14
Report for DGG Network
Security Audit – DGG Marketplace
Version: 1.1 - Public Report
Date: Apr 04, 2023

3. VERSION HISTORY
Version Date Status/Change Created by

1.0 Apr 04, 2023 Public Report Verichains Lab

1.1 Apr 06, 2023 Public Report Verichains Lab

Table 2. Report versions history

Page 15

You might also like