Day 4 of "Building an Equipment System with Smart Contracts" for @ethgardlegends.
Imagine you find a cool sword and want to equip it to your hero to gain benefits in the game. That's what I'm building.
In technical terms, the goal is to allow NFTs (ERC1155/ERC721) to be equippable on other NFTs (ERC721 => Heroes).
Today's progress:
Woke up today and instantly knew how to cut down more contract size. While I was using a shared item metadata mapping for common attributes, I also defined separate metadata mappings for each item type (weapon, armor, accessory) to set exclusive values like armor = 10
or damage = 15
.
The fix: I merged these into the existing custom stats struct in the common metadata. Since I was already using this struct for irregular attributes like strength and agility, it made sense to extend it for properties like minDamage and attackSpeed. This small change allowed me to remove more code, freeing up another 4kb, bringing the contract size down to around 20kb.
struct ItemStat {
Stat stat;
uint8 value;
}
/// Before
struct ItemMetadata {
uint32 itemId;
uint16 durability;
bool isSoulbound;
ItemStat[] stats; // i.e. 8 strength, 5 agility
}
struct WeaponMetadata {
uint32 itemId;
uint16 minDamage; // i.e. 10
uint16 attackSpeed; // i.e. 12
...
}
/// After
struct ItemMetadata {
uint32 itemId;
uint16 durability;
bool isSoulbound;
ItemStat[] stats; // i.e. 8 strength, 5 agility, 10 minDamage, 12 attackSpeed
}
I also renamed and refactored the contract from InventorySystem to EquipmentSystem - an important realization I had after finishing yesterday’s post. Since the code is currently focused purely on equipping and unequipping, it makes sense to be specific with the naming; especially with contract size limits in mind.
Next, I added logic to unsoulbound items. In the game, all items usually start as soulbound, meaning free-to-play players can earn items just like anyone else. But to trade them on the market, they need to be unsoulbound - which costs X amount of Y currency. The contract is flexible enough to support any currency, but in this case, it will be Ethershards - a soulbound currency earned only by owning assets while winning games.
With all tests updated and passing, I was finally able to deploy and initialize the contracts on testnet. That led me to the indexer - a system that listens for smart contract events and transforms them into database tables. Seeing the items I had defined in code now appearing in a structured database - completely automated via onchain events - was pretty satisfying. There’s still more logic to add, but some of it relies on actually minting and equipping items.
So, I started working on an early UI prototype for the Equipment System. Still very, very early, but it might give you a better insight into what I'm building. This pattern is also just how I like to work - switching between different layers of the stack. For example, I might start with smart contracts → backend → frontend → back to backend → more smart contract work → then frontend again, and so on. Keeps things fresh and helps me see the bigger picture.
Today's lesson:
To quote one of my favourite songs: "And I need to get some rest -- yo, where's the cess?
Take some rest.
I’m usually relentless when it comes to bug-hunting. I enjoy my work as a code-detective, and I find it hard to call it a night when a problem isn't solved. But after a long day, even if my motivation and persistence are there, my brain just isn’t at full power.
And yesterday/today was a perfect example of this. After a good night’s rest, I almost instantly saw the best solution for the contract size issue and a better solution in general. That of course not always the case, sometimes it takes longer to find the solution to an issue than one night, but taking some rest is a great start.
PS: If you're having trouble understanding certain parts but want to learn more, try the AI feature on Peakd or ChatGPT/Grok to have it explained 👍.
Love the art work of the card!
hey brother... I've been meaning to ask. Are you doing all this on your own? Did you get a team together?
Meet the team:
😄
HAHAHAHHAHA