@@ -7,7 +7,7 @@
Loading
7 7
import "./interfaces/IBinaryOptionMarketManager.sol";
8 8
9 9
// Libraries
10 -
import "./AddressListLib.sol";
10 +
import "./AddressSetLib.sol";
11 11
import "./SafeDecimalMath.sol";
12 12
13 13
// Internal references
@@ -24,7 +24,7 @@
Loading
24 24
    /* ========== LIBRARIES ========== */
25 25
26 26
    using SafeMath for uint;
27 -
    using AddressListLib for AddressListLib.AddressList;
27 +
    using AddressSetLib for AddressSetLib.AddressSet;
28 28
29 29
    /* ========== TYPES ========== */
30 30
@@ -54,8 +54,8 @@
Loading
54 54
    bool public marketCreationEnabled = true;
55 55
    uint public totalDeposited;
56 56
57 -
    AddressListLib.AddressList internal _activeMarkets;
58 -
    AddressListLib.AddressList internal _maturedMarkets;
57 +
    AddressSetLib.AddressSet internal _activeMarkets;
58 +
    AddressSetLib.AddressSet internal _maturedMarkets;
59 59
60 60
    BinaryOptionMarketManager internal _migratingManager;
61 61
@@ -275,7 +275,7 @@
Loading
275 275
            [fees.poolFee, fees.creatorFee, fees.refundFee]
276 276
        );
277 277
        market.setResolverAndSyncCache(resolver);
278 -
        _activeMarkets.push(address(market));
278 +
        _activeMarkets.add(address(market));
279 279
280 280
        // The debt can't be incremented in the new market's constructor because until construction is complete,
281 281
        // the manager doesn't know its address in order to grant it permission.
@@ -290,7 +290,7 @@
Loading
290 290
        require(_activeMarkets.contains(market), "Not an active market");
291 291
        BinaryOptionMarket(market).resolve();
292 292
        _activeMarkets.remove(market);
293 -
        _maturedMarkets.push(market);
293 +
        _maturedMarkets.add(market);
294 294
    }
295 295
296 296
    function cancelMarket(address market) external notPaused {
@@ -346,7 +346,7 @@
Loading
346 346
        if (_numMarkets == 0) {
347 347
            return;
348 348
        }
349 -
        AddressListLib.AddressList storage markets = active ? _activeMarkets : _maturedMarkets;
349 +
        AddressSetLib.AddressSet storage markets = active ? _activeMarkets : _maturedMarkets;
350 350
351 351
        uint runningDepositTotal;
352 352
        for (uint i; i < _numMarkets; i++) {
@@ -375,7 +375,7 @@
Loading
375 375
        if (_numMarkets == 0) {
376 376
            return;
377 377
        }
378 -
        AddressListLib.AddressList storage markets = active ? _activeMarkets : _maturedMarkets;
378 +
        AddressSetLib.AddressSet storage markets = active ? _activeMarkets : _maturedMarkets;
379 379
380 380
        uint runningDepositTotal;
381 381
        for (uint i; i < _numMarkets; i++) {
@@ -383,7 +383,7 @@
Loading
383 383
            require(!_isKnownMarket(address(market)), "Market already known.");
384 384
385 385
            market.acceptOwnership();
386 -
            markets.push(address(market));
386 +
            markets.add(address(market));
387 387
            // Update the market with the new manager address,
388 388
            runningDepositTotal = runningDepositTotal.add(market.deposited());
389 389
        }

@@ -0,0 +1,65 @@
Loading
1 +
pragma solidity ^0.5.16;
2 +
3 +
4 +
// https://docs.synthetix.io/contracts/source/libraries/addresssetlib/
5 +
library AddressSetLib {
6 +
    struct AddressSet {
7 +
        address[] elements;
8 +
        mapping(address => uint) indices;
9 +
    }
10 +
11 +
    function contains(AddressSet storage set, address candidate) internal view returns (bool) {
12 +
        if (set.elements.length == 0) {
13 +
            return false;
14 +
        }
15 +
        uint index = set.indices[candidate];
16 +
        return index != 0 || set.elements[0] == candidate;
17 +
    }
18 +
19 +
    function getPage(
20 +
        AddressSet storage set,
21 +
        uint index,
22 +
        uint pageSize
23 +
    ) internal view returns (address[] memory) {
24 +
        // NOTE: This implementation should be converted to slice operators if the compiler is updated to v0.6.0+
25 +
        uint endIndex = index + pageSize; // The check below that endIndex <= index handles overflow.
26 +
27 +
        // If the page extends past the end of the list, truncate it.
28 +
        if (endIndex > set.elements.length) {
29 +
            endIndex = set.elements.length;
30 +
        }
31 +
        if (endIndex <= index) {
32 +
            return new address[](0);
33 +
        }
34 +
35 +
        uint n = endIndex - index; // We already checked for negative overflow.
36 +
        address[] memory page = new address[](n);
37 +
        for (uint i; i < n; i++) {
38 +
            page[i] = set.elements[i + index];
39 +
        }
40 +
        return page;
41 +
    }
42 +
43 +
    function add(AddressSet storage set, address element) internal {
44 +
        // Adding to a set is an idempotent operation.
45 +
        if (!contains(set, element)) {
46 +
            set.indices[element] = set.elements.length;
47 +
            set.elements.push(element);
48 +
        }
49 +
    }
50 +
51 +
    function remove(AddressSet storage set, address element) internal {
52 +
        require(contains(set, element), "Element not in set.");
53 +
        // Replace the removed element with the last element of the list.
54 +
        uint index = set.indices[element];
55 +
        uint lastIndex = set.elements.length - 1; // We required that element is in the list, so it is not empty.
56 +
        if (index != lastIndex) {
57 +
            // No need to shift the last element if it is the one we want to delete.
58 +
            address shiftedElement = set.elements[lastIndex];
59 +
            set.elements[index] = shiftedElement;
60 +
            set.indices[shiftedElement] = index;
61 +
        }
62 +
        set.elements.pop();
63 +
        delete set.indices[element];
64 +
    }
65 +
}
Files Coverage
contracts 97.56%
Project Totals (61 files) 97.56%
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading