From 8508b2ab85cbde204568e7de48ab3e344a018482 Mon Sep 17 00:00:00 2001 From: mattdf Date: Fri, 27 Apr 2018 15:38:34 +0200 Subject: [PATCH 1/7] multi-trade poc --- contracts/Exchange.sol | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index 082ebd9..e3e508d 100644 --- a/contracts/Exchange.sol +++ b/contracts/Exchange.sol @@ -63,6 +63,29 @@ contract Exchange is Ownable, ExchangeInterface { emit Unsubscribed(msg.sender); } + + function multitrade(uint numOrders, address[] addresses, uint[] values, bytes32[] sigmain, uint16[] sigaux, uint maxFillAmount) external { + require(addresses.length == 3*numOrders); + require(values.length == 4*numOrders); + require(sigmain.length == 2*numOrders); + require(sigaux.length == numOrders); + + address[3] memory addrs; + uint[4] memory vals; + bytes memory s = new bytes(66); + + for (uint i = 0; i < numOrders; i++){ + for (uint j = 0; j < 3; j++){ + addrs[j] = addresses[(i*3)+j]; + } + for (j = 0; j < 4; j++){ + vals[j] = values[(i*4)+j]; + } + s = sigArrayToBytes(sigmain, sigaux, i); + trade(OrderLibrary.createOrder(addrs, vals), msg.sender, s, maxFillAmount); + } + } + /// @dev Takes an order. /// @param addresses Array of trade's maker, makerToken and takerToken. /// @param values Array of trade's makerTokenAmount, takerTokenAmount, expires and nonce. @@ -298,4 +321,16 @@ contract Exchange is Ownable, ExchangeInterface { return remainder.mul(1000000).div(numerator.mul(target)); } + + function sigArrayToBytes(bytes32[] sm, uint16[] sa, uint i) internal pure returns (bytes) { + bytes32 s1 = sm[i*2]; + bytes32 s2 = sm[i*2 + 1]; + uint16 s3 = sa[i]; + bytes memory s = new bytes(66); + assembly { + mstore(add(s, 32), s1) + mstore(add(s, 64), s2) + mstore(add(s, 96), s3) + } + } } From 0b012b17d87efff07e54848535e7bd3a6210fadf Mon Sep 17 00:00:00 2001 From: Dean Eigenmann Date: Fri, 27 Apr 2018 22:52:34 +0200 Subject: [PATCH 2/7] enhancement/logic-libraries (#96) * Created library * removed unused imports * renamed --- contracts/Exchange.sol | 177 ++++-------------------- contracts/Libraries/ExchangeLibrary.sol | 168 ++++++++++++++++++++++ 2 files changed, 192 insertions(+), 153 deletions(-) create mode 100644 contracts/Libraries/ExchangeLibrary.sol diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index e3e508d..78c303f 100644 --- a/contracts/Exchange.sol +++ b/contracts/Exchange.sol @@ -1,40 +1,27 @@ pragma solidity ^0.4.21; import "./ExchangeInterface.sol"; -import "./Libraries/SafeMath.sol"; -import "./Libraries/SignatureValidator.sol"; import "./Libraries/OrderLibrary.sol"; +import "./Libraries/ExchangeLibrary.sol"; import "./Ownership/Ownable.sol"; import "./Tokens/ERC20.sol"; -import "./HookSubscriber.sol"; contract Exchange is Ownable, ExchangeInterface { - using SafeMath for *; using OrderLibrary for OrderLibrary.Order; + using ExchangeLibrary for ExchangeLibrary.Exchange; address constant public ETH = 0x0; uint256 constant public MAX_FEE = 5000000000000000; // 0.5% ((0.5 / 100) * 10**18) - uint256 constant private MAX_ROUNDING_PERCENTAGE = 1000; // 0.1% - - uint256 constant private MAX_HOOK_GAS = 40000; // enough for a storage write and some accounting logic - VaultInterface public vault; - - uint public takerFee = 0; - address public feeAccount; - - mapping (address => mapping (bytes32 => bool)) private orders; - mapping (bytes32 => uint) private fills; - mapping (bytes32 => bool) private cancelled; - mapping (address => bool) private subscribed; + ExchangeLibrary.Exchange public exchange; function Exchange(uint _takerFee, address _feeAccount, VaultInterface _vault) public { require(address(_vault) != 0x0); setFees(_takerFee); setFeeAccount(_feeAccount); - vault = _vault; + exchange.vault = _vault; } /// @dev Withdraws tokens accidentally sent to this contract. @@ -51,15 +38,15 @@ contract Exchange is Ownable, ExchangeInterface { /// @dev Subscribes user to trade hooks. function subscribe() external { - require(!subscribed[msg.sender]); - subscribed[msg.sender] = true; + require(!exchange.subscribed[msg.sender]); + exchange.subscribed[msg.sender] = true; emit Subscribed(msg.sender); } /// @dev Unsubscribes user from trade hooks. function unsubscribe() external { - require(subscribed[msg.sender]); - subscribed[msg.sender] = false; + require(exchange.subscribed[msg.sender]); + exchange.subscribed[msg.sender] = false; emit Unsubscribed(msg.sender); } @@ -92,7 +79,7 @@ contract Exchange is Ownable, ExchangeInterface { /// @param signature Signed order along with signature mode. /// @param maxFillAmount Maximum amount of the order to be filled. function trade(address[3] addresses, uint[4] values, bytes signature, uint maxFillAmount) external { - trade(OrderLibrary.createOrder(addresses, values), msg.sender, signature, maxFillAmount); + exchange.trade(OrderLibrary.createOrder(addresses, values), msg.sender, signature, maxFillAmount); } /// @dev Cancels an order. @@ -105,10 +92,10 @@ contract Exchange is Ownable, ExchangeInterface { require(order.makerTokenAmount > 0 && order.takerTokenAmount > 0); bytes32 hash = order.hash(); - require(fills[hash] < order.takerTokenAmount); - require(!cancelled[hash]); + require(exchange.fills[hash] < order.takerTokenAmount); + require(!exchange.cancelled[hash]); - cancelled[hash] = true; + exchange.cancelled[hash] = true; emit Cancelled(hash); } @@ -121,16 +108,16 @@ contract Exchange is Ownable, ExchangeInterface { values ); - require(vault.isApproved(order.maker, this)); - require(vault.balanceOf(order.makerToken, order.maker) >= order.makerTokenAmount); + require(exchange.vault.isApproved(order.maker, this)); + require(exchange.vault.balanceOf(order.makerToken, order.maker) >= order.makerTokenAmount); require(order.makerToken != order.takerToken); require(order.makerTokenAmount > 0); require(order.takerTokenAmount > 0); bytes32 hash = order.hash(); - require(!orders[msg.sender][hash]); - orders[msg.sender][hash] = true; + require(!exchange.orders[msg.sender][hash]); + exchange.orders[msg.sender][hash] = true; emit Ordered( order.maker, @@ -154,17 +141,14 @@ contract Exchange is Ownable, ExchangeInterface { returns (bool) { OrderLibrary.Order memory order = OrderLibrary.createOrder(addresses, values); - - bytes32 hash = order.hash(); - - return canTrade(order, signature, hash); + return exchange.canTrade(order, signature, order.hash()); } /// @dev Returns if user has subscribed to trade hooks. /// @param subscriber Address of the subscriber. /// @return Boolean if user is subscribed. function isSubscribed(address subscriber) external view returns (bool) { - return subscribed[subscriber]; + return exchange.subscribed[subscriber]; } /// @dev Checks how much of an order can be filled. @@ -173,32 +157,32 @@ contract Exchange is Ownable, ExchangeInterface { /// @return Amount of the order which can be filled. function availableAmount(address[3] addresses, uint[4] values) external view returns (uint) { OrderLibrary.Order memory order = OrderLibrary.createOrder(addresses, values); - return availableAmount(order, order.hash()); + return exchange.availableAmount(order, order.hash()); } /// @dev Returns how much of an order was filled. /// @param hash Hash of the order. /// @return Amount which was filled. function filled(bytes32 hash) external view returns (uint) { - return fills[hash]; + return exchange.fills[hash]; } /// @dev Sets the taker fee. /// @param _takerFee New taker fee. function setFees(uint _takerFee) public onlyOwner { require(_takerFee <= MAX_FEE); - takerFee = _takerFee; + exchange.takerFee = _takerFee; } /// @dev Sets the account where fees will be transferred to. /// @param _feeAccount Address for the account. function setFeeAccount(address _feeAccount) public onlyOwner { require(_feeAccount != 0x0); - feeAccount = _feeAccount; + exchange.feeAccount = _feeAccount; } function vault() public view returns (VaultInterface) { - return vault; + return exchange.vault; } /// @dev Checks if an order was created on chain. @@ -206,120 +190,7 @@ contract Exchange is Ownable, ExchangeInterface { /// @param hash Hash of the order. /// @return Boolean if the order was created on chain. function isOrdered(address user, bytes32 hash) public view returns (bool) { - return orders[user][hash]; - } - - /// @dev Executes the actual trade by transferring balances. - /// @param order Order to be traded. - /// @param taker Address of the taker. - /// @param signature Signed order along with signature mode. - /// @param maxFillAmount Maximum amount of the order to be filled. - function trade(OrderLibrary.Order memory order, address taker, bytes signature, uint maxFillAmount) internal { - require(taker != order.maker); - bytes32 hash = order.hash(); - - require(order.makerToken != order.takerToken); - require(canTrade(order, signature, hash)); - - uint fillAmount = SafeMath.min256(maxFillAmount, availableAmount(order, hash)); - - require(roundingPercent(fillAmount, order.takerTokenAmount, order.makerTokenAmount) <= MAX_ROUNDING_PERCENTAGE); - require(vault.balanceOf(order.takerToken, taker) >= fillAmount); - - uint makeAmount = order.makerTokenAmount.mul(fillAmount).div(order.takerTokenAmount); - uint tradeTakerFee = makeAmount.mul(takerFee).div(1 ether); - - if (tradeTakerFee > 0) { - vault.transfer(order.makerToken, order.maker, feeAccount, tradeTakerFee); - } - - vault.transfer(order.takerToken, taker, order.maker, fillAmount); - vault.transfer(order.makerToken, order.maker, taker, makeAmount.sub(tradeTakerFee)); - - fills[hash] = fills[hash].add(fillAmount); - assert(fills[hash] <= order.takerTokenAmount); - - if (subscribed[order.maker]) { - order.maker.call.gas(MAX_HOOK_GAS)(HookSubscriber(order.maker).tradeExecuted.selector, order.takerToken, fillAmount); - } - - emit Traded( - hash, - order.makerToken, - makeAmount, - order.takerToken, - fillAmount, - order.maker, - taker - ); - } - - /// @dev Indicates whether or not an certain amount of an order can be traded. - /// @param order Order to be traded. - /// @param signature Signed order along with signature mode. - /// @param hash Hash of the order. - /// @return Boolean if order can be traded - function canTrade(OrderLibrary.Order memory order, bytes signature, bytes32 hash) - internal - view - returns (bool) - { - // if the order has never been traded against, we need to check the sig. - if (fills[hash] == 0) { - // ensures order was either created on chain, or signature is valid - if (!isOrdered(order.maker, hash) && !SignatureValidator.isValidSignature(hash, order.maker, signature)) { - return false; - } - } - - if (cancelled[hash]) { - return false; - } - - if (!vault.isApproved(order.maker, this)) { - return false; - } - - if (order.takerTokenAmount == 0) { - return false; - } - - if (order.makerTokenAmount == 0) { - return false; - } - - // ensures that the order still has an available amount to be filled. - if (availableAmount(order, hash) == 0) { - return false; - } - - return order.expires > now; - } - - /// @dev Returns the maximum available amount that can be taken of an order. - /// @param order Order to check. - /// @param hash Hash of the order. - /// @return Amount of the order that can be filled. - function availableAmount(OrderLibrary.Order memory order, bytes32 hash) internal view returns (uint) { - return SafeMath.min256( - order.takerTokenAmount.sub(fills[hash]), - vault.balanceOf(order.makerToken, order.maker).mul(order.takerTokenAmount).div(order.makerTokenAmount) - ); - } - - /// @dev Returns the percentage which was rounded when dividing. - /// @param numerator Numerator. - /// @param denominator Denominator. - /// @param target Value to multiply with. - /// @return Percentage rounded. - function roundingPercent(uint numerator, uint denominator, uint target) internal pure returns (uint) { - // Inspired by https://github.com/0xProject/contracts/blob/1.0.0/contracts/Exchange.sol#L472-L490 - uint remainder = mulmod(target, numerator, denominator); - if (remainder == 0) { - return 0; - } - - return remainder.mul(1000000).div(numerator.mul(target)); + return exchange.orders[user][hash]; } function sigArrayToBytes(bytes32[] sm, uint16[] sa, uint i) internal pure returns (bytes) { diff --git a/contracts/Libraries/ExchangeLibrary.sol b/contracts/Libraries/ExchangeLibrary.sol new file mode 100644 index 0000000..3e3a6e1 --- /dev/null +++ b/contracts/Libraries/ExchangeLibrary.sol @@ -0,0 +1,168 @@ +pragma solidity ^0.4.23; + +import "./OrderLibrary.sol"; +import "./SafeMath.sol"; +import "./SignatureValidator.sol"; +import "./../Vault/VaultInterface.sol"; +import "./../HookSubscriber.sol"; + +library ExchangeLibrary { + + using SafeMath for *; + using OrderLibrary for OrderLibrary.Order; + + event Traded( + bytes32 indexed hash, + address makerToken, + uint makerTokenAmount, + address takerToken, + uint takerTokenAmount, + address maker, + address taker + ); + + struct Exchange { + VaultInterface vault; + uint takerFee; + address feeAccount; + mapping (address => mapping (bytes32 => bool)) orders; + mapping (bytes32 => uint) fills; + mapping (bytes32 => bool) cancelled; + mapping (address => bool) subscribed; + } + + uint256 constant private MAX_ROUNDING_PERCENTAGE = 1000; // 0.1% + uint256 constant private MAX_HOOK_GAS = 40000; // enough for a storage write and some accounting logic + + /// @dev Executes the actual trade by transferring balances. + /// @param self Exchange storage. + /// @param order Order to be traded. + /// @param taker Address of the taker. + /// @param signature Signed order along with signature mode. + /// @param maxFillAmount Maximum amount of the order to be filled. + function trade( + Exchange storage self, + OrderLibrary.Order memory order, + address taker, + bytes signature, + uint maxFillAmount + ) + internal + { + require(taker != order.maker); + bytes32 hash = order.hash(); + + require(order.makerToken != order.takerToken); + require(canTrade(self, order, signature, hash)); + + uint fillAmount = SafeMath.min256(maxFillAmount, availableAmount(self, order, hash)); + + require(roundingPercent(fillAmount, order.takerTokenAmount, order.makerTokenAmount) <= MAX_ROUNDING_PERCENTAGE); + require(self.vault.balanceOf(order.takerToken, taker) >= fillAmount); + + uint makeAmount = order.makerTokenAmount.mul(fillAmount).div(order.takerTokenAmount); + uint tradeTakerFee = makeAmount.mul(self.takerFee).div(1 ether); + + if (tradeTakerFee > 0) { + self.vault.transfer(order.makerToken, order.maker, self.feeAccount, tradeTakerFee); + } + + self.vault.transfer(order.takerToken, taker, order.maker, fillAmount); + self.vault.transfer(order.makerToken, order.maker, taker, makeAmount.sub(tradeTakerFee)); + + self.fills[hash] = self.fills[hash].add(fillAmount); + assert(self.fills[hash] <= order.takerTokenAmount); + + if (self.subscribed[order.maker]) { + order.maker.call.gas(MAX_HOOK_GAS)( + HookSubscriber(order.maker).tradeExecuted.selector, + order.takerToken, + fillAmount + ); + } + + emit Traded( + hash, + order.makerToken, + makeAmount, + order.takerToken, + fillAmount, + order.maker, + taker + ); + } + + /// @dev Indicates whether or not an certain amount of an order can be traded. + /// @param self Exchange storage. + /// @param order Order to be traded. + /// @param signature Signed order along with signature mode. + /// @param hash Hash of the order. + /// @return Boolean if order can be traded + function canTrade(Exchange storage self, OrderLibrary.Order memory order, bytes signature, bytes32 hash) + internal + view + returns (bool) + { + // if the order has never been traded against, we need to check the sig. + if (self.fills[hash] == 0) { + // ensures order was either created on chain, or signature is valid + if (!self.orders[order.maker][hash] && !SignatureValidator.isValidSignature(hash, order.maker, signature)) { + return false; + } + } + + if (self.cancelled[hash]) { + return false; + } + + if (!self.vault.isApproved(order.maker, this)) { + return false; + } + + if (order.takerTokenAmount == 0) { + return false; + } + + if (order.makerTokenAmount == 0) { + return false; + } + + // ensures that the order still has an available amount to be filled. + if (availableAmount(self, order, hash) == 0) { + return false; + } + + return order.expires > now; + } + + /// @dev Returns the maximum available amount that can be taken of an order. + /// @param self Exchange storage. + /// @param order Order to check. + /// @param hash Hash of the order. + /// @return Amount of the order that can be filled. + function availableAmount(Exchange storage self, OrderLibrary.Order memory order, bytes32 hash) + internal + view + returns (uint) + { + return SafeMath.min256( + order.takerTokenAmount.sub(self.fills[hash]), + self.vault.balanceOf(order.makerToken, order.maker).mul(order.takerTokenAmount).div(order.makerTokenAmount) + ); + } + + /// @dev Returns the percentage which was rounded when dividing. + /// @param numerator Numerator. + /// @param denominator Denominator. + /// @param target Value to multiply with. + /// @return Percentage rounded. + function roundingPercent(uint numerator, uint denominator, uint target) internal pure returns (uint) { + // Inspired by https://github.com/0xProject/contracts/blob/1.0.0/contracts/Exchange.sol#L472-L490 + uint remainder = mulmod(target, numerator, denominator); + if (remainder == 0) { + return 0; + } + + return remainder.mul(1000000).div(numerator.mul(target)); + } +} From 68e1314c680d8fc3bfe953c9fd8505bfceb6dd4d Mon Sep 17 00:00:00 2001 From: mattdf Date: Sat, 28 Apr 2018 00:04:03 +0200 Subject: [PATCH 3/7] update to use lib, remove redundant vars/init --- contracts/Exchange.sol | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index 78c303f..07c17b0 100644 --- a/contracts/Exchange.sol +++ b/contracts/Exchange.sol @@ -51,17 +51,16 @@ contract Exchange is Ownable, ExchangeInterface { } - function multitrade(uint numOrders, address[] addresses, uint[] values, bytes32[] sigmain, uint16[] sigaux, uint maxFillAmount) external { - require(addresses.length == 3*numOrders); - require(values.length == 4*numOrders); - require(sigmain.length == 2*numOrders); - require(sigaux.length == numOrders); + function multitrade(address[] addresses, uint[] values, bytes32[] sigmain, uint16[] sigaux, uint maxFillAmount) external { + require(addresses.length == 3*sigaux.length); + require(values.length == 4*sigaux.length); + require(sigmain.length == 2*sigaux.length); address[3] memory addrs; uint[4] memory vals; - bytes memory s = new bytes(66); + bytes memory s; - for (uint i = 0; i < numOrders; i++){ + for (uint i = 0; i < sigaux.length; i++){ for (uint j = 0; j < 3; j++){ addrs[j] = addresses[(i*3)+j]; } @@ -69,7 +68,7 @@ contract Exchange is Ownable, ExchangeInterface { vals[j] = values[(i*4)+j]; } s = sigArrayToBytes(sigmain, sigaux, i); - trade(OrderLibrary.createOrder(addrs, vals), msg.sender, s, maxFillAmount); + exchange.trade(OrderLibrary.createOrder(addrs, vals), msg.sender, s, maxFillAmount); } } From 5ae887bd55525dcba7b455ab7baaa64b975a56a5 Mon Sep 17 00:00:00 2001 From: mattdf Date: Sat, 28 Apr 2018 00:19:10 +0200 Subject: [PATCH 4/7] add maxamount per trade --- contracts/Exchange.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index 07c17b0..5951325 100644 --- a/contracts/Exchange.sol +++ b/contracts/Exchange.sol @@ -51,10 +51,11 @@ contract Exchange is Ownable, ExchangeInterface { } - function multitrade(address[] addresses, uint[] values, bytes32[] sigmain, uint16[] sigaux, uint maxFillAmount) external { + function multitrade(address[] addresses, uint[] values, bytes32[] sigmain, uint16[] sigaux, uint[] maxFillAmount) external { require(addresses.length == 3*sigaux.length); require(values.length == 4*sigaux.length); require(sigmain.length == 2*sigaux.length); + require(maxFillAmount.length == sigaux.length); address[3] memory addrs; uint[4] memory vals; @@ -68,7 +69,7 @@ contract Exchange is Ownable, ExchangeInterface { vals[j] = values[(i*4)+j]; } s = sigArrayToBytes(sigmain, sigaux, i); - exchange.trade(OrderLibrary.createOrder(addrs, vals), msg.sender, s, maxFillAmount); + exchange.trade(OrderLibrary.createOrder(addrs, vals), msg.sender, s, maxFillAmount[i]); } } From 3ba1508a64be8b07c7a7bf60452c0f09ce6ba573 Mon Sep 17 00:00:00 2001 From: mattdf Date: Sat, 28 Apr 2018 00:42:24 +0200 Subject: [PATCH 5/7] add multifillupto for single token trades, make trade func return fill amounts --- contracts/Exchange.sol | 31 +++++++++++++++++++++++-- contracts/Libraries/ExchangeLibrary.sol | 4 +++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index 5951325..5a32460 100644 --- a/contracts/Exchange.sol +++ b/contracts/Exchange.sol @@ -51,6 +51,33 @@ contract Exchange is Ownable, ExchangeInterface { } + function multifillUpTo(address makerToken, address takerToken, address[] makers, uint[] values, bytes32[] sigmain, uint16[] sigaux, uint maxFillAmount) external { + require(makers.length == sigaux.length); + require(makers.length*2 == sigmain.length); + require(makers.length*4 == values.length); + + address[3] memory addrs; + uint[4] memory vals; + bytes memory s; + uint filledSoFar; + + for (uint i = 0; i < makers.length; i++){ + for (uint j = 0; j < 4; j++){ + vals[j] = values[i*4 + j]; + } + addrs[0] = makers[i]; + addrs[1] = makerToken; + addrs[2] = takerToken; + s = sigArrayToBytes(sigmain, sigaux, i); + uint filled = exchange.trade(OrderLibrary.createOrder(addrs, vals), msg.sender, s, maxFillAmount); + filledSoFar = filledSoFar + filled; + if (filledSoFar >= maxFillAmount){ + return; + } + } + } + + function multitrade(address[] addresses, uint[] values, bytes32[] sigmain, uint16[] sigaux, uint[] maxFillAmount) external { require(addresses.length == 3*sigaux.length); require(values.length == 4*sigaux.length); @@ -78,8 +105,8 @@ contract Exchange is Ownable, ExchangeInterface { /// @param values Array of trade's makerTokenAmount, takerTokenAmount, expires and nonce. /// @param signature Signed order along with signature mode. /// @param maxFillAmount Maximum amount of the order to be filled. - function trade(address[3] addresses, uint[4] values, bytes signature, uint maxFillAmount) external { - exchange.trade(OrderLibrary.createOrder(addresses, values), msg.sender, signature, maxFillAmount); + function trade(address[3] addresses, uint[4] values, bytes signature, uint maxFillAmount) external returns (uint) { + return exchange.trade(OrderLibrary.createOrder(addresses, values), msg.sender, signature, maxFillAmount); } /// @dev Cancels an order. diff --git a/contracts/Libraries/ExchangeLibrary.sol b/contracts/Libraries/ExchangeLibrary.sol index 3e3a6e1..7fdcb05 100644 --- a/contracts/Libraries/ExchangeLibrary.sol +++ b/contracts/Libraries/ExchangeLibrary.sol @@ -47,7 +47,7 @@ library ExchangeLibrary { bytes signature, uint maxFillAmount ) - internal + internal returns (uint) { require(taker != order.maker); bytes32 hash = order.hash(); @@ -90,6 +90,8 @@ library ExchangeLibrary { order.maker, taker ); + + return fillAmount; } /// @dev Indicates whether or not an certain amount of an order can be traded. From afa39be0ea4a38c5e2c0ec20626d6c143324379d Mon Sep 17 00:00:00 2001 From: mattdf Date: Sat, 28 Apr 2018 00:46:31 +0200 Subject: [PATCH 6/7] made maxfill calc in fillupto work --- contracts/Exchange.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index 5a32460..f9232a7 100644 --- a/contracts/Exchange.sol +++ b/contracts/Exchange.sol @@ -59,7 +59,7 @@ contract Exchange is Ownable, ExchangeInterface { address[3] memory addrs; uint[4] memory vals; bytes memory s; - uint filledSoFar; + uint filledSoFar = 0; for (uint i = 0; i < makers.length; i++){ for (uint j = 0; j < 4; j++){ @@ -69,7 +69,7 @@ contract Exchange is Ownable, ExchangeInterface { addrs[1] = makerToken; addrs[2] = takerToken; s = sigArrayToBytes(sigmain, sigaux, i); - uint filled = exchange.trade(OrderLibrary.createOrder(addrs, vals), msg.sender, s, maxFillAmount); + uint filled = exchange.trade(OrderLibrary.createOrder(addrs, vals), msg.sender, s, maxFillAmount-filledSoFar); filledSoFar = filledSoFar + filled; if (filledSoFar >= maxFillAmount){ return; From a62b32a3494e788de2a481d96bb9eaa10711ff81 Mon Sep 17 00:00:00 2001 From: mattdf Date: Sat, 28 Apr 2018 01:06:36 +0200 Subject: [PATCH 7/7] fix sig byte storage offset --- contracts/Exchange.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index f9232a7..e14a763 100644 --- a/contracts/Exchange.sol +++ b/contracts/Exchange.sol @@ -224,11 +224,14 @@ contract Exchange is Ownable, ExchangeInterface { bytes32 s1 = sm[i*2]; bytes32 s2 = sm[i*2 + 1]; uint16 s3 = sa[i]; + uint8 s4 = uint8(s3 % 256); + s3 = (s3 - uint16(s4)) / 256; bytes memory s = new bytes(66); assembly { mstore(add(s, 32), s1) mstore(add(s, 64), s2) - mstore(add(s, 96), s3) + mstore8(add(s, 96), s3) + mstore8(add(s, 97), s4) } } }