From d9092c51195bc1ebaff46cc5acd61093a7b5650b Mon Sep 17 00:00:00 2001 From: kongliangzhong Date: Thu, 19 Apr 2018 11:11:33 +0800 Subject: [PATCH 1/4] add OrderTracer --- contracts/LoopringProtocolImpl.sol | 34 +++++++--------- contracts/OrderTracer.sol | 65 ++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 19 deletions(-) create mode 100644 contracts/OrderTracer.sol diff --git a/contracts/LoopringProtocolImpl.sol b/contracts/LoopringProtocolImpl.sol index 5fbcb618..15412124 100644 --- a/contracts/LoopringProtocolImpl.sol +++ b/contracts/LoopringProtocolImpl.sol @@ -22,6 +22,7 @@ import "./lib/MathUint.sol"; import "./LoopringProtocol.sol"; import "./TokenRegistry.sol"; import "./TokenTransferDelegate.sol"; +import "./OrderTracer.sol"; /// @title An Implementation of LoopringProtocol. @@ -41,6 +42,7 @@ contract LoopringProtocolImpl is LoopringProtocol { address public lrcTokenAddress = 0x0; address public tokenRegistryAddress = 0x0; address public delegateAddress = 0x0; + address public orderTracerAddress = 0x0; uint64 public ringIndex = 0; uint8 public walletSplitPercentage = 0; @@ -60,19 +62,6 @@ contract LoopringProtocolImpl is LoopringProtocol { uint public constant RATE_RATIO_SCALE = 10000; - // The following map is used to keep trace of order fill and cancellation - // history. - mapping (bytes32 => uint) public cancelledOrFilled; - - // This map is used to keep trace of order's cancellation history. - mapping (bytes32 => uint) public cancelled; - - // A map from address to its cutoff timestamp. - mapping (address => uint) public cutoffs; - - // A map from address to its trading-pair cutoff timestamp. - mapping (address => mapping (bytes20 => uint)) public tradingPairCutoffs; - /// @param orderHash The order's hash /// @param feeSelection - /// A miner-supplied value indicating if LRC (value = 0) @@ -126,6 +115,7 @@ contract LoopringProtocolImpl is LoopringProtocol { address _lrcTokenAddress, address _tokenRegistryAddress, address _delegateAddress, + address _orderTracerAddress, uint _rateRatioCVSThreshold, uint8 _walletSplitPercentage ) @@ -134,6 +124,7 @@ contract LoopringProtocolImpl is LoopringProtocol { require(_lrcTokenAddress.isContract()); require(_tokenRegistryAddress.isContract()); require(_delegateAddress.isContract()); + require(_orderTracerAddress.isContract()); require(_rateRatioCVSThreshold > 0); require(_walletSplitPercentage > 0 && _walletSplitPercentage < 100); @@ -141,6 +132,7 @@ contract LoopringProtocolImpl is LoopringProtocol { lrcTokenAddress = _lrcTokenAddress; tokenRegistryAddress = _tokenRegistryAddress; delegateAddress = _delegateAddress; + orderTracerAddress = _orderTracerAddress; rateRatioCVSThreshold = _rateRatioCVSThreshold; walletSplitPercentage = _walletSplitPercentage; } @@ -204,8 +196,9 @@ contract LoopringProtocolImpl is LoopringProtocol { s ); - cancelled[orderHash] = cancelled[orderHash].add(cancelAmount); - cancelledOrFilled[orderHash] = cancelledOrFilled[orderHash].add(cancelAmount); + OrderTracer orderTracer = OrderTracer(orderTracerAddress); + orderTracer.addCancelled(orderHash, cancelAmount); + orderTracer.addCancelledOrFilled(orderHash, cancelAmount); emit OrderCancelled(orderHash, cancelAmount); } @@ -220,10 +213,12 @@ contract LoopringProtocolImpl is LoopringProtocol { uint t = (cutoff == 0 || cutoff >= block.timestamp) ? block.timestamp : cutoff; bytes20 tokenPair = bytes20(token1) ^ bytes20(token2); - require(tradingPairCutoffs[msg.sender][tokenPair] < t); + OrderTracer orderTracer = OrderTracer(orderTracerAddress); + + require(orderTracer.tradingPairCutoffs(msg.sender, tokenPair) < t); // "attempted to set cutoff to a smaller value" - tradingPairCutoffs[msg.sender][tokenPair] = t; + orderTracer.setTradingPairCutoffs(tokenPair, t); emit OrdersCancelled( msg.sender, token1, @@ -238,10 +233,11 @@ contract LoopringProtocolImpl is LoopringProtocol { external { uint t = (cutoff == 0 || cutoff >= block.timestamp) ? block.timestamp : cutoff; + OrderTracer orderTracer = OrderTracer(orderTracerAddress); - require(cutoffs[msg.sender] < t); // "attempted to set cutoff to a smaller value" + require(orderTracer.cutoffs(msg.sender) < t); // "attempted to set cutoff to a smaller value" - cutoffs[msg.sender] = t; + orderTracer.setCutoffs(t); emit AllOrdersCancelled(msg.sender, t); } diff --git a/contracts/OrderTracer.sol b/contracts/OrderTracer.sol new file mode 100644 index 00000000..ce79a428 --- /dev/null +++ b/contracts/OrderTracer.sol @@ -0,0 +1,65 @@ +/* + + Copyright 2017 Loopring Project Ltd (Loopring Foundation). + + 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.21; + + +/// @title OrderTracer +/// @author Kongliang Zhong - . +contract OrderTracer { + + // The following map is used to keep trace of order fill and cancellation + // history. + mapping (bytes32 => uint) public cancelledOrFilled; + + // This map is used to keep trace of order's cancellation history. + mapping (bytes32 => uint) public cancelled; + + // A map from address to its cutoff timestamp. + mapping (address => uint) public cutoffs; + + // A map from address to its trading-pair cutoff timestamp. + mapping (address => mapping (bytes20 => uint)) public tradingPairCutoffs; + + function addCancelled(bytes32 orderHash, uint cancelAmount) + onlyAuthorized + external + { + cancelled[orderHash] = cancelled[orderHash].add(cancelAmount); + } + + function addCancelledOrFilled(bytes32 orderHash, uint cancelOrFillAmount) + onlyAuthorized + external + { + cancelledOrFilled[orderHash] = cancelledOrFilled[orderHash].add(cancelOrFillAmount); + } + + function setCutoffs(uint t) + onlyAuthorized + external + { + cutoffs[tx.origin] = t; + } + + function setTradingPairCutoffs(bytes20 tokenPair, uint t) + onlyAuthorized + external + { + tradingPairCutoffs[tx.origin][tokenPair] = t; + } + +} From cdbb7fa86e7fff6fdf4e1d6c8d2cef4c0e5c3fdc Mon Sep 17 00:00:00 2001 From: kongliangzhong Date: Thu, 19 Apr 2018 12:20:48 +0800 Subject: [PATCH 2/4] change the way orders are signed: sign orders with delegate's address --- contracts/LoopringProtocolImpl.sol | 42 ++++++++-------- contracts/OrderTracer.sol | 65 ------------------------- contracts/TokenTransferDelegate.sol | 26 ++++++++++ contracts/TokenTransferDelegateImpl.sol | 29 +++++++++++ test/testLoopringProtocolImpl.ts | 8 +-- 5 files changed, 79 insertions(+), 91 deletions(-) delete mode 100644 contracts/OrderTracer.sol diff --git a/contracts/LoopringProtocolImpl.sol b/contracts/LoopringProtocolImpl.sol index 15412124..e47dc48d 100644 --- a/contracts/LoopringProtocolImpl.sol +++ b/contracts/LoopringProtocolImpl.sol @@ -22,7 +22,6 @@ import "./lib/MathUint.sol"; import "./LoopringProtocol.sol"; import "./TokenRegistry.sol"; import "./TokenTransferDelegate.sol"; -import "./OrderTracer.sol"; /// @title An Implementation of LoopringProtocol. @@ -42,7 +41,6 @@ contract LoopringProtocolImpl is LoopringProtocol { address public lrcTokenAddress = 0x0; address public tokenRegistryAddress = 0x0; address public delegateAddress = 0x0; - address public orderTracerAddress = 0x0; uint64 public ringIndex = 0; uint8 public walletSplitPercentage = 0; @@ -115,7 +113,6 @@ contract LoopringProtocolImpl is LoopringProtocol { address _lrcTokenAddress, address _tokenRegistryAddress, address _delegateAddress, - address _orderTracerAddress, uint _rateRatioCVSThreshold, uint8 _walletSplitPercentage ) @@ -124,7 +121,6 @@ contract LoopringProtocolImpl is LoopringProtocol { require(_lrcTokenAddress.isContract()); require(_tokenRegistryAddress.isContract()); require(_delegateAddress.isContract()); - require(_orderTracerAddress.isContract()); require(_rateRatioCVSThreshold > 0); require(_walletSplitPercentage > 0 && _walletSplitPercentage < 100); @@ -132,7 +128,6 @@ contract LoopringProtocolImpl is LoopringProtocol { lrcTokenAddress = _lrcTokenAddress; tokenRegistryAddress = _tokenRegistryAddress; delegateAddress = _delegateAddress; - orderTracerAddress = _orderTracerAddress; rateRatioCVSThreshold = _rateRatioCVSThreshold; walletSplitPercentage = _walletSplitPercentage; } @@ -196,9 +191,9 @@ contract LoopringProtocolImpl is LoopringProtocol { s ); - OrderTracer orderTracer = OrderTracer(orderTracerAddress); - orderTracer.addCancelled(orderHash, cancelAmount); - orderTracer.addCancelledOrFilled(orderHash, cancelAmount); + TokenTransferDelegate delegate = TokenTransferDelegate(delegateAddress); + delegate.addCancelled(orderHash, cancelAmount); + delegate.addCancelledOrFilled(orderHash, cancelAmount); emit OrderCancelled(orderHash, cancelAmount); } @@ -213,12 +208,12 @@ contract LoopringProtocolImpl is LoopringProtocol { uint t = (cutoff == 0 || cutoff >= block.timestamp) ? block.timestamp : cutoff; bytes20 tokenPair = bytes20(token1) ^ bytes20(token2); - OrderTracer orderTracer = OrderTracer(orderTracerAddress); + TokenTransferDelegate delegate = TokenTransferDelegate(delegateAddress); - require(orderTracer.tradingPairCutoffs(msg.sender, tokenPair) < t); + require(delegate.tradingPairCutoffs(msg.sender, tokenPair) < t); // "attempted to set cutoff to a smaller value" - orderTracer.setTradingPairCutoffs(tokenPair, t); + delegate.setTradingPairCutoffs(tokenPair, t); emit OrdersCancelled( msg.sender, token1, @@ -233,11 +228,11 @@ contract LoopringProtocolImpl is LoopringProtocol { external { uint t = (cutoff == 0 || cutoff >= block.timestamp) ? block.timestamp : cutoff; - OrderTracer orderTracer = OrderTracer(orderTracerAddress); + TokenTransferDelegate delegate = TokenTransferDelegate(delegateAddress); - require(orderTracer.cutoffs(msg.sender) < t); // "attempted to set cutoff to a smaller value" + require(delegate.cutoffs(msg.sender) < t); // "attempted to set cutoff to a smaller value" - orderTracer.setCutoffs(t); + delegate.setCutoffs(t); emit AllOrdersCancelled(msg.sender, t); } @@ -456,9 +451,9 @@ contract LoopringProtocolImpl is LoopringProtocol { // Update fill records if (state.buyNoMoreThanAmountB) { - cancelledOrFilled[state.orderHash] += nextFillAmountS; + delegate.addCancelledOrFilled(state.orderHash, nextFillAmountS); } else { - cancelledOrFilled[state.orderHash] += state.fillAmountS; + delegate.addCancelledOrFilled(state.orderHash, state.fillAmountS); } orderHashList[i] = state.orderHash; @@ -720,7 +715,7 @@ contract LoopringProtocolImpl is LoopringProtocol { if (state.buyNoMoreThanAmountB) { amount = state.amountB.tolerantSub( - cancelledOrFilled[state.orderHash] + delegate.cancelledOrFilled(state.orderHash) ); state.amountS = amount.mul(state.amountS) / state.amountB; @@ -729,7 +724,7 @@ contract LoopringProtocolImpl is LoopringProtocol { state.amountB = amount; } else { amount = state.amountS.tolerantSub( - cancelledOrFilled[state.orderHash] + delegate.cancelledOrFilled(state.orderHash) ); state.amountB = amount.mul(state.amountB) / state.amountS; @@ -885,9 +880,11 @@ contract LoopringProtocolImpl is LoopringProtocol { require(order.validUntil > block.timestamp); // order is expired bytes20 tradingPair = bytes20(order.tokenS) ^ bytes20(order.tokenB); - require(order.validSince > tradingPairCutoffs[order.owner][tradingPair]); + + TokenTransferDelegate delegate = TokenTransferDelegate(delegateAddress); + require(order.validSince > delegate.tradingPairCutoffs(order.owner, tradingPair)); // order trading pair is cut off - require(order.validSince > cutoffs[order.owner]); // order is cut off + require(order.validSince > delegate.cutoffs(order.owner)); // order is cut off } /// @dev Get the Keccak-256 hash of order with specified parameters. @@ -899,7 +896,7 @@ contract LoopringProtocolImpl is LoopringProtocol { returns (bytes32) { return keccak256( - address(this), + delegateAddress, order.owner, order.tokenS, order.tokenB, @@ -946,6 +943,7 @@ contract LoopringProtocolImpl is LoopringProtocol { returns (uint) { bytes20 tokenPair = bytes20(token1) ^ bytes20(token2); - return tradingPairCutoffs[orderOwner][tokenPair]; + TokenTransferDelegate delegate = TokenTransferDelegate(delegateAddress); + return delegate.tradingPairCutoffs(orderOwner, tokenPair); } } diff --git a/contracts/OrderTracer.sol b/contracts/OrderTracer.sol deleted file mode 100644 index ce79a428..00000000 --- a/contracts/OrderTracer.sol +++ /dev/null @@ -1,65 +0,0 @@ -/* - - Copyright 2017 Loopring Project Ltd (Loopring Foundation). - - 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.21; - - -/// @title OrderTracer -/// @author Kongliang Zhong - . -contract OrderTracer { - - // The following map is used to keep trace of order fill and cancellation - // history. - mapping (bytes32 => uint) public cancelledOrFilled; - - // This map is used to keep trace of order's cancellation history. - mapping (bytes32 => uint) public cancelled; - - // A map from address to its cutoff timestamp. - mapping (address => uint) public cutoffs; - - // A map from address to its trading-pair cutoff timestamp. - mapping (address => mapping (bytes20 => uint)) public tradingPairCutoffs; - - function addCancelled(bytes32 orderHash, uint cancelAmount) - onlyAuthorized - external - { - cancelled[orderHash] = cancelled[orderHash].add(cancelAmount); - } - - function addCancelledOrFilled(bytes32 orderHash, uint cancelOrFillAmount) - onlyAuthorized - external - { - cancelledOrFilled[orderHash] = cancelledOrFilled[orderHash].add(cancelOrFillAmount); - } - - function setCutoffs(uint t) - onlyAuthorized - external - { - cutoffs[tx.origin] = t; - } - - function setTradingPairCutoffs(bytes20 tokenPair, uint t) - onlyAuthorized - external - { - tradingPairCutoffs[tx.origin][tokenPair] = t; - } - -} diff --git a/contracts/TokenTransferDelegate.sol b/contracts/TokenTransferDelegate.sol index 5d11716a..2dfa4838 100644 --- a/contracts/TokenTransferDelegate.sol +++ b/contracts/TokenTransferDelegate.sol @@ -25,6 +25,19 @@ contract TokenTransferDelegate { event AddressAuthorized(address indexed addr, uint32 number); event AddressDeauthorized(address indexed addr, uint32 number); + // The following map is used to keep trace of order fill and cancellation + // history. + mapping (bytes32 => uint) public cancelledOrFilled; + + // This map is used to keep trace of order's cancellation history. + mapping (bytes32 => uint) public cancelled; + + // A map from address to its cutoff timestamp. + mapping (address => uint) public cutoffs; + + // A map from address to its trading-pair cutoff timestamp. + mapping (address => mapping (bytes20 => uint)) public tradingPairCutoffs; + /// @dev Add a Loopring protocol address. /// @param addr A loopring protocol address. function authorizeAddress( @@ -73,4 +86,17 @@ contract TokenTransferDelegate { public view returns (bool); + + function addCancelled(bytes32 orderHash, uint cancelAmount) + external; + + function addCancelledOrFilled(bytes32 orderHash, uint cancelOrFillAmount) + external; + + function setCutoffs(uint t) + external; + + function setTradingPairCutoffs(bytes20 tokenPair, uint t) + external; + } diff --git a/contracts/TokenTransferDelegateImpl.sol b/contracts/TokenTransferDelegateImpl.sol index 8d7b831e..3c51e05c 100644 --- a/contracts/TokenTransferDelegateImpl.sol +++ b/contracts/TokenTransferDelegateImpl.sol @@ -246,4 +246,33 @@ contract TokenTransferDelegateImpl is TokenTransferDelegate, Claimable { ); } } + + function addCancelled(bytes32 orderHash, uint cancelAmount) + onlyAuthorized + external + { + cancelled[orderHash] = cancelled[orderHash].add(cancelAmount); + } + + function addCancelledOrFilled(bytes32 orderHash, uint cancelOrFillAmount) + onlyAuthorized + external + { + cancelledOrFilled[orderHash] = cancelledOrFilled[orderHash].add(cancelOrFillAmount); + } + + function setCutoffs(uint t) + onlyAuthorized + external + { + cutoffs[tx.origin] = t; + } + + function setTradingPairCutoffs(bytes20 tokenPair, uint t) + onlyAuthorized + external + { + tradingPairCutoffs[tx.origin][tokenPair] = t; + } + } diff --git a/test/testLoopringProtocolImpl.ts b/test/testLoopringProtocolImpl.ts index dc61c0d7..b795bd80 100644 --- a/test/testLoopringProtocolImpl.ts +++ b/test/testLoopringProtocolImpl.ts @@ -111,7 +111,7 @@ contract("LoopringProtocolImpl", (accounts: string[]) => { const currBlockNumber = web3.eth.blockNumber; currBlockTimeStamp = web3.eth.getBlock(currBlockNumber).timestamp; - ringFactory = new RingFactory(LoopringProtocolImpl.address, + ringFactory = new RingFactory(TokenTransferDelegate.address, eosAddress, neoAddress, lrcAddress, @@ -856,7 +856,7 @@ contract("LoopringProtocolImpl", (accounts: string[]) => { order.params.lrcFee, cancelAmount]; - const cancelledOrFilledAmount0 = await loopringProtocolImpl.cancelledOrFilled(order.params.orderHashHex); + const cancelledOrFilledAmount0 = await tokenTransferDelegate.cancelledOrFilled(order.params.orderHashHex); const tx = await loopringProtocolImpl.cancelOrder(addresses, orderValues, order.params.buyNoMoreThanAmountB, @@ -866,7 +866,7 @@ contract("LoopringProtocolImpl", (accounts: string[]) => { order.params.s, {from: order.owner}); - const cancelledOrFilledAmount1 = await loopringProtocolImpl.cancelledOrFilled(order.params.orderHashHex); + const cancelledOrFilledAmount1 = await tokenTransferDelegate.cancelledOrFilled(order.params.orderHashHex); assert.equal(cancelledOrFilledAmount1.minus(cancelledOrFilledAmount0).toNumber(), cancelAmount.toNumber(), "cancelled amount not match"); }); @@ -913,7 +913,7 @@ contract("LoopringProtocolImpl", (accounts: string[]) => { describe("cancelAllOrders", () => { it("should be able to set cutoffs", async () => { await loopringProtocolImpl.cancelAllOrders(new BigNumber(1508566125), {from: order2Owner}); - const cutoff = await loopringProtocolImpl.cutoffs(order2Owner); + const cutoff = await tokenTransferDelegate.cutoffs(order2Owner); assert.equal(cutoff.toNumber(), 1508566125, "cutoff not set correctly"); }); From 5d82f11b4456312763afbf70130b73b0d328725c Mon Sep 17 00:00:00 2001 From: kongliangzhong Date: Thu, 19 Apr 2018 12:42:48 +0800 Subject: [PATCH 3/4] optimize --- contracts/LoopringProtocolImpl.sol | 22 +++++++++++++++++----- contracts/TokenTransferDelegate.sol | 3 +++ contracts/TokenTransferDelegateImpl.sol | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/contracts/LoopringProtocolImpl.sol b/contracts/LoopringProtocolImpl.sol index e47dc48d..3441461f 100644 --- a/contracts/LoopringProtocolImpl.sol +++ b/contracts/LoopringProtocolImpl.sol @@ -812,7 +812,6 @@ contract LoopringProtocolImpl is LoopringProtocol { orders = new OrderState[](params.ringSize); for (uint i = 0; i < params.ringSize; i++) { - bool marginSplitAsFee = (params.feeSelections & (uint16(1) << i)) > 0; orders[i] = OrderState( addressList[i][0], @@ -854,6 +853,8 @@ contract LoopringProtocolImpl is LoopringProtocol { params.ringHash ^= orderHash; } + validateOrdersCutoffs(orders); + params.ringHash = keccak256( params.ringHash, params.miner, @@ -878,13 +879,24 @@ contract LoopringProtocolImpl is LoopringProtocol { require(order.validSince <= block.timestamp); // order is too early to match require(order.validUntil > block.timestamp); // order is expired + } - bytes20 tradingPair = bytes20(order.tokenS) ^ bytes20(order.tokenB); + function validateOrdersCutoffs(OrderState[] orders) + private + view + { + address[] memory owners = new address[](orders.length); + bytes20[] memory tradingPairs = new bytes20[](orders.length); + uint[] memory validSinceTimes = new uint[](orders.length); + + for (uint i = 0; i < orders.length; i++) { + owners[i] = orders[i].owner; + tradingPairs[i] = bytes20(orders[i].tokenS) ^ bytes20(orders[i].tokenB); + validSinceTimes[i] = orders[i].validSince; + } TokenTransferDelegate delegate = TokenTransferDelegate(delegateAddress); - require(order.validSince > delegate.tradingPairCutoffs(order.owner, tradingPair)); - // order trading pair is cut off - require(order.validSince > delegate.cutoffs(order.owner)); // order is cut off + delegate.checkCutoffsBatch(owners, tradingPairs, validSinceTimes); } /// @dev Get the Keccak-256 hash of order with specified parameters. diff --git a/contracts/TokenTransferDelegate.sol b/contracts/TokenTransferDelegate.sol index 2dfa4838..ae9ad1e0 100644 --- a/contracts/TokenTransferDelegate.sol +++ b/contracts/TokenTransferDelegate.sol @@ -99,4 +99,7 @@ contract TokenTransferDelegate { function setTradingPairCutoffs(bytes20 tokenPair, uint t) external; + function checkCutoffsBatch(address[] owners, bytes20[] tradingPairs, uint[] validSince) + external + view; } diff --git a/contracts/TokenTransferDelegateImpl.sol b/contracts/TokenTransferDelegateImpl.sol index 3c51e05c..32f33eee 100644 --- a/contracts/TokenTransferDelegateImpl.sol +++ b/contracts/TokenTransferDelegateImpl.sol @@ -275,4 +275,18 @@ contract TokenTransferDelegateImpl is TokenTransferDelegate, Claimable { tradingPairCutoffs[tx.origin][tokenPair] = t; } + function checkCutoffsBatch(address[] owners, bytes20[] tradingPairs, uint[] validSince) + external + view + { + uint len = owners.length; + require(len == tradingPairs.length); + require(len == validSince.length); + + for(uint i = 0; i < len; i++) { + require(validSince[i] > tradingPairCutoffs[owners[i]][tradingPairs[i]]); // order trading pair is cut off + require(validSince[i] > cutoffs[owners[i]]); // order is cut off + } + } + } From ddbdc27353e839ec823bbbab8108ef1c35088f9d Mon Sep 17 00:00:00 2001 From: kongliangzhong Date: Thu, 19 Apr 2018 14:00:15 +0800 Subject: [PATCH 4/4] minor optimization --- contracts/LoopringProtocolImpl.sol | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/contracts/LoopringProtocolImpl.sol b/contracts/LoopringProtocolImpl.sol index 3441461f..6435e374 100644 --- a/contracts/LoopringProtocolImpl.sol +++ b/contracts/LoopringProtocolImpl.sol @@ -278,8 +278,10 @@ contract LoopringProtocolImpl is LoopringProtocol { // Assemble input data into structs so we can pass them to other functions. // This method also calculates ringHash, therefore it must be called before // calling `verifyRingSignatures`. + TokenTransferDelegate delegate = TokenTransferDelegate(delegateAddress); OrderState[] memory orders = assembleOrders( params, + delegate, addressList, uintArgsList, uint8ArgsList, @@ -290,7 +292,7 @@ contract LoopringProtocolImpl is LoopringProtocol { verifyTokensRegistered(params, orders); - handleRing(_ringIndex, params, orders); + handleRing(_ringIndex, params, orders, delegate); ringIndex = _ringIndex + 1; } @@ -357,12 +359,12 @@ contract LoopringProtocolImpl is LoopringProtocol { function handleRing( uint64 _ringIndex, RingParams params, - OrderState[] orders + OrderState[] orders, + TokenTransferDelegate delegate ) private { address _lrcTokenAddress = lrcTokenAddress; - TokenTransferDelegate delegate = TokenTransferDelegate(delegateAddress); // Do the hard work. verifyRingHasNoSubRing(params.ringSize, orders); @@ -800,6 +802,7 @@ contract LoopringProtocolImpl is LoopringProtocol { /// @return A list of orders. function assembleOrders( RingParams params, + TokenTransferDelegate delegate, address[4][] addressList, uint[6][] uintArgsList, uint8[1][] uint8ArgsList, @@ -853,7 +856,7 @@ contract LoopringProtocolImpl is LoopringProtocol { params.ringHash ^= orderHash; } - validateOrdersCutoffs(orders); + validateOrdersCutoffs(orders, delegate); params.ringHash = keccak256( params.ringHash, @@ -881,7 +884,7 @@ contract LoopringProtocolImpl is LoopringProtocol { require(order.validUntil > block.timestamp); // order is expired } - function validateOrdersCutoffs(OrderState[] orders) + function validateOrdersCutoffs(OrderState[] orders, TokenTransferDelegate delegate) private view { @@ -895,7 +898,6 @@ contract LoopringProtocolImpl is LoopringProtocol { validSinceTimes[i] = orders[i].validSince; } - TokenTransferDelegate delegate = TokenTransferDelegate(delegateAddress); delegate.checkCutoffsBatch(owners, tradingPairs, validSinceTimes); }