-
Notifications
You must be signed in to change notification settings - Fork 1
/
AddressProviderV3.sol
205 lines (167 loc) · 8.03 KB
/
AddressProviderV3.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2023.
pragma solidity ^0.8.17;
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {Ownable2Step, Ownable} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {ICreditManagerV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditManagerV3.sol";
import {IMarketConfiguratorV3} from "../interfaces/IMarketConfiguratorV3.sol";
import {IContractsRegister} from "../interfaces/IContractsRegister.sol";
import {IAddressProviderV3_1, ContractValue} from "../interfaces/IAddressProviderV3_1.sol";
import {
AddressNotFoundException,
CallerNotConfiguratorException
} from "@gearbox-protocol/core-v3/contracts/interfaces/IExceptions.sol";
import {IBotListV3} from "@gearbox-protocol/core-v3/contracts/interfaces/IBotListV3.sol";
import {IAccountFactoryV3} from "@gearbox-protocol/core-v3/contracts/interfaces/IAccountFactoryV3.sol";
import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
import {
AP_ADDRESS_PROVIDER,
AP_MARKET_CONFIGURATOR_FACTORY,
AP_BOT_LIST,
AP_ACCOUNT_FACTORY,
NO_VERSION_CONTROL
} from "../libraries/ContractLiterals.sol";
import {LibString} from "@solady/utils/LibString.sol";
struct ContractKey {
string key;
uint256 version;
}
/// @title Address provider V3
/// @notice Stores addresses of important contracts
contract AddressProviderV3_1 is Ownable2Step, IAddressProviderV3_1 {
using EnumerableSet for EnumerableSet.AddressSet;
// using LibString for string;
using LibString for bytes32;
/// @notice Contract version
uint256 public constant override version = 3_10;
bytes32 public constant override contractType = AP_ADDRESS_PROVIDER;
error MarketConfiguratorsOnlyException();
error CantRemoveMarketConfiguratorWithExistingPoolsException();
error MarketConfiguratorNotFoundException();
/// @notice Keeps market confifgurators
EnumerableSet.AddressSet internal _marketConfigurators;
/// @notice Mapping pool => MarketConfigurator
mapping(address => address) public override marketConfiguratorByPool;
/// @notice Mapping from (contract key, version) to contract addresses
mapping(string => mapping(uint256 => address)) public override addresses;
mapping(string => uint256) public latestVersions;
ContractKey[] internal contractKeys;
modifier marketConfiguratorFactoryOnly() {
if (msg.sender != getAddressOrRevert(AP_MARKET_CONFIGURATOR_FACTORY, NO_VERSION_CONTROL)) {
revert MarketConfiguratorsOnlyException();
}
_;
}
constructor() {
// The first event is emitted for the address provider itself to aid in contract discovery
emit SetAddress(AP_ADDRESS_PROVIDER.fromSmallString(), address(this), version);
}
/// @notice Returns the address of a contract with a given key and version
function getAddressOrRevert(string memory key, uint256 _version)
public
view
virtual
override
returns (address result)
{
result = addresses[key][_version];
if (result == address(0)) revert AddressNotFoundException();
}
/// @notice Returns the address of a contract with a given key and version
function getAddressOrRevert(bytes32 key, uint256 _version) public view virtual override returns (address result) {
return getAddressOrRevert(key.fromSmallString(), _version);
}
/// @notice Returns the address of a contract with a given key and version
function getLatestAddressOrRevert(string memory key) public view virtual returns (address result) {
return getAddressOrRevert(key, latestVersions[key]);
}
/// @notice Returns the address of a contract with a given key and version
function getLatestAddressOrRevert(bytes32 _key) public view virtual returns (address result) {
string memory key = _key.fromSmallString();
return getAddressOrRevert(key, latestVersions[key]);
}
/// @notice Sets the address for the passed contract key
/// @param key Contract key
/// @param value Contract address
/// @param saveVersion Whether to save contract's version
function setAddress(string memory key, address value, bool saveVersion) external override onlyOwner {
_setAddress(key, value, saveVersion ? IVersion(value).version() : NO_VERSION_CONTROL);
}
/// @notice Sets the address for the passed contract key
/// @param addr Contract address
/// @param saveVersion Whether to save contract's version
function setAddress(address addr, bool saveVersion) external override onlyOwner {
_setAddress(
IVersion(addr).contractType().fromSmallString(),
addr,
saveVersion ? IVersion(addr).version() : NO_VERSION_CONTROL
);
}
/// @dev Implementation of `setAddress`
function _setAddress(string memory key, address value, uint256 _version) internal virtual {
addresses[key][_version] = value;
uint256 latestVersion = latestVersions[key];
if (_version > latestVersion) {
latestVersions[key] = _version;
}
contractKeys.push(ContractKey(key, _version));
emit SetAddress(key, value, _version);
}
modifier marketConfiguratorsOnly() {
if (!_marketConfigurators.contains(msg.sender)) revert MarketConfiguratorsOnlyException();
_;
}
function addMarketConfigurator(address _marketConfigurator) external override marketConfiguratorFactoryOnly {
if (!_marketConfigurators.contains(_marketConfigurator)) {
_marketConfigurators.add(_marketConfigurator);
emit AddMarketConfigurator(_marketConfigurator);
}
}
function removeMarketConfigurator(address _marketConfigurator) external override marketConfiguratorFactoryOnly {
if (_marketConfigurators.contains(_marketConfigurator)) {
_marketConfigurators.add(_marketConfigurator);
emit RemoveMarketConfigurator(_marketConfigurator);
}
}
function marketConfigurators() external view override returns (address[] memory) {
return _marketConfigurators.values();
}
function isMarketConfigurator(address riskCurator) external view override returns (bool) {
return _marketConfigurators.contains(riskCurator);
}
function registerPool(address pool) external override marketConfiguratorsOnly {
marketConfiguratorByPool[pool] = msg.sender;
}
function registerCreditManager(address creditManager) external override marketConfiguratorsOnly {
// TODO: make method names more consistent?
IBotListV3(getLatestAddressOrRevert(AP_BOT_LIST)).approvedCreditManager(creditManager);
IAccountFactoryV3(getLatestAddressOrRevert(AP_ACCOUNT_FACTORY)).addCreditManager(creditManager);
}
// Getters
function marketConfiguratorByCreditManager(address creditManager) external view override returns (address) {
address pool = ICreditManagerV3(creditManager).pool();
address marketConfigurator = marketConfiguratorByPool[pool];
if (marketConfigurator == address(0)) revert MarketConfiguratorNotFoundException();
if (
IContractsRegister(IMarketConfiguratorV3(marketConfigurator).contractsRegister()).isCreditManager(
creditManager
)
) {
revert MarketConfiguratorNotFoundException();
}
return marketConfigurator;
}
function owner() public view override(Ownable, IAddressProviderV3_1) returns (address) {
return Ownable.owner();
}
function getAllSavedContracts() external view returns (ContractValue[] memory) {
ContractValue[] memory result = new ContractValue[](contractKeys.length);
for (uint256 i = 0; i < contractKeys.length; i++) {
result[i] = ContractValue(
contractKeys[i].key, addresses[contractKeys[i].key][contractKeys[i].version], contractKeys[i].version
);
}
return result;
}
}