diff --git a/broadcast/hyper-mainnet.impl.json b/broadcast/hyper-mainnet.impl.json new file mode 100644 index 00000000..01036c09 --- /dev/null +++ b/broadcast/hyper-mainnet.impl.json @@ -0,0 +1,8 @@ +{ + "Factory": "0xBaf6cEa5994c8D5840cdBcBDD17E973bc18AFced", + "Keeper": "0x7647ed486D5CaAdb43BBd4BEc61ef4D5A54879bA", + "SelfPeggingAsset": "0xF8A9ec45037B1Ad7636fD804DB7fa8dF19DAeD9f", + "SPAToken": "0xA13a352bbD90C65a07bA1a03a28Dd3957a81dD16", + "WSPAToken": "0x77dF165Efc8115c89E851c7FBc44D50f5A878005", + "rampAController": "0x57C5Ce7a3617eae4963CBCF036322ebd656E5017" +} \ No newline at end of file diff --git a/broadcast/hyper-mainnet.json b/broadcast/hyper-mainnet.json new file mode 100644 index 00000000..d1d51573 --- /dev/null +++ b/broadcast/hyper-mainnet.json @@ -0,0 +1,16 @@ +{ + "Factory": "0x4AE79551a9A203288481C2ae78B3da67E4E34b3D", + "RampAControllerBeacon": "0x34B681ed1643D3911199247D4b102965FaD6ff92", + "SPATokenBeacon": "0xcD6dE584aBd8dBCDc3Add1647DC9B83c823f2578", + "WSPATokenBeacon": "0x09fA3335C22278A0ae99A8514D6f8163C62E7Fac", + "SelfPeggingAssetBeacon": "0xe306253438ac6f787e4924aCfDc481CC7096B8a6", + "Zap": "0x2eA3D2Da5eEEb5AD9caC3821C6A5C0E7d8FA7412", + "WHype": "0x5555555555555555555555555555555555555555", + "BeHype": "0xd8FC8F0b03eBA61F64D08B0bef69d80916E5DdA9", + "WhypeBehypeKeeper": "0x975b6E7ed8134fFA37D3caaeCc4A682B2dB23b3a", + "WhypeBehypeParameterRegistry": "0xc37F49Da675F89258E64accF473BfF3dB65e145e", + "WhypeBehypePool": "0x3dCa4a74B814e4C6e1e516dDd8eC1Ef6052FEB70", + "WhypeBehypeRampAController": "0xBDcE8aEf402c442fe11A55Ad93Aeb98aF6B5CE2a", + "WhypeBehypeSPAToken": "0x00372D1B7701d387572b304295d0Bd805166B610", + "WhypeBehypeWSPAToken": "0x4f2431e8d3f2DfA56bd699C85866Ee444278BFA9" +} \ No newline at end of file diff --git a/script/AddPool.sol b/script/AddPool.sol new file mode 100644 index 00000000..14ec9c2f --- /dev/null +++ b/script/AddPool.sol @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +import { stdJson } from "forge-std/StdJson.sol"; +import { console2 } from "forge-std/console2.sol"; + +import { Deploy } from "script/Deploy.sol"; +import { Pool } from "script/Pool.sol"; +import { MockToken } from "../src/mock/MockToken.sol"; +import { SelfPeggingAsset } from "../src/SelfPeggingAsset.sol"; +import { ChainlinkOracleProvider } from "../src/misc/ChainlinkOracleProvider.sol"; +import "@chainlink/contracts/shared/interfaces/AggregatorV3Interface.sol"; +import { SelfPeggingAssetFactory } from "../src/SelfPeggingAssetFactory.sol"; +import { ChainlinkCompositeOracleProvider } from "../src/misc/ChainlinkCompositeOracleProvider.sol"; +import { MockExchangeRateProvider } from "../src/mock/MockExchangeRateProvider.sol"; + +contract AddPool is Deploy, Pool { + struct JSONData { + address Factory; + address LPTokenBeacon; + address SelfPeggingAssetBeacon; + address WETHwstETHPool; + address WETHwstETHPoolLPToken; + address WETHwstETHPoolWLPToken; + address WLPTokenBeacon; + address Zap; + address wstETHweETHPool; + address wstETHweETHPoolLPToken; + address wstETHweETHPoolWLPToken; + } + + struct JSONDataTestnet { + address Factory; + address LPTokenBeacon; + address SelfPeggingAssetBeacon; + address USDC; + address USDT; + address WLPTokenBeacon; + address Zap; + } + + function init() internal { + if (vm.envUint("HEX_PRIV_KEY") == 0) revert("No private key found"); + deployerPrivateKey = vm.envUint("HEX_PRIV_KEY"); + DEPLOYER = vm.addr(deployerPrivateKey); + } + + function run() public payable { + init(); + loadConfig(); + + vm.startBroadcast(deployerPrivateKey); + + uint256 chainId = getChainId(); + string memory networkName = getNetworkName(chainId); + string memory path = string.concat("./broadcast/", networkName, ".json"); + + string memory json = vm.readFile(path); + bytes memory data = vm.parseJson(json); + + if (chainId == 8453) { + JSONData memory jsonData = abi.decode(data, (JSONData)); + + factory = SelfPeggingAssetFactory(jsonData.Factory); + selfPeggingAssetBeacon = jsonData.SelfPeggingAssetBeacon; + lpTokenBeacon = jsonData.LPTokenBeacon; + wlpTokenBeacon = jsonData.WLPTokenBeacon; + zap = jsonData.Zap; + + address wstETHTostETHFeed = 0xB88BAc61a4Ca37C43a3725912B1f472c9A5bc061; + address weETHToETHFeed = 0xFC1415403EbB0c693f9a7844b92aD2Ff24775C65; + address stETHToETHFeed = 0xf586d0728a47229e747d824a939000Cf21dEF5A0; + + address wstETH = 0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452; + address weETH = 0x04C0599Ae5A44757c0af6F9eC3b93da8976c150A; + address weth = 0x4200000000000000000000000000000000000006; + + uint256 ethAmount = 0.0025e18; + + address sequencer = 0xBCF85224fc0756B9Fa45aA7892530B47e10b6433; + + // create chainlink oracle + address wstETHTostETHOracle = address( + new ChainlinkOracleProvider( + AggregatorV3Interface(sequencer), AggregatorV3Interface(wstETHTostETHFeed), 24 hours + ) + ); + + ChainlinkCompositeOracleProvider.Config[] memory configs = new ChainlinkCompositeOracleProvider.Config[](2); + configs[0] = ChainlinkCompositeOracleProvider.Config({ + feed: AggregatorV3Interface(weETHToETHFeed), + maxStalePeriod: 24 hours, + assetDecimals: 18, + isInverted: false + }); + configs[1] = ChainlinkCompositeOracleProvider.Config({ + feed: AggregatorV3Interface(stETHToETHFeed), + maxStalePeriod: 24 hours, + assetDecimals: 18, + isInverted: true + }); + + ChainlinkCompositeOracleProvider weETHTostETHOracle = + new ChainlinkCompositeOracleProvider(AggregatorV3Interface(sequencer), configs); + + (address lpToken, address pool, address wlpToken,,,) = + createChainlinkPool(wstETH, weETH, address(wstETHTostETHOracle), address(weETHTostETHOracle)); + + initialMint(wstETH, weETH, ethAmount, ethAmount, SelfPeggingAsset(pool)); + + ChainlinkCompositeOracleProvider.Config[] memory configs2 = new ChainlinkCompositeOracleProvider.Config[](1); + configs2[0] = ChainlinkCompositeOracleProvider.Config({ + feed: AggregatorV3Interface(stETHToETHFeed), + maxStalePeriod: 24 hours, + assetDecimals: 18, + isInverted: true + }); + + ChainlinkCompositeOracleProvider ETHTostETHOracle = + new ChainlinkCompositeOracleProvider(AggregatorV3Interface(sequencer), configs2); + + (address lpToken2, address pool2, address wlpToken2,,,) = + createChainlinkPool(weth, wstETH, address(ETHTostETHOracle), address(wstETHTostETHOracle)); + + initialMint(weth, wstETH, ethAmount, ethAmount, SelfPeggingAsset(pool2)); + + vm.writeJson(vm.serializeAddress("contracts", "Factory", address(factory)), path); + vm.writeJson(vm.serializeAddress("contracts", "LPTokenBeacon", lpTokenBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "SelfPeggingAssetBeacon", selfPeggingAssetBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "WETHwstETHPool", pool2), path); + vm.writeJson(vm.serializeAddress("contracts", "WETHwstETHPoolLPToken", lpToken2), path); + vm.writeJson(vm.serializeAddress("contracts", "WETHwstETHPoolWLPToken", wlpToken2), path); + vm.writeJson(vm.serializeAddress("contracts", "WLPTokenBeacon", wlpTokenBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "Zap", zap), path); + vm.writeJson(vm.serializeAddress("contracts", "wstETHweETHPool", pool), path); + vm.writeJson(vm.serializeAddress("contracts", "wstETHweETHPoolLPToken", lpToken), path); + vm.writeJson(vm.serializeAddress("contracts", "wstETHweETHPoolWLPToken", wlpToken), path); + } else if (chainId == 84_532) { + JSONDataTestnet memory jsonData = abi.decode(data, (JSONDataTestnet)); + + factory = SelfPeggingAssetFactory(jsonData.Factory); + selfPeggingAssetBeacon = jsonData.SelfPeggingAssetBeacon; + lpTokenBeacon = jsonData.LPTokenBeacon; + wlpTokenBeacon = jsonData.WLPTokenBeacon; + zap = jsonData.Zap; + + vm.writeJson(vm.serializeAddress("contracts", "Zap", zap), path); + vm.writeJson(vm.serializeAddress("contracts", "Factory", address(factory)), path); + vm.writeJson(vm.serializeAddress("contracts", "SelfPeggingAssetBeacon", selfPeggingAssetBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "LPTokenBeacon", lpTokenBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "WLPTokenBeacon", wlpTokenBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "USDC", jsonData.USDC), path); + vm.writeJson(vm.serializeAddress("contracts", "USDT", jsonData.USDT), path); + + uint256 amount = 0.0026e18; + + MockToken weth = new MockToken("WETH", "WETH", 18); + MockToken wstETH = new MockToken("wstETH", "wstETH", 18); + MockToken weETH = new MockToken("weETH", "weETH", 18); + + MockToken(weth).mint(DEPLOYER, amount); + MockToken(wstETH).mint(DEPLOYER, amount * 2); + MockToken(weETH).mint(DEPLOYER, amount); + + MockExchangeRateProvider WETHTostETHOracle = new MockExchangeRateProvider(1e18, 18); + MockExchangeRateProvider wstETHTostETHOracle = new MockExchangeRateProvider(1.1e18, 18); + MockExchangeRateProvider weETHTostETHOracle = new MockExchangeRateProvider(1.2e18, 18); + + (address lpToken, address pool, address wlpToken,,,) = createMockExchangeRatePool( + address(weth), address(wstETH), address(WETHTostETHOracle), address(wstETHTostETHOracle) + ); + + initialMint(address(weth), address(wstETH), amount, amount, SelfPeggingAsset(pool)); + + (address lpToken2, address pool2, address wlpToken2,,,) = createMockExchangeRatePool( + address(wstETH), address(weETH), address(wstETHTostETHOracle), address(weETHTostETHOracle) + ); + initialMint(address(wstETH), address(weETH), amount, amount, SelfPeggingAsset(pool2)); + + vm.writeJson(vm.serializeAddress("contracts", "wstETH", address(wstETH)), path); + vm.writeJson(vm.serializeAddress("contracts", "weETH", address(weETH)), path); + vm.writeJson(vm.serializeAddress("contracts", "WETH", address(weth)), path); + vm.writeJson(vm.serializeAddress("contracts", "WETHwstETHPool", pool), path); + vm.writeJson(vm.serializeAddress("contracts", "wstETHweETHPool", pool2), path); + vm.writeJson(vm.serializeAddress("contracts", "WETHwstETHPoolLPToken", lpToken), path); + vm.writeJson(vm.serializeAddress("contracts", "wstETHweETHPoolLPToken", lpToken2), path); + vm.writeJson(vm.serializeAddress("contracts", "WETHwstETHPoolWLPToken", wlpToken), path); + vm.writeJson(vm.serializeAddress("contracts", "wstETHweETHPoolWLPToken", wlpToken2), path); + } + + vm.stopBroadcast(); + } +} diff --git a/script/Config.sol b/script/Config.sol index 147498df..9d27fb23 100644 --- a/script/Config.sol +++ b/script/Config.sol @@ -13,29 +13,20 @@ contract Config is Script { address GOVERNOR; address DEPLOYER; - address usdc; - address usdt; - SelfPeggingAssetFactory factory; address selfPeggingAssetBeacon; - address spaTokenBeacon; - address wspaTokenBeacon; + address lpTokenBeacon; + address wlpTokenBeacon; address rampAControllerBeacon; + address factoryImplementation; address keeperImplementation; - address parameterRegistryBeacon; + address selfPeggingAssetImplentation; + address lpTokenImplentation; + address wlpTokenImplentation; + address rampAControllerImplentation; address zap; - struct JSONData { - address Factory; - address SPATokenBeacon; - address SelfPeggingAssetBeacon; - address USDC; - address USDT; - address WSPATokenBeacon; - address Zap; - } - - function loadConfig() internal view { + function loadConfig() internal { if (!testnet) { // POPULATE ADDRESSES BASED ON CHAIN ID // usdc = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; @@ -43,16 +34,21 @@ contract Config is Script { } } - function getNetworkName(uint256 chainId) internal pure returns (string memory) { + function getNetworkName(uint256 chainId) internal view returns (string memory) { if (chainId == 84_532) return "basesepolia"; else if (chainId == 421_614) return "arbitrumsepolia"; else if (chainId == 11_155_420) return "opsepolia"; else if (chainId == 10_143) return "monadtestnet"; else if (chainId == 80_069) return "bera-bepolia"; else if (chainId == 998) return "hyper-testnet"; + else if (chainId == 999) return "hyper-mainnet"; else if (chainId == 42_161) return "arbitrum"; else if (chainId == 5) return "base"; else if (chainId == 10) return "optimism"; + else if (chainId == 8453) return "base"; + else if (chainId == 57_054) return "sonic-testnet"; + else if (chainId == 146) return "sonic-mainnet"; + else if (chainId == 1) return "mainnet"; else revert("Invalid chain ID"); } diff --git a/script/CreatePool.s.sol b/script/CreatePool.s.sol deleted file mode 100644 index 363e880b..00000000 --- a/script/CreatePool.s.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.28; - -import { stdJson } from "forge-std/StdJson.sol"; -import { console } from "forge-std/console.sol"; - -import { Deploy } from "script/Deploy.sol"; -import { Setup } from "script/Setup.sol"; -import { Pool } from "script/Pool.sol"; -import { SelfPeggingAssetFactory } from "../src/SelfPeggingAssetFactory.sol"; -import { SelfPeggingAsset } from "../src/SelfPeggingAsset.sol"; -import { MockToken } from "../src/mock/MockToken.sol"; - -contract Testnet is Deploy, Setup, Pool { - function init() internal { - if (vm.envUint("HEX_PRIV_KEY") == 0) revert("No private key found"); - deployerPrivateKey = vm.envUint("HEX_PRIV_KEY"); - DEPLOYER = vm.addr(deployerPrivateKey); - } - - function run() public payable { - init(); - loadConfig(); - - vm.startBroadcast(deployerPrivateKey); - - string memory root = vm.projectRoot(); - string memory path; - string memory networkName = getNetworkName(getChainId()); - path = string.concat(root, "/broadcast/", networkName, ".json"); - - string memory json = vm.readFile(path); - bytes memory data = vm.parseJson(json); - - JSONData memory jsonData = abi.decode(data, (JSONData)); - - factory = SelfPeggingAssetFactory(jsonData.Factory); - selfPeggingAssetBeacon = jsonData.SelfPeggingAssetBeacon; - spaTokenBeacon = jsonData.SPATokenBeacon; - wspaTokenBeacon = jsonData.WSPATokenBeacon; - usdc = jsonData.USDC; - usdt = jsonData.USDT; - - (, address selfPeggingAsset,) = createStandardPool(); - - uint256 amount = 10_000e18; - - MockToken(usdc).mint(DEPLOYER, amount); - MockToken(usdt).mint(DEPLOYER, amount); - - initialMint(amount, amount, SelfPeggingAsset(selfPeggingAsset)); - - vm.stopBroadcast(); - } -} diff --git a/script/Deploy.sol b/script/Deploy.sol index 79d25973..df527457 100644 --- a/script/Deploy.sol +++ b/script/Deploy.sol @@ -12,9 +12,8 @@ import { Config } from "script/Config.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "../src/misc/ConstantExchangeRateProvider.sol"; import { Zap } from "../src/periphery/Zap.sol"; -import { Keeper } from "../src/periphery/Keeper.sol"; - import { RampAController } from "../src/periphery/RampAController.sol"; +import { Keeper } from "../src/periphery/Keeper.sol"; contract Deploy is Config { function deployBeacons() internal { @@ -22,22 +21,22 @@ contract Deploy is Config { console.log("deploy-beacon-logs"); console.log("---------------"); - address selfPeggingAssetImplementation = address(new SelfPeggingAsset()); - address spaTokenImplementation = address(new SPAToken()); - address wspaTokenImplementation = address(new WSPAToken()); - address rampAControllerImplementation = address(new RampAController()); + selfPeggingAssetImplentation = address(new SelfPeggingAsset()); + lpTokenImplentation = address(new SPAToken()); + wlpTokenImplentation = address(new WSPAToken()); + rampAControllerImplentation = address(new RampAController()); keeperImplementation = address(new Keeper()); - UpgradeableBeacon beacon = new UpgradeableBeacon(selfPeggingAssetImplementation, GOVERNOR); + UpgradeableBeacon beacon = new UpgradeableBeacon(selfPeggingAssetImplentation, GOVERNOR); selfPeggingAssetBeacon = address(beacon); - beacon = new UpgradeableBeacon(spaTokenImplementation, GOVERNOR); - spaTokenBeacon = address(beacon); + beacon = new UpgradeableBeacon(lpTokenImplentation, GOVERNOR); + lpTokenBeacon = address(beacon); - beacon = new UpgradeableBeacon(wspaTokenImplementation, GOVERNOR); - wspaTokenBeacon = address(beacon); + beacon = new UpgradeableBeacon(wlpTokenImplentation, GOVERNOR); + wlpTokenBeacon = address(beacon); - beacon = new UpgradeableBeacon(rampAControllerImplementation, GOVERNOR); + beacon = new UpgradeableBeacon(rampAControllerImplentation, GOVERNOR); rampAControllerBeacon = address(beacon); } @@ -46,27 +45,29 @@ contract Deploy is Config { console.log("deploy-factory-logs"); console.log("---------------"); - SelfPeggingAssetFactory.InitializeArgument memory args = SelfPeggingAssetFactory.InitializeArgument( - GOVERNOR, - GOVERNOR, - 0, - 0, - 0, - 0, - 100, - 30 minutes, - selfPeggingAssetBeacon, - spaTokenBeacon, - wspaTokenBeacon, - rampAControllerBeacon, - keeperImplementation, - address(new ConstantExchangeRateProvider()), - 0, - 0 + bytes memory data = abi.encodeCall( + SelfPeggingAssetFactory.initialize, + SelfPeggingAssetFactory.InitializeArgument( + GOVERNOR, + GOVERNOR, + 0, + 5_000_000, + 0, + 10_000_000_000, + 100, + 30 minutes, + selfPeggingAssetBeacon, + lpTokenBeacon, + wlpTokenBeacon, + rampAControllerBeacon, + keeperImplementation, + address(new ConstantExchangeRateProvider()), + 0, + 1_000_000_000 + ) ); - - bytes memory data = abi.encodeCall(SelfPeggingAssetFactory.initialize, (args)); - ERC1967Proxy proxy = new ERC1967Proxy(address(new SelfPeggingAssetFactory()), data); + factoryImplementation = address(new SelfPeggingAssetFactory()); + ERC1967Proxy proxy = new ERC1967Proxy(factoryImplementation, data); factory = SelfPeggingAssetFactory(address(proxy)); factory.transferOwnership(GOVERNOR); diff --git a/script/Mainnet.sol b/script/Mainnet.sol new file mode 100644 index 00000000..6109fe98 --- /dev/null +++ b/script/Mainnet.sol @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +import { stdJson } from "forge-std/StdJson.sol"; +import { console } from "forge-std/console.sol"; + +import { Deploy } from "script/Deploy.sol"; +import { Pool } from "script/Pool.sol"; +import { MockToken } from "../src/mock/MockToken.sol"; +import { SelfPeggingAsset } from "../src/SelfPeggingAsset.sol"; +import { ChainlinkOracleProvider } from "../src/misc/ChainlinkOracleProvider.sol"; +import "@chainlink/contracts/shared/interfaces/AggregatorV3Interface.sol"; + +contract Mainnet is Deploy, Pool { + function init() internal { + if (vm.envUint("HEX_PRIV_KEY") == 0) revert("No private key found"); + deployerPrivateKey = vm.envUint("HEX_PRIV_KEY"); + GOVERNOR = vm.addr(deployerPrivateKey); + DEPLOYER = vm.addr(deployerPrivateKey); + } + + function run() public payable { + init(); + loadConfig(); + + vm.startBroadcast(deployerPrivateKey); + + deployBeacons(); + deployFactory(); + deployZap(); + + uint256 chainId = getChainId(); + string memory networkName = getNetworkName(chainId); + string memory path = string.concat("./broadcast/", networkName, ".json"); + string memory pathImpl = string.concat("./broadcast/", networkName, ".impl.json"); + + if (chainId == 8453) { + // base mainnet + address wstETHFeed = 0x43a5C292A453A3bF3606fa856197f09D7B74251a; + address weETHFeed = 0xFC1415403EbB0c693f9a7844b92aD2Ff24775C65; + address cbETHFeed = 0x806b4Ac04501c29769051e42783cF04dCE41440b; + + address weth = 0x4200000000000000000000000000000000000006; + address wstETH = 0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452; + address weETH = 0x04C0599Ae5A44757c0af6F9eC3b93da8976c150A; + address cbETH = 0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22; + address usdc = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913; + address usdt = 0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2; + + uint256 ethAmount = 0.0027e18; + uint256 usdAmount = 5e6; + + address sequencer = 0xBCF85224fc0756B9Fa45aA7892530B47e10b6433; + + // create chainlink oracle + address wstETHOracle = address( + new ChainlinkOracleProvider( + AggregatorV3Interface(sequencer), AggregatorV3Interface(wstETHFeed), 24 hours + ) + ); + + address weETHOracle = address( + new ChainlinkOracleProvider( + AggregatorV3Interface(sequencer), AggregatorV3Interface(weETHFeed), 24 hours + ) + ); + + address cbETHOracle = address( + new ChainlinkOracleProvider( + AggregatorV3Interface(sequencer), AggregatorV3Interface(cbETHFeed), 24 hours + ) + ); + + (, address pool,,,,) = createChainlinkPool(weth, wstETH, wstETHOracle); + + initialMint(weth, wstETH, ethAmount, ethAmount, SelfPeggingAsset(pool)); + + (, pool,,,,) = createChainlinkPool(weth, weETH, weETHOracle); + + initialMint(weth, weETH, ethAmount, ethAmount, SelfPeggingAsset(pool)); + + (, pool,,,,) = createChainlinkPool(weth, cbETH, cbETHOracle); + + initialMint(weth, cbETH, ethAmount, ethAmount, SelfPeggingAsset(pool)); + + (, pool,,,,) = createStandardPool(usdc, usdt); + + initialMint(usdc, usdt, usdAmount, usdAmount, SelfPeggingAsset(pool)); + } else if (chainId == 146) { + // sonic mainnet + + address ws = 0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38; + address stS = 0xE5DA20F15420aD15DE0fa650600aFc998bbE3955; + address wOS = 0x9F0dF7799f6FDAd409300080cfF680f5A23df4b1; + + (address wSstSLpToken, address wSstSPool, address wSstSWlpToken,,,) = createStandardAndERC4626Pool(ws, stS); + + initialMint(ws, stS, 5e18, 4.9e18, SelfPeggingAsset(wSstSPool)); + + (address wSwOSLpToken, address wSwOSPool, address wSwOSWlpToken,,,) = createStandardAndERC4626Pool(ws, wOS); + + initialMint(ws, wOS, 5e18, 3e18, SelfPeggingAsset(wSwOSPool)); + + vm.writeJson(vm.serializeAddress("contracts", "Zap", zap), path); + vm.writeJson(vm.serializeAddress("contracts", "Factory", address(factory)), path); + vm.writeJson(vm.serializeAddress("contracts", "SelfPeggingAssetBeacon", selfPeggingAssetBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "LPTokenBeacon", lpTokenBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "WLPTokenBeacon", wlpTokenBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "wS", address(ws)), path); + vm.writeJson(vm.serializeAddress("contracts", "stS", address(stS)), path); + vm.writeJson(vm.serializeAddress("contracts", "wOS", address(wOS)), path); + vm.writeJson(vm.serializeAddress("contracts", "wSstSPool", address(wSstSPool)), path); + vm.writeJson(vm.serializeAddress("contracts", "wSstSPoolLPToken", wSstSLpToken), path); + vm.writeJson(vm.serializeAddress("contracts", "wSstSPoolWLPToken", wSstSWlpToken), path); + vm.writeJson(vm.serializeAddress("contracts", "wSwOSPool", address(wSwOSPool)), path); + vm.writeJson(vm.serializeAddress("contracts", "wSwOSPoolLPToken", wSwOSLpToken), path); + vm.writeJson(vm.serializeAddress("contracts", "wSwOSPoolWLPToken", wSwOSWlpToken), path); + } else if (chainId == 1) { + // mainnet + + address usdt = 0xdAC17F958D2ee523a2206206994597C13D831ec7; + address usdc = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; + + (address usdcusdtLpToken, address usdcusdtPool, address usdcusdtWlpToken,,,) = + createStandardPool(usdc, usdt); + + // initialMint(usdc, usdt, 50e6, 50e6, SelfPeggingAsset(usdcusdtPool)); + + vm.writeJson(vm.serializeAddress("contracts", "Zap", zap), path); + vm.writeJson(vm.serializeAddress("contracts", "Factory", address(factory)), path); + vm.writeJson(vm.serializeAddress("contracts", "SelfPeggingAssetBeacon", selfPeggingAssetBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "LPTokenBeacon", lpTokenBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "WLPTokenBeacon", wlpTokenBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "usdc", address(usdc)), path); + vm.writeJson(vm.serializeAddress("contracts", "usdt", address(usdt)), path); + vm.writeJson(vm.serializeAddress("contracts", "usdcusdtPool", address(usdcusdtPool)), path); + vm.writeJson(vm.serializeAddress("contracts", "usdcusdtPoolLPToken", usdcusdtLpToken), path); + vm.writeJson(vm.serializeAddress("contracts", "usdcusdtPoolWLPToken", usdcusdtWlpToken), path); + } else if (chainId == 999) { + // hyper evm mainnet + + address behype = 0xd8FC8F0b03eBA61F64D08B0bef69d80916E5DdA9; + address whype = 0x5555555555555555555555555555555555555555; + ( + address whypeBehypeLpToken, + address whypeBehypePool, + address whypeBehypeWlpToken, + address whypeBehypeRampAController, + address whypeBehypeParameterRegistry, + address whypeBehypeKeeper + ) = createExchangeRatePool( + whype, + behype, + 0xCeaD893b162D38e714D82d06a7fe0b0dc3c38E0b, + bytes4(abi.encodeWithSignature("exchangeRatio()")), + 18 + ); + + vm.writeJson(vm.serializeAddress("contracts", "Zap", zap), path); + vm.writeJson(vm.serializeAddress("contracts", "Factory", address(factory)), path); + vm.writeJson(vm.serializeAddress("contracts", "SelfPeggingAssetBeacon", selfPeggingAssetBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "SPATokenBeacon", lpTokenBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "WSPATokenBeacon", wlpTokenBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "RampAControllerBeacon", rampAControllerBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "BeHype", address(behype)), path); + vm.writeJson(vm.serializeAddress("contracts", "WHype", address(whype)), path); + vm.writeJson(vm.serializeAddress("contracts", "WhypeBehypePool", address(whypeBehypePool)), path); + vm.writeJson(vm.serializeAddress("contracts", "WhypeBehypeSPAToken", whypeBehypeLpToken), path); + vm.writeJson(vm.serializeAddress("contracts", "WhypeBehypeWSPAToken", whypeBehypeWlpToken), path); + vm.writeJson( + vm.serializeAddress("contracts", "WhypeBehypeRampAController", whypeBehypeRampAController), path + ); + vm.writeJson( + vm.serializeAddress("contracts", "whypeBehypeParameterRegistry", whypeBehypeParameterRegistry), path + ); + vm.writeJson(vm.serializeAddress("contracts", "WhypeBehypeKeeper", whypeBehypeKeeper), path); + + vm.writeJson(vm.serializeAddress("contracts", "Factory", address(factoryImplementation)), pathImpl); + vm.writeJson(vm.serializeAddress("contracts", "SelfPeggingAsset", selfPeggingAssetImplentation), pathImpl); + vm.writeJson(vm.serializeAddress("contracts", "SPAToken", lpTokenImplentation), pathImpl); + vm.writeJson(vm.serializeAddress("contracts", "WSPAToken", wlpTokenImplentation), pathImpl); + vm.writeJson(vm.serializeAddress("contracts", "rampAController", rampAControllerImplentation), pathImpl); + vm.writeJson(vm.serializeAddress("contracts", "Keeper", keeperImplementation), pathImpl); + } + + vm.stopBroadcast(); + } +} diff --git a/script/Pool.sol b/script/Pool.sol index 6d7b89c4..4ebdee7e 100644 --- a/script/Pool.sol +++ b/script/Pool.sol @@ -8,16 +8,21 @@ import { Config } from "script/Config.sol"; import { SelfPeggingAssetFactory } from "../src/SelfPeggingAssetFactory.sol"; import { SelfPeggingAsset } from "../src/SelfPeggingAsset.sol"; import { MockToken } from "../src/mock/MockToken.sol"; +import { MockExchangeRateProvider } from "../src/mock/MockExchangeRateProvider.sol"; +import { ChainlinkOracleProvider } from "../src/misc/ChainlinkOracleProvider.sol"; contract Pool is Config { - function createStandardPool() internal returns (address, address, address) { + function createStandardPool(address tokenA, address tokenB) + internal + returns (address, address, address, address, address, address) + { console.log("---------------"); console.log("create-pool-logs"); console.log("---------------"); SelfPeggingAssetFactory.CreatePoolArgument memory arg = SelfPeggingAssetFactory.CreatePoolArgument({ - tokenA: usdc, - tokenB: usdt, + tokenA: tokenA, + tokenB: tokenB, tokenAType: SelfPeggingAssetFactory.TokenType.Standard, tokenAOracle: address(0), tokenARateFunctionSig: "", @@ -31,35 +36,416 @@ contract Pool is Config { vm.recordLogs(); factory.createPool(arg); Vm.Log[] memory entries = vm.getRecordedLogs(); - bytes32 eventSig = keccak256("PoolCreated(address,address,address)"); + bytes32 eventSig = keccak256("PoolCreated(address,address,address,address,address,address)"); address decodedPoolToken; address decodedSelfPeggingAsset; address decodedWrappedPoolToken; + address decodedRampAController; + address keeper; + address parameterRegistry; for (uint256 i = 0; i < entries.length; i++) { Vm.Log memory log = entries[i]; if (log.topics[0] == eventSig) { - (decodedPoolToken, decodedSelfPeggingAsset, decodedWrappedPoolToken) = - abi.decode(log.data, (address, address, address)); + ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ) = abi.decode(log.data, (address, address, address, address, address, address)); } } - return (decodedPoolToken, decodedSelfPeggingAsset, decodedWrappedPoolToken); + return ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ); } - function initialMint(uint256 usdcAmount, uint256 usdtAmount, SelfPeggingAsset selfPeggingAsset) internal { + function createStandardAndRebasingPool(address tokenA, address tokenB) + internal + returns (address, address, address, address, address, address) + { + console.log("---------------"); + console.log("create-pool-logs"); + console.log("---------------"); + + SelfPeggingAssetFactory.CreatePoolArgument memory arg = SelfPeggingAssetFactory.CreatePoolArgument({ + tokenA: tokenA, + tokenB: tokenB, + tokenAType: SelfPeggingAssetFactory.TokenType.Standard, + tokenAOracle: address(0), + tokenARateFunctionSig: "", + tokenADecimalsFunctionSig: "", + tokenBType: SelfPeggingAssetFactory.TokenType.Rebasing, + tokenBOracle: address(0), + tokenBRateFunctionSig: "", + tokenBDecimalsFunctionSig: "" + }); + + vm.recordLogs(); + factory.createPool(arg); + Vm.Log[] memory entries = vm.getRecordedLogs(); + bytes32 eventSig = keccak256("PoolCreated(address,address,address,address,address,address)"); + + address decodedPoolToken; + address decodedSelfPeggingAsset; + address decodedWrappedPoolToken; + address decodedRampAController; + address keeper; + address parameterRegistry; + + for (uint256 i = 0; i < entries.length; i++) { + Vm.Log memory log = entries[i]; + + if (log.topics[0] == eventSig) { + ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ) = abi.decode(log.data, (address, address, address, address, address, address)); + } + } + + return ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ); + } + + function createStandardAndERC4626Pool(address tokenA, address tokenB) + internal + returns (address, address, address, address, address, address) + { + console.log("---------------"); + console.log("create-pool-logs"); + console.log("---------------"); + + SelfPeggingAssetFactory.CreatePoolArgument memory arg = SelfPeggingAssetFactory.CreatePoolArgument({ + tokenA: tokenA, + tokenB: tokenB, + tokenAType: SelfPeggingAssetFactory.TokenType.Standard, + tokenAOracle: address(0), + tokenARateFunctionSig: "", + tokenADecimalsFunctionSig: "", + tokenBType: SelfPeggingAssetFactory.TokenType.ERC4626, + tokenBOracle: address(0), + tokenBRateFunctionSig: "", + tokenBDecimalsFunctionSig: "" + }); + + vm.recordLogs(); + factory.createPool(arg); + Vm.Log[] memory entries = vm.getRecordedLogs(); + bytes32 eventSig = keccak256("PoolCreated(address,address,address,address,address,address)"); + + address decodedPoolToken; + address decodedSelfPeggingAsset; + address decodedWrappedPoolToken; + address decodedRampAController; + address keeper; + address parameterRegistry; + + for (uint256 i = 0; i < entries.length; i++) { + Vm.Log memory log = entries[i]; + + if (log.topics[0] == eventSig) { + ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ) = abi.decode(log.data, (address, address, address, address, address, address)); + } + } + + return ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ); + } + + function createExchangeRatePool( + address tokenA, + address tokenB, + address tokenBOracle, + bytes4 rateFunc, + uint8 decimals + ) + internal + returns (address, address, address, address, address, address) + { + console.log("---------------"); + console.log("create-pool-logs"); + console.log("---------------"); + + SelfPeggingAssetFactory.CreatePoolArgument memory arg = SelfPeggingAssetFactory.CreatePoolArgument({ + tokenA: tokenA, + tokenB: tokenB, + tokenAType: SelfPeggingAssetFactory.TokenType.Standard, + tokenAOracle: address(0), + tokenARateFunctionSig: "", + tokenADecimalsFunctionSig: "", + tokenBType: SelfPeggingAssetFactory.TokenType.Oracle, + tokenBOracle: tokenBOracle, + tokenBRateFunctionSig: abi.encodePacked(rateFunc), + tokenBDecimalsFunctionSig: abi.encodePacked(bytes1(decimals)) + }); + + vm.recordLogs(); + factory.createPool(arg); + Vm.Log[] memory entries = vm.getRecordedLogs(); + bytes32 eventSig = keccak256("PoolCreated(address,address,address,address,address,address)"); + + address decodedPoolToken; + address decodedSelfPeggingAsset; + address decodedWrappedPoolToken; + address decodedRampAController; + address keeper; + address parameterRegistry; + + for (uint256 i = 0; i < entries.length; i++) { + Vm.Log memory log = entries[i]; + + if (log.topics[0] == eventSig) { + ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ) = abi.decode(log.data, (address, address, address, address, address, address)); + } + } + + return ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ); + } + + function createChainlinkPool(address tokenA, address tokenB, address tokenBOracle) + internal + returns (address, address, address, address, address, address) + { + console.log("---------------"); + console.log("create-pool-logs"); + console.log("---------------"); + + SelfPeggingAssetFactory.CreatePoolArgument memory arg = SelfPeggingAssetFactory.CreatePoolArgument({ + tokenA: tokenA, + tokenB: tokenB, + tokenAType: SelfPeggingAssetFactory.TokenType.Standard, + tokenAOracle: address(0), + tokenARateFunctionSig: "", + tokenADecimalsFunctionSig: "", + tokenBType: SelfPeggingAssetFactory.TokenType.Oracle, + tokenBOracle: tokenBOracle, + tokenBRateFunctionSig: abi.encodePacked(ChainlinkOracleProvider.price.selector), + tokenBDecimalsFunctionSig: abi.encodePacked(ChainlinkOracleProvider.decimals.selector) + }); + + vm.recordLogs(); + factory.createPool(arg); + Vm.Log[] memory entries = vm.getRecordedLogs(); + bytes32 eventSig = keccak256("PoolCreated(address,address,address,address,address,address)"); + + address decodedPoolToken; + address decodedSelfPeggingAsset; + address decodedWrappedPoolToken; + address decodedRampAController; + address keeper; + address parameterRegistry; + + for (uint256 i = 0; i < entries.length; i++) { + Vm.Log memory log = entries[i]; + + if (log.topics[0] == eventSig) { + ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ) = abi.decode(log.data, (address, address, address, address, address, address)); + } + } + + return ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ); + } + + function createChainlinkPool(address tokenA, address tokenB, address tokenAOracle, address tokenBOracle) + internal + returns (address, address, address, address, address, address) + { + console.log("---------------"); + console.log("create-pool-logs"); + console.log("---------------"); + + SelfPeggingAssetFactory.CreatePoolArgument memory arg = SelfPeggingAssetFactory.CreatePoolArgument({ + tokenA: tokenA, + tokenB: tokenB, + tokenAType: SelfPeggingAssetFactory.TokenType.Oracle, + tokenAOracle: tokenAOracle, + tokenARateFunctionSig: abi.encodePacked(ChainlinkOracleProvider.price.selector), + tokenADecimalsFunctionSig: abi.encodePacked(ChainlinkOracleProvider.decimals.selector), + tokenBType: SelfPeggingAssetFactory.TokenType.Oracle, + tokenBOracle: tokenBOracle, + tokenBRateFunctionSig: abi.encodePacked(ChainlinkOracleProvider.price.selector), + tokenBDecimalsFunctionSig: abi.encodePacked(ChainlinkOracleProvider.decimals.selector) + }); + + vm.recordLogs(); + factory.createPool(arg); + Vm.Log[] memory entries = vm.getRecordedLogs(); + bytes32 eventSig = keccak256("PoolCreated(address,address,address,address,address,address)"); + + address decodedPoolToken; + address decodedSelfPeggingAsset; + address decodedWrappedPoolToken; + address decodedRampAController; + address keeper; + address parameterRegistry; + + for (uint256 i = 0; i < entries.length; i++) { + Vm.Log memory log = entries[i]; + + if (log.topics[0] == eventSig) { + ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ) = abi.decode(log.data, (address, address, address, address, address, address)); + } + } + + return ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ); + } + + function createMockExchangeRatePool(address tokenA, address tokenB, address tokenAOracle, address tokenBOracle) + internal + returns (address, address, address, address, address, address) + { + console.log("---------------"); + console.log("create-pool-logs"); + console.log("---------------"); + + SelfPeggingAssetFactory.CreatePoolArgument memory arg = SelfPeggingAssetFactory.CreatePoolArgument({ + tokenA: tokenA, + tokenB: tokenB, + tokenAType: SelfPeggingAssetFactory.TokenType.Oracle, + tokenAOracle: tokenAOracle, + tokenARateFunctionSig: abi.encodePacked(MockExchangeRateProvider.exchangeRate.selector), + tokenADecimalsFunctionSig: abi.encodePacked(MockExchangeRateProvider.exchangeRateDecimals.selector), + tokenBType: SelfPeggingAssetFactory.TokenType.Oracle, + tokenBOracle: tokenBOracle, + tokenBRateFunctionSig: abi.encodePacked(MockExchangeRateProvider.exchangeRate.selector), + tokenBDecimalsFunctionSig: abi.encodePacked(MockExchangeRateProvider.exchangeRateDecimals.selector) + }); + + vm.recordLogs(); + factory.createPool(arg); + Vm.Log[] memory entries = vm.getRecordedLogs(); + bytes32 eventSig = keccak256("PoolCreated(address,address,address,address,address,address)"); + + address decodedPoolToken; + address decodedSelfPeggingAsset; + address decodedWrappedPoolToken; + address decodedRampAController; + address keeper; + address parameterRegistry; + + for (uint256 i = 0; i < entries.length; i++) { + Vm.Log memory log = entries[i]; + + if (log.topics[0] == eventSig) { + ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ) = abi.decode(log.data, (address, address, address, address, address, address)); + } + } + + return ( + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + parameterRegistry, + keeper + ); + } + + function initialMint( + address tokenA, + address tokenB, + uint256 tokenAAmount, + uint256 tokenBAmount, + SelfPeggingAsset selfPeggingAsset + ) + internal + { console.log("---------------"); console.log("initial-mint-logs"); console.log("---------------"); + console.log("AAAA"); + + // console.log(MockToken(tokenB).balanceOf(0x3a3C006053a9B40286B9951A11bE4C5808c11dc8)); - MockToken(usdc).approve(address(selfPeggingAsset), usdcAmount); - MockToken(usdt).approve(address(selfPeggingAsset), usdtAmount); + MockToken(tokenA).approve(address(selfPeggingAsset), tokenAAmount); + MockToken(tokenB).approve(address(selfPeggingAsset), tokenBAmount); uint256[] memory amounts = new uint256[](2); - amounts[0] = usdcAmount; - amounts[1] = usdtAmount; + amounts[0] = tokenAAmount; + amounts[1] = tokenBAmount; selfPeggingAsset.mint(amounts, 0); } diff --git a/script/Setup.sol b/script/Setup.sol deleted file mode 100644 index 29779d2a..00000000 --- a/script/Setup.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.28; - -import { stdJson } from "forge-std/StdJson.sol"; -import { console } from "forge-std/console.sol"; -import { MockToken } from "../src/mock/MockToken.sol"; -import { Config } from "script/Config.sol"; - -contract Setup is Config { - function deployMocks() internal { - MockToken tokenA = new MockToken("USDC", "USDC", 6); - MockToken tokenB = new MockToken("USDT", "USDT", 6); - - usdc = address(tokenA); - usdt = address(tokenB); - } -} diff --git a/script/Testnet.s.sol b/script/Testnet.s.sol index 01fcc82b..83131123 100644 --- a/script/Testnet.s.sol +++ b/script/Testnet.s.sol @@ -5,9 +5,12 @@ import { stdJson } from "forge-std/StdJson.sol"; import { console } from "forge-std/console.sol"; import { Deploy } from "script/Deploy.sol"; -import { Setup } from "script/Setup.sol"; +import { Pool } from "script/Pool.sol"; +import { MockToken } from "../src/mock/MockToken.sol"; +import { SelfPeggingAsset } from "../src/SelfPeggingAsset.sol"; +import { MockExchangeRateProvider } from "../src/mock/MockExchangeRateProvider.sol"; -contract Testnet is Deploy, Setup { +contract Testnet is Deploy, Pool { function init() internal { if (vm.envUint("HEX_PRIV_KEY") == 0) revert("No private key found"); deployerPrivateKey = vm.envUint("HEX_PRIV_KEY"); @@ -21,27 +24,53 @@ contract Testnet is Deploy, Setup { vm.startBroadcast(deployerPrivateKey); - deployMocks(); deployBeacons(); deployFactory(); deployZap(); - string memory networkName = getNetworkName(getChainId()); + uint256 chainId = getChainId(); + string memory networkName = getNetworkName(chainId); string memory path = string.concat("./broadcast/", networkName, ".json"); - vm.writeJson(vm.serializeAddress("contracts", "USDC", usdc), path); + if (chainId == 57_054) { + MockExchangeRateProvider wSToS = new MockExchangeRateProvider(1e18, 18); + MockExchangeRateProvider stSToS = new MockExchangeRateProvider(1.015_58e18, 18); + MockExchangeRateProvider OSToS = new MockExchangeRateProvider(1.004_739e18, 18); - vm.writeJson(vm.serializeAddress("contracts", "USDT", usdt), path); + MockToken wS = new MockToken("wS", "wS", 18); + MockToken stS = new MockToken("stS", "stS", 18); + MockToken OS = new MockToken("OS", "OS", 18); - vm.writeJson(vm.serializeAddress("contracts", "Factory", address(factory)), path); + uint256 amount = 100e18; - vm.writeJson(vm.serializeAddress("contracts", "SelfPeggingAssetBeacon", selfPeggingAssetBeacon), path); + MockToken(wS).mint(DEPLOYER, amount * 2); + MockToken(stS).mint(DEPLOYER, amount); + MockToken(OS).mint(DEPLOYER, amount); - vm.writeJson(vm.serializeAddress("contracts", "SPATokenBeacon", spaTokenBeacon), path); + (address lpToken, address pool, address wlpToken,,,) = + createMockExchangeRatePool(address(wS), address(stS), address(wSToS), address(stSToS)); - vm.writeJson(vm.serializeAddress("contracts", "WSPATokenBeacon", wspaTokenBeacon), path); + initialMint(address(wS), address(stS), amount, amount, SelfPeggingAsset(pool)); - vm.writeJson(vm.serializeAddress("contracts", "Zap", zap), path); + (address lpToken2, address pool2, address wlpToken2,,,) = + createMockExchangeRatePool(address(wS), address(OS), address(wSToS), address(OSToS)); + initialMint(address(wS), address(OS), amount, amount, SelfPeggingAsset(pool2)); + + vm.writeJson(vm.serializeAddress("contracts", "Zap", zap), path); + vm.writeJson(vm.serializeAddress("contracts", "Factory", address(factory)), path); + vm.writeJson(vm.serializeAddress("contracts", "SelfPeggingAssetBeacon", selfPeggingAssetBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "LPTokenBeacon", lpTokenBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "WLPTokenBeacon", wlpTokenBeacon), path); + vm.writeJson(vm.serializeAddress("contracts", "wS", address(wS)), path); + vm.writeJson(vm.serializeAddress("contracts", "stS", address(stS)), path); + vm.writeJson(vm.serializeAddress("contracts", "OS", address(OS)), path); + vm.writeJson(vm.serializeAddress("contracts", "wSstSPool", address(pool)), path); + vm.writeJson(vm.serializeAddress("contracts", "wSstSPoolLPToken", lpToken), path); + vm.writeJson(vm.serializeAddress("contracts", "wSstSPoolWLPToken", wlpToken), path); + vm.writeJson(vm.serializeAddress("contracts", "wSOSPool", address(pool2)), path); + vm.writeJson(vm.serializeAddress("contracts", "wSOSPoolLPToken", lpToken2), path); + vm.writeJson(vm.serializeAddress("contracts", "wSOSPoolWLPToken", wlpToken2), path); + } vm.stopBroadcast(); } diff --git a/script/Upgrade.s.sol b/script/Upgrade.s.sol index 36c102bd..adfcd9e3 100644 --- a/script/Upgrade.s.sol +++ b/script/Upgrade.s.sol @@ -5,7 +5,6 @@ import { stdJson } from "forge-std/StdJson.sol"; import { console } from "forge-std/console.sol"; import { Deploy } from "script/Deploy.sol"; -import { Setup } from "script/Setup.sol"; import { Pool } from "script/Pool.sol"; import { SelfPeggingAssetFactory } from "../src/SelfPeggingAssetFactory.sol"; import { SelfPeggingAsset } from "../src/SelfPeggingAsset.sol"; @@ -17,7 +16,15 @@ import { WSPAToken } from "../src/WSPAToken.sol"; import { SelfPeggingAssetFactory } from "../src/SelfPeggingAssetFactory.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; -contract Upgrade is Deploy, Setup, Pool { +contract Upgrade is Deploy, Pool { + struct JSONData { + address Factory; + address LPTokenBeacon; + address SelfPeggingAssetBeacon; + address WLPTokenBeacon; + address Zap; + } + function init() internal { if (vm.envUint("HEX_PRIV_KEY") == 0) revert("No private key found"); deployerPrivateKey = vm.envUint("HEX_PRIV_KEY"); @@ -42,17 +49,17 @@ contract Upgrade is Deploy, Setup, Pool { factory = SelfPeggingAssetFactory(jsonData.Factory); selfPeggingAssetBeacon = jsonData.SelfPeggingAssetBeacon; - spaTokenBeacon = jsonData.SPATokenBeacon; - wspaTokenBeacon = jsonData.WSPATokenBeacon; + lpTokenBeacon = jsonData.LPTokenBeacon; + wlpTokenBeacon = jsonData.WLPTokenBeacon; // Upgrade - SPAToken spaTokenImpl = new SPAToken(); - WSPAToken wspaTokenImpl = new WSPAToken(); + SPAToken lpTokenImpl = new SPAToken(); + WSPAToken wlpTokenImpl = new WSPAToken(); SelfPeggingAsset selfPeggingAssetImpl = new SelfPeggingAsset(); SelfPeggingAssetFactory factoryImpl = SelfPeggingAssetFactory(factory); - UpgradeableBeacon(spaTokenBeacon).upgradeTo(address(spaTokenImpl)); - UpgradeableBeacon(wspaTokenBeacon).upgradeTo(address(wspaTokenImpl)); + UpgradeableBeacon(lpTokenBeacon).upgradeTo(address(lpTokenImpl)); + UpgradeableBeacon(wlpTokenBeacon).upgradeTo(address(wlpTokenImpl)); UpgradeableBeacon(selfPeggingAssetBeacon).upgradeTo(address(selfPeggingAssetImpl)); factory.upgradeToAndCall(address(factoryImpl), bytes("")); diff --git a/src/SPAToken.sol b/src/SPAToken.sol index 554d5b48..ea7ce1d6 100644 --- a/src/SPAToken.sol +++ b/src/SPAToken.sol @@ -173,13 +173,7 @@ contract SPAToken is Initializable, OwnableUpgradeable, ISPAToken { _disableInitializers(); } - function initialize( - string memory _name, - string memory _symbol, - uint256 _buffer, - address _keeper, - address _pool - ) + function initialize(string memory _name, string memory _symbol, uint256 _buffer, address _keeper, address _pool) public initializer { @@ -217,14 +211,7 @@ contract SPAToken is Initializable, OwnableUpgradeable, ISPAToken { * Requirements: * - the caller must have allowance for `_sender`'s tokens of at least `getPeggedTokenByShares(_sharesAmount)`. */ - function transferSharesFrom( - address _sender, - address _recipient, - uint256 _sharesAmount - ) - external - returns (uint256) - { + function transferSharesFrom(address _sender, address _recipient, uint256 _sharesAmount) external returns (uint256) { uint256 tokensAmount = getPeggedTokenByShares(_sharesAmount); if (tokensAmount == 0 && _sharesAmount > 0) tokensAmount = 1; // Prevent zero-cost transfers _spendAllowance(_sender, msg.sender, tokensAmount); @@ -327,6 +314,7 @@ contract SPAToken is Initializable, OwnableUpgradeable, ISPAToken { _approve(msg.sender, _spender, currentAllowance - _subtractedValue); return true; } + // solhint-enable max-line-length /** diff --git a/src/SelfPeggingAsset.sol b/src/SelfPeggingAsset.sol index b82f4864..c329d838 100644 --- a/src/SelfPeggingAsset.sol +++ b/src/SelfPeggingAsset.sol @@ -475,10 +475,7 @@ contract SelfPeggingAsset is Initializable, ReentrancyGuardUpgradeable, OwnableU * @param _minMintAmount Minimum amount of pool token to mint. * @return The amount of pool tokens minted. */ - function mint( - uint256[] calldata _amounts, - uint256 _minMintAmount - ) + function mint(uint256[] calldata _amounts, uint256 _minMintAmount) external nonReentrant syncRamping @@ -548,12 +545,7 @@ contract SelfPeggingAsset is Initializable, ReentrancyGuardUpgradeable, OwnableU * @param _minDy Minimum token _j to swap out in converted balance. * @return Amount of swap out. */ - function swap( - uint256 _i, - uint256 _j, - uint256 _dx, - uint256 _minDy - ) + function swap(uint256 _i, uint256 _j, uint256 _dx, uint256 _minDy) external nonReentrant syncRamping @@ -571,8 +563,8 @@ contract SelfPeggingAsset is Initializable, ReentrancyGuardUpgradeable, OwnableU collectFeeOrYield(false); uint256[] memory _balances = balances; uint256 prevBalanceI = _balances[_i]; - _balances[_i] += - (_dx * exchangeRateProviders[_i].exchangeRate() * precisions[_i]) / (10 ** exchangeRateDecimals[_i]); + _balances[_i] += (_dx * exchangeRateProviders[_i].exchangeRate() * precisions[_i]) + / (10 ** exchangeRateDecimals[_i]); uint256 y = _getY(_balances, _j, totalSupply, A); // dy = (balance[j] - y - 1) / precisions[j] in case there was rounding errors uint256 dy = (_balances[_j] - y - 1) / precisions[_j]; @@ -613,10 +605,7 @@ contract SelfPeggingAsset is Initializable, ReentrancyGuardUpgradeable, OwnableU * @param _minRedeemAmounts Minimum amount of underlying tokens to get. * @return An array of the amounts of each token to redeem. */ - function redeemProportion( - uint256 _amount, - uint256[] calldata _minRedeemAmounts - ) + function redeemProportion(uint256 _amount, uint256[] calldata _minRedeemAmounts) external nonReentrant syncRamping @@ -663,11 +652,7 @@ contract SelfPeggingAsset is Initializable, ReentrancyGuardUpgradeable, OwnableU * @param _minRedeemAmount Minimum amount of the underlying token to redeem to. * @return Amount received. */ - function redeemSingle( - uint256 _amount, - uint256 _i, - uint256 _minRedeemAmount - ) + function redeemSingle(uint256 _amount, uint256 _i, uint256 _minRedeemAmount) external nonReentrant syncRamping @@ -722,10 +707,7 @@ contract SelfPeggingAsset is Initializable, ReentrancyGuardUpgradeable, OwnableU * @param _maxRedeemAmount Maximum of pool token to redeem. * @return Amounts received. */ - function redeemMulti( - uint256[] calldata _amounts, - uint256 _maxRedeemAmount - ) + function redeemMulti(uint256[] calldata _amounts, uint256 _maxRedeemAmount) external nonReentrant syncRamping @@ -870,10 +852,7 @@ contract SelfPeggingAsset is Initializable, ReentrancyGuardUpgradeable, OwnableU /** * @dev Update the exchange rate provider for the token. */ - function donateD( - uint256[] calldata _amounts, - uint256 _minDonationAmount - ) + function donateD(uint256[] calldata _amounts, uint256 _minDonationAmount) external nonReentrant syncRamping @@ -1089,8 +1068,8 @@ contract SelfPeggingAsset is Initializable, ReentrancyGuardUpgradeable, OwnableU uint256 prevBalanceI = _balances[_i]; // balance[i] = balance[i] + dx * precisions[i] - _balances[_i] += - (_dx * exchangeRateProviders[_i].exchangeRate() * precisions[_i]) / (10 ** exchangeRateDecimals[_i]); + _balances[_i] += (_dx * exchangeRateProviders[_i].exchangeRate() * precisions[_i]) + / (10 ** exchangeRateDecimals[_i]); uint256 y = _getY(_balances, _j, D, getCurrentA()); // dy = (balance[j] - y - 1) / precisions[j] in case there was rounding errors uint256 dy = (_balances[_j] - y - 1) / precisions[_j]; @@ -1310,10 +1289,7 @@ contract SelfPeggingAsset is Initializable, ReentrancyGuardUpgradeable, OwnableU * @param _amounts Amounts of tokens to deposit. * @return Updated balances after deposit. */ - function _updateBalancesForDeposit( - uint256[] memory _balances, - uint256[] calldata _amounts - ) + function _updateBalancesForDeposit(uint256[] memory _balances, uint256[] calldata _amounts) internal view returns (uint256[] memory) @@ -1333,10 +1309,7 @@ contract SelfPeggingAsset is Initializable, ReentrancyGuardUpgradeable, OwnableU * @param _amounts Amounts of tokens to withdraw. * @return Updated balances after withdrawal. */ - function _updateBalancesForWithdrawal( - uint256[] memory _balances, - uint256[] calldata _amounts - ) + function _updateBalancesForWithdrawal(uint256[] memory _balances, uint256[] calldata _amounts) internal view returns (uint256[] memory) diff --git a/src/interfaces/ISPAToken.sol b/src/interfaces/ISPAToken.sol index 26ad3ac1..afe9392e 100644 --- a/src/interfaces/ISPAToken.sol +++ b/src/interfaces/ISPAToken.sol @@ -25,13 +25,7 @@ interface ISPAToken is IERC20 { function transferShares(address _recipient, uint256 _sharesAmount) external returns (uint256); /// @dev Transfer the shares from the sender to the recipient - function transferSharesFrom( - address _sender, - address _recipient, - uint256 _sharesAmount - ) - external - returns (uint256); + function transferSharesFrom(address _sender, address _recipient, uint256 _sharesAmount) external returns (uint256); /// @dev Mint the shares to the account function mintShares(address _account, uint256 _sharesAmount) external; diff --git a/src/interfaces/IZap.sol b/src/interfaces/IZap.sol index 52fec75a..ffb1b253 100644 --- a/src/interfaces/IZap.sol +++ b/src/interfaces/IZap.sol @@ -28,13 +28,7 @@ interface IZap { * @param amounts Array of token amounts to add * @return wspaAmount Amount of wrapped SPA tokens minted */ - function zapIn( - address spa, - address wspa, - address receiver, - uint256 minMintAmount, - uint256[] calldata amounts - ) + function zapIn(address spa, address wspa, address receiver, uint256 minMintAmount, uint256[] calldata amounts) external returns (uint256 wspaAmount); diff --git a/src/misc/ChainlinkCompositeOracleProvider.sol b/src/misc/ChainlinkCompositeOracleProvider.sol index dfc69e0b..594c5c3b 100644 --- a/src/misc/ChainlinkCompositeOracleProvider.sol +++ b/src/misc/ChainlinkCompositeOracleProvider.sol @@ -1,4 +1,4 @@ -//SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import "@chainlink/contracts/shared/interfaces/AggregatorV3Interface.sol"; @@ -157,15 +157,8 @@ contract ChainlinkCompositeOracleProvider { return; } - ( - /*uint80 roundID*/ - , - int256 answer, - uint256 startedAt, - /*uint256 updatedAt*/ - , - /*uint80 answeredInRound*/ - ) = sequencerUptimeFeed.latestRoundData(); + (/* uint80 roundID*/, int256 answer, uint256 startedAt,/* uint256 updatedAt*/,/* uint80 answeredInRound*/) = + sequencerUptimeFeed.latestRoundData(); // Answer == 0: Sequencer is up // Answer == 1: Sequencer is down diff --git a/src/misc/ChainlinkOracleProvider.sol b/src/misc/ChainlinkOracleProvider.sol index 3ec61e20..edcecb03 100644 --- a/src/misc/ChainlinkOracleProvider.sol +++ b/src/misc/ChainlinkOracleProvider.sol @@ -1,4 +1,4 @@ -//SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import "@chainlink/contracts/shared/interfaces/AggregatorV3Interface.sol"; @@ -99,15 +99,8 @@ contract ChainlinkOracleProvider { return; } - ( - /*uint80 roundID*/ - , - int256 answer, - uint256 startedAt, - /*uint256 updatedAt*/ - , - /*uint80 answeredInRound*/ - ) = sequencerUptimeFeed.latestRoundData(); + (/* uint80 roundID*/, int256 answer, uint256 startedAt,/* uint256 updatedAt*/,/* uint80 answeredInRound*/) = + sequencerUptimeFeed.latestRoundData(); // Answer == 0: Sequencer is up // Answer == 1: Sequencer is down diff --git a/src/misc/OracleExchangeRate.sol b/src/misc/OracleExchangeRate.sol index 16f114bd..8aaa51b3 100644 --- a/src/misc/OracleExchangeRate.sol +++ b/src/misc/OracleExchangeRate.sol @@ -4,26 +4,39 @@ pragma solidity ^0.8.28; import "../interfaces/IExchangeRateProvider.sol"; /** - * @notice Oracle exchange rate. + * @notice Oracle exchange rate provider supporting static or dynamic decimals. */ contract OracleExchangeRate is IExchangeRateProvider { /// @dev Oracle address - address public oracle; + address public immutable oracle; - /// @dev Rate function signature + /// @dev If static decimals are used, this stores them + uint8 public immutable staticDecimals; + + /// @dev Whether decimals are static + bool public immutable isStaticDecimals; + + /// @dev Rate function signature (always dynamic) bytes public rateFunc; - /// @dev Decimals function signature + /// @dev Decimals function signature or encoded static decimals bytes public decimalsFunc; /// @dev Error thrown when the internal call failed error InternalCallFailed(); - /// @dev Initialize the contract constructor(address _oracle, bytes memory _rateFunc, bytes memory _decimalsFunc) { oracle = _oracle; rateFunc = _rateFunc; decimalsFunc = _decimalsFunc; + + if (_decimalsFunc.length == 1) { + staticDecimals = uint8(bytes1(_decimalsFunc)); + isStaticDecimals = true; + } else { + staticDecimals = 0; + isStaticDecimals = false; + } } /// @dev Get the exchange rate @@ -31,18 +44,18 @@ contract OracleExchangeRate is IExchangeRateProvider { (bool success, bytes memory result) = oracle.staticcall(rateFunc); require(success, InternalCallFailed()); - uint256 decodedResult = abi.decode(result, (uint256)); - - return decodedResult; + return abi.decode(result, (uint256)); } - /// @dev Get the exchange rate decimals + /// @dev Get the exchange rate decimals (supports static or dynamic mode) function exchangeRateDecimals() external view returns (uint256) { - (bool success, bytes memory result) = oracle.staticcall(decimalsFunc); - require(success, InternalCallFailed()); - - uint256 decodedResult = abi.decode(result, (uint256)); - - return decodedResult; + if (isStaticDecimals) { + return staticDecimals; + } else { + (bool success, bytes memory result) = oracle.staticcall(decimalsFunc); + require(success, InternalCallFailed()); + + return abi.decode(result, (uint256)); + } } } diff --git a/src/mock/MockChainlinkV3Aggregator.sol b/src/mock/MockChainlinkV3Aggregator.sol index f2a02951..efcab166 100644 --- a/src/mock/MockChainlinkV3Aggregator.sol +++ b/src/mock/MockChainlinkV3Aggregator.sol @@ -1,4 +1,4 @@ -//SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import "@chainlink/contracts/shared/interfaces/AggregatorV3Interface.sol"; diff --git a/src/mock/WETH.sol b/src/mock/WETH.sol index 929d348a..9f1d8c6c 100644 --- a/src/mock/WETH.sol +++ b/src/mock/WETH.sol @@ -49,7 +49,8 @@ contract WETH9 { // solhint-disable max-line-length if ( src != msg.sender - && allowance[src][msg.sender] != uint256(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + && allowance[src][msg.sender] + != uint256(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) ) { require(allowance[src][msg.sender] >= wad, NoAllowance()); allowance[src][msg.sender] -= wad; diff --git a/src/periphery/Keeper.sol b/src/periphery/Keeper.sol index 7d3b9b0d..cb8af45b 100644 --- a/src/periphery/Keeper.sol +++ b/src/periphery/Keeper.sol @@ -356,11 +356,7 @@ contract Keeper is AccessControlUpgradeable, UUPSUpgradeable, IKeeper { * @param currentValue The current value for relative bounds checking * @param bounds The bounds object containing min, max, and relative change limits */ - function checkBounds( - uint256 newValue, - uint256 currentValue, - IParameterRegistry.Bounds memory bounds - ) + function checkBounds(uint256 newValue, uint256 currentValue, IParameterRegistry.Bounds memory bounds) internal pure { @@ -384,14 +380,7 @@ contract Keeper is AccessControlUpgradeable, UUPSUpgradeable, IKeeper { * @param currentValue The current value to compare against * @param bounds The bounds object containing relative change limits */ - function checkRange( - uint256 newValue, - uint256 currentValue, - IParameterRegistry.Bounds memory bounds - ) - internal - pure - { + function checkRange(uint256 newValue, uint256 currentValue, IParameterRegistry.Bounds memory bounds) internal pure { // Skip percentage checks if explicitly disabled or if current value is zero if (currentValue == 0) return; if (bounds.maxDecreasePct == 0 && bounds.maxIncreasePct == 0) return; diff --git a/src/periphery/ParameterRegistry.sol b/src/periphery/ParameterRegistry.sol index 612b7b68..4a30daae 100644 --- a/src/periphery/ParameterRegistry.sol +++ b/src/periphery/ParameterRegistry.sol @@ -14,7 +14,7 @@ import "../SelfPeggingAsset.sol"; contract ParameterRegistry is IParameterRegistry, Ownable { uint256 private constant MIN_MULTIPLIER = 1e10; // min offpeg multiplier 1 - uint256 private constant MAX_A = 10 ** 6; // 1M + uint256 private constant MAX_A = 10 ** 6; //1M uint64 private constant MAX_DECREASE_PCT_A = 0.9e10; // -90% uint64 private constant MAX_INCREASE_PCT_A = 9e10; // +900% diff --git a/src/periphery/Zap.sol b/src/periphery/Zap.sol index 123c7d00..92b505d3 100644 --- a/src/periphery/Zap.sol +++ b/src/periphery/Zap.sol @@ -29,13 +29,7 @@ contract Zap is IZap, ReentrancyGuard { * @param amounts Array of token amounts to add * @return wspaAmount Amount of wrapped SPA tokens minted */ - function zapIn( - address spa, - address wspa, - address receiver, - uint256 minMintAmount, - uint256[] calldata amounts - ) + function zapIn(address spa, address wspa, address receiver, uint256 minMintAmount, uint256[] calldata amounts) external nonReentrant returns (uint256 wspaAmount) @@ -208,11 +202,7 @@ contract Zap is IZap, ReentrancyGuard { /** * @dev Call SPA's redeemProportion function */ - function _redeemProportion( - address spa, - uint256 amount, - uint256[] calldata minAmountsOut - ) + function _redeemProportion(address spa, uint256 amount, uint256[] calldata minAmountsOut) internal returns (uint256[] memory) { @@ -227,17 +217,13 @@ contract Zap is IZap, ReentrancyGuard { /** * @dev Call SPA's redeemSingle function */ - function _redeemSingle( - address spa, - uint256 amount, - uint256 tokenIndex, - uint256 minAmountOut - ) + function _redeemSingle(address spa, uint256 amount, uint256 tokenIndex, uint256 minAmountOut) internal returns (uint256) { - (bool success, bytes memory data) = - spa.call(abi.encodeWithSignature("redeemSingle(uint256,uint256,uint256)", amount, tokenIndex, minAmountOut)); + (bool success, bytes memory data) = spa.call( + abi.encodeWithSignature("redeemSingle(uint256,uint256,uint256)", amount, tokenIndex, minAmountOut) + ); if (!success) _revertBytes(data); @@ -247,11 +233,7 @@ contract Zap is IZap, ReentrancyGuard { /** * @dev Call SPA's redeemMulti function */ - function _redeemMulti( - address spa, - uint256[] calldata amounts, - uint256 maxRedeemAmount - ) + function _redeemMulti(address spa, uint256[] calldata amounts, uint256 maxRedeemAmount) internal returns (uint256[] memory) { diff --git a/test/ChainlinkCompositeOracle.t.sol b/test/ChainlinkCompositeOracle.t.sol index 595ba3dd..fab61648 100644 --- a/test/ChainlinkCompositeOracle.t.sol +++ b/test/ChainlinkCompositeOracle.t.sol @@ -21,21 +21,15 @@ contract ChainlinkCompositeOracleProviderTest is Test { function test_weETHTostETH() external { ChainlinkCompositeOracleProvider.Config[] memory configs = new ChainlinkCompositeOracleProvider.Config[](2); configs[0] = ChainlinkCompositeOracleProvider.Config({ - feed: weETHToETHFeed, - maxStalePeriod: 24 hours, - assetDecimals: 18, - isInverted: false + feed: weETHToETHFeed, maxStalePeriod: 24 hours, assetDecimals: 18, isInverted: false }); configs[1] = ChainlinkCompositeOracleProvider.Config({ - feed: stETHToETHFeed, - maxStalePeriod: 24 hours, - assetDecimals: 18, - isInverted: true + feed: stETHToETHFeed, maxStalePeriod: 24 hours, assetDecimals: 18, isInverted: true }); ChainlinkCompositeOracleProvider oracle = new ChainlinkCompositeOracleProvider(AggregatorV3Interface(address(0)), configs); - assertEq(oracle.price(), 1.065471935837571059e18); + assertEq(oracle.price(), 1.065_471_935_837_571_059e18); } } diff --git a/test/Factory.t.sol b/test/Factory.t.sol index 4f32b489..e9fc1bbb 100644 --- a/test/Factory.t.sol +++ b/test/Factory.t.sol @@ -103,13 +103,13 @@ contract FactoryTest is Test { if (log.topics[0] == eventSig) { ( - decodedPoolToken, - decodedSelfPeggingAsset, - decodedWrappedPoolToken, - decodedRampAController, - decodedKeeper, - decodedParameterRegistry - ) = abi.decode(log.data, (address, address, address, address, address, address)); + decodedPoolToken, + decodedSelfPeggingAsset, + decodedWrappedPoolToken, + decodedRampAController, + decodedKeeper, + decodedParameterRegistry + ) = abi.decode(log.data, (address, address, address, address, address, address)); } } diff --git a/test/Keeper.t.sol b/test/Keeper.t.sol index 1cba94af..a8ed5da4 100644 --- a/test/Keeper.t.sol +++ b/test/Keeper.t.sol @@ -227,8 +227,8 @@ contract KeeperFuzzTest is Test { vm.assume(max <= 365 days); min = bound(min, 0, max); } else if (paramType == 8 || paramType == 9) { - vm.assume(oldValue <= 1_000_000_000e18); //1 billion margin - vm.assume(newValue <= 1_000_000_000e18); //1 billion margin + vm.assume(oldValue <= 1_000_000_000e18); // 1 billion margin + vm.assume(newValue <= 1_000_000_000e18); // 1 billion margin vm.assume(max <= type(uint256).max); min = bound(min, 0, max); } else if (paramType == 10) { @@ -265,10 +265,7 @@ contract KeeperFuzzTest is Test { vm.startPrank(governor); // Set boundaries IParameterRegistry.Bounds memory bounds = IParameterRegistry.Bounds({ - min: min, - max: max, - maxDecreasePct: maxDecreasePct, - maxIncreasePct: maxIncreasePct + min: min, max: max, maxDecreasePct: maxDecreasePct, maxIncreasePct: maxIncreasePct }); // Initial Value diff --git a/test/RampAController.t.sol b/test/RampAController.t.sol index 25eb0e9f..5b0a21b2 100644 --- a/test/RampAController.t.sol +++ b/test/RampAController.t.sol @@ -45,7 +45,7 @@ contract RampAControllerTest is Test { fees[1] = 1e8; fees[2] = 1e8; - offPegFeeMultiplier = 5e10; // 5x + offPegFeeMultiplier = 5e10; //5x providers = new MockExchangeRateProvider[](2); providers[0] = new MockExchangeRateProvider(1e18, 18); // 1:1 diff --git a/test/SelfPeggingAsset.t.sol b/test/SelfPeggingAsset.t.sol index e928a0a7..339926d1 100644 --- a/test/SelfPeggingAsset.t.sol +++ b/test/SelfPeggingAsset.t.sol @@ -183,7 +183,7 @@ contract SelfPeggingAssetTest is Test { assertEq(pool.balances(0), 105e18); assertEq(pool.balances(1), 85e18); - assertEq(pool.totalSupply(), 189.994704791049550806e18); + assertEq(pool.totalSupply(), 189.994_704_791_049_550_806e18); assertEq(pool.totalSupply(), spaToken.totalSupply()); @@ -237,8 +237,8 @@ contract SelfPeggingAssetTest is Test { assertEq(pool.balances(0), 105e18); assertEq(pool.balances(1), 85e18); - assertEq(pool.totalSupply(), 189.994704791049550806e18); - assertEq(spaToken.totalSupply(), 189.994704791049550806e18); + assertEq(pool.totalSupply(), 189.994_704_791_049_550_806e18); + assertEq(spaToken.totalSupply(), 189.994_704_791_049_550_806e18); uint256 amountToRedeem = spaToken.balanceOf(user2); vm.startPrank(user2); @@ -441,8 +441,8 @@ contract SelfPeggingAssetTest is Test { (uint256 exchangeAmount, uint256 feeAmount) = pool.getSwapAmount(1, 0, 8e18); - assertEq(exchangeAmount, 7.992985053666343961e18); - assertEq(feeAmount, 0.016018006119571831e18); + assertEq(exchangeAmount, 7.992_985_053_666_343_961e18); + assertEq(feeAmount, 0.016_018_006_119_571_831e18); } function testDynamicFeeForSwap() external { @@ -479,7 +479,7 @@ contract SelfPeggingAssetTest is Test { assertEq(pool.balances(0), 105e18); assertEq(pool.balances(1), 85e18); - assertEq(pool.totalSupply(), 189.994704791049550806e18); + assertEq(pool.totalSupply(), 189.994_704_791_049_550_806e18); assertEq(pool.totalSupply(), spaToken.totalSupply()); @@ -517,7 +517,7 @@ contract SelfPeggingAssetTest is Test { } function test_BurnValue_With_Losing_Shares() public { - //two users, user and user2, enter as liquidity providers. + // two users, user and user2, enter as liquidity providers. uint256 liquidity = 100e18; WETH.mint(user, liquidity); frxETH.mint(user, liquidity); @@ -540,7 +540,7 @@ contract SelfPeggingAssetTest is Test { pool.mint(amounts, 0); vm.stopPrank(); - //we create a profit balance (totalSupply > totalShares) via donation. + // we create a profit balance (totalSupply > totalShares) via donation. uint256 donation = 100e18; WETH.mint(owner, donation); vm.prank(owner); @@ -556,7 +556,7 @@ contract SelfPeggingAssetTest is Test { uint256 user_Balance_before = spaToken.balanceOf(user); uint256 totalSupply_before = spaToken.totalSupply(); - //attack: User `user2` calls burnShares(1) in a loop to destroy the value. + // attack: User `user2` calls burnShares(1) in a loop to destroy the value. uint256 iterations = 100; vm.startPrank(user2); for (uint256 i = 0; i < iterations; i++) { @@ -564,15 +564,15 @@ contract SelfPeggingAssetTest is Test { } vm.stopPrank(); - //check + // check uint256 user2_Shares_after = spaToken.sharesOf(user2); uint256 user_Balance_after = spaToken.balanceOf(user); uint256 totalSupply_after = spaToken.totalSupply(); - //user2 shares are dropped + // user2 shares are dropped assertGt(user2_Shares_before, user2_Shares_after, "User2's shares should have decreased"); - //total supply decreased by the amount that user2 burned + // total supply decreased by the amount that user2 burned assertEq( totalSupply_after, totalSupply_before - iterations, @@ -645,7 +645,7 @@ contract SelfPeggingAssetTest is Test { uint256 wstETHBalance = wstETH.balanceOf(user2); assertEq(rETHBalance, 0); - assertIsCloseTo(wstETHBalance, 1e18, 0.00005 ether); + assertIsCloseTo(wstETHBalance, 1e18, 0.000_05 ether); // Set buffer percentage to 5% vm.prank(owner); @@ -926,7 +926,7 @@ contract SelfPeggingAssetTest is Test { uint256[] memory _fees = new uint256[](3); _fees[0] = 0; - _fees[1] = 0.00001e10; + _fees[1] = 0.000_01e10; _fees[2] = 0; uint256[] memory _precisions = new uint256[](2); @@ -1053,7 +1053,7 @@ contract SelfPeggingAssetTest is Test { uint256[] memory _fees = new uint256[](3); _fees[0] = 0; - _fees[1] = 0.00001e10; + _fees[1] = 0.000_01e10; _fees[2] = 0; uint256[] memory _precisions = new uint256[](2); @@ -1313,7 +1313,7 @@ contract SelfPeggingAssetTest is Test { uint256[] memory fees = new uint256[](3); fees[0] = 0; - fees[1] = 0.00001e10; + fees[1] = 0.000_01e10; fees[2] = 0; precisions[0] = 1; precisions[1] = 1; @@ -1487,7 +1487,7 @@ contract SelfPeggingAssetTest is Test { uint256 token1newRate = 2e18; testToken1Rate.newRate(token1newRate); - //after setting new buffer and new exchange, an estimate of what rebase added value to contract would look like + // after setting new buffer and new exchange, an estimate of what rebase added value to contract would look like // is calculated below, rebase should correctly give a value close to this if precision mutiplication was // handled correctly, based on current supply value value1 = token1.balanceOf(address(_pool));