// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.7;
/*
此合約是一個類似”網購“的功能,通常我們使用的網購存在一個可信任的第三方中介,當買家收貨確認后,賣家才收到錢
但是此合約由于沒有第三方中介,所以使用了押金的方式,當雙方都有押金在合約中鎖定,可有意愿去解決出現的末知問題
由賣家發(fā)起網購合約,設定商品的價錢value,然后雙方都支付兩倍value的價錢作為押金,并鎖定。
完成交易收到貨后,賣家可以退回3倍value(押金+貨款),買家可以退回1倍value(押金)
部署地址 https://rinkeby.etherscan.io/tx/0x641a0f38bf11b377cd7fe926a4ed508769e7d643bf1cb9a4f4268f1757e66558
*/
contract Purchase {
uint public value; // 約定的商品價錢
uint public value2; // 約定的商品價錢
address payable public seller; // 賣家地址
address payable public buyer; // 買家地址
enum State { Created, Locked, Release, Inactive } // 訂單狀態(tài)枚舉
State public state; // 當前訂單狀態(tài)
// 條件判斷修飾符
modifier condition(bool condition_) {
require(condition_);
_;
}
/// 只有買家可以調用此函數
error OnlyBuyer();
/// 只有賣家可以調用此函數
error OnlySeller();
/// 當前訂單狀態(tài)不允許調用此函數
error InvalidState();
/// 傳入的參數必須是偶數
error ValueNotEven();
// modifier修飾符:判斷是否買家在調用函數
modifier onlyBuyer() {
if (msg.sender != buyer) {
revert OnlyBuyer(); // 不是則回滾狀態(tài)、向外報錯
}
_;
}
// modifier修飾符:判斷是否買家在調用函數
modifier onlySeller() {
if(msg.sender != seller) {
revert OnlySeller(); // 不是則回滾狀態(tài)、向外報錯
}
_;
}
// modifier修飾符:判斷是否在`state`狀態(tài)
modifier inState(State state_) {
if (state != state_) {
revert InvalidState(); // 不是則回滾狀態(tài)、向外報錯
}
_;
}
event Aborted(); // 交易結束
event PurchaseConfirmed(); // 交易確定
event ItemReceived(); // 已收到貨
event SellerRefunded(); // 賣家退款
/// 需要確定`msg.value`是一個偶數
/// 因為solidity在除法計數中,小數會直接截斷(如 99 / 2 = 49.5 會截斷為49)
/// 使用乘法 * 2去判斷傳入的value是否偶數
constructor() payable {
seller = payable(msg.sender);
value = msg.value / 2;
if ((2 * value) != msg.value) {
revert ValueNotEven();
}
}
/// 中止交易,并取回以太幣。
/// 只能在合同開始前,由賣方調用
function abort()
external
onlySeller
inState(State.Created)
{
emit Aborted();
state = State.Inactive;// 更改合約狀態(tài)為Inactive
// 我們直接在這里使用轉賬。它是重入安全的,
// 因為我們是最后一行調用transfer的,并且已經在之前修改了State狀態(tài)。
seller.transfer(address(this).balance);
}
/// 以買家身份確定交易
/// 交易必須包含`2 * value`的以太幣(value是constructor方法賣家確定的)
/// 這些以太幣會鎖定直到交易完成(confirmReceived函數被調用)
function confirmPurchase()
external
inState(State.Created)
condition(msg.value == (2 * value))
payable
{
emit PurchaseConfirmed(); // 告知交易確認
buyer = payable(msg.sender); // 記錄買家
state = State.Locked; // 更改合約狀態(tài)為Locked
}
/// 確認收貨,這將會解鎖以太幣
function confirmReceived()
external
onlyBuyer
inState(State.Locked)
{
emit ItemReceived(); // 告知已收貨
// 首先更改狀態(tài)是很重要的,否則再次調用此函數,會再次發(fā)起transfer轉賬
state = State.Release;
// 留下貨款,取回押金
buyer.transfer(value);
}
/// 此函數給賣家退回押金和貨款
function refundSeller()
external
onlySeller
inState(State.Release)
{
emit SellerRefunded();
// 首先更改狀態(tài)是很重要的,否則再次調用此函數,會再次發(fā)起transfer轉賬
state = State.Inactive;
// 取回押金和貨款
seller.transfer(3 * value);
}
}
[solidity] 簡單的遠程購買合約
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
相關閱讀更多精彩內容
- 如果不了解MQTT的可以看這篇文章http://www.cnblogs.com/yangfengwu/p/7764...
- EVM 的作用是什么EVM 就是執(zhí)行智能合約字節(jié)碼指令的地方。通過 EVM 執(zhí)行智能合約來完成符合約束條件的交易,...
- 本項目使用vue+elementUI技術做前臺頁面,使用springboot+mybatis做后臺功能,并能整合阿...
- 轉自:https://learnblockchain.cn/2018/03/14/solidity-api/ So...