BlackLemon Marketplace - Audit Report
Audit Summary
BlackLemon is building a new marketplace that allows users to buy and sell NFTs.
For this audit, we reviewed the project team's contracts at commit 57476598c415e8ef6f4dbbf4add02c238c92fac2 on the team's private GitHub repository.
We previously reviewed the project team's token contract here and staking contract here.
Please ensure trust in the team prior to exchanging NFTs as they have substantial control in the ecosystem.
Date: January 3rd, 2022.
Audit Findings
Optimization - Finding #1
Description: Several functions are declared public, but are never called internally. A state variable can never be modified, but is not declared constant.Recommendation: We recommend declaring these functions external and declaring the state variable constant for additional gas savings on each call.Functions: - Exchange: setTreasury, setTreasuryPercent, atomicMatch State Variables: - ExchangeCore: personalSignPrefix
Contracts Overview
Exchange and ExchangeCore Contracts:
- These contracts serve as a marketplace which allows users to exchange tokens for NFTs.
- Users can create a buy or sell order by submitting gasless signed messages and once a corresponding order is submitted and validated, the exchange transaction occurs.
- Signed messages are stored on the team server and this process relies on off chain logic.
- Users should excerise caution and ensure that any buy or sell order uses trusted tokens.
- For users' orders to match, the following criteria must be met:
- The type and amount of the specified exchange token must be equal.
- Both orders must still be active.
- Both users' signatures must be validated with the original hash.
- Finally the seller and buyer addresses must be different.
- For an order to be active, its expiration time must not have elapsed and the order must not have already been filled.
- Upon order execution, a treasury tax is deducted from the sale amount and transferred to the treasury address.
- The owner can update the treasury address and set the treasury tax percentage to any value at any time.
- The contract utilizes ReentrancyGuard to prevent reentrancy attacks in applicable functions.
- The contracts are deployed with Solidity v0.8.X, preventing any overflow/underflow-related issues.
External Threat Results
Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Storage Write | N/A | PASS |
Arbitrary Jump | N/A | PASS |
Centralization of Control | The owner can set the treasury tax to any amount at any time. Generating a signed message hash requires the use of off chain logic. | WARNING |
Delegate Call to Untrusted Contract | N/A | PASS |
Dependence on Predictable Variables | N/A | PASS |
Deprecated Opcodes | N/A | PASS |
Ether Thief | N/A | PASS |
Exceptions | N/A | PASS |
External Calls | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Logical Issues | N/A | PASS |
Multiple Sends | N/A | PASS |
Suicide | N/A | PASS |
State Change External Calls | N/A | PASS |
Unchecked Retval | N/A | PASS |
User Supplied Assertion | N/A | PASS |
Critical Solidity Compiler | N/A | PASS |
Overall Contract Safety | PASS |
Exchange Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Pub] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
- [Prv] _setOwner #
+ ReentrancyGuarded
+ EIP712
- [Int] hash
+ ERC1271
- [Pub] isValidSignature
+ [Int] IERC165
- [Ext] supportsInterface
+ [Int] IERC721 (IERC165)
- [Ext] balanceOf
- [Ext] ownerOf
- [Ext] safeTransferFrom #
- [Ext] transferFrom #
- [Ext] approve #
- [Ext] getApproved
- [Ext] setApprovalForAll #
- [Ext] isApprovedForAll
- [Ext] safeTransferFrom #
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Int] verifyCallResult
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ ExchangeCore (ReentrancyGuarded, EIP712, Ownable)
- [Int] setTreasury_ #
- modifiers: onlyOwner
- [Int] setTreasuryPercent_ #
- modifiers: onlyOwner
- [Prv] calculateShareAmount_
- [Int] hashOrder_
- [Int] hashToSign_
- [Int] validateOrderParameters_
- [Int] validateOrderAuthorization_
- [Int] atomicMatch_ #
- modifiers: reentrancyGuard
+ Exchange (ExchangeCore)
- [Ext] hashOrder
- [Ext] hashToSign
- [Pub] setTreasury #
- modifiers: onlyOwner
- [Pub] setTreasuryPercent #
- modifiers: onlyOwner
- [Ext] validateOrderParameters
- [Ext] validateOrderAuthorization
- [Pub] atomicMatch ($)
ExchangeCore Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Pub] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
- [Prv] _setOwner #
+ ReentrancyGuarded
+ EIP712
- [Int] hash
+ ERC1271
- [Pub] isValidSignature
+ [Int] IERC165
- [Ext] supportsInterface
+ [Int] IERC721 (IERC165)
- [Ext] balanceOf
- [Ext] ownerOf
- [Ext] safeTransferFrom #
- [Ext] transferFrom #
- [Ext] approve #
- [Ext] getApproved
- [Ext] setApprovalForAll #
- [Ext] isApprovedForAll
- [Ext] safeTransferFrom #
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Int] verifyCallResult
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ ExchangeCore (ReentrancyGuarded, EIP712, Ownable)
- [Int] setTreasury_ #
- modifiers: onlyOwner
- [Int] setTreasuryPercent_ #
- modifiers: onlyOwner
- [Prv] calculateShareAmount_
- [Int] hashOrder_
- [Int] hashToSign_
- [Int] validateOrderParameters_
- [Int] validateOrderAuthorization_
- [Int] atomicMatch_ #
- modifiers: reentrancyGuard