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

1.功能描述

該合約主要功能描述如下:
用戶A發(fā)起盲拍項目赡盘,即提出拍賣申請。

競標(biāo)原則

1.所有人都可以對任何一個盲拍項目發(fā)出拍賣申請。
2.競拍用戶每次出價都需要給出一個對外可見的價格(顯式價格)森逮,同時給出一個自己心里認(rèn)為可以接受的價格(隱式價格)妖谴。顯式價格在競拍階段其他人是可以看見的,但是隱式價格別人看不見酵熙。因為這個隱式價格被該用戶利用自己定的密碼加密轧简。即每個人競標(biāo)時輸入兩個數(shù)字和一個密碼,隱式價格和密碼直接在remix編輯器中以參數(shù)的形式輸入匾二,顯式價格以value的形式將以太坊輸入合約內(nèi)哮独。也就是說如果我想買這個東西準(zhǔn)備花10eth,但是我想放出假話我要用12eth來買察藐,我就要先將12eth打入這個合約內(nèi)皮璧。
3.用戶可以重復(fù)對一個商品進行多次競拍(隱式價格可以改,但是你需要記住你最高的一次競拍的密碼和隱式價格)分飞,如果由于誤操作導(dǎo)致隱式價格和密碼兩次都輸入一樣悴务,那么第一次輸入合約的以太坊將無法返還。這點需要注意譬猫!
4.顯式價格必須大于隱式價格讯檐,否則在揭標(biāo)的時候會被認(rèn)作無效標(biāo)。無效競標(biāo)可以提交染服,用于迷惑競爭者别洪,揭標(biāo)時系統(tǒng)會自動退款。
5.競標(biāo)成功的人最終會以合約內(nèi)所有揭標(biāo)后的次高價購買到商品(買家花費的錢比心理預(yù)期少柳刮,賣家至少會得到起拍價)挖垛。

揭標(biāo)原則

1.只能在競標(biāo)仲裁之間進行
2.競標(biāo)者在揭標(biāo)的相關(guān)函數(shù)中輸入每個發(fā)起過的競標(biāo)的隱式價格和密碼痒钝。這樣每一次發(fā)起的競標(biāo)會由合約進行判斷處理,如果不符合獲勝條件會自動返回給競標(biāo)發(fā)起人晕换。(如果兩次競標(biāo)同一個隱式價格和密碼午乓,只能對最后一次的標(biāo)進行揭標(biāo),前面標(biāo)的錢將丟失在合約中無法退回)
3.揭標(biāo)的時候會一直動態(tài)更新當(dāng)前產(chǎn)品的最高價闸准,次高價和出價人益愈。這時候的所有價格都是隱式價格。由于這個時候已經(jīng)無法競標(biāo)夷家,所以公開隱式價格已經(jīng)無所謂了蒸其,同時也可以讓競標(biāo)成功者知道次高價為多少。
4.競標(biāo)失敗的人會得到系統(tǒng)發(fā)回來的退款库快。
5.最高價的人得到顯式價格與隱式價格的差額摸袁。剩余在合約內(nèi)的前為隱式價格,到仲裁投票后會將與次高位出價的差額退回义屏。
6.如果參與競標(biāo)但是未及時揭標(biāo)靠汁,無法自動退款。所以揭標(biāo)是必須要做的闽铐!

仲裁原則

1.仲裁者不允許是買家或競標(biāo)者蝶怔,會有require()進行判斷。

  1. 創(chuàng)建一個合約兄墅,將次高價金額踢星、買家、賣家隙咸、仲裁人信息轉(zhuǎn)到第該合約內(nèi)沐悦。
  2. 仲裁結(jié)束后,將差額(最高價-次高價的)退還給競標(biāo)獲勝的買家五督。

仲裁投票原則

1.只有賣家藏否,競標(biāo)獲勝者和仲裁者可以參與投票。每個人只能投票一次充包,投票有兩個選擇秕岛,一個是支持付款給賣家,一個是付款給買家误证。這個過程是為了防止賣家不發(fā)貨继薛,或者買家拿到東西不愿意付錢設(shè)置的。2.兩個選擇得到票數(shù)先到達兩票時愈捅,合約會執(zhí)行對應(yīng)的付款行為遏考。

我所使用的solidity編譯器版本為0.5.0版本

代碼實現(xiàn)

1.定義競標(biāo)商品結(jié)構(gòu)

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;
        //商品的狀態(tài):競標(biāo)中,賣出成功蓝谨,賣出失敗
        ProductStatus status;
        //新的灌具,或者二手的
        ProductCondition condition;
        //最高價格
        uint highestBid;
        //次高價格
        uint secondHighestBid;
        //最高出價者
        address payable highestBidder;
        //所有的競標(biāo)人數(shù)
        uint totalBids;
    }
    enum ProductStatus {OPEN,SOLD,UNSOLD}
    enum ProductCondition {USED,NEW}
}

2.賣家添加競拍商品至商城

在合約中需要添加兩個mapping結(jié)構(gòu)青团,用于賣家-商品-商品id之間相互查找

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

添加函數(shù)

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.競標(biāo)

定義標(biāo)結(jié)構(gòu)

struct Bid {
        //對應(yīng)拍賣品的ID
        uint productId;
        //該標(biāo)中的顯式價格
        uint price2Show;
        //是否揭標(biāo)標(biāo)志位,為了保證每個標(biāo)只能被揭一次
        bool isRevealed;
        //本次投標(biāo)的投標(biāo)人地址
        address bidder;
    }

由于每個人都可以對任何產(chǎn)品發(fā)起投標(biāo)咖楣,所以我們需要為每個商品添加一個管理競標(biāo)的數(shù)據(jù)結(jié)構(gòu)督笆。
設(shè)計思路:由于不想對心里的隱式價格保密,同時還希望能找到自己能找到該標(biāo)诱贿,別人找不到娃肿,設(shè)計數(shù)據(jù)結(jié)構(gòu)如下:

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

address是競標(biāo)人地址,byte32是隱式價格和密碼字符串packed后生成的哈希珠十。這樣料扰,這有自己能找到該標(biāo)。
注意:如果多次競標(biāo)時焙蹭,輸入與上次相同的隱式價格和密碼晒杈,所對應(yīng)的hash一樣。這樣導(dǎo)致key被覆蓋孔厉,上一次的標(biāo)就找不到了拯钻。這也是前面所提的,為什么輸入相同的隱式價格和密碼字符串時撰豺,上一次的競標(biāo)將丟失粪般,里面的以太坊也將丟失在合約內(nèi)無法退出的原因。
將該數(shù)據(jù)結(jié)構(gòu)加入Product結(jié)構(gòu)體

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

競標(biāo)函數(shù)

 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];
        //確保只能在揭標(biāo)前發(fā)起競標(biāo)
         require(now<product.revealStartTime);
        product.totalBids++;
        //添加標(biāo)進管理數(shù)據(jù)結(jié)構(gòu)
        Bid memory b = Bid(_productIndex, msg.value, false, msg.sender);
        product.bids[msg.sender][bytesInfo]=b;
    }

此時可以寫一些輔助函數(shù)來進行代碼階段性測試

    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神姿搜,熱愛一切被梨花照過的姑娘寡润。
以下是我個人的公眾號,如果有技術(shù)問題可以關(guān)注我的公眾號來跟我交流舅柜。
同時我也會在這個公眾號上每周更新我的原創(chuàng)文章梭纹,喜歡的小伙伴或者老伙計可以支持一下!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末致份,一起剝皮案震驚了整個濱河市变抽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌氮块,老刑警劉巖绍载,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異滔蝉,居然都是意外死亡击儡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門蝠引,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阳谍,“玉大人蛀柴,你說我怎么就攤上這事〗煤唬” “怎么了鸽疾?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長训貌。 經(jīng)常有香客問我制肮,道長,這世上最難降的妖魔是什么旺订? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任弄企,我火速辦了婚禮,結(jié)果婚禮上区拳,老公的妹妹穿的比我還像新娘拘领。我一直安慰自己,他們只是感情好樱调,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布约素。 她就那樣靜靜地躺著,像睡著了一般笆凌。 火紅的嫁衣襯著肌膚如雪圣猎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天乞而,我揣著相機與錄音送悔,去河邊找鬼。 笑死爪模,一個胖子當(dāng)著我的面吹牛欠啤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播屋灌,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼洁段,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了共郭?” 一聲冷哼從身側(cè)響起祠丝,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎除嘹,沒想到半個月后写半,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡尉咕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年叠蝇,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片龙考。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蟆肆,死狀恐怖矾睦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情炎功,我是刑警寧澤枚冗,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蛇损,受9級特大地震影響赁温,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜淤齐,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一股囊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧更啄,春花似錦稚疹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至义锥,卻和暖如春柳沙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拌倍。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工赂鲤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人柱恤。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓数初,卻偏偏與公主長得像,于是被迫代替她去往敵國和親膨更。 傳聞我的和親對象是個殘疾皇子妙真,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容