保险智能合约

//A basic learning-by-doing insurance contract in Solidity
//Author Davide "dada" Carboni
//Licensed under MIT
pragma solidity ^0.4.2;
contract Insurance {

    //premium is what you pay to subscribe the policy
    //premium是您付费订阅该政策   保费
//  uint  public   premium;

    //oracle is the 3rp party in charge of stating if a claim is legit
    //oracle是第三方,负责说明如果索赔是合法的  第三方
    
    address public  oracle;

    //protection is the financial protection provided by the contract
    //protection是合同规定的财务保护 
//  uint  public   protection;

    //insurer is the one who locks his money to fund the protection
    //保险公司
    address public insurer;

    //subscriber is who wants the insurance protection
    //投保人
//  address public subscriber;
//银行
    address public bank;
    
    struct userInsurance{
        uint state;
        uint premium;
        uint protection;
        uint duration;
        
        
    }
    
    struct User{
        //投保的状态
        address userAddress;
        
        string username;
        //address oracle;
        //uint premium;
        //uint prot;
        //uint duration;
        //uint state;
        uint numInsurances;
        mapping(uint=>userInsurance) insurances;
    }
    
    uint public numUsers;
    uint public numInsurances;
    mapping(uint=>User) public  users;
    mapping (address => uint) public balances;
    
    //给一个用户的地址,新增一个用户
    function newUser(address userAddress,string username) returns (uint userID) {
        userID = numUsers++; 
        users[userID]=User(userAddress,username,0);
        newUsered(msg.sender,numUsers);
    }
    function newInsurance(uint userID,uint premium,uint prot,uint duration)payable{
        User u=users[userID];
        u.insurances[u.numInsurances++]=userInsurance(0,premium,prot,duration);
        NewInsuranced(msg.sender,u.numInsurances);
    }
    
    
    //得到投保人的姓名和投保的状态
    function getUser(uint userID,uint numInsurances)constant returns(address,string,uint)
    {
        User u=users[userID];
        return (u.userAddress,
        u.username,
        u.numInsurances
        //u.insurances[numInsurances].state,
        //u.insurances[numInsurances].premium,
        //u.insurances[numInsurances].protection,
        //u.insurances[numInsurances].duration
        );
    }
    function getInsurance(uint userID,uint numInsurances)constant returns(uint,uint,uint,uint)
    {
        User u=users[userID];
        return(
        u.insurances[numInsurances].state,
        u.insurances[numInsurances].premium,
        u.insurances[numInsurances].protection,
        u.insurances[numInsurances].duration
            );
    }
    
    function getNumUsers() constant returns (uint) {
        return numUsers;
    }
    function getNumInsurances()constant returns(uint){
        return  numInsurances;
    }
  
   //银行给用户转账 
  function sendMoney(address receiver, uint amount) payable{
        if (balances[msg.sender] < amount) return;
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        SentMoney(msg.sender, receiver, amount);
    }
    //银行创造钱
    function mint(address receiver, uint amount) {
        if (msg.sender != bank) return;
        balances[receiver] += amount;
        Minted(msg.sender,receiver,amount);
    }
    
    function setOracle(address orac)returns(address oracle){
         oracle=orac;
         //return oracle;
         SetOracled(msg.sender,orac);
    }
    

    

    //contractCreator is who deploys the contract for profit
    // 为了利润部署了合同
    address public contractCreator;

    //the contract goes through many states
    //状态
    //uint public state;
    uint CREATED=0;
    uint VALID=1;//有效
    uint SUBSCRIBED=2;//订阅
    uint ACTIVE=3;//激活
    uint CLAIMED=4;//索赔登记
    uint EXPIRED=5;//过期
    uint PAID=6;//支付
    uint REJECTED=7;//拒绝

    //let's assign a fixed profit to who created the contract
    //让我们为创建合同的人分配固定利润
    uint constant profit = 200 finney;

    //duration, a contract cannot last for ever
    //持续时间
    //uint duration;

    //expireTime is when the contract expires
    //expireTime是合同到期的时间
    uint expireTime;

    event Inited(uint _state);
    event subscribed(address _from,uint _state);
    event backed(address _from ,uint _state);
    event claimed(address _from,uint _state);
    event oracleDeclareClaimed(address _from ,uint _state);
    event newUsered(address _from,uint _numUsers);
    event SentMoney(address from, address to, uint amount);
    event Minted(address from,address to,uint amount);
    event SetOracled(address _from,address _to);
    event NewInsuranced(address _from,uint _numInsurances);

    function Insurance(){
        // this function use no args because of Truffle limitation
        contractCreator = msg.sender;//当前函数的外部调用者就是contractCreator
        bank=msg.sender;
    //  state = CREATED;

    }


    function init(uint userID,uint numInsurances) {
        User u= users[userID];
        userInsurance ui=u.insurances[numInsurances];
        if(ui.state!=CREATED) throw;//`throw`会终止和撤销所有的状态和以太改变。
           //如果函数调用无效,这通常是一个好的选择。
           //但是需要注意,这会消耗提供的所有gas。
    //  u.oracle = anOracle;
        //u.premium = aPremium * 1 ether;
            ui.premium = ui.premium * 1 ether;
        //u.prot = prot * 1 ether;
        ui. protection = ui. protection * 1 ether;
        //u.duration = ttl;

        bool valid;//有效
        //let's check all the var are set
        valid =  ui.premium !=0 && ui.protection!=0 && ui.duration!=0;
        if (!valid) throw;
        ui.state = VALID;
        Inited(ui.state);
    }
//投保
    function subscribe(uint userID,uint numInsurances) payable {
        User u= users[userID];
        userInsurance ui=u.insurances[numInsurances];
        //is in the proper state?
        //是否处于正常状态?
        if(ui.state != VALID) throw;

        //can't be both subscriber and oracle
        //不能既是投保人又是oracle第三方 
        if(msg.sender == oracle) throw;

        //must pay the exact sum
        //必须支付确切的金额
        if(balances[u.userAddress]==ui.premium){
        
            //users=msg.sender;
            ui.state = SUBSCRIBED;

            //the contract creator grabs his money
            //合同创造者抓住他的钱
            //if(!contractCreator.send(profit)) throw;
            subscribed(msg.sender,ui.state);
        }
        else throw;
    }

//赚钱
    function back(uint userID,uint numInsurances) payable{
         User u= users[userID];
         userInsurance ui=u.insurances[numInsurances];
        //check proper state
        //检查正确的状态
        if(ui.state != SUBSCRIBED) throw;//已经投保

        //can't be both backer and oracle
        //不能既是受益人又是oracle
        if(msg.sender == oracle) throw;

        //must lock the exact sum for protection
        //赔偿金额
        if(balances[msg.sender]>ui.protection){
            insurer=msg.sender;
            ui.state = ACTIVE;
            //insurer gets his net gain
            //保险公司获得净收益
            //if(!insurer.send(u.premium - profit)) throw; //this prevents re-entrant code
            //这防止了重入代码
            sendMoney(insurer,ui.premium);
            expireTime = now + ui.duration;
            backed(msg.sender,ui.state);
        }
        else throw;
    }

    function claim(uint userID,uint numInsurances)payable{
         User u= users[userID];
         userInsurance ui=u.insurances[numInsurances];
        //if expired unlock sum to insurer and destroy contract
        //如果到期解锁金额给保险公司并销毁合同
        if(now > expireTime){
            ui.state = EXPIRED;
            //if(!insurer.send(u.prot))throw;//解冻保险公司押金,退回保险公司
            //selfdestruct(contractCreator);
            sendMoney(insurer,ui.protection);
            claimed(msg.sender,ui.state);
        }

        //check if state is ACTIVE
        if(ui.state!=ACTIVE)throw;

        //are you the subscriber?
        //if(msg.sender != u.userAddress)throw;

        //ok, claim registered
        //确定,索赔登记
        ui.state=CLAIMED;
        claimed(msg.sender,ui.state);
    }

    function oracleDeclareClaim (bool isTrue,uint userID,uint numInsurances)payable{
        User u= users[userID];
        userInsurance ui=u.insurances[numInsurances];

        //is claimed?
        if(ui.state != CLAIMED)throw;

        //are you the oracle?
        if(msg.sender!=oracle)throw;

        //if claim is legit then send money to subscriber
        if(isTrue){
            ui.state = PAID;
            //if(!u.userAddress.send(u.prot))throw;
            sendMoney(u.userAddress,ui.protection);

        }else{
            ui.state = REJECTED;
            //if(!insurer.send(u.prot))throw;
            sendMoney(insurer,ui.protection);
            oracleDeclareClaimed(msg.sender,ui.state);

        }

        //in any case destroy the contract and change is back to creator
        //在任何情况下破坏合同和变化回到创造者
        //selfdestruct(contractCreator);
    }






}