Thursday, March 29, 2018

Reinventing Insurance Through Ethereum and Solidity

Below is code for a very simple smart contract that would implement about 40% of a decentralized insurance policy.  The remainder of the implementation would require a user interface to allow people to subscribe, pay premiums at certain time intervals, make claims, and (especially important for decentralization) verify the claims of others.

But Don't Tell Your Insurance Agent To Go Suck It Just Yet


I've been following matters of cryptocurrency since early 2013, back when Bitcoin was a mere $73.  At that point, I wasn't willing to bet the farm, but the idea of distributed anonymous (but yet fully transparent and public) transaction ledgers for the sake of auditability and traceability was alluring, especially for the sake of tracking physical assets and eliminating other big giant institutions such as title companies.  I ended up placing in a company hackathon in 2015 (and then getting invited to a subsequent, and very exclusive, company hackathon to further refine the idea before many executives) by implementing such an idea by using colored coins, which at the time, was the state-of-the-art way to use cryptocurrency to transcend simply monetary transactions and actually track "assets" with other meanings besides their value in Bitcoin.

At this point, there were rumblings of a magical new cryptocurrency called Ethereum that would revolutionize the notion of adding metadata to transactions, and could in fact be used to implement entire systems (called smart contracts) that could run themselves in order to perform computation to facilitate deciding whether or not to perform a transaction.  At first, I thought it was too good to be true, but later on in 2016, I found myself going to local Ethereum user group meetings where folks were diving into smart contracts and discussing ways to turn entire industries upside-down by cutting out all sorts of middlemen, such as our friendly but hapless insurance agent mentioned earlier.

I tried throughout the rest of 2016 to get my hands on some real live Ether through a faucet so I could start playing with making my own real smart contracts and do some real live experiments.  Little did I know that this was not required, because browser-based clients such as Remix allow you to write smart contracts without needing so much as a testnet, but my fruitless efforts fraught with frustration over none of these faucets actually depositing ether into any of my wallets led to me abandoning Ethereum to go catch up on the evolution in machine learning that has happened since I got out of college instead.

Anyway, the chance to get in on Ethereum at $7-20 per ether is probably long gone.  However, the amazing possibilities to disrupt many different industries, as highlighted by the surge in ICOs (initial coin offerings) in late 2017, has got me and many of my peers finally getting moving on related development efforts.  And so, hot off the press, I bring you this very basic implementation of an insurance policy in Ethereum.

Do As I Say, Not As I Do


The operating principle of this contract has been highly simplified from what would really be needed in an actual insurance policy, and this was written in about an hour while I had no previous experience with Solidity, so it's important to know it might not be well-written code executing a non-well-written insurance policy.  Nevertheless, it will help illustrate some of the key concepts in coding.

The insurance policy starts life when one user instantiates the contract.  Upon instantiation, nothing happens other than the formation of the contract account.  Once the contract account is formed, users of externally-owned accounts (EOAs) -- i.e. you & me who have wallets and control of them with private keys -- can send ether to this contract account in order to subscribe you to the insurance policy.  You can continue sending ether to it as long as you like.  You can keep track of how much ether you have sent to it.

When it comes time to make a claim, it is simple to do so -- just call the claim() function on the contract.  This allows other members of the insurance pool to verify your claim (hypothetically) and, if they approve, they can call the approveClaim() function.  Once two other members of the insurance pool have done this, and once you have paid in the minimum amount, then the contract will automatically credit your account with ether in the amount of payoutAmt.

Some things to note:

  • The contract must have a payable function in order to be able to accept ether.  To keep track of what was paid by whom, use the instance variables msg.sender and msg.value.
  • There is not really a good notion of null in Solidity.  In the instances where there was not a defined Subscriber (i.e. subscribers[address] is undefined), it tends to be just as valid to continue using the null pointer (where as you would get an exception in basically any other language), but once you go to read the values of one of the objects, it would read as 0.  This is why, if you plan to have values that could be legitimately 0, you might want to plan for another variable to indicate initialization of an object in a Mapping.  For my particular case, I could assume that a user with an amtPaid (amount paid in) of 0 probably didn't exist, and even if they did, it wouldn't really matter if they initialized another one properly and went forward using that one.


pragma solidity ^0.4.0;
contract Insurance {

    uint totalPot;
    address myContract;

    struct Subscriber {
        uint payoutAmt;
        uint amtPaid;
        bool hasClaim;
        address[] votes;
    }
    mapping(address => Subscriber) subscribers;

    function Insurance() public {
    }

    function claim() public {
        Subscriber storage sender = subscribers[msg.sender];
        sender.hasClaim = true;
    }

    function viewClaim() public constant returns (uint signedContracts) {
        Subscriber storage sender = subscribers[msg.sender];
        if (!sender.hasClaim) return 99999999;  // only because -1 wouldn't work
        return sender.votes.length;
    }

    function approveClaim(address claimantAddr) public {
        if (claimantAddr == msg.sender) return;
        Subscriber storage claimant = subscribers[claimantAddr];
        if (!claimant.hasClaim) return;
        if (subscribers[msg.sender].amtPaid == 0) return;
        claimant.votes.push(claimantAddr);
        // Remember payOut handles all testing to see if conditions are met
        payOut(claimantAddr);
    }

    // Note that paying in automatically subscribes you to the policy if you're not already joined
    function payIn() public payable {
        if (subscribers[msg.sender].amtPaid == 0) {
            subscribers[msg.sender] = Subscriber({payoutAmt: 10 ether, amtPaid: 0, hasClaim: false, votes: new address[](0)});
        }
        Subscriber storage sender = subscribers[msg.sender];
        sender.amtPaid += msg.value;
        if (sender.hasClaim) {
            payOut(msg.sender);
        }
    }

    function viewPaidIn() public constant returns (uint amtPaid) {
        Subscriber storage sender = subscribers[msg.sender];
        amtPaid = sender.amtPaid;
    }

    function payOut(address claimantAddr) private {
        Subscriber storage claimant = subscribers[claimantAddr];
        if (claimant.votes.length > 1 && claimant.amtPaid >= claimant.payoutAmt) {
            claimantAddr.transfer(claimant.payoutAmt);
            claimant.votes = new address[](0);
            claimant.hasClaim = false;
        }
    }

}


What next?


This, being only 64 lines of code, and done in about an hour by someone skilled at programming but having no previous Solidity experience, leads me to believe you could just have a bunch of clever programmers hypothesizing about how to disrupt any given industry over lunch as a warmup for what work they have to do in order to actually put food on the table, and then go on and actually implement it in the time between dinner and bedtime.  Sure there are a lot of details that need to go into this to really make it polished, like especially a long tail of testing in order to make sure the contract is bulletproof.  But, if it's so easy to write an insurance policy, just imagine what else can be done with Ethereum in just as quickly!