Skip to content

Latest commit

 

History

History
714 lines (430 loc) · 19.5 KB

report.md

File metadata and controls

714 lines (430 loc) · 19.5 KB

Aderyn Analysis Report

This report was generated by Aderyn, a static analysis tool built by Cyfrin, a blockchain security company. This report is not a substitute for manual audit or security review. It should not be relied upon for any purpose other than to assist in the identification of potential security vulnerabilities.

Table of Contents

Summary

Files Summary

Key Value
.sol Files 6
Total nSLOC 768

Files Details

Filepath nSLOC
src/ARTBlockVoting.sol 77
src/ArtBlockAMM.sol 81
src/ArtBlockGovernance.sol 148
src/ArtBlockNFT.sol 47
src/CustomERC20Token.sol 26
src/MainEngine.sol 389
Total 768

Issue Summary

Category No. of Issues
High 5
Low 10

High Issues

H-1: Arbitrary from passed to transferFrom (or safeTransferFrom)

Passing an arbitrary from address to transferFrom (or safeTransferFrom) can lead to loss of funds, because anyone can transfer tokens from the from address if an approval is made.

2 Found Instances
  • Found in src/MainEngine.sol Line: 256

             artBlockToken.transferFrom(communityCreator, address(this), COMMUNITY_CREATION_FEE * PRECESSION);
  • Found in src/MainEngine.sol Line: 320

             artBlockToken.transferFrom(to, address(this), cost * PRECESSION);

H-2: Unprotected initializer

Consider protecting the initializer functions with modifiers.

2 Found Instances
  • Found in src/ArtBlockGovernance.sol Line: 202

         function initializeRateChangeProposal(
  • Found in src/ArtBlockGovernance.sol Line: 260

         function isReadyToInitiateRateChange(uint256 proposalIndex) external view returns (bool) {

H-3: Contract Name Reused in Different Files

When compiling contracts with certain development frameworks (for example: Truffle), having contracts with the same name across different files can lead to one being overwritten.

2 Found Instances
  • Found in src/ARTBlockVoting.sol Line: 29

     interface IMainEngine {
  • Found in src/ArtBlockGovernance.sol Line: 6

     interface IMainEngine {

H-4: Uninitialized State Variables

Solidity does initialize variables by default when you declare them, however it's good practice to explicitly declare an initial value. For example, if you transfer money to an address we must make sure that the address has been initialized.

1 Found Instances
  • Found in src/ArtBlockNFT.sol Line: 11

         uint256 private _nextTokenId;

H-5: Weak Randomness

The use of keccak256 hash functions on predictable values like block.timestamp, block.number, or similar data, including modulo operations on these values, should be avoided for generating randomness, as they are easily predictable and manipulable. The PREVRANDAO opcode also should not be used as a source of randomness. Instead, utilize Chainlink VRF for cryptographically secure and provably random values to ensure protocol integrity.

1 Found Instances
  • Found in src/MainEngine.sol Line: 340

             bytes4 productId = bytes4(keccak256(abi.encodePacked(msg.sender, block.timestamp, metadata, price, commToken)));

Low Issues

L-1: Centralization Risk for trusted owners

Contracts have owners with privileged rights to perform admin tasks and need to be trusted to not perform malicious updates or drain funds.

4 Found Instances
  • Found in src/ArtBlockNFT.sol Line: 10

     contract ArtBlockNFT is ERC721, ERC721Enumerable, ERC721URIStorage, Ownable {
  • Found in src/ArtBlockNFT.sol Line: 17

         function safeMint(address to, string memory uri, bytes4 productId) external onlyOwner {
  • Found in src/ArtBlockNFT.sol Line: 24

         function safeTransfer(address from, address to, uint256 tokenId) external onlyOwner {
  • Found in src/CustomERC20Token.sol Line: 13

     contract CustomERC20Token is ERC20, ERC20Burnable, Ownable {

L-2: Unsafe ERC20 Operations should not be used

ERC20 functions may not behave as expected. For example: return values are not always meaningful. It is recommended to use OpenZeppelin's SafeERC20 library.

15 Found Instances
  • Found in src/ArtBlockAMM.sol Line: 47

             tokenIn.transferFrom(msg.sender, address(this), _amountIn);
  • Found in src/ArtBlockAMM.sol Line: 53

             tokenOut.transfer(msg.sender, amountOut);
  • Found in src/ArtBlockAMM.sol Line: 59

             token0.transferFrom(msg.sender, address(this), _amount0);
  • Found in src/ArtBlockAMM.sol Line: 60

             token1.transferFrom(msg.sender, address(this), _amount1);
  • Found in src/ArtBlockAMM.sol Line: 88

             token0.transfer(msg.sender, amount0);
  • Found in src/ArtBlockAMM.sol Line: 89

             token1.transfer(msg.sender, amount1);
  • Found in src/MainEngine.sol Line: 256

             artBlockToken.transferFrom(communityCreator, address(this), COMMUNITY_CREATION_FEE * PRECESSION);
  • Found in src/MainEngine.sol Line: 320

             artBlockToken.transferFrom(to, address(this), cost * PRECESSION);
  • Found in src/MainEngine.sol Line: 352

             CustomERC20Token(commToken).transferFrom(msg.sender, address(this), stakedAmount);
  • Found in src/MainEngine.sol Line: 409

             CustomERC20Token(productInfo[productId].currentCommunity).transfer(
  • Found in src/MainEngine.sol Line: 420

             CustomERC20Token(productInfo[productId].currentCommunity).transfer(
  • Found in src/MainEngine.sol Line: 478

                     CustomERC20Token(communityToken).transferFrom(msg.sender, product.author, (product.price * 3) / 100);
  • Found in src/MainEngine.sol Line: 479

                     CustomERC20Token(communityToken).transferFrom(
  • Found in src/MainEngine.sol Line: 483

                     CustomERC20Token(communityToken).transferFrom(msg.sender, product.currentOwner, product.price);
  • Found in src/MainEngine.sol Line: 523

             CustomERC20Token(community).transfer(communityInfo[community].communityCreator, (price * 3) / 100);

L-3: Solidity pragma should be specific, not wide

Consider using a specific version of Solidity in your contracts instead of a wide version. For example, instead of pragma solidity ^0.8.0;, use pragma solidity 0.8.0;

6 Found Instances
  • Found in src/ARTBlockVoting.sol Line: 24

     pragma solidity ^0.8.20;
  • Found in src/ArtBlockAMM.sol Line: 2

     pragma solidity ^0.8.24;
  • Found in src/ArtBlockGovernance.sol Line: 2

     pragma solidity ^0.8.20;
  • Found in src/ArtBlockNFT.sol Line: 3

     pragma solidity ^0.8.20;
  • Found in src/CustomERC20Token.sol Line: 2

     pragma solidity ^0.8.20;
  • Found in src/MainEngine.sol Line: 24

     pragma solidity ^0.8.23;

L-4: Missing checks for address(0) when assigning values to address state variables

Check for address(0) when assigning values to address state variables.

3 Found Instances
  • Found in src/MainEngine.sol Line: 587

             votingContractAddr = votingContract;
  • Found in src/MainEngine.sol Line: 595

             govContract = governanceContract;
  • Found in src/MainEngine.sol Line: 603

             artBlockNFTContract = nftContract;

L-5: public functions not used internally could be marked external

Instead of marking a function as public, consider marking it as external if it is not used internally.

16 Found Instances
  • Found in src/ArtBlockNFT.sol Line: 50

         function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) {
  • Found in src/ArtBlockNFT.sol Line: 54

         function supportsInterface(bytes4 interfaceId)
  • Found in src/CustomERC20Token.sol Line: 68

         function mint(address to, uint256 amount) public onlyMainEngine {
  • Found in src/CustomERC20Token.sol Line: 79

         function burnFrom(address account, uint256 amount) public override onlyMainEngine {
  • Found in src/CustomERC20Token.sol Line: 88

         function decimals() public view virtual override returns (uint8) {
  • Found in src/MainEngine.sol Line: 290

         function buyArtBlockToken(address to, uint256 amount) public payable {
  • Found in src/MainEngine.sol Line: 314

         function buyCommunityToken(address to, uint256 amount, address communityToken) public {
  • Found in src/MainEngine.sol Line: 430

         function canCalculateVotingResult(bytes4 productId) public view returns (bool) {
  • Found in src/MainEngine.sol Line: 441

         function listProductToMarketPlace(
  • Found in src/MainEngine.sol Line: 466

         function buyProduct(
  • Found in src/MainEngine.sol Line: 614

         function getTokenAddress() public view returns (address) {
  • Found in src/MainEngine.sol Line: 622

         function getCreatorProtocol() public view returns (address) {
  • Found in src/MainEngine.sol Line: 632

         function isCommunityMembr(address user, address communityToken) public view returns (bool) {
  • Found in src/MainEngine.sol Line: 646

         function getTotalMemberOfCommunity(address communityToken) public view returns (uint256) {
  • Found in src/MainEngine.sol Line: 654

         function getCommunityActivityPoints(address communityToken) public view returns (uint256) {
  • Found in src/MainEngine.sol Line: 658

         function getCommunityCreationFee() public pure returns (uint256) {

L-6: Define and use constant variables instead of using literals

If the same constant literal value is used multiple times, create a constant state variable and reference it throughout the contract.

20 Found Instances
  • Found in src/ARTBlockVoting.sol Line: 150

             uint256 communityTokenWeight = (userCommunitytoken * 6) / 10; // 60% weightage of the
  • Found in src/ARTBlockVoting.sol Line: 152

             uint256 artblockTokenWeight = (userArtBlockToken * 4) / 10; // 40% weightage of the artblock
  • Found in src/ArtBlockGovernance.sol Line: 228

             uint256 communityTokenWeight = (userCommunitytoken * 6) / 10; // 60% weightage of the community token
  • Found in src/ArtBlockGovernance.sol Line: 229

             uint256 artblockTokenWeight = (userArtBlockToken * 4) / 10; // 40% weightage of the artblock token
  • Found in src/MainEngine.sol Line: 419

             uint256 halfStakeValue = (productBaseInfo[productId].stakeAmount * 50) / 100;
  • Found in src/MainEngine.sol Line: 478

                     CustomERC20Token(communityToken).transferFrom(msg.sender, product.author, (product.price * 3) / 100);
  • Found in src/MainEngine.sol Line: 480

                         msg.sender, product.currentOwner, (product.price * 97) / 100
  • Found in src/MainEngine.sol Line: 517

             if (getUserActivityPoints(msg.sender, community) < 10) {
  • Found in src/MainEngine.sol Line: 523

             CustomERC20Token(community).transfer(communityInfo[community].communityCreator, (price * 3) / 100);
  • Found in src/MainEngine.sol Line: 543

                 return (price * 3 * PRECESSION) / 10; // If the product is exclusive then the stake amount is 30% of the
  • Found in src/MainEngine.sol Line: 546

                 return (price * 15 * PRECESSION) / 100; // If the product is not exclusive then the stake amount is 15% of
  • Found in src/MainEngine.sol Line: 568

             uint256 rateIncrease = (communityPoints * 1000) / 1000; // Example: rate increases by 1% for every 1000 points
  • Found in src/MainEngine.sol Line: 569

             uint256 userDiscount = (userPoints * 100) / 100; // Example: 1% discount for every 100 points
  • Found in src/MainEngine.sol Line: 570

             uint256 adjustment = 1 ether + (rateIncrease * 1 ether / 100) - (userDiscount * 1 ether / 100);

L-7: PUSH0 is not supported by all chains

Solc compiler version 0.8.20 switches the default target EVM version to Shanghai, which means that the generated bytecode will include PUSH0 opcodes. Be sure to select the appropriate EVM version in case you intend to deploy on a chain other than mainnet like L2 chains that may not support PUSH0, otherwise deployment of your contracts will fail.

6 Found Instances
  • Found in src/ARTBlockVoting.sol Line: 24

     pragma solidity ^0.8.20;
  • Found in src/ArtBlockAMM.sol Line: 2

     pragma solidity ^0.8.24;
  • Found in src/ArtBlockGovernance.sol Line: 2

     pragma solidity ^0.8.20;
  • Found in src/ArtBlockNFT.sol Line: 3

     pragma solidity ^0.8.20;
  • Found in src/CustomERC20Token.sol Line: 2

     pragma solidity ^0.8.20;
  • Found in src/MainEngine.sol Line: 24

     pragma solidity ^0.8.23;

L-8: Modifiers invoked only once can be shoe-horned into the function

5 Found Instances
  • Found in src/ARTBlockVoting.sol Line: 77

         modifier onlyMainEngine() {
  • Found in src/ArtBlockGovernance.sol Line: 71

         modifier onlyMainEngine() {
  • Found in src/ArtBlockGovernance.sol Line: 78

         modifier onlyCommunityMember(address communityToken) {
  • Found in src/MainEngine.sol Line: 197

         modifier hasEnoughBalanceToBuy(bytes4 productId, address communityToken) {
  • Found in src/MainEngine.sol Line: 204

         modifier canPostProductToSell(bytes4 productId) {

L-9: Internal functions called only once can be inlined

Instead of separating the logic into a separate function, consider inlining the logic into the calling function. This can reduce the number of function calls and improve readability.

3 Found Instances
  • Found in src/ArtBlockGovernance.sol Line: 202

         function initializeRateChangeProposal(
  • Found in src/MainEngine.sol Line: 541

         function getStackAmountFromPrice(uint256 price, bool isExclusive) internal view returns (uint256) {
  • Found in src/MainEngine.sol Line: 567

         function calculateRateAdjustment(uint256 communityPoints, uint256 userPoints) internal pure returns (uint256) {

L-10: Unused Custom Error

it is recommended that the definition be removed when custom error is unused

1 Found Instances
  • Found in src/MainEngine.sol Line: 58

         error MainEngine__ProductAlreadyExists();