5.1 介紹
我們?cè)噲D使用以太坊來(lái)實(shí)現(xiàn)一個(gè)沒有第三方擔(dān)保的買賣合同融痛。
5.2 實(shí)現(xiàn)
//聲明使用的SOLIDITY 版本號(hào)
pragma solidity >=0.4.22 <0.6.0;
//購(gòu)買合同
contract Purchase {
// 商品價(jià)格
uint public value;
//賣方
address payable public seller;
//賣方
address payable public buyer;
//聲明一個(gè)商品狀態(tài)的枚舉:創(chuàng)建,鎖定蔗牡,已處理
enum State { Created, Locked, Inactive }
//當(dāng)前合同商品的狀態(tài)
State public state;
//構(gòu)造函數(shù)payable 表示在部署這個(gè)合約的時(shí)候 可以發(fā)送以太幣
constructor() public payable {
//創(chuàng)建合約的人就是賣方
seller = msg.sender;
//msg.value 表示創(chuàng)建合約的時(shí)候喊儡,賣方壓得以太幣數(shù)量。 押金必須是價(jià)格的雙倍瓦胎,且是偶數(shù)。
value = msg.value / 2;
require((2 * value) == msg.value, "Value has to be even.");
}
//modifier 是以太坊的關(guān)鍵字尤揣,你可以理解為過濾器搔啊,其可以用來(lái)修飾函數(shù)。
modifier condition(bool _condition) {
require(_condition);
_; // 表示繼續(xù)執(zhí)行
}
//只能是買方調(diào)用
modifier onlyBuyer() {
require(
msg.sender == buyer,
"Only buyer can call this."
);
_;
}
//只能是賣方調(diào)用
modifier onlySeller() {
require(
msg.sender == seller,
"Only seller can call this."
);
_;
}
//判斷輸入狀態(tài)和當(dāng)前商品狀態(tài)是否一致
modifier inState(State _state) {
require(
state == _state,
"Invalid state."
);
_;
}
// event (事件) 的以太坊的關(guān)鍵字北戏,他其實(shí)是以logs日記的形式記錄信息负芋。
event Aborted();
event PurchaseConfirmed();
event ItemReceived();
/// 贖回操作。賣方可以撤回押金嗜愈,改變商品狀態(tài)為已經(jīng)處理旧蛾。
// 該函數(shù) 會(huì)觸發(fā)兩個(gè)攔截器 onlySeller inState
function abort() public onlySeller inState(State.Created)
{
//調(diào)用事件。log日記中記錄了一個(gè)Aborted 行為蠕嫁。
emit Aborted();
state = State.Inactive;
seller.transfer(address(this).balance);
}
/// 下單锨天。 condition過濾器聲明 下單金額必須是商品的兩倍價(jià)格
function confirmPurchase()
public
inState(State.Created)
condition(msg.value == (2 * value))
payable
{
emit PurchaseConfirmed();
buyer = msg.sender;
//改變商品的狀態(tài)為鎖定中
state = State.Locked;
}
/// 點(diǎn)擊已收貨
function confirmReceived()
public
onlyBuyer
inState(State.Locked)
{
emit ItemReceived();
state = State.Inactive;
//將 買方的押金 退回
buyer.transfer(value);
//剩余的資金退回賣方賬號(hào)。
seller.transfer(address(this).balance);
}
}
5.3 思考
大家可以去思考下 在去中心化的以太坊網(wǎng)絡(luò)中剃毒,該應(yīng)用是如何實(shí)現(xiàn)的無(wú)擔(dān)保病袄。
5.4 transfer / send 兩個(gè)函數(shù)
transfer 和 send 在功能上并沒有什么區(qū)別,只是對(duì)于錯(cuò)誤發(fā)生的時(shí)候處理方式不同赘阀。
send 在轉(zhuǎn)賬失敗的時(shí)候回返回 boolean 而 transfer 會(huì)直接終止合約的執(zhí)行陪拘。 某種意義上來(lái)說 transfer 就是加了事務(wù)。
因此在使用send有一些風(fēng)險(xiǎn):如果調(diào)用棧深度超過1024或是gas不夠纤壁,所有的轉(zhuǎn)讓操作都會(huì)失敗,為了更安全的以太幣轉(zhuǎn)移捺信,如果用send就必須每次都要檢查返回值酌媒,使用transfer方法會(huì)更好欠痴;