Implementation and tests in the protocol for cancelling all orders up to a specific time

This commit is contained in:
Greg Hysen
2018-03-15 13:58:54 -07:00
committed by Amir Bandeali
parent e98b4ea26d
commit aeb0742434
7 changed files with 134 additions and 16 deletions

View File

@@ -30,7 +30,7 @@ contract Exchange is
MixinSettlementProxy,
MixinWrapperFunctions
{
string constant public VERSION = "2.0.0-alpha";
string constant public VERSION = "2.0.1-alpha";
function Exchange(
IToken _zrxToken,

View File

@@ -53,38 +53,43 @@ contract IExchange {
uint256 takerTokenCancelledAmount,
bytes32 indexed orderHash
);
event LogCancelBefore(
address indexed maker,
uint256 salt
);
function ZRX_TOKEN_CONTRACT()
public view
returns (address);
function TOKEN_TRANSFER_PROXY_CONTRACT()
public view
returns (address);
function EXTERNAL_QUERY_GAS_LIMIT()
public view
returns (uint16);
function VERSION()
public view
returns (string);
function filled(bytes32)
public view
returns (uint256);
function cancelled(bytes32)
public view
returns (uint256);
/// @dev Calculates the sum of values already filled and cancelled for a given order.
/// @param orderHash The Keccak-256 hash of the given order.
/// @return Sum of values already filled and cancelled.
function getUnavailableTakerTokenAmount(bytes32 orderHash)
public view
returns (uint256 unavailableTakerTokenAmount);
/// @dev Calculates partial value given a numerator and denominator.
/// @param numerator Numerator.
/// @param denominator Denominator.
@@ -93,7 +98,7 @@ contract IExchange {
function getPartialAmount(uint256 numerator, uint256 denominator, uint256 target)
public pure
returns (uint256 partialAmount);
/// @dev Checks if rounding error > 0.1%.
/// @param numerator Numerator.
/// @param denominator Denominator.
@@ -102,7 +107,7 @@ contract IExchange {
function isRoundingError(uint256 numerator, uint256 denominator, uint256 target)
public pure
returns (bool isError);
/// @dev Calculates Keccak-256 hash of order with specified parameters.
/// @param orderAddresses Array of order's maker, taker, makerToken, takerToken, and feeRecipient.
/// @param orderValues Array of order's makerTokenAmount, takerTokenAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
@@ -110,7 +115,7 @@ contract IExchange {
function getOrderHash(address[5] orderAddresses, uint256[6] orderValues)
public view
returns (bytes32 orderHash);
/// @dev Verifies that an order signature is valid.
/// @param signer address of signer.
/// @param hash Signed Keccak-256 hash.
@@ -126,7 +131,7 @@ contract IExchange {
bytes32 s)
public pure
returns (bool isValid);
/// @dev Fills the input order.
/// @param orderAddresses Array of order's maker, taker, makerToken, takerToken, and feeRecipient.
/// @param orderValues Array of order's makerTokenAmount, takerTokenAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
@@ -144,7 +149,7 @@ contract IExchange {
bytes32 s)
public
returns (uint256 takerTokenFilledAmount);
/// @dev Cancels the input order.
/// @param orderAddresses Array of order's maker, taker, makerToken, takerToken, and feeRecipient.
/// @param orderValues Array of order's makerTokenAmount, takerTokenAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
@@ -157,6 +162,9 @@ contract IExchange {
public
returns (uint256 takerTokenCancelledAmount);
/// @dev Cancels all orders for a specified maker up to a certain time.
/// @param salt Orders created with a lower salt value will be cancelled
function cancelOrdersBefore(uint256 salt) external;
/// @dev Fills an order with specified parameters and ECDSA signature. Throws if specified amount not filled entirely.
/// @param orderAddresses Array of order's maker, taker, makerToken, takerToken, and feeRecipient.

View File

@@ -43,6 +43,10 @@ contract MixinExchangeCore is
mapping (bytes32 => uint256) public filled;
mapping (bytes32 => uint256) public cancelled;
// Mapping of makerAddress => lowest salt an order can have in order to be fillable
// Orders with a salt less than their maker's epoch are considered cancelled
mapping (address => uint256) public makerEpoch;
event LogFill(
address indexed makerAddress,
address takerAddress,
@@ -66,6 +70,11 @@ contract MixinExchangeCore is
bytes32 indexed orderHash
);
event LogCancelBefore(
address indexed maker,
uint256 salt
);
/*
* Core exchange functions
*/
@@ -119,6 +128,12 @@ contract MixinExchangeCore is
return 0;
}
// Validate order is not cancelled
if (order.salt < makerEpoch[order.makerAddress]) {
LogError(uint8(Errors.ORDER_FULLY_FILLED_OR_CANCELLED), orderHash);
return 0;
}
// Update state
filled[orderHash] = safeAdd(filled[orderHash], takerTokenFilledAmount);
@@ -154,7 +169,7 @@ contract MixinExchangeCore is
{
// Compute the order hash
bytes32 orderHash = getOrderHash(order);
// Validate the order
require(order.makerTokenAmount > 0);
require(order.takerTokenAmount > 0);
@@ -186,7 +201,16 @@ contract MixinExchangeCore is
);
return takerTokenCancelledAmount;
}
/// @param salt Orders created with a salt less than this value will be cancelled.
function cancelOrdersBefore(uint256 salt)
external
{
require(salt > makerEpoch[msg.sender]); // epoch must be monotonically increasing
makerEpoch[msg.sender] = salt;
LogCancelBefore(msg.sender, salt);
}
/// @dev Checks if rounding error > 0.1%.
/// @param numerator Numerator.
/// @param denominator Denominator.

View File

@@ -36,4 +36,7 @@ contract MExchangeCore is LibOrder {
public
returns (uint256 takerTokenCancelledAmount);
function cancelOrdersBefore(
uint256 salt)
external;
}

View File

@@ -167,6 +167,18 @@ export class ExchangeWrapper {
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
return tx;
}
public async cancelOrdersBeforeAsync(
timestamp: BigNumber,
from: string,
): Promise<TransactionReceiptWithDecodedLogs> {
const txHash = await this._exchange.cancelOrdersBefore.sendTransactionAsync(
timestamp,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
return tx;
}
public async getOrderHashAsync(signedOrder: SignedOrder): Promise<string> {
const order = orderUtils.getOrderStruct(signedOrder);
const orderHash = await this._exchange.getOrderHash.callAsync(order);

View File

@@ -28,6 +28,10 @@ export interface BatchCancelOrders {
takerTokenCancelAmounts: BigNumber[];
}
export interface CancelOrdersBefore {
timestamp: BigNumber;
}
export interface DefaultOrderParams {
exchangeAddress: string;
makerAddress: string;