该内部合约用于卖家、买家、仲裁人对每一笔竞拍成功的交易进行投票,进行最后的支付操作。
合约结构如下:
contract Arbitration{
//仲裁人地址
address payable arbitrator;
//卖家地址
address payable seller;
//买家地址
address payable buyer;
//卖家获得票数
uint totalVotes2Seller;
//买家获得票数
uint totalVotes2Buyer;
//用于判断合约内的钱是否已经被支付给买家或者卖家
bool isSpent ;
//用于判断仲裁人、卖家和买家是否进行多次投票的数据结构
mapping(address=>bool) isAddressVoted;
constructor(address payable _arbitrator,address payable _seller,address payable _buyer) payable public {
arbitrator=_arbitrator;
seller=_seller;
buyer=_buyer;
}
}
辅助函数用于做代码阶段性测试:
function getBalance()public view returns(uint){
return address(this).balance;
}
function getAritrationInfo()public view returns(address,address,address,uint,uint){
return (arbitrator,seller,buyer,totalVotes2Seller,totalVotes2Buyer);
}
由于买家、卖家、仲裁人只可见主合约Auction。所以,我们要通过合约Auction中的方法,调用内部合约Arbitration中的方法来实现投票已经支付功能。
也就是说在合约Arbitration中完成投票和支付功能的实现,在合约Auction中实现函数的调用。
投票和支付功能函数
//修饰器,用于限定调用权限:只有仲裁人、卖家或者买家才可以投票
modifier callerLimit(address _operator){
require(_operator == arbitrator || _operator == seller || _operator == buyer);
_;
}
//投票给卖家
function vote2Seller(address _operator) public callerLimit(_operator) {
//保证该Arbitration是未支付过的
require(!isSpent);
//保证该投票者还没有投过票
require(!isAddressVoted[_operator]);
isAddressVoted[_operator]=true;
//支付功能:如果卖家得票数大于等于2,即合约把本次竞拍的以太坊转给卖家
if(++totalVotes2Seller==2){
isSpent=true;
seller.transfer(address(this).balance);
}
}
//投票给买家
function vote2Buyer(address _operator) public callerLimit(_operator) {
//保证该Arbitration是未支付过的
require(!isSpent);
//保证该投票者还没有投过票
require(!isAddressVoted[_operator]);
isAddressVoted[_operator]=true;
//支付功能:如果卖家得票数大于等于2,即合约把本次竞拍的以太坊转给买家
if(++totalVotes2Buyer==2){
isSpent=true;
buyer.transfer(address(this).balance);
}
}
功能函数实现之后,需要在主合约Auction中增添用户可以调用的函数接口:
contract Auction{
...
//投票给卖家
function vote2Seller(uint _productIndex)public {
//通过商品编号找到该商品对应的Arbitration实例
Arbitration arb=proIndex2Arbitration[_productIndex];
//调用合约内的功能函数
arb.vote2Seller(msg.sender);
}
//投票给买家
function vote2Buyer(uint _productIndex)public {
//通过商品编号找到该商品对应的Arbitration实例
Arbitration arb=proIndex2Arbitration[_productIndex];
//调用合约内的功能函数
arb.vote2Buyer(msg.sender);
}
}
同时编写辅助函数用于代码阶段性测试:
function getArbitrationInfo(uint _productIndex) public view returns(address ,address,address,uint,uint){
//利用商品编号找到对应的Arbitration实例
Arbitration arb = proIndex2Arbitration[_productIndex];
//然后通过合约Arbitration中的辅助函数来向主合约中返回信息
return arb.getAritrationInfo();
}
这样一个关于盲拍的智能合约功能就已经实现了。大家可以自己模拟一些用户在Remix编辑器中进行测试。
由于之前我是使用solidity 0.4.24版本的编译器,所以在版本5的代码语法上有许多变化的地方。
出于“强迫症”,本合约遇到的改动罗列如下:
一、
address payable xxx;
如果涉及到转账的地址,0.5.0版本必须在address关键字后追加payable关键字
二、
function fun1(string memory xxx) ..{}
定义函数时,0.5.5版本像string这样的引用类型后必须加memory,不能省略。
三、
Contract1 c1 = new Contract1;
0.4.24版本中,在合约内部创建其他合约实例的时候返回值可以用address类型变量来接收。但是在0.5.0版本中,必须以合约实例的变量来接受。
ps:
本人热爱图灵,热爱中本聪,热爱V神,热爱一切被梨花照过的姑娘。
以下是我个人的公众号,如果有技术问题可以关注我的公众号来跟我交流。
同时我也会在这个公众号上每周更新我的原创文章,喜欢的小伙伴或者老伙计可以支持一下!