INSK-2 : Collection

Discussion - https://github.com/evm-ink/docs/issues/3

This proposal suggests a more efficient approach to managing collections for inscriptions on EVM-compatible chains. We aim to simplify and streamline the process while capturing all relevant information accurately. This new approach will benefit anyone who needs to work with these types of collections, regardless of their level of technical expertise. To achieve this, we have carefully considered various use cases and provided plenty of examples to make the concepts easy to understand.

Audience

The target audience for this proposal is anyone who wants to learn more about the topic. We have kept the language as non-technical as possible so everyone can understand it. We have also included many examples and use cases to help illustrate the concepts.

Background

If you ever wanted to create a collection with inscription, then you have most probably seen two types:

You inscribe everything yourself one by one. Now, there is nothing that tells us that inscriptions do belong to some collection. It is not different from randomly inscribed images. The inscription proposed a JSON format that can be inscribed, and it should signify the creation of the collection.

You convince other people to inscribe images themself. You give them an image and tell them how to inscribe.

Problems

While I am pleased to see some improvements, some issues still need to be addressed.

How do we know that an item belongs to a collection? Nothing stops me from including any items in JSON. Imagine that you are halfway inscribing your items, and someone just created a collection and included your items. How can you provide it? This is the most essential part of having a collection in the first place: the idea that it belongs to something valuable. Do you want your inscription to be stolen that easily?

It is expensive. One inscription can cost, on average, ~0.5(link) to 25(link) $ depending on the gas price. So, a 10k items collection will cost at least 5000 and at most 250,000$. Sounds like a hefty price for a collector. We can delegate the inscription to users and let them inscribe. We can, but it would make the previous problem even harder. At least if we know that he made all the items we inscribed by one creator and then collection, we can work with it. Now we have 10k images inscribed by different creators, and someone else should make a collection JSON. Imagine buying an item thinking it belongs to some collection, while it is not.

It is very hard to add extra functionality. How can you let users mint inscriptions for some price? How about bulk minting?

It is hard to do for non-technical people. Imagine that you have 10k images. You must write a script to deploy inscriptions, save transaction hash, and generate JSON. How are average creators supposed to do this?

Proposed Solution

We want to solve the issues above, improve collections, and add more functionality for the creators.

We propose to use contracts to identify the origin of the inscription. If the inscription was created by contract, we consider it to belong to it.

What can you do?

  • We know that an inscription belongs to a collection if and only if it was created by it.-

  • The lazy minting is now possible. We can let users claim inscriptions themself, and our contract will simply be sent.

  • Bulk minting is also possible. We have no problems creating multiple inscriptions in one transaction and sending all of them to a user. The creator will still be the contract.

  • You can now have priced minting. You can let people pay if they want to inscribe your item.

  • You can have whitelisting and allow only specific addresses to mint.

  • You can limit mint by time and allow to mint only at specific times.

Examples

The code examples provided here are for educational purposes only and should not be used directly in production environments.

Whitelisted collection claim

contract Whitelisted {
    mapping(address => bool) private whitelisted;

    constructor() {
        whitelisted[0x0000000000000000000000000000000000000000] = true;
        whitelisted[0x0000000000000000000000000000000000000001] = true;
        whitelisted[0x0000000000000000000000000000000000000002] = true;
    }

    function claim() public {
        require(whitelisted[msg.sender], "You aren't whitelisted");

        bytes memory inscription = bytes("data:text/plain,hello");
        (bool sent, ) = msg.sender.call{value: 0}(inscription);
        require(sent, "Failed to send");
    }
}

Bulk BRC-20 minting

contract BulkBRC20Mint {
    function claim(uint count) public {
        for (uint i = 0; i < count; i++) {
            bytes memory inscription = bytes(
                'data:,{"p":"brc-20","op":"mint","tick":"x","amt":"10"}'
            );
            (bool sent, ) = msg.sender.call(inscription);
            require(sent, "Failed to send");
        }
    }
}
contract PricedMint {
    function claim() public payable {
        require(msg.value >= 0.01 ether, "Not enough");

        bytes memory inscription = bytes(
            'data:,{"p":"brc-20","op":"mint","tick":"x","amt":"10"}'
        );
        (bool sent, ) = msg.sender.call(inscription);
        require(sent, "Failed to send");
    }
}

Signed and priced collection claim

contract SignedPriced {
    uint256 public price = 0.01 ether;
    address payable private _signer =
        payable(0xAaAaAAaAAAaabbBbBBBBBbbBBbCcCCCCCcCCcccc);

    error InvalidAmout();
    error InvalidSignature();

    function claim(bytes memory data, bytes calldata signature) public payable {
        if (msg.value < price) {
            revert InvalidAmout();
        }

        bytes32 hash = keccak256(data);
        bytes32 message = ECDSA.toEthSignedMessageHash(hash);
        address recovered = ECDSA.recover(message, signature);
        if (recovered != _signer) {
            revert InvalidSignature();
        }

        (bool sent, ) = msg.sender.call{value: 0}(data);
        require(sent, "Failed to send Ether");
    }
}

Conclusion:

We aspire to enable creators by unlocking the potential of current contracts. We strongly believe in avoiding any limitations that could impede their artistic expression. Just because something couldn't be accomplished using ordinals on Bitcoin doesn't mean we should hold back on EVM. Instead, we can embrace the strengths of ordinals and take them to new heights.

Last updated