• 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

97.53
/contracts/protocol/core/actions/MixinOwnerActions.sol
1
// SPDX-License-Identifier: Apache 2.0
2
pragma solidity >=0.8.0 <0.9.0;
3

4
import {MixinActions} from "./MixinActions.sol";
5
import {IEApps} from "../../extensions/adapters/interfaces/IEApps.sol";
6
import {IERC20} from "../../interfaces/IERC20.sol";
7
import {IRigoblockV3PoolOwnerActions} from "../../interfaces/pool/IRigoblockV3PoolOwnerActions.sol";
8
import {ApplicationsLib, ApplicationsSlot} from "../../libraries/ApplicationsLib.sol";
9
import {EnumerableSet, AddressSet} from "../../libraries/EnumerableSet.sol";
10
import {ExternalApp} from "../../types/ExternalApp.sol";
11

12
abstract contract MixinOwnerActions is MixinActions {
13
    using ApplicationsLib for ApplicationsSlot;
14
    using EnumerableSet for AddressSet;
15

16
    error PoolCallerIsNotOwner();
17
    error PoolFeeBiggerThanMax(uint16 maxFee);
18
    error PoolInputIsNotContract();
19
    error PoolLockupPeriodInvalid(uint48 minimum, uint48 maximum);
20
    error PoolNullOwnerInput();
21
    error PoolSpreadInvalid(uint16 maxSpread);
22

23
    modifier onlyOwner() {
24
        require(msg.sender == pool().owner, PoolCallerIsNotOwner());
64✔
25
        _;
56✔
26
    }
27

28
    /// @inheritdoc IRigoblockV3PoolOwnerActions
29
    function changeFeeCollector(address feeCollector) external override onlyOwner {
5✔
30
        poolParams().feeCollector = feeCollector;
4✔
31
        emit NewCollector(msg.sender, address(this), feeCollector);
4✔
32
    }
33

34
    /// @inheritdoc IRigoblockV3PoolOwnerActions
35
    function changeMinPeriod(uint48 minPeriod) external override onlyOwner {
5✔
36
        /// @notice minimum period is always at least 1 to prevent flash txs.
37
        require(
4✔
38
            minPeriod >= _MIN_LOCKUP && minPeriod <= _MAX_LOCKUP,
39
            PoolLockupPeriodInvalid(_MIN_LOCKUP, _MAX_LOCKUP)
40
        );
41
        poolParams().minPeriod = minPeriod;
2✔
42
        emit MinimumPeriodChanged(address(this), minPeriod);
2✔
43
    }
44

45
    /// @inheritdoc IRigoblockV3PoolOwnerActions
46
    function changeSpread(uint16 newSpread) external override onlyOwner {
5✔
47
        // 0 value is sentinel for uninitialized spread, returning _MAX_SPREAD
48
        require(newSpread > 0 && newSpread <= _MAX_SPREAD, PoolSpreadInvalid(_MAX_SPREAD));
4✔
49
        poolParams().spread = newSpread;
2✔
50
        emit SpreadChanged(address(this), newSpread);
2✔
51
    }
52

53
    function purgeInactiveTokensAndApps() external override onlyOwner {
7✔
54
        // retrieve the list and mapping of stored tokens
55
        AddressSet storage set = activeTokensSet();
6✔
56
        ApplicationsSlot storage appsBitmap = activeApplications();
6✔
57
        uint256 packedApps = appsBitmap.packedApplications;
6✔
58
        ExternalApp[] memory activeApps;
6✔
59

60
        // TODO: test we get the correct balances, as fallback delegatecalls to extension in this case
61
        try IEApps(address(this)).getAppTokenBalances(packedApps) returns (ExternalApp[] memory apps) {
6✔
62
            for (uint256 i = 0; i < apps.length; i++) {
6✔
63
                if (
13✔
64
                    apps[i].balances.length == 0 &&
65
                    ApplicationsLib.isActiveApplication(packedApps, uint256(apps[i].appType))
66
                ) {
67
                    appsBitmap.removeApplication(apps[i].appType);
1✔
68
                }
69
            }
70
            activeApps = apps;
6✔
71
        } catch Error(string memory reason) {
72
            // do not allow removing tokens if the apps do not return their tokens correctly
NEW
73
            revert(reason);
×
74
        }
75

76
        // base token is never pushed to active list for gas savings, we can safely remove any unactive token
77
        for (uint256 i = 0; i < set.addresses.length; i++) {
6✔
78
            bool shouldRemove = true;
4✔
79
            // skip removal if a token is active in an application
80
            for (uint256 j = 0; j < activeApps.length; j++) {
4✔
81
                for (uint256 k = 0; k < activeApps[j].balances.length; k++) {
9✔
82
                    if (activeApps[j].balances[k].token == set.addresses[i]) {
4✔
83
                        shouldRemove = false;
2✔
84
                        break; // Exit k loop
2✔
85
                    }
86
                }
87
                if (!shouldRemove) {
9✔
88
                    break; // Exit j loop if token found in any app
2✔
89
                }
90
            }
91

92
            if (shouldRemove) {
4✔
93
                // TODO: should also handle native currency
94
                try IERC20(set.addresses[i]).balanceOf(address(this)) returns (uint256 _balance) {
2✔
95
                    if (_balance <= 1) {
2✔
96
                        set.remove(set.addresses[i]);
1✔
97
                    }
98
                } catch {
NEW
99
                    continue;
×
100
                }
101
            }
102
        }
103
    }
104

105
    /// @inheritdoc IRigoblockV3PoolOwnerActions
106
    function setKycProvider(address kycProvider) external override onlyOwner {
5✔
107
        require(_isContract(kycProvider), PoolInputIsNotContract());
4✔
108
        poolParams().kycProvider = kycProvider;
3✔
109
        emit KycProviderSet(address(this), kycProvider);
3✔
110
    }
111

112
    /// @inheritdoc IRigoblockV3PoolOwnerActions
113
    function setTransactionFee(uint16 transactionFee) external override onlyOwner {
6✔
114
        require(transactionFee <= _MAX_TRANSACTION_FEE, PoolFeeBiggerThanMax(_MAX_TRANSACTION_FEE)); //fee cannot be higher than 1%
5✔
115
        poolParams().transactionFee = transactionFee;
4✔
116
        emit NewFee(msg.sender, address(this), transactionFee);
4✔
117
    }
118

119
    /// @inheritdoc IRigoblockV3PoolOwnerActions
120
    function setOwner(address newOwner) public override onlyOwner {
31✔
121
        require(newOwner != _ZERO_ADDRESS, PoolNullOwnerInput());
29✔
122
        address oldOwner = pool().owner;
28✔
123
        pool().owner = newOwner;
28✔
124
        emit NewOwner(oldOwner, newOwner);
28✔
125
    }
126

127
    function _isContract(address target) private view returns (bool) {
128
        return target.code.length > 0;
4✔
129
    }
130
}
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