diff --git a/docs/plantuml/EthenaContracts.png b/docs/plantuml/EthenaContracts.png index a885662a..eb16832d 100644 Binary files a/docs/plantuml/EthenaContracts.png and b/docs/plantuml/EthenaContracts.png differ diff --git a/docs/plantuml/EthenaContracts.puml b/docs/plantuml/EthenaContracts.puml index 03b22d4b..8f6a4619 100644 --- a/docs/plantuml/EthenaContracts.puml +++ b/docs/plantuml/EthenaContracts.puml @@ -36,10 +36,6 @@ object "StakedUSDe" as susde <><> #$thirdPartyColor { asset: USDe } -' object "Aave Market" as aMarket <><> #$originColor { -' asset: USDe -' } - object "Aave Vault" as aVault <><> #$thirdPartyColor { asset: USDe } @@ -48,15 +44,11 @@ object "aUSDe" as aUSDe <> #$thirdPartyColor { asset: USDe } -arm <.> capMan +capMan <.> arm arm ..> adapter -adapter ..> unstaker +adapter .> unstaker adapter ..> susde unstaker ..> susde -' arm ..> aMarket -' aMarket ..> aVault -' aVault ..> aUSDe -' aMarket ...> aUSDe arm ..> aVault aVault ..> aUSDe diff --git a/docs/plantuml/usdcContracts.png b/docs/plantuml/usdcContracts.png index 94d67180..2ffd2033 100644 Binary files a/docs/plantuml/usdcContracts.png and b/docs/plantuml/usdcContracts.png differ diff --git a/docs/plantuml/usdcContracts.puml b/docs/plantuml/usdcContracts.puml index 2282689c..00b84f34 100644 --- a/docs/plantuml/usdcContracts.puml +++ b/docs/plantuml/usdcContracts.puml @@ -25,27 +25,27 @@ object "CapManager" as capMan <><> #$originColor { } object "PaxosAssetAdapter\n(PYUSD)" as pyusdAdapter <><> #$originColor { - base asset: PYUSD + asset: PYUSD } object "PaxosAssetAdapter\n(USDG)" as usdgAdapter <><> #$originColor { - base asset: USDG + asset: USDG } -object "PYUSD" as pyusd <> #$thirdPartyColor { - base asset +object "PYUSD Deposit" as pyusd <> #$thirdPartyColor { + asset: PYUSD } -object "USDG" as usdg <> #$thirdPartyColor { - base asset +object "USDG Deposit" as usdg <> #$thirdPartyColor { + asset: USDG } -arm <.> capMan : deposit caps -arm ..> pyusdAdapter : request / claim -arm ..> usdgAdapter : request / claim +capMan <.> arm : deposit caps +arm ..> pyusdAdapter : transfer +arm ..> usdgAdapter : transfer -pyusdAdapter ..> pyusd : queues and submits +pyusdAdapter ..> pyusd : transfer -usdgAdapter ..> usdg : queues and submits +usdgAdapter ..> usdg : transfer @enduml diff --git a/docs/plantuml/wethContracts.png b/docs/plantuml/wethContracts.png index 0f6398d5..8d135839 100644 Binary files a/docs/plantuml/wethContracts.png and b/docs/plantuml/wethContracts.png differ diff --git a/docs/plantuml/wethContracts.puml b/docs/plantuml/wethContracts.puml index 6c40098a..06f2b8ad 100644 --- a/docs/plantuml/wethContracts.puml +++ b/docs/plantuml/wethContracts.puml @@ -24,6 +24,14 @@ object "MultiAssetARM\n(WETH ARM)" as arm <><> #$originColor { base assets: stETH, wstETH, eETH, weETH } +object "Morpho Market" as morphoMarket <><> #$originColor { + asset: WETH +} + +object "Yearn WETH ARM Vault" as morphoVault <> #$thirdPartyColor { + asset: WETH +} + object "CapManager" as capMan <><> #$originColor { total-assets cap liquidity-provider caps @@ -59,8 +67,10 @@ object "Ether.fi\nWithdrawal NFT" as etherfiNft <><> #$thirdPart } zapper ..> arm : deposits for receiver +arm .right.> morphoMarket : deposit /\nredeem +morphoMarket ...> morphoVault : deposit /\nredeem -arm <.> capMan : deposit caps +capMan <.> arm : deposit caps arm ..> stethAdapter : request / claim arm ..> wstethAdapter : request / claim arm ..> eethAdapter : request / claim diff --git a/script/deploy/mainnet/043_AddOriginAssetsToWETHARMScript.s.sol b/script/deploy/mainnet/043_AddOriginAssetsToWETHARMScript.s.sol new file mode 100644 index 00000000..67338f5d --- /dev/null +++ b/script/deploy/mainnet/043_AddOriginAssetsToWETHARMScript.s.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.23; + +// Contracts +import {Proxy} from "contracts/Proxy.sol"; +import {Mainnet} from "contracts/utils/Addresses.sol"; +import {MultiAssetARM} from "contracts/MultiAssetARM.sol"; +import {OriginAssetAdapter} from "contracts/adapters/OriginAssetAdapter.sol"; +import {WrappedOriginAssetAdapter} from "contracts/adapters/WrappedOriginAssetAdapter.sol"; + +// Deployment +import {AbstractDeployScript} from "script/deploy/helpers/AbstractDeployScript.s.sol"; + +/// @title Add Origin assets to the WETH ARM +/// @notice Deploys OETH and wOETH adapters that redeem through the OETH Vault's asynchronous +/// withdrawal queue, then registers both tokens as base assets on the existing WETH ARM. +/// @dev The adapter proxies are owned by the mainnet 2/8 multisig. The same multisig owns the WETH +/// ARM and performs the base-asset registration actions simulated by `_fork()`. +contract $043_AddOriginAssetsToWETHARMScript is AbstractDeployScript("043_AddOriginAssetsToWETHARMScript") { + /// 0.99998e36 = base asset valued at 0.99998 WETH in totalAssets(). + uint256 internal constant CROSS_PRICE = 0.99998e36; + /// 0.9997e36 = ARM pays 0.9997 WETH per base asset bought from traders. + uint256 internal constant BUY_PRICE = 0.9997e36; + /// 1e36 = ARM charges 1 WETH per base asset sold to traders. + uint256 internal constant SELL_PRICE = 1e36; + + function _execute() internal override { + address wethARM = resolver.resolve("WETH_ARM"); + + // 1. Deploy the adapter for rebasing OETH. + OriginAssetAdapter oethAdapterImpl = + new OriginAssetAdapter(wethARM, Mainnet.OETH, Mainnet.WETH, Mainnet.OETH_VAULT); + _recordDeployment("WETH_ARM_OETH_ADAPTER_IMPL", address(oethAdapterImpl)); + + Proxy oethAdapterProxy = new Proxy(); + oethAdapterProxy.initialize( + address(oethAdapterImpl), Mainnet.MULTISIG_2_OF_8, abi.encodeWithSignature("initialize()") + ); + _recordDeployment("WETH_ARM_OETH_ADAPTER", address(oethAdapterProxy)); + + // 2. Deploy the adapter that unwraps wOETH before requesting an OETH Vault withdrawal. + WrappedOriginAssetAdapter woethAdapterImpl = + new WrappedOriginAssetAdapter(wethARM, Mainnet.WOETH, Mainnet.OETH, Mainnet.WETH, Mainnet.OETH_VAULT); + _recordDeployment("WETH_ARM_WOETH_ADAPTER_IMPL", address(woethAdapterImpl)); + + Proxy woethAdapterProxy = new Proxy(); + woethAdapterProxy.initialize( + address(woethAdapterImpl), Mainnet.MULTISIG_2_OF_8, abi.encodeWithSignature("initialize()") + ); + _recordDeployment("WETH_ARM_WOETH_ADAPTER", address(woethAdapterProxy)); + } + + function _fork() internal override { + MultiAssetARM wethARM = MultiAssetARM(payable(resolver.resolve("WETH_ARM"))); + + // Idempotent: the deployment runner can replay pending multisig actions on forks. + (,,,,,,,, address oethAdapter) = wethARM.baseAssetConfigs(Mainnet.OETH); + if (oethAdapter == address(0)) { + vm.prank(Mainnet.MULTISIG_2_OF_8); + wethARM.addBaseAsset( + Mainnet.OETH, + resolver.resolve("WETH_ARM_OETH_ADAPTER"), + BUY_PRICE, + SELL_PRICE, + 0, // buyAmount: no swaps until the operator sets swap limits. + 0, // sellAmount + CROSS_PRICE, + true // OETH is accounted for 1:1 with WETH. + ); + } + + (,,,,,,,, address woethAdapter) = wethARM.baseAssetConfigs(Mainnet.WOETH); + if (woethAdapter == address(0)) { + vm.prank(Mainnet.MULTISIG_2_OF_8); + wethARM.addBaseAsset( + Mainnet.WOETH, + resolver.resolve("WETH_ARM_WOETH_ADAPTER"), + BUY_PRICE, + SELL_PRICE, + 0, // buyAmount: no swaps until the operator sets swap limits. + 0, // sellAmount + CROSS_PRICE, + false // wOETH is valued through its ERC-4626 conversion rate. + ); + } + } +} diff --git a/src/js/tasks/actions/setPricesWETH.ts b/src/js/tasks/actions/setPricesWETH.ts index 8e1ff8ea..3f9e52b3 100644 --- a/src/js/tasks/actions/setPricesWETH.ts +++ b/src/js/tasks/actions/setPricesWETH.ts @@ -8,7 +8,15 @@ import { mainnet } from "../../utils/addresses"; const multiAssetARMAbi = require("../../../abis/MultiAssetARM.json"); const LIDO_BASES = new Set(["STETH", "WSTETH"]); -const SUPPORTED_BASES = new Set(["STETH", "WSTETH", "EETH", "WEETH"]); +const ORIGIN_BASES = new Set(["OETH", "WOETH"]); +const SUPPORTED_BASES = new Set([ + "STETH", + "WSTETH", + "EETH", + "WEETH", + "OETH", + "WOETH", +]); const lidoDefaults = { maxBuyPrice: 0.9999, @@ -30,6 +38,16 @@ const etherFiDefaults = { kyber: true, }; +const originDefaults = { + maxBuyPrice: 0.9995, + minBuyPrice: 0.996, + maxSellPrice: 0.9999, + minSellPrice: 0.9995, + tolerance: 0.3, + inch: false, + kyber: true, +}; + action({ name: "setPricesWETH", description: "Set prices for WETH ARM", @@ -39,7 +57,7 @@ action({ .addOptionalParam( "bases", "Comma-separated list of base assets to set prices for.", - "STETH,WSTETH,EETH,WEETH", + "STETH,WSTETH,EETH,WEETH,OETH,WOETH", types.string, ) .addOptionalParam( @@ -160,7 +178,11 @@ action({ log.info("Setting prices for WETH ARM"); for (const base of bases) { - const defaults = LIDO_BASES.has(base) ? lidoDefaults : etherFiDefaults; + const defaults = LIDO_BASES.has(base) + ? lidoDefaults + : ORIGIN_BASES.has(base) + ? originDefaults + : etherFiDefaults; await setPricesForBases({ setPrices, bases: [base],