From afee515d0429f55da141a78e853b60a05e1f2706 Mon Sep 17 00:00:00 2001 From: miguelmtz <36620902+miguelmtzinf@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:24:44 +0100 Subject: [PATCH] feat: Add GSM deployment script (#378) * feat: Add GSM deployment script * fix: Fix hardhat remappings * fix: Add clean ups --- .gitignore | 2 + .gitmodules | 6 ++ foundry.toml | 1 + hardhat-remappings.txt | 5 +- lib/aave-address-book | 1 + lib/solidity-utils | 1 + remappings.txt | 17 ++++ src/script/DeployGsmLaunch.s.sol | 167 +++++++++++++++++++++++++++++++ 8 files changed, 199 insertions(+), 1 deletion(-) create mode 160000 lib/aave-address-book create mode 160000 lib/solidity-utils create mode 100644 remappings.txt create mode 100644 src/script/DeployGsmLaunch.s.sol diff --git a/.gitignore b/.gitignore index 5d837c4b..8b986898 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ forge-cache /report lcov.info combined-lcov.info + +broadcast/ diff --git a/.gitmodules b/.gitmodules index 02e9abc7..5d6f8936 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,9 @@ [submodule "lib/aave-stk-v1-5"] path = lib/aave-stk-v1-5 url = https://github.com/bgd-labs/aave-stk-v1-5 +[submodule "lib/aave-address-book"] + path = lib/aave-address-book + url = https://github.com/bgd-labs/aave-address-book +[submodule "lib/solidity-utils"] + path = lib/solidity-utils + url = https://github.com/bgd-labs/solidity-utils diff --git a/foundry.toml b/foundry.toml index a648c138..34476dd8 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,5 +1,6 @@ [profile.default] src = 'src/contracts' +script = 'src/script' out = 'out' test = 'src/test' cache_path = 'forge-cache' diff --git a/hardhat-remappings.txt b/hardhat-remappings.txt index 8e03c6d5..9bf754d1 100644 --- a/hardhat-remappings.txt +++ b/hardhat-remappings.txt @@ -1,3 +1,6 @@ ds-test/=lib/forge-std/lib/ds-test/src/ forge-std/=lib/forge-std/src/ -aave-stk-v1-5/=lib/aave-stk-v1-5/ \ No newline at end of file +aave-stk-v1-5/=lib/aave-stk-v1-5/ +aave-address-book/=lib/aave-address-book/src/ +aave-v3-core/=lib/aave-address-book/lib/aave-v3-core/ +solidity-utils/=lib/solidity-utils/src/ \ No newline at end of file diff --git a/lib/aave-address-book b/lib/aave-address-book new file mode 160000 index 00000000..e65e63ce --- /dev/null +++ b/lib/aave-address-book @@ -0,0 +1 @@ +Subproject commit e65e63cec1dd61e7a21ed0db34795a708577a503 diff --git a/lib/solidity-utils b/lib/solidity-utils new file mode 160000 index 00000000..9d4d0415 --- /dev/null +++ b/lib/solidity-utils @@ -0,0 +1 @@ +Subproject commit 9d4d041562f7ac2918e216e2e7c74172afe3d2af diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 00000000..f22aa24d --- /dev/null +++ b/remappings.txt @@ -0,0 +1,17 @@ +@aave/=node_modules/@aave/ +@aave/core-v3/=node_modules/@aave/core-v3/ +@aave/periphery-v3/=node_modules/@aave/periphery-v3/ +@openzeppelin/=node_modules/@openzeppelin/ +aave-stk-v1-5/=lib/aave-stk-v1-5/ +ds-test/=lib/forge-std/lib/ds-test/src/ +eth-gas-reporter/=node_modules/eth-gas-reporter/ +forge-std/=lib/forge-std/src/ +hardhat-deploy/=node_modules/hardhat-deploy/ +hardhat/=node_modules/hardhat/ +aave-address-book/=lib/aave-address-book/src/ +aave-helpers/=lib/aave-stk-v1-5/lib/aave-helpers/ +aave-v3-core/=lib/aave-address-book/lib/aave-v3-core/ +aave-v3-periphery/=lib/aave-address-book/lib/aave-v3-periphery/ +erc4626-tests/=lib/aave-stk-v1-5/lib/openzeppelin-contracts/lib/erc4626-tests/ +openzeppelin-contracts/=lib/aave-stk-v1-5/lib/openzeppelin-contracts/ +solidity-utils/=lib/solidity-utils/src/ diff --git a/src/script/DeployGsmLaunch.s.sol b/src/script/DeployGsmLaunch.s.sol new file mode 100644 index 00000000..9983c5b1 --- /dev/null +++ b/src/script/DeployGsmLaunch.s.sol @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Script, console2} from 'forge-std/Script.sol'; +import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; +import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {IPoolAddressesProvider} from '@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol'; +import {Gsm} from '../contracts/facilitators/gsm/Gsm.sol'; +import {IGsm} from '../contracts/facilitators/gsm/interfaces/IGsm.sol'; +import {FixedPriceStrategy} from '../contracts/facilitators/gsm/priceStrategy/FixedPriceStrategy.sol'; +import {FixedFeeStrategy} from '../contracts/facilitators/gsm/feeStrategy/FixedFeeStrategy.sol'; +import {GsmRegistry} from '../contracts/facilitators/gsm/misc/GsmRegistry.sol'; +import {OracleSwapFreezer} from '../contracts/facilitators/gsm/swapFreezer/OracleSwapFreezer.sol'; + +// GSM USDC +uint8 constant USDC_DECIMALS = 6; +uint128 constant USDC_EXPOSURE_CAP = 500_000e6; +string constant GSM_USDC_FACILITATOR_LABEL = 'GSM USDC'; +uint128 constant GSM_USDC_BUCKET_CAPACITY = 500_000e18; + +// GSM USDT +uint8 constant USDT_DECIMALS = 6; +uint128 constant USDT_EXPOSURE_CAP = 500_000e6; +string constant GSM_USDT_FACILITATOR_LABEL = 'GSM USDT'; +uint128 constant GSM_USDT_BUCKET_CAPACITY = 500_000e18; + +uint256 constant GSM_PRICE_RATIO = 1e18; +uint256 constant GSM_BUY_FEE_BPS = 0.002e4; // 0.2%, 0.5e4 is 50% +uint256 constant GSM_SELL_FEE_BPS = 0.002e4; // 0.2% + +uint128 constant SWAP_FREEZE_LOWER_BOUND = 0.99e8; +uint128 constant SWAP_FREEZE_UPPER_BOUND = 1.01e8; +uint128 constant SWAP_UNFREEZE_LOWER_BOUND = 0.995e8; +uint128 constant SWAP_UNFREEZE_UPPER_BOUND = 1.005e8; +bool constant SWAP_UNFREEZE_ALLOWED = true; + +contract DeployGsmLaunch is Script { + function run() external { + uint256 deployerPrivateKey = vm.envUint('PRIVATE_KEY'); + address deployerAddress = vm.addr(deployerPrivateKey); + console2.log('Deployer Address: ', deployerAddress); + console2.log('Deployer Balance: ', address(deployerAddress).balance); + console2.log('Block Number: ', block.number); + vm.startBroadcast(deployerPrivateKey); + _deploy(); + vm.stopBroadcast(); + } + + function _deploy() internal { + // ------------------------------------------------ + // 1. FixedPriceStrategy + // ------------------------------------------------ + FixedPriceStrategy gsmUsdcPriceStrategy = new FixedPriceStrategy( + GSM_PRICE_RATIO, + AaveV3EthereumAssets.USDC_UNDERLYING, + USDC_DECIMALS + ); + console2.log('GSM USDC FixedPriceStrategy: ', address(gsmUsdcPriceStrategy)); + + FixedPriceStrategy gsmUsdtPriceStrategy = new FixedPriceStrategy( + GSM_PRICE_RATIO, + AaveV3EthereumAssets.USDT_UNDERLYING, + USDT_DECIMALS + ); + console2.log('GSM USDT FixedPriceStrategy: ', address(gsmUsdtPriceStrategy)); + + // ------------------------------------------------ + // 2. GSM implementations + // ------------------------------------------------ + Gsm gsmUsdcImpl = new Gsm( + AaveV3EthereumAssets.GHO_UNDERLYING, + AaveV3EthereumAssets.USDC_UNDERLYING, + address(gsmUsdcPriceStrategy) + ); + console2.log('GSM USDC Implementation: ', address(gsmUsdcImpl)); + + Gsm gsmUsdtImpl = new Gsm( + AaveV3EthereumAssets.GHO_UNDERLYING, + AaveV3EthereumAssets.USDT_UNDERLYING, + address(gsmUsdtPriceStrategy) + ); + console2.log('GSM USDT Implementation: ', address(gsmUsdtImpl)); + + gsmUsdcImpl.initialize( + GovernanceV3Ethereum.EXECUTOR_LVL_1, + address(AaveV3Ethereum.COLLECTOR), + USDC_EXPOSURE_CAP + ); + gsmUsdtImpl.initialize( + GovernanceV3Ethereum.EXECUTOR_LVL_1, + address(AaveV3Ethereum.COLLECTOR), + USDT_EXPOSURE_CAP + ); + + // ------------------------------------------------ + // 3. GSM proxy deployment and initialization + // ------------------------------------------------ + bytes memory gsmUsdcInitParams = abi.encodeWithSignature( + 'initialize(address,address,uint128)', + GovernanceV3Ethereum.EXECUTOR_LVL_1, + address(AaveV3Ethereum.COLLECTOR), + USDC_EXPOSURE_CAP + ); + TransparentUpgradeableProxy gsmUsdcProxy = new TransparentUpgradeableProxy( + address(gsmUsdcImpl), + MiscEthereum.PROXY_ADMIN, + gsmUsdcInitParams + ); + Gsm gsmUsdc = Gsm(address(gsmUsdcProxy)); + console2.log('GSM USDC Proxy: ', address(gsmUsdcProxy)); + + bytes memory gsmUsdtInitParams = abi.encodeWithSignature( + 'initialize(address,address,uint128)', + GovernanceV3Ethereum.EXECUTOR_LVL_1, + address(AaveV3Ethereum.COLLECTOR), + USDT_EXPOSURE_CAP + ); + TransparentUpgradeableProxy gsmUsdtProxy = new TransparentUpgradeableProxy( + address(gsmUsdtImpl), + MiscEthereum.PROXY_ADMIN, + gsmUsdtInitParams + ); + Gsm gsmUsdt = Gsm(address(gsmUsdtProxy)); + console2.log('GSM USDT Proxy: ', address(gsmUsdtProxy)); + + // ------------------------------------------------ + // 4. FixedFeeStrategy + // ------------------------------------------------ + FixedFeeStrategy fixedFeeStrategy = new FixedFeeStrategy(GSM_BUY_FEE_BPS, GSM_SELL_FEE_BPS); + console2.log('GSM FixedFeeStrategy: ', address(fixedFeeStrategy)); + + // ------------------------------------------------ + // 5. OracleSwapFreezers + // ------------------------------------------------ + OracleSwapFreezer gsmUsdcOracleSwapFreezer = new OracleSwapFreezer( + IGsm(address(gsmUsdc)), + AaveV3EthereumAssets.USDC_UNDERLYING, + IPoolAddressesProvider(address(AaveV3Ethereum.POOL_ADDRESSES_PROVIDER)), + SWAP_FREEZE_LOWER_BOUND, + SWAP_FREEZE_UPPER_BOUND, + SWAP_UNFREEZE_LOWER_BOUND, + SWAP_UNFREEZE_UPPER_BOUND, + SWAP_UNFREEZE_ALLOWED + ); + console2.log('GSM USDC OracleSwapFreezer: ', address(gsmUsdcOracleSwapFreezer)); + + OracleSwapFreezer gsmUsdtOracleSwapFreezer = new OracleSwapFreezer( + IGsm(address(gsmUsdt)), + AaveV3EthereumAssets.USDT_UNDERLYING, + IPoolAddressesProvider(address(AaveV3Ethereum.POOL_ADDRESSES_PROVIDER)), + SWAP_FREEZE_LOWER_BOUND, + SWAP_FREEZE_UPPER_BOUND, + SWAP_UNFREEZE_LOWER_BOUND, + SWAP_UNFREEZE_UPPER_BOUND, + SWAP_UNFREEZE_ALLOWED + ); + console2.log('GSM USDT OracleSwapFreezer: ', address(gsmUsdtOracleSwapFreezer)); + + // ------------------------------------------------ + // 6. Deploy GsmRegistry + // ------------------------------------------------ + GsmRegistry gsmRegistry = new GsmRegistry(GovernanceV3Ethereum.EXECUTOR_LVL_1); + console2.log('GsmRegistry: ', address(gsmRegistry)); + } +}