Make cancelOrdersUpTo compatible with sender abstraction

This commit is contained in:
Amir Bandeali
2018-06-16 21:45:12 -07:00
parent 7dd208fb49
commit e92926e881
11 changed files with 548 additions and 47 deletions

View File

@@ -44,9 +44,9 @@ contract MixinExchangeCore is
// Mapping of orderHash => cancelled
mapping (bytes32 => bool) public cancelled;
// Mapping of makerAddress => lowest salt an order can have in order to be fillable
// Mapping of makerAddress => senderAddress => 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;
mapping (address => mapping (address => uint256)) public makerEpoch;
////// Core exchange functions //////
@@ -56,10 +56,13 @@ contract MixinExchangeCore is
external
{
address makerAddress = getCurrentContextAddress();
// If this function is called via `executeTransaction`, we only update the makerEpoch for the makerAddress/msg.sender combination.
// This allows external filter contracts to add rules to how orders are cancelled via this function.
address senderAddress = makerAddress == msg.sender ? address(0) : msg.sender;
// makerEpoch is initialized to 0, so to cancelUpTo we need salt + 1
uint256 newMakerEpoch = salt + 1;
uint256 oldMakerEpoch = makerEpoch[makerAddress];
uint256 oldMakerEpoch = makerEpoch[makerAddress][senderAddress];
// Ensure makerEpoch is monotonically increasing
require(
@@ -68,8 +71,8 @@ contract MixinExchangeCore is
);
// Update makerEpoch
makerEpoch[makerAddress] = newMakerEpoch;
emit CancelUpTo(makerAddress, newMakerEpoch);
makerEpoch[makerAddress][senderAddress] = newMakerEpoch;
emit CancelUpTo(makerAddress, senderAddress, newMakerEpoch);
}
/// @dev Fills the input order.
@@ -180,7 +183,7 @@ contract MixinExchangeCore is
orderInfo.orderStatus = uint8(OrderStatus.CANCELLED);
return orderInfo;
}
if (makerEpoch[order.makerAddress] > order.salt) {
if (makerEpoch[order.makerAddress][order.senderAddress] > order.salt) {
orderInfo.orderStatus = uint8(OrderStatus.CANCELLED);
return orderInfo;
}

View File

@@ -52,6 +52,7 @@ contract MExchangeCore is
// CancelUpTo event is emitted whenever `cancelOrdersUpTo` is executed succesfully.
event CancelUpTo(
address indexed makerAddress,
address indexed senderAddress,
uint256 makerEpoch
);

View File

@@ -0,0 +1,97 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;
import "../../protocol/Exchange/interfaces/IExchange.sol";
import "../../protocol/Exchange/libs/LibOrder.sol";
contract ExchangeWrapper {
// Exchange contract.
IExchange EXCHANGE;
constructor (address _exchange)
public
{
EXCHANGE = IExchange(_exchange);
}
/// @dev Fills an order using `msg.sender` as the taker.
/// @param order Order struct containing order specifications.
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
/// @param salt Arbitrary value to gaurantee uniqueness of 0x transaction hash.
/// @param orderSignature Proof that order has been created by maker.
/// @param takerSignature Proof that taker wishes to call this function with given params.
function fillOrder(
LibOrder.Order memory order,
uint256 takerAssetFillAmount,
uint256 salt,
bytes memory orderSignature,
bytes memory takerSignature
)
public
{
address takerAddress = msg.sender;
// Encode arguments into byte array.
bytes memory data = abi.encodeWithSelector(
EXCHANGE.fillOrder.selector,
order,
takerAssetFillAmount,
orderSignature
);
// Call `fillOrder` via `executeTransaction`.
EXCHANGE.executeTransaction(
salt,
takerAddress,
data,
takerSignature
);
}
/// @dev Cancels all orders created by sender with a salt less than or equal to the specified salt value.
/// @param cancelSalt Orders created with a salt less or equal to this value will be cancelled.
/// @param salt Arbitrary value to gaurantee uniqueness of 0x transaction hash.
/// @param makerSignature Proof that maker wishes to call this function with given params.
function cancelOrdersUpTo(
uint256 cancelSalt,
uint256 salt,
bytes makerSignature
)
external
{
address makerAddress = msg.sender;
// Encode arguments into byte array.
bytes memory data = abi.encodeWithSelector(
EXCHANGE.cancelOrdersUpTo.selector,
cancelSalt
);
// Call `cancelOrdersUpTo` via `executeTransaction`.
EXCHANGE.executeTransaction(
salt,
makerAddress,
data,
makerSignature
);
}
}

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.23;
pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;
import "../../protocol/Exchange/interfaces/IExchange.sol";

View File

@@ -7,6 +7,7 @@ import * as DummyERC721Token from '../artifacts/DummyERC721Token.json';
import * as ERC20Proxy from '../artifacts/ERC20Proxy.json';
import * as ERC721Proxy from '../artifacts/ERC721Proxy.json';
import * as Exchange from '../artifacts/Exchange.json';
import * as ExchangeWrapper from '../artifacts/ExchangeWrapper.json';
import * as MixinAuthorizable from '../artifacts/MixinAuthorizable.json';
import * as MultiSigWallet from '../artifacts/MultiSigWallet.json';
import * as MultiSigWalletWithTimeLock from '../artifacts/MultiSigWalletWithTimeLock.json';
@@ -29,6 +30,7 @@ export const artifacts = {
ERC20Proxy: (ERC20Proxy as any) as ContractArtifact,
ERC721Proxy: (ERC721Proxy as any) as ContractArtifact,
Exchange: (Exchange as any) as ContractArtifact,
ExchangeWrapper: (ExchangeWrapper as any) as ContractArtifact,
EtherToken: (EtherToken as any) as ContractArtifact,
MixinAuthorizable: (MixinAuthorizable as any) as ContractArtifact,
MultiSigWallet: (MultiSigWallet as any) as ContractArtifact,