|
| 1 | +// SPDX-License-Identifier: UNLICENSED |
| 2 | +pragma solidity ^0.8.27; |
| 3 | + |
| 4 | +import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol"; |
| 5 | +import {IEVault, IERC20} from "evk/EVault/IEVault.sol"; |
| 6 | +import {IEulerRouterFactory, IEulerRouter} from "./interfaces/Misc.sol"; |
| 7 | +import "evk/EVault/shared/Constants.sol"; |
| 8 | +import {GenericFactory} from "evk/GenericFactory/GenericFactory.sol"; |
| 9 | +import {StubOracle} from "./StubOracle.sol"; |
| 10 | + |
| 11 | +contract LayerCredit { |
| 12 | + GenericFactory immutable private eVaultFactory; |
| 13 | + IEulerRouterFactory immutable private routerFactory; |
| 14 | + StubOracle immutable private stubOracle; |
| 15 | + |
| 16 | + address public settingAdmin; |
| 17 | + uint16 public settingNumVaultLimit; // Special value of 0 means system sunset (no new bond creation allowed) |
| 18 | + uint40 public settingMaxTermDuration; |
| 19 | + uint40 public settingReserveMultiplier; // 1e4 scale |
| 20 | + uint256 public settlementInterestRate; |
| 21 | + |
| 22 | + constructor(address eVaultFactory_, address routerFactory_, address settingAdmin_) { |
| 23 | + eVaultFactory = GenericFactory(eVaultFactory_); |
| 24 | + routerFactory = IEulerRouterFactory(routerFactory_); |
| 25 | + stubOracle = new StubOracle(); |
| 26 | + |
| 27 | + settingAdmin = settingAdmin_; |
| 28 | + settingNumVaultLimit = 4; |
| 29 | + settingMaxTermDuration = 90 days; |
| 30 | + settingReserveMultiplier = 20e4; |
| 31 | + settlementInterestRate = 21964959992727444861; // 100% APY |
| 32 | + } |
| 33 | + |
| 34 | + struct DeployBondVault { |
| 35 | + address asset; |
| 36 | + address oracle; |
| 37 | + uint256 interestRate; |
| 38 | + address restrictedLender; |
| 39 | + address restrictedBorrower; |
| 40 | + bool noEarlyRepay; |
| 41 | + } |
| 42 | + |
| 43 | + struct DeployBondLTV { |
| 44 | + uint256 collateralIndex; |
| 45 | + uint256 liabilityIndex; |
| 46 | + uint16 liquidationLTV; |
| 47 | + } |
| 48 | + |
| 49 | + struct DeployBondParams { |
| 50 | + address unitOfAccount; |
| 51 | + uint256 termDuration; |
| 52 | + uint256 interestFee; |
| 53 | + address interestFeeRecipient; |
| 54 | + DeployBondVault[] vaults; |
| 55 | + DeployBondLTV[] ltvs; |
| 56 | + } |
| 57 | + |
| 58 | + error SystemSunset(); |
| 59 | + error InvalidTermDuration(); |
| 60 | + error InvalidNumberOfVaults(); |
| 61 | + error InvalidLTVIndex(); |
| 62 | + |
| 63 | + function deployBond(DeployBondParams memory p) external { |
| 64 | + require(settingNumVaultLimit != 0, SystemSunset()); |
| 65 | + require(p.termDuration <= settingMaxTermDuration, InvalidTermDuration()); |
| 66 | + |
| 67 | + require(p.vaults.length >= 2 && p.vaults.length <= settingNumVaultLimit, InvalidNumberOfVaults()); |
| 68 | + |
| 69 | + IEulerRouter router = IEulerRouter(IEulerRouterFactory(routerFactory).deploy(address(this))); |
| 70 | + |
| 71 | + IEVault[] memory vaults = new IEVault[](p.vaults.length); |
| 72 | + |
| 73 | + for (uint256 i = 0; i < p.vaults.length; i++) { |
| 74 | + IEVault vault = vaults[i] = IEVault(GenericFactory(eVaultFactory).createProxy(address(0), true, abi.encodePacked(p.vaults[i].asset, address(router), p.unitOfAccount))); |
| 75 | + |
| 76 | + vault.setInterestRateModel(address(this)); |
| 77 | + vault.setHookConfig(address(this), OP_CONVERT_FEES | OP_BORROW | OP_REPAY | OP_REPAY_WITH_SHARES | OP_DEPOSIT | OP_MINT | OP_SKIM | OP_VAULT_STATUS_CHECK); |
| 78 | + vault.setMaxLiquidationDiscount(0.15e4); |
| 79 | + vault.setLiquidationCoolOffTime(1); |
| 80 | + |
| 81 | + router.govSetResolvedVault(address(vault), true); |
| 82 | + router.govSetConfig(p.vaults[i].asset, p.unitOfAccount, address(stubOracle)); |
| 83 | + } |
| 84 | + |
| 85 | + for (uint256 i = 0; i < p.ltvs.length; i++) { |
| 86 | + require(p.ltvs[i].collateralIndex < p.vaults.length, InvalidLTVIndex()); |
| 87 | + require(p.ltvs[i].liabilityIndex < p.vaults.length, InvalidLTVIndex()); |
| 88 | + |
| 89 | + vaults[p.ltvs[i].liabilityIndex].setLTV(address(vaults[p.ltvs[i].collateralIndex]), uint16(p.ltvs[i].liquidationLTV * 0.98e18 / 1e18), p.ltvs[i].liquidationLTV, 0); |
| 90 | + } |
| 91 | + |
| 92 | + // Install final oracles |
| 93 | + |
| 94 | + for (uint256 i = 0; i < p.vaults.length; i++) { |
| 95 | + router.govSetConfig(p.vaults[i].asset, p.unitOfAccount, p.vaults[i].oracle); |
| 96 | + } |
| 97 | + |
| 98 | + router.transferGovernance(address(0)); |
| 99 | + } |
| 100 | +} |
0 commit comments