11pragma solidity ^ 0.4.21 ;
22
33import "./ExchangeInterface.sol " ;
4- import "./Libraries/SafeMath.sol " ;
5- import "./Libraries/SignatureValidator.sol " ;
64import "./Libraries/OrderLibrary.sol " ;
5+ import "./Libraries/ExchangeLibrary.sol " ;
76import "./Ownership/Ownable.sol " ;
87import "./Tokens/ERC20.sol " ;
9- import "./HookSubscriber.sol " ;
108
119contract Exchange is Ownable , ExchangeInterface {
1210
13- using SafeMath for * ;
1411 using OrderLibrary for OrderLibrary.Order;
12+ using ExchangeLibrary for ExchangeLibrary.Exchange;
1513
1614 address constant public ETH = 0x0 ;
1715
1816 uint256 constant public MAX_FEE = 5000000000000000 ; // 0.5% ((0.5 / 100) * 10**18)
19- uint256 constant private MAX_ROUNDING_PERCENTAGE = 1000 ; // 0.1%
20-
21- uint256 constant private MAX_HOOK_GAS = 40000 ; // enough for a storage write and some accounting logic
2217
23- VaultInterface public vault;
24-
25- uint public takerFee = 0 ;
26- address public feeAccount;
27-
28- mapping (address => mapping (bytes32 => bool )) private orders;
29- mapping (bytes32 => uint ) private fills;
30- mapping (bytes32 => bool ) private cancelled;
31- mapping (address => bool ) private subscribed;
18+ ExchangeLibrary.Exchange public exchange;
3219
3320 function Exchange (uint _takerFee , address _feeAccount , VaultInterface _vault ) public {
3421 require (address (_vault) != 0x0 );
3522 setFees (_takerFee);
3623 setFeeAccount (_feeAccount);
37- vault = _vault;
24+ exchange. vault = _vault;
3825 }
3926
4027 /// @dev Withdraws tokens accidentally sent to this contract.
@@ -51,15 +38,15 @@ contract Exchange is Ownable, ExchangeInterface {
5138
5239 /// @dev Subscribes user to trade hooks.
5340 function subscribe () external {
54- require (! subscribed[msg .sender ]);
55- subscribed[msg .sender ] = true ;
41+ require (! exchange. subscribed[msg .sender ]);
42+ exchange. subscribed[msg .sender ] = true ;
5643 emit Subscribed (msg .sender );
5744 }
5845
5946 /// @dev Unsubscribes user from trade hooks.
6047 function unsubscribe () external {
61- require (subscribed[msg .sender ]);
62- subscribed[msg .sender ] = false ;
48+ require (exchange. subscribed[msg .sender ]);
49+ exchange. subscribed[msg .sender ] = false ;
6350 emit Unsubscribed (msg .sender );
6451 }
6552
@@ -92,7 +79,7 @@ contract Exchange is Ownable, ExchangeInterface {
9279 /// @param signature Signed order along with signature mode.
9380 /// @param maxFillAmount Maximum amount of the order to be filled.
9481 function trade (address [3 ] addresses , uint [4 ] values , bytes signature , uint maxFillAmount ) external {
95- trade (OrderLibrary.createOrder (addresses, values), msg .sender , signature, maxFillAmount);
82+ exchange. trade (OrderLibrary.createOrder (addresses, values), msg .sender , signature, maxFillAmount);
9683 }
9784
9885 /// @dev Cancels an order.
@@ -105,10 +92,10 @@ contract Exchange is Ownable, ExchangeInterface {
10592 require (order.makerTokenAmount > 0 && order.takerTokenAmount > 0 );
10693
10794 bytes32 hash = order.hash ();
108- require (fills[hash] < order.takerTokenAmount);
109- require (! cancelled[hash]);
95+ require (exchange. fills[hash] < order.takerTokenAmount);
96+ require (! exchange. cancelled[hash]);
11097
111- cancelled[hash] = true ;
98+ exchange. cancelled[hash] = true ;
11299 emit Cancelled (hash);
113100 }
114101
@@ -121,16 +108,16 @@ contract Exchange is Ownable, ExchangeInterface {
121108 values
122109 );
123110
124- require (vault.isApproved (order.maker, this ));
125- require (vault.balanceOf (order.makerToken, order.maker) >= order.makerTokenAmount);
111+ require (exchange. vault.isApproved (order.maker, this ));
112+ require (exchange. vault.balanceOf (order.makerToken, order.maker) >= order.makerTokenAmount);
126113 require (order.makerToken != order.takerToken);
127114 require (order.makerTokenAmount > 0 );
128115 require (order.takerTokenAmount > 0 );
129116
130117 bytes32 hash = order.hash ();
131118
132- require (! orders[msg .sender ][hash]);
133- orders[msg .sender ][hash] = true ;
119+ require (! exchange. orders[msg .sender ][hash]);
120+ exchange. orders[msg .sender ][hash] = true ;
134121
135122 emit Ordered (
136123 order.maker,
@@ -154,17 +141,14 @@ contract Exchange is Ownable, ExchangeInterface {
154141 returns (bool )
155142 {
156143 OrderLibrary.Order memory order = OrderLibrary.createOrder (addresses, values);
157-
158- bytes32 hash = order.hash ();
159-
160- return canTrade (order, signature, hash);
144+ return exchange.canTrade (order, signature, order.hash ());
161145 }
162146
163147 /// @dev Returns if user has subscribed to trade hooks.
164148 /// @param subscriber Address of the subscriber.
165149 /// @return Boolean if user is subscribed.
166150 function isSubscribed (address subscriber ) external view returns (bool ) {
167- return subscribed[subscriber];
151+ return exchange. subscribed[subscriber];
168152 }
169153
170154 /// @dev Checks how much of an order can be filled.
@@ -173,153 +157,40 @@ contract Exchange is Ownable, ExchangeInterface {
173157 /// @return Amount of the order which can be filled.
174158 function availableAmount (address [3 ] addresses , uint [4 ] values ) external view returns (uint ) {
175159 OrderLibrary.Order memory order = OrderLibrary.createOrder (addresses, values);
176- return availableAmount (order, order.hash ());
160+ return exchange. availableAmount (order, order.hash ());
177161 }
178162
179163 /// @dev Returns how much of an order was filled.
180164 /// @param hash Hash of the order.
181165 /// @return Amount which was filled.
182166 function filled (bytes32 hash ) external view returns (uint ) {
183- return fills[hash];
167+ return exchange. fills[hash];
184168 }
185169
186170 /// @dev Sets the taker fee.
187171 /// @param _takerFee New taker fee.
188172 function setFees (uint _takerFee ) public onlyOwner {
189173 require (_takerFee <= MAX_FEE);
190- takerFee = _takerFee;
174+ exchange. takerFee = _takerFee;
191175 }
192176
193177 /// @dev Sets the account where fees will be transferred to.
194178 /// @param _feeAccount Address for the account.
195179 function setFeeAccount (address _feeAccount ) public onlyOwner {
196180 require (_feeAccount != 0x0 );
197- feeAccount = _feeAccount;
181+ exchange. feeAccount = _feeAccount;
198182 }
199183
200184 function vault () public view returns (VaultInterface) {
201- return vault;
185+ return exchange. vault;
202186 }
203187
204188 /// @dev Checks if an order was created on chain.
205189 /// @param user User who created the order.
206190 /// @param hash Hash of the order.
207191 /// @return Boolean if the order was created on chain.
208192 function isOrdered (address user , bytes32 hash ) public view returns (bool ) {
209- return orders[user][hash];
210- }
211-
212- /// @dev Executes the actual trade by transferring balances.
213- /// @param order Order to be traded.
214- /// @param taker Address of the taker.
215- /// @param signature Signed order along with signature mode.
216- /// @param maxFillAmount Maximum amount of the order to be filled.
217- function trade (OrderLibrary.Order memory order , address taker , bytes signature , uint maxFillAmount ) internal {
218- require (taker != order.maker);
219- bytes32 hash = order.hash ();
220-
221- require (order.makerToken != order.takerToken);
222- require (canTrade (order, signature, hash));
223-
224- uint fillAmount = SafeMath.min256 (maxFillAmount, availableAmount (order, hash));
225-
226- require (roundingPercent (fillAmount, order.takerTokenAmount, order.makerTokenAmount) <= MAX_ROUNDING_PERCENTAGE);
227- require (vault.balanceOf (order.takerToken, taker) >= fillAmount);
228-
229- uint makeAmount = order.makerTokenAmount.mul (fillAmount).div (order.takerTokenAmount);
230- uint tradeTakerFee = makeAmount.mul (takerFee).div (1 ether);
231-
232- if (tradeTakerFee > 0 ) {
233- vault.transfer (order.makerToken, order.maker, feeAccount, tradeTakerFee);
234- }
235-
236- vault.transfer (order.takerToken, taker, order.maker, fillAmount);
237- vault.transfer (order.makerToken, order.maker, taker, makeAmount.sub (tradeTakerFee));
238-
239- fills[hash] = fills[hash].add (fillAmount);
240- assert (fills[hash] <= order.takerTokenAmount);
241-
242- if (subscribed[order.maker]) {
243- order.maker.call.gas (MAX_HOOK_GAS)(HookSubscriber (order.maker).tradeExecuted.selector , order.takerToken, fillAmount);
244- }
245-
246- emit Traded (
247- hash,
248- order.makerToken,
249- makeAmount,
250- order.takerToken,
251- fillAmount,
252- order.maker,
253- taker
254- );
255- }
256-
257- /// @dev Indicates whether or not an certain amount of an order can be traded.
258- /// @param order Order to be traded.
259- /// @param signature Signed order along with signature mode.
260- /// @param hash Hash of the order.
261- /// @return Boolean if order can be traded
262- function canTrade (OrderLibrary.Order memory order , bytes signature , bytes32 hash )
263- internal
264- view
265- returns (bool )
266- {
267- // if the order has never been traded against, we need to check the sig.
268- if (fills[hash] == 0 ) {
269- // ensures order was either created on chain, or signature is valid
270- if (! isOrdered (order.maker, hash) && ! SignatureValidator.isValidSignature (hash, order.maker, signature)) {
271- return false ;
272- }
273- }
274-
275- if (cancelled[hash]) {
276- return false ;
277- }
278-
279- if (! vault.isApproved (order.maker, this )) {
280- return false ;
281- }
282-
283- if (order.takerTokenAmount == 0 ) {
284- return false ;
285- }
286-
287- if (order.makerTokenAmount == 0 ) {
288- return false ;
289- }
290-
291- // ensures that the order still has an available amount to be filled.
292- if (availableAmount (order, hash) == 0 ) {
293- return false ;
294- }
295-
296- return order.expires > now ;
297- }
298-
299- /// @dev Returns the maximum available amount that can be taken of an order.
300- /// @param order Order to check.
301- /// @param hash Hash of the order.
302- /// @return Amount of the order that can be filled.
303- function availableAmount (OrderLibrary.Order memory order , bytes32 hash ) internal view returns (uint ) {
304- return SafeMath.min256 (
305- order.takerTokenAmount.sub (fills[hash]),
306- vault.balanceOf (order.makerToken, order.maker).mul (order.takerTokenAmount).div (order.makerTokenAmount)
307- );
308- }
309-
310- /// @dev Returns the percentage which was rounded when dividing.
311- /// @param numerator Numerator.
312- /// @param denominator Denominator.
313- /// @param target Value to multiply with.
314- /// @return Percentage rounded.
315- function roundingPercent (uint numerator , uint denominator , uint target ) internal pure returns (uint ) {
316- // Inspired by https://github.com/0xProject/contracts/blob/1.0.0/contracts/Exchange.sol#L472-L490
317- uint remainder = mulmod (target, numerator, denominator);
318- if (remainder == 0 ) {
319- return 0 ;
320- }
321-
322- return remainder.mul (1000000 ).div (numerator.mul (target));
193+ return exchange.orders[user][hash];
323194 }
324195
325196 function sigArrayToBytes (bytes32 [] sm , uint16 [] sa , uint i ) internal pure returns (bytes ) {
0 commit comments