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

Andon Mitev
  • 345
  • 2
  • 12
  • Optimizer is usually 200, but probably will not fix the problem, u need to make your contract smaller – Majd TL Oct 30 '21 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 – Andon Mitev Oct 30 '21 at 18:30

1 Answers1

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?".

cameel
  • 2,211
  • 5
  • 21