Dutch Auction Contract Wrapper
This commit is contained in:
parent
7dda953bc9
commit
c850046ea0
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "1.2.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added Dutch Auction Wrapper",
|
||||||
|
"pr": 1465
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -29,13 +29,13 @@ import { RevertReason, SignedOrder } from '@0x/types';
|
|||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import ethAbi = require('ethereumjs-abi');
|
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { DutchAuctionContract } from '../../generated-wrappers/dutch_auction';
|
import { DutchAuctionContract } from '../../generated-wrappers/dutch_auction';
|
||||||
import { artifacts } from '../../src/artifacts';
|
import { artifacts } from '../../src/artifacts';
|
||||||
|
|
||||||
|
import { DutchAuctionWrapper } from '../utils/dutch_auction_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
@ -68,19 +68,9 @@ describe(ContractName.DutchAuction, () => {
|
|||||||
let erc721MakerAssetIds: BigNumber[];
|
let erc721MakerAssetIds: BigNumber[];
|
||||||
const tenMinutesInSeconds = 10 * 60;
|
const tenMinutesInSeconds = 10 * 60;
|
||||||
|
|
||||||
function extendMakerAssetData(makerAssetData: string, beginTimeSeconds: BigNumber, beginAmount: BigNumber): string {
|
let dutchAuctionInstance: DutchAuctionContract;
|
||||||
return ethUtil.bufferToHex(
|
let dutchAuctionWrapper: DutchAuctionWrapper;
|
||||||
Buffer.concat([
|
let defaultMakerAssetData: string;
|
||||||
ethUtil.toBuffer(makerAssetData),
|
|
||||||
ethUtil.toBuffer(
|
|
||||||
(ethAbi as any).rawEncode(
|
|
||||||
['uint256', 'uint256'],
|
|
||||||
[beginTimeSeconds.toString(), beginAmount.toString()],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await blockchainLifecycle.startAsync();
|
await blockchainLifecycle.startAsync();
|
||||||
@ -136,6 +126,7 @@ describe(ContractName.DutchAuction, () => {
|
|||||||
dutchAuctionInstance.address,
|
dutchAuctionInstance.address,
|
||||||
provider,
|
provider,
|
||||||
);
|
);
|
||||||
|
dutchAuctionWrapper = new DutchAuctionWrapper(dutchAuctionInstance, provider);
|
||||||
|
|
||||||
defaultMakerAssetAddress = erc20TokenA.address;
|
defaultMakerAssetAddress = erc20TokenA.address;
|
||||||
const defaultTakerAssetAddress = wethContract.address;
|
const defaultTakerAssetAddress = wethContract.address;
|
||||||
@ -174,7 +165,7 @@ describe(ContractName.DutchAuction, () => {
|
|||||||
feeRecipientAddress,
|
feeRecipientAddress,
|
||||||
// taker address or sender address should be set to the ducth auction contract
|
// taker address or sender address should be set to the ducth auction contract
|
||||||
takerAddress: dutchAuctionContract.address,
|
takerAddress: dutchAuctionContract.address,
|
||||||
makerAssetData: extendMakerAssetData(
|
makerAssetData: assetDataUtils.encodeDutchAuctionAssetData(
|
||||||
assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
||||||
auctionBeginTimeSeconds,
|
auctionBeginTimeSeconds,
|
||||||
auctionBeginAmount,
|
auctionBeginAmount,
|
||||||
@ -199,6 +190,7 @@ describe(ContractName.DutchAuction, () => {
|
|||||||
const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
|
const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
|
||||||
sellerOrderFactory = new OrderFactory(makerPrivateKey, sellerDefaultOrderParams);
|
sellerOrderFactory = new OrderFactory(makerPrivateKey, sellerDefaultOrderParams);
|
||||||
buyerOrderFactory = new OrderFactory(takerPrivateKey, buyerDefaultOrderParams);
|
buyerOrderFactory = new OrderFactory(takerPrivateKey, buyerDefaultOrderParams);
|
||||||
|
defaultMakerAssetData = assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress);
|
||||||
});
|
});
|
||||||
after(async () => {
|
after(async () => {
|
||||||
await blockchainLifecycle.revertAsync();
|
await blockchainLifecycle.revertAsync();
|
||||||
@ -215,49 +207,41 @@ describe(ContractName.DutchAuction, () => {
|
|||||||
describe('matchOrders', () => {
|
describe('matchOrders', () => {
|
||||||
it('should be worth the begin price at the begining of the auction', async () => {
|
it('should be worth the begin price at the begining of the auction', async () => {
|
||||||
auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp + 2);
|
auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp + 2);
|
||||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
const makerAssetData = assetDataUtils.encodeDutchAuctionAssetData(
|
||||||
makerAssetData: extendMakerAssetData(
|
defaultMakerAssetData,
|
||||||
assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
auctionBeginTimeSeconds,
|
||||||
auctionBeginTimeSeconds,
|
auctionBeginAmount,
|
||||||
auctionBeginAmount,
|
);
|
||||||
),
|
sellOrder = await sellerOrderFactory.newSignedOrderAsync({ makerAssetData });
|
||||||
});
|
const auctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder);
|
||||||
const auctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
expect(auctionDetails.currentTimeSeconds).to.be.bignumber.lte(auctionBeginTimeSeconds);
|
||||||
expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionBeginAmount);
|
expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionBeginAmount);
|
||||||
expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount);
|
expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount);
|
||||||
});
|
});
|
||||||
it('should be be worth the end price at the end of the auction', async () => {
|
it('should be be worth the end price at the end of the auction', async () => {
|
||||||
auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds * 2);
|
auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds * 2);
|
||||||
auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds);
|
auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds);
|
||||||
|
const makerAssetData = assetDataUtils.encodeDutchAuctionAssetData(
|
||||||
|
defaultMakerAssetData,
|
||||||
|
auctionBeginTimeSeconds,
|
||||||
|
auctionBeginAmount,
|
||||||
|
);
|
||||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||||
makerAssetData: extendMakerAssetData(
|
makerAssetData,
|
||||||
assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
|
||||||
auctionBeginTimeSeconds,
|
|
||||||
auctionBeginAmount,
|
|
||||||
),
|
|
||||||
expirationTimeSeconds: auctionEndTimeSeconds,
|
expirationTimeSeconds: auctionEndTimeSeconds,
|
||||||
});
|
});
|
||||||
const auctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
const auctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder);
|
||||||
|
expect(auctionDetails.currentTimeSeconds).to.be.bignumber.gte(auctionEndTimeSeconds);
|
||||||
expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionEndAmount);
|
expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionEndAmount);
|
||||||
expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount);
|
expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount);
|
||||||
});
|
});
|
||||||
it('should match orders at current amount and send excess to buyer', async () => {
|
it('should match orders at current amount and send excess to buyer', async () => {
|
||||||
const beforeAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
const beforeAuctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder);
|
||||||
buyOrder = await buyerOrderFactory.newSignedOrderAsync({
|
buyOrder = await buyerOrderFactory.newSignedOrderAsync({
|
||||||
makerAssetAmount: beforeAuctionDetails.currentAmount.times(2),
|
makerAssetAmount: beforeAuctionDetails.currentAmount.times(2),
|
||||||
});
|
});
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
await dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress);
|
||||||
await dutchAuctionContract.matchOrders.sendTransactionAsync(
|
const afterAuctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder);
|
||||||
buyOrder,
|
|
||||||
sellOrder,
|
|
||||||
buyOrder.signature,
|
|
||||||
sellOrder.signature,
|
|
||||||
{
|
|
||||||
from: takerAddress,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
const afterAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
|
||||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||||
expect(newBalances[dutchAuctionContract.address][wethContract.address]).to.be.bignumber.equal(
|
expect(newBalances[dutchAuctionContract.address][wethContract.address]).to.be.bignumber.equal(
|
||||||
constants.ZERO_AMOUNT,
|
constants.ZERO_AMOUNT,
|
||||||
@ -276,17 +260,8 @@ describe(ContractName.DutchAuction, () => {
|
|||||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||||
makerFee: new BigNumber(1),
|
makerFee: new BigNumber(1),
|
||||||
});
|
});
|
||||||
const txHash = await dutchAuctionContract.matchOrders.sendTransactionAsync(
|
await dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress);
|
||||||
buyOrder,
|
const afterAuctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder);
|
||||||
sellOrder,
|
|
||||||
buyOrder.signature,
|
|
||||||
sellOrder.signature,
|
|
||||||
{
|
|
||||||
from: takerAddress,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
|
||||||
const afterAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
|
||||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||||
expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
|
expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
|
||||||
erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
|
erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
|
||||||
@ -299,18 +274,9 @@ describe(ContractName.DutchAuction, () => {
|
|||||||
buyOrder = await buyerOrderFactory.newSignedOrderAsync({
|
buyOrder = await buyerOrderFactory.newSignedOrderAsync({
|
||||||
makerFee: new BigNumber(1),
|
makerFee: new BigNumber(1),
|
||||||
});
|
});
|
||||||
const txHash = await dutchAuctionContract.matchOrders.sendTransactionAsync(
|
await dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress);
|
||||||
buyOrder,
|
|
||||||
sellOrder,
|
|
||||||
buyOrder.signature,
|
|
||||||
sellOrder.signature,
|
|
||||||
{
|
|
||||||
from: takerAddress,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
|
||||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||||
const afterAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
const afterAuctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder);
|
||||||
expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
|
expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte(
|
||||||
erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
|
erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount),
|
||||||
);
|
);
|
||||||
@ -321,24 +287,17 @@ describe(ContractName.DutchAuction, () => {
|
|||||||
it('should revert when auction expires', async () => {
|
it('should revert when auction expires', async () => {
|
||||||
auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds * 2);
|
auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds * 2);
|
||||||
auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds);
|
auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds);
|
||||||
|
const makerAssetData = assetDataUtils.encodeDutchAuctionAssetData(
|
||||||
|
defaultMakerAssetData,
|
||||||
|
auctionBeginTimeSeconds,
|
||||||
|
auctionBeginAmount,
|
||||||
|
);
|
||||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||||
expirationTimeSeconds: auctionEndTimeSeconds,
|
expirationTimeSeconds: auctionEndTimeSeconds,
|
||||||
makerAssetData: extendMakerAssetData(
|
makerAssetData,
|
||||||
assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
|
||||||
auctionBeginTimeSeconds,
|
|
||||||
auctionBeginAmount,
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
return expectTransactionFailedAsync(
|
return expectTransactionFailedAsync(
|
||||||
dutchAuctionContract.matchOrders.sendTransactionAsync(
|
dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress),
|
||||||
buyOrder,
|
|
||||||
sellOrder,
|
|
||||||
buyOrder.signature,
|
|
||||||
sellOrder.signature,
|
|
||||||
{
|
|
||||||
from: takerAddress,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RevertReason.AuctionExpired,
|
RevertReason.AuctionExpired,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -347,15 +306,7 @@ describe(ContractName.DutchAuction, () => {
|
|||||||
makerAssetAmount: sellOrder.takerAssetAmount,
|
makerAssetAmount: sellOrder.takerAssetAmount,
|
||||||
});
|
});
|
||||||
return expectTransactionFailedAsync(
|
return expectTransactionFailedAsync(
|
||||||
dutchAuctionContract.matchOrders.sendTransactionAsync(
|
dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress),
|
||||||
buyOrder,
|
|
||||||
sellOrder,
|
|
||||||
buyOrder.signature,
|
|
||||||
sellOrder.signature,
|
|
||||||
{
|
|
||||||
from: takerAddress,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RevertReason.AuctionInvalidAmount,
|
RevertReason.AuctionInvalidAmount,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -364,38 +315,23 @@ describe(ContractName.DutchAuction, () => {
|
|||||||
takerAssetAmount: auctionBeginAmount.plus(1),
|
takerAssetAmount: auctionBeginAmount.plus(1),
|
||||||
});
|
});
|
||||||
return expectTransactionFailedAsync(
|
return expectTransactionFailedAsync(
|
||||||
dutchAuctionContract.matchOrders.sendTransactionAsync(
|
dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress),
|
||||||
buyOrder,
|
|
||||||
sellOrder,
|
|
||||||
buyOrder.signature,
|
|
||||||
sellOrder.signature,
|
|
||||||
{
|
|
||||||
from: takerAddress,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RevertReason.AuctionInvalidAmount,
|
RevertReason.AuctionInvalidAmount,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('begin time is less than end time', async () => {
|
it('begin time is less than end time', async () => {
|
||||||
auctionBeginTimeSeconds = new BigNumber(auctionEndTimeSeconds).plus(tenMinutesInSeconds);
|
auctionBeginTimeSeconds = new BigNumber(auctionEndTimeSeconds).plus(tenMinutesInSeconds);
|
||||||
|
const makerAssetData = assetDataUtils.encodeDutchAuctionAssetData(
|
||||||
|
defaultMakerAssetData,
|
||||||
|
auctionBeginTimeSeconds,
|
||||||
|
auctionBeginAmount,
|
||||||
|
);
|
||||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||||
expirationTimeSeconds: auctionEndTimeSeconds,
|
expirationTimeSeconds: auctionEndTimeSeconds,
|
||||||
makerAssetData: extendMakerAssetData(
|
makerAssetData,
|
||||||
assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
|
||||||
auctionBeginTimeSeconds,
|
|
||||||
auctionBeginAmount,
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
return expectTransactionFailedAsync(
|
return expectTransactionFailedAsync(
|
||||||
dutchAuctionContract.matchOrders.sendTransactionAsync(
|
dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress),
|
||||||
buyOrder,
|
|
||||||
sellOrder,
|
|
||||||
buyOrder.signature,
|
|
||||||
sellOrder.signature,
|
|
||||||
{
|
|
||||||
from: takerAddress,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RevertReason.AuctionInvalidBeginTime,
|
RevertReason.AuctionInvalidBeginTime,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -404,45 +340,30 @@ describe(ContractName.DutchAuction, () => {
|
|||||||
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
||||||
});
|
});
|
||||||
return expectTransactionFailedAsync(
|
return expectTransactionFailedAsync(
|
||||||
dutchAuctionContract.matchOrders.sendTransactionAsync(
|
dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress),
|
||||||
buyOrder,
|
|
||||||
sellOrder,
|
|
||||||
buyOrder.signature,
|
|
||||||
sellOrder.signature,
|
|
||||||
{
|
|
||||||
from: takerAddress,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RevertReason.InvalidAssetData,
|
RevertReason.InvalidAssetData,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('ERC721', () => {
|
describe('ERC721', () => {
|
||||||
it('should match orders when ERC721', async () => {
|
it('should match orders when ERC721', async () => {
|
||||||
const makerAssetId = erc721MakerAssetIds[0];
|
const makerAssetId = erc721MakerAssetIds[0];
|
||||||
|
const erc721MakerAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId);
|
||||||
|
const makerAssetData = assetDataUtils.encodeDutchAuctionAssetData(
|
||||||
|
erc721MakerAssetData,
|
||||||
|
auctionBeginTimeSeconds,
|
||||||
|
auctionBeginAmount,
|
||||||
|
);
|
||||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||||
makerAssetAmount: new BigNumber(1),
|
makerAssetAmount: new BigNumber(1),
|
||||||
makerAssetData: extendMakerAssetData(
|
makerAssetData,
|
||||||
assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
|
|
||||||
auctionBeginTimeSeconds,
|
|
||||||
auctionBeginAmount,
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
buyOrder = await buyerOrderFactory.newSignedOrderAsync({
|
buyOrder = await buyerOrderFactory.newSignedOrderAsync({
|
||||||
takerAssetAmount: new BigNumber(1),
|
takerAssetAmount: new BigNumber(1),
|
||||||
takerAssetData: sellOrder.makerAssetData,
|
takerAssetData: sellOrder.makerAssetData,
|
||||||
});
|
});
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
await dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress);
|
||||||
await dutchAuctionContract.matchOrders.sendTransactionAsync(
|
const afterAuctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder);
|
||||||
buyOrder,
|
|
||||||
sellOrder,
|
|
||||||
buyOrder.signature,
|
|
||||||
sellOrder.signature,
|
|
||||||
{
|
|
||||||
from: takerAddress,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
const afterAuctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
|
||||||
const newBalances = await erc20Wrapper.getBalancesAsync();
|
const newBalances = await erc20Wrapper.getBalancesAsync();
|
||||||
// HACK gte used here due to a bug in ganache where the timestamp can change
|
// HACK gte used here due to a bug in ganache where the timestamp can change
|
||||||
// between multiple calls to the same block. Which can move the amount in our case
|
// between multiple calls to the same block. Which can move the amount in our case
|
||||||
|
62
contracts/extensions/test/utils/dutch_auction_wrapper.ts
Normal file
62
contracts/extensions/test/utils/dutch_auction_wrapper.ts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { artifacts as protocolArtifacts } from '@0x/contracts-protocol';
|
||||||
|
import { LogDecoder } from '@0x/contracts-test-utils';
|
||||||
|
import { artifacts as tokensArtifacts } from '@0x/contracts-tokens';
|
||||||
|
import { DutchAuctionDetails, SignedOrder } from '@0x/types';
|
||||||
|
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||||
|
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { DutchAuctionContract } from '../../generated-wrappers/dutch_auction';
|
||||||
|
import { artifacts } from '../../src/artifacts';
|
||||||
|
|
||||||
|
export class DutchAuctionWrapper {
|
||||||
|
private readonly _dutchAuctionContract: DutchAuctionContract;
|
||||||
|
private readonly _web3Wrapper: Web3Wrapper;
|
||||||
|
private readonly _logDecoder: LogDecoder;
|
||||||
|
|
||||||
|
constructor(contractInstance: DutchAuctionContract, provider: Provider) {
|
||||||
|
this._dutchAuctionContract = contractInstance;
|
||||||
|
this._web3Wrapper = new Web3Wrapper(provider);
|
||||||
|
this._logDecoder = new LogDecoder(this._web3Wrapper, {
|
||||||
|
...artifacts,
|
||||||
|
...tokensArtifacts,
|
||||||
|
...protocolArtifacts,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Matches the buy and sell orders at an amount given the following: the current block time, the auction
|
||||||
|
* start time and the auction begin amount. The sell order is a an order at the lowest amount
|
||||||
|
* at the end of the auction. Excess from the match is transferred to the seller.
|
||||||
|
* Over time the price moves from beginAmount to endAmount given the current block.timestamp.
|
||||||
|
* @param buyOrder The Buyer's order. This order is for the current expected price of the auction.
|
||||||
|
* @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction).
|
||||||
|
* @param from Address the transaction is being sent from.
|
||||||
|
* @return Transaction receipt with decoded logs.
|
||||||
|
*/
|
||||||
|
public async matchOrdersAsync(
|
||||||
|
buyOrder: SignedOrder,
|
||||||
|
sellOrder: SignedOrder,
|
||||||
|
from: string,
|
||||||
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
|
const txHash = await this._dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||||
|
buyOrder,
|
||||||
|
sellOrder,
|
||||||
|
buyOrder.signature,
|
||||||
|
sellOrder.signature,
|
||||||
|
{
|
||||||
|
from,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Calculates the Auction Details for the given order
|
||||||
|
* @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction).
|
||||||
|
* @return The dutch auction details.
|
||||||
|
*/
|
||||||
|
public async getAuctionDetailsAsync(sellOrder: SignedOrder): Promise<DutchAuctionDetails> {
|
||||||
|
const afterAuctionDetails = await this._dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
||||||
|
return afterAuctionDetails;
|
||||||
|
}
|
||||||
|
}
|
@ -305,4 +305,24 @@ export const assetDataUtils = {
|
|||||||
throw new Error(`Unrecognized asset proxy id: ${assetProxyId}`);
|
throw new Error(`Unrecognized asset proxy id: ${assetProxyId}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Dutch auction details are encoded with the asset data for a 0x order. This function produces a hex
|
||||||
|
* encoded assetData string, containing information both about the asset being traded and the
|
||||||
|
* dutch auction; which is usable in the makerAssetData or takerAssetData fields in a 0x order.
|
||||||
|
* @param assetData Hex encoded assetData string for the asset being auctioned.
|
||||||
|
* @param beginTimeSeconds Begin time of the dutch auction.
|
||||||
|
* @param beginAmount Starting amount being sold in the dutch auction.
|
||||||
|
* @return The hex encoded assetData string.
|
||||||
|
*/
|
||||||
|
encodeDutchAuctionAssetData(assetData: string, beginTimeSeconds: BigNumber, beginAmount: BigNumber): string {
|
||||||
|
const assetDataBuffer = ethUtil.toBuffer(assetData);
|
||||||
|
const abiEncodedAuctionData = (ethAbi as any).rawEncode(
|
||||||
|
['uint256', 'uint256'],
|
||||||
|
[beginTimeSeconds.toString(), beginAmount.toString()],
|
||||||
|
);
|
||||||
|
const abiEncodedAuctionDataBuffer = ethUtil.toBuffer(abiEncodedAuctionData);
|
||||||
|
const dutchAuctionDataBuffer = Buffer.concat([assetDataBuffer, abiEncodedAuctionDataBuffer]);
|
||||||
|
const dutchAuctionData = ethUtil.bufferToHex(dutchAuctionDataBuffer);
|
||||||
|
return dutchAuctionData;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -676,3 +676,12 @@ export interface SimpleEvmOutput {
|
|||||||
export interface SimpleEvmBytecodeOutput {
|
export interface SimpleEvmBytecodeOutput {
|
||||||
object: string;
|
object: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DutchAuctionDetails {
|
||||||
|
beginTimeSeconds: BigNumber;
|
||||||
|
endTimeSeconds: BigNumber;
|
||||||
|
beginAmount: BigNumber;
|
||||||
|
endAmount: BigNumber;
|
||||||
|
currentAmount: BigNumber;
|
||||||
|
currentTimeSeconds: BigNumber;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user