Challenge:
Need a way to efficiently verify membership of a Loot Bag in some set X. For example, is Loot Bag 105 a member of the Library guild? In this case, it’s getWeapon
function returns Book
. We can verify that by calling the Solidity function and passing item ID 105, but we have to somehow understand that the Book
string implies membership in the Library guild.
The fact that Books mean membership in the Library guild is an additional piece of metadata that can be used in games, governance and other on-chain mechanism designs. Another example is group raids, where a developer might want to understand what is actually inside the bags in order to improve the game experience.
I’m assuming that comparing a lot of strings in Solidity is a pain for developers. If a developer were to check this on-chain, they would have to compare against all known permutations of Book, such as Book of the Twins and a hundred other variations. Furthermore, they would have to do this for each item name => guild association. Another example is mythical Loot items, which vary in name diversity to an extreme degree, where each name might be different in each Bag. Is there a solution which can scale to handle these degrees of diversity, while still being efficient for on-chain verification, and not being a huge pain for developers?
Solution: Merkle Root verification
I propose using a Merkle tree structure where the leaf nodes consist of the items in the set. The root of the tree, the Merkle root, can then be used to cryptographically verify membership in the set. This verification can happen on-chain, efficiently and securely.
For example, we can take the names of all 4364 mythical items, and produce the Merkle root once, off-chain. Anyone could reproduce this Merkle root for themselves to verify its correctness. The Merkle root is then submitted to a smart contract GuildMetadata.sol
, which allows any developer in the Loot ecosystem to call a function such as isItemMemberOfGuild(itemName, guildName)
.
The item name and the guild name can be passed as arguments to the function, and the function would check for the membership of hash(itemName)
within the merkle root for guildName
.
Generalizability
Using this technique, there can be a single contract that is used as a Guild metadata contract. Multiple items can be verified, within multiple guilds, so it’s scalable up to a large design space of item => guild combinations. For example:
- Any Divine items = Divine Lodge guild
- All Divine Robes = Divine Roles guild
- All Katanas = Katana guild
- All Mythical items = Mythical guild
- Any dragon item = Dragon guild
- …
It also doesn’t matter how many Bags there are, 8000 or 2 million. They all could use the same technique to create the associations from a group of names to some metadata.
Expanding the names
Using this technique, if a derivative or future project wanted to add names to the set, the Merkle root could just be recomputed and submitted without modifying the contracts that rely on these associations.
Other Association Types
In this example, I used an item-to-guild association, but the technique works with associations to other kinds of data. The general problem of having to check many diverse names for membership in sets can be solved using this technique.
Questions
- For the divine items to Divine Lodge example, the attribute to check could be the
head
,foot
,chest
orhand
. ShouldisItemMemberOfGuild
also require an argument for the attribute name to check, orany
to check all of them? - Are there any other ways to somehow improve this technique?
- Is it worth it, in terms of gas and compute, to perform the check this way?
Could this work?
I am a Solidity noob so I could be wrong in my thinking of this. I’m relying on second-hand knowledge of how other smart contract systems use Merkle roots, not first-hand experience. I’d love for someone with the Solidity expertise to take this idea, verify it could work and run with it for the benefit of the Loot community. If not, I could try to build myself, but it would take longer.