奇了,結婚也能寫成區塊鏈智能合約
阿新 • • 發佈:2018-12-13
可能 進行 aes art 流行 crypto pan sender extern
在下面的文章中,我將深入介紹“智能婚禮合約”的技術實施細節。 請記住,這是一個原型,因此產品功能可能並不齊全。
如果您對整體想法和概念感興趣,可以在這裏閱讀更多相關信息。
介紹
該項目基本上是使用Truffle Framework(Truffle,Ganache)、Web3和MetaMask完成。這是與以太坊進行通信的簡單Web前端構建的。
實現
一般的想法是建立一個婚姻合同的數字版本,參考過去的西方書面紙質結婚合同(中國似乎不流行),包含所有必要的功能,如管理資金和資產。 然而,我們希望這款產品不僅僅優先處理數字等價物,合同同樣也能處理資金,也能動態管理資產(這聽起來很花哨,但它很直接)。
現在讓我們來看看一些代碼。
合約部署
首先要做的是將新婚夫妻的錢包地址作為構造函數參數添加到合同中。 因為這些地址無法更改,所以這是最好的方法。
),這是保證高可靠性的去中心化存儲系統,兼容AWS S3的接口,並且能做到12個9地(99.9999999999%)保證文件不會丟失(具體原理可見《How decentralized storage is able to ensure that data is not lost》)。
在以太坊上存儲數據需要花費很多。 基於他們的黃紙存儲256字節需要20k的Gas。 我們假設PDF有100 kB:
100kB/256 bit = ~390 (256-bit words)
390 (256-bit words) * 20k (Gas) * 10 Gwei (gas price) = 0.078 ETH
想象一下,一個小文件存儲就要支付10美元以上。 如果你想上傳一個更大的文件,這可能很容易花費數百甚至數千美元。 我們只需要將文件的哈西上鏈(存儲在區塊鏈上),而不是將整個文件存儲在以太坊上。
簽名合約
成功部署合同並上傳IPFS哈希後,智能婚禮合約處於未簽名狀態。
const SmartWeddingContract = artifacts.require("./contracts/SmartWeddingContract.sol"); const husbandAddress = require("../config.js").husbandAddress; const wifeAddress = require("../config.js").wifeAddress; module.exports= function(deployer) { deployer.deploy(SmartWeddingContract, husbandAddress, wifeAddress); };
上傳可寫合約 您可能會問,既然我們的最終目標是創建一個優秀的數字合同版本,為什麽我們還要上傳一份書面合同。 原因是我們希望它能在法律背景下工作。 而現在,如果與一份簡單的舊書面法律文件沒有任何聯系,這在奧地利是不行的。 因此,書面合同是手工簽署的,並保存為PDF上傳到IPFS(去中心化存儲系統)。 該文件可以在這裏找到: 【解讀】:IPFS除非自己部署IPFS節點, 否則不能保證數據不丟失。因為IPFS是不帶有激勵性質的去中心化存儲系統。如果要保證文件不丟失,可以采用PP.IO(https://pp.io
modifier isSigned() { require(signed == true, "Contract has not been signed by both spouses yet!"); _; }
夫妻雙方必須首先使用私鑰對其進行簽名,以便調用更多功能。 這是由於isSigned修飾符在調用之前檢查合同的狀態。
function signContract() external onlySpouse { require(isSameString(writtenContractIpfsHash, ""), "Written contract ipfs hash has been proposed yet!"); require(hasSigned[msg.sender] == false, "Spouse has already signed the contract!"); // Sender簽名 hasSigned[msg.sender] = true; emit Signed(now, msg.sender); // 檢查夫妻雙方是否都已經簽名 if (hasSigned[husbandAddress] && hasSigned[wifeAddress]) { signed = true; emit ContractSigned(now); } }
signContract函數只能由夫妻調用。 “神奇”部分是最後的multisig。 if-clause 檢查丈夫和妻子是否簽署了合同。 如果是,則全局簽名狀態更改為true。
資產 資產,例如:汽車,房子、股票甚至是婚姻合約管理的主要內容,應聲明以下問題:- 誰擁有什麽?
- 離婚後會發生什麽?
function proposeAsset(string _data, uint _husbandAllocation, uint _wifeAllocation) external onlySpouse isSigned isNotDivorced { require(isSameString(_data, ""), "No asset data provided!"); require(_husbandAllocation >= 0, "Husband allocation invalid!"); require(_wifeAllocation >= 0, "Wife allocation invalid!"); require((_husbandAllocation + _wifeAllocation) == 100, "Total allocation must be equal to 100%!"); // 添加新資產 Asset memory newAsset = Asset({ data: _data, husbandAllocation: _husbandAllocation, wifeAllocation: _wifeAllocation, added: false, removed: false }); uint newAssetId = assets.push(newAsset); emit AssetProposed(now, _data, msg.sender); // 映射到存儲對象(否則無法訪問映射) Asset storage asset = assets[newAssetId - 1]; // Sender立刻批準 asset.hasApprovedAdd[msg.sender] = true; emit AssetAddApproved(now, _data, msg.sender); }
批準一個資產 在簽訂合約時,資產以相同的方式批準(使用multisig)。只有配偶雙方同意才能添加資產。
function approveAsset(uint _assetId) external onlySpouse isSigned isNotDivorced { require(_assetId > 0 && _assetId <= assets.length, "Invalid asset id!"); Asset storage asset = assets[_assetId - 1]; require(asset.added == false, "Asset has already been added!"); require(asset.removed == false, "Asset has already been removed!"); require(asset.hasApprovedAdd[msg.sender] == false, "Asset has already approved by sender!"); // Sender批準 asset.hasApprovedAdd[msg.sender] = true; emit AssetAddApproved(now, asset.data, msg.sender); // 檢查夫妻雙方是否都已批準 if (asset.hasApprovedAdd[husbandAddress] && asset.hasApprovedAdd[wifeAddress]) { asset.added = true; emit AssetAdded(now, asset.data); } }
刪除一個資產 同樣,雙方必須都同意才能刪除資產。
function removeAsset(uint _assetId) external onlySpouse isSigned isNotDivorced { require(_assetId > 0 && _assetId <= assets.length, "Invalid asset id!"); Asset storage asset = assets[_assetId - 1]; require(asset.added, "Asset has not been added yet!"); require(asset.removed == false, "Asset has already been removed!"); require(asset.hasApprovedRemove[msg.sender] == false, "Removing the asset has already been approved by the sender!"); // 批準 Sender 刪除 asset.hasApprovedRemove[msg.sender] = true; emit AssetRemoveApproved(now, asset.data, msg.sender); // 檢查夫妻雙方是否都批準移除資產 if (asset.hasApprovedRemove[husbandAddress] && asset.hasApprovedRemove[wifeAddress]) { asset.removed = true; emit AssetRemoved(now, asset.data); } }
合約作為儲蓄賬戶 智能婚禮合約也可以用作儲蓄賬戶。 它可以充當普通的以太坊錢包,這意味著它可以接收ETH。 並且通過支付功能,妻子和丈夫都可以通過這個錢包地址發送到另一個地址(例如,支付食物或假期,購買其他資產......)來花費這些ETH。
function() external payable isSigned isNotDivorced { emit FundsReceived(now, msg.sender, msg.value); }
這是默認功能。 重要的關鍵詞是可支付。 它使智能合約能夠獲得資金(ETH)。
function pay(address _to, uint _amount) external onlySpouse isSigned isNotDivorced { require(_to != address(0), "Sending funds to address zero is prohibited!"); require(_amount <= address(this).balance, "Not enough balance available!"); // 將資金發送到目的地地址 _to.transfer(_amount); emit FundsSent(now, _to, _amount); }
付費功能僅獲取目的地地址和要發送的金額。
離婚 也許最重要的功能是離婚後會發生的事情,這也是婚姻合同存在的原因之一。 離婚功能只能由配偶調用。和以前一樣,必須雙發都同意離婚。一旦雙方同意,合同狀態就會改變。 剩余的資金(ETH)被分成兩半並發送給每一方。function divorce() external onlySpouse isSigned isNotDivorced { require(hasDivorced[msg.sender] == false, "Sender has already approved to divorce!"); // Sender批準 hasDivorced[msg.sender] = true; emit DivorceApproved(now, msg.sender); // 檢查夫妻雙方是否都同意離婚 if (hasDivorced[husbandAddress] && hasDivorced[wifeAddress]) { divorced = true; emit Divorced(now); // 獲取合約的余額 uint balance = address(this).balance; // 將余額分成兩半 if (balance != 0) { uint balancePerSpouse = balance / 2; // 轉賬給原丈夫方 husbandAddress.transfer(balancePerSpouse); emit FundsSent(now, husbandAddress, balancePerSpouse); // 轉賬給原妻子方 wifeAddress.transfer(balancePerSpouse); emit FundsSent(now, wifeAddress, balancePerSpouse); } } }
在將合同狀態更改為離婚後,任何人都無法再與合同互動。 這是由於isNotDivorced修飾符在起作用。它被添加到所有關鍵功能中,以確保以後不能更改任何內容。
modifier isNotDivorced() { require(divorced == false, "Can not be called after spouses agreed to divorce!"); _; }事件 DApp使用了許多事件。幾乎在每種情況下都會發出它們,以便為前端應用程序創建正確的日誌。 每個事件還有一個時間戳變量。它僅顯示一個大致的時間。事件在web前端執行的時間。Web3也支持這一點,所以沒有必要記錄每個事件的時間戳,但是: Web3需要為每個事件異步查詢遠程以太坊節點(這看起來相當愚蠢) 但它是免費的(在Solidity事件中存儲數據不需要任何費用)
event WrittenContractProposed(uint timestamp, string ipfsHash, address wallet);
event Signed(uint timestamp, address wallet);
event ContractSigned(uint timestamp);
event AssetProposed(uint timestamp, string asset, address wallet);
event AssetAddApproved(uint timestamp, string asset, address wallet);
event AssetAdded(uint timestamp, string asset);
event AssetRemoveApproved(uint timestamp, string asset, address wallet);
event AssetRemoved(uint timestamp, string asset);
event DivorceApproved(uint timestamp, address wallet);
event Divorced(uint timestamp);
event FundsSent(uint timestamp, address wallet, uint amount);
event FundsReceived(uint timestamp, address wallet, uint amount);
智能婚禮合同部署在以太坊Ropsten測試網和以太坊主網上。
GitHub
完整的源代碼可在以下位置獲得: https://github.com/block42-blockchain-company/smart-wedding-contract
文章作者:Wayne Wong
轉載請註明出處
如果有關於PPIO的交流,可以通過下面的方式聯系我:
加我微信,註意備註來源
wechat:omnigeeker
奇了,結婚也能寫成區塊鏈智能合約