拍得到智能合约流程
先把逻辑捋顺再看代码
竞标规则
-
仅可在竞标时间段内竞标,竞标结束后⽆法再次竞标,竞标⻚⾯关闭
-
每个⼈都可以参与竞标。(卖家⾃⼰也可以参与竞标)
-
每个⼈可以多次对同⼀产品竞标。(我可以看到别⼈⽐我⾼的时候,再次出价;可以使⽤战略, 多次出价迷惑敌⼈)
-
流程:
每个⼈竞标时输⼊两个数字和⼀个密码:
迷惑价格:30元(打到合约的⾦额,后⾯揭标时会退还差价,公开)
理想出价:10元(隐秘,不会在竞标函数中作为显示参数传⼊)
密码字符串(隐秘)
系统记录相关信息
迷惑价格必须⼤于理想价格时,否则视为⽆效竞标,⽆效竞标可以提交,⽤于迷惑竞争者,揭标 时⾃动退款。
竞标成功的⼈最终会以 次⾼价 购买商品(买家花费的钱⽐⼼理预期少,卖家⾄少会得到起拍 价)。
-
揭标规则
-
仅限于 竞标结束 和 终结拍卖 之前这段时间内完成
-
流程: i. 每个⼈输⼊⼀个数字和⼀个密码: i. 理想出价(同竞标时的数字) ii. 密码(同竞标时的字符串) ii. 揭标时会⼀直动态更新产品的最⾼的出价⼈、最⾼价、次⾼价格。 iii. 淘汰的⼈得到退款(当初转⼊的 迷惑价格 )。 iv. 最⾼价的⼈得到迷惑价格与理想出价的差额。
-
如果参与竞标但是未及时揭标,⽆法⾃动退款
-
终结竞拍规则
-
由任意⼀个第三⽅的⼈来执⾏终结。
-
流程: i. 创建⼀个 第三⽅合约 ,将次⾼价⾦额、买家、卖家、仲裁⼈信息转⼊到第三⽅合约。 ii. 转差额(最⾼价-次⾼价的)给买家。
-
对第三⽅合约投票
-
合约中含有买家,卖家,仲裁⼈,次⾼价⾦额。
-
仅这三个⼈可以进⾏投票,且每⼈⼀票。
-
票数达到两票的⼈获得合约中的⾦额,拍卖结束
1.定义商品结构
struct Product {
//
uint id; //商品唯一id
string name;//商品名称
string category;//商品类别
string imageLink;//ipfs-->图片链接
string descLink;//ipfs-->商品描述信息链接
uint startPrice;//竞拍起始价格
uint auctionStartTime;//竞拍开始时间
uint auctionEndTime;//竞拍结束时间
ProductStatus status;
ProductCondition condition;
//竞标信息
uint highestBid; //最高出价, 50,理想价格
address highestBidder; //最高出价人
uint secondHighestBid; //次高价,40
uint totalBids; //所有的竞标数量
}
enum ProductStatus {
Open, Sold, Unsold} //竞标中,卖了,没卖出
enum ProductCondition {
Used, New} 新的,旧的
2.存储商品结构
mapping(卖家地址address => mapping(产品id => 产品Product)) stores
mapping(产品id => 卖家地址address) productToOwner
3.添加商品函数
function addProductToStore(string _name, string _category, string _imageLink, string _descLink, uint _startTime, uint _endTime, uint _startPrice, uint condition) public {
productIndex++; //全局唯一
Product memory product = Product({
id : productIndex,
name : _name,
category : _category,
imageLink : _imageLink,
descLink : _descLink,
startPrice : _startPrice,
auctionStartTime : _startTime,
auctionEndTime : _endTime,
status : ProductStatus.Open,
condition : ProductCondition(condition)
highestBid: 0,
highestBidder : 0,
secondHighestBid : 0,
totalBids : 0
});
//把创建好的商品添加到我们的商店结构中
stores[msg.sender][productIndex] = product;
productIdToOwner[productIndex] = msg.sender;
}
}
4.通过商品id获取商品信息
function getProductById(uint _productId) public view returns (uint, string, string, string, string, uint, uint, uint, uint){
//通过id向定义的两个mapping结构中查询并返回
address owner = productIdToOwner[_productId];
Product memory product = stores[owner][_productId];
return (
product.id, product.name, product.category, product.imageLink, product.descLink,
product.auctionStartTime, product.auctionEndTime, product.startPrice, uint(product.status)
);
5.定义竞标结构
struct Bid {
uint productId;//产品id
uint price; //迷惑价格,不是理想价格
bool isRevealed;//是否揭标
address bidder;//竞标人
}
6.在Product中增加存储所有合约自己相关竞标的结构
// 存储所有的竞标人对这个商品的竞标(与stroes类似)
mapping(address => mapping(bytes32 => Bid)) bids;
7.添加竞标函数bid
function bid(uint _productId, uint _idealPrice, string _secret) public payable {
//将传入的理想价格和明文进行keccak256加密成密文
bytes memory bytesInfo = abi.encodePacked(_idealPrice, _secret);
bytes32 bytesHash = keccak256(bytesInfo);
//通过id获取商品信息
address owner = productIdToOwner[_productId];
Product storage product = stores[owner][_productId];
//每一个竞标必须大于等于起始价格
require(msg.value >= product.startPrice);
//竞标总数+1
product.totalBids++;
//存储竞标人对这个商品的竞标
Bid memory bidLocal = Bid(_productId, msg.value, false, msg.sender);
product.bids[msg.sender][bytesHash] = bidLocal;
}
8.验证竞标
//获取指定的bid信息
function getBidById(uint _productId, uint _idealPrice, string _secret) public view returns (uint, uint, bool, address) {
//通过id获取商品信息
address owner = productIdToOwner[_productId];
Product storage product = stores[owner][_productId];
//通过参数生成密文
bytes memory bytesInfo = abi.encodePacked(_idealPrice, _secret);
bytes32 bytesHash = keccak256(bytesInfo);
//从竞标mapping取出竞标信息并返回
Bid memory bidLocal = product.bids[msg.sender][bytesHash];
return (bidLocal.productId, bidLocal.price, bidLocal.isRevealed, bidLocal.bidder);
}
9.揭标
//揭标事件,做log日志返回给客户端
event revealEvent(uint productid, bytes32 bidId, uint idealPrice, uint price, uint refund);
function revealBid(uint _productId, uint _idealPrice, string _secret) public {
//通过id取商品信息
address owner = productIdToOwner[_productId