• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

RigoBlock / v3-contracts / 13358123822

16 Feb 2025 07:28PM UTC coverage: 95.379% (+1.0%) from 94.346%
13358123822

Pull #642

github

web-flow
Merge f1071ed27 into da745e9a8
Pull Request #642: fix: minor fixes

900 of 994 branches covered (90.54%)

Branch coverage included in aggregate %.

53 of 62 new or added lines in 6 files covered. (85.48%)

1 existing line in 1 file now uncovered.

1866 of 1906 relevant lines covered (97.9%)

69.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.76
/contracts/protocol/libraries/EnumerableSet.sol
1
// SPDX-License-Identifier: Apache 2.0
2
/*
3

4
 Copyright 2025 Rigo Intl.
5

6
 Licensed under the Apache License, Version 2.0 (the "License");
7
 you may not use this file except in compliance with the License.
8
 You may obtain a copy of the License at
9

10
     http://www.apache.org/licenses/LICENSE-2.0
11

12
 Unless required by applicable law or agreed to in writing, software
13
 distributed under the License is distributed on an "AS IS" BASIS,
14
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 See the License for the specific language governing permissions and
16
 limitations under the License.
17

18
*/
19

20
pragma solidity ^0.8.20;
21

22
import {IEOracle} from "../extensions/adapters/interfaces/IEOracle.sol";
23

24
struct AddressSet {
25
    // List of stored addresses
26
    address[] addresses;
27
    // Mapping of address to position.
28
    // Position 0 means an address has never been added before.
29
    mapping(address => uint256) positions;
30
}
31

32
/// @notice Pool initialization parameters.
33
/// @dev This struct is not visible externally and used to store/read pool init params.
34
/// @param name String of the pool name (max 32 characters).
35
/// @param symbol Bytes8 of the pool symbol (from 3 to 5 characters).
36
/// @param decimals Uint8 decimals.
37
/// @param owner Address of the pool operator.
38
/// @param unlocked Boolean the pool is locked for reentrancy check.
39
/// @param baseToken Address of the base token of the pool (0 for base currency).
40
struct Pool {
41
    string name;
42
    bytes8 symbol;
43
    uint8 decimals;
44
    address owner;
45
    bool unlocked;
46
    address baseToken;
47
}
48

49
/// @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/structs/EnumerableSet.sol
50
library EnumerableSet {
51
    error AddressListExceedsMaxLength();
52
    error TokenPriceFeedDoesNotExist(address token);
53

54
    // limit size of array to prevent DOS to nav estimates
55
    uint256 private constant _MAX_UNIQUE_ADDRESSES = type(uint8).max;
56

57
    // flag for removed address
58
    uint256 private constant REMOVED_ADDRESS_FLAG = type(uint256).max;
59

60
    /// @notice Base token is never pushed to active tokens, as already stored.
61
    /// @dev Skips and returns false for base token, which is already in storage.
62
    function addUnique(AddressSet storage set, IEOracle eOracle, address token, address baseToken) internal {
63
        if (token != baseToken) {
313✔
64
            if (set.positions[token] == 0 || set.positions[token] == REMOVED_ADDRESS_FLAG) {
236!
65
                require(set.addresses.length < _MAX_UNIQUE_ADDRESSES, AddressListExceedsMaxLength());
181!
66

67
                // perform a staticcall to the oracle extension and assert token has a price feed
68
                require(eOracle.hasPriceFeed(token), TokenPriceFeedDoesNotExist(token));
181!
69

70
                // update storage
71
                set.addresses.push(token);
181✔
72
                set.positions[token] = set.addresses.length;
181✔
73
            }
74
        }
75
    }
76

77
    function remove(AddressSet storage set, address token) internal {
78
        uint256 position = set.positions[token];
1✔
79

80
        if (position != 0 && position != REMOVED_ADDRESS_FLAG) {
1!
81
            // Copy last element at position and pop last element
82
            uint256 addressIndex = position - 1;
1✔
83
            uint256 lastIndex = set.addresses.length - 1;
1✔
84

85
            if (addressIndex != lastIndex) {
1!
NEW
86
                address lastAddress = set.addresses[lastIndex];
×
87

88
                // Move the lastToken to the index where the token to delete is
NEW
89
                set.addresses[addressIndex] = lastAddress;
×
90
                // Update the tracked position of the lastToken (that was just moved)
NEW
91
                set.positions[lastAddress] = position;
×
92
            }
93

94
            // Delete the slot where the moved token was stored
95
            set.addresses.pop();
1✔
96

97
            // Delete the tracked position for the deleted slot without clearing storage
98
            set.positions[token] = REMOVED_ADDRESS_FLAG;
1✔
99
            return;
1✔
100
        }
101
    }
102

103
    function isActive(AddressSet storage set, address token) internal view returns (bool) {
104
        uint256 position = set.positions[token];
16✔
105
        return (position != 0 && position != REMOVED_ADDRESS_FLAG);
16✔
106
    }
107
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc