智能合约经典代码实战(一)——盲拍合约

由于学业上的需求,所以速成了一波Solidity。紧接着我会进行几篇经典代码的实战笔记的撰写,主要是写一些复现过程中出现的问题,以作记录。小白一枚,合理探讨,大佬勿喷……

合约使用场景:当我们需要对某一件事物进行竞拍的时候,存在一种盲拍的方式。也就是说,所有有资格出价竞拍的用户在规定时间内都可以进行出价,但是价格都是不对外公开的,只有等竞拍到时间才会公布获胜者以及出价金额,其余代币会返回给发送者。

在线IDE:Remix

 

pragma solidity ^0.7.0;  //不知道什么原因,原文给的版本,我的remix不识别address payable,所以调高了solc版本,相应的一些全局变量会有一些更改,不影响大局。

contract BlindAuction {
   //竞拍者:盲拍所递交的加密代码+msg.value(货币) struct Bid { bytes32 blindedBid; uint deposit; }   //可支付地址,即可以使用transfer这样一类的交易函数 address payable public beneficiary;
  //竞拍截止时间 uint public biddingEnd;
  //明牌截止时间 uint public revealEnd;
  //本次拍卖结束标志 bool public ended;
  //通过Hash将地址与Bid结构的竞拍者信息进行映射 mapping(address => Bid[]) public bids;
  //最高价者 address public highestBidder;
  //最高价 uint public highestBid;
  //为了方便返款,通过映射的方式记录 mapping(address => uint) pendingReturns;   //当竞拍结束后,会调用这个事件,记录到区块链中 event AuctionEnded(address winner, uint highestBid);   //修改器,用来限制时间 modifier onlyBefore(uint _time) { require(block.timestamp < _time); _; } modifier onlyAfter(uint _time) { require(block.timestamp > _time); _; }   //用来创建一个竞拍合约的 constructor ( uint _biddingTime, uint _revealTime, address payable _beneficiary ) payable public { beneficiary = _beneficiary; biddingEnd = block.timestamp + _biddingTime; revealEnd = biddingEnd + _revealTime; }   //竞拍函数:这里要详细说的一个点就是竞拍者将竞拍价格+fake属性+密钥通过keccak256进行编码加密。着重说明的是fake为false时是真正报价,fake为true时是用来迷惑其他报价者混淆真实数据。 function bid(bytes32 _blindedBid) public payable onlyBefore(biddingEnd) {
    //因为每个用户可以多次进行输入价格,所以每个地址所映射的用户有一个Bid结构数组用来存储相关数据。 bids[msg.sender].push(Bid({ blindedBid: _blindedBid, deposit: msg.value })); }   //明牌函数 function reveal( uint[] memory _values, bool[] memory _fake, bytes32[] memory _secret ) public onlyAfter(biddingEnd) onlyBefore(revealEnd) {
    //做相应的限制,要求数据的统一 uint length = bids[msg.sender].length; require(_values.length == length); require(_fake.length == length); require(_secret.length == length);     //返款总数 uint refund;
    //遍历账户下每一个出款记录,在保证数据的正确情况下将所有价格总计起来返还 for (uint i = 0; i < length; i++) { Bid storage bidToCheck = bids[msg.sender][i]; (uint value, bool fake, bytes32 secret) = (_values[i], _fake[i], _secret[i]); if (bidToCheck.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) { continue; } refund += bidToCheck.deposit;
        //这里主要是用来判断资金是否充足,是否是更高价以用来更改数据 if (!fake && bidToCheck.deposit >= value) { if (placeBid(msg.sender, value)) refund -= value; }
        //先更改合约数据 bidToCheck.blindedBid = bytes32(0); }
      //再进行货币交易,防止重复还款 msg.sender.transfer(refund); }     //内部函数,用来出价的,选择最高价 function placeBid(address bidder, uint value) internal returns (bool success) { if (value <= highestBid) { return false; } if (highestBidder != address(0)) { pendingReturns[highestBidder] += highestBid; } highestBid = value; highestBidder = bidder; return true; }     //退款函数,还是要注意先判断条件、再修改内部状态数据、最后进行货币交易 function withdraw() public { uint amount = pendingReturns[msg.sender]; if (amount > 0) { pendingReturns[msg.sender] = 0; msg.sender.transfer(amount); } }     //竞拍事件结束,修改竞拍事件状态,发送事件宣布结果,并最后发送款项给受益方 function auctionEnd() public onlyAfter(revealEnd) { require(!ended); emit AuctionEnded(highestBidder, highestBid); ended = true; beneficiary.transfer(highestBid); } }

 

上一篇:Angular 应用级别的依赖 Fake


下一篇:[hdu7044]Fall with Fake Problem