A couple months back, I found out that you could build smart contracts off of the Ethereum blockchain and create decentralized applications to communicate with it. This was extremely surprising to me because I always viewed Ethereum strictly as a trading asset with no utility due to my lack of research. Once I read a little bit more about Ethereum, web3.js, and Solidity -- I knew I had to create my own dapp and explore this area a bit more.
I wanted to create a dapp that could host events similar to Eventbrite. There would be two primary roles - Coordinator and Participant. The coordinator would be the whoever created the event and the participant would be anyone who purchased a ticket. The smart contract would hold the funds of participants and would only release the funds to the coordinator if the majority of participants voted the event as valid or if the voting period ends and there aren't enough votes. If the majority of participants voted the event as invalid or if the coordinator cancels the event before the start date, then the participants would be able to receive a refund.
The reason why I implemented this feature is because coordinators can scam users and never end up hosting the event. This incentivizes coordinators to host legitimate events in order to receive payment. In addition, if the event is invalid, this will incentivize participants to vote the event as invalid in order to receive a refund. Lastly, if there are not enough votes and the voting period ends, the coordinator will be able to receive payment meaning there was not enough interest from participants to vote the event as invalid. This idea may sound interesting in theory but one caveat is that even if the coordinator hosts a legitimate event, a majority of participants can still band together and vote the event as invalid to trigger a refund. There might be more issues with this approach, but it doesn't matter because my main goal here was to learn more about web3.js and Solidity.
- Solidity to create my smart contract
- web3.js to allow me to interact with the Ethereum blockchain
- IPFS to store my images, no database needed 😮
- Next.js on the front end as usual 😎
- Truffle suite's Ganache to deploy a local Ethereum blockchain on my personal workspace to develop.
- Tailwind CSS - This was my first time using this and I really liked it. I love the fact that it provides a wide variety for customization but sometimes it would get a bit too confusing when I had like 10+ classnames for an element. For a small project that doesn't require too much on the front end, I would probably use a different styling framework.
I first started by creating the smart contract on Remix IDE (great IDE btw). I personally like to think of a smart contract as the backend service deployed on the blockchain that handles all the business logic. Solidity is an interesting language and it reminded me of C++ so it wasn't too hard for me to pick up. There were some things that I had to get used to though, for example, you can't simply just call a method to get the length of an array. You have to declare a separate integer variable and keep track of the array size. Also it's extremely important to be as efficient with your code as possible. If not, you can significantly increase the cost of gas fees. The reason why this happens is because the smart contract uses gas for computation to modify storage variables on the smart contract. Solidity also has some cool data types like address which stores and Ethereum address and mapping which is a hashmap data structure. Function modifiers are also really cool - they serve as some form of prerequisite before the function can be called. Lastly, there isn't a date object built in for Solidity. To retrieve an approximate date time, you need to get the last mined block's timestamp. There's probably more stuff that I'm missing but these were the main things that I found interesting.
The dapp would contain only 3 pages:
- Coordinators can upload an image directly to IPFS to stylize their event. IPFS is a peer to peer network allowing users to store and share data (same thing as a torrent really) in a decentralized manner. This means that there isn't a centralized database required on my end to host these images. The user can simply upload an image, IPFS hashes the image, and our dapp stores the hash on the smart contract to reference when needed.
Price (in Wei)
- I'm using Ethereum's smallest denomination which is wei. 1000000000000000000 wei is equivalent to 1 Ether.
Start Date Offset (in Seconds) / End Date Offset (in Seconds)
- Start date determines when the event will start and end date determins when the event will end.
- This is the number of seconds after creating the event. If a coordinator provides SD for Start Date Offset and ED for End Date Offset and assuming that our block's current timestamp of the event creation is T, the event's start date will be T + SD seconds and the end date will be T + ED seconds, where ED > SD.
Voting Period Offset (in Seconds)
- Voting period is the amount of time the participants are allowed to vote after the event has ended.
- If the coordinator provides a value of VP seconds for Voting Period, then users will only be allowed to vote on an event between T + ED and T + ED + VP.
Is this user friendly? Hell no lol, having the coordinator calculate the number of seconds to determine the start date, end date, and voting period would be a huge pain. Again the user interface and user experience was not a primary concern for me when I was working on this project.
Once a user clicks on an event on the home page, they will be redirected to the drilldown page allowing users to view the event with more information.
Depending on the user's role and status of the event, different actions and messages will be presented on the page.
- Non coordinators or non participants can purchase a ticket only if the event is not running or not canceled.
- Only participants can receive a refund if the event is canceled or voted as invalid by the majority.
- Only participants can vote (Invalid or Valid) if the event is not canceled, has ended, is within the voting period, has bought a ticket already, and has not voted yet.
- Only the coordinator can retrieve payment if the event has not been canceled and enough voters have voted the event as valid OR the event has not been canceled and the voting period has ended and does not have majority vote.
- Only the coordinator can cancel the event if the event has not started yet and has not been canceled yet.
- Instead of asking coordinators to provide Start Date, End Date, and Voting Period offset values in seconds; we can replace the input box with date pickers allowing a more user friendly approach.
- There should be a minimum amount of time required for voting period offset. The coordinator can currently set the Voting Period offset to 1 second and receive payment.
- Pagination on the home page instead of displaying all events stored on the smart contract.
- Filterable home page which displays events that have not started yet, have started, or have ended.
- Allowing coordinators to select which denomination they would like to pay in instead of defaulting to wei.
- Better styling lol
- ...and more!