diff options
Diffstat (limited to 'packages/contracts/src')
6 files changed, 67 insertions, 16 deletions
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol index e925634df..7a705a0ee 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol @@ -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, diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/IExchange.sol b/packages/contracts/src/contracts/current/protocol/Exchange/IExchange.sol index 8f17f9315..3a43fca9b 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/IExchange.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/IExchange.sol @@ -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. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol index 1f3108188..6d69b1787 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol @@ -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. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol index e40120d01..b39996995 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol @@ -36,4 +36,7 @@ contract MExchangeCore is LibOrder { public returns (uint256 takerTokenCancelledAmount); + function cancelOrdersBefore( + uint256 salt) + external; } diff --git a/packages/contracts/src/utils/exchange_wrapper.ts b/packages/contracts/src/utils/exchange_wrapper.ts index 5996867cb..d4206adc3 100644 --- a/packages/contracts/src/utils/exchange_wrapper.ts +++ b/packages/contracts/src/utils/exchange_wrapper.ts @@ -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); diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index 9f874d9ec..1a924a66d 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -28,6 +28,10 @@ export interface BatchCancelOrders { takerTokenCancelAmounts: BigNumber[]; } +export interface CancelOrdersBefore { + timestamp: BigNumber; +} + export interface DefaultOrderParams { exchangeAddress: string; makerAddress: string; |