0

Guys i have 2 simple contracts but i'm not able to compile them, every time when i try i'm hitting this error Error in plugin hardhat-contract-sizer: Warning: 1 contracts exceed the size limit for mainnet deployment.

  1. CollectionManager - used to instantiate multiple different Collections - 25.146kb

  2. Collection - used to create NFT-s and payment splitter here is the source for both - 16.953kb

  3. Collection Manager

//SPDX-License-Identifier: Unlicense

pragma solidity ^0.8.0;

import "../collection/Collection.sol";
import "./ICollectionManager.sol";

contract CollectionManager is ICollectionManager {
    address[] private collections;

    // Mapping from artist to collection addresses
    mapping(address => address[]) private collectionsOf;

    function createCollection(
        string memory _uri,
        string memory _name,
        string memory _symbol,
        uint256 _startingAt,
        address[] memory _payees,
        uint256[] memory _shares
    ) public {
        Collection collection = new Collection(
            _uri,
            _name,
            _symbol,
            _startingAt,
            _payees,
            _shares
        );

        collections.push(address(collection));
        collectionsOf[msg.sender].push(address(collection));

        emit CollectionCreated(msg.sender, address(collection));
    }

    function create(
        address payable _collectionAddress,
        string calldata _cid,
        uint256 _maxSupply
    ) external {
        Collection(_collectionAddress).create(_cid, _maxSupply);
    }

    function mint(
        address payable _collectionAddress,
        address _account,
        uint256 _id
    ) external {
        Collection(_collectionAddress).mint(_account, _id);
    }

    function getCollections() external view returns (address[] memory) {
        return collections;
    }

    function getCollectionForArtist(address _artist)
        external
        view
        returns (address[] memory)
    {
        return collectionsOf[_artist];
    }
}

  1. Collection
//SPDX-License-Identifier: Unlicense

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/finance/PaymentSplitter.sol";

import "./ICollection.sol";

contract Collection is ICollection, ERC1155, Ownable, PaymentSplitter {
    using Counters for Counters.Counter;
    Counters.Counter private ID;

    string public name;
    string public symbol;

    uint256 private startingAt;

    // Mapping from token ID to token URI
    mapping(uint256 => string) private idToUri;

    // Mapping from token ID to max supply
    mapping(uint256 => uint256) private maxSupply;

    // Mapping from token ID to total supply
    mapping(uint256 => uint256) private totalSupply;

    constructor(
        string memory _uri,
        string memory _name,
        string memory _symbol,
        uint256 _startingAt,
        address[] memory _payees,
        uint256[] memory _shares
    ) payable ERC1155(_uri) PaymentSplitter(_payees, _shares) {
        require(_startingAt > block.timestamp, "Invalid timestamp"); // + 5 * 86400 - 5 DAYS maybe/for example
        name = _name;
        symbol = _symbol;
        startingAt = _startingAt;
    }

    function create(string calldata _cid, uint256 _maxSupply)
        external
        payable
        override
        onlyOwner
        returns (uint256 _id)
    {
        require(startingAt > block.timestamp, "Already started");
        require(_maxSupply > 0, "Supply > 0");

        _id = _nextId();

        maxSupply[_id] = _maxSupply;
        totalSupply[_id] = 0;

        string memory _uri = _createUri(_cid);
        idToUri[_id] = _uri;

        _mint(msg.sender, _id, 0, "");

        emit Created(_uri, _id, msg.sender);
    }

    function mint(address _account, uint256 _id) external onlyOwner {
        require(startingAt < block.timestamp, "Not started");
        require(_exists(_id), "Invalid id");
        require(totalSupply[_id] < maxSupply[_id], "Limit Reached");

        totalSupply[_id] = totalSupply[_id] + 1;

        _mint(_account, _id, 1, "");
    }

    function uri(uint256 _id) public view override returns (string memory) {
        return idToUri[_id];
    }

    function _nextId() private returns (uint256 id) {
        ID.increment();
        return ID.current();
    }

    function _exists(uint256 _id) private view returns (bool) {
        return (bytes(idToUri[_id]).length > 0);
    }

    function _createUri(string memory _cid)
        private
        view
        returns (string memory _uri)
    {
        string memory baseUri = super.uri(0);
        return string(abi.encodePacked(baseUri, _cid));
    }
}

I have enabled:

settings: {
    optimizer: {
      enabled: true,
      runs: 1,
    },
  },

but seems like not working properly or i'm receiving this error cuz my ManagerCollection contract is 25.146kb

2
  • Optimizer is usually 200, but probably will not fix the problem, u need to make your contract smaller
    – Majd TL
    Oct 30, 2021 at 17:42
  • Like which one of the both, collection have some very basic functionality and the collection manager it's very plain as well Oct 30, 2021 at 18:30

1 Answer 1

1

Your CollectionManager is pretty big because to be able to deploy an instance of Collection, it must contain a copy of Collection's bytecode.

You could work around that by creating a separate contract/library that's responsible for deploying instances of Collection on demand. This would make CollectionManager's bytecode smaller at the cost of having to make an extra external call (but this is not a significant overhead compared to the cost of creating a new contract instance anyway).

The second biggest factor that affects the size in your case is probably the inheritance. Collection inherits from a few contracts and they in turn inherit from other contracts. That adds up quickly. It's definitely much better to inherit from a well-tested base than to do a custom implementation of these features in your contract but you must be aware that this does come at a cost. Maybe you could split some functionality into an external library?

Setting --optimize-runs to 0 might help a bit with contract size but at the cost of potentially making your contract a bit more expensive to execute so that's a trade-off. By setting it to a low value you basically say that you care about size more than about the cost of execution and the optimizer will choose smaller code over more efficient one whenever possible. Also, the difference will probably not be very dramatic.

If you want some ideas for what else you could optimize, take a look at my earlier answer for a similar question: "EIP170 - Which contract features explain its size the most?".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.