/
LendingPoolAddressesProvider.sol
490 lines (436 loc) · 17 KB
/
LendingPoolAddressesProvider.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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.8.19;
import {Ownable} from "../../dependencies/openzeppelin/contracts/Ownable.sol";
// Prettier ignore to prevent buidler flatter bug
// prettier-ignore
import {InitializableImmutableAdminUpgradeabilityProxy} from '../../dependencies/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol';
import {ILendingPoolAddressesProvider} from "../../interfaces/ILendingPoolAddressesProvider.sol";
import {Errors} from "../libraries/helpers/Errors.sol";
/**
* @title LendingPoolAddressesProvider contract
* @dev Main registry of addresses part of or connected to the protocol, including permissioned roles
* - Acting also as factory of proxies and admin of those, so with right to change its implementations
* - Owned by the Vmex Governance
* @author Vmex
**/
contract LendingPoolAddressesProvider is
Ownable,
ILendingPoolAddressesProvider
{
string private _marketId;
// List of addresses that are not specific to a tranche
mapping(bytes32 => address) private _addresses;
// List of addresses that are specific to a tranche:
// _addressesTranche[TRANCHE_ADMIN][0] is the admin address for tranche 0
mapping(bytes32 => mapping(uint64 => address)) private _addressesTranche;
// Whitelisted addresses that are allowed to create permissionless tranches
mapping(address => bool) whitelistedAddresses;
// Whether or not permissionless tranches are enabled for all users
bool permissionlessTranches;
bytes32 private constant GLOBAL_ADMIN = "GLOBAL_ADMIN";
bytes32 private constant LENDING_POOL = "LENDING_POOL";
bytes32 private constant ATOKEN = "ATOKEN";
bytes32 private constant ATOKEN_BEACON = "ATOKEN_BEACON";
bytes32 private constant VARIABLE_DEBT = "VARIABLE_DEBT";
bytes32 private constant VARIABLE_DEBT_BEACON = "VARIABLE_DEBT_BEACON";
bytes32 private constant LENDING_POOL_CONFIGURATOR =
"LENDING_POOL_CONFIGURATOR";
bytes32 private constant TRANCHE_ADMIN = "TRANCHE_ADMIN";
bytes32 private constant EMERGENCY_ADMIN = "EMERGENCY_ADMIN";
bytes32 private constant LENDING_POOL_COLLATERAL_MANAGER =
"COLLATERAL_MANAGER";
bytes32 private constant VMEX_PRICE_ORACLE = "VMEX_PRICE_ORACLE";
bytes32 private constant LENDING_RATE_ORACLE = "LENDING_RATE_ORACLE";
bytes32 private constant CURVE_ADDRESS_PROVIDER = "CURVE_ADDRESS_PROVIDER";
bytes32 private constant ASSET_MAPPINGS = "ASSET_MAPPINGS";
bytes32 private constant VMEX_TREASURY_ADDRESS = "VMEX_TREASURY_ADDRESS";
bytes32 private constant INCENTIVES_CONTROLLER = "INCENTIVES_CONTROLLER";
constructor(string memory marketId) {
_setMarketId(marketId);
permissionlessTranches = false;
}
function getVMEXTreasury() external view override returns(address){
return getAddress(VMEX_TREASURY_ADDRESS);
}
function setVMEXTreasury(address add) external override onlyOwner {
_setVMEXTreasury(add);
}
function _setVMEXTreasury(address add) internal {
_addresses[VMEX_TREASURY_ADDRESS] = add;
emit VMEXTreasuryUpdated(add);
}
/**
* @dev Sets whether permissionless tranches are enabled or disabled for all users.
* @param val True if permissionless tranches are enabled, false otherwise
**/
function setPermissionlessTranches(bool val) external onlyOwner {
permissionlessTranches = val;
}
/**
* @dev Add a user to create permissionless tranches.
* @param ad The user's address
* @param val Whether or not to enable this user to create permissionless tranches
**/
function addWhitelistedAddress(address ad, bool val) external onlyOwner {
whitelistedAddresses[ad] = val;
}
/**
* @dev Checks whether an address is allowed to create permissionless tranches.
* @param ad The user's address
**/
function isWhitelistedAddress(address ad)
external
view
override
returns (bool)
{
return permissionlessTranches || whitelistedAddresses[ad];
}
/**
* @dev Returns the id of the Vmex market to which this contracts points to
* @return The market id
**/
function getMarketId() external view override returns (string memory) {
return _marketId;
}
/**
* @dev Allows to set the market which this LendingPoolAddressesProvider represents
* @param marketId The market id
*/
function setMarketId(string memory marketId) external override onlyOwner {
_setMarketId(marketId);
}
/**
* @dev General function to update the implementation of a proxy registered with
* certain `id`. If there is no proxy registered, it will instantiate one and
* set as implementation the `implementationAddress`
* IMPORTANT Use this function carefully, only for ids that don't have an explicit
* setter function, in order to avoid unexpected consequences
* @param id The id
* @param implementationAddress The address of the new implementation
*/
function setAddressAsProxy(bytes32 id, address implementationAddress)
external
override
onlyOwner
{
_updateImpl(id, implementationAddress);
emit AddressSet(id, implementationAddress, true);
}
/**
* @dev Sets an address for an id replacing the address saved in the addresses map
* IMPORTANT Use this function carefully, as it will do a hard replacement
* @param id The id
* @param newAddress The address to set
*/
function setAddress(bytes32 id, address newAddress)
external
override
onlyOwner
{
_addresses[id] = newAddress;
emit AddressSet(id, newAddress, false);
}
/**
* @dev Returns an address by id
* @return The address
*/
function getAddress(bytes32 id) public view override returns (address) {
return _addresses[id];
}
/**
* @dev Returns an address in a tranche by id and trancheId
* @return The address
*/
function getAddressTranche(bytes32 id, uint64 trancheId)
public
view
override
returns (address)
{
return _addressesTranche[id][trancheId];
}
/**
* @dev Returns the address of the LendingPool proxy
* @return The LendingPool proxy address
**/
function getLendingPool() external view override returns (address) {
return getAddress(LENDING_POOL);
}
/**
* @dev Updates the implementation of the LendingPool, or creates the proxy
* setting the new `pool` implementation on the first time calling it
* @param pool The new LendingPool implementation
**/
function setLendingPoolImpl(address pool) external override onlyOwner {
_updateImpl(LENDING_POOL, pool);
emit LendingPoolUpdated(pool);
}
/**
* @dev Returns the address of the aToken impl address
* @return The aToken proxy address
**/
function getAToken() external view override returns (address) {
return getAddress(ATOKEN);
}
/**
* @dev Updates the implementation of the LendingPool, or creates the proxy
* setting the new `pool` implementation on the first time calling it
* @param aToken The new aToken implementation
**/
function setATokenImpl(address aToken) external override onlyOwner {
_addresses[ATOKEN] = aToken;
emit ATokenUpdated(aToken);
}
/**
* @dev Returns the address of the aToken beacon address
* @return The aToken beacon address
**/
function getATokenBeacon() external view override returns (address) {
return getAddress(ATOKEN_BEACON);
}
/**
* @dev Updates the implementation of the atoken beacon
* @param aTokenBeacon The new aToken implementation
**/
function setATokenBeacon(address aTokenBeacon) external override onlyOwner {
_addresses[ATOKEN_BEACON] = aTokenBeacon;
emit ATokenBeaconUpdated(aTokenBeacon);
}
/**
* @dev Returns the address of the LendingPool proxy
* @return The aToken proxy address
**/
function getVariableDebtToken() external view override returns (address) {
return getAddress(VARIABLE_DEBT);
}
/**
* @dev Updates the implementation of the LendingPool, or creates the proxy
* setting the new `pool` implementation on the first time calling it
* @param aToken The new aToken implementation
**/
function setVariableDebtToken(address aToken) external override onlyOwner {
// don't use _updateImpl since this just stores the address, the upgrade is done in LendingPoolConfigurator
_addresses[VARIABLE_DEBT] = aToken;
emit VariableDebtUpdated(aToken);
}
/**
* @dev Returns the address of the variable debt token beacon
* @return The aToken proxy address
**/
function getVariableDebtTokenBeacon() external view override returns (address) {
return getAddress(VARIABLE_DEBT_BEACON);
}
/**
* @dev Updates the beacon implementation
* @param variableDebtBeacon The new aToken implementation
**/
function setVariableDebtTokenBeacon(address variableDebtBeacon) external override onlyOwner {
// don't use _updateImpl since this just stores the address, the upgrade is done in LendingPoolConfigurator
_addresses[VARIABLE_DEBT_BEACON] = variableDebtBeacon;
emit VariableDebtBeaconUpdated(variableDebtBeacon);
}
/**
* @dev Returns the address of the LendingPoolConfigurator proxy
* @return The LendingPoolConfigurator proxy address
**/
function getLendingPoolConfigurator()
external
view
override
returns (address)
{
return getAddress(LENDING_POOL_CONFIGURATOR);
}
/**
* @dev Updates the implementation of the LendingPoolConfigurator, or creates the proxy
* setting the new `configurator` implementation on the first time calling it
* @param newAddress The new LendingPoolConfigurator implementation
**/
function setLendingPoolConfiguratorImpl(address newAddress)
external
override
onlyOwner
{
_updateImpl(LENDING_POOL_CONFIGURATOR, newAddress);
emit LendingPoolConfiguratorUpdated(newAddress);
}
/**
* @dev Returns the address of the LendingPoolCollateralManager. Since the manager is used
* through delegateCall within the LendingPool contract, the proxy contract pattern does not work properly hence
* the addresses are changed directly
* @return The address of the LendingPoolCollateralManager
**/
function getLendingPoolCollateralManager()
external
view
override
returns (address)
{
return getAddress(LENDING_POOL_COLLATERAL_MANAGER);
}
/**
* @dev Updates the address of the LendingPoolCollateralManager
* @param manager The new LendingPoolCollateralManager address
**/
function setLendingPoolCollateralManager(address manager)
external
override
onlyOwner
{
_addresses[LENDING_POOL_COLLATERAL_MANAGER] = manager;
emit LendingPoolCollateralManagerUpdated(manager);
}
/**
* @dev The functions below are getters/setters of addresses that are outside the context
* of the protocol hence the upgradable proxy pattern is not used
**/
/**
* @dev Gets the global admin, the admin to entire market
* @return The address of the global admin
**/
function getGlobalAdmin() external view override returns (address) {
return getAddress(GLOBAL_ADMIN);
}
/**
* @dev Sets the global admin, the admin to entire market
* IMPORTANT Use this function carefully, as it will do a hard replacement
* @param admin The address of the new admin
**/
function setGlobalAdmin(address admin) external override onlyOwner {
_addresses[GLOBAL_ADMIN] = admin;
}
/**
* @dev Gets the tranche admin, the admin to a single tranche
* @param trancheId The id of the tranche
* @return The address of the tranche admin
**/
function getTrancheAdmin(uint64 trancheId)
external
view
override
returns (address)
{
return getAddressTranche(TRANCHE_ADMIN, trancheId);
}
/**
* @dev Manually sets the tranche admin without checking if the tranche has been taken
* @param admin The address of the new admin
* @param trancheId The id of the tranche
**/
function setTrancheAdmin(address admin, uint64 trancheId) external override {
require(
_msgSender() == owner() ||
_msgSender() == getAddressTranche(TRANCHE_ADMIN, trancheId),
Errors.CALLER_NOT_TRANCHE_ADMIN
);
_addressesTranche[TRANCHE_ADMIN][trancheId] = admin;
emit ConfigurationAdminUpdated(admin, trancheId);
}
/**
* @dev Adds the tranche admin to registry, checking if the tranche has been taken
* @param admin The address of the new admin
* @param trancheId The id of the tranche
**/
function addTrancheAdmin(address admin, uint64 trancheId) external override {
// anyone can add their own tranche, but you just have to choose a trancheId that hasn't been used yet
require(
_msgSender() == getAddress(LENDING_POOL_CONFIGURATOR),
Errors.LP_CALLER_NOT_LENDING_POOL_CONFIGURATOR
);
assert(_addressesTranche[TRANCHE_ADMIN][trancheId] == address(0)); //this should never be false
_addressesTranche[TRANCHE_ADMIN][trancheId] = admin;
emit ConfigurationAdminUpdated(admin, trancheId);
}
/**
* @dev Gets the emergency admin for the market
* @return The emergency admin address
**/
function getEmergencyAdmin() external view override returns (address) {
return getAddress(EMERGENCY_ADMIN);
}
/**
* @dev Sets the emergency admin for the market
* @param emergencyAdmin The address of the new admin
**/
function setEmergencyAdmin(address emergencyAdmin) external override onlyOwner {
_addresses[EMERGENCY_ADMIN] = emergencyAdmin;
emit EmergencyAdminUpdated(emergencyAdmin);
}
/**
* @dev Get the vmex price oracle
* @return The address of the vmex price oracle
**/
function getPriceOracle()
external
view
override
returns (address)
{
return getAddress(VMEX_PRICE_ORACLE);
}
/**
* @dev Set the vmex price oracle
* @param priceOracle The address of the new vmex price oracle
**/
function setPriceOracle(address priceOracle)
external
override
onlyOwner
{
_updateImpl(VMEX_PRICE_ORACLE, priceOracle);
emit PriceOracleUpdated(priceOracle);
}
/**
* @dev Internal function to update the implementation of a specific proxied component of the protocol
* - If there is no proxy registered in the given `id`, it creates the proxy setting `newAdress`
* as implementation and calls the initialize() function on the proxy
* - If there is already a proxy registered, it just updates the implementation to `newAddress` and
* calls the initialize() function via upgradeToAndCall() in the proxy
* @param id The id of the proxy to be updated
* @param newAddress The address of the new implementation
**/
function _updateImpl(bytes32 id, address newAddress) internal {
address payable proxyAddress = payable(_addresses[id]);
InitializableImmutableAdminUpgradeabilityProxy proxy =
InitializableImmutableAdminUpgradeabilityProxy(proxyAddress);
bytes memory params =
abi.encodeWithSignature("initialize(address)", address(this));
if (proxyAddress == address(0)) {
proxy = new InitializableImmutableAdminUpgradeabilityProxy(
address(this)
);
proxy.initialize(newAddress, params);
_addresses[id] = address(proxy);
emit ProxyCreated(id, address(proxy));
} else {
proxy.upgradeToAndCall(newAddress, params);
}
}
function _setMarketId(string memory marketId) internal {
_marketId = marketId;
emit MarketIdSet(marketId);
}
/**
* @dev Set the asset mappings
* @return The address of the asset mappings
**/
function getAssetMappings() external view override returns (address){
return getAddress(ASSET_MAPPINGS);
}
/**
* @dev Set the asset mappings
* @param assetMappings The address of the new asset mappings
**/
function setAssetMappingsImpl(address assetMappings) external override onlyOwner{
_updateImpl(ASSET_MAPPINGS, assetMappings);
emit AssetMappingsUpdated(assetMappings);
}
function getIncentivesController() external view override returns(address) {
return getAddress(INCENTIVES_CONTROLLER);
}
function setIncentivesController(address incentives) external override {
_addresses[INCENTIVES_CONTROLLER] = incentives;
emit IncentivesControllerUpdated(incentives);
}
}