Platform: Code4rena
Start Date: 17/07/2023
Pot Size: $85,500 USDC
Total HM: 11
Participants: 26
Period: 14 days
Judge: Picodes
Total Solo HM: 1
Id: 263
League: ETH
Rank: 11/26
Findings: 1
Award: $31.38
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: MiloTruck
Also found by: 0xAnah, AlexCzm, Bughunter101, BugzyVonBuggernaut, DavidGiladi, Emmanuel, Iurii3, Kaysoft, MohammedRizwan, Prestige, Rolezn, Sathish9098, Stormreckson, adeolu, descharre, evmboi32, fatherOfBlocks, ginlee, ihtishamsudo, juancito, mrudenko, tnquanghuy0512
31.3772 USDC - $31.38
blacklist
functionAs stated in the project:
NFT thefts have increased recently, so with the addition of hacked NFTs to the platform, NFTs can be converted into liquidity. To prevent this, I recommend adding the blacklist function.
Marketplaces such as Opensea have a blacklist feature that will not list NFTs that have been reported theft, NFT projects such as Manifold have blacklist functions in their smart contracts.
Here is the project example; Manifold
Manifold Contract https://etherscan.io/address/0xe4e4003afe3765aca8149a82fc064c0b125b9e5a#code
modifier nonBlacklistRequired(address extension) { require(!_blacklistedExtensions.contains(extension), "Extension blacklisted"); _; }
Recommended Mitigation Steps Add to Blacklist function and modifier.
tokenURI
function should return empty string instead of revert when followTokenId
not existcreateProfile()
The function createProfile also has a potential lack of access control. The function only validates that the sender of the transaction is whitelisted, but it does not check if the sender has the permission to create a profile. This means that any whitelisted address could create a profile, even if they do not have the permission to do so.
createProfile()
function names used in different contracts LensHub.sol
, ProfileLib.sol
This can lead to confusion and errors. It is better to give each function a unique name that reflects its purpose
initialize()
function and set their own values this will create unintended consequences
Once contract The function initialize() has a potential lack of access control. The function only checks if the contract has already been initialized, but it does not check if the sender of the transaction is the LensHub. This means that any account could call the function and set the followed profile ID and royalty, which could have unintended consequences
_followedProfileId
,_setRoyalty(1000)
values. Once _initialize value set to true then initialize() function always revertsonlyHub
modifierremoveFollower(), approveFollower()
functionThis means that any account could call the function and unfollow any profile, even if they do not own the profile or have been approved by the owner of the profile. This could have unintended consequences, such as preventing users from receiving royalties from their followers
The function only checks if the sender of the transaction is the owner of the follow token or if the sender has been approved by the owner of the follow token. However, it does not check if the sender is the owner of the profile that is being unfollowed.
supportsInterface()
function in the ERC2981CollectionRoyalties contract. This means that the function will only return true if the interface ID is supported by the LensBaseERC721
contractinterface ID
is a valid interface IDincrement operators
. Some places ++X
used and some places X++
usedfollowerProfileId
validity not checked in _followMintingNewToken()
when minting new token . followerProfileId
can be zero valueunchecked
block may cause problem in future when _followerCount
increased . For safety remove unchecked keywordcurrentFollowerProfileId != 0
> 0
check should be used instead of !=The check currentFollowerProfileId > 0 may be more efficient than the check currentFollowerProfileId != 0. This is because the check currentFollowerProfileId > 0 can be evaluated more quickly than the check currentFollowerProfileId != 0.
tokenId
generation when minting new NFT instead of user defined inputs . Use state variable to increment the tokenId
valuesuint256
when assigning critical values to immutable variables in constructor
If any human errors we need to redeploy the over all contract. Add necessary sanity checks
onlyEOA
modifier check even though it is not an EOA
Create a contract that inherits from another contract that is an EOA. For example, the following contract inherits from the Ownable contract, which is an EOA.
contract MyContract is Ownable { // ... }
Because the MyContract contract inherits from the Ownable contract, it will also be an EOA. This means that the onlyEOA modifier will not prevent calls to the MyContract contract
approve()
, setApprovalForAll()
functions should use whenNotPaused
modifierThe approve and setApprovalForAll functions do need to use the whenNotPaused modifier. This is because these functions allow users to grant other users permission to spend their tokens, and it is important to ensure that these functions cannot be called when the contract is paused.
The whenNotPaused modifier is a Solidity modifier that prevents functions from being called when the contract is paused. This means that if the contract is paused, then the approve and setApprovalForAll functions will not be able to be called, even if the user has the correct permissions.
executeLensV2Upgrade()
function_upgrade
function does not perform any pre-upgrade checks
and post-upgrade checks
, which means that there is no way to ensure that the contract is in a good state before it is upgraded. This could lead to problems if the contract is upgraded while it is in a bad state_validateLocalName
and _validateLocalNameMigration
functions prohibit handle names starting with underscores. Such restrictions as they might lead to unexpected limitations for users in certain casesHandlesErrors.sol
. While it's not shown in the provided code, ensure that the error messages provide sufficient information for debugging and don't leak sensitive dataIt is recommended that Solidity contracts are fully annotated using NatSpec for all public interfaces (everything in the ABI). It is clearly stated in the Solidity official documentation. In complex projects such as Defi, the interpretation of all functions and their arguments and returns is important for code readability and auditability. https://docs.soliditylang.org/en/v0.8.15/natspec-format.html
Recommendation NatSpec comments should be increased in Contracts
Recommendation Code:
/** * @notice Sets approval for specific withdrawer addresses * @dev This function updates the amount of the withdrawApproval mapping value based on the given 3 argument values * @param withdrawer_ Withdrawer address from state variable * @param token_ instance of ERC20 * @param amount_ User amount * @param
#0 - c4-pre-sort
2023-08-04T15:00:16Z
141345 marked the issue as high quality report
#1 - c4-judge
2023-08-28T20:39:02Z
Picodes marked the issue as grade-a
#2 - vicnaum
2023-08-31T10:13:59Z
@Picodes please revisit this. I've seen much better grade-b reports. Most of the findings in this report don't make any sense at all and look ChatGPT generated.
#3 - c4-judge
2023-08-31T16:24:25Z
Picodes marked the issue as grade-b