This project addresses the pain point of handling debts within a group. Whether settling debts from betting with friends or keeping track of who's paid for what during a long trip (our team right now!), there simply isn't a good service to 1) keep track of debts and tally up final necessary payments after a series of transactions, and 2) to the greatest extent possible, automate the final payment process. Addressing both would allow for groups to not only better manage finances and have clarity on spending, but also speed up the resolution timeline of debts. Our project is set up such that the frontend, hosted via firebase, stores and tracks different proposed transactions, while the backend deals with automatic payment term approval and transactions. A concrete example of this in action is a series of transactions from our time in Amsterdam ("Nyle owes Christy 0.02 ETH for Saturday dinner", "group owes Ash 0.24 ETH for travel expenses", etc.). These are easily entered throughout the trip via the frontend, with a dashboard displaying the transactions and an option to add new ones. After someone has deemed that transactions are done and the group should settle payments, they simply click a button to propose the group splits payments; at this point, each group member is shown the final amount they owe/are owed, and "agrees" by either paying the amount owed or not hitting the cancel button. On the solidity backend, a group is first initialized with addresses and final dues/amounts owed per address. "senders" (those who owe money) send the amount they owe to the contract, where funds remain locked until all senders have deposited their debts (and no one has canceled the payment split). At that point, the receivers() function is called and each receiver is sent the amount they are owed from the funds locked in the contract. Note that since we're splitting all transactions, the sum of all debts and amounts owed will be 0. The group can be disbanded in two ways: either receivers() has successfully finished distributing funds, or any individual group member has hit cancel on the frontend.
The core framework of this project was a Truffle/React dapp. We used Truffle because of the ease with which we could test everything locally; specific smart contract functions, broader interactions with React components, etc. We also, of course, chose to build an EVM compatible app because of ETH's widespread popularity and the straightforward changes we'd make to port to EVM compatible platforms, such as Polygon and Optimism. Our focus on the backend was on designing efficient and intuitive functions: the logic boils down to storing Groups as structs (that use mappings to amounts owed) and functions to create a group, send debts, distribute locked funds, and cancel. One memorable aspect of the technical design process was spending a long time debugging, only for us to realize that the code was completely correct (test cases were inaccurate compared to our expectations). We seriously had correct code, but spent over 5 hours "debugging" on this; the issue ended up being that we were entering microscopic amounts of money for "amounts owed" by users because the unit was Wei instead of Ether, so it appeared as if contract funds and address funds were not changing when they were (just a super small amount). We will certainly remember the time we spent on this, and have learned a valuable lesson about "testing the test cases", not just the functions we run them on!