保險智慧合約

weixin_34087301發表於2018-03-01
//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);
    }






}

相關文章