0x-start-project源码学习 - 8

还有一种场景的叫做dutchAuction,翻译时荷兰式拍卖,也就是减价拍卖,由卖家给出开始拍卖的价格以及最低价格,随着时间价格会一路走低,一直到最低拍卖价。
在0x中这种交易其实也是由match order的方式完成,不过实时价格由拍卖合约确定

1
2
const auctionDetails = await contractWrappers.dutchAuction.getAuctionDetailsAsync(sellSignedOrder);
const currentAuctionAmount = auctionDetails.currentAmount;

卖家通过确定拍卖资产,拍卖金额,拍卖开始时间,通过dutchAuctionWrapper.encodeDutchAuctionAssetData将数据打包为拍卖资产,将拍卖资产的订单签名发布。之后由买方通过contractWrappers.dutchAuction获取实时拍卖价格,创建买方订单并进行签名,通过match order完成订单交易。

具体场景源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
PrintUtils.printScenario('Dutch Auction');
// Initialize the ContractWrappers, this provides helper functions around calling
// 0x contracts as well as ERC20/ERC721 token contracts on the blockchain
const contractWrappers = new ContractWrappers(providerEngine, { networkId: NETWORK_CONFIGS.networkId });
// Initialize the Web3Wrapper, this provides helper functions around fetching
// account information, balances, general contract logs
const web3Wrapper = new Web3Wrapper(providerEngine);
// 获得卖方,买方地址
const [sellMaker, buyMaker] = await web3Wrapper.getAvailableAddressesAsync();
const zrxTokenAddress = contractAddresses.zrxToken;
const etherTokenAddress = contractAddresses.etherToken;
const printUtils = new PrintUtils(
web3Wrapper,
contractWrappers,
{ sellMaker, buyMaker },
{ WETH: etherTokenAddress, ZRX: zrxTokenAddress },
);
printUtils.printAccounts();
// the amount the maker is selling of maker asset
const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS);
// the initial opening price of the auction
// 拍卖初始金额
const auctionBeginAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS);
// the final amount at the end of the auction
// 拍卖下限金额
const auctionEndAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(0.1), DECIMALS);
// 0x v2 uses hex encoded asset data strings to encode all the information needed to identify an asset
// 设置交易资产
const makerAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress);
const takerAssetData = assetDataUtils.encodeERC20AssetData(etherTokenAddress);
// Begin the auction ten minutes ago
// 10分钟前秒数
const auctionBeginTimeSeconds = new BigNumber(Date.now() - TEN_MINUTES_MS)
.div(ONE_SECOND_MS)
.integerValue(BigNumber.ROUND_CEIL);
// Additional data is encoded in the maker asset data, this includes the begin time and begin amount
// for the auction
// 生成拍卖数据,资产类型,开始拍卖时间,开始拍卖金额
const dutchAuctionEncodedAssetData = DutchAuctionWrapper.encodeDutchAuctionAssetData(
makerAssetData,
auctionBeginTimeSeconds,
auctionBeginAmount,
);
let txHash;
let txReceipt;
// Allow the 0x ERC20 Proxy to move ZRX on behalf of makerAccount
// 对0x进行资产授权
const sellMakerZRXApprovalTxHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
zrxTokenAddress,
sellMaker,
);
await printUtils.awaitTransactionMinedSpinnerAsync('Sell Maker ZRX Approval', sellMakerZRXApprovalTxHash);
// Approve the ERC20 Proxy to move WETH for rightMaker
const buyMakerWETHApprovalTxHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
etherTokenAddress,
buyMaker,
);
await printUtils.awaitTransactionMinedSpinnerAsync('Buy Maker WETH Approval', buyMakerWETHApprovalTxHash);
// Convert ETH into WETH for taker by depositing ETH into the WETH contract
const buyMakerWETHDepositTxHash = await contractWrappers.etherToken.depositAsync(
etherTokenAddress,
auctionBeginAmount,
buyMaker,
);
await printUtils.awaitTransactionMinedSpinnerAsync('Buy Maker WETH Deposit', buyMakerWETHDepositTxHash);
PrintUtils.printData('Setup', [
['Sell Maker ZRX Approval', sellMakerZRXApprovalTxHash],
['Buy Maker WETH Approval', buyMakerWETHApprovalTxHash],
['Buy Maker WETH Deposit', buyMakerWETHDepositTxHash],
]);
// Set up the Order and fill it
// 生成订单过期时间
// 生成交易地址
const randomExpiration = getRandomFutureDateInSeconds();
const exchangeAddress = contractAddresses.exchange;
// Create the order
// 创建买方订单
const sellOrder: Order = {
exchangeAddress,
makerAddress: sellMaker,
// taker address is specified to ensure ONLY the dutch auction contract
// can fill this order (ensuring the price given the block time)
// taker地址为拍卖合约地址
takerAddress: contractWrappers.dutchAuction.address,
senderAddress: NULL_ADDRESS,
feeRecipientAddress: NULL_ADDRESS,
expirationTimeSeconds: randomExpiration,
salt: generatePseudoRandomSalt(),
makerAssetAmount,
// taker asset amount is the auction end price. The Dutch Auction
// contract ensures this is filled at the correct amount
// taker资产金额为拍卖下限金额
takerAssetAmount: auctionEndAmount,
// maker asset data is encoded with additional data used by
// the Dutch Auction contract
// 卖方资产为包含拍卖信息
makerAssetData: dutchAuctionEncodedAssetData,
takerAssetData,
makerFee: ZERO,
takerFee: ZERO,
};
PrintUtils.printData('Sell Order', Object.entries(sellOrder));
// Generate the order hash and sign it
// 对订单进行签名
const sellOrderHashHex = orderHashUtils.getOrderHashHex(sellOrder);
const sellOrderSignature = await signatureUtils.ecSignHashAsync(providerEngine, sellOrderHashHex, sellMaker);
const sellSignedOrder = { ...sellOrder, signature: sellOrderSignature };
// Create the buy order
// 因为价格随时间变化,通过getAuctionDetailsAsyn获取当前的价格信息
const auctionDetails = await contractWrappers.dutchAuction.getAuctionDetailsAsync(sellSignedOrder);
const currentAuctionAmount = auctionDetails.currentAmount;
// The buyer creates a matching order, specifying the current auction amount
// 创建买方订单
const buyOrder: Order = {
...sellOrder,
makerAddress: buyMaker,
makerAssetData: sellOrder.takerAssetData,
takerAssetData: sellOrder.makerAssetData,
makerAssetAmount: currentAuctionAmount,
takerAssetAmount: sellOrder.makerAssetAmount,
};
PrintUtils.printData('Buy Order', Object.entries(buyOrder));
// Generate the order hash and sign it
// 签名买方订单
const buyOrderHashHex = orderHashUtils.getOrderHashHex(buyOrder);
const buyOrderSignature = await signatureUtils.ecSignHashAsync(providerEngine, buyOrderHashHex, buyMaker);
const buySignedOrder = { ...buyOrder, signature: buyOrderSignature };
// Print out the Balances and Allowances
await printUtils.fetchAndPrintContractAllowancesAsync();
await printUtils.fetchAndPrintContractBalancesAsync();
// Match the orders via the Dutch Auction contract
// 通过匹配订单完成交易
txHash = await contractWrappers.dutchAuction.matchOrdersAsync(buySignedOrder, sellSignedOrder, buyMaker, {
gasLimit: TX_DEFAULTS.gas,
});
txReceipt = await printUtils.awaitTransactionMinedSpinnerAsync('DutchAuction', txHash);
printUtils.printTransaction('DutchAuction', txReceipt, [
['sell orderHash', sellOrderHashHex],
['buy orderHash', buyOrderHashHex],
]);
// Print the Balances
await printUtils.fetchAndPrintContractBalancesAsync();
// Stop the Provider Engine
providerEngine.stop();