如何编写一个拍卖的智能合约

您所在的位置:网站首页 上海健身器械公司排名榜 如何编写一个拍卖的智能合约

如何编写一个拍卖的智能合约

#如何编写一个拍卖的智能合约| 来源: 网络整理| 查看: 265

拍卖的方式有几种,其中有两种概念你需要先了解下,一种是公开拍卖(open auction),一种叫盲拍(blind auction)。简单来讲就是,前一种拍卖大家都能互相看到对方的出价,而后一种则看不到。

先看一个简单的公开拍卖。

contract SimpleAuction { //拍卖的受益人 address payable public beneficiary; //拍卖的结束时间 uint public auctionEndTime; // 最高出价的人 address public highestBidder; // 最高出价的价格 uint public highestBid; // 这个map用来存放出价的人以及对应的出价,便于拍卖结束后退还 mapping(address => uint) pendingReturns; //标识拍卖结束了,一旦结束就不能改了 bool ended;

payable表示这个地址可以接收以太币。因为存放的是受益人的地址当然是可以接受以太币的。uctionEndTime是一个时间戳变量,表示拍卖的结束时间。

// 用来记录当前出价最高的事件 event HighestBidIncreased(address bidder, uint amount); // 用来记录拍卖结束后 event AuctionEnded(address winner, uint amount);

这里是定义两个事件,用来记录状态的变更。

/// 拍卖已经结束 error AuctionAlreadyEnded(); /// 已经有更高的出价者了 error BidNotHighEnough(uint highestBid); /// 拍卖还未结束 error AuctionNotYetEnded(); /// auctionEnd 方法已经被调用了 error AuctionEndAlreadyCalled();

这里有几个之前没讲过的知识点,首先是注释用/// 三斜杠,这样的注释可以用来生成文档(natSpec)。这里只是一个简单的示例,还可以定义的很复杂,比如:

/// @title A simulator for trees /// @author Larry A. Gardner /// @notice You can use this contract for only the most basic simulation /// @dev All function calls are currently implemented without side effects /// @custom:experimental This is an experimental contract. contract Tree { /// @notice Calculate tree age in years, rounded up, for live trees /// @dev The Alexandr N. Tetearing algorithm could increase precision /// @param rings The number of rings from dendrochronological sample /// @return Age in years, rounded up for partial years function age(uint256 rings) external virtual pure returns (uint256) { return rings + 1; } /// @notice Returns the amount of leaves the tree has. /// @dev Returns only a fixed number. function leaves() external virtual pure returns(uint256) { return 2; } }

另外就是error关键字,我们可以用error来定义一个错误,然后当某个条件满足时,我们再用revert关键字报告一个错误,同时错误背后的原因通过natSpec做了解释。后面的代码会看到调用。

// 通过构造函数初始化受益人和拍卖的结束时间 constructor( uint biddingTime, address payable beneficiaryAddress ) { beneficiary = beneficiaryAddress; auctionEndTime = block.timestamp + biddingTime; }

block.timestamp 向合约提供当前区块的时间戳。

function bid() external payable { if (block.timestamp > auctionEndTime) revert AuctionAlreadyEnded(); if (msg.value 0) { pendingReturns[msg.sender] = 0; if (!payable(msg.sender).send(amount)) { // No need to call throw here, just reset the amount owing pendingReturns[msg.sender] = amount; return false; } } return true; }

拍卖结束后,没有赢得最终拍卖的那些出价者需要有一个接口进行退款,就是这个withdraw方法。payable(msg.sender).send这句的意思是将以太币发送回调用者的地址。用payable修饰表示这个地址可以接收以太币。

function auctionEnd() external { if (block.timestamp < auctionEndTime) revert AuctionNotYetEnded(); if (ended) revert AuctionEndAlreadyCalled(); ended = true; emit AuctionEnded(highestBidder, highestBid); beneficiary.transfer(highestBid); }

调用这个方法可以结束拍卖。前面先进行检查,看是否满足结束的条件。如果满足就更新状态并且记录日志。最后就是把拍卖的钱转给受益人。

我们把这段程序放在remix运行下,看看效果。

首先传入一个结束时间和受益人地址进行初始化。

在这里插入图片描述

我这里设置的受益人地址说:0x5B38Da6a701c568545dCfcB03FcB875f56beddC4

获取下变量的初始值看看,

在这里插入图片描述

看着都没啥问题。我们现在模拟一次出价,点击bid方法,然后value那里我们先默认用0,点击后发现报错:

[vm]from: 0x5B3...eddC4to: SimpleAuction.bid() 0xD7A...F771Bvalue: 0 weidata: 0x199...8aeeflogs: 0hash: 0x9b7...a19d1 transact to SimpleAuction.bid errored: VM error: revert. revert The transaction has been reverted to the initial state. Error provided by the contract: BidNotHighEnough : 已经有更高的出价者了 Parameters: { "highestBid": { "value": "0" } }

有没有注意到,我们通过注释的写的error的描述,在错误出现的时候打印出来了。这样验证了我们前面的内容。

我么首先让用户a(地址是:0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2)出价11 wei,然后让用户b (地址是:0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db)出价 20 wei,你会看到出价成功后对应的地址上的余额就会减少(同时也会扣除gas fee)。

点击拍卖结束后,受益人的地址上余额就会增加。同时我们可以选择对应的没有拍卖成功的出价人的地址,然后点击withdraw,他的出价会返回来。

参考:

docs.soliditylang.org/en/v0.8.10/…


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3