diff --git a/script/deploy/DeployManager.sol b/script/deploy/DeployManager.sol index 8b62e18e..2edf1437 100644 --- a/script/deploy/DeployManager.sol +++ b/script/deploy/DeployManager.sol @@ -23,6 +23,7 @@ import {DeployEtherFiARMScript} from "./mainnet/011_DeployEtherFiARMScript.sol"; import {UpgradeEtherFiARMScript} from "./mainnet/012_UpgradeEtherFiARMScript.sol"; import {UpgradeOETHARMScript} from "./mainnet/013_UpgradeOETHARMScript.sol"; import {DeployEthenaARMScript} from "./mainnet/014_DeployEthenaARMScript.sol"; +import {UpgradeEthenaARMScript} from "./mainnet/015_UpgradeEthenaARMScript.sol"; contract DeployManager is Script { using stdJson for string; @@ -84,6 +85,7 @@ contract DeployManager is Script { _runDeployFile(new UpgradeEtherFiARMScript()); _runDeployFile(new UpgradeOETHARMScript()); _runDeployFile(new DeployEthenaARMScript()); + _runDeployFile(new UpgradeEthenaARMScript()); } else if (block.chainid == 17000) { // Holesky } else if (block.chainid == 146) { diff --git a/script/deploy/mainnet/015_UpgradeEthenaARMScript.sol b/script/deploy/mainnet/015_UpgradeEthenaARMScript.sol new file mode 100644 index 00000000..ae5ad535 --- /dev/null +++ b/script/deploy/mainnet/015_UpgradeEthenaARMScript.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.23; + +// Foundry imports +import {console} from "forge-std/console.sol"; + +// Contract imports +import {Proxy} from "contracts/Proxy.sol"; +import {EthenaARM} from "contracts/EthenaARM.sol"; +import {Mainnet} from "contracts/utils/Addresses.sol"; + +// Deployment imports +import {GovProposal, GovSixHelper} from "contracts/utils/GovSixHelper.sol"; +import {AbstractDeployScript} from "../AbstractDeployScript.sol"; + +contract UpgradeEthenaARMScript is AbstractDeployScript { + using GovSixHelper for GovProposal; + + GovProposal public govProposal; + + string public constant override DEPLOY_NAME = "015_UpgradeEthenaARMScript"; + bool public constant override proposalExecuted = false; + + EthenaARM armImpl; + + function _execute() internal override { + console.log("Deploy:", DEPLOY_NAME); + console.log("------------"); + + // 1. Deploy new ARM implementation + uint256 claimDelay = tenderlyTestnet ? 1 minutes : 10 minutes; + armImpl = new EthenaARM( + Mainnet.USDE, + Mainnet.SUSDE, + claimDelay, + 1e18, // minSharesToRedeem + 100e18 // allocateThreshold + ); + _recordDeploy("ETHENA_ARM_IMPL", address(armImpl)); + + console.log("Finished deploying", DEPLOY_NAME); + } + + function _fork() internal override { + vm.startPrank(Proxy(payable(deployedContracts["ETHENA_ARM"])).owner()); + Proxy(payable(deployedContracts["ETHENA_ARM"])).upgradeTo(address(armImpl)); + vm.stopPrank(); + } +} diff --git a/src/contracts/EthenaARM.sol b/src/contracts/EthenaARM.sol index e7a2e22e..fcf67a8f 100644 --- a/src/contracts/EthenaARM.sol +++ b/src/contracts/EthenaARM.sol @@ -22,7 +22,7 @@ contract EthenaARM is Initializable, AbstractARM { IStakedUSDe public immutable susde; /// @notice The total amount of liquidity asset (USDe) currently in cooldown - uint256 internal _liquidityAmountInCooldown; + uint256 public liquidityAmountInCooldown; /// @notice Array of unstaker helper contracts address[MAX_UNSTAKERS] public unstakers; /// @notice The index of the next unstaker to use in the round robin @@ -97,7 +97,7 @@ contract EthenaARM is Initializable, AbstractARM { uint256 liquidityAmount = EthenaUnstaker(unstaker).requestUnstake(baseAmount); - _liquidityAmountInCooldown += liquidityAmount; + liquidityAmountInCooldown += liquidityAmount; // Emit event for the request emit RequestBaseWithdrawal(unstaker, baseAmount, liquidityAmount); @@ -109,7 +109,7 @@ contract EthenaARM is Initializable, AbstractARM { UserCooldown memory cooldown = susde.cooldowns(address(unstaker)); require(cooldown.underlyingAmount > 0, "EthenaARM: No cooldown amount"); - _liquidityAmountInCooldown -= cooldown.underlyingAmount; + liquidityAmountInCooldown -= cooldown.underlyingAmount; // Claim all the underlying USDe that has cooled down for the unstaker and send to the ARM EthenaUnstaker(unstaker).claimUnstake(); @@ -121,7 +121,7 @@ contract EthenaARM is Initializable, AbstractARM { /// This can be for many different cooldowns. /// This can be either in the cooldown period or ready to be claimed. function _externalWithdrawQueue() internal view override returns (uint256) { - return _liquidityAmountInCooldown; + return liquidityAmountInCooldown; } /// @dev Convert between base asset (sUSDe) and liquidity asset (USDe). diff --git a/src/js/tasks/liquidity.js b/src/js/tasks/liquidity.js index 2c728dd9..33029885 100644 --- a/src/js/tasks/liquidity.js +++ b/src/js/tasks/liquidity.js @@ -156,6 +156,10 @@ const logLiquidity = async ({ block, arm }) => { baseWithdraws = await armContract.vaultWithdrawalAmount({ blockTag, }); + } else if (arm === "Ethena") { + baseWithdraws = await armContract.liquidityAmountInCooldown({ + blockTag, + }); } let lendingMarketBalance = 0n; diff --git a/test/invariants/LidoARM/TargetFunction.sol b/test/invariants/LidoARM/TargetFunction.sol index 55a3dbc6..d323525e 100644 --- a/test/invariants/LidoARM/TargetFunction.sol +++ b/test/invariants/LidoARM/TargetFunction.sol @@ -320,7 +320,7 @@ abstract contract TargetFunction is Properties { //////////////////////////////////////////////////// /// --- HELPERS //////////////////////////////////////////////////// - uint256 constant SHARES_UP_ONLY__ERROR_TOLERANCE = 1e4; + uint256 constant SHARES_UP_ONLY__ERROR_TOLERANCE = 1e6; function finalizeLidoClaims() public { if (lidoWithdrawRequests.length == 0) return;