基于以太坊的次高价盲拍solidity智能合约(一)

1.功能描述

该合约主要功能描述如下:
用户A发起盲拍项目,即提出拍卖申请。

竞标原则

1.所有人都可以对任何一个盲拍项目发出拍卖申请。
2.竞拍用户每次出价都需要给出一个对外可见的价格(显式价格),同时给出一个自己心里认为可以接受的价格(隐式价格)。显式价格在竞拍阶段其他人是可以看见的,但是隐式价格别人看不见。因为这个隐式价格被该用户利用自己定的密码加密。即每个人竞标时输入两个数字和一个密码,隐式价格和密码直接在remix编辑器中以参数的形式输入,显式价格以value的形式将以太坊输入合约内。也就是说如果我想买这个东西准备花10eth,但是我想放出假话我要用12eth来买,我就要先将12eth打入这个合约内。
3.用户可以重复对一个商品进行多次竞拍(隐式价格可以改,但是你需要记住你最高的一次竞拍的密码和隐式价格),如果由于误操作导致隐式价格和密码两次都输入一样,那么第一次输入合约的以太坊将无法返还。这点需要注意!
4.显式价格必须大于隐式价格,否则在揭标的时候会被认作无效标。无效竞标可以提交,用于迷惑竞争者,揭标时系统会自动退款。
5.竞标成功的人最终会以合约内所有揭标后的次高价购买到商品(买家花费的钱比心理预期少,卖家至少会得到起拍价)。

揭标原则

1.只能在竞标仲裁之间进行
2.竞标者在揭标的相关函数中输入每个发起过的竞标的隐式价格和密码。这样每一次发起的竞标会由合约进行判断处理,如果不符合获胜条件会自动返回给竞标发起人。(如果两次竞标同一个隐式价格和密码,只能对最后一次的标进行揭标,前面标的钱将丢失在合约中无法退回)
3.揭标的时候会一直动态更新当前产品的最高价,次高价和出价人。这时候的所有价格都是隐式价格。由于这个时候已经无法竞标,所以公开隐式价格已经无所谓了,同时也可以让竞标成功者知道次高价为多少。
4.竞标失败的人会得到系统发回来的退款。
5.最高价的人得到显式价格与隐式价格的差额。剩余在合约内的前为隐式价格,到仲裁投票后会将与次高位出价的差额退回。
6.如果参与竞标但是未及时揭标,无法自动退款。所以揭标是必须要做的!

仲裁原则

1.仲裁者不允许是买家或竞标者,会有require()进行判断。

  1. 创建一个合约,将次高价金额、买家、卖家、仲裁人信息转到第该合约内。
  2. 仲裁结束后,将差额(最高价-次高价的)退还给竞标获胜的买家。

仲裁投票原则

1.只有卖家,竞标获胜者和仲裁者可以参与投票。每个人只能投票一次,投票有两个选择,一个是支持付款给卖家,一个是付款给买家。这个过程是为了防止卖家不发货,或者买家拿到东西不愿意付钱设置的。2.两个选择得到票数先到达两票时,合约会执行对应的付款行为。

我所使用的solidity编译器版本为0.5.0版本

代码实现

1.定义竞标商品结构

pragma solidity ^0.5.0;

contract Auction {
    uint productIndex;
    struct Product{
        uint id;
        string name;
        string category;
        //图片的链接
        string imageLink;
        //商品描述信息的链接
        string descLink;
        uint startPrice;
        uint revealStartTime;
        uint arbitrateStartTime;
        //商品的状态:竞标中,卖出成功,卖出失败
        ProductStatus status;
        //新的,或者二手的
        ProductCondition condition;
        //最高价格
        uint highestBid;
        //次高价格
        uint secondHighestBid;
        //最高出价者
        address payable highestBidder;
        //所有的竞标人数
        uint totalBids;
    }
    enum ProductStatus {OPEN,SOLD,UNSOLD}
    enum ProductCondition {USED,NEW}
}

2.卖家添加竞拍商品至商城

在合约中需要添加两个mapping结构,用于卖家-商品-商品id之间相互查找

 mapping(address=>mapping(uint=>Product)) stores;
 mapping(uint=>address payable) public productIdToOwmer;

添加函数

function addProductToStore(
   string memory _name,
   string memory _category,
   string memory _imageLink,
   string memory _descLink,
   uint _startPrice,
   uint _revealStartTime,
   uint _arbitrateStartTime,
   ProductCondition _condition) public{
       productIndex++;
       Product memory pro =  Product({
           id:productIndex,
           name:_name,
           category:_category,
           imageLink:_imageLink,
           descLink:_descLink,
           startPrice:_startPrice,
           revealStartTime:_revealStartTime,
           arbitrateStartTime:_arbitrateStartTime,
           status:ProductStatus.OPEN,
           condition:_condition,
           highestBid:0,
           secondHighestBid:0,
           highestBidder:address(0),
           totalBids:0
       });
       stores[msg.sender][productIndex]=pro;
       productIdToOwmer[productIndex]=msg.sender;
   }

3.竞标

定义标结构

struct Bid {
        //对应拍卖品的ID
        uint productId;
        //该标中的显式价格
        uint price2Show;
        //是否揭标标志位,为了保证每个标只能被揭一次
        bool isRevealed;
        //本次投标的投标人地址
        address bidder;
    }

由于每个人都可以对任何产品发起投标,所以我们需要为每个商品添加一个管理竞标的数据结构。
设计思路:由于不想对心里的隐式价格保密,同时还希望能找到自己能找到该标,别人找不到,设计数据结构如下:

mapping(address=>mapping(bytes32=>Bid)) bids;

address是竞标人地址,byte32是隐式价格和密码字符串packed后生成的哈希。这样,这有自己能找到该标。
注意:如果多次竞标时,输入与上次相同的隐式价格和密码,所对应的hash一样。这样导致key被覆盖,上一次的标就找不到了。这也是前面所提的,为什么输入相同的隐式价格和密码字符串时,上一次的竞标将丢失,里面的以太坊也将丢失在合约内无法退出的原因。
将该数据结构加入Product结构体

struct Product{
    ...
    mapping(address=>mapping(bytes32=>Bid)) bids;
    ...
    }

竞标函数

 function bid(uint _productIndex,uint _idealPrice,string memory _password) public payable{
        //对隐式价格和密码打包并求哈希    
        bytes memory bidInfo = abi.encodePacked(_idealPrice,_password);
        bytes32 bytesInfo = keccak256(bidInfo);
        //通过商品编号找到该拍卖商品的实例
        address owner = productIdToOwmer[_productIndex];
        Product storage product = stores[owner][_productIndex];
        //确保只能在揭标前发起竞标
         require(now<product.revealStartTime);
        product.totalBids++;
        //添加标进管理数据结构
        Bid memory b = Bid(_productIndex, msg.value, false, msg.sender);
        product.bids[msg.sender][bytesInfo]=b;
    }

此时可以写一些辅助函数来进行代码阶段性测试

    function getBidById(uint _productIndex,uint _idealPrice,string memory _password) public view returns(uint,uint,bool,address){
        address owner = productIdToOwmer[_productIndex];
        bytes memory bidInfo = abi.encodePacked(_idealPrice,_password);
        bytes32 bidBytes = keccak256(bidInfo);
        Product storage pro = stores[owner][_productIndex];
        Bid memory b = pro.bids[msg.sender][bidBytes];
        return (b.productId,b.price2Show,b.isRevealed,b.bidder);
    }

    function getBalance() public view returns(uint){
        return address(this).balance;
    }

ps:
本人热爱图灵,热爱中本聪,热爱V神,热爱一切被梨花照过的姑娘。
以下是我个人的公众号,如果有技术问题可以关注我的公众号来跟我交流。
同时我也会在这个公众号上每周更新我的原创文章,喜欢的小伙伴或者老伙计可以支持一下!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容