Create extension for utility struct

Hi folks,

I’m currently developing my own smart contracts, and I saw the smart contract utility from openzeppelin there is an utility for EnumerableSet, but there is lack of type. I’m trying to recreate it for EnumerableSet for type String as follows

library EnumerableSetString {
   // Inspired from the original EnumerableSet
  struct Set {
    // Storage of set values
    string[] _values;

    mapping (string => uint256) _indexes;
  }

  // the rest function is very similar, just changed the parameter type accordingly
  function _add(Set storage set, string memory value) private returns (bool) {
    if (!_contains(set, value)) {
      set._values.push(value);
      // The value is stored at length-1, but we add 1 to all indexes
      // and use 0 as a sentinel value
      set._indexes[value] = set._values.length;
      return true;
    } else {
      return false;
    }
  }

  struct StringSet {
    Set _inner;
  }

  // Public method
  function add(StringSet storage set, string calldata value) internal returns (bool) {
    return _add(set._inner, value);
  }

  //The rest has functions like _remove, _contains, _length, _at
}

What do you folks think? Why this is not included by default on OpenZeppelin libs? Any suggestions, feedback, very much appreciated.

We’ve included types for which we are aware of good use cases. Please share what you plan to do with this enumerable set!

You don’t need to separate between Set and StringSet. It’s built that way in OpenZeppelin Contracts because we needed to write it in a generic way for multiple types.

I want to create a ERC 721 NFT Smart Contract for my next project. It’s something like continuity of my NFT that created on opensea using their shared smart contract.

What I want to do is people that already hold token from my previous project on opensea could mint their own token on my next project on my site. But I need a way to verify it securely, and I’m thinking do it on the contract itself. So this enumerable string set will holds the “valid” token, then it will be removed one by one once the user mint it.

I haven’t really test this code, but I think something like

function mint(address to, string calldata validToken) public returns (uint256) {
    // Check valid token, This is the enumerable instance that holds all the valid token
    require(validTokens.contains(validToken));

    // Remove the token
    validTokens.remove(validToken);

    // ERC-721 normal flow to create new token.
    _tokenIds.increment();
    uint256 nextToken = _tokenIds.current();
    _mint(to, nextToken);
    return nextToken;
  }

what do you think @frangio ? I’m very open for any feedback for this approach.

Using strings sounds a little weird. I encourage you to check out our workshop on NFT airdrops, I think it’s very much aligned with what you want to do! Recap and video are on our blog.

hi @frangio, thanks for your links. I think I could use that approach, even my use cases a little different. In my case, user need to be able to prove that they poses a pair of tokens from my previous project, I think I’ll do the verification process off chain to safe some gas, but I’ll do the merkletree verification on the contract to make sure everyone pair of token will will be converted (or minted) to be a single token.

1 Like