Skip to content
This repository was archived by the owner on Sep 20, 2019. It is now read-only.

Commit 0b012b1

Browse files
Dean Eigenmannmattdf
authored andcommitted
enhancement/logic-libraries (#96)
* Created library * removed unused imports * renamed
1 parent 8508b2a commit 0b012b1

File tree

2 files changed

+192
-153
lines changed

2 files changed

+192
-153
lines changed

contracts/Exchange.sol

Lines changed: 24 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,27 @@
11
pragma solidity ^0.4.21;
22

33
import "./ExchangeInterface.sol";
4-
import "./Libraries/SafeMath.sol";
5-
import "./Libraries/SignatureValidator.sol";
64
import "./Libraries/OrderLibrary.sol";
5+
import "./Libraries/ExchangeLibrary.sol";
76
import "./Ownership/Ownable.sol";
87
import "./Tokens/ERC20.sol";
9-
import "./HookSubscriber.sol";
108

119
contract 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

Comments
 (0)