From 322ec2f15f633003c05ce0fe947cd2116de2575b Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 9 Oct 2024 15:43:46 +1100 Subject: [PATCH] Safety check in setCrossPrice so no stETH in ARM when cross price reduced --- src/contracts/AbstractARM.sol | 18 ++++++++---- .../LidoFixedPriceMultiLpARM/Setters.t.sol | 29 ++++++++++++++++--- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/contracts/AbstractARM.sol b/src/contracts/AbstractARM.sol index b4db783..90987d4 100644 --- a/src/contracts/AbstractARM.sol +++ b/src/contracts/AbstractARM.sol @@ -391,13 +391,21 @@ abstract contract AbstractARM is OwnableOperable, ERC20Upgradeable { emit TraderateChanged(_baseToTokenRate, _tokenToBaseRate); } - function setCrossPrice(uint256 _crossPrice) external onlyOwner { - require(_crossPrice >= PRICE_SCALE - MAX_PRICE_DEVIATION, "ARM: cross price too low"); - require(_crossPrice <= PRICE_SCALE, "ARM: cross price too high"); + function setCrossPrice(uint256 newCrossPrice) external onlyOwner { + require(newCrossPrice >= PRICE_SCALE - MAX_PRICE_DEVIATION, "ARM: cross price too low"); + require(newCrossPrice <= PRICE_SCALE, "ARM: cross price too high"); + + // If the new cross price is lower than the current cross price + if (newCrossPrice < crossPrice) { + // The base asset, eg stETH, is not the liquidity asset, eg WETH + address baseAsset = liquidityAsset == address(token0) ? address(token1) : address(token0); + // Check there is not a significant amount of base assets in the ARM + require(IERC20(baseAsset).balanceOf(address(this)) < MIN_TOTAL_SUPPLY, "ARM: too many base assets"); + } - crossPrice = _crossPrice; + crossPrice = newCrossPrice; - emit CrossPriceUpdated(_crossPrice); + emit CrossPriceUpdated(newCrossPrice); } //////////////////////////////////////////////////// diff --git a/test/fork/LidoFixedPriceMultiLpARM/Setters.t.sol b/test/fork/LidoFixedPriceMultiLpARM/Setters.t.sol index af68ae0..55e3456 100644 --- a/test/fork/LidoFixedPriceMultiLpARM/Setters.t.sol +++ b/test/fork/LidoFixedPriceMultiLpARM/Setters.t.sol @@ -89,7 +89,7 @@ contract Fork_Concrete_lidoARM_Setters_Test_ is Fork_Shared_Test_ { ////////////////////////////////////////////////////// /// --- Set Prices - REVERTING TESTS ////////////////////////////////////////////////////// - function test_RevertWhen_SetPrices_Because_PriceCross() public { + function test_RevertWhen_SetPrices_Because_PriceCross() public asLidoARMOwner { vm.expectRevert("ARM: Price cross"); lidoARM.setPrices(90 * 1e33, 89 * 1e33); @@ -160,7 +160,7 @@ contract Fork_Concrete_lidoARM_Setters_Test_ is Fork_Shared_Test_ { } ////////////////////////////////////////////////////// - /// --- Set Prices - REVERTING TESTS + /// --- Set Cross Price - REVERTING TESTS ////////////////////////////////////////////////////// function test_RevertWhen_SetCrossPrice_Because_NotOwner() public asRandomAddress { vm.expectRevert("ARM: Only owner can call this function."); @@ -182,11 +182,20 @@ contract Fork_Concrete_lidoARM_Setters_Test_ is Fork_Shared_Test_ { lidoARM.setCrossPrice(1.0001e36); } + function test_RevertWhen_SetCrossPrice_With_stETH_Because_PriceDrop() public { + deal(address(steth), address(lidoARM), MIN_TOTAL_SUPPLY + 1); + + vm.expectRevert("ARM: too many base assets"); + lidoARM.setCrossPrice(0.9998e36); + } + ////////////////////////////////////////////////////// - /// --- Set Prices - PASSING TESTS + /// --- Set Cross Price - PASSING TESTS ////////////////////////////////////////////////////// - function test_SetCrossPrice_Owner() public { + function test_SetCrossPrice_No_StETH_Owner() public { + deal(address(steth), address(lidoARM), MIN_TOTAL_SUPPLY - 1); + // at 1.0 vm.expectEmit({emitter: address(lidoARM)}); emit AbstractARM.CrossPriceUpdated(1e36); @@ -198,6 +207,18 @@ contract Fork_Concrete_lidoARM_Setters_Test_ is Fork_Shared_Test_ { lidoARM.setCrossPrice(0.9998e36); } + function test_SetCrossPrice_With_StETH_PriceUp_Owner() public { + // 2 basis points lower than 1.0 + lidoARM.setCrossPrice(0.9998e36); + + deal(address(steth), address(lidoARM), MIN_TOTAL_SUPPLY + 1); + + // 4 basis points lower than 1.0 + // vm.expectEmit({emitter: address(lidoARM)}); + // emit AbstractARM.CrossPriceUpdated(0.9996e36); + lidoARM.setCrossPrice(0.9999e36); + } + ////////////////////////////////////////////////////// /// --- OWNABLE - REVERTING TESTS //////////////////////////////////////////////////////