Welcome back to EGS Garage with Chaz, a journey through the process of building an Ethereum DApp from idea to deployment. This isn’t formal coding advice; it’s an open diary of my experience and what I’ve learned along the way. Smart contracts are hard – but far from impossible to learn if you’ve got the right mix of motivation and humility. I hope this series inspires you to give it a shot yourself. If you need to catch up, check out my first 3 entries: #1, #2, #3.

BridgeBurner is a smart contract designed to put social and financial pressure on two parties to attend a meeting or other appointment set in a calendar. Let’s say you and a friend keep rescheduling a lunch together. You could use a smart contract like BridgeBurner to put your money where your mouth is by putting down a deposit that’ll start burning if you don’t arrive on time.

Inheritance

In my last post, I decided to base BridgeBurner on the ERC-1620 standard. I figured BridgeBurner would just inherit either the contract from ERC-1620 or Paul Berg’s implementation of it, Streams.sol. But I soon realized that I hadn’t fully understand this concept as it pertained to Solidity before I started working. And that’s probably why I ended up having to rethink my approach.

When I say one contract inherits another, I’m not talking about the idea of passing down exclusive ownership of something. Rather, I’m referring to a new smart contract adopting all of the code and functions of an existing contract, but without the existing contract losing any of those characteristics. Basically, the existing contract serves as a building block for the new contract. This is a nice feature of open source software that lets anyone build on existing tech without having to reinvent the wheel.

Let’s take Streams.sol as an example. On line 12 where it says “contract Streams is Ownable, IERC1620,” that means that the Streams contract has inherited all the functions of the IERC620 smart contracts. So instead of starting from scratch, you can point to an existing contract that already does what you’re looking to do.

Abstract smart contracts

IERC1620.sol is what is called an interface, which is similar an abstract contract. Abstract smart contracts include at least one function that is not implemented. This concept works well for standards, which don’t need to act as standalone programs but which are meant for others to use and build upon. In that context, abstract contracts outline which functions need to exist in order to comply with a standard, in this case ERC-1620 money streams. It’s up to you – the builder of the DApp using smart contracts inherited from the abstract contract – to implement all the necessary functions. Going back to our example, Paul’s Streams.sol implements all of the “empty” functions it inherits from IERC1620.sol.

Learn from my mistakes

At first, I imagined I would simply build BridgeBurner’s dates as a layer on top of the Streams contract. I plugged away on this hunch, but I never stopped to work out the full design of the contract or how a layered approach would actually work. On top of that, I ran into difficulties importing smart contracts, because I kept jumping around on different compilers and laptops.

I tried to just power through the roadblocks. When I eventually tried inheriting IERC1620.sol directly, I ran into this error:

“Contracts that inherit an abstraction must implement all its method signatures exactly. Error at launch.”

That’s when it finally clicked in my head and I realized the flaws in my thought process.

Back to the drawing board

I realized that Streams.sol is just one implementation of IERC1620. I’d used the Streams contract as my building block instead of stepping back a level to the IERC1620 standard and modifying it to meet BridgeBurner’s needs (that is, to make it work with dates). Somewhere along the way, I managed to ignore the basic concepts of inheritance.

When I did step back, I realized that inheriting all of the functions from Streams.sol wouldn’t work. Streams includes the ability to pass updates to existing streams. But in order to impose maximum social pressure in the BridgeBurner context, the date should be fixed. BridgeBurner’s about honoring commitments: once a guest accepts an invite by depositing funds into the contract, there’s no going back.

I realize that making the date immutable could seem a bit extreme. But this could be mitigated by, e.g., a UI that includes a confirmation screen before locking in the date. I believe making it irreversible better accomplishes the goals I had in mind for BridgeBurner. And if I were to inherit all functions from the Streams contract, I’d have to nullify certain functions and have dead weight in the contract.

If you replace every part of a car…

So I went about implementing a modified version of the struct Stream, which I called Date. Creating the Date struct allowed me to picture where burn-streams would fit in. Forcing myself essentially to reverse-engineer Streams.sol from the ground up forced me to truly understand how the functions actually worked together.

Also, I learned a thing or two about when and why you’d log an event in Solidity. But we’ll get into that another time.

Thanks for reading. Send all comments, questions, or concerns to @ChazSchmidt on Twitter or in the Concourse Discord.