Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Storage Write | N/A | PASS |
Arbitrary Jump | N/A | PASS |
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 |
Flash Loans | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Multiple Sends | N/A | PASS |
Oracles | 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 |
Black Lemon - Smart Contract Audit Report
Summary
Black Lemon is a new ERC20 token and platform for NFT staking.
Notes on the Token Contract:The initial supply of the token is set to 10 million [10,000,000]. No burn functions are present; though the circulating supply can be reduced by sending tokens to the 0x..dead address, if desired. The owner has the ability to assign and remove addresses to a Minter role. The assigned Minter(s) can mint tokens at any time up to a hard cap of 500 million tokens. As the token has not yet been deployed to the mainnet, there was no token allocation for our team to analyze. Upon deployment, the owner of the contract will be assigned to the Default Admin role. The Default Admin has the ability to assign and remove addresses to a Pauser role. The assigned Pauser has the ability to freeze/unfreeze all token transfers at any time. As the project is deployed with Solidity v0.8.2, it is protected from overflows.
Notes on the NFT Staking Contract:Users can stake NFTs in this contract to earn rewards in the form of the project's ERC20 token. Only NFT contracts whitelisted by the team will be allowed to be staked in the contract. Upon staking their ERC-1155 NFT, a user will receive an NFT token representing their stake. Users rewards will be automatically claimed when they unstake from the contract; or users can manually claim them. Users will not be able to stake until the team calls start(); after which staking cannot be stopped. The team has the ability to mint the ERC-1155 tokens at any time. Only contract addresses built to return a specific data value can receive the ERC-1155 which will be minted by the contract. The team can set the reward token address, add rewards, update the weight of staked NFTs, and withdraw ERC20 tokens erroneously sent to the contract. The getCurrentStageInf() and getClaimableRewards() functions have external calls inside a loop, which could consume a large amount of gas if the number of loops is high. Users should not stake a very large number of NFTs from the same address to ensure no issues will be encountered. The start(), getRewards(address) and getCurrentStageInf(address) functions should be declared external insetad of public to save some gas on each call.
Notes on the Exchange Contract:The exchange contract holds logic for matching buy and sell orders using atomic swaps. The team can update the treasury addresses and the seller addresses at any time. The personalSignPrefix variable in the ExchangeCore contract should be constant to save gas on deployment and each reference. The bytes32 hash_ input variable to the validateOrderParameters() function is unused and can be removed. The addTreasuryAdd_(), setSeller_(), atomicMatch_(), and ecrecover_() functions should be declared external instead of public to save some gas on each call.
Audit Findings Summary
- No issues from external attackers were identified.
- We recommend renouncing ownership after a successful deployment.
- Ensure trust in the team as they can mint tokens, pause transfers, and update variables related to NFT staking.
- Date: August 31st, 2021
Details: Token Contract
($) = payable function
# = non-constant function
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Int] IERC20Metadata (IERC20)
- [Ext] name
- [Ext] symbol
- [Ext] decimals
+ Context
- [Int] _msgSender
- [Int] _msgData
+ ERC20 (Context, IERC20, IERC20Metadata)
- [Pub] #
- [Pub] name
- [Pub] symbol
- [Pub] decimals
- [Pub] totalSupply
- [Pub] balanceOf
- [Pub] transfer #
- [Pub] allowance
- [Pub] approve #
- [Pub] transferFrom #
- [Pub] increaseAllowance #
- [Pub] decreaseAllowance #
- [Int] _transfer #
- [Int] _mint #
- [Int] _burn #
- [Int] _approve #
- [Int] _beforeTokenTransfer #
- [Int] _afterTokenTransfer #
+ Pausable (Context)
- [Pub] #
- [Pub] paused
- [Int] _pause #
- modifiers: whenNotPaused
- [Int] _unpause #
- modifiers: whenPaused
+ [Int] IAccessControl
- [Ext] hasRole
- [Ext] getRoleAdmin
- [Ext] grantRole #
- [Ext] revokeRole #
- [Ext] renounceRole #
+ [Lib] Strings
- [Int] toString
- [Int] toHexString
- [Int] toHexString
+ [Int] IERC165
- [Ext] supportsInterface
+ ERC165 (IERC165)
- [Pub] supportsInterface
+ AccessControl (Context, IAccessControl, ERC165)
- [Pub] supportsInterface
- [Pub] hasRole
- [Int] _checkRole
- [Pub] getRoleAdmin
- [Pub] grantRole #
- modifiers: onlyRole
- [Pub] revokeRole #
- modifiers: onlyRole
- [Pub] renounceRole #
- [Int] _setupRole #
- [Int] _setRoleAdmin #
- [Prv] _grantRole #
- [Prv] _revokeRole #
+ BlackLemon (ERC20, Pausable, AccessControl)
- [Pub] #
- modifiers: ERC20
- [Pub] pause #
- modifiers: onlyRole
- [Pub] unpause #
- modifiers: onlyRole
- [Pub] mint #
- modifiers: onlyRole
- [Int] _beforeTokenTransfer #
- modifiers: whenNotPaused
Details: NFT Staking Contract (V2)
($) = payable function
# = non-constant function
+ [Int] IERC165
- [Ext] supportsInterface
+ [Int] IERC1155Receiver (IERC165)
- [Ext] onERC1155Received #
- [Ext] onERC1155BatchReceived #
+ [Int] IERC1155 (IERC165)
- [Ext] balanceOf
- [Ext] balanceOfBatch
- [Ext] setApprovalForAll #
- [Ext] isApprovedForAll
- [Ext] safeTransferFrom #
- [Ext] safeBatchTransferFrom #
+ [Int] IAccessControl
- [Ext] hasRole
- [Ext] getRoleAdmin
- [Ext] grantRole #
- [Ext] revokeRole #
- [Ext] renounceRole #
+ Context
- [Int] _msgSender
- [Int] _msgData
+ [Lib] Strings
- [Int] toString
- [Int] toHexString
- [Int] toHexString
+ ERC165 (IERC165)
- [Pub] supportsInterface
+ AccessControl (Context, IAccessControl, ERC165)
- [Pub] supportsInterface
- [Pub] hasRole
- [Int] _checkRole
- [Pub] getRoleAdmin
- [Pub] grantRole #
- modifiers: onlyRole
- [Pub] revokeRole #
- modifiers: onlyRole
- [Pub] renounceRole #
- [Int] _setupRole #
- [Int] _setRoleAdmin #
- [Prv] _grantRole #
- [Prv] _revokeRole #
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Int] IERC1155MetadataURI (IERC1155)
- [Ext] uri
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Int] verifyCallResult
+ ERC1155 (Context, ERC165, IERC1155, IERC1155MetadataURI)
- [Pub] #
- [Pub] supportsInterface
- [Pub] uri
- [Pub] balanceOf
- [Pub] balanceOfBatch
- [Pub] setApprovalForAll #
- [Pub] isApprovedForAll
- [Pub] safeTransferFrom #
- [Pub] safeBatchTransferFrom #
- [Int] _safeTransferFrom #
- [Int] _safeBatchTransferFrom #
- [Int] _setURI #
- [Int] _mint #
- [Int] _mintBatch #
- [Int] _burn #
- [Int] _burnBatch #
- [Int] _beforeTokenTransfer #
- [Prv] _doSafeTransferAcceptanceCheck #
- [Prv] _doSafeBatchTransferAcceptanceCheck #
- [Prv] _asSingletonArray
+ [Lib] EnumerableSet
- [Prv] _add #
- [Prv] _remove #
- [Prv] _contains
- [Prv] _length
- [Prv] _at
- [Prv] _values
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
- [Int] values
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
- [Int] values
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
- [Int] values
+ Collection (ERC1155, AccessControl)
- [Pub] #
- modifiers: ERC1155
- [Int] addSeedIdsBatch #
- [Int] addSeedId #
- [Ext] addWeight #
- modifiers: onlyRole
- [Ext] mint #
- modifiers: onlyRole
- [Ext] mintBatch #
- modifiers: onlyRole
- [Pub] supportsInterface
+ [Lib] UintSet
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
- [Int] getArray
+ [Int] IMintableToken
- [Ext] mint #
+ NftStakingV2 (AccessControl, IERC1155Receiver)
- [Pub] #
- [Pub] start #
- modifiers: onlyRole,hasNotStarted
- [Ext] setRewardToken #
- modifiers: onlyRole
- [Ext] addReward #
- modifiers: hasNotStarted,onlyRole
- [Ext] addWhitelist #
- modifiers: onlyRole
- [Ext] withdrawERC20 #
- modifiers: onlyRole
- [Int] _getSeedIds #
- [Int] _getWeight #
- [Prv] _stageControl #
- [Prv] _registerStaker #
- [Prv] _calculateTotalRew
- [Int] _stakeNft #
- modifiers: hasStarted
- [Int] _batchStakeNfts #
- modifiers: hasStarted
- [Ext] unStakeNft #
- [Ext] batchUnstakeNfts #
- [Pub] claimRewards #
- [Pub] getRewards
- modifiers: hasStarted
- [Ext] getClaimableRewards
- modifiers: hasStarted
- [Pub] getCurrentStageInf
- [Ext] getUserTokenIds
- [Ext] getMinted
- [Ext] onERC1155Received #
- [Ext] onERC1155BatchReceived #
Details: Exchange Contract
($) = payable function
# = non-constant function
+ 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] IERC1155 (IERC165)
- [Ext] balanceOf
- [Ext] balanceOfBatch
- [Ext] setApprovalForAll #
- [Ext] isApprovedForAll
- [Ext] safeTransferFrom #
- [Ext] safeBatchTransferFrom #
+ [Int] IERC1155Receiver (IERC165)
- [Ext] onERC1155Received #
- [Ext] onERC1155BatchReceived #
+ [Int] IERC1155MetadataURI (IERC1155)
- [Ext] uri
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Int] verifyCallResult
+ ERC165 (IERC165)
- [Pub] supportsInterface
+ ERC1155 (Context, ERC165, IERC1155, IERC1155MetadataURI)
- [Pub] #
- [Pub] supportsInterface
- [Pub] uri
- [Pub] balanceOf
- [Pub] balanceOfBatch
- [Pub] setApprovalForAll #
- [Pub] isApprovedForAll
- [Pub] safeTransferFrom #
- [Pub] safeBatchTransferFrom #
- [Int] _safeTransferFrom #
- [Int] _safeBatchTransferFrom #
- [Int] _setURI #
- [Int] _mint #
- [Int] _mintBatch #
- [Int] _burn #
- [Int] _burnBatch #
- [Int] _beforeTokenTransfer #
- [Prv] _doSafeTransferAcceptanceCheck #
- [Prv] _doSafeBatchTransferAcceptanceCheck #
- [Prv] _asSingletonArray
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ [Lib] SafeMath
- [Int] tryAdd
- [Int] trySub
- [Int] tryMul
- [Int] tryDiv
- [Int] tryMod
- [Int] add
- [Int] sub
- [Int] mul
- [Int] div
- [Int] mod
- [Int] sub
- [Int] div
- [Int] mod
+ ExchangeCore (ReentrancyGuarded, EIP712, Ownable)
- [Int] addTreasuryAdd #
- modifiers: onlyOwner
- [Int] setSeller #
- modifiers: onlyOwner
- [Int] hashOrder
- [Int] hashToSign
- [Int] exists
- [Int] validateOrderParameters
- [Int] validateOrderAuthorization
- [Int] atomicMatch #
- modifiers: reentrancyGuard
+ Exchange (ExchangeCore)
- [Ext] hashOrder_
- [Ext] hashToSign_
- [Pub] addTreasuryAdd_ #
- modifiers: onlyOwner
- [Pub] setSeller_ #
- modifiers: onlyOwner
- [Ext] validateOrderParameters_
- [Ext] validateOrderAuthorization_
- [Pub] atomicMatch_ ($)
- [Pub] ecrecover_