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

RigoBlock / v3-contracts / 13268348478

11 Feb 2025 05:02PM UTC coverage: 87.539%. First build
13268348478

Pull #622

github

web-flow
Merge 20081ca08 into 08bd3b51b
Pull Request #622: feat: automated nav

785 of 964 branches covered (81.43%)

Branch coverage included in aggregate %.

588 of 745 new or added lines in 28 files covered. (78.93%)

1758 of 1941 relevant lines covered (90.57%)

48.43 hits per line

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

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

4
 Copyright 2024 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
library EnumerableSet {
50
    error AddressListExceedsMaxLength();
51
    error TokenPriceFeedDoesNotExist(address token);
52

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

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

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

66
                // perform a staticcall to the oracle extension and assert new token has a price feed. Removed token as well
67
                try eOracle.hasPriceFeed(token) returns (bool hasFeed) {
15✔
68
                    require(hasFeed, TokenPriceFeedDoesNotExist(token));
15!
69
                } catch Error(string memory reason) {
NEW
70
                    revert(reason);
×
71
                }
72

73
                // update storage
74
                set.addresses.push(token);
15✔
75
                set.positions[token] = set.addresses.length;
15✔
76
            }
77
        }
78
    }
79

80
    function remove(AddressSet storage set, address token) internal returns (bool) {
81
        uint256 position = set.positions[token];
1✔
82

83
        if (position != 0) {
1!
84
            // Copy last element at index position and pop last element
85
            uint256 tokenIndex = position - 1;
1✔
86
            uint256 lastIndex = set.addresses.length - 1;
1✔
87

88
            if (tokenIndex != lastIndex) {
1!
NEW
89
                address lastToken = set.addresses[lastIndex];
×
90

91
                // Move the lastToken to the index where the token to delete is
NEW
92
                set.addresses[tokenIndex] = lastToken;
×
93
                // Update the tracked position of the lastToken (that was just moved)
NEW
94
                set.positions[lastToken] = position;
×
95
            }
96

97
            // Delete the slot where the moved token was stored
98
            set.addresses.pop();
1✔
99

100
            // Delete the tracked position for the deleted slot without clearing storage
101
            set.positions[token] = _REMOVED_ADDRESS_FLAG;
1✔
102

103
            return true;
1✔
104
        } else {
NEW
105
            return false;
×
106
        }
107
    }
108
}
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