I have seen a Solidity smart contract made by Polkamon, which is used to store NFT hashes, so that users can create an NFT without minting it, so that they can save Gas fees if they don't like their new NFT.

I am confused about the significance of one particular line of code, it is a require function that makes sure that a hash is found in the list of hashes that have been generated by users of the NFT platform.

require(registeredHashes[to][keccak256(abi.encode(to, ids))], "Hash not registered" );

What exactly is going on here?

Here is the rest of the smart contract:

contract SoftMinter is Ownable {
    // Mapping from address to bool, if egg was already claimed
    // The hash is about the userId and the nftIds array
    mapping(address => mapping(bytes32 => bool)) public registeredHashes;
    mapping(uint256 => bool) public alreadyMinted;

    CanMint private _nftContract;

    constructor(CanMint nftContract) public {
        _nftContract = nftContract;

    function mint(
        address to,
        uint256[] memory ids,
        uint256 indexToMint
    ) public {
            registeredHashes[to][keccak256(abi.encode(to, ids))],
            "Hash not registered"
        require(!alreadyMinted[ids[indexToMint]], "Already minted");
        if (registeredHashes[to][keccak256(abi.encode(to, ids))]) {
            alreadyMinted[ids[indexToMint]] = true;
            _nftContract.mint(to, ids[indexToMint]);

    //adding hash
    function addHash(address to, bytes32 dataHash) public onlyOwner {
        require(!registeredHashes[to][dataHash], "Hash already registered");
        registeredHashes[to][dataHash] = true;

2 Answers 2


It checks if the address to already registered a digest made of the hash of the address to and an array of uint256 called ids.

If it has not already registered that digest, the transaction will revert (it will be cancelled). That's what require do. In that case, the error message will be "Hash not registered".

  • Thank you, that part I understand, but why is it using a keccak256(abi.encode(to, ids) Commented Apr 12, 2021 at 7:17

Ethereum has the hash function keccak256 built in, which is a version of SHA3. A hash function basically maps an input into a random 256-bit hexadecimal number.

In Solidity, it is best practice to encode input data before passing it to a hash function like keccak256.

The keyword abi.encodePacked is used for encoding data input.

so basically keccak256(abi.encode(to, ids) will first encode your input and then finally return a hash of the encoded input.

Check: https://medium.com/0xcode/hashing-functions-in-solidity-using-keccak256-70779ea55bb0 for more information on this.

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.