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

RigoBlock / v3-contracts / 13261352678

11 Feb 2025 10:59AM UTC coverage: 84.94% (+2.6%) from 82.368%
13261352678

Pull #622

github

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

761 of 962 branches covered (79.11%)

Branch coverage included in aggregate %.

523 of 711 new or added lines in 28 files covered. (73.56%)

18 existing lines in 5 files now uncovered.

1698 of 1933 relevant lines covered (87.84%)

44.05 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
    // TODO: check if should log, even though we already store in list so not strictly needed.
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) {
43✔
64
            if (set.positions[token] == 0 || set.positions[token] == _REMOVED_ADDRESS_FLAG) {
33!
65
                require(set.addresses.length < _MAX_UNIQUE_ADDRESSES, AddressListExceedsMaxLength());
15!
66

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

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

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

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

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

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

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

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

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

© 2025 Coveralls, Inc