From ab7a6513ddac878b9463b987739a19251ca2acd2 Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Tue, 26 Nov 2024 00:58:20 +0400 Subject: [PATCH 1/6] IGP-56 --- contracts/payloads/IGP56/PayloadIGP56.sol | 1057 +++++++++++++++++++++ 1 file changed, 1057 insertions(+) create mode 100644 contracts/payloads/IGP56/PayloadIGP56.sol diff --git a/contracts/payloads/IGP56/PayloadIGP56.sol b/contracts/payloads/IGP56/PayloadIGP56.sol new file mode 100644 index 0000000..fa88439 --- /dev/null +++ b/contracts/payloads/IGP56/PayloadIGP56.sol @@ -0,0 +1,1057 @@ +pragma solidity ^0.8.21; +pragma experimental ABIEncoderV2; + +import {BigMathMinified} from "../libraries/bigMathMinified.sol"; +import {LiquidityCalcs} from "../libraries/liquidityCalcs.sol"; +import {LiquiditySlotsLink} from "../libraries/liquiditySlotsLink.sol"; + +interface IGovernorBravo { + function _acceptAdmin() external; + + function _setVotingDelay(uint256 newVotingDelay) external; + + function _setVotingPeriod(uint256 newVotingPeriod) external; + + function _acceptAdminOnTimelock() external; + + function _setImplementation(address implementation_) external; + + function propose( + address[] memory targets, + uint256[] memory values, + string[] memory signatures, + bytes[] memory calldatas, + string memory description + ) external returns (uint256); + + function admin() external view returns (address); + + function pendingAdmin() external view returns (address); + + function timelock() external view returns (address); + + function votingDelay() external view returns (uint256); + + function votingPeriod() external view returns (uint256); +} + +interface ITimelock { + function acceptAdmin() external; + + function setDelay(uint256 delay_) external; + + function setPendingAdmin(address pendingAdmin_) external; + + function queueTransaction( + address target, + uint256 value, + string memory signature, + bytes memory data, + uint256 eta + ) external returns (bytes32); + + function executeTransaction( + address target, + uint256 value, + string memory signature, + bytes memory data, + uint256 eta + ) external payable returns (bytes memory); + + function pendingAdmin() external view returns (address); + + function admin() external view returns (address); + + function delay() external view returns (uint256); +} + +interface AdminModuleStructs { + struct AddressBool { + address addr; + bool value; + } + + struct AddressUint256 { + address addr; + uint256 value; + } + + struct RateDataV1Params { + address token; + uint256 kink; + uint256 rateAtUtilizationZero; + uint256 rateAtUtilizationKink; + uint256 rateAtUtilizationMax; + } + + struct RateDataV2Params { + address token; + uint256 kink1; + uint256 kink2; + uint256 rateAtUtilizationZero; + uint256 rateAtUtilizationKink1; + uint256 rateAtUtilizationKink2; + uint256 rateAtUtilizationMax; + } + + struct TokenConfig { + address token; + uint256 fee; + uint256 threshold; + } + + struct UserSupplyConfig { + address user; + address token; + uint8 mode; + uint256 expandPercent; + uint256 expandDuration; + uint256 baseWithdrawalLimit; + } + + struct UserBorrowConfig { + address user; + address token; + uint8 mode; + uint256 expandPercent; + uint256 expandDuration; + uint256 baseDebtCeiling; + uint256 maxDebtCeiling; + } +} + +interface IFluidLiquidityAdmin { + /// @notice adds/removes auths. Auths generally could be contracts which can have restricted actions defined on contract. + /// auths can be helpful in reducing governance overhead where it's not needed. + /// @param authsStatus_ array of structs setting allowed status for an address. + /// status true => add auth, false => remove auth + function updateAuths( + AdminModuleStructs.AddressBool[] calldata authsStatus_ + ) external; + + /// @notice adds/removes guardians. Only callable by Governance. + /// @param guardiansStatus_ array of structs setting allowed status for an address. + /// status true => add guardian, false => remove guardian + function updateGuardians( + AdminModuleStructs.AddressBool[] calldata guardiansStatus_ + ) external; + + /// @notice changes the revenue collector address (contract that is sent revenue). Only callable by Governance. + /// @param revenueCollector_ new revenue collector address + function updateRevenueCollector(address revenueCollector_) external; + + /// @notice changes current status, e.g. for pausing or unpausing all user operations. Only callable by Auths. + /// @param newStatus_ new status + /// status = 2 -> pause, status = 1 -> resume. + function changeStatus(uint256 newStatus_) external; + + /// @notice update tokens rate data version 1. Only callable by Auths. + /// @param tokensRateData_ array of RateDataV1Params with rate data to set for each token + function updateRateDataV1s( + AdminModuleStructs.RateDataV1Params[] calldata tokensRateData_ + ) external; + + /// @notice update tokens rate data version 2. Only callable by Auths. + /// @param tokensRateData_ array of RateDataV2Params with rate data to set for each token + function updateRateDataV2s( + AdminModuleStructs.RateDataV2Params[] calldata tokensRateData_ + ) external; + + /// @notice updates token configs: fee charge on borrowers interest & storage update utilization threshold. + /// Only callable by Auths. + /// @param tokenConfigs_ contains token address, fee & utilization threshold + function updateTokenConfigs( + AdminModuleStructs.TokenConfig[] calldata tokenConfigs_ + ) external; + + /// @notice updates user classes: 0 is for new protocols, 1 is for established protocols. + /// Only callable by Auths. + /// @param userClasses_ struct array of uint256 value to assign for each user address + function updateUserClasses( + AdminModuleStructs.AddressUint256[] calldata userClasses_ + ) external; + + /// @notice sets user supply configs per token basis. Eg: with interest or interest-free and automated limits. + /// Only callable by Auths. + /// @param userSupplyConfigs_ struct array containing user supply config, see `UserSupplyConfig` struct for more info + function updateUserSupplyConfigs( + AdminModuleStructs.UserSupplyConfig[] memory userSupplyConfigs_ + ) external; + + /// @notice setting user borrow configs per token basis. Eg: with interest or interest-free and automated limits. + /// Only callable by Auths. + /// @param userBorrowConfigs_ struct array containing user borrow config, see `UserBorrowConfig` struct for more info + function updateUserBorrowConfigs( + AdminModuleStructs.UserBorrowConfig[] memory userBorrowConfigs_ + ) external; + + /// @notice pause operations for a particular user in class 0 (class 1 users can't be paused by guardians). + /// Only callable by Guardians. + /// @param user_ address of user to pause operations for + /// @param supplyTokens_ token addresses to pause withdrawals for + /// @param borrowTokens_ token addresses to pause borrowings for + function pauseUser( + address user_, + address[] calldata supplyTokens_, + address[] calldata borrowTokens_ + ) external; + + /// @notice unpause operations for a particular user in class 0 (class 1 users can't be paused by guardians). + /// Only callable by Guardians. + /// @param user_ address of user to unpause operations for + /// @param supplyTokens_ token addresses to unpause withdrawals for + /// @param borrowTokens_ token addresses to unpause borrowings for + function unpauseUser( + address user_, + address[] calldata supplyTokens_, + address[] calldata borrowTokens_ + ) external; + + /// @notice collects revenue for tokens to configured revenueCollector address. + /// @param tokens_ array of tokens to collect revenue for + /// @dev Note that this can revert if token balance is < revenueAmount (utilization > 100%) + function collectRevenue(address[] calldata tokens_) external; + + /// @notice gets the current updated exchange prices for n tokens and updates all prices, rates related data in storage. + /// @param tokens_ tokens to update exchange prices for + /// @return supplyExchangePrices_ new supply rates of overall system for each token + /// @return borrowExchangePrices_ new borrow rates of overall system for each token + function updateExchangePrices( + address[] calldata tokens_ + ) + external + returns ( + uint256[] memory supplyExchangePrices_, + uint256[] memory borrowExchangePrices_ + ); + + function readFromStorage( + bytes32 slot_ + ) external view returns (uint256 result_); +} + +interface FluidVaultFactory { + /// @notice Sets an address as allowed vault deployment logic (`deploymentLogic_`) contract or not. + /// This function can only be called by the owner. + /// @param deploymentLogic_ The address of the vault deployment logic contract to be set. + /// @param allowed_ A boolean indicating whether the specified address is allowed to deploy new type of vault. + function setVaultDeploymentLogic( + address deploymentLogic_, + bool allowed_ + ) external; + + /// @notice Sets an address (`vaultAuth_`) as allowed vault authorization or not for a specific vault (`vault_`). + /// This function can only be called by the owner. + /// @param vault_ The address of the vault for which the authorization is being set. + /// @param vaultAuth_ The address to be set as vault authorization. + /// @param allowed_ A boolean indicating whether the specified address is allowed to update the specific vault config. + function setVaultAuth( + address vault_, + address vaultAuth_, + bool allowed_ + ) external; + + /// @notice Computes the address of a vault based on its given ID (`vaultId_`). + /// @param vaultId_ The ID of the vault. + /// @return vault_ Returns the computed address of the vault. + function getVaultAddress( + uint256 vaultId_ + ) external view returns (address vault_); +} + +interface IFluidReserveContract { + function isRebalancer(address user) external returns (bool); + + function rebalanceFToken(address protocol_) external; + + function rebalanceVault(address protocol_) external; + + function transferFunds(address token_) external; + + function getProtocolTokens(address protocol_) external; + + function updateAuth(address auth_, bool isAuth_) external; + + function updateRebalancer(address rebalancer_, bool isRebalancer_) external; + + function approve( + address[] memory protocols_, + address[] memory tokens_, + uint256[] memory amounts_ + ) external; + + function revoke( + address[] memory protocols_, + address[] memory tokens_ + ) external; +} + +interface IFTokenAdmin { + /// @notice updates the rewards rate model contract. + /// Only callable by LendingFactory auths. + /// @param rewardsRateModel_ the new rewards rate model contract address. + /// can be set to address(0) to set no rewards (to save gas) + function updateRewards(address rewardsRateModel_) external; + + /// @notice Balances out the difference between fToken supply at Liquidity vs totalAssets(). + /// Deposits underlying from rebalancer address into Liquidity but doesn't mint any shares + /// -> thus making deposit available as rewards. + /// Only callable by rebalancer. + /// @return assets_ amount deposited to Liquidity + function rebalance() external payable returns (uint256 assets_); + + /// @notice gets the liquidity exchange price of the underlying asset, calculates the updated exchange price (with reward rates) + /// and writes those values to storage. + /// Callable by anyone. + /// @return tokenExchangePrice_ exchange price of fToken share to underlying asset + /// @return liquidityExchangePrice_ exchange price at Liquidity for the underlying asset + function updateRates() + external + returns (uint256 tokenExchangePrice_, uint256 liquidityExchangePrice_); + + /// @notice sends any potentially stuck funds to Liquidity contract. Only callable by LendingFactory auths. + function rescueFunds(address token_) external; + + /// @notice Updates the rebalancer address (ReserveContract). Only callable by LendingFactory auths. + function updateRebalancer(address rebalancer_) external; +} + +interface IERC20 { + function allowance( + address spender, + address caller + ) external view returns (uint256); + + function balanceOf(address account) external view returns (uint256); +} + +interface FluidDexFactory { + /// @notice Computes the address of a dex based on its given ID (`dexId_`). + /// @param dexId_ The ID of the dex. + /// @return dex_ Returns the computed address of the dex. + function getDexAddress(uint256 dexId_) external view returns (address dex_); + + function setDexAuth(address dex_, address dexAuth_, bool allowed_) external; + + function owner() external view returns (address); +} + +interface IFluidDex { + /// @param upperThresholdPercent_ in 4 decimals, 10000 = 1% + /// @param lowerThresholdPercent_ in 4 decimals, 10000 = 1% + /// @param thresholdShiftTime_ in secs, in how much time the threshold percent should take to shift the ranges + /// @param shiftTime_ in secs, in how much time the upper config changes should be fully done. + function updateThresholdPercent( + uint upperThresholdPercent_, + uint lowerThresholdPercent_, + uint thresholdShiftTime_, + uint shiftTime_ + ) external; + + function updateCenterPriceLimits( + uint maxCenterPrice_, + uint minCenterPrice_ + ) external; + + function updateCenterPriceAddress( + uint centerPriceAddress_, + uint percent_, + uint time_ + ) external; + + function readFromStorage( + bytes32 slot_ + ) external view returns (uint256 result_); + + function updateMaxSupplyShares(uint maxSupplyShares_) external; + + function updateMaxBorrowShares(uint maxBorrowShares_) external; + + /// @notice struct to set user supply & withdrawal config + struct UserSupplyConfig { + /// + /// @param user address + address user; + /// + /// @param expandPercent withdrawal limit expand percent. in 1e2: 100% = 10_000; 1% = 100 + /// Also used to calculate rate at which withdrawal limit should decrease (instant). + uint256 expandPercent; + /// + /// @param expandDuration withdrawal limit expand duration in seconds. + /// used to calculate rate together with expandPercent + uint256 expandDuration; + /// + /// @param baseWithdrawalLimit base limit, below this, user can withdraw the entire amount. + /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token: + /// with interest -> raw, without interest -> normal + uint256 baseWithdrawalLimit; + } + + /// @notice struct to set user borrow & payback config + struct UserBorrowConfig { + /// + /// @param user address + address user; + /// + /// @param expandPercent debt limit expand percent. in 1e2: 100% = 10_000; 1% = 100 + /// Also used to calculate rate at which debt limit should decrease (instant). + uint256 expandPercent; + /// + /// @param expandDuration debt limit expand duration in seconds. + /// used to calculate rate together with expandPercent + uint256 expandDuration; + /// + /// @param baseDebtCeiling base borrow limit. until here, borrow limit remains as baseDebtCeiling + /// (user can borrow until this point at once without stepped expansion). Above this, automated limit comes in place. + /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token: + /// with interest -> raw, without interest -> normal + uint256 baseDebtCeiling; + /// + /// @param maxDebtCeiling max borrow ceiling, maximum amount the user can borrow. + /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token: + /// with interest -> raw, without interest -> normal + uint256 maxDebtCeiling; + } + + function updateUserBorrowConfigs( + UserBorrowConfig[] memory userBorrowConfigs_ + ) external; + + function updateUserSupplyConfigs( + UserSupplyConfig[] memory userSupplyConfigs_ + ) external; + + struct InitializeVariables { + bool smartCol; + uint token0ColAmt; + bool smartDebt; + uint token0DebtAmt; + uint centerPrice; + uint fee; + uint revenueCut; + uint upperPercent; + uint lowerPercent; + uint upperShiftThreshold; + uint lowerShiftThreshold; + uint thresholdShiftTime; + uint centerPriceAddress; + uint hookAddress; + uint maxCenterPrice; + uint minCenterPrice; + } + + function initialize(InitializeVariables memory initializeVariables_) external payable; +} + +interface IFluidDexResolver { + struct Configs { + bool isSmartCollateralEnabled; + bool isSmartDebtEnabled; + uint256 fee; + uint256 revenueCut; + uint256 upperRange; + uint256 lowerRange; + uint256 upperShiftThreshold; + uint256 lowerShiftThreshold; + uint256 shiftingTime; + address centerPriceAddress; + address hookAddress; + uint256 maxCenterPrice; + uint256 minCenterPrice; + uint256 utilizationLimitToken0; + uint256 utilizationLimitToken1; + uint256 maxSupplyShares; + uint256 maxBorrowShares; + } + + function getDexConfigs( + address dex_ + ) external view returns (Configs memory configs_); +} + +interface IFluidVaultT1 { + /// @notice updates the Vault oracle to `newOracle_`. Must implement the FluidOracle interface. + function updateOracle(address newOracle_) external; + + /// @notice updates the all Vault core settings according to input params. + /// All input values are expected in 1e2 (1% = 100, 100% = 10_000). + function updateCoreSettings( + uint256 supplyRateMagnifier_, + uint256 borrowRateMagnifier_, + uint256 collateralFactor_, + uint256 liquidationThreshold_, + uint256 liquidationMaxLimit_, + uint256 withdrawGap_, + uint256 liquidationPenalty_, + uint256 borrowFee_ + ) external; + + /// @notice updates the allowed rebalancer to `newRebalancer_`. + function updateRebalancer(address newRebalancer_) external; + + /// @notice updates the supply rate magnifier to `supplyRateMagnifier_`. Input in 1e2 (1% = 100, 100% = 10_000). + function updateSupplyRateMagnifier(uint supplyRateMagnifier_) external; + + /// @notice updates the borrow rate magnifier to `borrowRateMagnifier_`. Input in 1e2 (1% = 100, 100% = 10_000). + function updateBorrowRateMagnifier(uint borrowRateMagnifier_) external; + + /// @notice updates the collateral factor to `collateralFactor_`. Input in 1e2 (1% = 100, 100% = 10_000). + function updateCollateralFactor(uint collateralFactor_) external; + + /// @notice updates the liquidation threshold to `liquidationThreshold_`. Input in 1e2 (1% = 100, 100% = 10_000). + function updateLiquidationThreshold(uint liquidationThreshold_) external; + + /// @notice updates the liquidation max limit to `liquidationMaxLimit_`. Input in 1e2 (1% = 100, 100% = 10_000). + function updateLiquidationMaxLimit(uint liquidationMaxLimit_) external; + + /// @notice updates the withdrawal gap to `withdrawGap_`. Input in 1e2 (1% = 100, 100% = 10_000). + function updateWithdrawGap(uint withdrawGap_) external; + + /// @notice updates the liquidation penalty to `liquidationPenalty_`. Input in 1e2 (1% = 100, 100% = 10_000). + function updateLiquidationPenalty(uint liquidationPenalty_) external; + + /// @notice updates the borrow fee to `borrowFee_`. Input in 1e2 (1% = 100, 100% = 10_000). + function updateBorrowFee(uint borrowFee_) external; + + function readFromStorage( + bytes32 slot_ + ) external view returns (uint256 result_); + + struct ConstantViews { + address liquidity; + address factory; + address adminImplementation; + address secondaryImplementation; + address supplyToken; + address borrowToken; + uint8 supplyDecimals; + uint8 borrowDecimals; + uint vaultId; + bytes32 liquiditySupplyExchangePriceSlot; + bytes32 liquidityBorrowExchangePriceSlot; + bytes32 liquidityUserSupplySlot; + bytes32 liquidityUserBorrowSlot; + } + + /// @notice returns all Vault constants + function constantsView() + external + view + returns (ConstantViews memory constantsView_); +} + +interface ILendingRewards { + function start() external; +} + +interface IFluidVault { + function updateOracle(uint256 newOracle_) external; +} + +interface IDSAV2 { + function cast( + string[] memory _targetNames, + bytes[] memory _datas, + address _origin + ) + external + payable + returns (bytes32); + + function isAuth(address user) external view returns (bool); +} + +contract PayloadIGP56 { + uint256 public constant PROPOSAL_ID = 56; + + address public constant PROPOSER = + 0xA45f7bD6A5Ff45D31aaCE6bCD3d426D9328cea01; + address public constant PROPOSER_AVO_MULTISIG = + 0x059a94a72451c0ae1Cc1cE4bf0Db52421Bbe8210; + address public constant PROPOSER_AVO_MULTISIG_2 = + 0x9efdE135CA4832AbF0408c44c6f5f370eB0f35e8; + address public constant PROPOSER_AVO_MULTISIG_3 = + 0x5C43AAC965ff230AC1cF63e924D0153291D78BaD; + + IGovernorBravo public constant GOVERNOR = + IGovernorBravo(0x0204Cd037B2ec03605CFdFe482D8e257C765fA1B); + ITimelock public constant TIMELOCK = + ITimelock(0x2386DC45AdDed673317eF068992F19421B481F4c); + + address public constant TEAM_MULTISIG = + 0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e; + + IDSAV2 public constant TREASURY = IDSAV2(0x28849D2b63fA8D361e5fc15cB8aBB13019884d09); + + address public immutable ADDRESS_THIS; + + IFluidLiquidityAdmin public constant LIQUIDITY = + IFluidLiquidityAdmin(0x52Aa899454998Be5b000Ad077a46Bbe360F4e497); + IFluidReserveContract public constant FLUID_RESERVE = + IFluidReserveContract(0x264786EF916af64a1DB19F513F24a3681734ce92); + + FluidVaultFactory public constant VAULT_FACTORY = + FluidVaultFactory(0x324c5Dc1fC42c7a4D43d92df1eBA58a54d13Bf2d); + FluidDexFactory public constant DEX_FACTORY = + FluidDexFactory(0x91716C4EDA1Fb55e84Bf8b4c7085f84285c19085); + + address internal constant ETH_ADDRESS = + 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + address internal constant wstETH_ADDRESS = + 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; + address internal constant weETH_ADDRESS = + 0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee; + + address internal constant USDC_ADDRESS = + 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; + address internal constant USDT_ADDRESS = + 0xdAC17F958D2ee523a2206206994597C13D831ec7; + address internal constant sUSDe_ADDRESS = + 0x9D39A5DE30e57443BfF2A8307A4256c8797A3497; + address internal constant sUSDs_ADDRESS = + 0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD; + address internal constant USDe_ADDRESS = + 0x4c9EDD5852cd905f086C759E8383e09bff1E68B3; + + address internal constant GHO_ADDRESS = + 0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f; + + address internal constant WBTC_ADDRESS = + 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599; + address internal constant cbBTC_ADDRESS = + 0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf; + + address internal constant INST_ADDRESS = + 0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb; + + address public constant F_USDT = 0x5C20B550819128074FD538Edf79791733ccEdd18; + address public constant F_USDC = 0x9Fb7b4477576Fe5B32be4C1843aFB1e55F251B33; + + uint256 internal constant X8 = 0xff; + uint256 internal constant X10 = 0x3ff; + uint256 internal constant X14 = 0x3fff; + uint256 internal constant X15 = 0x7fff; + uint256 internal constant X16 = 0xffff; + uint256 internal constant X18 = 0x3ffff; + uint256 internal constant X24 = 0xffffff; + uint256 internal constant X64 = 0xffffffffffffffff; + + uint256 internal constant DEFAULT_EXPONENT_SIZE = 8; + uint256 internal constant DEFAULT_EXPONENT_MASK = 0xff; + + IFluidDexResolver public constant FLUID_DEX_RESOLVER = + IFluidDexResolver(0x7af0C11F5c787632e567e6418D74e5832d8FFd4c); + + bool public executable; + + struct Dex { + address dex; + address tokenA; + address tokenB; + bool smartCollateral; + bool smartDebt; + uint256 baseWithdrawalLimitInUSD; + uint256 baseBorrowLimitInUSD; + uint256 maxBorrowLimitInUSD; + } + + enum TYPE { + TYPE_2, + TYPE_3, + TYPE_4 + } + + struct Vault { + address vault; + TYPE vaultType; + address supplyToken; + address borrowToken; + uint256 baseWithdrawalLimitInUSD; + uint256 baseBorrowLimitInUSD; + uint256 maxBorrowLimitInUSD; + } + + constructor() { + ADDRESS_THIS = address(this); + } + + function propose(string memory description) external { + require( + msg.sender == PROPOSER || + msg.sender == TEAM_MULTISIG || + address(this) == PROPOSER_AVO_MULTISIG || + address(this) == PROPOSER_AVO_MULTISIG_2 || + address(PROPOSER_AVO_MULTISIG_3) == PROPOSER_AVO_MULTISIG_3, + "msg.sender-not-allowed" + ); + + uint256 totalActions = 1; + address[] memory targets = new address[](totalActions); + uint256[] memory values = new uint256[](totalActions); + string[] memory signatures = new string[](totalActions); + bytes[] memory calldatas = new bytes[](totalActions); + + // Action 1: call executePayload on timelock contract to execute payload related to Fluid. + targets[0] = address(TIMELOCK); + values[0] = 0; + signatures[0] = "executePayload(address,string,bytes)"; + calldatas[0] = abi.encode(ADDRESS_THIS, "execute()", abi.encode()); + + uint256 proposedId = GOVERNOR.propose( + targets, + values, + signatures, + calldatas, + description + ); + + require(proposedId == PROPOSAL_ID, "PROPOSAL_IS_NOT_SAME"); + } + + function execute() external { + require(address(this) == address(TIMELOCK), "not-valid-caller"); + require(PayloadIGP56(ADDRESS_THIS).executable(), "not-executable"); + + // Action 1: Set INST Market Rates + action1(); + + // Action 2: Set INST-USDC Dex Pool Limits + action2(); + } + + function verifyProposal() external view {} + + /** + * | + * | Proposal Payload Actions | + * |__________________________________ + */ + + /// @notice Action 1: Set INST Market Rates. + function action1() internal { + AdminModuleStructs.RateDataV2Params[] memory params_ = new AdminModuleStructs.RateDataV2Params[](1); + + params_[0] = AdminModuleStructs.RateDataV2Params({ + token: USDC_ADDRESS, // USDC + kink1: 85 * 1e2, // 85% + kink2: 93 * 1e2, // 93% + rateAtUtilizationZero: 0, // 0% + rateAtUtilizationKink1: 7 * 1e2, // 7% + rateAtUtilizationKink2: 10 * 1e2, // 10% + rateAtUtilizationMax: 33 * 1e2 // 33% + }); + + LIQUIDITY.updateRateDataV2s(params_); + } + + /// @notice Action 2: Set INST-ETH Dex Pool Limits + function action2() internal { + address INST_ETH_ADDRESS = getDexAddress(10); + + { // Set DEX Limits on Liquidity Layer + Dex memory DEX_INST_ETH = Dex({ + dex: INST_ETH_ADDRESS, + tokenA: INST_ADDRESS, + tokenB: ETH_ADDRESS, + smartCollateral: true, + smartDebt: false, + baseWithdrawalLimitInUSD: 50_000_000, // $50M + baseBorrowLimitInUSD: 0, // $0 + maxBorrowLimitInUSD: 0 // $0 + }); + setDexLimits(DEX_INST_ETH); // Smart Collateral + } + + { // Initialize INST-ETH DEX + + uint256 centerPrice_ = uint256(10 * 1e27) / (3500); // Assuming ETH Price 3_500 and $10M INST + uint256 minCenterPrice_ = centerPrice_ / 100; + uint256 maxCenterPrice_ = centerPrice_ * 100; + + uint256 token0Amount_ = 20 * 1e18; + uint256 token1Amount_ = centerPrice_ * token0Amount_ / 1e27; + + IFluidDex.InitializeVariables memory initializeVariables_ = IFluidDex.InitializeVariables({ + smartCol: true, + token0ColAmt: token0Amount_, + smartDebt: false, + token0DebtAmt: 0, + centerPrice: centerPrice_, + fee: 1 * 1e4, + revenueCut: 0, + upperPercent: 30 * 1e4, + lowerPercent: 30 * 1e4, + upperShiftThreshold: 0, + lowerShiftThreshold: 0, + thresholdShiftTime: 30 days, + centerPriceAddress: 0, + hookAddress: 0, + maxCenterPrice: maxCenterPrice_, + minCenterPrice: minCenterPrice_ + }); + + IFluidDex(INST_ETH_ADDRESS).initialize{value: token1Amount_}(initializeVariables_); + } + + { // Set DSA Treasury as user on INST-ETH Dex + IFluidDex.UserSupplyConfig[] + memory config_ = new IFluidDex.UserSupplyConfig[](1); + + config_[0] = IFluidDex.UserSupplyConfig({ + user: address(TREASURY), + expandPercent: 25 * 1e2, // 25% + expandDuration: 12 hours, // 12 hours + baseWithdrawalLimit: 75 * 1e18 // 75 shares // TODO: Verify this + }); + + IFluidDex(INST_ETH_ADDRESS).updateUserSupplyConfigs( + config_ + ); + } + + { // Supply 8M INST + string[] memory targets = new string[](1); + bytes[] memory encodedSpells = new bytes[](1); + + string memory depositSignature = "deposit(address,uint256,uint256,uint256)"; + + // Spell 1: Deposit INST into INST-ETH Dex + { + uint256 token0Amount_ = 8_000_000 * 1e18; // 8M INST + uint256 token1Amount_ = 0; // 0 ETH + uint256 minShareAmount_ = 0; // 0 shares + + targets[0] = "BASIC-A"; + encodedSpells[0] = abi.encodeWithSignature( + depositSignature, + INST_ETH_ADDRESS, + token0Amount_, // token0 INST + token1Amount_, // token1 ETH + minShareAmount_ + ); + } + + IDSAV2(TREASURY).cast(targets, encodedSpells, address(this)); + } + } + + /** + * | + * | Team Multisig Functions | + * |__________________________________ + */ + + modifier onlyTeamMultisig() { + require(msg.sender == TEAM_MULTISIG, "msg.sender-not-allowed"); + _; + } + + function setExecutable(bool executable_) external onlyTeamMultisig { + executable = executable_; + } + + /** + * | + * | Proposal Payload Helpers | + * |__________________________________ + */ + function getVaultAddress(uint256 vaultId_) public view returns (address) { + return VAULT_FACTORY.getVaultAddress(vaultId_); + } + + function getDexAddress(uint256 dexId_) public view returns (address) { + return DEX_FACTORY.getDexAddress(dexId_); + } + + struct SupplyProtocolConfig { + address protocol; + address supplyToken; + uint256 expandPercent; + uint256 expandDuration; + uint256 baseWithdrawalLimitInUSD; + } + + struct BorrowProtocolConfig { + address protocol; + address borrowToken; + uint256 expandPercent; + uint256 expandDuration; + uint256 baseBorrowLimitInUSD; + uint256 maxBorrowLimitInUSD; + } + + function setDexLimits(Dex memory dex_) internal { + // Smart Collateral + if (dex_.smartCollateral) { + SupplyProtocolConfig memory protocolConfigTokenA_ = SupplyProtocolConfig({ + protocol: dex_.dex, + supplyToken: dex_.tokenA, + expandPercent: 50 * 1e2, // 50% + expandDuration: 1 hours, // 1 hour + baseWithdrawalLimitInUSD: dex_.baseWithdrawalLimitInUSD + }); + + setSupplyProtocolLimits(protocolConfigTokenA_); + + SupplyProtocolConfig memory protocolConfigTokenB_ = SupplyProtocolConfig({ + protocol: dex_.dex, + supplyToken: dex_.tokenB, + expandPercent: 50 * 1e2, // 50% + expandDuration: 1 hours, // 1 hour + baseWithdrawalLimitInUSD: dex_.baseWithdrawalLimitInUSD + }); + + setSupplyProtocolLimits(protocolConfigTokenB_); + } + + // Smart Debt + if (dex_.smartDebt) { + BorrowProtocolConfig memory protocolConfigTokenA_ = BorrowProtocolConfig({ + protocol: dex_.dex, + borrowToken: dex_.tokenA, + expandPercent: 50 * 1e2, // 50% + expandDuration: 1 hours, // 1 hour + baseBorrowLimitInUSD: dex_.baseBorrowLimitInUSD, + maxBorrowLimitInUSD: dex_.maxBorrowLimitInUSD + }); + + setBorrowProtocolLimits(protocolConfigTokenA_); + + BorrowProtocolConfig memory protocolConfigTokenB_ = BorrowProtocolConfig({ + protocol: dex_.dex, + borrowToken: dex_.tokenB, + expandPercent: 50 * 1e2, // 50% + expandDuration: 1 hours, // 1 hour + baseBorrowLimitInUSD: dex_.baseBorrowLimitInUSD, + maxBorrowLimitInUSD: dex_.maxBorrowLimitInUSD + }); + + setBorrowProtocolLimits(protocolConfigTokenB_); + } + } + + function setSupplyProtocolLimits( + SupplyProtocolConfig memory protocolConfig_ + ) internal { + { + // Supply Limits + AdminModuleStructs.UserSupplyConfig[] + memory configs_ = new AdminModuleStructs.UserSupplyConfig[](1); + + configs_[0] = AdminModuleStructs.UserSupplyConfig({ + user: address(protocolConfig_.protocol), + token: protocolConfig_.supplyToken, + mode: 1, + expandPercent: protocolConfig_.expandPercent, + expandDuration: protocolConfig_.expandDuration, + baseWithdrawalLimit: getRawAmount( + protocolConfig_.supplyToken, + 0, + protocolConfig_.baseWithdrawalLimitInUSD, + true + ) + }); + + LIQUIDITY.updateUserSupplyConfigs(configs_); + } + } + + function setBorrowProtocolLimits( + BorrowProtocolConfig memory protocolConfig_ + ) internal { + { + // Borrow Limits + AdminModuleStructs.UserBorrowConfig[] + memory configs_ = new AdminModuleStructs.UserBorrowConfig[](1); + + configs_[0] = AdminModuleStructs.UserBorrowConfig({ + user: address(protocolConfig_.protocol), + token: protocolConfig_.borrowToken, + mode: 1, + expandPercent: protocolConfig_.expandPercent, + expandDuration: protocolConfig_.expandDuration, + baseDebtCeiling: getRawAmount( + protocolConfig_.borrowToken, + 0, + protocolConfig_.baseBorrowLimitInUSD, + false + ), + maxDebtCeiling: getRawAmount( + protocolConfig_.borrowToken, + 0, + protocolConfig_.maxBorrowLimitInUSD, + false + ) + }); + + LIQUIDITY.updateUserBorrowConfigs(configs_); + } + } + + function getRawAmount( + address token, + uint256 amount, + uint256 amountInUSD, + bool isSupply + ) public view returns (uint256) { + if (amount > 0 && amountInUSD > 0) { + revert("both usd and amount are not zero"); + } + uint256 exchangePriceAndConfig_ = LIQUIDITY.readFromStorage( + LiquiditySlotsLink.calculateMappingStorageSlot( + LiquiditySlotsLink.LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT, + token + ) + ); + + ( + uint256 supplyExchangePrice, + uint256 borrowExchangePrice + ) = LiquidityCalcs.calcExchangePrices(exchangePriceAndConfig_); + + uint256 usdPrice = 0; + uint256 decimals = 18; + if (token == ETH_ADDRESS) { + usdPrice = 3_350 * 1e2; + decimals = 18; + } else if (token == wstETH_ADDRESS) { + usdPrice = 3_950 * 1e2; + decimals = 18; + } else if (token == weETH_ADDRESS) { + usdPrice = 3_500 * 1e2; + decimals = 18; + } else if (token == cbBTC_ADDRESS || token == WBTC_ADDRESS) { + usdPrice = 99_000 * 1e2; + decimals = 8; + } else if (token == USDC_ADDRESS || token == USDT_ADDRESS) { + usdPrice = 1 * 1e2; + decimals = 6; + } else if (token == sUSDe_ADDRESS) { + usdPrice = 1.12 * 1e2; + decimals = 18; + } else if (token == sUSDs_ADDRESS) { + usdPrice = 1.12 * 1e2; + decimals = 18; + } else if (token == GHO_ADDRESS || token == USDe_ADDRESS) { + usdPrice = 1 * 1e2; + decimals = 18; + } else if (token == INST_ADDRESS) { + usdPrice = 5.75 * 1e2; + decimals = 18; + } else { + revert("not-found"); + } + + uint256 exchangePrice = isSupply + ? supplyExchangePrice + : borrowExchangePrice; + + if (amount > 0) { + return (amount * 1e12) / exchangePrice; + } else { + return + (amountInUSD * 1e12 * (10 ** decimals)) / + ((usdPrice * exchangePrice) / 1e2); + } + } +} From adfdfae73c8f47ec12490e1c7b3bc7a51956beea Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Tue, 26 Nov 2024 01:09:58 +0400 Subject: [PATCH 2/6] update --- contracts/payloads/IGP56/PayloadIGP56.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/payloads/IGP56/PayloadIGP56.sol b/contracts/payloads/IGP56/PayloadIGP56.sol index fa88439..66d2c35 100644 --- a/contracts/payloads/IGP56/PayloadIGP56.sol +++ b/contracts/payloads/IGP56/PayloadIGP56.sol @@ -821,7 +821,7 @@ contract PayloadIGP56 { uint256 token1Amount_ = 0; // 0 ETH uint256 minShareAmount_ = 0; // 0 shares - targets[0] = "BASIC-A"; + targets[0] = "FLUID-DEX-A"; encodedSpells[0] = abi.encodeWithSignature( depositSignature, INST_ETH_ADDRESS, From 7d6267b0bf158dceec46251bfc428368e5080eec Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Tue, 26 Nov 2024 02:42:04 +0400 Subject: [PATCH 3/6] IGP-56 --- contracts/payloads/IGP56/PayloadIGP56.sol | 144 ++++++++++------------ 1 file changed, 65 insertions(+), 79 deletions(-) diff --git a/contracts/payloads/IGP56/PayloadIGP56.sol b/contracts/payloads/IGP56/PayloadIGP56.sol index 66d2c35..2dbc24c 100644 --- a/contracts/payloads/IGP56/PayloadIGP56.sol +++ b/contracts/payloads/IGP56/PayloadIGP56.sol @@ -322,6 +322,8 @@ interface IERC20 { address caller ) external view returns (uint256); + function approve(address spender, uint256 amount) external returns (bool); + function balanceOf(address account) external view returns (uint256); } @@ -715,8 +717,11 @@ contract PayloadIGP56 { // Action 1: Set INST Market Rates action1(); - // Action 2: Set INST-USDC Dex Pool Limits + // Action 2: Set INST-ETH Dex Pool and INST-ETH_ETH Vault Limits action2(); + + // Action 3: Transfer 5M INST to Team Multisig + action3(); } function verifyProposal() external view {} @@ -744,7 +749,7 @@ contract PayloadIGP56 { LIQUIDITY.updateRateDataV2s(params_); } - /// @notice Action 2: Set INST-ETH Dex Pool Limits + /// @notice Action 2: Set INST-ETH Dex Pool and INST-ETH_ETH Vault Limits function action2() internal { address INST_ETH_ADDRESS = getDexAddress(10); @@ -760,94 +765,47 @@ contract PayloadIGP56 { maxBorrowLimitInUSD: 0 // $0 }); setDexLimits(DEX_INST_ETH); // Smart Collateral - } - - { // Initialize INST-ETH DEX - - uint256 centerPrice_ = uint256(10 * 1e27) / (3500); // Assuming ETH Price 3_500 and $10M INST - uint256 minCenterPrice_ = centerPrice_ / 100; - uint256 maxCenterPrice_ = centerPrice_ * 100; - - uint256 token0Amount_ = 20 * 1e18; - uint256 token1Amount_ = centerPrice_ * token0Amount_ / 1e27; - - IFluidDex.InitializeVariables memory initializeVariables_ = IFluidDex.InitializeVariables({ - smartCol: true, - token0ColAmt: token0Amount_, - smartDebt: false, - token0DebtAmt: 0, - centerPrice: centerPrice_, - fee: 1 * 1e4, - revenueCut: 0, - upperPercent: 30 * 1e4, - lowerPercent: 30 * 1e4, - upperShiftThreshold: 0, - lowerShiftThreshold: 0, - thresholdShiftTime: 30 days, - centerPriceAddress: 0, - hookAddress: 0, - maxCenterPrice: maxCenterPrice_, - minCenterPrice: minCenterPrice_ - }); - IFluidDex(INST_ETH_ADDRESS).initialize{value: token1Amount_}(initializeVariables_); + DEX_FACTORY.setDexAuth(INST_ETH_ADDRESS, TEAM_MULTISIG, true); } - { // Set DSA Treasury as user on INST-ETH Dex - IFluidDex.UserSupplyConfig[] - memory config_ = new IFluidDex.UserSupplyConfig[](1); - - config_[0] = IFluidDex.UserSupplyConfig({ - user: address(TREASURY), - expandPercent: 25 * 1e2, // 25% - expandDuration: 12 hours, // 12 hours - baseWithdrawalLimit: 75 * 1e18 // 75 shares // TODO: Verify this + { + // [TYPE 2] INST-ETH | ETH | Smart collateral & debt + Vault memory VAULT_INST_ETH = Vault({ + vault: getVaultAddress(75), + vaultType: TYPE.TYPE_2, + supplyToken: address(0), + borrowToken: ETH_ADDRESS, + baseWithdrawalLimitInUSD: 0, // set at Dex + baseBorrowLimitInUSD: 100, // $100 + maxBorrowLimitInUSD: 150 // $150 }); - IFluidDex(INST_ETH_ADDRESS).updateUserSupplyConfigs( - config_ - ); - } + setVaultLimits(VAULT_INST_ETH); // TYPE_2 => 75 - { // Supply 8M INST - string[] memory targets = new string[](1); - bytes[] memory encodedSpells = new bytes[](1); - - string memory depositSignature = "deposit(address,uint256,uint256,uint256)"; - - // Spell 1: Deposit INST into INST-ETH Dex - { - uint256 token0Amount_ = 8_000_000 * 1e18; // 8M INST - uint256 token1Amount_ = 0; // 0 ETH - uint256 minShareAmount_ = 0; // 0 shares - - targets[0] = "FLUID-DEX-A"; - encodedSpells[0] = abi.encodeWithSignature( - depositSignature, - INST_ETH_ADDRESS, - token0Amount_, // token0 INST - token1Amount_, // token1 ETH - minShareAmount_ - ); - } - - IDSAV2(TREASURY).cast(targets, encodedSpells, address(this)); + VAULT_FACTORY.setVaultAuth( + getVaultAddress(75), + TEAM_MULTISIG, + true + ); } } - /** - * | - * | Team Multisig Functions | - * |__________________________________ - */ + /// @notice Action 3: Transfer 5M INST to Team Multisig + function action3() internal { + string[] memory targets = new string[](1); + bytes[] memory encodedSpells = new bytes[](1); - modifier onlyTeamMultisig() { - require(msg.sender == TEAM_MULTISIG, "msg.sender-not-allowed"); - _; - } + string memory withdrawSignature = "withdraw(address,uint256,address,uint256,uint256)"; + + // Spell 1: Transfer INST + { + uint256 INST_AMOUNT = 5_000_000 * 1e18; // 5M INST + targets[0] = "BASIC-A"; + encodedSpells[0] = abi.encodeWithSignature(withdrawSignature, INST_ADDRESS, INST_AMOUNT, TEAM_MULTISIG, 0, 0); + } - function setExecutable(bool executable_) external onlyTeamMultisig { - executable = executable_; + IDSAV2(TREASURY).cast(targets, encodedSpells, address(this)); } /** @@ -988,6 +946,34 @@ contract PayloadIGP56 { } } + + function setVaultLimits(Vault memory vault_) internal { + if (vault_.vaultType == TYPE.TYPE_3) { + SupplyProtocolConfig memory protocolConfig_ = SupplyProtocolConfig({ + protocol: vault_.vault, + supplyToken: vault_.supplyToken, + expandPercent: 25 * 1e2, // 25% + expandDuration: 12 hours, // 12 hours + baseWithdrawalLimitInUSD: vault_.baseWithdrawalLimitInUSD + }); + + setSupplyProtocolLimits(protocolConfig_); + } + + if (vault_.vaultType == TYPE.TYPE_2) { + BorrowProtocolConfig memory protocolConfig_ = BorrowProtocolConfig({ + protocol: vault_.vault, + borrowToken: vault_.borrowToken, + expandPercent: 20 * 1e2, // 20% + expandDuration: 12 hours, // 12 hours + baseBorrowLimitInUSD: vault_.baseBorrowLimitInUSD, + maxBorrowLimitInUSD: vault_.maxBorrowLimitInUSD + }); + + setBorrowProtocolLimits(protocolConfig_); + } + } + function getRawAmount( address token, uint256 amount, From edc886d183b08b0d857bb7ad6d4fac8151b23f4b Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Tue, 26 Nov 2024 16:22:08 +0400 Subject: [PATCH 4/6] Update --- contracts/payloads/IGP56/PayloadIGP56.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/payloads/IGP56/PayloadIGP56.sol b/contracts/payloads/IGP56/PayloadIGP56.sol index 2dbc24c..f543d6f 100644 --- a/contracts/payloads/IGP56/PayloadIGP56.sol +++ b/contracts/payloads/IGP56/PayloadIGP56.sol @@ -737,7 +737,7 @@ contract PayloadIGP56 { AdminModuleStructs.RateDataV2Params[] memory params_ = new AdminModuleStructs.RateDataV2Params[](1); params_[0] = AdminModuleStructs.RateDataV2Params({ - token: USDC_ADDRESS, // USDC + token: INST_ADDRESS, // INST kink1: 85 * 1e2, // 85% kink2: 93 * 1e2, // 93% rateAtUtilizationZero: 0, // 0% @@ -760,7 +760,7 @@ contract PayloadIGP56 { tokenB: ETH_ADDRESS, smartCollateral: true, smartDebt: false, - baseWithdrawalLimitInUSD: 50_000_000, // $50M + baseWithdrawalLimitInUSD: 10_000_000, // $10M baseBorrowLimitInUSD: 0, // $0 maxBorrowLimitInUSD: 0 // $0 }); @@ -777,8 +777,8 @@ contract PayloadIGP56 { supplyToken: address(0), borrowToken: ETH_ADDRESS, baseWithdrawalLimitInUSD: 0, // set at Dex - baseBorrowLimitInUSD: 100, // $100 - maxBorrowLimitInUSD: 150 // $150 + baseBorrowLimitInUSD: 200, // $200 + maxBorrowLimitInUSD: 300 // $300 }); setVaultLimits(VAULT_INST_ETH); // TYPE_2 => 75 From 949a76ae2e95fcb3ca5033ea3eb618b564e3c8cf Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Tue, 26 Nov 2024 16:59:12 +0400 Subject: [PATCH 5/6] update --- contracts/payloads/IGP56/PayloadIGP56.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/payloads/IGP56/PayloadIGP56.sol b/contracts/payloads/IGP56/PayloadIGP56.sol index f543d6f..7c21b5d 100644 --- a/contracts/payloads/IGP56/PayloadIGP56.sol +++ b/contracts/payloads/IGP56/PayloadIGP56.sol @@ -738,12 +738,12 @@ contract PayloadIGP56 { params_[0] = AdminModuleStructs.RateDataV2Params({ token: INST_ADDRESS, // INST - kink1: 85 * 1e2, // 85% - kink2: 93 * 1e2, // 93% + kink1: 40 * 1e2, // 40% + kink2: 80 * 1e2, // 80% rateAtUtilizationZero: 0, // 0% - rateAtUtilizationKink1: 7 * 1e2, // 7% - rateAtUtilizationKink2: 10 * 1e2, // 10% - rateAtUtilizationMax: 33 * 1e2 // 33% + rateAtUtilizationKink1: 5 * 1e2, // 5% + rateAtUtilizationKink2: 20 * 1e2, // 20% + rateAtUtilizationMax: 50 * 1e2 // 50% }); LIQUIDITY.updateRateDataV2s(params_); From 24bd4765f0094160fba0676ed8b8317880af2f08 Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Tue, 26 Nov 2024 19:27:46 +0400 Subject: [PATCH 6/6] Fix --- contracts/payloads/IGP56/PayloadIGP56.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/contracts/payloads/IGP56/PayloadIGP56.sol b/contracts/payloads/IGP56/PayloadIGP56.sol index 7c21b5d..c812f68 100644 --- a/contracts/payloads/IGP56/PayloadIGP56.sol +++ b/contracts/payloads/IGP56/PayloadIGP56.sol @@ -644,8 +644,6 @@ contract PayloadIGP56 { IFluidDexResolver public constant FLUID_DEX_RESOLVER = IFluidDexResolver(0x7af0C11F5c787632e567e6418D74e5832d8FFd4c); - bool public executable; - struct Dex { address dex; address tokenA; @@ -712,7 +710,6 @@ contract PayloadIGP56 { function execute() external { require(address(this) == address(TIMELOCK), "not-valid-caller"); - require(PayloadIGP56(ADDRESS_THIS).executable(), "not-executable"); // Action 1: Set INST Market Rates action1();