See original extended article here.

What We Set Out To Do:

We set out to gain a completely working Ethereum application prototype for crowdfunded loans. It had to have both a back-end (Smart Contract) and a front-end (Dapp). The end goal being a way to validate the market and understand the technology stack for further development. For the website to work you need to have the Metamask plugin with an unlocked wallet (other Ethereum nodes that inject Web3 API should also work) and be on Ethereum’s test network.

Here’s how a loan works in the system now:

Request a loan by providing the funding goal, the investment period, the payback period, and the goal interest rate. The loan is created and listed starting with an investment period. During the investment period, investors can put out money for the loan. That amount can’t yet be taken out by either party. If the funding goal is not reached, the investors should be able to withdraw their money and the Loan should fail. Otherwise the debtor can withdraw the loan and the payback period begins. If the debt is not paid, then the loan is defaulted and has failed. If the debt is paid back, then the loan has been successful. After the payback period is finished and the loan was successful, the investors can withdraw their investment.

What’s A Dapp?

A Dapp is just a normal website that can be hosted anywhere. By using Ethereum Javascript Web3 API you can interact with an Ethereum node installed either on your client’s computer, or any other public Node set-up on the internet. That Node acts as a gateway to the Ethereum network and allows you to talk to the deployed smart contracts.

The Dapp’s Back End:

In a Dapp, the back-end instead of living on some company owned server is your smart contract living on the blockchain. They’re written in Solidity (there are other Contract languages, but this one is a lot more popular and nowadays the preferred way to write contracts). While you still need to write Ethereum Contracts directly, frameworks such as Truffle or Embark provide additional value with easy deployments on networks, migrations for updating existing contracts, and on-chain and off-chain unit testing. We ended up using Truffle supplemented with TestRPC Node.

The Dapp’s Front End:

As for the front-end itself we decided on using Angular 2. A lot of the community uses Meteor.js since it nicely fits into the Dapp model.

Smart Contracts:

A Smart Contracts’ code is immutable. Once you deploy something, it’s going to live in it’s current form on the blockchain forever. Contracts are modeled after Object Oriented Programming, and thus their internal state can be changed by calling their methods. Such method calls are a blockchain transaction, they are mined and the Contract state is changed for every participating Ethereum client, and so they need to run on every computer.

Sending Ether From A Smart Contract:

Sending Ether from a Smart Contract is a tricky beast. Since the address to which we send money to can also be a Smart Contract, it’s methods also need to be run when money is received, and they run midway through the execution of the first Smart Contract’s method, and so the second Smart Contract can also call the first Smart Contract during its execution. This is a property called reentrancy. This means that if the Contract is written wrong, it’s state might not be what you expect when a method is called. One scenario where this can be exploited is when the Smart Contract updates its state only after sending money. It’s not hard to imagine an attacker who writes a Smart Contract which calls ReceivePayment() each time it receives money, the execution would loop and all funds of the Loan contract could be siphoned out. That’s why it’s a good pattern to update the state beforehand.

Testing Our Loans:

The biggest problem in testing was the ability to test the deadlines of our Loans — you can’t speed up time, and TestRPC doesn’t allow jumping the block.numberconstant upwards. We ended up sidestepping the problem by exploiting the inner workings of TestRPC — a single block is mined for every single transaction. We simply pushed as many empty transactions as needed to reach the blocks we needed to move forward. This solution doesn’t work on real networks though. We don’t think there’s actually any way to test deadlines on a real network without inventing time travel, or testing a real loan with real time.

We also wanted to get all existing loans and refresh the data after something interesting happened on the blockchain. Fortunately Web3 allows for event watching.

Improvements For Next Iterations:

Right now the loan works on deadlines and before doing any operations, the Smart Contract checks on which range of deadlines it is. This is error prone (especially to one-off block errors), introduces some duplication, and is hard to read. The next iteration should make use of state machine pattern which is very easy to write and understand using Solidity’s modifiers, which would allow to only make an operation if in the proper state.

We’ve run out of time so not all functionality of the smart contract is visible on the Dapp front-end. Withdrawing funds by investors and contract owners still needs to be done manually using Web3 APIs.

While the loans refreshes on the front-end properly when something interesting happens, such as an investment, or a payback, it can’t detect when a period ends and refreshes. This is because the contract only runs on demand instead of being online all the time. There are some on-chain solutions such as the Ethereum Alarm Clock, but the cheapest and easiest way would be to have Javascript timers on the front-end estimate when the period should end and refresh the loan then. One technical problem with that is that the block mining time is variable on Ethereum, so we can only estimate the time when the deadline block is mined. This problem wouldn’t be visible to the user though. We could check the contract again after the timer ends behind the scenes, and adjust timers accordingly.

To increase security, in the next iteration we would like to separate each loan into it’s own separate Contract. Currently if there’s a bug in withdrawal methods, the attacker can siphon all the funds of each loan. If the loans were separate, only the affected loan funds could be stolen. We would design it by having a global aggregation Contract which would also deploy Loans. This design would also allow for the Loan code to be updateable in a sensible way — current loans would stay the same, guaranteeing the owner couldn’t meddle, but the new loans could have a newer version deployed during creation.

Conclusions:

Programming on the Ethereum blockchain is very unusual work, breaking lots of normal conventions. Smart Contracts allow you to think of your web application in terms of events based infrastructure and not worry about providing a back-end. On the other hand, writing contracts is a lot harder than normal back-end. You need to have quite a lot more in mind — starting with security, and thinking in terms of function reentrancy, through immutability needed for better planning up-front, and ending with having explicit costs to each action you do, and trying to avoid dynamic loops, and try to make everything work in a constant amount of time.