From 1a98c47674c0576631879de7ea2417969f4936b4 Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Mon, 15 Apr 2024 23:37:18 +0400 Subject: [PATCH 1/4] IGP-18 --- contracts/payloads/IGP18/PayloadIGP18.sol | 363 ++++++++++++++++++++++ 1 file changed, 363 insertions(+) create mode 100644 contracts/payloads/IGP18/PayloadIGP18.sol diff --git a/contracts/payloads/IGP18/PayloadIGP18.sol b/contracts/payloads/IGP18/PayloadIGP18.sol new file mode 100644 index 0000000..d2f65db --- /dev/null +++ b/contracts/payloads/IGP18/PayloadIGP18.sol @@ -0,0 +1,363 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +interface IGovernorBravo { + function _acceptAdmin() external; + + function _setVotingDelay(uint newVotingDelay) external; + + function _setVotingPeriod(uint newVotingPeriod) external; + + function _acceptAdminOnTimelock() external; + + function _setImplementation(address implementation_) external; + + function propose( + address[] memory targets, + uint[] memory values, + string[] memory signatures, + bytes[] memory calldatas, + string memory description + ) external returns (uint); + + 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(uint delay_) external; + + function setPendingAdmin(address pendingAdmin_) external; + + function queueTransaction( + address target, + uint value, + string memory signature, + bytes memory data, + uint eta + ) external returns (bytes32); + + function executeTransaction( + address target, + uint value, + string memory signature, + bytes memory data, + uint 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 IProxy { + function setAdmin(address newAdmin_) external; + + function setDummyImplementation(address newDummyImplementation_) external; + + function addImplementation(address implementation_, bytes4[] calldata sigs_) external; + + function removeImplementation(address implementation_) external; + + function getAdmin() external view returns (address); + + function getDummyImplementation() external view returns (address); + + function getImplementationSigs(address impl_) external view returns (bytes4[] memory); + + function getSigsImplementation(bytes4 sig_) external view returns (address); + + function readFromStorage(bytes32 slot_) external view returns (uint256 result_); +} + +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_ + ); +} + +interface IFluidLiquidityWeETHTransferModule { + function depositZircuit() external; +} + +contract PayloadIGP18 { + uint256 public constant PROPOSAL_ID = 18; + + address public constant PROPOSER = + 0xA45f7bD6A5Ff45D31aaCE6bCD3d426D9328cea01; + + address public constant PROPOSER_AVO_MULTISIG = + 0x059A94A72951c0ae1cc1CE3BF0dB52421bbE8210; + + IGovernorBravo public constant GOVERNOR = + IGovernorBravo(0x0204Cd037B2ec03605CFdFe482D8e257C765fA1B); + ITimelock public immutable TIMELOCK = + ITimelock(0x2386DC45AdDed673317eF068992F19421B481F4c); + + address public immutable ADDRESS_THIS; + + address public constant TEAM_MULTISIG = + 0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e; + + IFluidLiquidityAdmin public constant LIQUIDITY = + IFluidLiquidityAdmin(0x52Aa899454998Be5b000Ad077a46Bbe360F4e497); + + constructor() { + ADDRESS_THIS = address(this); + } + + function propose(string memory description) external { + require( + msg.sender == PROPOSER || + msg.sender == TEAM_MULTISIG || + address(this) == PROPOSER_AVO_MULTISIG, + "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"); + + // Action 1: Remove old UserModule from Liquidity infiniteProxy. + action1(); + + // Action 2:Add new UserModule to Liquidity infiniteProxy. + action2(); + + // Action 3: Add new WeETHTransferModule to Liquidity infiniteProxy. + action3(); + + // Action 4: call WeETHTransferModule depositZircuit() on Liquidity + action4(); + } + + function verifyProposal() external view {} + + /***********************************| + | Proposal Payload Actions | + |__________________________________*/ + + /// @notice Action 1: Remove old UserModule from Liquidity infiniteProxy. + function action1() internal { + IProxy(address(LIQUIDITY)).removeImplementation(0xfB45BC79e01b4e92706412A54e011db251104C74); + } + + /// @notice Action 2: Add new UserModule to Liquidity infiniteProxy. + function action2() internal { + bytes4[] memory sigs_ = new bytes4[](1); + + sigs_[0] = + bytes4(keccak256("operate(address,int256,int256,address,address,bytes)")); + + IProxy(address(LIQUIDITY)).addImplementation( + 0x968738c127f91b560bD614487F859999D5D02d9c, + sigs_ + ); + } + + /// @notice Action 3: Add new WeETHTransferModule to Liquidity infiniteProxy + function action3() internal { + bytes4[] memory sigs_ = new bytes4[](2); + + sigs_[0] = bytes4(keccak256("depositZircuit()")); + sigs_[1] = bytes4(keccak256("withdrawZircuit()")); + + IProxy(address(LIQUIDITY)).addImplementation( + 0xaD99E8416f505aCE0A087C5dAB7214F15aE3D1d1, + sigs_ + ); + } + + /// @notice Action 4: call WeETHTransferModule depositZircuit() on Liquidity + function action4() internal { + IFluidLiquidityWeETHTransferModule(address(LIQUIDITY)).depositZircuit(); + } +} From 427a4482041a03e5d67b580f0793cc3ab2ca9b41 Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Fri, 19 Apr 2024 16:48:41 +0400 Subject: [PATCH 2/4] update --- contracts/payloads/IGP18/PayloadIGP18.sol | 84 +++++++++++------------ 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/contracts/payloads/IGP18/PayloadIGP18.sol b/contracts/payloads/IGP18/PayloadIGP18.sol index d2f65db..13dd5a7 100644 --- a/contracts/payloads/IGP18/PayloadIGP18.sol +++ b/contracts/payloads/IGP18/PayloadIGP18.sol @@ -242,8 +242,37 @@ interface IFluidLiquidityAdmin { ); } -interface IFluidLiquidityWeETHTransferModule { - function depositZircuit() external; +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 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; } contract PayloadIGP18 { @@ -267,6 +296,8 @@ contract PayloadIGP18 { IFluidLiquidityAdmin public constant LIQUIDITY = IFluidLiquidityAdmin(0x52Aa899454998Be5b000Ad077a46Bbe360F4e497); + + address public constant VAULT_weETH_wstETH = address(0x40D9b8417E6E1DcD358f04E3328bCEd061018A82); constructor() { ADDRESS_THIS = address(this); @@ -306,17 +337,8 @@ contract PayloadIGP18 { function execute() external { require(address(this) == address(TIMELOCK), "not-valid-caller"); - // Action 1: Remove old UserModule from Liquidity infiniteProxy. + // Action 1: Update weETH/wstETH vault parameters. action1(); - - // Action 2:Add new UserModule to Liquidity infiniteProxy. - action2(); - - // Action 3: Add new WeETHTransferModule to Liquidity infiniteProxy. - action3(); - - // Action 4: call WeETHTransferModule depositZircuit() on Liquidity - action4(); } function verifyProposal() external view {} @@ -325,39 +347,15 @@ contract PayloadIGP18 { | Proposal Payload Actions | |__________________________________*/ - /// @notice Action 1: Remove old UserModule from Liquidity infiniteProxy. + /// @notice Action 1: Update weETH/wstETH vault parameters. function action1() internal { - IProxy(address(LIQUIDITY)).removeImplementation(0xfB45BC79e01b4e92706412A54e011db251104C74); - } + // Update collateral factor from 90.5% to 93%. + IFluidVaultT1(VAULT_weETH_wstETH).updateCollateralFactor(93 * 1e2); // 93% or 93 * 1e2 - /// @notice Action 2: Add new UserModule to Liquidity infiniteProxy. - function action2() internal { - bytes4[] memory sigs_ = new bytes4[](1); + // Update collateral factor from 93% to 95%. + IFluidVaultT1(VAULT_weETH_wstETH).updateLiquidationThreshold(53 * 1e2); // 95% or 95 * 1e2 - sigs_[0] = - bytes4(keccak256("operate(address,int256,int256,address,address,bytes)")); - - IProxy(address(LIQUIDITY)).addImplementation( - 0x968738c127f91b560bD614487F859999D5D02d9c, - sigs_ - ); - } - - /// @notice Action 3: Add new WeETHTransferModule to Liquidity infiniteProxy - function action3() internal { - bytes4[] memory sigs_ = new bytes4[](2); - - sigs_[0] = bytes4(keccak256("depositZircuit()")); - sigs_[1] = bytes4(keccak256("withdrawZircuit()")); - - IProxy(address(LIQUIDITY)).addImplementation( - 0xaD99E8416f505aCE0A087C5dAB7214F15aE3D1d1, - sigs_ - ); - } - - /// @notice Action 4: call WeETHTransferModule depositZircuit() on Liquidity - function action4() internal { - IFluidLiquidityWeETHTransferModule(address(LIQUIDITY)).depositZircuit(); + // Update collateral factor from 95% to 96%. + IFluidVaultT1(VAULT_weETH_wstETH).updateLiquidationMaxLimit(96 * 1e2); // 96% or 96 * 1e2 } } From cf50e65c59ca3d026997256f4a931e76eabf77a4 Mon Sep 17 00:00:00 2001 From: Samyak Jain <34437877+KaymasJain@users.noreply.github.com> Date: Fri, 19 Apr 2024 20:58:22 +0400 Subject: [PATCH 3/4] minor fix --- contracts/payloads/IGP18/PayloadIGP18.sol | 24 +++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/contracts/payloads/IGP18/PayloadIGP18.sol b/contracts/payloads/IGP18/PayloadIGP18.sol index 13dd5a7..7008f1a 100644 --- a/contracts/payloads/IGP18/PayloadIGP18.sol +++ b/contracts/payloads/IGP18/PayloadIGP18.sol @@ -121,7 +121,10 @@ interface IProxy { function setDummyImplementation(address newDummyImplementation_) external; - function addImplementation(address implementation_, bytes4[] calldata sigs_) external; + function addImplementation( + address implementation_, + bytes4[] calldata sigs_ + ) external; function removeImplementation(address implementation_) external; @@ -129,11 +132,15 @@ interface IProxy { function getDummyImplementation() external view returns (address); - function getImplementationSigs(address impl_) external view returns (bytes4[] memory); + function getImplementationSigs( + address impl_ + ) external view returns (bytes4[] memory); function getSigsImplementation(bytes4 sig_) external view returns (address); - function readFromStorage(bytes32 slot_) external view returns (uint256 result_); + function readFromStorage( + bytes32 slot_ + ) external view returns (uint256 result_); } interface IFluidLiquidityAdmin { @@ -296,8 +303,9 @@ contract PayloadIGP18 { IFluidLiquidityAdmin public constant LIQUIDITY = IFluidLiquidityAdmin(0x52Aa899454998Be5b000Ad077a46Bbe360F4e497); - - address public constant VAULT_weETH_wstETH = address(0x40D9b8417E6E1DcD358f04E3328bCEd061018A82); + + address public constant VAULT_weETH_wstETH = + address(0x40D9b8417E6E1DcD358f04E3328bCEd061018A82); constructor() { ADDRESS_THIS = address(this); @@ -352,10 +360,10 @@ contract PayloadIGP18 { // Update collateral factor from 90.5% to 93%. IFluidVaultT1(VAULT_weETH_wstETH).updateCollateralFactor(93 * 1e2); // 93% or 93 * 1e2 - // Update collateral factor from 93% to 95%. - IFluidVaultT1(VAULT_weETH_wstETH).updateLiquidationThreshold(53 * 1e2); // 95% or 95 * 1e2 + // Update liquidation threshold from 93% to 95%. + IFluidVaultT1(VAULT_weETH_wstETH).updateLiquidationThreshold(95 * 1e2); // 95% or 95 * 1e2 - // Update collateral factor from 95% to 96%. + // Update max liquidation limit from 95% to 96%. IFluidVaultT1(VAULT_weETH_wstETH).updateLiquidationMaxLimit(96 * 1e2); // 96% or 96 * 1e2 } } From da0b54056e2f396235ae5e3c993e886b19fb82af Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Fri, 19 Apr 2024 23:57:00 +0400 Subject: [PATCH 4/4] fix --- contracts/payloads/IGP18/PayloadIGP18.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/payloads/IGP18/PayloadIGP18.sol b/contracts/payloads/IGP18/PayloadIGP18.sol index 7008f1a..2089c94 100644 --- a/contracts/payloads/IGP18/PayloadIGP18.sol +++ b/contracts/payloads/IGP18/PayloadIGP18.sol @@ -357,13 +357,13 @@ contract PayloadIGP18 { /// @notice Action 1: Update weETH/wstETH vault parameters. function action1() internal { - // Update collateral factor from 90.5% to 93%. - IFluidVaultT1(VAULT_weETH_wstETH).updateCollateralFactor(93 * 1e2); // 93% or 93 * 1e2 + // Update max liquidation limit from 95% to 96%. + IFluidVaultT1(VAULT_weETH_wstETH).updateLiquidationMaxLimit(96 * 1e2); // 96% or 96 * 1e2 // Update liquidation threshold from 93% to 95%. IFluidVaultT1(VAULT_weETH_wstETH).updateLiquidationThreshold(95 * 1e2); // 95% or 95 * 1e2 - // Update max liquidation limit from 95% to 96%. - IFluidVaultT1(VAULT_weETH_wstETH).updateLiquidationMaxLimit(96 * 1e2); // 96% or 96 * 1e2 + // Update collateral factor from 90.5% to 93%. + IFluidVaultT1(VAULT_weETH_wstETH).updateCollateralFactor(93 * 1e2); // 93% or 93 * 1e2 } }