creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/payloads/IGP16/PayloadIGP16.sol": {
        "content": "pragma solidity ^0.7.0;\npragma experimental ABIEncoderV2;\n\ninterface IGovernorBravo {\n    function _acceptAdmin() external;\n\n    function _setVotingDelay(uint newVotingDelay) external;\n\n    function _setVotingPeriod(uint newVotingPeriod) external;\n\n    function _acceptAdminOnTimelock() external;\n\n    function _setImplementation(address implementation_) external;\n\n    function propose(\n        address[] memory targets,\n        uint[] memory values,\n        string[] memory signatures,\n        bytes[] memory calldatas,\n        string memory description\n    ) external returns (uint);\n\n    function admin() external view returns (address);\n\n    function pendingAdmin() external view returns (address);\n\n    function timelock() external view returns (address);\n\n    function votingDelay() external view returns (uint256);\n\n    function votingPeriod() external view returns (uint256);\n}\n\ninterface ITimelock {\n    function acceptAdmin() external;\n\n    function setDelay(uint delay_) external;\n\n    function setPendingAdmin(address pendingAdmin_) external;\n\n    function queueTransaction(\n        address target,\n        uint value,\n        string memory signature,\n        bytes memory data,\n        uint eta\n    ) external returns (bytes32);\n\n    function executeTransaction(\n        address target,\n        uint value,\n        string memory signature,\n        bytes memory data,\n        uint eta\n    ) external payable returns (bytes memory);\n\n    function pendingAdmin() external view returns (address);\n\n    function admin() external view returns (address);\n\n    function delay() external view returns (uint256);\n}\n\ninterface AdminModuleStructs {\n    struct AddressBool {\n        address addr;\n        bool value;\n    }\n\n    struct AddressUint256 {\n        address addr;\n        uint256 value;\n    }\n\n    struct RateDataV1Params {\n        address token;\n        uint256 kink;\n        uint256 rateAtUtilizationZero;\n        uint256 rateAtUtilizationKink;\n        uint256 rateAtUtilizationMax;\n    }\n\n    struct RateDataV2Params {\n        address token;\n        uint256 kink1;\n        uint256 kink2;\n        uint256 rateAtUtilizationZero;\n        uint256 rateAtUtilizationKink1;\n        uint256 rateAtUtilizationKink2;\n        uint256 rateAtUtilizationMax;\n    }\n\n    struct TokenConfig {\n        address token;\n        uint256 fee;\n        uint256 threshold;\n    }\n\n    struct UserSupplyConfig {\n        address user;\n        address token;\n        uint8 mode;\n        uint256 expandPercent;\n        uint256 expandDuration;\n        uint256 baseWithdrawalLimit;\n    }\n\n    struct UserBorrowConfig {\n        address user;\n        address token;\n        uint8 mode;\n        uint256 expandPercent;\n        uint256 expandDuration;\n        uint256 baseDebtCeiling;\n        uint256 maxDebtCeiling;\n    }\n}\n\ninterface IFluidLiquidityAdmin {\n    /// @notice adds/removes auths. Auths generally could be contracts which can have restricted actions defined on contract.\n    ///         auths can be helpful in reducing governance overhead where it's not needed.\n    /// @param authsStatus_ array of structs setting allowed status for an address.\n    ///                     status true => add auth, false => remove auth\n    function updateAuths(\n        AdminModuleStructs.AddressBool[] calldata authsStatus_\n    ) external;\n\n    /// @notice adds/removes guardians. Only callable by Governance.\n    /// @param guardiansStatus_ array of structs setting allowed status for an address.\n    ///                         status true => add guardian, false => remove guardian\n    function updateGuardians(\n        AdminModuleStructs.AddressBool[] calldata guardiansStatus_\n    ) external;\n\n    /// @notice changes the revenue collector address (contract that is sent revenue). Only callable by Governance.\n    /// @param revenueCollector_  new revenue collector address\n    function updateRevenueCollector(address revenueCollector_) external;\n\n    /// @notice changes current status, e.g. for pausing or unpausing all user operations. Only callable by Auths.\n    /// @param newStatus_ new status\n    ///        status = 2 -> pause, status = 1 -> resume.\n    function changeStatus(uint256 newStatus_) external;\n\n    /// @notice                  update tokens rate data version 1. Only callable by Auths.\n    /// @param tokensRateData_   array of RateDataV1Params with rate data to set for each token\n    function updateRateDataV1s(\n        AdminModuleStructs.RateDataV1Params[] calldata tokensRateData_\n    ) external;\n\n    /// @notice                  update tokens rate data version 2. Only callable by Auths.\n    /// @param tokensRateData_   array of RateDataV2Params with rate data to set for each token\n    function updateRateDataV2s(\n        AdminModuleStructs.RateDataV2Params[] calldata tokensRateData_\n    ) external;\n\n    /// @notice updates token configs: fee charge on borrowers interest & storage update utilization threshold.\n    ///         Only callable by Auths.\n    /// @param tokenConfigs_ contains token address, fee & utilization threshold\n    function updateTokenConfigs(\n        AdminModuleStructs.TokenConfig[] calldata tokenConfigs_\n    ) external;\n\n    /// @notice updates user classes: 0 is for new protocols, 1 is for established protocols.\n    ///         Only callable by Auths.\n    /// @param userClasses_ struct array of uint256 value to assign for each user address\n    function updateUserClasses(\n        AdminModuleStructs.AddressUint256[] calldata userClasses_\n    ) external;\n\n    /// @notice sets user supply configs per token basis. Eg: with interest or interest-free and automated limits.\n    ///         Only callable by Auths.\n    /// @param userSupplyConfigs_ struct array containing user supply config, see `UserSupplyConfig` struct for more info\n    function updateUserSupplyConfigs(\n        AdminModuleStructs.UserSupplyConfig[] memory userSupplyConfigs_\n    ) external;\n\n    /// @notice setting user borrow configs per token basis. Eg: with interest or interest-free and automated limits.\n    ///         Only callable by Auths.\n    /// @param userBorrowConfigs_ struct array containing user borrow config, see `UserBorrowConfig` struct for more info\n    function updateUserBorrowConfigs(\n        AdminModuleStructs.UserBorrowConfig[] memory userBorrowConfigs_\n    ) external;\n\n    /// @notice pause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\n    /// Only callable by Guardians.\n    /// @param user_          address of user to pause operations for\n    /// @param supplyTokens_  token addresses to pause withdrawals for\n    /// @param borrowTokens_  token addresses to pause borrowings for\n    function pauseUser(\n        address user_,\n        address[] calldata supplyTokens_,\n        address[] calldata borrowTokens_\n    ) external;\n\n    /// @notice unpause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\n    /// Only callable by Guardians.\n    /// @param user_          address of user to unpause operations for\n    /// @param supplyTokens_  token addresses to unpause withdrawals for\n    /// @param borrowTokens_  token addresses to unpause borrowings for\n    function unpauseUser(\n        address user_,\n        address[] calldata supplyTokens_,\n        address[] calldata borrowTokens_\n    ) external;\n\n    /// @notice         collects revenue for tokens to configured revenueCollector address.\n    /// @param tokens_  array of tokens to collect revenue for\n    /// @dev            Note that this can revert if token balance is < revenueAmount (utilization > 100%)\n    function collectRevenue(address[] calldata tokens_) external;\n\n    /// @notice gets the current updated exchange prices for n tokens and updates all prices, rates related data in storage.\n    /// @param tokens_ tokens to update exchange prices for\n    /// @return supplyExchangePrices_ new supply rates of overall system for each token\n    /// @return borrowExchangePrices_ new borrow rates of overall system for each token\n    function updateExchangePrices(\n        address[] calldata tokens_\n    )\n        external\n        returns (\n            uint256[] memory supplyExchangePrices_,\n            uint256[] memory borrowExchangePrices_\n        );\n}\n\ninterface IFluidLendingFactory {\n    /// @notice creates token for `asset_` for a lending protocol with interest. Only callable by deployers.\n    /// @param  asset_              address of the asset\n    /// @param  fTokenType_         type of fToken:\n    /// - if it's the native token, it should use `NativeUnderlying`\n    /// - otherwise it should use `fToken`\n    /// - could be more types available, check `fTokenTypes()`\n    /// @param  isNativeUnderlying_ flag to signal fToken type that uses native underlying at Liquidity\n    /// @return token_              address of the created token\n    function createToken(\n        address asset_,\n        string calldata fTokenType_,\n        bool isNativeUnderlying_\n    ) external returns (address token_);\n}\n\ninterface IFluidVaultT1Factory {\n    function deployVault(\n        address vaultDeploymentLogic_,\n        bytes calldata vaultDeploymentData_\n    ) external returns (address vault_);\n\n    function setVaultAuth(\n        address vault_,\n        address vaultAuth_,\n        bool allowed_\n    ) external;\n}\n\ninterface IFluidVaultT1DeploymentLogic {\n    function vaultT1(address supplyToken_, address borrowToken_) external;\n}\n\ninterface IFluidVaultT1 {\n    /// @notice updates the Vault oracle to `newOracle_`. Must implement the FluidOracle interface.\n    function updateOracle(address newOracle_) external;\n\n    /// @notice updates the all Vault core settings according to input params.\n    /// All input values are expected in 1e2 (1% = 100, 100% = 10_000).\n    function updateCoreSettings(\n        uint256 supplyRateMagnifier_,\n        uint256 borrowRateMagnifier_,\n        uint256 collateralFactor_,\n        uint256 liquidationThreshold_,\n        uint256 liquidationMaxLimit_,\n        uint256 withdrawGap_,\n        uint256 liquidationPenalty_,\n        uint256 borrowFee_\n    ) external;\n\n    /// @notice updates the allowed rebalancer to `newRebalancer_`.\n    function updateRebalancer(address newRebalancer_) external;\n\n    /// @notice updates the supply rate magnifier to `supplyRateMagnifier_`. Input in 1e2 (1% = 100, 100% = 10_000).\n    function updateSupplyRateMagnifier(uint supplyRateMagnifier_) external;\n\n    /// @notice updates the collateral factor to `collateralFactor_`. Input in 1e2 (1% = 100, 100% = 10_000).\n    function updateCollateralFactor(uint collateralFactor_) external;\n}\n\ninterface IFluidLending {\n    /// @notice Updates the rebalancer address (ReserveContract). Only callable by LendingFactory auths.\n    function updateRebalancer(address rebalancer_) external;\n}\n\ninterface IFTokenAdmin {\n    /// @notice updates the rewards rate model contract.\n    ///         Only callable by LendingFactory auths.\n    /// @param rewardsRateModel_  the new rewards rate model contract address.\n    ///                           can be set to address(0) to set no rewards (to save gas)\n    function updateRewards(address rewardsRateModel_) external;\n\n    /// @notice Balances out the difference between fToken supply at Liquidity vs totalAssets().\n    ///         Deposits underlying from rebalancer address into Liquidity but doesn't mint any shares\n    ///         -> thus making deposit available as rewards.\n    ///         Only callable by rebalancer.\n    /// @return assets_ amount deposited to Liquidity\n    function rebalance() external payable returns (uint256 assets_);\n\n    /// @notice gets the liquidity exchange price of the underlying asset, calculates the updated exchange price (with reward rates)\n    ///         and writes those values to storage.\n    ///         Callable by anyone.\n    /// @return tokenExchangePrice_ exchange price of fToken share to underlying asset\n    /// @return liquidityExchangePrice_ exchange price at Liquidity for the underlying asset\n    function updateRates()\n        external\n        returns (uint256 tokenExchangePrice_, uint256 liquidityExchangePrice_);\n\n    /// @notice sends any potentially stuck funds to Liquidity contract. Only callable by LendingFactory auths.\n    function rescueFunds(address token_) external;\n\n    /// @notice Updates the rebalancer address (ReserveContract). Only callable by LendingFactory auths.\n    function updateRebalancer(address rebalancer_) external;\n}\n\ncontract PayloadIGP16 {\n    uint256 public constant PROPOSAL_ID = 16;\n\n    address public constant PROPOSER =\n        0xA45f7bD6A5Ff45D31aaCE6bCD3d426D9328cea01;\n\n    address public constant PROPOSER_AVO_MULTISIG =\n        0x059A94A72951c0ae1cc1CE3BF0dB52421bbE8210;\n\n    IGovernorBravo public constant GOVERNOR =\n        IGovernorBravo(0x0204Cd037B2ec03605CFdFe482D8e257C765fA1B);\n    ITimelock public immutable TIMELOCK =\n        ITimelock(0x2386DC45AdDed673317eF068992F19421B481F4c);\n\n    address public immutable ADDRESS_THIS;\n\n    address public constant TEAM_MULTISIG =\n        0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e;\n\n    IFluidLiquidityAdmin public constant LIQUIDITY =\n        IFluidLiquidityAdmin(0x52Aa899454998Be5b000Ad077a46Bbe360F4e497);\n    IFluidVaultT1Factory public constant VAULT_T1_FACTORY =\n        IFluidVaultT1Factory(0x324c5Dc1fC42c7a4D43d92df1eBA58a54d13Bf2d);\n     IFluidLendingFactory public constant LENDING_FACTORY =\n        IFluidLendingFactory(0x54B91A0D94cb471F37f949c60F7Fa7935b551D03);\n\n    address public constant USDC_ADDRESS =\n        0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n    address public constant USDT_ADDRESS =\n        0xdAC17F958D2ee523a2206206994597C13D831ec7;\n\n    address public constant ETH_ADDRESS =\n        0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n    address public constant weETH_ADDRESS =\n        0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee;\n    address public constant wstETH_ADDRESS =\n        0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0;\n\n    address public constant VAULT_ETH_USDC = address(0xeAbBfca72F8a8bf14C4ac59e69ECB2eB69F0811C);\n    address public constant VAULT_ETH_USDT = address(0xbEC491FeF7B4f666b270F9D5E5C3f443cBf20991);\n    address public constant VAULT_wstETH_USDC = address(0x51197586F6A9e2571868b6ffaef308f3bdfEd3aE);\n    address public constant VAULT_wstETH_USDT = address(0x1c2bB46f36561bc4F05A94BD50916496aa501078);\n    address public constant VAULT_weETH_wstETH = address(0x40D9b8417E6E1DcD358f04E3328bCEd061018A82);\n\n    \n\n    constructor() {\n        ADDRESS_THIS = address(this);\n    }\n\n    function propose(string memory description) external {\n        require(\n            msg.sender == PROPOSER ||\n                msg.sender == TEAM_MULTISIG ||\n                address(this) == PROPOSER_AVO_MULTISIG,\n            \"msg.sender-not-allowed\"\n        );\n\n        uint256 totalActions = 1;\n        address[] memory targets = new address[](totalActions);\n        uint256[] memory values = new uint256[](totalActions);\n        string[] memory signatures = new string[](totalActions);\n        bytes[] memory calldatas = new bytes[](totalActions);\n\n        // Action 1: call executePayload on timelock contract to execute payload related to Fluid\n        targets[0] = address(TIMELOCK);\n        values[0] = 0;\n        signatures[0] = \"executePayload(address,string,bytes)\";\n        calldatas[0] = abi.encode(ADDRESS_THIS, \"execute()\", abi.encode());\n\n        uint256 proposedId = GOVERNOR.propose(\n            targets,\n            values,\n            signatures,\n            calldatas,\n            description\n        );\n\n        require(proposedId == PROPOSAL_ID, \"PROPOSAL_IS_NOT_SAME\");\n    }\n\n    function execute() external {\n        require(address(this) == address(TIMELOCK), \"not-valid-caller\");\n\n        // Action 1: Update wstETH market rate curve and set fee as 10%\n        action1();\n\n        // Action 2: Update ETH market rate curve and set fee as 0%.\n        action2();\n\n        // Action 3: Add config handler on liquidity layer for weETH/wstETH vault to make borrow limit dynamic.\n        action3();\n\n        // Action 4: Update supply rate magnifier wstETH/USDC and wstETH/USDT vault.\n        action4();\n\n        // Action 5: Pauses ETH Rewards on ETH/USDC and ETH/USDT vaults.\n        action5();\n\n        // Action 6: Enabling wstETH token on lending protocol.\n        action6();\n    }\n\n    function verifyProposal() external view {}\n\n    /***********************************|\n    |     Proposal Payload Actions      |\n    |__________________________________*/\n\n    /// @notice Action 1: Update wstETH market rate curve and set fee as 10%\n    function action1() internal {\n        {\n            AdminModuleStructs.RateDataV2Params[]\n                memory params_ = new AdminModuleStructs.RateDataV2Params[](1);\n\n            params_[0] = AdminModuleStructs.RateDataV2Params({\n                token: wstETH_ADDRESS, // wstETH\n                kink1: 70 * 1e2, // 70%\n                kink2: 90 * 1e2, // 90%\n                rateAtUtilizationZero: 0, // 0%\n                rateAtUtilizationKink1: 20 * 1e2, // 20%\n                rateAtUtilizationKink2: 40 * 1e2, // 40%\n                rateAtUtilizationMax: 150 * 1e2 // 150%\n            });\n\n            LIQUIDITY.updateRateDataV2s(params_);\n        }\n\n        {\n            AdminModuleStructs.TokenConfig[]\n                memory params_ = new AdminModuleStructs.TokenConfig[](1);\n\n            params_[0] = AdminModuleStructs.TokenConfig({\n                token: wstETH_ADDRESS, // wstETH\n                threshold: 0.3 * 1e2, // 0.3\n                fee: 10 * 1e2 // 10%\n            });\n\n            LIQUIDITY.updateTokenConfigs(params_);\n        }\n    }\n\n    /// @notice Action 2: Update ETH market rate curve and set fee as 0%.\n    function action2() internal {\n        {\n            AdminModuleStructs.RateDataV2Params[]\n                memory params_ = new AdminModuleStructs.RateDataV2Params[](1);\n\n            params_[0] = AdminModuleStructs.RateDataV2Params({\n                token: ETH_ADDRESS, // ETH\n                kink1: 70 * 1e2, // 70%\n                kink2: 90 * 1e2, // 90%\n                rateAtUtilizationZero: 0, // 0%\n                rateAtUtilizationKink1: 15 * 1e2, // 15%\n                rateAtUtilizationKink2: 25 * 1e2, // 25%\n                rateAtUtilizationMax: 150 * 1e2 // 150%\n            });\n\n            LIQUIDITY.updateRateDataV2s(params_);\n        }\n\n\n         {\n            AdminModuleStructs.TokenConfig[]\n                memory params_ = new AdminModuleStructs.TokenConfig[](1);\n\n            params_[0] = AdminModuleStructs.TokenConfig({\n                token: ETH_ADDRESS, // wstETH\n                threshold: 0.3 * 1e2, // 0.3\n                fee: 0 * 1e2 // 0%\n            });\n\n            LIQUIDITY.updateTokenConfigs(params_);\n        }\n    }\n\n    /// @notice Action 3: Add config handler on liquidity layer for weETH/wstETH vault to make borrow limit dynamic\n    function action3() internal {\n        address VAULT_weETH_wstETH_CONFIG_HANDLER = address(0x133098588cdF2e35B9478a1f4979C4f7Ccee3a06);\n\n        AdminModuleStructs.AddressBool[]\n            memory configs_ = new AdminModuleStructs.AddressBool[](1);\n\n        configs_[0] = AdminModuleStructs.AddressBool({\n            addr: address(VAULT_weETH_wstETH_CONFIG_HANDLER),\n            value: true\n        });\n\n        LIQUIDITY.updateAuths(configs_);\n    }\n\n    /// @notice Action 4: Update supply rate magnifier wstETH/USDC and wstETH/USDT vault.\n    function action4() internal {\n        IFluidVaultT1(VAULT_wstETH_USDC).updateSupplyRateMagnifier(80 * 1e2); // 0.8x supplyRateMagnifier\n        IFluidVaultT1(VAULT_wstETH_USDT).updateSupplyRateMagnifier(80 * 1e2); // 0.8x supplyRateMagnifier\n    }\n\n\n    /// @notice Action 5: Pauses ETH Rewards on ETH/USDC and ETH/USDT vaults.\n    function action5() internal {\n        IFluidVaultT1(VAULT_ETH_USDC).updateSupplyRateMagnifier(100 * 1e2); // 1x supplyRateMagnifier\n        VAULT_T1_FACTORY.setVaultAuth(VAULT_ETH_USDC, 0x58Dc7894a7B1B9D065CE2e94a73f62686B439A2A, false); // Removing Rewards contracts as auth\n\n        IFluidVaultT1(VAULT_ETH_USDT).updateSupplyRateMagnifier(100 * 1e2); // 1x supplyRateMagnifier\n        VAULT_T1_FACTORY.setVaultAuth(VAULT_ETH_USDT, 0xB36Db4dfF978D2d552a5149E2fd0FBefA2a32809, false); // Removing Rewards contracts as auth\n\n    }\n\n    /// @notice Action 6: Deploy and enable wstETH token on lending protocol.\n    function action6() internal {\n        // deploy fToken for wstETH\n        address F_WSTETH = LENDING_FACTORY.createToken(wstETH_ADDRESS, \"fToken\", false);\n\n        // Set user supply config for the vault on Liquidity Layer.\n        {\n            AdminModuleStructs.UserSupplyConfig[]\n                memory configs_ = new AdminModuleStructs.UserSupplyConfig[](1);\n\n            configs_[0] = AdminModuleStructs.UserSupplyConfig({\n                user: address(F_WSTETH),\n                token: wstETH_ADDRESS,\n                mode: 1,\n                expandPercent: 25 * 1e2, // 25%\n                expandDuration: 12 hours,\n                baseWithdrawalLimit: 4000 * 1e18 // 4000 wstETH\n            });\n\n            LIQUIDITY.updateUserSupplyConfigs(configs_);\n        }\n\n        // set rebalancer at fToken to reserve contract proxy\n        IFluidLending(F_WSTETH).updateRebalancer(0x264786EF916af64a1DB19F513F24a3681734ce92);\n    }\n}"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}