From 4802adffcd6e4a38021003419311c0f244883b1e Mon Sep 17 00:00:00 2001 From: Dominic Romanowski Date: Thu, 13 Jun 2024 15:09:04 +1000 Subject: [PATCH] update scripts --- scripts/config-mainnet.sol | 9 ++ scripts/deploy-lrt-market.s.sol | 144 ++++++++++++++++++++++++++++++++ scripts/utils.sol | 9 +- 3 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 scripts/deploy-lrt-market.s.sol diff --git a/scripts/config-mainnet.sol b/scripts/config-mainnet.sol index 99b1243a..a8fb6626 100644 --- a/scripts/config-mainnet.sol +++ b/scripts/config-mainnet.sol @@ -199,6 +199,11 @@ library Config { mmPerpReq: 0.1e18, imPerpReq: 0.2e18 }); + } else if (keccak256(abi.encodePacked(market)) == keccak256(abi.encodePacked("rswETH"))) { + baseMarginParams = IStandardManager.BaseMarginParams({ + marginFactor: 0.7e18, + IMScale: 0.9e18 + }); } else { revert("market not supported"); } @@ -237,6 +242,10 @@ library Config { perpCap = 10_000_000e18; optionCap = 0; baseCap = 0; + } else if (keccak256(abi.encodePacked(market)) == keccak256(abi.encodePacked("rswETH"))) { + perpCap = 0; + optionCap = 0; + baseCap = 10_000_000e18; } else { revert("market not supported"); } diff --git a/scripts/deploy-lrt-market.s.sol b/scripts/deploy-lrt-market.s.sol new file mode 100644 index 00000000..ae4cef00 --- /dev/null +++ b/scripts/deploy-lrt-market.s.sol @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import "openzeppelin/token/ERC20/extensions/IERC20Metadata.sol"; +import {OptionAsset} from "../src/assets/OptionAsset.sol"; +import {PerpAsset} from "../src/assets/PerpAsset.sol"; +import {WLWrappedERC20Asset} from "../src/assets/WLWrappedERC20Asset.sol"; +import {LyraSpotFeed} from "../src/feeds/LyraSpotFeed.sol"; +import {LyraSpotDiffFeed} from "../src/feeds/LyraSpotDiffFeed.sol"; +import {LyraVolFeed} from "../src/feeds/LyraVolFeed.sol"; +import {LyraRateFeedStatic} from "../src/feeds/LyraRateFeedStatic.sol"; +import {LyraForwardFeed} from "../src/feeds/LyraForwardFeed.sol"; +import {PMRM} from "../src/risk-managers/PMRM.sol"; +import {PMRMLib} from "../src/risk-managers/PMRMLib.sol"; +import {BasePortfolioViewer} from "../src/risk-managers/BasePortfolioViewer.sol"; +import {IPMRM} from "../src/interfaces/IPMRM.sol"; +import {IManager} from "../src/interfaces/IManager.sol"; +import {IStandardManager} from "../src/interfaces/IStandardManager.sol"; +import {IForwardFeed} from "../src/interfaces/IForwardFeed.sol"; +import {IVolFeed} from "../src/interfaces/IVolFeed.sol"; + +import {MockSpotDiffFeed} from "../test/shared/mocks/MockSpotDiffFeed.sol"; + +import "forge-std/console2.sol"; +import {Deployment, ConfigJson, Market} from "./types.sol"; +import {Utils} from "./utils.sol"; + +// get all default params +import "./config-mainnet.sol"; +import "../src/feeds/SFPSpotFeed.sol"; + +/** + * MARKET_NAME=usdt forge script scripts/deploy-base-only-market.s.sol --private-key {} --rpc {} --broadcast + **/ +contract DeployMarket is Utils { + + /// @dev main function + function run() external { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + + // revert if not found + string memory marketName = vm.envString("MARKET_NAME"); + + console2.log("Start deploying new market: ", marketName); + address deployer = vm.addr(deployerPrivateKey); + console2.log("Deployer: ", deployer); + + // load configs + ConfigJson memory config = _loadConfig(); + + // load deployed core contracts + Deployment memory deployment = _loadDeployment(); + + // deploy core contracts + Market memory market = _deployMarketContracts(marketName, config, deployment); + + _setPermissionAndCaps(deployment, marketName, market); + _registerMarketToSRM(marketName, deployment, market); + _writeToMarketJson(marketName, market); + + PMRM(_getContract("ETH", "pmrm")).setWhitelistedCallee(address(market.spotFeed), true); + PMRM(_getContract("BTC", "pmrm")).setWhitelistedCallee(address(market.spotFeed), true); + + vm.stopBroadcast(); + } + + /// @dev deploy all contract needed for a single market + function _deployMarketContracts(string memory marketName, ConfigJson memory config, Deployment memory deployment) internal returns (Market memory market) { + // get the market ERC20 from config (it should be added to the config) + address marketERC20; + if ((keccak256(abi.encodePacked(marketName)) == keccak256(abi.encodePacked("SFP")))) { + marketERC20 = vm.parseJsonAddress(_readDeploymentFile("strands"), ".sfp"); + // cast as LyraSpotFeed for simplicity + market.spotFeed = LyraSpotFeed(address(new SFPSpotFeed(IStrandsSFP(marketERC20)))); + } else { + marketERC20 = _getMarketERC20(marketName); + + console2.log("target erc20:", marketERC20); + + market.spotFeed = new LyraSpotFeed(); + + // init feeds + market.spotFeed.setHeartbeat(Config.SPOT_HEARTBEAT); + + for (uint i = 0; i < config.feedSigners.length; ++i) { + market.spotFeed.addSigner(config.feedSigners[i], true); + } + } + + market.base = new WLWrappedERC20Asset(deployment.subAccounts, IERC20Metadata(marketERC20)); + } + + function _setPermissionAndCaps(Deployment memory deployment, string memory marketName, Market memory market) internal { + // each asset whitelist the standard manager + _whitelistAndSetCapForManager(address(deployment.srm), marketName, market); + console2.log("All asset whitelist both managers!"); + } + + function _registerMarketToSRM(string memory marketName, Deployment memory deployment, Market memory market) internal { + // find market ID + uint marketId = deployment.srm.createMarket(marketName); + + console2.log("market ID for newly created market:", marketId); + + (,,IStandardManager.OracleContingencyParams memory oracleContingencyParams, + IStandardManager.BaseMarginParams memory baseMarginParams) = Config.getSRMParams(marketName); + + // set assets per market + deployment.srm.whitelistAsset(market.base, marketId, IStandardManager.AssetType.Base); + + deployment.srm.setOraclesForMarket(marketId, market.spotFeed, IForwardFeed(address(0)), IVolFeed(address(0))); + deployment.srm.setOracleContingencyParams(marketId, oracleContingencyParams); + deployment.srm.setBaseAssetMarginFactor(marketId, baseMarginParams.marginFactor, baseMarginParams.IMScale); + + deployment.srmViewer.setOIFeeRateBPS(address(market.base), Config.OI_FEE_BPS); + deployment.srm.setMinOIFee(Config.MIN_OI_FEE); + + deployment.srm.setWhitelistedCallee(address(market.spotFeed), true); + } + + function _whitelistAndSetCapForManager(address manager, string memory marketName, Market memory market) internal { + market.base.setWhitelistManager(manager, true); + + (, , uint baseCap) = Config.getSRMCaps(marketName); + + market.base.setTotalPositionCap(IManager(manager), baseCap); + } + + /** + * @dev write to deployments/{network}/{marketName}.json + */ + function _writeToMarketJson(string memory name, Market memory market) internal { + + string memory objKey = "market-deployments"; + + vm.serializeAddress(objKey, "base", address(market.base)); + string memory finalObj = vm.serializeAddress(objKey, "spotFeed", address(market.spotFeed)); + + // build path + _writeToDeployments(name, finalObj); + } + +} \ No newline at end of file diff --git a/scripts/utils.sol b/scripts/utils.sol index 951c9735..659d6600 100644 --- a/scripts/utils.sol +++ b/scripts/utils.sol @@ -23,7 +23,7 @@ contract Utils is Script { /// @dev get config from current chainId function _loadConfig() internal view returns (ConfigJson memory config) { - string memory file = _readInput("config"); + string memory file = _readDeploymentFile("shared"); config.usdc = abi.decode(vm.parseJson(file, ".usdc"), (address)); config.feedSigners = abi.decode(vm.parseJson(file, ".feedSigners"), (address[])); @@ -44,6 +44,11 @@ contract Utils is Script { deployment.stableFeed = ISpotFeed(abi.decode(vm.parseJson(content, ".stableFeed"), (address))); } + function _getContract(string memory filename, string memory key) internal view returns (address) { + string memory content = _readDeploymentFile(filename); + return abi.decode(vm.parseJson(content, string.concat(".", key)), (address)); + } + ///@dev read input from json ///@dev standard path: scripts/input/{chainId}/{input}.json, as defined in //// https://book.getfoundry.sh/tutorials/best-practices?highlight=script#scripts @@ -83,7 +88,7 @@ contract Utils is Script { } function _getMarketERC20(string memory name) internal view returns (address) { - string memory file = _readInput("config"); + string memory file = _readDeploymentFile("shared"); return abi.decode(vm.parseJson(file, string.concat(".", _toLower(name))), (address)); } } \ No newline at end of file