|
2 | 2 | pragma solidity ^0.8.13; |
3 | 3 |
|
4 | 4 | import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; |
5 | | -import {IEVault, IERC20} from "evk/EVault/IEVault.sol"; |
| 5 | +import {IEVault, IERC20, IRiskManager} from "evk/EVault/IEVault.sol"; |
6 | 6 | import {RPow} from "evk/EVault/shared/lib/RPow.sol"; |
7 | 7 | import {IEulerSwapRegistry} from "euler-swap/interfaces/IEulerSwapRegistry.sol"; |
8 | 8 | import {IEulerSwap} from "euler-swap/interfaces/IEulerSwap.sol"; |
9 | 9 |
|
10 | 10 | contract MaglevLens { |
11 | | - // Packed: underlying asset (address), decimals (uint8), symbol (variable) |
| 11 | + //// Vault queries |
12 | 12 |
|
| 13 | + /// @dev Packed output: underlying asset (address), decimals (uint8), symbol (variable) |
13 | 14 | function vaultsStatic(address[] calldata vaults) external view returns (bytes[] memory output) { |
14 | 15 | unchecked { |
15 | 16 | output = new bytes[](vaults.length); |
@@ -187,6 +188,8 @@ contract MaglevLens { |
187 | 188 | } |
188 | 189 | } |
189 | 190 |
|
| 191 | + //// EulerSwap queries |
| 192 | + |
190 | 193 | struct EulerSwapData { |
191 | 194 | address addr; |
192 | 195 | IEulerSwap.StaticParams sParams; |
@@ -266,4 +269,48 @@ contract MaglevLens { |
266 | 269 | require(reserve0 >= reserve0Min && reserve0 <= reserve0Max, AssertEulerSwapReservesFailure()); |
267 | 270 | require(reserve1 >= reserve1Min && reserve1 <= reserve1Max, AssertEulerSwapReservesFailure()); |
268 | 271 | } |
| 272 | + |
| 273 | + //// Liquidity Queries |
| 274 | + |
| 275 | + error MultipleControllers(); |
| 276 | + |
| 277 | + /// Packed health score: controller (address), health (uint32), error (bool) |
| 278 | + /// @dev Health scores are 1e6 scale. |
| 279 | + function getHealthScores(address evc, address[] calldata addrs) external view returns (uint256[] memory healths) { |
| 280 | + healths = new uint256[](addrs.length); |
| 281 | + |
| 282 | + for (uint256 i = 0; i < addrs.length; ++i) { |
| 283 | + address addr = addrs[i]; |
| 284 | + |
| 285 | + address controller; |
| 286 | + uint32 health; |
| 287 | + uint8 errorFlag; |
| 288 | + |
| 289 | + { |
| 290 | + address[] memory controllers = IEVC(evc).getControllers(addr); |
| 291 | + require(controllers.length < 2, MultipleControllers()); |
| 292 | + if (controllers.length == 1) controller = controllers[0]; |
| 293 | + } |
| 294 | + |
| 295 | + if (controller != address(0)) { |
| 296 | + (bool success, bytes memory data) = controller.staticcall(abi.encodeCall(IRiskManager.accountLiquidity, (addr, true))); |
| 297 | + |
| 298 | + if (success) { |
| 299 | + (uint256 collateralValue, uint256 liabilityValue) = abi.decode(data, (uint256, uint256)); |
| 300 | + |
| 301 | + if (liabilityValue == 0) { |
| 302 | + health = type(uint32).max; |
| 303 | + } else { |
| 304 | + uint256 h = 1e6 * collateralValue / liabilityValue; |
| 305 | + if (h > type(uint32).max) h = type(uint32).max; |
| 306 | + health = uint32(h); |
| 307 | + } |
| 308 | + } else { |
| 309 | + errorFlag = 1; |
| 310 | + } |
| 311 | + } |
| 312 | + |
| 313 | + healths[i] = (uint160(controller) << 40) | (health << 32) | errorFlag; |
| 314 | + } |
| 315 | + } |
269 | 316 | } |
0 commit comments