chore: time movement for geth
This commit is contained in:
@@ -86,11 +86,9 @@ contract DutchAuction {
|
||||
{
|
||||
AuctionDetails memory auctionDetails = getAuctionDetails(sellOrder);
|
||||
// Ensure the auction has not yet started
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
require(block.timestamp >= auctionDetails.beginTime, "AUCTION_NOT_STARTED");
|
||||
require(auctionDetails.currentTime >= auctionDetails.beginTime, "AUCTION_NOT_STARTED");
|
||||
// Ensure the auction has not expired. This will fail later in 0x but we can save gas by failing early
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
require(sellOrder.expirationTimeSeconds > block.timestamp, "AUCTION_EXPIRED");
|
||||
require(sellOrder.expirationTimeSeconds > auctionDetails.currentTime, "AUCTION_EXPIRED");
|
||||
// Ensure the auction goes from high to low
|
||||
require(auctionDetails.beginPrice > auctionDetails.endPrice, "INVALID_PRICE");
|
||||
// Validate the buyer amount is greater than the current auction price
|
||||
@@ -141,20 +139,24 @@ contract DutchAuction {
|
||||
(uint256 auctionBeginTimeSeconds, uint256 auctionBeginPrice) = decodeParameters(order.salt);
|
||||
require(order.expirationTimeSeconds > auctionBeginTimeSeconds, "INVALID_BEGIN_TIME");
|
||||
uint256 auctionDurationSeconds = order.expirationTimeSeconds-auctionBeginTimeSeconds;
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
uint256 currentDurationSeconds = order.expirationTimeSeconds-block.timestamp;
|
||||
uint256 minPrice = order.takerAssetAmount;
|
||||
uint256 priceDiff = auctionBeginPrice-minPrice;
|
||||
uint256 currentPrice = minPrice + (currentDurationSeconds*priceDiff/auctionDurationSeconds);
|
||||
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
uint256 timestamp = block.timestamp;
|
||||
auctionDetails.beginTime = auctionBeginTimeSeconds;
|
||||
auctionDetails.endTime = order.expirationTimeSeconds;
|
||||
auctionDetails.beginPrice = auctionBeginPrice;
|
||||
auctionDetails.endPrice = minPrice;
|
||||
auctionDetails.currentPrice = currentPrice;
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
auctionDetails.currentTime = block.timestamp;
|
||||
auctionDetails.currentTime = timestamp;
|
||||
|
||||
uint256 remainingDurationSeconds = order.expirationTimeSeconds-timestamp;
|
||||
uint256 priceDelta = auctionBeginPrice-minPrice;
|
||||
uint256 currentPrice = minPrice + (remainingDurationSeconds*priceDelta/auctionDurationSeconds);
|
||||
// If the auction has not yet begun the current price is the auctionBeginPrice
|
||||
currentPrice = timestamp < auctionBeginTimeSeconds ? auctionBeginPrice : currentPrice;
|
||||
// If the auction has ended the current price is the minPrice
|
||||
// auction end time is guaranteed by 0x Exchange to fail due to the order expiration
|
||||
currentPrice = timestamp >= order.expirationTimeSeconds ? minPrice : currentPrice;
|
||||
auctionDetails.currentPrice = currentPrice;
|
||||
return auctionDetails;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
const DECIMALS_DEFAULT = 18;
|
||||
|
||||
describe(ContractName.DutchAuction, () => {
|
||||
describe.only(ContractName.DutchAuction, () => {
|
||||
let makerAddress: string;
|
||||
let owner: string;
|
||||
let takerAddress: string;
|
||||
@@ -49,11 +49,26 @@ describe(ContractName.DutchAuction, () => {
|
||||
let tenMinutesInSeconds: number;
|
||||
let currentBlockTimestamp: number;
|
||||
let auctionBeginTime: BigNumber;
|
||||
let auctionEndTime: BigNumber;
|
||||
let auctionBeginPrice: BigNumber;
|
||||
let auctionEndPrice: BigNumber;
|
||||
let encodedParams: BigNumber;
|
||||
let sellOrder: SignedOrder;
|
||||
let buyOrder: SignedOrder;
|
||||
let erc721MakerAssetIds: BigNumber[];
|
||||
async function increaseTimeAsync(): Promise<void> {
|
||||
const timestampBefore = await getLatestBlockTimestampAsync();
|
||||
await web3Wrapper.increaseTimeAsync(5);
|
||||
const timestampAfter = await getLatestBlockTimestampAsync();
|
||||
// HACK send some transactions
|
||||
if (timestampAfter === timestampBefore) {
|
||||
await web3Wrapper.sendTransactionAsync({ to: makerAddress, from: makerAddress, value: new BigNumber(1) });
|
||||
await web3Wrapper.sendTransactionAsync({ to: makerAddress, from: makerAddress, value: new BigNumber(1) });
|
||||
await web3Wrapper.sendTransactionAsync({ to: makerAddress, from: makerAddress, value: new BigNumber(1) });
|
||||
await web3Wrapper.sendTransactionAsync({ to: makerAddress, from: makerAddress, value: new BigNumber(1) });
|
||||
await web3Wrapper.sendTransactionAsync({ to: makerAddress, from: makerAddress, value: new BigNumber(1) });
|
||||
}
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
@@ -132,12 +147,19 @@ describe(ContractName.DutchAuction, () => {
|
||||
web3Wrapper.abiDecoder.addABI(exchangeInstance.abi);
|
||||
web3Wrapper.abiDecoder.addABI(zrxToken.abi);
|
||||
erc20Wrapper.addTokenOwnerAddress(dutchAuctionContract.address);
|
||||
|
||||
tenMinutesInSeconds = 10 * 60;
|
||||
currentBlockTimestamp = await getLatestBlockTimestampAsync();
|
||||
// Default auction begins 10 minutes ago
|
||||
auctionBeginTime = new BigNumber(currentBlockTimestamp).minus(tenMinutesInSeconds);
|
||||
// Default auction ends 10 from now
|
||||
auctionEndTime = new BigNumber(currentBlockTimestamp).plus(tenMinutesInSeconds);
|
||||
auctionBeginPrice = Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT);
|
||||
auctionEndPrice = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT);
|
||||
encodedParams = await dutchAuctionContract.encodeParameters.callAsync(auctionBeginTime, auctionBeginPrice);
|
||||
const zero = Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT);
|
||||
|
||||
// Default sell order and buy order are exact mirrors
|
||||
const sellerDefaultOrderParams = {
|
||||
salt: encodedParams, // Set the encoded params as the salt for the seller order
|
||||
exchangeAddress: exchangeInstance.address,
|
||||
@@ -147,18 +169,23 @@ describe(ContractName.DutchAuction, () => {
|
||||
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
|
||||
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
|
||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), DECIMALS_DEFAULT),
|
||||
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), DECIMALS_DEFAULT),
|
||||
makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
|
||||
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
|
||||
takerAssetAmount: auctionEndPrice,
|
||||
expirationTimeSeconds: auctionEndTime,
|
||||
makerFee: zero,
|
||||
takerFee: zero,
|
||||
};
|
||||
// Default buy order is for the auction begin price
|
||||
const buyerDefaultOrderParams = {
|
||||
...sellerDefaultOrderParams,
|
||||
makerAddress: takerAddress,
|
||||
makerAssetData: sellerDefaultOrderParams.takerAssetData,
|
||||
takerAssetData: sellerDefaultOrderParams.makerAssetData,
|
||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT),
|
||||
makerAssetAmount: auctionBeginPrice,
|
||||
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), DECIMALS_DEFAULT),
|
||||
};
|
||||
|
||||
encodedParams = await dutchAuctionContract.encodeParameters.callAsync(auctionBeginTime, auctionBeginPrice);
|
||||
|
||||
const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
|
||||
const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
|
||||
sellerOrderFactory = new OrderFactory(makerPrivateKey, sellerDefaultOrderParams);
|
||||
@@ -170,11 +197,6 @@ describe(ContractName.DutchAuction, () => {
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
erc20Balances = await erc20Wrapper.getBalancesAsync();
|
||||
tenMinutesInSeconds = 10 * 60;
|
||||
currentBlockTimestamp = await getLatestBlockTimestampAsync();
|
||||
auctionBeginTime = new BigNumber(currentBlockTimestamp).minus(tenMinutesInSeconds);
|
||||
auctionBeginPrice = Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT);
|
||||
encodedParams = await dutchAuctionContract.encodeParameters.callAsync(auctionBeginTime, auctionBeginPrice);
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync();
|
||||
buyOrder = await buyerOrderFactory.newSignedOrderAsync();
|
||||
});
|
||||
@@ -183,6 +205,7 @@ describe(ContractName.DutchAuction, () => {
|
||||
});
|
||||
describe('matchOrders', () => {
|
||||
it('should encode and decode parameters', async () => {
|
||||
encodedParams = await dutchAuctionContract.encodeParameters.callAsync(auctionBeginTime, auctionBeginPrice);
|
||||
const [decodedBegin, decodedBeginPrice] = await dutchAuctionContract.decodeParameters.callAsync(
|
||||
encodedParams,
|
||||
);
|
||||
@@ -190,9 +213,6 @@ describe(ContractName.DutchAuction, () => {
|
||||
expect(decodedBeginPrice).to.be.bignumber.equal(auctionBeginPrice);
|
||||
});
|
||||
it('should be worth the begin price at the begining of the auction', async () => {
|
||||
// TODO this is flakey
|
||||
currentBlockTimestamp = await web3Wrapper.getBlockTimestampAsync('latest');
|
||||
await web3Wrapper.increaseTimeAsync(1);
|
||||
auctionBeginTime = new BigNumber(currentBlockTimestamp + 2);
|
||||
encodedParams = await dutchAuctionContract.encodeParameters.callAsync(auctionBeginTime, auctionBeginPrice);
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||
@@ -202,6 +222,18 @@ describe(ContractName.DutchAuction, () => {
|
||||
expect(auctionDetails.currentPrice).to.be.bignumber.equal(auctionBeginPrice);
|
||||
expect(auctionDetails.beginPrice).to.be.bignumber.equal(auctionBeginPrice);
|
||||
});
|
||||
it('should be be worth the end price at the end of the auction', async () => {
|
||||
auctionBeginTime = new BigNumber(currentBlockTimestamp - 1000);
|
||||
auctionEndTime = new BigNumber(currentBlockTimestamp - 100);
|
||||
encodedParams = await dutchAuctionContract.encodeParameters.callAsync(auctionBeginTime, auctionBeginPrice);
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||
salt: encodedParams,
|
||||
expirationTimeSeconds: auctionEndTime,
|
||||
});
|
||||
const auctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
||||
expect(auctionDetails.currentPrice).to.be.bignumber.equal(auctionEndPrice);
|
||||
expect(auctionDetails.beginPrice).to.be.bignumber.equal(auctionBeginPrice);
|
||||
});
|
||||
it('should match orders and send excess to seller', async () => {
|
||||
const txHash = await dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||
buyOrder,
|
||||
@@ -224,11 +256,11 @@ describe(ContractName.DutchAuction, () => {
|
||||
it('should have valid getAuctionDetails at a block in the future', async () => {
|
||||
let auctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
||||
const beforePrice = auctionDetails.currentPrice;
|
||||
// Increase block time
|
||||
await web3Wrapper.increaseTimeAsync(60);
|
||||
await increaseTimeAsync();
|
||||
auctionDetails = await dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
|
||||
const currentPrice = auctionDetails.currentPrice;
|
||||
expect(beforePrice).to.be.bignumber.greaterThan(currentPrice);
|
||||
|
||||
buyOrder = await buyerOrderFactory.newSignedOrderAsync({
|
||||
makerAssetAmount: currentPrice,
|
||||
});
|
||||
@@ -248,8 +280,12 @@ describe(ContractName.DutchAuction, () => {
|
||||
);
|
||||
});
|
||||
it('should revert when auction expires', async () => {
|
||||
// Increase block time
|
||||
await web3Wrapper.increaseTimeAsync(tenMinutesInSeconds);
|
||||
auctionEndTime = new BigNumber(currentBlockTimestamp - 100);
|
||||
encodedParams = await dutchAuctionContract.encodeParameters.callAsync(auctionBeginTime, auctionBeginPrice);
|
||||
sellOrder = await sellerOrderFactory.newSignedOrderAsync({
|
||||
salt: encodedParams,
|
||||
expirationTimeSeconds: auctionEndTime,
|
||||
});
|
||||
return expectTransactionFailedAsync(
|
||||
dutchAuctionContract.matchOrders.sendTransactionAsync(
|
||||
buyOrder,
|
||||
@@ -264,8 +300,7 @@ describe(ContractName.DutchAuction, () => {
|
||||
);
|
||||
});
|
||||
it('cannot be filled for less than the current price', async () => {
|
||||
// Increase block time
|
||||
await web3Wrapper.increaseTimeAsync(60);
|
||||
await increaseTimeAsync();
|
||||
buyOrder = await buyerOrderFactory.newSignedOrderAsync({
|
||||
makerAssetAmount: sellOrder.takerAssetAmount,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user