//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);
}
}